Skip to content

Commit b816090

Browse files
author
Tim Streicher
committed
fix: tests and types
1 parent 90c5965 commit b816090

File tree

4 files changed

+120
-33
lines changed

4 files changed

+120
-33
lines changed

src/test/conversion-custom.test.ts

+16-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {applyDRFInterceptor, convertFilterSetConfig} from '../middleware'
1+
import {convertFilterSetConfig} from '../middleware'
22
import type {FilterSetConfig} from '../types'
33

44
interface Data {
@@ -17,15 +17,16 @@ interface CustomObject {
1717
}
1818

1919
interface CustomFilter {
20-
20+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2121
custom1: any[]
22-
custom2: CustomObject
22+
custom2: number
23+
custom3: CustomObject
2324

2425
}
2526

2627
interface CustomFilterSetMapping {
2728
number: 'exact' | 'lte' | 'lt' | 'gt' | 'custom1'
28-
text: 'lt' | 'exact' | 'custom2'
29+
text: 'lt' | 'exact' | 'custom2' | 'custom3'
2930
}
3031

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

4142
test('it should accept a CustomKeyConfig ', () => {
42-
const customObject: CustomObject = {attribute: ''}
4343
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
4444
number: {custom1: ['']},
45-
text: {custom2: customObject},
45+
text: {custom2: 123},
4646
}
4747
const converted = convertFilterSetConfig(simpleConfig)
4848
// eslint-disable-next-line camelcase
49-
expect(converted).toEqual({number__custom1: [''], text__custom2: customObject})
49+
expect(converted).toEqual({number__custom1: [''], text__custom2: 123})
5050
})
5151

5252
test('it should accept a CustomKeyConfig and standard DRF filters', () => {
53-
const customObject = {attribute: ''}
5453
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
5554
number: {custom1: [''], exact: 123},
56-
text: {custom2: customObject, lt: 'foo'},
55+
text: {custom2: 123, lt: 'foo'},
5756
}
5857
const converted = convertFilterSetConfig(simpleConfig)
5958
// eslint-disable-next-line camelcase
60-
expect(converted).toEqual({number__custom1: [''], number__exact: 123, text__custom2: customObject, text__lt: 'foo'})
59+
expect(converted).toEqual({number__custom1: [''], number__exact: 123, text__custom2: 123, text__lt: 'foo'})
6160
})
6261

6362
test('it should convert the filter defined with a custom filter handler', () => {
64-
const customObject = {attribute: ''}
63+
const obj = {attribute: ''}
6564
const simpleConfig: FilterSetConfig<Data, CustomFilterSetMapping, CustomFilter> = {
6665
number: {custom1: [''], exact: 123},
67-
text: {custom2: customObject, lt: 'foo'},
66+
text: {custom3: obj, lt: 'foo'},
6867
}
6968
const converted = convertFilterSetConfig(simpleConfig, {
70-
custom1: (key, data) => {
69+
custom1: (_key, _data) => {
7170
return [{key: 'handler', value: 987}]
7271
},
73-
custom2: (key, data) => {
72+
custom3: (key, data) => {
7473
const list = []
75-
if (data && 'attribute' in data)
76-
list.push({key: 'custom', value: data.attribute})
74+
if (data && data[key] && 'attribute' in data[key])
75+
list.push({key: 'custom', value: data[key]})
7776

7877
return list
7978
},
8079
})
8180
// eslint-disable-next-line camelcase
82-
expect(converted).toEqual({number__handler: 987, number__exact: 123, text__custom: '', text__lt: 'foo'})
81+
expect(converted).toEqual({number__handler: 987, number__exact: 123, text__custom: obj, text__lt: 'foo'})
8382
})
8483

src/test/conversion-object-ref.test.ts

+78-10
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ test('it should convert objects with value filters', () => {
3737
expect(converted).toEqual({data__number: 123, data__noNumber: date})
3838
})
3939

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

51+
interface CircleMapping {
52+
// data: FilterSetMapping
53+
dummy: 'lt'
54+
}
55+
56+
interface NumberDataMapping {
57+
number: 'lt' | 'gt' | 'custom1'
58+
circle: CircleMapping
59+
}
60+
5161
interface FilterSetMapping {
52-
data: 'lt' | 'gt' | 'custom1'
62+
data: NumberDataMapping
5363
text: 'lt' | 'exact'
5464
}
5565

56-
test('it should convert objects with standard filters and a Mapping', () => {
57-
const numberData = {number: 123}
66+
test('it should convert objects with a custom filter', () => {
5867
const simpleConfig: FilterSetConfig<Data, FilterSetMapping> = {
5968
data: {
60-
number: {custom1: 123},
69+
number: {
70+
custom1: 123,
71+
},
6172
},
6273
}
6374
const converted = convertFilterSetConfig(simpleConfig)
6475
// eslint-disable-next-line camelcase
65-
expect(converted).toEqual({data__number__lte: numberData})
76+
expect(converted).toEqual({data__number__custom1: 123})
6677
})
6778

68-
test('it should convert complex objects with standard filters', () => {
69-
const simpleConfig: FilterSetConfig<Data> = {
70-
data: {number: {lt: 123}},
79+
interface A {
80+
b?: {
81+
c: {
82+
text: string
83+
}
84+
}
85+
}
86+
87+
interface AMapping {
88+
b: {
89+
c: {
90+
text: 'exact'
91+
}
92+
}
93+
94+
}
95+
96+
test('it should convert objects with nested objects', () => {
97+
const simpleConfig: FilterSetConfig<A> = {
98+
b: {
99+
c: {
100+
text: {exact: 'foo'},
101+
},
102+
},
103+
}
104+
const converted = convertFilterSetConfig(simpleConfig)
105+
// eslint-disable-next-line camelcase
106+
expect(converted).toEqual({b__c__text__exact: 'foo'})
107+
})
108+
109+
interface ALoop {
110+
b?: {
111+
c?: {
112+
a?: ALoop
113+
}
114+
}
115+
attributeA?: number
116+
}
117+
118+
interface ALoopMapping {
119+
b: {
120+
c: {
121+
a: AMapping
122+
}
123+
}
124+
attributeA: 'lt'
125+
126+
}
127+
128+
test('it should convert objects with looping objects', () => {
129+
const simpleConfig: FilterSetConfig<ALoop, ALoopMapping> = {
130+
b: {
131+
c: {
132+
a: {
133+
attributeA: {
134+
lt: 123,
135+
},
136+
},
137+
},
138+
},
71139
}
72140
const converted = convertFilterSetConfig(simpleConfig)
73141
// eslint-disable-next-line camelcase
74-
expect(converted).toEqual({data__number__lt: 123, text: 'string'})
142+
expect(converted).toEqual({b__c__a__attributeA__lt: 123})
75143
})
76144

src/test/type.test.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ test('Error when attribute has the wrong type', () => {
3737
text: {value: 123},
3838
}
3939
const converted = convertFilterSetConfig(simpleConfig)
40-
expect(converted).toEqual({text: 'string'})
40+
expect(converted).toEqual({text: 123})
4141
})
4242

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

6161
interface CustomFilter {
62+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6263
custom1: any[]
6364
custom2: number
6465
}
@@ -91,3 +92,15 @@ test('error when custom has the wrong type', () => {
9192
// eslint-disable-next-line camelcase
9293
expect(converted).toEqual({text__custom2: ''})
9394
})
95+
96+
test('error when custom has the wrong type', () => {
97+
const simpleConfig: FilterSetConfig<Data, FilterSetMappingCustom, CustomFilter> = {
98+
text: {
99+
// @ts-expect-error custom filter has wrong type
100+
custom2: '',
101+
},
102+
}
103+
const converted = convertFilterSetConfig(simpleConfig)
104+
// eslint-disable-next-line camelcase
105+
expect(converted).toEqual({text__custom2: ''})
106+
})

src/types.ts

+12-5
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,11 @@ export interface FilterSetRangeGTE<T> extends FilterSetAffix<T> {
6969
type FilterSet<T> = FilterSetRange<T> | FilterSetExact<T> | FilterSetAffix<T> | FilterSetIn<T>
7070

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

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

113+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
111114
export type FilterSetConfig<D = Record<any, any>, K extends FSKeyConfig<D> | null = null, C extends CustomKeyConfig | null = null> = {
112115
[key in keyof D]:
113116
{value: D[key]} // no filters apply
@@ -116,8 +119,11 @@ export type FilterSetConfig<D = Record<any, any>, K extends FSKeyConfig<D> | nul
116119
FilterSet<D[key]> // no config so we take the default combinations for each key
117120
: CheckConfigKeys<D, Exclude<K, null>, key, C> // check if key is inside the config
118121
) | (
119-
D[key] extends Record<any, any> ? // check if the type of the key is a Record, so we add extended references
120-
FilterSetConfig<D[key]>
122+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
123+
D[key] extends (Record<any, any> | undefined) ? // check if the type of the key is a Record, so we add extended references
124+
(key extends keyof K ?
125+
FilterSetConfig<D[key], K[key]>
126+
: FilterSetConfig<D[key]>)
121127
: never // no types added otherwise
122128
)
123129
}
@@ -134,7 +140,8 @@ export interface Filter {
134140
* @param key: the defined key
135141
* @param data: the enclosing data containing the data of the key as well as other data on the same hierarchy
136142
*/
137-
export type FilterHandler = (key: string, data: unknown) => Array<Filter>
143+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
144+
export type FilterHandler = (key: string, data: any) => Array<Filter>
138145

139146
/**
140147
*

0 commit comments

Comments
 (0)