Skip to content

Commit 19a0002

Browse files
committed
test(unstable): add async-validation mutators tests
1 parent 4213005 commit 19a0002

File tree

5 files changed

+318
-8
lines changed

5 files changed

+318
-8
lines changed

src/lib/unstable/__tests__/helpers.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type {Tools} from 'final-form';
2+
13
import {JsonSchemaType, SchemaRendererMode} from '../core/constants';
24
import type {
35
IndependentView,
@@ -194,6 +196,9 @@ export function createMockSchema<T extends JsonSchema>(
194196
} as T;
195197
}
196198

199+
export const mockTools = {} as Tools<{}, {}>;
200+
export const serviceFieldName = 'serviceFieldName';
201+
197202
describe('helpers', () => {
198203
test('just empty test', () => {
199204
expect(true).toBe(true);

src/lib/unstable/core/SchemaRendererServiceField/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,13 @@ const processAjvValidateErrors = <Schema extends JsonSchema>({
278278

279279
w.promise.then((result) => {
280280
setValidationCache({
281-
name: serviceFieldName,
282281
cache: {
283282
[w.instancePath]: {
284283
...w.params,
285284
result,
286285
},
287286
},
287+
serviceFieldName,
288288
});
289289
});
290290
},
@@ -397,7 +397,7 @@ export const getValidate = <Schema extends JsonSchema>({
397397
});
398398

399399
if (Object.keys(waiters).length) {
400-
setValidationWaiters({name: serviceFieldName, waiters});
400+
setValidationWaiters({serviceFieldName, waiters});
401401
}
402402

403403
const result = processErrorItems({
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
import type {InternalFormState, MutableState} from 'final-form';
2+
3+
import {mockTools, serviceFieldName} from '../../../../__tests__/helpers.test';
4+
import {JsonSchemaType} from '../../../constants';
5+
import {setValidationCache, setValidationWaiters} from '../async-validation';
6+
import type {ValidationCache, ValidationWaiter} from '../types';
7+
8+
const createMockWaiterAndCache = (prefix = '') => {
9+
const fieldName = `fieldName${prefix}`;
10+
const waiter: ValidationWaiter = {
11+
schema: {type: JsonSchemaType.String},
12+
validator: jest.fn(),
13+
value: `value${prefix}`,
14+
};
15+
const cache: ValidationCache = {...waiter, result: `result${prefix}`};
16+
17+
return {cache, fieldName, waiter};
18+
};
19+
20+
const createMockMutableState = (fields: Record<string, any> = {}): MutableState<{}, {}> => {
21+
const mockFormState = {} as InternalFormState;
22+
23+
return {
24+
fields,
25+
formState: mockFormState,
26+
fieldSubscribers: {},
27+
};
28+
};
29+
30+
describe('async-validation', () => {
31+
describe('setValidationWaiters', () => {
32+
it('should not modify state if service field does not exist', () => {
33+
const {fieldName, waiter} = createMockWaiterAndCache();
34+
const mutableState = createMockMutableState();
35+
36+
setValidationWaiters(
37+
[{serviceFieldName, waiters: {[fieldName]: waiter}}],
38+
mutableState,
39+
mockTools,
40+
);
41+
42+
expect(mutableState.fields).toEqual({});
43+
});
44+
45+
it('should not modify state if waiters are not provided', () => {
46+
const mutableState = createMockMutableState({
47+
[serviceFieldName]: {data: {}},
48+
});
49+
50+
setValidationWaiters(
51+
[{serviceFieldName, waiters: undefined as any}],
52+
mutableState,
53+
mockTools,
54+
);
55+
56+
expect(mutableState.fields[serviceFieldName].data).toEqual({});
57+
});
58+
59+
it('should add waiter to the validation state', () => {
60+
const {fieldName, waiter} = createMockWaiterAndCache();
61+
const mutableState = createMockMutableState({
62+
[serviceFieldName]: {data: {}},
63+
[fieldName]: {},
64+
});
65+
66+
setValidationWaiters(
67+
[{serviceFieldName, waiters: {[fieldName]: waiter}}],
68+
mutableState,
69+
mockTools,
70+
);
71+
72+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({
73+
[fieldName]: waiter,
74+
});
75+
expect(mutableState.fields[fieldName].validating).toBe(true);
76+
});
77+
78+
it('should add waiters to the validation state', () => {
79+
const waiterAndCacheKit = createMockWaiterAndCache();
80+
const waiterAndCacheKit2 = createMockWaiterAndCache('2');
81+
82+
const mutableState = createMockMutableState({
83+
[serviceFieldName]: {data: {}},
84+
[waiterAndCacheKit.fieldName]: {validating: false},
85+
[waiterAndCacheKit2.fieldName]: {validating: false},
86+
});
87+
88+
setValidationWaiters(
89+
[
90+
{
91+
serviceFieldName,
92+
waiters: {
93+
[waiterAndCacheKit.fieldName]: waiterAndCacheKit.waiter,
94+
[waiterAndCacheKit2.fieldName]: waiterAndCacheKit2.waiter,
95+
},
96+
},
97+
],
98+
mutableState,
99+
mockTools,
100+
);
101+
102+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({
103+
[waiterAndCacheKit.fieldName]: waiterAndCacheKit.waiter,
104+
[waiterAndCacheKit2.fieldName]: waiterAndCacheKit2.waiter,
105+
});
106+
expect(mutableState.fields[waiterAndCacheKit.fieldName].validating).toBe(true);
107+
expect(mutableState.fields[waiterAndCacheKit2.fieldName].validating).toBe(true);
108+
});
109+
110+
it('should merge waiters with existing waiters', () => {
111+
const waiterAndCacheKit = createMockWaiterAndCache();
112+
const existingWaiterAndCacheKit = createMockWaiterAndCache('existing');
113+
const mutableState = createMockMutableState({
114+
[serviceFieldName]: {
115+
data: {
116+
waiters: {
117+
[existingWaiterAndCacheKit.fieldName]: existingWaiterAndCacheKit.waiter,
118+
},
119+
},
120+
},
121+
[waiterAndCacheKit.fieldName]: {},
122+
});
123+
124+
setValidationWaiters(
125+
[
126+
{
127+
serviceFieldName,
128+
waiters: {[waiterAndCacheKit.fieldName]: waiterAndCacheKit.waiter},
129+
},
130+
],
131+
mutableState,
132+
mockTools,
133+
);
134+
135+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({
136+
[existingWaiterAndCacheKit.fieldName]: existingWaiterAndCacheKit.waiter,
137+
[waiterAndCacheKit.fieldName]: waiterAndCacheKit.waiter,
138+
});
139+
expect(mutableState.fields[waiterAndCacheKit.fieldName].validating).toBe(true);
140+
});
141+
});
142+
143+
describe('setValidationCache', () => {
144+
it('should not modify state if field does not exist', () => {
145+
const {cache, fieldName} = createMockWaiterAndCache();
146+
const mutableState = createMockMutableState();
147+
148+
setValidationCache(
149+
[{serviceFieldName, cache: {[fieldName]: cache}}],
150+
mutableState,
151+
mockTools,
152+
);
153+
154+
expect(mutableState.fields).toEqual({});
155+
});
156+
157+
it('should not modify state if cache is not provided', () => {
158+
const mutableState = createMockMutableState({
159+
[serviceFieldName]: {data: {}},
160+
});
161+
162+
setValidationCache(
163+
[{serviceFieldName, cache: undefined as any}],
164+
mutableState,
165+
mockTools,
166+
);
167+
168+
expect(mutableState.fields[serviceFieldName].data).toEqual({});
169+
});
170+
171+
it('should add cache to the validation state', () => {
172+
const {cache, fieldName} = createMockWaiterAndCache();
173+
const mutableState = createMockMutableState({
174+
[serviceFieldName]: {data: {}},
175+
[fieldName]: {},
176+
});
177+
178+
setValidationCache(
179+
[{serviceFieldName, cache: {[fieldName]: cache}}],
180+
mutableState,
181+
mockTools,
182+
);
183+
184+
expect(mutableState.fields[serviceFieldName].data.cache).toEqual({
185+
[fieldName]: [cache],
186+
});
187+
});
188+
189+
it('should append to existing cache', () => {
190+
const fieldName = 'fieldName';
191+
const existingWaiterAndCacheKit = createMockWaiterAndCache('existing');
192+
const waiterAndCacheKit = createMockWaiterAndCache();
193+
const mutableState = createMockMutableState({
194+
[serviceFieldName]: {
195+
data: {
196+
cache: {
197+
[fieldName]: [existingWaiterAndCacheKit.cache],
198+
},
199+
},
200+
},
201+
[fieldName]: {},
202+
});
203+
204+
setValidationCache(
205+
[{serviceFieldName, cache: {[fieldName]: waiterAndCacheKit.cache}}],
206+
mutableState,
207+
mockTools,
208+
);
209+
210+
expect(mutableState.fields[serviceFieldName].data.cache).toEqual({
211+
[fieldName]: [existingWaiterAndCacheKit.cache, waiterAndCacheKit.cache],
212+
});
213+
});
214+
215+
it('should clear waiter and set validating to false when waiter matches cache', () => {
216+
const fieldName = 'fieldName';
217+
const {cache, waiter} = createMockWaiterAndCache();
218+
const mutableState = createMockMutableState({
219+
[serviceFieldName]: {data: {waiters: {[fieldName]: waiter}}},
220+
[fieldName]: {validating: true},
221+
});
222+
223+
setValidationCache(
224+
[{serviceFieldName, cache: {[fieldName]: cache}}],
225+
mutableState,
226+
mockTools,
227+
);
228+
229+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({});
230+
expect(mutableState.fields[fieldName].validating).toBe(false);
231+
});
232+
233+
it('should not clear waiter when waiter does not match cache', () => {
234+
const fieldName = 'fieldName';
235+
const {waiter} = createMockWaiterAndCache('1');
236+
const {cache} = createMockWaiterAndCache('2');
237+
238+
const mutableState = createMockMutableState({
239+
[serviceFieldName]: {data: {waiters: {[fieldName]: waiter}}},
240+
[fieldName]: {validating: true},
241+
});
242+
243+
setValidationCache(
244+
[{serviceFieldName, cache: {[fieldName]: cache}}],
245+
mutableState,
246+
mockTools,
247+
);
248+
249+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({
250+
[fieldName]: waiter,
251+
});
252+
expect(mutableState.fields[fieldName].validating).toBe(true);
253+
});
254+
255+
it('should handle multiple cache entries', () => {
256+
const fieldName = 'fieldName';
257+
const waiterAndCacheKit = createMockWaiterAndCache(fieldName);
258+
259+
const fieldName2 = 'fieldName2';
260+
const waiterAndCacheKit2 = createMockWaiterAndCache(fieldName2);
261+
262+
const mutableState = createMockMutableState({
263+
[serviceFieldName]: {
264+
data: {
265+
waiters: {
266+
[fieldName]: waiterAndCacheKit.waiter,
267+
[fieldName2]: waiterAndCacheKit2.waiter,
268+
},
269+
},
270+
},
271+
[fieldName]: {validating: true},
272+
[fieldName2]: {validating: true},
273+
});
274+
275+
setValidationCache(
276+
[
277+
{
278+
serviceFieldName,
279+
cache: {
280+
[fieldName]: waiterAndCacheKit.cache,
281+
[fieldName2]: waiterAndCacheKit2.cache,
282+
},
283+
},
284+
],
285+
mutableState,
286+
mockTools,
287+
);
288+
289+
expect(mutableState.fields[serviceFieldName].data.waiters).toEqual({});
290+
expect(mutableState.fields[fieldName].validating).toBe(false);
291+
expect(mutableState.fields[fieldName2].validating).toBe(false);
292+
expect(mutableState.fields[serviceFieldName].data.cache).toEqual({
293+
[fieldName]: [waiterAndCacheKit.cache],
294+
[fieldName2]: [waiterAndCacheKit2.cache],
295+
});
296+
});
297+
});
298+
});

src/lib/unstable/core/mutators/async-validation/async-validation.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import type {
88
} from './types';
99

1010
export const setValidationWaiters: SetValidationWaitersFunction = (
11-
[{name, waiters}],
11+
[{serviceFieldName, waiters}],
1212
mutableState,
1313
) => {
14-
const validationState = mutableState.fields[name]?.data as ValidationState | undefined;
14+
const validationState = mutableState.fields[serviceFieldName]?.data as
15+
| ValidationState
16+
| undefined;
1517

1618
if (validationState && waiters) {
1719
Object.keys(waiters).forEach((waiterName) => {
@@ -29,8 +31,13 @@ export const setValidationWaiters: SetValidationWaitersFunction = (
2931
}
3032
};
3133

32-
export const setValidationCache: SetValidationCacheFunction = ([{cache, name}], mutableState) => {
33-
const validationState = mutableState.fields[name]?.data as ValidationState | undefined;
34+
export const setValidationCache: SetValidationCacheFunction = (
35+
[{cache, serviceFieldName}],
36+
mutableState,
37+
) => {
38+
const validationState = mutableState.fields[serviceFieldName]?.data as
39+
| ValidationState
40+
| undefined;
3441

3542
if (validationState && cache) {
3643
Object.keys(cache).forEach((cacheName) => {

src/lib/unstable/core/mutators/async-validation/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface ValidationState {
2222
}
2323

2424
export interface SetValidationWaitersParams {
25-
name: string;
25+
serviceFieldName: string;
2626
waiters: {
2727
[key: string]: ValidationWaiter;
2828
};
@@ -43,7 +43,7 @@ export interface SetValidationCacheParams {
4343
cache: {
4444
[key: string]: ValidationCache;
4545
};
46-
name: string;
46+
serviceFieldName: string;
4747
}
4848

4949
export type SetValidationCacheFunction<

0 commit comments

Comments
 (0)