Skip to content

Commit

Permalink
fix: tests and types
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Streicher committed Mar 15, 2023
1 parent 90c5965 commit b816090
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 33 deletions.
33 changes: 16 additions & 17 deletions src/test/conversion-custom.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {applyDRFInterceptor, convertFilterSetConfig} from '../middleware'
import {convertFilterSetConfig} from '../middleware'
import type {FilterSetConfig} from '../types'

interface Data {
Expand All @@ -17,15 +17,16 @@ interface CustomObject {
}

interface CustomFilter {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
custom1: any[]
custom2: CustomObject
custom2: number
custom3: CustomObject

}

interface CustomFilterSetMapping {
number: 'exact' | 'lte' | 'lt' | 'gt' | 'custom1'
text: 'lt' | 'exact' | 'custom2'
text: 'lt' | 'exact' | 'custom2' | 'custom3'
}

test('it should accept a KeyConfig ', () => {
Expand All @@ -39,46 +40,44 @@ test('it should accept a KeyConfig ', () => {
})

test('it should accept a CustomKeyConfig ', () => {
const customObject: CustomObject = {attribute: ''}
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
number: {custom1: ['']},
text: {custom2: customObject},
text: {custom2: 123},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({number__custom1: [''], text__custom2: customObject})
expect(converted).toEqual({number__custom1: [''], text__custom2: 123})
})

test('it should accept a CustomKeyConfig and standard DRF filters', () => {
const customObject = {attribute: ''}
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
number: {custom1: [''], exact: 123},
text: {custom2: customObject, lt: 'foo'},
text: {custom2: 123, lt: 'foo'},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({number__custom1: [''], number__exact: 123, text__custom2: customObject, text__lt: 'foo'})
expect(converted).toEqual({number__custom1: [''], number__exact: 123, text__custom2: 123, text__lt: 'foo'})
})

test('it should convert the filter defined with a custom filter handler', () => {
const customObject = {attribute: ''}
const obj = {attribute: ''}
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
number: {custom1: [''], exact: 123},
text: {custom2: customObject, lt: 'foo'},
text: {custom3: obj, lt: 'foo'},
}
const converted = convertFilterSetConfig(simpleConfig, {
custom1: (key, data) => {
custom1: (_key, _data) => {
return [{key: 'handler', value: 987}]
},
custom2: (key, data) => {
custom3: (key, data) => {
const list = []
if (data && 'attribute' in data)
list.push({key: 'custom', value: data.attribute})
if (data && data[key] && 'attribute' in data[key])
list.push({key: 'custom', value: data[key]})

return list
},
})
// eslint-disable-next-line camelcase
expect(converted).toEqual({number__handler: 987, number__exact: 123, text__custom: '', text__lt: 'foo'})
expect(converted).toEqual({number__handler: 987, number__exact: 123, text__custom: obj, text__lt: 'foo'})
})

88 changes: 78 additions & 10 deletions src/test/conversion-object-ref.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('it should convert objects with value filters', () => {
expect(converted).toEqual({data__number: 123, data__noNumber: date})
})

test('it should convert complex objects with filters', () => {
test('it should convert objects with filters', () => {
const simpleConfig: FilterSetConfig<Data> = {
data: {
number: {lt: 123},
Expand All @@ -48,29 +48,97 @@ test('it should convert complex objects with filters', () => {
expect(converted).toEqual({data__number__lt: 123})
})

interface CircleMapping {
// data: FilterSetMapping
dummy: 'lt'
}

interface NumberDataMapping {
number: 'lt' | 'gt' | 'custom1'
circle: CircleMapping
}

interface FilterSetMapping {
data: 'lt' | 'gt' | 'custom1'
data: NumberDataMapping
text: 'lt' | 'exact'
}

test('it should convert objects with standard filters and a Mapping', () => {
const numberData = {number: 123}
test('it should convert objects with a custom filter', () => {
const simpleConfig: FilterSetConfig<Data, FilterSetMapping> = {
data: {
number: {custom1: 123},
number: {
custom1: 123,
},
},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({data__number__lte: numberData})
expect(converted).toEqual({data__number__custom1: 123})
})

test('it should convert complex objects with standard filters', () => {
const simpleConfig: FilterSetConfig<Data> = {
data: {number: {lt: 123}},
interface A {
b?: {
c: {
text: string
}
}
}

interface AMapping {
b: {
c: {
text: 'exact'
}
}

}

test('it should convert objects with nested objects', () => {
const simpleConfig: FilterSetConfig<A> = {
b: {
c: {
text: {exact: 'foo'},
},
},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({b__c__text__exact: 'foo'})
})

interface ALoop {
b?: {
c?: {
a?: ALoop
}
}
attributeA?: number
}

interface ALoopMapping {
b: {
c: {
a: AMapping
}
}
attributeA: 'lt'

}

test('it should convert objects with looping objects', () => {
const simpleConfig: FilterSetConfig<ALoop, ALoopMapping> = {
b: {
c: {
a: {
attributeA: {
lt: 123,
},
},
},
},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({data__number__lt: 123, text: 'string'})
expect(converted).toEqual({b__c__a__attributeA__lt: 123})
})

15 changes: 14 additions & 1 deletion src/test/type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('Error when attribute has the wrong type', () => {
text: {value: 123},
}
const converted = convertFilterSetConfig(simpleConfig)
expect(converted).toEqual({text: 'string'})
expect(converted).toEqual({text: 123})
})

interface FilterSetMapping {
Expand All @@ -59,6 +59,7 @@ test('error when filter key is disallowed in mapping', () => {
})

interface CustomFilter {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
custom1: any[]
custom2: number
}
Expand Down Expand Up @@ -91,3 +92,15 @@ test('error when custom has the wrong type', () => {
// eslint-disable-next-line camelcase
expect(converted).toEqual({text__custom2: ''})
})

test('error when custom has the wrong type', () => {
const simpleConfig: FilterSetConfig<Data, FilterSetMappingCustom, CustomFilter> = {
text: {
// @ts-expect-error custom filter has wrong type
custom2: '',
},
}
const converted = convertFilterSetConfig(simpleConfig)
// eslint-disable-next-line camelcase
expect(converted).toEqual({text__custom2: ''})
})
17 changes: 12 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@ export interface FilterSetRangeGTE<T> extends FilterSetAffix<T> {
type FilterSet<T> = FilterSetRange<T> | FilterSetExact<T> | FilterSetAffix<T> | FilterSetIn<T>

// Config to exclude certain filters and enable custom filters
export type FSKeyConfig<D> = Partial<Record<keyof D, string>>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type FSKeyConfig<D> = Partial<Record<keyof D, any>>

export type CustomKeyConfig = {[key: string]: unknown}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type CustomKeyConfig = Record<any, any>
& {
[key in keyof FilterSet<unknown>]?: never
}
Expand Down Expand Up @@ -108,6 +110,7 @@ type CheckConfigKeys<D, K extends FSKeyConfig<D>, key extends keyof D, C extends
)
: FilterSet<D[key]> // no config for the key so we take the default combinations

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type FilterSetConfig<D = Record<any, any>, K extends FSKeyConfig<D> | null = null, C extends CustomKeyConfig | null = null> = {
[key in keyof D]:
{value: D[key]} // no filters apply
Expand All @@ -116,8 +119,11 @@ export type FilterSetConfig<D = Record<any, any>, K extends FSKeyConfig<D> | nul
FilterSet<D[key]> // no config so we take the default combinations for each key
: CheckConfigKeys<D, Exclude<K, null>, key, C> // check if key is inside the config
) | (
D[key] extends Record<any, any> ? // check if the type of the key is a Record, so we add extended references
FilterSetConfig<D[key]>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
D[key] extends (Record<any, any> | undefined) ? // check if the type of the key is a Record, so we add extended references
(key extends keyof K ?
FilterSetConfig<D[key], K[key]>
: FilterSetConfig<D[key]>)
: never // no types added otherwise
)
}
Expand All @@ -134,7 +140,8 @@ export interface Filter {
* @param key: the defined key
* @param data: the enclosing data containing the data of the key as well as other data on the same hierarchy
*/
export type FilterHandler = (key: string, data: unknown) => Array<Filter>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type FilterHandler = (key: string, data: any) => Array<Filter>

/**
*
Expand Down

0 comments on commit b816090

Please sign in to comment.