diff --git a/src/components/CategoryPicker.tsx b/src/components/CategoryPicker.tsx index 0c855507371a..19bb98bff58e 100644 --- a/src/components/CategoryPicker.tsx +++ b/src/components/CategoryPicker.tsx @@ -3,6 +3,8 @@ import {useOnyx} from 'react-native-onyx'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import * as CategoryOptionsListUtils from '@libs/CategoryOptionListUtils'; +import type {Category} from '@libs/CategoryOptionListUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -27,7 +29,7 @@ function CategoryPicker({selectedCategory, policyID, onSubmit}: CategoryPickerPr const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState(''); const offlineMessage = isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''; - const selectedOptions = useMemo(() => { + const selectedOptions = useMemo((): Category[] => { if (!selectedCategory) { return []; } @@ -35,8 +37,8 @@ function CategoryPicker({selectedCategory, policyID, onSubmit}: CategoryPickerPr return [ { name: selectedCategory, - accountID: undefined, isSelected: true, + enabled: true, }, ]; }, [selectedCategory]); @@ -44,11 +46,9 @@ function CategoryPicker({selectedCategory, policyID, onSubmit}: CategoryPickerPr const [sections, headerMessage, shouldShowTextInput] = useMemo(() => { const categories = policyCategories ?? policyCategoriesDraft ?? {}; const validPolicyRecentlyUsedCategories = policyRecentlyUsedCategories?.filter?.((p) => !isEmptyObject(p)); - const {categoryOptions} = OptionsListUtils.getFilteredOptions({ + const categoryOptions = CategoryOptionsListUtils.getCategoryListSections({ searchValue: debouncedSearchValue, selectedOptions, - includeP2P: false, - includeCategories: true, categories, recentlyUsedCategories: validPolicyRecentlyUsedCategories, }); diff --git a/src/components/Search/SearchFiltersChatsSelector.tsx b/src/components/Search/SearchFiltersChatsSelector.tsx index 47cd2a6086d4..11f53a12b211 100644 --- a/src/components/Search/SearchFiltersChatsSelector.tsx +++ b/src/components/Search/SearchFiltersChatsSelector.tsx @@ -23,7 +23,6 @@ const defaultListOptions = { personalDetails: [], userToInvite: null, currentUserOption: null, - categoryOptions: [], headerMessage: '', }; @@ -75,7 +74,7 @@ function SearchFiltersChatsSelector({initialReportIDs, onFiltersUpdate, isScreen }, [defaultOptions, cleanSearchTerm, selectedOptions]); const {sections, headerMessage} = useMemo(() => { - const newSections: OptionsListUtils.CategorySection[] = []; + const newSections: OptionsListUtils.Section[] = []; if (!areOptionsInitialized) { return {sections: [], headerMessage: undefined}; } diff --git a/src/components/Search/SearchFiltersParticipantsSelector.tsx b/src/components/Search/SearchFiltersParticipantsSelector.tsx index 1e0c3ca8aae7..bb45e30cc5ad 100644 --- a/src/components/Search/SearchFiltersParticipantsSelector.tsx +++ b/src/components/Search/SearchFiltersParticipantsSelector.tsx @@ -25,7 +25,6 @@ const defaultListOptions = { personalDetails: [], currentUserOption: null, headerMessage: '', - categoryOptions: [], }; function getSelectedOptionData(option: Option): OptionData { @@ -73,7 +72,7 @@ function SearchFiltersParticipantsSelector({initialAccountIDs, onFiltersUpdate}: }, [defaultOptions, cleanSearchTerm, selectedOptions]); const {sections, headerMessage} = useMemo(() => { - const newSections: OptionsListUtils.CategorySection[] = []; + const newSections: OptionsListUtils.Section[] = []; if (!areOptionsInitialized) { return {sections: [], headerMessage: undefined}; } diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index 4c57c0d1f63f..bc586ff9c860 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -72,7 +72,7 @@ function SearchRouter({onRouterClose}: SearchRouterProps) { const {options, areOptionsInitialized} = useOptionsList(); const searchOptions = useMemo(() => { if (!areOptionsInitialized) { - return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null, categoryOptions: []}; + return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } return OptionsListUtils.getSearchOptions(options, '', betas ?? []); }, [areOptionsInitialized, betas, options]); diff --git a/src/libs/CategoryOptionListUtils.ts b/src/libs/CategoryOptionListUtils.ts new file mode 100644 index 000000000000..5e3feed05af3 --- /dev/null +++ b/src/libs/CategoryOptionListUtils.ts @@ -0,0 +1,282 @@ +// eslint-disable-next-line you-dont-need-lodash-underscore/get +import lodashGet from 'lodash/get'; +import lodashSet from 'lodash/set'; +import CONST from '@src/CONST'; +import type {PolicyCategories} from '@src/types/onyx'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import times from '@src/utils/times'; +import * as Localize from './Localize'; +import type {OptionTree, SectionBase} from './OptionsListUtils'; + +type CategoryTreeSection = SectionBase & { + data: OptionTree[]; + indexOffset?: number; +}; + +type Category = { + name: string; + enabled: boolean; + isSelected?: boolean; + pendingAction?: OnyxCommon.PendingAction; +}; + +type Hierarchy = Record; + +/** + * Builds the options for the category tree hierarchy via indents + * + * @param options - an initial object array + * @param options[].enabled - a flag to enable/disable option in a list + * @param options[].name - a name of an option + * @param [isOneLine] - a flag to determine if text should be one line + */ +function getCategoryOptionTree(options: Record | Category[], isOneLine = false, selectedOptions: Category[] = []): OptionTree[] { + const optionCollection = new Map(); + Object.values(options).forEach((option) => { + if (isOneLine) { + if (optionCollection.has(option.name)) { + return; + } + + optionCollection.set(option.name, { + text: option.name, + keyForList: option.name, + searchText: option.name, + tooltipText: option.name, + isDisabled: !option.enabled || option.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + isSelected: !!option.isSelected, + pendingAction: option.pendingAction, + }); + + return; + } + + option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { + const indents = times(index, () => CONST.INDENTS).join(''); + const isChild = array.length - 1 === index; + const searchText = array.slice(0, index + 1).join(CONST.PARENT_CHILD_SEPARATOR); + const selectedParentOption = !isChild && Object.values(selectedOptions).find((op) => op.name === searchText); + const isParentOptionDisabled = !selectedParentOption || !selectedParentOption.enabled || selectedParentOption.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + + if (optionCollection.has(searchText)) { + return; + } + + optionCollection.set(searchText, { + text: `${indents}${optionName}`, + keyForList: searchText, + searchText, + tooltipText: optionName, + isDisabled: isChild ? !option.enabled || option.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : isParentOptionDisabled, + isSelected: isChild ? !!option.isSelected : !!selectedParentOption, + pendingAction: option.pendingAction, + }); + }); + }); + + return Array.from(optionCollection.values()); +} + +/** + * Builds the section list for categories + */ +function getCategoryListSections({ + categories, + searchValue, + selectedOptions = [], + recentlyUsedCategories = [], + maxRecentReportsToShow = CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, +}: { + categories: PolicyCategories; + selectedOptions?: Category[]; + searchValue?: string; + recentlyUsedCategories?: string[]; + maxRecentReportsToShow?: number; +}): CategoryTreeSection[] { + const sortedCategories = sortCategories(categories); + const enabledCategories = Object.values(sortedCategories).filter((category) => category.enabled); + const enabledCategoriesNames = enabledCategories.map((category) => category.name); + const selectedOptionsWithDisabledState: Category[] = []; + const categorySections: CategoryTreeSection[] = []; + const numberOfEnabledCategories = enabledCategories.length; + + selectedOptions.forEach((option) => { + if (enabledCategoriesNames.includes(option.name)) { + const categoryObj = enabledCategories.find((category) => category.name === option.name); + selectedOptionsWithDisabledState.push({...(categoryObj ?? option), isSelected: true, enabled: true}); + return; + } + selectedOptionsWithDisabledState.push({...option, isSelected: true, enabled: false}); + }); + + if (numberOfEnabledCategories === 0 && selectedOptions.length > 0) { + const data = getCategoryOptionTree(selectedOptionsWithDisabledState, true); + categorySections.push({ + // "Selected" section + title: '', + shouldShow: false, + data, + indexOffset: data.length, + }); + + return categorySections; + } + + if (searchValue) { + const categoriesForSearch = [...selectedOptionsWithDisabledState, ...enabledCategories]; + const searchCategories: Category[] = []; + + categoriesForSearch.forEach((category) => { + if (!category.name.toLowerCase().includes(searchValue.toLowerCase())) { + return; + } + searchCategories.push({ + ...category, + isSelected: selectedOptions.some((selectedOption) => selectedOption.name === category.name), + }); + }); + + const data = getCategoryOptionTree(searchCategories, true); + categorySections.push({ + // "Search" section + title: '', + shouldShow: true, + data, + indexOffset: data.length, + }); + + return categorySections; + } + + if (selectedOptions.length > 0) { + const data = getCategoryOptionTree(selectedOptionsWithDisabledState, true); + categorySections.push({ + // "Selected" section + title: '', + shouldShow: false, + data, + indexOffset: data.length, + }); + } + + const selectedOptionNames = selectedOptions.map((selectedOption) => selectedOption.name); + const filteredCategories = enabledCategories.filter((category) => !selectedOptionNames.includes(category.name)); + + if (numberOfEnabledCategories < CONST.STANDARD_LIST_ITEM_LIMIT) { + const data = getCategoryOptionTree(filteredCategories, false, selectedOptionsWithDisabledState); + categorySections.push({ + // "All" section when items amount less than the threshold + title: '', + shouldShow: false, + data, + indexOffset: data.length, + }); + + return categorySections; + } + + const filteredRecentlyUsedCategories = recentlyUsedCategories + .filter( + (categoryName) => + !selectedOptionNames.includes(categoryName) && categories[categoryName]?.enabled && categories[categoryName]?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + ) + .map((categoryName) => ({ + name: categoryName, + enabled: categories[categoryName].enabled ?? false, + })); + + if (filteredRecentlyUsedCategories.length > 0) { + const cutRecentlyUsedCategories = filteredRecentlyUsedCategories.slice(0, maxRecentReportsToShow); + + const data = getCategoryOptionTree(cutRecentlyUsedCategories, true); + categorySections.push({ + // "Recent" section + title: Localize.translateLocal('common.recent'), + shouldShow: true, + data, + indexOffset: data.length, + }); + } + + const data = getCategoryOptionTree(filteredCategories, false, selectedOptionsWithDisabledState); + categorySections.push({ + // "All" section when items amount more than the threshold + title: Localize.translateLocal('common.all'), + shouldShow: true, + data, + indexOffset: data.length, + }); + + return categorySections; +} + +/** + * Sorts categories using a simple object. + * It builds an hierarchy (based on an object), where each category has a name and other keys as subcategories. + * Via the hierarchy we avoid duplicating and sort categories one by one. Subcategories are being sorted alphabetically. + */ +function sortCategories(categories: Record): Category[] { + // Sorts categories alphabetically by name. + const sortedCategories = Object.values(categories).sort((a, b) => a.name.localeCompare(b.name)); + + // An object that respects nesting of categories. Also, can contain only uniq categories. + const hierarchy: Hierarchy = {}; + /** + * Iterates over all categories to set each category in a proper place in hierarchy + * It gets a path based on a category name e.g. "Parent: Child: Subcategory" -> "Parent.Child.Subcategory". + * { + * Parent: { + * name: "Parent", + * Child: { + * name: "Child" + * Subcategory: { + * name: "Subcategory" + * } + * } + * } + * } + */ + sortedCategories.forEach((category) => { + const path = category.name.split(CONST.PARENT_CHILD_SEPARATOR); + const existedValue = lodashGet(hierarchy, path, {}) as Hierarchy; + lodashSet(hierarchy, path, { + ...existedValue, + name: category.name, + pendingAction: category.pendingAction, + }); + }); + + /** + * A recursive function to convert hierarchy into an array of category objects. + * The category object contains base 2 properties: "name" and "enabled". + * It iterates each key one by one. When a category has subcategories, goes deeper into them. Also, sorts subcategories alphabetically. + */ + const flatHierarchy = (initialHierarchy: Hierarchy) => + Object.values(initialHierarchy).reduce((acc: Category[], category) => { + const {name, pendingAction, ...subcategories} = category; + if (name) { + const categoryObject: Category = { + name, + pendingAction, + enabled: categories[name]?.enabled ?? false, + }; + + acc.push(categoryObject); + } + + if (!isEmptyObject(subcategories)) { + const nestedCategories = flatHierarchy(subcategories); + + acc.push(...nestedCategories.sort((a, b) => a.name.localeCompare(b.name))); + } + + return acc; + }, []); + + return flatHierarchy(hierarchy); +} + +export {getCategoryListSections, getCategoryOptionTree, sortCategories}; + +export type {Category, SectionBase as CategorySectionBase, CategoryTreeSection, Hierarchy}; diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 3308658fa735..8fa89558bd25 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -1,9 +1,6 @@ /* eslint-disable no-continue */ import {Str} from 'expensify-common'; -// eslint-disable-next-line you-dont-need-lodash-underscore/get -import lodashGet from 'lodash/get'; import lodashOrderBy from 'lodash/orderBy'; -import lodashSet from 'lodash/set'; import lodashSortBy from 'lodash/sortBy'; import Onyx from 'react-native-onyx'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; @@ -32,7 +29,6 @@ import type {Attendee, Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import times from '@src/utils/times'; import Timing from './actions/Timing'; import filterArrayByMatch from './filterArrayByMatch'; import * as LocalePhoneNumber from './LocalePhoneNumber'; @@ -84,29 +80,15 @@ type PayeePersonalDetails = { keyForList: string; }; -type CategorySectionBase = { +type SectionBase = { title: string | undefined; shouldShow: boolean; }; -type CategorySection = CategorySectionBase & { +type Section = SectionBase & { data: Option[]; }; -type CategoryTreeSection = CategorySectionBase & { - data: OptionTree[]; - indexOffset?: number; -}; - -type Category = { - name: string; - enabled: boolean; - isSelected?: boolean; - pendingAction?: OnyxCommon.PendingAction; -}; - -type Hierarchy = Record; - type GetOptionsConfig = { reportActions?: ReportActions; betas?: OnyxEntry; @@ -127,9 +109,6 @@ type GetOptionsConfig = { includeMoneyRequests?: boolean; excludeUnknownUsers?: boolean; includeP2P?: boolean; - includeCategories?: boolean; - categories?: PolicyCategories; - recentlyUsedCategories?: string[]; canInviteUser?: boolean; includeSelectedOptions?: boolean; transactionViolations?: OnyxCollection; @@ -165,14 +144,13 @@ type MemberForList = { }; type SectionForSearchTerm = { - section: CategorySection; + section: Section; }; type Options = { recentReports: ReportUtils.OptionData[]; personalDetails: ReportUtils.OptionData[]; userToInvite: ReportUtils.OptionData | null; currentUserOption: ReportUtils.OptionData | null | undefined; - categoryOptions: CategoryTreeSection[]; }; type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: boolean; showPersonalDetails?: boolean}; @@ -871,254 +849,6 @@ function hasEnabledOptions(options: PolicyCategories | PolicyTag[]): boolean { return Object.values(options).some((option: PolicyTag | PolicyCategory) => option.enabled && option.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); } -/** - * Sorts categories using a simple object. - * It builds an hierarchy (based on an object), where each category has a name and other keys as subcategories. - * Via the hierarchy we avoid duplicating and sort categories one by one. Subcategories are being sorted alphabetically. - */ -function sortCategories(categories: Record): Category[] { - // Sorts categories alphabetically by name. - const sortedCategories = Object.values(categories).sort((a, b) => a.name.localeCompare(b.name)); - - // An object that respects nesting of categories. Also, can contain only uniq categories. - const hierarchy: Hierarchy = {}; - /** - * Iterates over all categories to set each category in a proper place in hierarchy - * It gets a path based on a category name e.g. "Parent: Child: Subcategory" -> "Parent.Child.Subcategory". - * { - * Parent: { - * name: "Parent", - * Child: { - * name: "Child" - * Subcategory: { - * name: "Subcategory" - * } - * } - * } - * } - */ - sortedCategories.forEach((category) => { - const path = category.name.split(CONST.PARENT_CHILD_SEPARATOR); - const existedValue = lodashGet(hierarchy, path, {}) as Hierarchy; - lodashSet(hierarchy, path, { - ...existedValue, - name: category.name, - pendingAction: category.pendingAction, - }); - }); - - /** - * A recursive function to convert hierarchy into an array of category objects. - * The category object contains base 2 properties: "name" and "enabled". - * It iterates each key one by one. When a category has subcategories, goes deeper into them. Also, sorts subcategories alphabetically. - */ - const flatHierarchy = (initialHierarchy: Hierarchy) => - Object.values(initialHierarchy).reduce((acc: Category[], category) => { - const {name, pendingAction, ...subcategories} = category; - if (name) { - const categoryObject: Category = { - name, - pendingAction, - enabled: categories[name]?.enabled ?? false, - }; - - acc.push(categoryObject); - } - - if (!isEmptyObject(subcategories)) { - const nestedCategories = flatHierarchy(subcategories); - - acc.push(...nestedCategories.sort((a, b) => a.name.localeCompare(b.name))); - } - - return acc; - }, []); - - return flatHierarchy(hierarchy); -} - -/** - * Builds the options for the category tree hierarchy via indents - * - * @param options - an initial object array - * @param options[].enabled - a flag to enable/disable option in a list - * @param options[].name - a name of an option - * @param [isOneLine] - a flag to determine if text should be one line - */ -function getCategoryOptionTree(options: Record | Category[], isOneLine = false, selectedOptions: Category[] = []): OptionTree[] { - const optionCollection = new Map(); - Object.values(options).forEach((option) => { - if (isOneLine) { - if (optionCollection.has(option.name)) { - return; - } - - optionCollection.set(option.name, { - text: option.name, - keyForList: option.name, - searchText: option.name, - tooltipText: option.name, - isDisabled: !option.enabled || option.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - isSelected: !!option.isSelected, - pendingAction: option.pendingAction, - }); - - return; - } - - option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { - const indents = times(index, () => CONST.INDENTS).join(''); - const isChild = array.length - 1 === index; - const searchText = array.slice(0, index + 1).join(CONST.PARENT_CHILD_SEPARATOR); - const selectedParentOption = !isChild && Object.values(selectedOptions).find((op) => op.name === searchText); - const isParentOptionDisabled = !selectedParentOption || !selectedParentOption.enabled || selectedParentOption.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; - - if (optionCollection.has(searchText)) { - return; - } - - optionCollection.set(searchText, { - text: `${indents}${optionName}`, - keyForList: searchText, - searchText, - tooltipText: optionName, - isDisabled: isChild ? !option.enabled || option.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : isParentOptionDisabled, - isSelected: isChild ? !!option.isSelected : !!selectedParentOption, - pendingAction: option.pendingAction, - }); - }); - }); - - return Array.from(optionCollection.values()); -} - -/** - * Builds the section list for categories - */ -function getCategoryListSections( - categories: PolicyCategories, - recentlyUsedCategories: string[], - selectedOptions: Category[], - searchInputValue: string, - maxRecentReportsToShow: number, -): CategoryTreeSection[] { - const sortedCategories = sortCategories(categories); - const enabledCategories = Object.values(sortedCategories).filter((category) => category.enabled); - const enabledCategoriesNames = enabledCategories.map((category) => category.name); - const selectedOptionsWithDisabledState: Category[] = []; - const categorySections: CategoryTreeSection[] = []; - const numberOfEnabledCategories = enabledCategories.length; - - selectedOptions.forEach((option) => { - if (enabledCategoriesNames.includes(option.name)) { - const categoryObj = enabledCategories.find((category) => category.name === option.name); - selectedOptionsWithDisabledState.push({...(categoryObj ?? option), isSelected: true, enabled: true}); - return; - } - selectedOptionsWithDisabledState.push({...option, isSelected: true, enabled: false}); - }); - - if (numberOfEnabledCategories === 0 && selectedOptions.length > 0) { - const data = getCategoryOptionTree(selectedOptionsWithDisabledState, true); - categorySections.push({ - // "Selected" section - title: '', - shouldShow: false, - data, - indexOffset: data.length, - }); - - return categorySections; - } - - if (searchInputValue) { - const categoriesForSearch = [...selectedOptionsWithDisabledState, ...enabledCategories]; - const searchCategories: Category[] = []; - - categoriesForSearch.forEach((category) => { - if (!category.name.toLowerCase().includes(searchInputValue.toLowerCase())) { - return; - } - searchCategories.push({ - ...category, - isSelected: selectedOptions.some((selectedOption) => selectedOption.name === category.name), - }); - }); - - const data = getCategoryOptionTree(searchCategories, true); - categorySections.push({ - // "Search" section - title: '', - shouldShow: true, - data, - indexOffset: data.length, - }); - - return categorySections; - } - - if (selectedOptions.length > 0) { - const data = getCategoryOptionTree(selectedOptionsWithDisabledState, true); - categorySections.push({ - // "Selected" section - title: '', - shouldShow: false, - data, - indexOffset: data.length, - }); - } - - const selectedOptionNames = selectedOptions.map((selectedOption) => selectedOption.name); - const filteredCategories = enabledCategories.filter((category) => !selectedOptionNames.includes(category.name)); - - if (numberOfEnabledCategories < CONST.STANDARD_LIST_ITEM_LIMIT) { - const data = getCategoryOptionTree(filteredCategories, false, selectedOptionsWithDisabledState); - categorySections.push({ - // "All" section when items amount less than the threshold - title: '', - shouldShow: false, - data, - indexOffset: data.length, - }); - - return categorySections; - } - - const filteredRecentlyUsedCategories = recentlyUsedCategories - .filter( - (categoryName) => - !selectedOptionNames.includes(categoryName) && categories[categoryName]?.enabled && categories[categoryName]?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, - ) - .map((categoryName) => ({ - name: categoryName, - enabled: categories[categoryName].enabled ?? false, - })); - - if (filteredRecentlyUsedCategories.length > 0) { - const cutRecentlyUsedCategories = filteredRecentlyUsedCategories.slice(0, maxRecentReportsToShow); - - const data = getCategoryOptionTree(cutRecentlyUsedCategories, true); - categorySections.push({ - // "Recent" section - title: Localize.translateLocal('common.recent'), - shouldShow: true, - data, - indexOffset: data.length, - }); - } - - const data = getCategoryOptionTree(filteredCategories, false, selectedOptionsWithDisabledState); - categorySections.push({ - // "All" section when items amount more than the threshold - title: Localize.translateLocal('common.all'), - shouldShow: true, - data, - indexOffset: data.length, - }); - - return categorySections; -} - /** * Checks if a report option is selected based on matching accountID or reportID. * @@ -1344,9 +1074,6 @@ function getOptions( includeMoneyRequests = false, excludeUnknownUsers = false, includeP2P = true, - includeCategories = false, - categories = {}, - recentlyUsedCategories = [], canInviteUser = true, includeSelectedOptions = false, transactionViolations = {}, @@ -1358,18 +1085,6 @@ function getOptions( shouldBoldTitleByDefault = true, }: GetOptionsConfig, ): Options { - if (includeCategories) { - const categoryOptions = getCategoryListSections(categories, recentlyUsedCategories, selectedOptions as Category[], searchInputValue, maxRecentReportsToShow); - - return { - recentReports: [], - personalDetails: [], - userToInvite: null, - currentUserOption: null, - categoryOptions, - }; - } - const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue))); const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number?.e164 ?? '' : searchInputValue.toLowerCase(); const topmostReportId = Navigation.getTopmostReportId() ?? '-1'; @@ -1625,7 +1340,6 @@ function getOptions( recentReports: recentReportOptions, userToInvite: canInviteUser ? userToInvite : null, currentUserOption, - categoryOptions: [], }; } @@ -1708,9 +1422,6 @@ type FilteredOptionsParams = { excludeLogins?: string[]; includeOwnedWorkspaceChats?: boolean; includeP2P?: boolean; - includeCategories?: boolean; - categories?: PolicyCategories; - recentlyUsedCategories?: string[]; canInviteUser?: boolean; includeSelectedOptions?: boolean; maxRecentReportsToShow?: number; @@ -1741,9 +1452,6 @@ function getFilteredOptions(params: FilteredOptionsParamsWithDefaultSearchValue excludeLogins = [], includeOwnedWorkspaceChats = false, includeP2P = true, - includeCategories = false, - categories = {}, - recentlyUsedCategories = [], canInviteUser = true, includeSelectedOptions = false, maxRecentReportsToShow = CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW, @@ -1763,9 +1471,6 @@ function getFilteredOptions(params: FilteredOptionsParamsWithDefaultSearchValue excludeLogins, includeOwnedWorkspaceChats, includeP2P, - includeCategories, - categories, - recentlyUsedCategories, canInviteUser, includeSelectedOptions, includeSelfDM, @@ -1799,9 +1504,6 @@ function getAttendeeOptions( includeOwnedWorkspaceChats, includeRecentReports: false, includeP2P, - includeCategories: false, - categories: {}, - recentlyUsedCategories: [], canInviteUser, includeSelectedOptions: false, maxRecentReportsToShow: 0, @@ -2099,7 +1801,6 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt personalDetails: personalDetails ?? [], userToInvite: null, currentUserOption, - categoryOptions: [], }; }, options); @@ -2135,7 +1836,6 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt recentReports: sortedRecentReports, userToInvite, currentUserOption: matchResults.currentUserOption, - categoryOptions: [], }; } @@ -2149,7 +1849,6 @@ function getEmptyOptions(): Options { personalDetails: [], userToInvite: null, currentUserOption: null, - categoryOptions: [], }; } @@ -2181,9 +1880,7 @@ export { getLastMessageTextForReport, getEnabledCategoriesCount, hasEnabledOptions, - sortCategories, sortAlphabetically, - getCategoryOptionTree, formatMemberForList, formatSectionsFromSearchTerm, getShareLogOptions, @@ -2204,4 +1901,4 @@ export { hasReportErrors, }; -export type {MemberForList, CategorySection, CategoryTreeSection, Options, OptionList, SearchOption, PayeePersonalDetails, Category, Option, OptionTree}; +export type {Section, SectionBase, MemberForList, Options, OptionList, SearchOption, PayeePersonalDetails, Option, OptionTree}; diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx index c28290e353e7..8ab5e209a904 100755 --- a/src/pages/NewChatPage.tsx +++ b/src/pages/NewChatPage.tsx @@ -139,7 +139,7 @@ function NewChatPage() { useOptions(); const [sections, firstKeyForList] = useMemo(() => { - const sectionsList: OptionsListUtils.CategorySection[] = []; + const sectionsList: OptionsListUtils.Section[] = []; let firstKey = ''; const formatResults = OptionsListUtils.formatSectionsFromSearchTerm(debouncedSearchTerm, selectedOptions, recentReports, personalDetails); diff --git a/src/pages/RoomInvitePage.tsx b/src/pages/RoomInvitePage.tsx index 3fafc163e5ff..5294ba3b566d 100644 --- a/src/pages/RoomInvitePage.tsx +++ b/src/pages/RoomInvitePage.tsx @@ -72,7 +72,7 @@ function RoomInvitePage({ const defaultOptions = useMemo(() => { if (!areOptionsInitialized) { - return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null, categoryOptions: []}; + return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], '', excludedUsers); @@ -95,7 +95,6 @@ function RoomInvitePage({ selectedOptions: newSelectedOptions, recentReports: [], currentUserOption: null, - categoryOptions: [], }; }, [areOptionsInitialized, betas, excludedUsers, options.personalDetails, selectedOptions]); diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersCardPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersCardPage.tsx index 92d07c3caffc..8e178f94029c 100644 --- a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersCardPage.tsx +++ b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersCardPage.tsx @@ -10,7 +10,7 @@ import SelectionList from '@components/SelectionList'; import CardListItem from '@components/SelectionList/CardListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {CategorySection} from '@libs/OptionsListUtils'; +import type {Section} from '@libs/OptionsListUtils'; import type {OptionData} from '@libs/ReportUtils'; import Navigation from '@navigation/Navigation'; import * as SearchActions from '@userActions/Search'; @@ -28,7 +28,7 @@ function SearchFiltersCardPage() { const [newCards, setNewCards] = useState(currentCards ?? []); const sections = useMemo(() => { - const newSections: CategorySection[] = []; + const newSections: Section[] = []; const cards = Object.values(cardList ?? {}) .sort((a, b) => a.bank.localeCompare(b.bank)) .map((card) => { diff --git a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx index ca655caea123..9d5253385604 100644 --- a/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx +++ b/src/pages/iou/request/MoneyRequestAttendeeSelector.tsx @@ -113,7 +113,6 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde personalDetails: [], currentUserOption: null, headerMessage: '', - categoryOptions: [], }; } const newOptions = OptionsListUtils.filterOptions(defaultOptions, debouncedSearchTerm, { @@ -129,7 +128,7 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde * Returns the sections needed for the OptionsSelector */ const [sections, header] = useMemo(() => { - const newSections: OptionsListUtils.CategorySection[] = []; + const newSections: OptionsListUtils.Section[] = []; if (!areOptionsInitialized || !didScreenTransitionEnd) { return [newSections, '']; } diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index a17cffd0cdd9..638c58708971 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -102,7 +102,6 @@ function MoneyRequestParticipantsSelector({ personalDetails: [], currentUserOption: null, headerMessage: '', - categoryOptions: [], }; } @@ -137,7 +136,6 @@ function MoneyRequestParticipantsSelector({ personalDetails: [], currentUserOption: null, headerMessage: '', - categoryOptions: [], }; } @@ -158,7 +156,7 @@ function MoneyRequestParticipantsSelector({ * @returns {Array} */ const [sections, header] = useMemo(() => { - const newSections: OptionsListUtils.CategorySection[] = []; + const newSections: OptionsListUtils.Section[] = []; if (!areOptionsInitialized || !didScreenTransitionEnd) { return [newSections, '']; } diff --git a/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx b/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx index cd4674ce0165..50e0fb9aed97 100644 --- a/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx +++ b/src/pages/settings/AboutPage/ShareLogList/BaseShareLogList.tsx @@ -34,7 +34,6 @@ function BaseShareLogList({onAttachLogToReport}: BaseShareLogListProps) { personalDetails: [], userToInvite: null, currentUserOption: null, - categoryOptions: [], headerMessage: '', }; } diff --git a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx index 6f54fc098633..1b5fc3ce246c 100644 --- a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx +++ b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx @@ -50,7 +50,6 @@ function useOptions() { personalDetails, currentUserOption, headerMessage, - categoryOptions: [], }; }, [optionsList.reports, optionsList.personalDetails, betas, existingDelegates, isLoading]); diff --git a/src/pages/tasks/TaskAssigneeSelectorModal.tsx b/src/pages/tasks/TaskAssigneeSelectorModal.tsx index 33ca336206fe..27da040fa654 100644 --- a/src/pages/tasks/TaskAssigneeSelectorModal.tsx +++ b/src/pages/tasks/TaskAssigneeSelectorModal.tsx @@ -62,7 +62,6 @@ function useOptions() { personalDetails, currentUserOption, headerMessage, - categoryOptions: [], }; }, [optionsList.reports, optionsList.personalDetails, betas, isLoading]); diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.tsx b/src/pages/tasks/TaskShareDestinationSelectorModal.tsx index 8465474ef609..7ce89e666300 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.tsx +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.tsx @@ -63,7 +63,6 @@ function TaskShareDestinationSelectorModal() { personalDetails: [], userToInvite: null, currentUserOption: null, - categoryOptions: [], header: '', }; } @@ -75,7 +74,6 @@ function TaskShareDestinationSelectorModal() { personalDetails: [], userToInvite: null, currentUserOption: null, - categoryOptions: [], header, }; }, [areOptionsInitialized, optionList.personalDetails, optionList.reports]); diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index a259fc7b9ce1..9321a8bfd6b7 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -87,12 +87,12 @@ function WorkspaceInvitePage({route, policy}: WorkspaceInvitePageProps) { const defaultOptions = useMemo(() => { if (!areOptionsInitialized) { - return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null, categoryOptions: []}; + return {recentReports: [], personalDetails: [], userToInvite: null, currentUserOption: null}; } const inviteOptions = OptionsListUtils.getMemberInviteOptions(options.personalDetails, betas ?? [], '', excludedUsers, true); - return {...inviteOptions, recentReports: [], currentUserOption: null, categoryOptions: []}; + return {...inviteOptions, recentReports: [], currentUserOption: null}; }, [areOptionsInitialized, betas, excludedUsers, options.personalDetails]); const inviteOptions = useMemo( diff --git a/tests/unit/CategoryOptionListUtilsTest.ts b/tests/unit/CategoryOptionListUtilsTest.ts new file mode 100644 index 000000000000..2537094511ce --- /dev/null +++ b/tests/unit/CategoryOptionListUtilsTest.ts @@ -0,0 +1,1242 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import * as CategoryOptionsListUtils from '@libs/CategoryOptionListUtils'; +import type {PolicyCategories} from '@src/types/onyx'; +import type {PendingAction} from '@src/types/onyx/OnyxCommon'; + +describe('CategoryOptionListUtils', () => { + it('getCategoryListSections()', () => { + const search = 'Food'; + const emptySearch = ''; + const wrongSearch = 'bla bla'; + const recentlyUsedCategories = ['Taxi', 'Restaurant']; + const selectedOptions: CategoryOptionsListUtils.Category[] = [ + { + name: 'Medical', + enabled: true, + }, + ]; + const smallCategoriesList: PolicyCategories = { + Taxi: { + enabled: false, + name: 'Taxi', + unencodedName: 'Taxi', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + pendingAction: undefined, + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + unencodedName: 'Restaurant', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + pendingAction: 'delete', + }, + Food: { + enabled: true, + name: 'Food', + unencodedName: 'Food', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + pendingAction: undefined, + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + unencodedName: 'Food: Meat', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + pendingAction: undefined, + }, + }; + const smallResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: false, + data: [ + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: true, + isSelected: false, + pendingAction: 'delete', + }, + ], + indexOffset: 3, + }, + ]; + const smallSearchResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: true, + indexOffset: 2, + data: [ + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food: Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Food: Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ], + }, + ]; + const smallWrongSearchResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: true, + indexOffset: 0, + data: [], + }, + ]; + const largeCategoriesList: PolicyCategories = { + Taxi: { + enabled: false, + name: 'Taxi', + unencodedName: 'Taxi', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + unencodedName: 'Restaurant', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + Food: { + enabled: true, + name: 'Food', + unencodedName: 'Food', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + unencodedName: 'Food: Meat', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Food: Milk': { + enabled: true, + name: 'Food: Milk', + unencodedName: 'Food: Milk', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Food: Vegetables': { + enabled: false, + name: 'Food: Vegetables', + unencodedName: 'Food: Vegetables', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Cars: Audi': { + enabled: true, + name: 'Cars: Audi', + unencodedName: 'Cars: Audi', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Cars: BMW': { + enabled: false, + name: 'Cars: BMW', + unencodedName: 'Cars: BMW', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Cars: Mercedes-Benz': { + enabled: true, + name: 'Cars: Mercedes-Benz', + unencodedName: 'Cars: Mercedes-Benz', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + Medical: { + enabled: false, + name: 'Medical', + unencodedName: 'Medical', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Travel: Meals': { + enabled: true, + name: 'Travel: Meals', + unencodedName: 'Travel: Meals', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Travel: Meals: Breakfast': { + enabled: true, + name: 'Travel: Meals: Breakfast', + unencodedName: 'Travel: Meals: Breakfast', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Travel: Meals: Dinner': { + enabled: false, + name: 'Travel: Meals: Dinner', + unencodedName: 'Travel: Meals: Dinner', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + 'Travel: Meals: Lunch': { + enabled: true, + name: 'Travel: Meals: Lunch', + unencodedName: 'Travel: Meals: Lunch', + areCommentsRequired: false, + 'GL Code': '', + externalID: '', + origin: '', + }, + }; + const largeResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: false, + indexOffset: 1, + data: [ + { + text: 'Medical', + keyForList: 'Medical', + searchText: 'Medical', + tooltipText: 'Medical', + isDisabled: true, + isSelected: true, + pendingAction: undefined, + }, + ], + }, + { + title: 'Recent', + shouldShow: true, + indexOffset: 1, + data: [ + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ], + }, + { + title: 'All', + shouldShow: true, + indexOffset: 11, + data: [ + { + text: 'Cars', + keyForList: 'Cars', + searchText: 'Cars', + tooltipText: 'Cars', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Audi', + keyForList: 'Cars: Audi', + searchText: 'Cars: Audi', + tooltipText: 'Audi', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Mercedes-Benz', + keyForList: 'Cars: Mercedes-Benz', + searchText: 'Cars: Mercedes-Benz', + tooltipText: 'Mercedes-Benz', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Milk', + keyForList: 'Food: Milk', + searchText: 'Food: Milk', + tooltipText: 'Milk', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Travel', + keyForList: 'Travel', + searchText: 'Travel', + tooltipText: 'Travel', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Meals', + keyForList: 'Travel: Meals', + searchText: 'Travel: Meals', + tooltipText: 'Meals', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Breakfast', + keyForList: 'Travel: Meals: Breakfast', + searchText: 'Travel: Meals: Breakfast', + tooltipText: 'Breakfast', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Lunch', + keyForList: 'Travel: Meals: Lunch', + searchText: 'Travel: Meals: Lunch', + tooltipText: 'Lunch', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ], + }, + ]; + const largeSearchResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: true, + indexOffset: 3, + data: [ + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food: Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Food: Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food: Milk', + keyForList: 'Food: Milk', + searchText: 'Food: Milk', + tooltipText: 'Food: Milk', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ], + }, + ]; + const largeWrongSearchResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: true, + indexOffset: 0, + data: [], + }, + ]; + const emptyCategoriesList = {}; + const emptySelectedResultList: CategoryOptionsListUtils.CategoryTreeSection[] = [ + { + title: '', + shouldShow: false, + indexOffset: 1, + data: [ + { + text: 'Medical', + keyForList: 'Medical', + searchText: 'Medical', + tooltipText: 'Medical', + isDisabled: true, + isSelected: true, + pendingAction: undefined, + }, + ], + }, + ]; + + const smallResult = CategoryOptionsListUtils.getCategoryListSections({ + searchValue: emptySearch, + categories: smallCategoriesList, + }); + expect(smallResult).toStrictEqual(smallResultList); + + const smallSearchResult = CategoryOptionsListUtils.getCategoryListSections({searchValue: search, categories: smallCategoriesList}); + expect(smallSearchResult).toStrictEqual(smallSearchResultList); + + const smallWrongSearchResult = CategoryOptionsListUtils.getCategoryListSections({searchValue: wrongSearch, categories: smallCategoriesList}); + expect(smallWrongSearchResult).toStrictEqual(smallWrongSearchResultList); + + const largeResult = CategoryOptionsListUtils.getCategoryListSections({ + searchValue: emptySearch, + selectedOptions, + categories: largeCategoriesList, + recentlyUsedCategories, + }); + expect(largeResult).toStrictEqual(largeResultList); + + const largeSearchResult = CategoryOptionsListUtils.getCategoryListSections({ + searchValue: search, + selectedOptions, + categories: largeCategoriesList, + recentlyUsedCategories, + }); + expect(largeSearchResult).toStrictEqual(largeSearchResultList); + + const largeWrongSearchResult = CategoryOptionsListUtils.getCategoryListSections({ + searchValue: wrongSearch, + selectedOptions, + categories: largeCategoriesList, + recentlyUsedCategories, + }); + expect(largeWrongSearchResult).toStrictEqual(largeWrongSearchResultList); + + const emptyResult = CategoryOptionsListUtils.getCategoryListSections({searchValue: search, selectedOptions, categories: emptyCategoriesList}); + expect(emptyResult).toStrictEqual(emptySelectedResultList); + }); + + it('getCategoryOptionTree()', () => { + const categories = { + Meals: { + enabled: true, + name: 'Meals', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + Food: { + enabled: true, + name: 'Food', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + }, + 'Food: Milk': { + enabled: true, + name: 'Food: Milk', + }, + 'Cars: Audi': { + enabled: true, + name: 'Cars: Audi', + }, + 'Cars: Mercedes-Benz': { + enabled: true, + name: 'Cars: Mercedes-Benz', + }, + 'Travel: Meals': { + enabled: true, + name: 'Travel: Meals', + }, + 'Travel: Meals: Breakfast': { + enabled: true, + name: 'Travel: Meals: Breakfast', + }, + 'Travel: Meals: Lunch': { + enabled: true, + name: 'Travel: Meals: Lunch', + }, + Plain: { + enabled: true, + name: 'Plain', + }, + Audi: { + enabled: true, + name: 'Audi', + }, + Health: { + enabled: true, + name: 'Health', + }, + 'A: B: C': { + enabled: true, + name: 'A: B: C', + }, + 'A: B: C: D: E': { + enabled: true, + name: 'A: B: C: D: E', + }, + }; + const result = [ + { + text: 'Meals', + keyForList: 'Meals', + searchText: 'Meals', + tooltipText: 'Meals', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Milk', + keyForList: 'Food: Milk', + searchText: 'Food: Milk', + tooltipText: 'Milk', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Cars', + keyForList: 'Cars', + searchText: 'Cars', + tooltipText: 'Cars', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Audi', + keyForList: 'Cars: Audi', + searchText: 'Cars: Audi', + tooltipText: 'Audi', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Mercedes-Benz', + keyForList: 'Cars: Mercedes-Benz', + searchText: 'Cars: Mercedes-Benz', + tooltipText: 'Mercedes-Benz', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Travel', + keyForList: 'Travel', + searchText: 'Travel', + tooltipText: 'Travel', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Meals', + keyForList: 'Travel: Meals', + searchText: 'Travel: Meals', + tooltipText: 'Meals', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Breakfast', + keyForList: 'Travel: Meals: Breakfast', + searchText: 'Travel: Meals: Breakfast', + tooltipText: 'Breakfast', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' Lunch', + keyForList: 'Travel: Meals: Lunch', + searchText: 'Travel: Meals: Lunch', + tooltipText: 'Lunch', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Plain', + keyForList: 'Plain', + searchText: 'Plain', + tooltipText: 'Plain', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Audi', + keyForList: 'Audi', + searchText: 'Audi', + tooltipText: 'Audi', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Health', + keyForList: 'Health', + searchText: 'Health', + tooltipText: 'Health', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'A', + keyForList: 'A', + searchText: 'A', + tooltipText: 'A', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' B', + keyForList: 'A: B', + searchText: 'A: B', + tooltipText: 'B', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' C', + keyForList: 'A: B: C', + searchText: 'A: B: C', + tooltipText: 'C', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' D', + keyForList: 'A: B: C: D', + searchText: 'A: B: C: D', + tooltipText: 'D', + isDisabled: true, + isSelected: false, + pendingAction: undefined, + }, + { + text: ' E', + keyForList: 'A: B: C: D: E', + searchText: 'A: B: C: D: E', + tooltipText: 'E', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ]; + const resultOneLine = [ + { + text: 'Meals', + keyForList: 'Meals', + searchText: 'Meals', + tooltipText: 'Meals', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food: Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Food: Meat', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Food: Milk', + keyForList: 'Food: Milk', + searchText: 'Food: Milk', + tooltipText: 'Food: Milk', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Cars: Audi', + keyForList: 'Cars: Audi', + searchText: 'Cars: Audi', + tooltipText: 'Cars: Audi', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Cars: Mercedes-Benz', + keyForList: 'Cars: Mercedes-Benz', + searchText: 'Cars: Mercedes-Benz', + tooltipText: 'Cars: Mercedes-Benz', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Travel: Meals', + keyForList: 'Travel: Meals', + searchText: 'Travel: Meals', + tooltipText: 'Travel: Meals', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Travel: Meals: Breakfast', + keyForList: 'Travel: Meals: Breakfast', + searchText: 'Travel: Meals: Breakfast', + tooltipText: 'Travel: Meals: Breakfast', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Travel: Meals: Lunch', + keyForList: 'Travel: Meals: Lunch', + searchText: 'Travel: Meals: Lunch', + tooltipText: 'Travel: Meals: Lunch', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Plain', + keyForList: 'Plain', + searchText: 'Plain', + tooltipText: 'Plain', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Audi', + keyForList: 'Audi', + searchText: 'Audi', + tooltipText: 'Audi', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'Health', + keyForList: 'Health', + searchText: 'Health', + tooltipText: 'Health', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'A: B: C', + keyForList: 'A: B: C', + searchText: 'A: B: C', + tooltipText: 'A: B: C', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + { + text: 'A: B: C: D: E', + keyForList: 'A: B: C: D: E', + searchText: 'A: B: C: D: E', + tooltipText: 'A: B: C: D: E', + isDisabled: false, + isSelected: false, + pendingAction: undefined, + }, + ]; + + expect(CategoryOptionsListUtils.getCategoryOptionTree(categories)).toStrictEqual(result); + expect(CategoryOptionsListUtils.getCategoryOptionTree(categories, true)).toStrictEqual(resultOneLine); + }); + + it('sortCategories', () => { + const categoriesIncorrectOrdering = { + Taxi: { + name: 'Taxi', + enabled: false, + }, + 'Test1: Subtest2': { + name: 'Test1: Subtest2', + enabled: true, + }, + 'Test: Test1: Subtest4': { + name: 'Test: Test1: Subtest4', + enabled: true, + }, + Taxes: { + name: 'Taxes', + enabled: true, + }, + Test: { + name: 'Test', + enabled: true, + pendingAction: 'delete' as PendingAction, + }, + Test1: { + name: 'Test1', + enabled: true, + }, + 'Travel: Nested-Travel': { + name: 'Travel: Nested-Travel', + enabled: true, + }, + 'Test1: Subtest1': { + name: 'Test1: Subtest1', + enabled: true, + }, + 'Test: Test1': { + name: 'Test: Test1', + enabled: true, + }, + 'Test: Test1: Subtest1': { + name: 'Test: Test1: Subtest1', + enabled: true, + }, + 'Test: Test1: Subtest3': { + name: 'Test: Test1: Subtest3', + enabled: false, + }, + 'Test: Test1: Subtest2': { + name: 'Test: Test1: Subtest2', + enabled: true, + }, + 'Test: Test2': { + name: 'Test: Test2', + enabled: true, + }, + Travel: { + name: 'Travel', + enabled: true, + }, + Utilities: { + name: 'Utilities', + enabled: true, + }, + 'Test: Test3: Subtest1': { + name: 'Test: Test3: Subtest1', + enabled: true, + }, + 'Test1: Subtest3': { + name: 'Test1: Subtest3', + enabled: true, + }, + }; + const result = [ + { + name: 'Taxes', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Taxi', + enabled: false, + pendingAction: undefined, + }, + { + name: 'Test', + enabled: true, + pendingAction: 'delete', + }, + { + name: 'Test: Test1', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test: Test1: Subtest1', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test: Test1: Subtest2', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test: Test1: Subtest3', + enabled: false, + pendingAction: undefined, + }, + { + name: 'Test: Test1: Subtest4', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test: Test2', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test: Test3: Subtest1', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test1', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test1: Subtest1', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test1: Subtest2', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Test1: Subtest3', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Travel', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Travel: Nested-Travel', + enabled: true, + pendingAction: undefined, + }, + { + name: 'Utilities', + enabled: true, + pendingAction: undefined, + }, + ]; + const categoriesIncorrectOrdering2 = { + 'Cars: BMW': { + enabled: false, + name: 'Cars: BMW', + }, + Medical: { + enabled: false, + name: 'Medical', + }, + 'Travel: Meals: Lunch': { + enabled: true, + name: 'Travel: Meals: Lunch', + }, + 'Cars: Mercedes-Benz': { + enabled: true, + name: 'Cars: Mercedes-Benz', + }, + Food: { + enabled: true, + name: 'Food', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + }, + 'Travel: Meals: Dinner': { + enabled: false, + name: 'Travel: Meals: Dinner', + }, + 'Food: Vegetables': { + enabled: false, + name: 'Food: Vegetables', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + Taxi: { + enabled: false, + name: 'Taxi', + }, + 'Food: Milk': { + enabled: true, + name: 'Food: Milk', + }, + 'Travel: Meals': { + enabled: true, + name: 'Travel: Meals', + }, + 'Travel: Meals: Breakfast': { + enabled: true, + name: 'Travel: Meals: Breakfast', + }, + 'Cars: Audi': { + enabled: true, + name: 'Cars: Audi', + }, + }; + const result2 = [ + { + enabled: true, + name: 'Cars: Audi', + pendingAction: undefined, + }, + { + enabled: false, + name: 'Cars: BMW', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Cars: Mercedes-Benz', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Food', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Food: Meat', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Food: Milk', + pendingAction: undefined, + }, + { + enabled: false, + name: 'Food: Vegetables', + pendingAction: undefined, + }, + { + enabled: false, + name: 'Medical', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Restaurant', + pendingAction: undefined, + }, + { + enabled: false, + name: 'Taxi', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Travel: Meals', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Travel: Meals: Breakfast', + pendingAction: undefined, + }, + { + enabled: false, + name: 'Travel: Meals: Dinner', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Travel: Meals: Lunch', + pendingAction: undefined, + }, + ]; + const categoriesIncorrectOrdering3 = { + 'Movies: Mr. Nobody': { + enabled: true, + name: 'Movies: Mr. Nobody', + }, + Movies: { + enabled: true, + name: 'Movies', + }, + 'House, M.D.': { + enabled: true, + name: 'House, M.D.', + }, + 'Dr. House': { + enabled: true, + name: 'Dr. House', + }, + 'Many.dots.on.the.way.': { + enabled: true, + name: 'Many.dots.on.the.way.', + }, + 'More.Many.dots.on.the.way.': { + enabled: false, + name: 'More.Many.dots.on.the.way.', + }, + }; + const result3 = [ + { + enabled: true, + name: 'Dr. House', + pendingAction: undefined, + }, + { + enabled: true, + name: 'House, M.D.', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Many.dots.on.the.way.', + pendingAction: undefined, + }, + { + enabled: false, + name: 'More.Many.dots.on.the.way.', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Movies', + pendingAction: undefined, + }, + { + enabled: true, + name: 'Movies: Mr. Nobody', + pendingAction: undefined, + }, + ]; + + expect(CategoryOptionsListUtils.sortCategories(categoriesIncorrectOrdering)).toStrictEqual(result); + expect(CategoryOptionsListUtils.sortCategories(categoriesIncorrectOrdering2)).toStrictEqual(result2); + expect(CategoryOptionsListUtils.sortCategories(categoriesIncorrectOrdering3)).toStrictEqual(result3); + }); +}); diff --git a/tests/unit/OptionsListUtilsTest.ts b/tests/unit/OptionsListUtilsTest.ts index d71b5522e11b..0e66993bc2cf 100644 --- a/tests/unit/OptionsListUtilsTest.ts +++ b/tests/unit/OptionsListUtilsTest.ts @@ -6,8 +6,7 @@ import CONST from '@src/CONST'; import * as OptionsListUtils from '@src/libs/OptionsListUtils'; import * as ReportUtils from '@src/libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetails, Policy, PolicyCategories, Report} from '@src/types/onyx'; -import type {PendingAction} from '@src/types/onyx/OnyxCommon'; +import type {PersonalDetails, Policy, Report} from '@src/types/onyx'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; type PersonalDetailsList = Record; @@ -638,1253 +637,6 @@ describe('OptionsListUtils', () => { expect(results.personalDetails.at(3)?.text).toBe('Invisible Woman'); }); - it('getFilteredOptions() for categories', () => { - const search = 'Food'; - const emptySearch = ''; - const wrongSearch = 'bla bla'; - const recentlyUsedCategories = ['Taxi', 'Restaurant']; - const selectedOptions: Array> = [ - { - name: 'Medical', - enabled: true, - }, - ]; - const smallCategoriesList: PolicyCategories = { - Taxi: { - enabled: false, - name: 'Taxi', - unencodedName: 'Taxi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - pendingAction: undefined, - }, - Restaurant: { - enabled: true, - name: 'Restaurant', - unencodedName: 'Restaurant', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - pendingAction: 'delete', - }, - Food: { - enabled: true, - name: 'Food', - unencodedName: 'Food', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - pendingAction: undefined, - }, - 'Food: Meat': { - enabled: true, - name: 'Food: Meat', - unencodedName: 'Food: Meat', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - pendingAction: undefined, - }, - }; - const smallResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: false, - data: [ - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Restaurant', - keyForList: 'Restaurant', - searchText: 'Restaurant', - tooltipText: 'Restaurant', - isDisabled: true, - isSelected: false, - pendingAction: 'delete', - }, - ], - indexOffset: 3, - }, - ]; - const smallSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: true, - indexOffset: 2, - data: [ - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food: Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Food: Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ], - }, - ]; - const smallWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: true, - indexOffset: 0, - data: [], - }, - ]; - const largeCategoriesList: PolicyCategories = { - Taxi: { - enabled: false, - name: 'Taxi', - unencodedName: 'Taxi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - Restaurant: { - enabled: true, - name: 'Restaurant', - unencodedName: 'Restaurant', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - Food: { - enabled: true, - name: 'Food', - unencodedName: 'Food', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Food: Meat': { - enabled: true, - name: 'Food: Meat', - unencodedName: 'Food: Meat', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Food: Milk': { - enabled: true, - name: 'Food: Milk', - unencodedName: 'Food: Milk', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Food: Vegetables': { - enabled: false, - name: 'Food: Vegetables', - unencodedName: 'Food: Vegetables', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Cars: Audi': { - enabled: true, - name: 'Cars: Audi', - unencodedName: 'Cars: Audi', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Cars: BMW': { - enabled: false, - name: 'Cars: BMW', - unencodedName: 'Cars: BMW', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Cars: Mercedes-Benz': { - enabled: true, - name: 'Cars: Mercedes-Benz', - unencodedName: 'Cars: Mercedes-Benz', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - Medical: { - enabled: false, - name: 'Medical', - unencodedName: 'Medical', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Travel: Meals': { - enabled: true, - name: 'Travel: Meals', - unencodedName: 'Travel: Meals', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Travel: Meals: Breakfast': { - enabled: true, - name: 'Travel: Meals: Breakfast', - unencodedName: 'Travel: Meals: Breakfast', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Travel: Meals: Dinner': { - enabled: false, - name: 'Travel: Meals: Dinner', - unencodedName: 'Travel: Meals: Dinner', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - 'Travel: Meals: Lunch': { - enabled: true, - name: 'Travel: Meals: Lunch', - unencodedName: 'Travel: Meals: Lunch', - areCommentsRequired: false, - 'GL Code': '', - externalID: '', - origin: '', - }, - }; - const largeResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: false, - indexOffset: 1, - data: [ - { - text: 'Medical', - keyForList: 'Medical', - searchText: 'Medical', - tooltipText: 'Medical', - isDisabled: true, - isSelected: true, - pendingAction: undefined, - }, - ], - }, - { - title: 'Recent', - shouldShow: true, - indexOffset: 1, - data: [ - { - text: 'Restaurant', - keyForList: 'Restaurant', - searchText: 'Restaurant', - tooltipText: 'Restaurant', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ], - }, - { - title: 'All', - shouldShow: true, - indexOffset: 11, - data: [ - { - text: 'Cars', - keyForList: 'Cars', - searchText: 'Cars', - tooltipText: 'Cars', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Audi', - keyForList: 'Cars: Audi', - searchText: 'Cars: Audi', - tooltipText: 'Audi', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Mercedes-Benz', - keyForList: 'Cars: Mercedes-Benz', - searchText: 'Cars: Mercedes-Benz', - tooltipText: 'Mercedes-Benz', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Milk', - keyForList: 'Food: Milk', - searchText: 'Food: Milk', - tooltipText: 'Milk', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Restaurant', - keyForList: 'Restaurant', - searchText: 'Restaurant', - tooltipText: 'Restaurant', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Travel', - keyForList: 'Travel', - searchText: 'Travel', - tooltipText: 'Travel', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Meals', - keyForList: 'Travel: Meals', - searchText: 'Travel: Meals', - tooltipText: 'Meals', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Breakfast', - keyForList: 'Travel: Meals: Breakfast', - searchText: 'Travel: Meals: Breakfast', - tooltipText: 'Breakfast', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Lunch', - keyForList: 'Travel: Meals: Lunch', - searchText: 'Travel: Meals: Lunch', - tooltipText: 'Lunch', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ], - }, - ]; - const largeSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: true, - indexOffset: 3, - data: [ - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food: Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Food: Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food: Milk', - keyForList: 'Food: Milk', - searchText: 'Food: Milk', - tooltipText: 'Food: Milk', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ], - }, - ]; - const largeWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: true, - indexOffset: 0, - data: [], - }, - ]; - const emptyCategoriesList = {}; - const emptySelectedResultList: OptionsListUtils.CategoryTreeSection[] = [ - { - title: '', - shouldShow: false, - indexOffset: 1, - data: [ - { - text: 'Medical', - keyForList: 'Medical', - searchText: 'Medical', - tooltipText: 'Medical', - isDisabled: true, - isSelected: true, - pendingAction: undefined, - }, - ], - }, - ]; - - const smallResult = OptionsListUtils.getFilteredOptions({ - reports: OPTIONS.reports, - personalDetails: OPTIONS.personalDetails, - searchValue: emptySearch, - includeP2P: false, - includeCategories: true, - categories: smallCategoriesList, - }); - expect(smallResult.categoryOptions).toStrictEqual(smallResultList); - - const smallSearchResult = OptionsListUtils.getFilteredOptions({searchValue: search, includeP2P: false, includeCategories: true, categories: smallCategoriesList}); - expect(smallSearchResult.categoryOptions).toStrictEqual(smallSearchResultList); - - const smallWrongSearchResult = OptionsListUtils.getFilteredOptions({searchValue: wrongSearch, includeP2P: false, includeCategories: true, categories: smallCategoriesList}); - expect(smallWrongSearchResult.categoryOptions).toStrictEqual(smallWrongSearchResultList); - - const largeResult = OptionsListUtils.getFilteredOptions({ - searchValue: emptySearch, - selectedOptions, - includeP2P: false, - includeCategories: true, - categories: largeCategoriesList, - recentlyUsedCategories, - }); - expect(largeResult.categoryOptions).toStrictEqual(largeResultList); - - const largeSearchResult = OptionsListUtils.getFilteredOptions({ - searchValue: search, - selectedOptions, - - includeP2P: false, - includeCategories: true, - categories: largeCategoriesList, - recentlyUsedCategories, - }); - expect(largeSearchResult.categoryOptions).toStrictEqual(largeSearchResultList); - - const largeWrongSearchResult = OptionsListUtils.getFilteredOptions({ - searchValue: wrongSearch, - selectedOptions, - includeP2P: false, - includeCategories: true, - categories: largeCategoriesList, - recentlyUsedCategories, - }); - expect(largeWrongSearchResult.categoryOptions).toStrictEqual(largeWrongSearchResultList); - - const emptyResult = OptionsListUtils.getFilteredOptions({searchValue: search, selectedOptions, includeP2P: false, includeCategories: true, categories: emptyCategoriesList}); - expect(emptyResult.categoryOptions).toStrictEqual(emptySelectedResultList); - }); - - it('getCategoryOptionTree()', () => { - const categories = { - Meals: { - enabled: true, - name: 'Meals', - }, - Restaurant: { - enabled: true, - name: 'Restaurant', - }, - Food: { - enabled: true, - name: 'Food', - }, - 'Food: Meat': { - enabled: true, - name: 'Food: Meat', - }, - 'Food: Milk': { - enabled: true, - name: 'Food: Milk', - }, - 'Cars: Audi': { - enabled: true, - name: 'Cars: Audi', - }, - 'Cars: Mercedes-Benz': { - enabled: true, - name: 'Cars: Mercedes-Benz', - }, - 'Travel: Meals': { - enabled: true, - name: 'Travel: Meals', - }, - 'Travel: Meals: Breakfast': { - enabled: true, - name: 'Travel: Meals: Breakfast', - }, - 'Travel: Meals: Lunch': { - enabled: true, - name: 'Travel: Meals: Lunch', - }, - Plain: { - enabled: true, - name: 'Plain', - }, - Audi: { - enabled: true, - name: 'Audi', - }, - Health: { - enabled: true, - name: 'Health', - }, - 'A: B: C': { - enabled: true, - name: 'A: B: C', - }, - 'A: B: C: D: E': { - enabled: true, - name: 'A: B: C: D: E', - }, - }; - const result = [ - { - text: 'Meals', - keyForList: 'Meals', - searchText: 'Meals', - tooltipText: 'Meals', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Restaurant', - keyForList: 'Restaurant', - searchText: 'Restaurant', - tooltipText: 'Restaurant', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Milk', - keyForList: 'Food: Milk', - searchText: 'Food: Milk', - tooltipText: 'Milk', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Cars', - keyForList: 'Cars', - searchText: 'Cars', - tooltipText: 'Cars', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Audi', - keyForList: 'Cars: Audi', - searchText: 'Cars: Audi', - tooltipText: 'Audi', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Mercedes-Benz', - keyForList: 'Cars: Mercedes-Benz', - searchText: 'Cars: Mercedes-Benz', - tooltipText: 'Mercedes-Benz', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Travel', - keyForList: 'Travel', - searchText: 'Travel', - tooltipText: 'Travel', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Meals', - keyForList: 'Travel: Meals', - searchText: 'Travel: Meals', - tooltipText: 'Meals', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Breakfast', - keyForList: 'Travel: Meals: Breakfast', - searchText: 'Travel: Meals: Breakfast', - tooltipText: 'Breakfast', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' Lunch', - keyForList: 'Travel: Meals: Lunch', - searchText: 'Travel: Meals: Lunch', - tooltipText: 'Lunch', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Plain', - keyForList: 'Plain', - searchText: 'Plain', - tooltipText: 'Plain', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Audi', - keyForList: 'Audi', - searchText: 'Audi', - tooltipText: 'Audi', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Health', - keyForList: 'Health', - searchText: 'Health', - tooltipText: 'Health', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'A', - keyForList: 'A', - searchText: 'A', - tooltipText: 'A', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' B', - keyForList: 'A: B', - searchText: 'A: B', - tooltipText: 'B', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' C', - keyForList: 'A: B: C', - searchText: 'A: B: C', - tooltipText: 'C', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' D', - keyForList: 'A: B: C: D', - searchText: 'A: B: C: D', - tooltipText: 'D', - isDisabled: true, - isSelected: false, - pendingAction: undefined, - }, - { - text: ' E', - keyForList: 'A: B: C: D: E', - searchText: 'A: B: C: D: E', - tooltipText: 'E', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ]; - const resultOneLine = [ - { - text: 'Meals', - keyForList: 'Meals', - searchText: 'Meals', - tooltipText: 'Meals', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Restaurant', - keyForList: 'Restaurant', - searchText: 'Restaurant', - tooltipText: 'Restaurant', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food', - keyForList: 'Food', - searchText: 'Food', - tooltipText: 'Food', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food: Meat', - keyForList: 'Food: Meat', - searchText: 'Food: Meat', - tooltipText: 'Food: Meat', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Food: Milk', - keyForList: 'Food: Milk', - searchText: 'Food: Milk', - tooltipText: 'Food: Milk', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Cars: Audi', - keyForList: 'Cars: Audi', - searchText: 'Cars: Audi', - tooltipText: 'Cars: Audi', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Cars: Mercedes-Benz', - keyForList: 'Cars: Mercedes-Benz', - searchText: 'Cars: Mercedes-Benz', - tooltipText: 'Cars: Mercedes-Benz', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Travel: Meals', - keyForList: 'Travel: Meals', - searchText: 'Travel: Meals', - tooltipText: 'Travel: Meals', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Travel: Meals: Breakfast', - keyForList: 'Travel: Meals: Breakfast', - searchText: 'Travel: Meals: Breakfast', - tooltipText: 'Travel: Meals: Breakfast', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Travel: Meals: Lunch', - keyForList: 'Travel: Meals: Lunch', - searchText: 'Travel: Meals: Lunch', - tooltipText: 'Travel: Meals: Lunch', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Plain', - keyForList: 'Plain', - searchText: 'Plain', - tooltipText: 'Plain', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Audi', - keyForList: 'Audi', - searchText: 'Audi', - tooltipText: 'Audi', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'Health', - keyForList: 'Health', - searchText: 'Health', - tooltipText: 'Health', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'A: B: C', - keyForList: 'A: B: C', - searchText: 'A: B: C', - tooltipText: 'A: B: C', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - { - text: 'A: B: C: D: E', - keyForList: 'A: B: C: D: E', - searchText: 'A: B: C: D: E', - tooltipText: 'A: B: C: D: E', - isDisabled: false, - isSelected: false, - pendingAction: undefined, - }, - ]; - - expect(OptionsListUtils.getCategoryOptionTree(categories)).toStrictEqual(result); - expect(OptionsListUtils.getCategoryOptionTree(categories, true)).toStrictEqual(resultOneLine); - }); - - it('sortCategories', () => { - const categoriesIncorrectOrdering = { - Taxi: { - name: 'Taxi', - enabled: false, - }, - 'Test1: Subtest2': { - name: 'Test1: Subtest2', - enabled: true, - }, - 'Test: Test1: Subtest4': { - name: 'Test: Test1: Subtest4', - enabled: true, - }, - Taxes: { - name: 'Taxes', - enabled: true, - }, - Test: { - name: 'Test', - enabled: true, - pendingAction: 'delete' as PendingAction, - }, - Test1: { - name: 'Test1', - enabled: true, - }, - 'Travel: Nested-Travel': { - name: 'Travel: Nested-Travel', - enabled: true, - }, - 'Test1: Subtest1': { - name: 'Test1: Subtest1', - enabled: true, - }, - 'Test: Test1': { - name: 'Test: Test1', - enabled: true, - }, - 'Test: Test1: Subtest1': { - name: 'Test: Test1: Subtest1', - enabled: true, - }, - 'Test: Test1: Subtest3': { - name: 'Test: Test1: Subtest3', - enabled: false, - }, - 'Test: Test1: Subtest2': { - name: 'Test: Test1: Subtest2', - enabled: true, - }, - 'Test: Test2': { - name: 'Test: Test2', - enabled: true, - }, - Travel: { - name: 'Travel', - enabled: true, - }, - Utilities: { - name: 'Utilities', - enabled: true, - }, - 'Test: Test3: Subtest1': { - name: 'Test: Test3: Subtest1', - enabled: true, - }, - 'Test1: Subtest3': { - name: 'Test1: Subtest3', - enabled: true, - }, - }; - const result = [ - { - name: 'Taxes', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Taxi', - enabled: false, - pendingAction: undefined, - }, - { - name: 'Test', - enabled: true, - pendingAction: 'delete', - }, - { - name: 'Test: Test1', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test: Test1: Subtest1', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test: Test1: Subtest2', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test: Test1: Subtest3', - enabled: false, - pendingAction: undefined, - }, - { - name: 'Test: Test1: Subtest4', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test: Test2', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test: Test3: Subtest1', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test1', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test1: Subtest1', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test1: Subtest2', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Test1: Subtest3', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Travel', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Travel: Nested-Travel', - enabled: true, - pendingAction: undefined, - }, - { - name: 'Utilities', - enabled: true, - pendingAction: undefined, - }, - ]; - const categoriesIncorrectOrdering2 = { - 'Cars: BMW': { - enabled: false, - name: 'Cars: BMW', - }, - Medical: { - enabled: false, - name: 'Medical', - }, - 'Travel: Meals: Lunch': { - enabled: true, - name: 'Travel: Meals: Lunch', - }, - 'Cars: Mercedes-Benz': { - enabled: true, - name: 'Cars: Mercedes-Benz', - }, - Food: { - enabled: true, - name: 'Food', - }, - 'Food: Meat': { - enabled: true, - name: 'Food: Meat', - }, - 'Travel: Meals: Dinner': { - enabled: false, - name: 'Travel: Meals: Dinner', - }, - 'Food: Vegetables': { - enabled: false, - name: 'Food: Vegetables', - }, - Restaurant: { - enabled: true, - name: 'Restaurant', - }, - Taxi: { - enabled: false, - name: 'Taxi', - }, - 'Food: Milk': { - enabled: true, - name: 'Food: Milk', - }, - 'Travel: Meals': { - enabled: true, - name: 'Travel: Meals', - }, - 'Travel: Meals: Breakfast': { - enabled: true, - name: 'Travel: Meals: Breakfast', - }, - 'Cars: Audi': { - enabled: true, - name: 'Cars: Audi', - }, - }; - const result2 = [ - { - enabled: true, - name: 'Cars: Audi', - pendingAction: undefined, - }, - { - enabled: false, - name: 'Cars: BMW', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Cars: Mercedes-Benz', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Food', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Food: Meat', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Food: Milk', - pendingAction: undefined, - }, - { - enabled: false, - name: 'Food: Vegetables', - pendingAction: undefined, - }, - { - enabled: false, - name: 'Medical', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Restaurant', - pendingAction: undefined, - }, - { - enabled: false, - name: 'Taxi', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Travel: Meals', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Travel: Meals: Breakfast', - pendingAction: undefined, - }, - { - enabled: false, - name: 'Travel: Meals: Dinner', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Travel: Meals: Lunch', - pendingAction: undefined, - }, - ]; - const categoriesIncorrectOrdering3 = { - 'Movies: Mr. Nobody': { - enabled: true, - name: 'Movies: Mr. Nobody', - }, - Movies: { - enabled: true, - name: 'Movies', - }, - 'House, M.D.': { - enabled: true, - name: 'House, M.D.', - }, - 'Dr. House': { - enabled: true, - name: 'Dr. House', - }, - 'Many.dots.on.the.way.': { - enabled: true, - name: 'Many.dots.on.the.way.', - }, - 'More.Many.dots.on.the.way.': { - enabled: false, - name: 'More.Many.dots.on.the.way.', - }, - }; - const result3 = [ - { - enabled: true, - name: 'Dr. House', - pendingAction: undefined, - }, - { - enabled: true, - name: 'House, M.D.', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Many.dots.on.the.way.', - pendingAction: undefined, - }, - { - enabled: false, - name: 'More.Many.dots.on.the.way.', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Movies', - pendingAction: undefined, - }, - { - enabled: true, - name: 'Movies: Mr. Nobody', - pendingAction: undefined, - }, - ]; - - expect(OptionsListUtils.sortCategories(categoriesIncorrectOrdering)).toStrictEqual(result); - expect(OptionsListUtils.sortCategories(categoriesIncorrectOrdering2)).toStrictEqual(result2); - expect(OptionsListUtils.sortCategories(categoriesIncorrectOrdering3)).toStrictEqual(result3); - }); - it('formatMemberForList()', () => { const formattedMembers = Object.values(PERSONAL_DETAILS).map((personalDetail) => OptionsListUtils.formatMemberForList(personalDetail)); diff --git a/tests/unit/TagsOptionsListUtilsTest.ts b/tests/unit/TagsOptionsListUtilsTest.ts index f3051c63be6a..57ebebc218fd 100644 --- a/tests/unit/TagsOptionsListUtilsTest.ts +++ b/tests/unit/TagsOptionsListUtilsTest.ts @@ -39,7 +39,7 @@ describe('TagsOptionsListUtils', () => { pendingAction: 'delete', }, }; - const smallResultList: OptionsListUtils.CategorySection[] = [ + const smallResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: false, @@ -75,7 +75,7 @@ describe('TagsOptionsListUtils', () => { ], }, ]; - const smallSearchResultList: OptionsListUtils.CategorySection[] = [ + const smallSearchResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: true, @@ -92,7 +92,7 @@ describe('TagsOptionsListUtils', () => { ], }, ]; - const smallWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const smallWrongSearchResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: true, @@ -157,7 +157,7 @@ describe('TagsOptionsListUtils', () => { accountID: undefined, }, }; - const largeResultList: OptionsListUtils.CategorySection[] = [ + const largeResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: true, @@ -259,7 +259,7 @@ describe('TagsOptionsListUtils', () => { ], }, ]; - const largeSearchResultList: OptionsListUtils.CategorySection[] = [ + const largeSearchResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: true, @@ -285,7 +285,7 @@ describe('TagsOptionsListUtils', () => { ], }, ]; - const largeWrongSearchResultList: OptionsListUtils.CategoryTreeSection[] = [ + const largeWrongSearchResultList: OptionsListUtils.Section[] = [ { title: '', shouldShow: true, diff --git a/tests/unit/TaxOptionsListUtilsTest.ts b/tests/unit/TaxOptionsListUtilsTest.ts index 255cedd7c7d5..f0e1eac4826a 100644 --- a/tests/unit/TaxOptionsListUtilsTest.ts +++ b/tests/unit/TaxOptionsListUtilsTest.ts @@ -1,4 +1,4 @@ -import type {CategorySection} from '@libs/OptionsListUtils'; +import type {Section} from '@libs/OptionsListUtils'; import * as TaxOptionsListUtils from '@libs/TaxOptionsListUtils'; import type {Policy, TaxRatesWithDefault, Transaction} from '@src/types/onyx'; @@ -45,7 +45,7 @@ describe('TaxOptionsListUtils', () => { taxCode: 'CODE1', } as Transaction; - const resultList: CategorySection[] = [ + const resultList: Section[] = [ { data: [ { @@ -84,7 +84,7 @@ describe('TaxOptionsListUtils', () => { }, ]; - const searchResultList: CategorySection[] = [ + const searchResultList: Section[] = [ { data: [ { @@ -103,7 +103,7 @@ describe('TaxOptionsListUtils', () => { }, ]; - const wrongSearchResultList: CategorySection[] = [ + const wrongSearchResultList: Section[] = [ { data: [], shouldShow: true,