diff --git a/.coderabbit.yaml b/.coderabbit.yaml index cfa2ef550..49fe0f1f0 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -4,23 +4,25 @@ chat: auto_reply: true reviews: - collapse_walkthrough: false - high_level_summary: true - poem: false - request_changes_workflow: false - review_status: false - path_filters: [] auto_review: enabled: true drafts: true base_branches: - 'main' - labels: - - coderabbit + collapse_walkthrough: false + high_level_summary: false + path_filters: + - '!CHANGELOG.md' + - '!**/package-lock.json' + - '!**/yarn.lock' path_instructions: - - path: '**/*.[jt]sx?' + - path: '**/*' instructions: | - Keep your comments short. - Check for typos and bad English naming. + - Proofread comments, documentation and code. - Avoid general concepts and focus on the code. - - Suggest code change with concrete code. + - Suggest code changes with concrete code. + poem: false + request_changes_workflow: false + review_status: false diff --git a/.commitlintrc b/.commitlintrc index 74079f93c..871105ae5 100644 --- a/.commitlintrc +++ b/.commitlintrc @@ -25,6 +25,11 @@ "always", "Infinity" ], + "header-max-length": [ + 2, + "always", + 120 + ], "type-enum": [ 2, "always", diff --git a/src/index.ts b/src/index.ts index a5995b193..d5eb9f1da 100644 --- a/src/index.ts +++ b/src/index.ts @@ -148,6 +148,7 @@ export { getOptionsFromIdAndName } from './utils/getOptionsFromIdAndName' export { getOptionsFromLabelledEnum } from './utils/getOptionsFromLabelledEnum' export { getPseudoRandomString } from './utils/getPseudoRandomString' export { getSelectedOptionFromOptionValue } from './utils/getSelectedOptionFromOptionValue' +export { getSelectedOptionFromOptionValueInTree } from './utils/getSelectedOptionFromOptionValueInTree' export { getUtcizedDayjs } from './utils/getUtcizedDayjs' export { humanizePastDate } from './utils/humanizePastDate' export { isArray } from './utils/isArray' diff --git a/src/utils/__tests__/getSelectedOptionFromOptionValue.test.ts b/src/utils/__tests__/getSelectedOptionFromOptionValue.test.ts index f972caec0..88c0a81ce 100644 --- a/src/utils/__tests__/getSelectedOptionFromOptionValue.test.ts +++ b/src/utils/__tests__/getSelectedOptionFromOptionValue.test.ts @@ -20,44 +20,44 @@ describe('utils/getSelectedOptionFromOptionValue()', () => { it('should return the correct option for boolean options', () => { const allOptions = FAKE_BOOLEAN_OPTIONS - const selectedOptionValue = FAKE_BOOLEAN_OPTIONS[1]!.value + const selectedOptionValue = false const result = getSelectedOptionFromOptionValue(allOptions, selectedOptionValue) - expect(result).toBe(FAKE_BOOLEAN_OPTIONS[1]) + expect(result).toEqual({ label: 'No', value: false }) }) it('should return the correct option for number options', () => { const allOptions = FAKE_NUMBER_OPTIONS - const selectedOptionValue = FAKE_NUMBER_OPTIONS[1]!.value + const selectedOptionValue = 2 const result = getSelectedOptionFromOptionValue(allOptions, selectedOptionValue) - expect(result).toBe(FAKE_NUMBER_OPTIONS[1]) + expect(result).toEqual({ label: 'Second Option', value: 2 }) }) it('should return the correct option for a object options', () => { const allOptions = FAKE_OBJECT_OPTIONS - const selectedOptionValue = FAKE_OBJECT_OPTIONS[1]!.value + const selectedOptionValue = { id: 2, name: 'Second Option Name' } const optionValueKey = 'id' const result = getSelectedOptionFromOptionValue(allOptions, selectedOptionValue, optionValueKey) - expect(result).toBe(FAKE_OBJECT_OPTIONS[1]) + expect(result).toEqual({ label: 'Second Option', value: { id: 2, name: 'Second Option Name' } }) }) it('should return the correct option for string options', () => { const allOptions = FAKE_STRING_OPTIONS - const selectedOptionValue = FAKE_STRING_OPTIONS[1]!.value + const selectedOptionValue = 'SECOND_OPTION' const result = getSelectedOptionFromOptionValue(allOptions, selectedOptionValue) - expect(result).toBe(FAKE_STRING_OPTIONS[1]) + expect(result).toEqual({ label: 'Second Option', value: 'SECOND_OPTION' }) }) it('should throw an error with object option when does NOT exist', () => { const allOptions = FAKE_OBJECT_OPTIONS - const selectedOptionValue = FAKE_OBJECT_OPTIONS[1]!.value + const selectedOptionValue = { id: 2, name: 'Second Option Name' } const optionValueKey = 'non-existent' const call = () => getSelectedOptionFromOptionValue(allOptions, selectedOptionValue, optionValueKey as any) diff --git a/src/utils/__tests__/getSelectedOptionFromOptionValueInTree.test.ts b/src/utils/__tests__/getSelectedOptionFromOptionValueInTree.test.ts new file mode 100644 index 000000000..b6d3735e3 --- /dev/null +++ b/src/utils/__tests__/getSelectedOptionFromOptionValueInTree.test.ts @@ -0,0 +1,60 @@ +import { describe, expect, it } from '@jest/globals' + +// Assuming these mocks are structured similarly to the ones used previously, +// adjusted for tree options +import { LOREM_IPSUM } from '../../../__mocks__/fake_text' +import { + FAKE_NUMBER_TREE_OPTIONS, + FAKE_OBJECT_TREE_OPTIONS, + FAKE_STRING_TREE_OPTIONS +} from '../../../__mocks__/fake_tree_options' +import { getSelectedOptionFromOptionValueInTree } from '../getSelectedOptionFromOptionValueInTree' + +describe('utils/getSelectedOptionFromOptionValueInTree()', () => { + it('should return undefined for undefined selectedOptionValue', () => { + const allOptions = FAKE_STRING_TREE_OPTIONS + const selectedOptionValue = undefined + + const result = getSelectedOptionFromOptionValueInTree(allOptions, selectedOptionValue) + + expect(result).toBeUndefined() + }) + + it('should return the correct tree option for number values', () => { + const allOptions = FAKE_NUMBER_TREE_OPTIONS + const selectedOptionValue = 4 + + const result = getSelectedOptionFromOptionValueInTree(allOptions, selectedOptionValue) + + expect(result).toEqual({ label: LOREM_IPSUM, value: 4 }) + }) + + it('should return the correct tree option for object values', () => { + const allOptions = FAKE_OBJECT_TREE_OPTIONS + const selectedOptionValue = { id: 4, name: 'Chatty Option Name' } + const optionValueKey = 'id' + + const result = getSelectedOptionFromOptionValueInTree(allOptions, selectedOptionValue, optionValueKey) + + expect(result).toEqual({ label: LOREM_IPSUM, value: { id: 4, name: 'Chatty Option Name' } }) + }) + + it('should return the correct tree option for string values', () => { + const allOptions = FAKE_STRING_TREE_OPTIONS + const selectedOptionValue = 'CHATTY_OPTION' + + const result = getSelectedOptionFromOptionValueInTree(allOptions, selectedOptionValue) + + expect(result).toEqual({ label: LOREM_IPSUM, value: 'CHATTY_OPTION' }) + }) + + it('should throw an error with object option when does NOT exist', () => { + const allOptions = FAKE_OBJECT_TREE_OPTIONS + const selectedOptionValue = { id: 4, name: 'Chatty Option Name' } + const optionValueKey = 'non-existent' + + const call = () => getSelectedOptionFromOptionValueInTree(allOptions, selectedOptionValue, optionValueKey as any) + + expect(call).toThrow() + }) +}) diff --git a/src/utils/getSelectedOptionFromOptionValue.ts b/src/utils/getSelectedOptionFromOptionValue.ts index 943f18146..69333782a 100644 --- a/src/utils/getSelectedOptionFromOptionValue.ts +++ b/src/utils/getSelectedOptionFromOptionValue.ts @@ -5,7 +5,7 @@ import { getOptionValueKeyValueFromOptionValue } from './getOptionValueKeyValueF import type { Option, OptionValueType } from '@types_/definitions' /** - * Get the selected option from the option value. + * Get the matching option from an option value in an option list. */ export function getSelectedOptionFromOptionValue( allOptions: Array>, diff --git a/src/utils/getSelectedOptionFromOptionValueInTree.ts b/src/utils/getSelectedOptionFromOptionValueInTree.ts new file mode 100644 index 000000000..31c64787f --- /dev/null +++ b/src/utils/getSelectedOptionFromOptionValueInTree.ts @@ -0,0 +1,28 @@ +import { getSelectedOptionFromOptionValue } from './getSelectedOptionFromOptionValue' + +import type { Option, OptionValueType, TreeOption } from '@types_/definitions' + +function getLeafOptionsFromTreeOptions( + treeOptions: Array> +): Array> { + return treeOptions.reduce>>((leafOptions, option) => { + if ('value' in option) { + return [...leafOptions, option as Option] + } + + return [...leafOptions, ...getLeafOptionsFromTreeOptions(option.children)] + }, []) +} + +/** + * Get the matching tree option deepest child from a tree option value in a tree option list. + */ +export function getSelectedOptionFromOptionValueInTree( + allOptions: Array>, + selectedOptionValue: OptionValue | undefined, + optionValueKey?: keyof OptionValue | undefined +): Option | undefined { + const allLeafOptions = getLeafOptionsFromTreeOptions(allOptions) + + return getSelectedOptionFromOptionValue(allLeafOptions, selectedOptionValue, optionValueKey) +}