Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(utils): add getSelectedTreeOptionFromTreeOptionValue() #1117

Merged
merged 5 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions .commitlintrc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"always",
"Infinity"
],
"header-max-length": [
2,
"always",
120
],
"type-enum": [
2,
"always",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
18 changes: 9 additions & 9 deletions src/utils/__tests__/getSelectedOptionFromOptionValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <selectedOptionValue> 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)
Expand Down
60 changes: 60 additions & 0 deletions src/utils/__tests__/getSelectedOptionFromOptionValueInTree.test.ts
Original file line number Diff line number Diff line change
@@ -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 <selectedOptionValue> 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()
})
})
2 changes: 1 addition & 1 deletion src/utils/getSelectedOptionFromOptionValue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<OptionValue extends OptionValueType = string>(
allOptions: Array<Option<OptionValue>>,
Expand Down
28 changes: 28 additions & 0 deletions src/utils/getSelectedOptionFromOptionValueInTree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getSelectedOptionFromOptionValue } from './getSelectedOptionFromOptionValue'

import type { Option, OptionValueType, TreeOption } from '@types_/definitions'

function getLeafOptionsFromTreeOptions<OptionValue extends OptionValueType>(
treeOptions: Array<TreeOption<OptionValue>>
): Array<Option<OptionValue>> {
return treeOptions.reduce<Array<Option<OptionValue>>>((leafOptions, option) => {
if ('value' in option) {
return [...leafOptions, option as Option<OptionValue>]
}

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<OptionValue extends OptionValueType = string>(
allOptions: Array<TreeOption<OptionValue>>,
selectedOptionValue: OptionValue | undefined,
optionValueKey?: keyof OptionValue | undefined
): Option<OptionValue> | undefined {
const allLeafOptions = getLeafOptionsFromTreeOptions(allOptions)

return getSelectedOptionFromOptionValue(allLeafOptions, selectedOptionValue, optionValueKey)
}
Loading