@sanity/validation 3.0.0-dev-preview.20 → 3.0.0-dev-preview.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/lib/dts/src/index.d.ts +36 -13
  2. package/lib/index.js +1525 -1291
  3. package/lib/index.js.map +1 -1
  4. package/lib/index.mjs +1542 -0
  5. package/lib/index.mjs.map +1 -0
  6. package/package.json +24 -18
  7. package/src/index.ts +3 -1
  8. package/src/util/requestIdleCallback.ts +31 -0
  9. package/src/validateDocument.test.ts +0 -80
  10. package/src/validateDocument.ts +82 -43
  11. package/src/validators/slugValidator.ts +16 -2
  12. package/lib/dts/src/Rule.d.ts +0 -4
  13. package/lib/dts/src/Rule.d.ts.map +0 -1
  14. package/lib/dts/src/Rule.js +0 -336
  15. package/lib/dts/src/Rule.js.map +0 -1
  16. package/lib/dts/src/ValidationError.d.ts +0 -4
  17. package/lib/dts/src/ValidationError.d.ts.map +0 -1
  18. package/lib/dts/src/ValidationError.js +0 -18
  19. package/lib/dts/src/ValidationError.js.map +0 -1
  20. package/lib/dts/src/index.d.ts.map +0 -1
  21. package/lib/dts/src/index.js +0 -7
  22. package/lib/dts/src/index.js.map +0 -1
  23. package/lib/dts/src/inferFromSchema.d.ts +0 -4
  24. package/lib/dts/src/inferFromSchema.d.ts.map +0 -1
  25. package/lib/dts/src/inferFromSchema.js +0 -14
  26. package/lib/dts/src/inferFromSchema.js.map +0 -1
  27. package/lib/dts/src/inferFromSchemaType.d.ts +0 -5
  28. package/lib/dts/src/inferFromSchemaType.d.ts.map +0 -1
  29. package/lib/dts/src/inferFromSchemaType.js +0 -33
  30. package/lib/dts/src/inferFromSchemaType.js.map +0 -1
  31. package/lib/dts/src/util/convertToValidationMarker.d.ts +0 -6
  32. package/lib/dts/src/util/convertToValidationMarker.d.ts.map +0 -1
  33. package/lib/dts/src/util/convertToValidationMarker.js +0 -51
  34. package/lib/dts/src/util/convertToValidationMarker.js.map +0 -1
  35. package/lib/dts/src/util/deepEquals.d.ts +0 -6
  36. package/lib/dts/src/util/deepEquals.d.ts.map +0 -1
  37. package/lib/dts/src/util/deepEquals.js +0 -65
  38. package/lib/dts/src/util/deepEquals.js.map +0 -1
  39. package/lib/dts/src/util/escapeRegex.d.ts +0 -3
  40. package/lib/dts/src/util/escapeRegex.d.ts.map +0 -1
  41. package/lib/dts/src/util/escapeRegex.js +0 -6
  42. package/lib/dts/src/util/escapeRegex.js.map +0 -1
  43. package/lib/dts/src/util/normalizeValidationRules.d.ts +0 -6
  44. package/lib/dts/src/util/normalizeValidationRules.d.ts.map +0 -1
  45. package/lib/dts/src/util/normalizeValidationRules.js +0 -104
  46. package/lib/dts/src/util/normalizeValidationRules.js.map +0 -1
  47. package/lib/dts/src/util/normalizeValidationRules.test.d.ts +0 -2
  48. package/lib/dts/src/util/normalizeValidationRules.test.d.ts.map +0 -1
  49. package/lib/dts/src/util/normalizeValidationRules.test.js +0 -150
  50. package/lib/dts/src/util/normalizeValidationRules.test.js.map +0 -1
  51. package/lib/dts/src/util/pathToString.d.ts +0 -3
  52. package/lib/dts/src/util/pathToString.d.ts.map +0 -1
  53. package/lib/dts/src/util/pathToString.js +0 -18
  54. package/lib/dts/src/util/pathToString.js.map +0 -1
  55. package/lib/dts/src/util/typeString.d.ts +0 -2
  56. package/lib/dts/src/util/typeString.d.ts.map +0 -1
  57. package/lib/dts/src/util/typeString.js +0 -23
  58. package/lib/dts/src/util/typeString.js.map +0 -1
  59. package/lib/dts/src/util/typeString.test.d.ts +0 -2
  60. package/lib/dts/src/util/typeString.test.d.ts.map +0 -1
  61. package/lib/dts/src/util/typeString.test.js +0 -24
  62. package/lib/dts/src/util/typeString.test.js.map +0 -1
  63. package/lib/dts/src/validateDocument.d.ts +0 -25
  64. package/lib/dts/src/validateDocument.d.ts.map +0 -1
  65. package/lib/dts/src/validateDocument.js +0 -165
  66. package/lib/dts/src/validateDocument.js.map +0 -1
  67. package/lib/dts/src/validateDocument.test.d.ts +0 -2
  68. package/lib/dts/src/validateDocument.test.d.ts.map +0 -1
  69. package/lib/dts/src/validateDocument.test.js +0 -717
  70. package/lib/dts/src/validateDocument.test.js.map +0 -1
  71. package/lib/dts/src/validators/arrayValidator.d.ts +0 -4
  72. package/lib/dts/src/validators/arrayValidator.d.ts.map +0 -1
  73. package/lib/dts/src/validators/arrayValidator.js +0 -79
  74. package/lib/dts/src/validators/arrayValidator.js.map +0 -1
  75. package/lib/dts/src/validators/booleanValidator.d.ts +0 -4
  76. package/lib/dts/src/validators/booleanValidator.d.ts.map +0 -1
  77. package/lib/dts/src/validators/booleanValidator.js +0 -12
  78. package/lib/dts/src/validators/booleanValidator.js.map +0 -1
  79. package/lib/dts/src/validators/dateValidator.d.ts +0 -5
  80. package/lib/dts/src/validators/dateValidator.d.ts.map +0 -1
  81. package/lib/dts/src/validators/dateValidator.js +0 -83
  82. package/lib/dts/src/validators/dateValidator.js.map +0 -1
  83. package/lib/dts/src/validators/genericValidator.d.ts +0 -4
  84. package/lib/dts/src/validators/genericValidator.d.ts.map +0 -1
  85. package/lib/dts/src/validators/genericValidator.js +0 -93
  86. package/lib/dts/src/validators/genericValidator.js.map +0 -1
  87. package/lib/dts/src/validators/numberValidator.d.ts +0 -4
  88. package/lib/dts/src/validators/numberValidator.d.ts.map +0 -1
  89. package/lib/dts/src/validators/numberValidator.js +0 -47
  90. package/lib/dts/src/validators/numberValidator.js.map +0 -1
  91. package/lib/dts/src/validators/objectValidator.d.ts +0 -4
  92. package/lib/dts/src/validators/objectValidator.d.ts.map +0 -1
  93. package/lib/dts/src/validators/objectValidator.js +0 -48
  94. package/lib/dts/src/validators/objectValidator.js.map +0 -1
  95. package/lib/dts/src/validators/slugValidator.d.ts +0 -9
  96. package/lib/dts/src/validators/slugValidator.d.ts.map +0 -1
  97. package/lib/dts/src/validators/slugValidator.js +0 -83
  98. package/lib/dts/src/validators/slugValidator.js.map +0 -1
  99. package/lib/dts/src/validators/stringValidator.d.ts +0 -4
  100. package/lib/dts/src/validators/stringValidator.d.ts.map +0 -1
  101. package/lib/dts/src/validators/stringValidator.js +0 -94
  102. package/lib/dts/src/validators/stringValidator.js.map +0 -1
  103. package/lib/dts/test/array.test.d.ts +0 -2
  104. package/lib/dts/test/array.test.d.ts.map +0 -1
  105. package/lib/dts/test/array.test.js +0 -55
  106. package/lib/dts/test/array.test.js.map +0 -1
  107. package/lib/dts/test/children.test.d.ts +0 -2
  108. package/lib/dts/test/children.test.d.ts.map +0 -1
  109. package/lib/dts/test/children.test.js +0 -70
  110. package/lib/dts/test/children.test.js.map +0 -1
  111. package/lib/dts/test/createSchema.d.ts +0 -6
  112. package/lib/dts/test/createSchema.d.ts.map +0 -1
  113. package/lib/dts/test/createSchema.js +0 -19
  114. package/lib/dts/test/createSchema.js.map +0 -1
  115. package/lib/dts/test/generics.test.d.ts +0 -2
  116. package/lib/dts/test/generics.test.d.ts.map +0 -1
  117. package/lib/dts/test/generics.test.js +0 -60
  118. package/lib/dts/test/generics.test.js.map +0 -1
  119. package/lib/dts/test/infer.test.d.ts +0 -2
  120. package/lib/dts/test/infer.test.d.ts.map +0 -1
  121. package/lib/dts/test/infer.test.js +0 -244
  122. package/lib/dts/test/infer.test.js.map +0 -1
  123. package/lib/dts/test/mocks/mockSanityClient.d.ts +0 -6
  124. package/lib/dts/test/mocks/mockSanityClient.d.ts.map +0 -1
  125. package/lib/dts/test/mocks/mockSanityClient.js +0 -8
  126. package/lib/dts/test/mocks/mockSanityClient.js.map +0 -1
  127. package/lib/dts/test/nullExport.d.ts +0 -3
  128. package/lib/dts/test/nullExport.d.ts.map +0 -1
  129. package/lib/dts/test/nullExport.js +0 -4
  130. package/lib/dts/test/nullExport.js.map +0 -1
  131. package/lib/dts/test/numbers.test.d.ts +0 -2
  132. package/lib/dts/test/numbers.test.d.ts.map +0 -1
  133. package/lib/dts/test/numbers.test.js +0 -57
  134. package/lib/dts/test/numbers.test.js.map +0 -1
  135. package/lib/dts/test/strings.test.d.ts +0 -2
  136. package/lib/dts/test/strings.test.d.ts.map +0 -1
  137. package/lib/dts/test/strings.test.js +0 -100
  138. package/lib/dts/test/strings.test.js.map +0 -1
  139. package/lib/dts/tsconfig.lib.tsbuildinfo +0 -1
  140. package/lib/dts/tsconfig.tsbuildinfo +0 -1
  141. package/lib/index.cjs +0 -1341
  142. package/lib/index.cjs.map +0 -1
@@ -1,717 +0,0 @@
1
- import { createSchema } from '../test/createSchema';
2
- import { createMockSanityClient } from '../test/mocks/mockSanityClient';
3
- import validateDocument, { resolveTypeForArrayItem, validateItem } from './validateDocument';
4
- import { convertToValidationMarker } from './util/convertToValidationMarker';
5
- jest.mock('./util/convertToValidationMarker', () => {
6
- return {
7
- convertToValidationMarker: jest.fn(jest.requireActual('./util/convertToValidationMarker').convertToValidationMarker),
8
- };
9
- });
10
- beforeEach(() => {
11
- ;
12
- convertToValidationMarker.mockClear();
13
- });
14
- // mock client
15
- const client = createMockSanityClient();
16
- const getClient = (options) => client;
17
- describe('resolveTypeForArrayItem', () => {
18
- const schema = createSchema({
19
- types: [
20
- {
21
- name: 'foo',
22
- type: 'object',
23
- fields: [{ name: 'title', type: 'number' }],
24
- },
25
- {
26
- name: 'bar',
27
- type: 'object',
28
- fields: [{ name: 'title', type: 'string' }],
29
- },
30
- ],
31
- });
32
- const fooType = schema.get('foo');
33
- const barType = schema.get('bar');
34
- it('finds a matching schema type for an array item value given a list of candidate types', () => {
35
- const resolved = resolveTypeForArrayItem({
36
- _type: 'bar',
37
- _key: 'exampleKey',
38
- title: 5,
39
- }, [fooType, barType]);
40
- expect(resolved).toBe(barType);
41
- });
42
- it('assumes the type if there is only one possible candidate', () => {
43
- const resolved = resolveTypeForArrayItem({
44
- // notice no _type
45
- _key: 'exampleKey',
46
- title: 5,
47
- }, [fooType]);
48
- expect(resolved).toBe(fooType);
49
- });
50
- });
51
- describe('validateDocument', () => {
52
- it('takes in a document + a compiled schema and returns a list of validation markers', async () => {
53
- const schema = createSchema({
54
- types: [
55
- {
56
- name: 'simpleDoc',
57
- type: 'document',
58
- title: 'Simple Document',
59
- fields: [
60
- {
61
- name: 'title',
62
- type: 'string',
63
- validation: (rule) => rule.required(),
64
- },
65
- ],
66
- },
67
- ],
68
- });
69
- const document = {
70
- _id: 'testId',
71
- _createdAt: '2021-08-27T14:48:51.650Z',
72
- _rev: 'exampleRev',
73
- _type: 'simpleDoc',
74
- _updatedAt: '2021-08-27T14:48:51.650Z',
75
- title: null,
76
- };
77
- const result = await validateDocument(getClient, document, schema);
78
- expect(result).toMatchObject([
79
- {
80
- level: 'error',
81
- item: {
82
- message: 'Expected type "String", got "null"',
83
- paths: [],
84
- },
85
- path: ['title'],
86
- },
87
- {
88
- level: 'error',
89
- item: {
90
- message: 'Required',
91
- paths: [],
92
- },
93
- path: ['title'],
94
- },
95
- ]);
96
- });
97
- });
98
- describe('validateItem', () => {
99
- it("runs nested validation on an undefined value for object types if it's required", async () => {
100
- const validation = (rule) => [
101
- rule.required().error('This is required!'),
102
- rule.max(160).warning('Too long!'),
103
- ];
104
- const schema = createSchema({
105
- types: [
106
- {
107
- name: 'testObj',
108
- type: 'object',
109
- title: 'Test Object',
110
- fields: [
111
- { name: 'registeredString', type: 'registeredString' },
112
- { name: 'inlineString', type: 'string', validation },
113
- {
114
- name: 'registeredObject',
115
- type: 'registeredObjectField',
116
- validation: (rule) => rule.required(),
117
- },
118
- {
119
- name: 'inlineObject',
120
- type: 'object',
121
- fields: [{ name: 'foo', type: 'string', validation }],
122
- validation: (rule) => rule.required(),
123
- },
124
- {
125
- name: 'notRequiredRegisteredObject',
126
- type: 'registeredObjectField',
127
- },
128
- {
129
- name: 'notRequiredInlineObject',
130
- type: 'object',
131
- fields: [{ name: 'foo', type: 'string', validation }],
132
- },
133
- ],
134
- },
135
- { name: 'registeredString', title: 'Registered String', type: 'string', validation },
136
- {
137
- title: 'Registered Object Field',
138
- name: 'registeredObjectField',
139
- type: 'object',
140
- fields: [{ name: 'foo', type: 'string', validation }],
141
- },
142
- ],
143
- });
144
- // ensures there are no schema formatting issues
145
- expect(schema._validation).toHaveLength(0);
146
- await expect(validateItem({
147
- client,
148
- getClient,
149
- schema,
150
- value: {},
151
- document: undefined,
152
- path: [],
153
- parent: undefined,
154
- type: schema.get('testObj'),
155
- getDocumentExists: undefined,
156
- })).resolves.toMatchObject([
157
- {
158
- level: 'error',
159
- item: { message: 'This is required!' },
160
- path: ['registeredString'],
161
- },
162
- {
163
- level: 'error',
164
- item: { message: 'This is required!' },
165
- path: ['inlineString'],
166
- },
167
- {
168
- level: 'error',
169
- item: { message: 'Required' },
170
- path: ['registeredObject'],
171
- },
172
- {
173
- level: 'error',
174
- item: { message: 'This is required!' },
175
- path: ['registeredObject', 'foo'],
176
- },
177
- {
178
- level: 'error',
179
- item: { message: 'Required' },
180
- path: ['inlineObject'],
181
- },
182
- {
183
- level: 'error',
184
- item: { message: 'This is required!' },
185
- path: ['inlineObject', 'foo'],
186
- },
187
- ]);
188
- });
189
- it('runs nested validation for object-level rules set via Rule.fields()', async () => {
190
- const schema = createSchema({
191
- types: [
192
- {
193
- name: 'testObj',
194
- type: 'object',
195
- title: 'Test Object',
196
- fields: [
197
- { name: 'foo', type: 'string' },
198
- { name: 'bar', type: 'string' },
199
- ],
200
- validation: (rule) => [
201
- rule.required(),
202
- rule.fields({
203
- foo: (r) => r.required(),
204
- bar: (r) => r.required(),
205
- }),
206
- ],
207
- },
208
- ],
209
- });
210
- // ensures there are no schema formatting issues
211
- expect(schema._validation).toHaveLength(0);
212
- await expect(validateItem({
213
- client,
214
- getClient,
215
- schema,
216
- document: undefined,
217
- parent: undefined,
218
- path: undefined,
219
- type: schema.get('testObj'),
220
- value: { foo: 5 },
221
- getDocumentExists: undefined,
222
- })).resolves.toMatchObject([
223
- {
224
- item: { message: 'Expected type "String", got "Number"' },
225
- level: 'error',
226
- path: ['foo'],
227
- },
228
- {
229
- item: { message: 'Required' },
230
- level: 'error',
231
- path: ['bar'],
232
- },
233
- ]);
234
- });
235
- // @todo this one fails, needs investigation for what is actually the expected outcome
236
- it.skip('runs nested validation for markDefs', async () => {
237
- const linkValidationSpy = jest.fn(() => true);
238
- const internalLinkSpy = jest.fn(() => 'mock invalid response');
239
- const schema = createSchema({
240
- types: [
241
- {
242
- name: 'post',
243
- title: 'Post',
244
- type: 'document',
245
- fields: [
246
- { name: 'title', type: 'string' },
247
- { name: 'body', type: 'string' },
248
- ],
249
- },
250
- {
251
- name: 'registeredEditor',
252
- type: 'object',
253
- title: 'Registered Editor',
254
- fields: [
255
- {
256
- name: 'editor',
257
- type: 'array',
258
- of: [
259
- {
260
- type: 'block',
261
- marks: {
262
- annotations: [
263
- {
264
- name: 'exampleAnnotation',
265
- type: 'object',
266
- fields: [{ name: 'value', type: 'string' }],
267
- },
268
- ],
269
- },
270
- },
271
- ],
272
- },
273
- ],
274
- },
275
- {
276
- name: 'blockTest',
277
- type: 'document',
278
- title: 'blockTest',
279
- fields: [
280
- {
281
- name: 'content',
282
- title: 'Content',
283
- type: 'array',
284
- of: [
285
- {
286
- type: 'block',
287
- marks: {
288
- annotations: [
289
- {
290
- name: 'link',
291
- type: 'object',
292
- title: 'link',
293
- fields: [{ name: 'url', type: 'url' }],
294
- validation: (rule) => rule.custom(linkValidationSpy),
295
- },
296
- {
297
- name: 'internalLink',
298
- type: 'object',
299
- title: 'Internal link',
300
- fields: [{ name: 'reference', type: 'reference', to: [{ type: 'post' }] }],
301
- validation: (rule) => rule.custom(internalLinkSpy),
302
- },
303
- { name: 'nestedEditor', type: 'registeredEditor' },
304
- ],
305
- },
306
- },
307
- ],
308
- },
309
- ],
310
- },
311
- ],
312
- });
313
- expect(schema._validation).toHaveLength(0);
314
- const nestedBlock = {
315
- _type: 'block',
316
- _key: 'nested-block-key',
317
- children: [
318
- {
319
- _key: 'some-key',
320
- _type: 'span',
321
- text: 'hey',
322
- marks: ['example-annotation-key'],
323
- },
324
- ],
325
- markDefs: [
326
- {
327
- _type: 'exampleAnnotation',
328
- _key: 'example-annotation-key',
329
- value: 5,
330
- },
331
- ],
332
- style: 'normal',
333
- };
334
- const block = {
335
- _key: 'block-key',
336
- _type: 'block',
337
- children: [
338
- {
339
- _key: 'child-0',
340
- _type: 'span',
341
- marks: ['0', '1', '2'],
342
- text: 'hey',
343
- },
344
- ],
345
- markDefs: [
346
- {
347
- _key: '0',
348
- _type: 'link',
349
- url: 'https://example.com',
350
- },
351
- {
352
- _key: '1',
353
- _type: 'internalLink',
354
- _ref: 'post-id',
355
- },
356
- {
357
- _key: '2',
358
- _type: 'nestedEditor',
359
- editor: [nestedBlock],
360
- },
361
- ],
362
- style: 'normal',
363
- };
364
- const document = {
365
- _id: 'mock-id',
366
- _type: 'blockTest',
367
- _createdAt: '2021-11-15T21:06:41.812Z',
368
- _rev: 'example-ref',
369
- _updatedAt: '2021-11-15T21:06:41.812Z',
370
- content: [block],
371
- };
372
- const result = await validateItem({
373
- client,
374
- getClient,
375
- schema,
376
- document: document,
377
- parent: undefined,
378
- path: [],
379
- type: schema.get('blockTest'),
380
- value: document,
381
- getDocumentExists: undefined,
382
- });
383
- expect(result).toMatchObject([
384
- {
385
- item: { message: 'mock invalid response', paths: [] },
386
- level: 'error',
387
- path: ['content', { _key: 'block-key' }, 'markDefs', { _key: '1' }],
388
- },
389
- // this tests for nested markDef validation
390
- {
391
- item: {
392
- message: 'Expected type "String", got "Number"',
393
- paths: [],
394
- },
395
- level: 'error',
396
- path: [
397
- 'content',
398
- { _key: 'block-key' },
399
- 'markDefs',
400
- { _key: '2' },
401
- 'editor',
402
- { _key: 'nested-block-key' },
403
- 'markDefs',
404
- { _key: 'example-annotation-key' },
405
- 'value',
406
- ],
407
- },
408
- ]);
409
- expect(linkValidationSpy.mock.calls).toMatchObject([
410
- [
411
- {
412
- _key: '0',
413
- _type: 'link',
414
- url: 'https://example.com',
415
- },
416
- {
417
- document: { _id: 'mock-id' },
418
- parent: { _key: 'block-key' },
419
- path: ['content', { _key: 'block-key' }, 'markDefs', { _key: '0' }],
420
- type: { name: 'link' },
421
- },
422
- ],
423
- ]);
424
- expect(internalLinkSpy.mock.calls).toMatchObject([
425
- [
426
- {
427
- _key: '1',
428
- _ref: 'post-id',
429
- _type: 'internalLink',
430
- },
431
- {
432
- document: { _id: 'mock-id' },
433
- parent: { _key: 'block-key' },
434
- path: ['content', { _key: 'block-key' }, 'markDefs', { _key: '1' }],
435
- type: { name: 'internalLink' },
436
- },
437
- ],
438
- ]);
439
- });
440
- it('resolves an array item type if there is just one type', async () => {
441
- const schema = createSchema({
442
- types: [
443
- {
444
- name: 'values',
445
- title: 'Values',
446
- type: 'array',
447
- // note that there is only one type available
448
- of: [{ type: 'arrayItem' }],
449
- validation: (rule) => rule.required(),
450
- },
451
- {
452
- title: 'Array Item',
453
- name: 'arrayItem',
454
- type: 'object',
455
- fields: [{ name: 'title', type: 'string' }],
456
- },
457
- ],
458
- });
459
- // ensures there are no schema formatting issues
460
- expect(schema._validation).toHaveLength(0);
461
- const values = [
462
- {
463
- // note how this doesn't have a _type
464
- title: 5,
465
- _key: 'exampleKey',
466
- },
467
- ];
468
- await expect(validateItem({
469
- client,
470
- getClient,
471
- schema,
472
- document: undefined,
473
- parent: undefined,
474
- path: [],
475
- type: schema.get('values'),
476
- value: values,
477
- getDocumentExists: undefined,
478
- })).resolves.toEqual([
479
- {
480
- level: 'error',
481
- item: {
482
- message: 'Expected type "String", got "Number"',
483
- paths: [],
484
- },
485
- path: [{ _key: 'exampleKey' }, 'title'],
486
- },
487
- ]);
488
- });
489
- it('properly passes the nested value, type, and path to rule.validate', async () => {
490
- const schema = createSchema({
491
- types: [
492
- {
493
- name: 'root',
494
- type: 'object',
495
- title: 'Root',
496
- fields: [
497
- {
498
- name: 'level1Object',
499
- type: 'object',
500
- validation: (rule) => rule.custom(() => 'from level 1 object'),
501
- fields: [
502
- {
503
- name: 'level2String',
504
- type: 'string',
505
- validation: (rule) => rule.custom(() => 'from level 2 via object'),
506
- },
507
- ],
508
- },
509
- {
510
- name: 'level1Array',
511
- type: 'array',
512
- validation: (rule) => rule.custom(() => 'from level 1 array'),
513
- of: [
514
- {
515
- type: 'object',
516
- fields: [
517
- {
518
- name: 'level2Number',
519
- type: 'number',
520
- validation: (rule) => rule.custom(() => 'from level 2 via array'),
521
- },
522
- ],
523
- },
524
- ],
525
- },
526
- ],
527
- validation: (rule) => rule.custom(() => 'from root'),
528
- },
529
- ],
530
- });
531
- // ensures there are no schema formatting issues
532
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
533
- expect(schema._validation).toHaveLength(0);
534
- const value = {
535
- level1Object: { level3String: 'a string' },
536
- level1Array: [{ level2Number: 5 }],
537
- };
538
- const document = {
539
- value,
540
- _type: 'something',
541
- _createdAt: '2021-09-05T19:28:30.882Z',
542
- _id: 'something.id',
543
- _rev: 'exampleRev',
544
- _updatedAt: '2021-09-05T19:28:30.882Z',
545
- };
546
- const getField = ({ in: type, name }) => {
547
- const result = 'fields' in type && type.fields.find((f) => f.name === name)?.type;
548
- if (!result)
549
- throw new Error(`Could not find field \`${name}\` in \`${type.name}\``);
550
- return result;
551
- };
552
- const rootType = schema.get('root');
553
- const level1ObjectType = getField({ in: rootType, name: 'level1Object' });
554
- const level2StringType = getField({ in: level1ObjectType, name: 'level2String' });
555
- const level1ArrayType = getField({ in: rootType, name: 'level1Array' });
556
- const level2NumberType = getField({
557
- in: level1ArrayType.of[0],
558
- name: 'level2Number',
559
- });
560
- await expect(validateItem({
561
- client,
562
- getClient,
563
- schema,
564
- value,
565
- type: rootType,
566
- document,
567
- parent: document,
568
- path: undefined,
569
- getDocumentExists: undefined,
570
- })).resolves.toMatchObject([
571
- {
572
- item: { message: 'from root' },
573
- path: [],
574
- },
575
- {
576
- item: { message: 'from level 1 object' },
577
- path: ['level1Object'],
578
- },
579
- {
580
- item: { message: 'from level 2 via object' },
581
- path: ['level1Object', 'level2String'],
582
- },
583
- {
584
- item: { message: 'from level 1 array' },
585
- path: ['level1Array'],
586
- },
587
- {
588
- item: { message: 'from level 2 via array' },
589
- path: ['level1Array', 0, 'level2Number'],
590
- },
591
- ]);
592
- const calls = convertToValidationMarker.mock.calls;
593
- expect(calls.find((call) => call[0] === 'from root')).toMatchObject([
594
- 'from root',
595
- 'error',
596
- {
597
- parent: document,
598
- document: document,
599
- path: [],
600
- type: rootType,
601
- },
602
- ]);
603
- expect(calls.find((call) => call[0] === 'from level 1 object')).toMatchObject([
604
- 'from level 1 object',
605
- 'error',
606
- {
607
- parent: value,
608
- document: document,
609
- path: ['level1Object'],
610
- type: level1ObjectType,
611
- },
612
- ]);
613
- expect(calls.find((call) => call[0] === 'from level 2 via object')).toMatchObject([
614
- 'from level 2 via object',
615
- 'error',
616
- {
617
- parent: value.level1Object,
618
- document: document,
619
- path: ['level1Object', 'level2String'],
620
- type: level2StringType,
621
- },
622
- ]);
623
- expect(calls.find((call) => call[0] === 'from level 1 array')).toMatchObject([
624
- 'from level 1 array',
625
- 'error',
626
- {
627
- parent: value,
628
- document: document,
629
- path: ['level1Array'],
630
- type: level1ArrayType,
631
- },
632
- ]);
633
- expect(calls.find((call) => call[0] === 'from level 2 via array')).toMatchObject([
634
- 'from level 2 via array',
635
- 'error',
636
- {
637
- parent: value.level1Array[0],
638
- document: document,
639
- path: ['level1Array', 0, 'level2Number'],
640
- type: level2NumberType,
641
- },
642
- ]);
643
- });
644
- it('runs all nested validation checks concurrently', async () => {
645
- const resolvers = new Set();
646
- const customValidationFn = () => new Promise((resolve) => resolvers.add(resolve));
647
- const schema = createSchema({
648
- types: [
649
- {
650
- name: 'root',
651
- type: 'object',
652
- fields: [
653
- {
654
- name: 'level1Object',
655
- type: 'object',
656
- validation: (rule) => [
657
- rule.custom(customValidationFn),
658
- rule.fields({
659
- level2String: (r) => r.custom(customValidationFn),
660
- }),
661
- ],
662
- fields: [
663
- {
664
- name: 'level2String',
665
- type: 'string',
666
- validation: (rule) => rule.custom(customValidationFn),
667
- },
668
- ],
669
- },
670
- {
671
- name: 'level1Array',
672
- type: 'array',
673
- validation: (rule) => rule.custom(customValidationFn),
674
- of: [
675
- {
676
- type: 'object',
677
- fields: [
678
- {
679
- name: 'level2Number',
680
- type: 'number',
681
- validation: (rule) => rule.custom(customValidationFn),
682
- },
683
- ],
684
- },
685
- ],
686
- },
687
- ],
688
- validation: (rule) => rule.custom(customValidationFn),
689
- },
690
- ],
691
- });
692
- const value = {
693
- level1Object: { level3String: 'a string' },
694
- level1Array: [{ level2Number: 5 }],
695
- };
696
- const resultPromise = validateItem({
697
- client,
698
- getClient,
699
- schema,
700
- value,
701
- document: undefined,
702
- parent: undefined,
703
- path: undefined,
704
- type: schema.get('root'),
705
- getDocumentExists: undefined,
706
- });
707
- // after `validateItem(...)` has been initiated, all of the custom
708
- // validation calls should have fired so the resolver size should equal the
709
- // amount of total fields
710
- expect(resolvers.size).toBe(6);
711
- for (const resolver of resolvers) {
712
- resolver(true);
713
- }
714
- await resultPromise;
715
- });
716
- });
717
- //# sourceMappingURL=validateDocument.test.js.map