@sanity/validation 2.30.1-purple-unicorn.964 → 3.0.0-dev-preview.0

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 (48) hide show
  1. package/lib/dts/src/Rule.js +317 -312
  2. package/lib/dts/src/ValidationError.js +16 -16
  3. package/lib/dts/src/index.js +7 -7
  4. package/lib/dts/src/inferFromSchema.js +11 -11
  5. package/lib/dts/src/inferFromSchemaType.js +24 -24
  6. package/lib/dts/src/util/convertToValidationMarker.js +44 -53
  7. package/lib/dts/src/util/deepEquals.js +50 -49
  8. package/lib/dts/src/util/escapeRegex.js +4 -4
  9. package/lib/dts/src/util/normalizeValidationRules.js +87 -78
  10. package/lib/dts/src/util/normalizeValidationRules.test.d.ts +2 -2
  11. package/lib/dts/src/util/normalizeValidationRules.test.js +149 -149
  12. package/lib/dts/src/util/pathToString.js +16 -16
  13. package/lib/dts/src/util/typeString.js +17 -14
  14. package/lib/dts/src/util/typeString.test.d.ts +2 -2
  15. package/lib/dts/src/util/typeString.test.js +23 -24
  16. package/lib/dts/src/validateDocument.js +132 -157
  17. package/lib/dts/src/validateDocument.test.d.ts +2 -2
  18. package/lib/dts/src/validateDocument.test.js +664 -678
  19. package/lib/dts/src/validators/arrayValidator.js +75 -75
  20. package/lib/dts/src/validators/booleanValidator.js +11 -11
  21. package/lib/dts/src/validators/dateValidator.js +74 -68
  22. package/lib/dts/src/validators/genericValidator.js +89 -87
  23. package/lib/dts/src/validators/numberValidator.js +46 -48
  24. package/lib/dts/src/validators/objectValidator.js +47 -47
  25. package/lib/dts/src/validators/slugValidator.js +68 -74
  26. package/lib/dts/src/validators/stringValidator.js +93 -93
  27. package/lib/dts/test/array.test.d.ts +2 -2
  28. package/lib/dts/test/array.test.js +54 -78
  29. package/lib/dts/test/children.test.d.ts +2 -2
  30. package/lib/dts/test/children.test.js +69 -87
  31. package/lib/dts/test/createSchema.d.ts +6 -3
  32. package/lib/dts/test/createSchema.js +17 -17
  33. package/lib/dts/test/generics.test.d.ts +2 -2
  34. package/lib/dts/test/generics.test.js +59 -59
  35. package/lib/dts/test/infer.test.d.ts +2 -2
  36. package/lib/dts/test/infer.test.js +236 -285
  37. package/lib/dts/test/mocks/mockSanityClient.d.ts +4 -5
  38. package/lib/dts/test/mocks/mockSanityClient.d.ts.map +1 -1
  39. package/lib/dts/test/mocks/mockSanityClient.js +6 -6
  40. package/lib/dts/test/nullExport.d.ts +3 -3
  41. package/lib/dts/test/nullExport.js +2 -2
  42. package/lib/dts/test/numbers.test.d.ts +2 -2
  43. package/lib/dts/test/numbers.test.js +56 -62
  44. package/lib/dts/test/strings.test.d.ts +2 -2
  45. package/lib/dts/test/strings.test.js +99 -150
  46. package/lib/dts/tsconfig.lib.tsbuildinfo +1 -1
  47. package/lib/dts/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +4 -4
@@ -1,48 +1,48 @@
1
- import {isReference} from '@sanity/types'
2
- import genericValidator from './genericValidator'
3
- const metaKeys = ['_key', '_type', '_weak']
1
+ import { isReference } from '@sanity/types';
2
+ import genericValidator from './genericValidator';
3
+ const metaKeys = ['_key', '_type', '_weak'];
4
4
  const objectValidators = {
5
- ...genericValidator,
6
- presence: (expected, value, message) => {
7
- if (expected !== 'required') {
8
- return true
9
- }
10
- const keys = value && Object.keys(value).filter((key) => !metaKeys.includes(key))
11
- if (value === undefined || (keys && keys.length === 0)) {
12
- return message || 'Required'
13
- }
14
- return true
15
- },
16
- reference: async (_unused, value, message, context) => {
17
- if (!value) {
18
- return true
19
- }
20
- if (!isReference(value)) {
21
- return message || true
22
- }
23
- const {type, getDocumentExists} = context
24
- if (!type) {
25
- throw new Error(`\`type\` was not provided in validation context`)
26
- }
27
- if ('weak' in type && type.weak) {
28
- return true
29
- }
30
- if (!getDocumentExists) {
31
- throw new Error(`\`getDocumentExists\` was not provided in validation context`)
32
- }
33
- const exists = await getDocumentExists({id: value._ref})
34
- if (!exists) {
35
- return 'This reference must be published'
36
- }
37
- return true
38
- },
39
- assetRequired: (flag, value, message) => {
40
- if (!value || !value.asset || !value.asset._ref) {
41
- const assetType = flag.assetType || 'Asset'
42
- return message || `${assetType} required`
43
- }
44
- return true
45
- },
46
- }
47
- export default objectValidators
48
- //# sourceMappingURL=objectValidator.js.map
5
+ ...genericValidator,
6
+ presence: (expected, value, message) => {
7
+ if (expected !== 'required') {
8
+ return true;
9
+ }
10
+ const keys = value && Object.keys(value).filter((key) => !metaKeys.includes(key));
11
+ if (value === undefined || (keys && keys.length === 0)) {
12
+ return message || 'Required';
13
+ }
14
+ return true;
15
+ },
16
+ reference: async (_unused, value, message, context) => {
17
+ if (!value) {
18
+ return true;
19
+ }
20
+ if (!isReference(value)) {
21
+ return message || true;
22
+ }
23
+ const { type, getDocumentExists } = context;
24
+ if (!type) {
25
+ throw new Error(`\`type\` was not provided in validation context`);
26
+ }
27
+ if ('weak' in type && type.weak) {
28
+ return true;
29
+ }
30
+ if (!getDocumentExists) {
31
+ throw new Error(`\`getDocumentExists\` was not provided in validation context`);
32
+ }
33
+ const exists = await getDocumentExists({ id: value._ref });
34
+ if (!exists) {
35
+ return 'This reference must be published';
36
+ }
37
+ return true;
38
+ },
39
+ assetRequired: (flag, value, message) => {
40
+ if (!value || !value.asset || !value.asset._ref) {
41
+ const assetType = flag.assetType || 'Asset';
42
+ return message || `${assetType} required`;
43
+ }
44
+ return true;
45
+ },
46
+ };
47
+ export default objectValidators;
48
+ //# sourceMappingURL=objectValidator.js.map
@@ -1,65 +1,59 @@
1
- import {isKeyedObject} from '@sanity/types'
2
- import {memoize} from 'lodash'
1
+ import { isKeyedObject } from '@sanity/types';
2
+ import { memoize } from 'lodash';
3
3
  // import getClient from '../getClient'
4
- const memoizedWarnOnArraySlug = memoize(warnOnArraySlug)
4
+ const memoizedWarnOnArraySlug = memoize(warnOnArraySlug);
5
5
  function getDocumentIds(id) {
6
- const isDraft = id.indexOf('drafts.') === 0
7
- return {
8
- published: isDraft ? id.slice('drafts.'.length) : id,
9
- draft: isDraft ? id : `drafts.${id}`,
10
- }
6
+ const isDraft = id.indexOf('drafts.') === 0;
7
+ return {
8
+ published: isDraft ? id.slice('drafts.'.length) : id,
9
+ draft: isDraft ? id : `drafts.${id}`,
10
+ };
11
11
  }
12
12
  function serializePath(path) {
13
- return path.reduce((target, part, i) => {
14
- const isIndex = typeof part === 'number'
15
- const isKey = isKeyedObject(part)
16
- const separator = i === 0 ? '' : '.'
17
- const add = isIndex || isKey ? '[]' : `${separator}${part}`
18
- return `${target}${add}`
19
- }, '')
13
+ return path.reduce((target, part, i) => {
14
+ const isIndex = typeof part === 'number';
15
+ const isKey = isKeyedObject(part);
16
+ const separator = i === 0 ? '' : '.';
17
+ const add = isIndex || isKey ? '[]' : `${separator}${part}`;
18
+ return `${target}${add}`;
19
+ }, '');
20
20
  }
21
21
  const defaultIsUnique = (slug, context) => {
22
- const {client, document, path, type} = context
23
- const schemaOptions = type?.options
24
- if (!document) {
25
- throw new Error(`\`document\` was not provided in validation context.`)
26
- }
27
- if (!path) {
28
- throw new Error(`\`path\` was not provided in validation context.`)
29
- }
30
- const disableArrayWarning = schemaOptions?.disableArrayWarning || false
31
- const {published, draft} = getDocumentIds(document._id)
32
- const docType = document._type
33
- const atPath = serializePath(path.concat('current'))
34
- if (!disableArrayWarning && atPath.includes('[]')) {
35
- memoizedWarnOnArraySlug(serializePath(path))
36
- }
37
- const constraints = [
38
- '_type == $docType',
39
- `!(_id in [$draft, $published])`,
40
- `${atPath} == $slug`,
41
- ].join(' && ')
42
- return client.fetch(
43
- `!defined(*[${constraints}][0]._id)`,
44
- {
45
- docType,
46
- draft,
47
- published,
48
- slug,
49
- },
50
- {tag: 'validation.slug-is-unique'}
51
- )
52
- }
22
+ const { client, document, path, type } = context;
23
+ const schemaOptions = type?.options;
24
+ if (!document) {
25
+ throw new Error(`\`document\` was not provided in validation context.`);
26
+ }
27
+ if (!path) {
28
+ throw new Error(`\`path\` was not provided in validation context.`);
29
+ }
30
+ const disableArrayWarning = schemaOptions?.disableArrayWarning || false;
31
+ const { published, draft } = getDocumentIds(document._id);
32
+ const docType = document._type;
33
+ const atPath = serializePath(path.concat('current'));
34
+ if (!disableArrayWarning && atPath.includes('[]')) {
35
+ memoizedWarnOnArraySlug(serializePath(path));
36
+ }
37
+ const constraints = [
38
+ '_type == $docType',
39
+ `!(_id in [$draft, $published])`,
40
+ `${atPath} == $slug`,
41
+ ].join(' && ');
42
+ return client.fetch(`!defined(*[${constraints}][0]._id)`, {
43
+ docType,
44
+ draft,
45
+ published,
46
+ slug,
47
+ }, { tag: 'validation.slug-is-unique' });
48
+ };
53
49
  function warnOnArraySlug(serializedPath) {
54
- /* eslint-disable no-console */
55
- console.warn(
56
- [
57
- `Slug field at path ${serializedPath} is within an array and cannot be automatically checked for uniqueness`,
58
- `If you need to check for uniqueness, provide your own "isUnique" method`,
59
- `To disable this message, set \`disableArrayWarning: true\` on the slug \`options\` field`,
60
- ].join('\n')
61
- )
62
- /* eslint-enable no-console */
50
+ /* eslint-disable no-console */
51
+ console.warn([
52
+ `Slug field at path ${serializedPath} is within an array and cannot be automatically checked for uniqueness`,
53
+ `If you need to check for uniqueness, provide your own "isUnique" method`,
54
+ `To disable this message, set \`disableArrayWarning: true\` on the slug \`options\` field`,
55
+ ].join('\n'));
56
+ /* eslint-enable no-console */
63
57
  }
64
58
  /**
65
59
  * Validates slugs values by querying for uniqueness from the client.
@@ -68,22 +62,22 @@ function warnOnArraySlug(serializedPath) {
68
62
  * that's populated in `inferFromSchemaType` when the type name is `slug`
69
63
  */
70
64
  export const slugValidator = async (value, context) => {
71
- if (!value) {
72
- return true
73
- }
74
- if (typeof value !== 'object') {
75
- return 'Slug must be an object'
76
- }
77
- const slugValue = value.current
78
- if (!slugValue) {
79
- return 'Slug must have a value'
80
- }
81
- const options = context?.type?.options
82
- const isUnique = options?.isUnique || defaultIsUnique
83
- const wasUnique = await isUnique(slugValue, {...context, defaultIsUnique})
84
- if (wasUnique) {
85
- return true
86
- }
87
- return 'Slug is already in use'
88
- }
89
- //# sourceMappingURL=slugValidator.js.map
65
+ if (!value) {
66
+ return true;
67
+ }
68
+ if (typeof value !== 'object') {
69
+ return 'Slug must be an object';
70
+ }
71
+ const slugValue = value.current;
72
+ if (!slugValue) {
73
+ return 'Slug must have a value';
74
+ }
75
+ const options = context?.type?.options;
76
+ const isUnique = options?.isUnique || defaultIsUnique;
77
+ const wasUnique = await isUnique(slugValue, { ...context, defaultIsUnique });
78
+ if (wasUnique) {
79
+ return true;
80
+ }
81
+ return 'Slug is already in use';
82
+ };
83
+ //# sourceMappingURL=slugValidator.js.map
@@ -1,94 +1,94 @@
1
- import genericValidator from './genericValidator'
2
- const DUMMY_ORIGIN = 'http://sanity'
3
- const emailRegex =
4
- /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
5
- const isRelativeUrl = (url) => /^\.*\//.test(url)
1
+ import genericValidator from './genericValidator';
2
+ const DUMMY_ORIGIN = 'http://sanity';
3
+ const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
4
+ const isRelativeUrl = (url) => /^\.*\//.test(url);
6
5
  const stringValidators = {
7
- ...genericValidator,
8
- min: (minLength, value, message) => {
9
- if (!value || value.length >= minLength) {
10
- return true
11
- }
12
- return message || `Must be at least ${minLength} characters long`
13
- },
14
- max: (maxLength, value, message) => {
15
- if (!value || value.length <= maxLength) {
16
- return true
17
- }
18
- return message || `Must be at most ${maxLength} characters long`
19
- },
20
- length: (wantedLength, value, message) => {
21
- const strValue = value || ''
22
- if (strValue.length === wantedLength) {
23
- return true
24
- }
25
- return message || `Must be exactly ${wantedLength} characters long`
26
- },
27
- uri: (constraints, value, message) => {
28
- const strValue = value || ''
29
- const {options} = constraints
30
- const {allowCredentials, relativeOnly} = options
31
- const allowRelative = options.allowRelative || relativeOnly
32
- let url
33
- try {
34
- // WARNING: Safari checks for a given `base` param by looking at the length of arguments passed
35
- // to new URL(str, base), and will fail if invoked with new URL(strValue, undefined)
36
- url = allowRelative ? new URL(strValue, DUMMY_ORIGIN) : new URL(strValue)
37
- } catch (err) {
38
- return message || 'Not a valid URL'
39
- }
40
- if (relativeOnly && url.origin !== DUMMY_ORIGIN) {
41
- return message || 'Only relative URLs are allowed'
42
- }
43
- if (!allowRelative && url.origin === DUMMY_ORIGIN && isRelativeUrl(strValue)) {
44
- return message || 'Relative URLs are not allowed'
45
- }
46
- if (!allowCredentials && (url.username || url.password)) {
47
- return message || `Username/password not allowed`
48
- }
49
- const urlScheme = url.protocol.replace(/:$/, '')
50
- const matchesAllowedScheme = options.scheme.some((scheme) => scheme.test(urlScheme))
51
- if (!matchesAllowedScheme) {
52
- return message || 'Does not match allowed protocols/schemes'
53
- }
54
- return true
55
- },
56
- stringCasing: (casing, value, message) => {
57
- const strValue = value || ''
58
- if (casing === 'uppercase' && strValue !== strValue.toLocaleUpperCase()) {
59
- return message || `Must be all uppercase letters`
60
- }
61
- if (casing === 'lowercase' && strValue !== strValue.toLocaleLowerCase()) {
62
- return message || `Must be all lowercase letters`
63
- }
64
- return true
65
- },
66
- presence: (flag, value, message) => {
67
- if (flag === 'required' && !value) {
68
- return message || 'Required'
69
- }
70
- return true
71
- },
72
- regex: (options, value, message) => {
73
- const {pattern, name, invert} = options
74
- const regName = name || `"${pattern.toString()}"`
75
- const strValue = value || ''
76
- const matches = pattern.test(strValue)
77
- if ((!invert && !matches) || (invert && matches)) {
78
- const defaultMessage = invert
79
- ? `Should not match ${regName}-pattern`
80
- : `Does not match ${regName}-pattern`
81
- return message || defaultMessage
82
- }
83
- return true
84
- },
85
- email: (_unused, value, message) => {
86
- const strValue = `${value || ''}`.trim()
87
- if (!strValue || emailRegex.test(strValue)) {
88
- return true
89
- }
90
- return message || 'Must be a valid email address'
91
- },
92
- }
93
- export default stringValidators
94
- //# sourceMappingURL=stringValidator.js.map
6
+ ...genericValidator,
7
+ min: (minLength, value, message) => {
8
+ if (!value || value.length >= minLength) {
9
+ return true;
10
+ }
11
+ return message || `Must be at least ${minLength} characters long`;
12
+ },
13
+ max: (maxLength, value, message) => {
14
+ if (!value || value.length <= maxLength) {
15
+ return true;
16
+ }
17
+ return message || `Must be at most ${maxLength} characters long`;
18
+ },
19
+ length: (wantedLength, value, message) => {
20
+ const strValue = value || '';
21
+ if (strValue.length === wantedLength) {
22
+ return true;
23
+ }
24
+ return message || `Must be exactly ${wantedLength} characters long`;
25
+ },
26
+ uri: (constraints, value, message) => {
27
+ const strValue = value || '';
28
+ const { options } = constraints;
29
+ const { allowCredentials, relativeOnly } = options;
30
+ const allowRelative = options.allowRelative || relativeOnly;
31
+ let url;
32
+ try {
33
+ // WARNING: Safari checks for a given `base` param by looking at the length of arguments passed
34
+ // to new URL(str, base), and will fail if invoked with new URL(strValue, undefined)
35
+ url = allowRelative ? new URL(strValue, DUMMY_ORIGIN) : new URL(strValue);
36
+ }
37
+ catch (err) {
38
+ return message || 'Not a valid URL';
39
+ }
40
+ if (relativeOnly && url.origin !== DUMMY_ORIGIN) {
41
+ return message || 'Only relative URLs are allowed';
42
+ }
43
+ if (!allowRelative && url.origin === DUMMY_ORIGIN && isRelativeUrl(strValue)) {
44
+ return message || 'Relative URLs are not allowed';
45
+ }
46
+ if (!allowCredentials && (url.username || url.password)) {
47
+ return message || `Username/password not allowed`;
48
+ }
49
+ const urlScheme = url.protocol.replace(/:$/, '');
50
+ const matchesAllowedScheme = options.scheme.some((scheme) => scheme.test(urlScheme));
51
+ if (!matchesAllowedScheme) {
52
+ return message || 'Does not match allowed protocols/schemes';
53
+ }
54
+ return true;
55
+ },
56
+ stringCasing: (casing, value, message) => {
57
+ const strValue = value || '';
58
+ if (casing === 'uppercase' && strValue !== strValue.toLocaleUpperCase()) {
59
+ return message || `Must be all uppercase letters`;
60
+ }
61
+ if (casing === 'lowercase' && strValue !== strValue.toLocaleLowerCase()) {
62
+ return message || `Must be all lowercase letters`;
63
+ }
64
+ return true;
65
+ },
66
+ presence: (flag, value, message) => {
67
+ if (flag === 'required' && !value) {
68
+ return message || 'Required';
69
+ }
70
+ return true;
71
+ },
72
+ regex: (options, value, message) => {
73
+ const { pattern, name, invert } = options;
74
+ const regName = name || `"${pattern.toString()}"`;
75
+ const strValue = value || '';
76
+ const matches = pattern.test(strValue);
77
+ if ((!invert && !matches) || (invert && matches)) {
78
+ const defaultMessage = invert
79
+ ? `Should not match ${regName}-pattern`
80
+ : `Does not match ${regName}-pattern`;
81
+ return message || defaultMessage;
82
+ }
83
+ return true;
84
+ },
85
+ email: (_unused, value, message) => {
86
+ const strValue = `${value || ''}`.trim();
87
+ if (!strValue || emailRegex.test(strValue)) {
88
+ return true;
89
+ }
90
+ return message || 'Must be a valid email address';
91
+ },
92
+ };
93
+ export default stringValidators;
94
+ //# sourceMappingURL=stringValidator.js.map
@@ -1,2 +1,2 @@
1
- export {}
2
- //# sourceMappingURL=array.test.d.ts.map
1
+ export {};
2
+ //# sourceMappingURL=array.test.d.ts.map
@@ -1,79 +1,55 @@
1
- import {Rule} from '../src'
2
- const context = {client: {}}
1
+ import { Rule } from '../src';
2
+ const context = { client: {} };
3
3
  describe('array', () => {
4
- test('required constraint', async () => {
5
- const rule = Rule.array().required()
6
- await expect(rule.validate(null, context)).resolves.toMatchSnapshot('required: null')
7
- await expect(rule.validate(undefined, context)).resolves.toMatchSnapshot('required: undefined')
8
- await expect(rule.validate([], context)).resolves.toMatchSnapshot('required: empty array')
9
- await expect(rule.validate(['hei'], context)).resolves.toMatchSnapshot('required: valid')
10
- })
11
- test('min length constraint', async () => {
12
- const rule = Rule.array().min(2)
13
- await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('min length: too short')
14
- await expect(rule.validate(['a', 'b', 'c'], context)).resolves.toMatchSnapshot(
15
- 'min length: valid'
16
- )
17
- })
18
- test('max length constraint', async () => {
19
- const rule = Rule.array().max(2)
20
- await expect(rule.validate(['a', 'b', 'c', 'd'], context)).resolves.toMatchSnapshot(
21
- 'max length: too long'
22
- )
23
- await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('max length: valid')
24
- })
25
- test('exact length constraint', async () => {
26
- const rule = Rule.array().length(2)
27
- await expect(rule.validate(['a', 'b', 'c'], context)).resolves.toMatchSnapshot(
28
- 'exact length: too long'
29
- )
30
- await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('exact length: too short')
31
- await expect(rule.validate(['a', 'b'], context)).resolves.toMatchSnapshot('exact length: valid')
32
- })
33
- test('unique constraint (default, simple values)', async () => {
34
- const rule = Rule.array().unique()
35
- await expect(rule.validate(['a', 'b', 'c', 'd'], context)).resolves.toMatchSnapshot(
36
- 'simple unique: valid'
37
- )
38
- await expect(rule.validate(['a', 'b', 'c', 'a'], context)).resolves.toMatchSnapshot(
39
- 'simple unique: duplicates'
40
- )
41
- })
42
- test('unique constraint (default, object values)', async () => {
43
- const rule = Rule.array().unique()
44
- const ref = (id) => ({_ref: id, _type: 'reference'})
45
- await expect(rule.validate(['a', 'b', 'c', 'd'].map(ref), context)).resolves.toMatchSnapshot(
46
- 'object unique: valid'
47
- )
48
- await expect(rule.validate(['a', 'b', 'c', 'a'].map(ref), context)).resolves.toMatchSnapshot(
49
- 'object unique: duplicates'
50
- )
51
- })
52
- test('unique constraint (default, array values)', async () => {
53
- const rule = Rule.array().unique()
54
- const refArr = (id) => [{_ref: id, _type: 'reference'}]
55
- await expect(rule.validate(['a', 'b', 'c', 'd'].map(refArr), context)).resolves.toMatchSnapshot(
56
- 'array unique: valid'
57
- )
58
- await expect(rule.validate(['a', 'a', 'c', 'd'].map(refArr), context)).resolves.toMatchSnapshot(
59
- 'array unique: duplicates'
60
- )
61
- })
62
- test('unique constraint (default, bool values)', async () => {
63
- const rule = Rule.array().unique()
64
- await expect(rule.validate([true, false], context)).resolves.toMatchSnapshot(
65
- 'boolean unique: valid'
66
- )
67
- await expect(rule.validate([false, true, false], context)).resolves.toMatchSnapshot(
68
- 'boolean unique: duplicates'
69
- )
70
- })
71
- test('unique constraint (default, numeric values)', async () => {
72
- const rule = Rule.array().unique()
73
- await expect(rule.validate([1, 3], context)).resolves.toMatchSnapshot('numeric unique: valid')
74
- await expect(rule.validate([3, 1, 3], context)).resolves.toMatchSnapshot(
75
- 'numeric unique: duplicates'
76
- )
77
- })
78
- })
79
- //# sourceMappingURL=array.test.js.map
4
+ test('required constraint', async () => {
5
+ const rule = Rule.array().required();
6
+ await expect(rule.validate(null, context)).resolves.toMatchSnapshot('required: null');
7
+ await expect(rule.validate(undefined, context)).resolves.toMatchSnapshot('required: undefined');
8
+ await expect(rule.validate([], context)).resolves.toMatchSnapshot('required: empty array');
9
+ await expect(rule.validate(['hei'], context)).resolves.toMatchSnapshot('required: valid');
10
+ });
11
+ test('min length constraint', async () => {
12
+ const rule = Rule.array().min(2);
13
+ await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('min length: too short');
14
+ await expect(rule.validate(['a', 'b', 'c'], context)).resolves.toMatchSnapshot('min length: valid');
15
+ });
16
+ test('max length constraint', async () => {
17
+ const rule = Rule.array().max(2);
18
+ await expect(rule.validate(['a', 'b', 'c', 'd'], context)).resolves.toMatchSnapshot('max length: too long');
19
+ await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('max length: valid');
20
+ });
21
+ test('exact length constraint', async () => {
22
+ const rule = Rule.array().length(2);
23
+ await expect(rule.validate(['a', 'b', 'c'], context)).resolves.toMatchSnapshot('exact length: too long');
24
+ await expect(rule.validate(['a'], context)).resolves.toMatchSnapshot('exact length: too short');
25
+ await expect(rule.validate(['a', 'b'], context)).resolves.toMatchSnapshot('exact length: valid');
26
+ });
27
+ test('unique constraint (default, simple values)', async () => {
28
+ const rule = Rule.array().unique();
29
+ await expect(rule.validate(['a', 'b', 'c', 'd'], context)).resolves.toMatchSnapshot('simple unique: valid');
30
+ await expect(rule.validate(['a', 'b', 'c', 'a'], context)).resolves.toMatchSnapshot('simple unique: duplicates');
31
+ });
32
+ test('unique constraint (default, object values)', async () => {
33
+ const rule = Rule.array().unique();
34
+ const ref = (id) => ({ _ref: id, _type: 'reference' });
35
+ await expect(rule.validate(['a', 'b', 'c', 'd'].map(ref), context)).resolves.toMatchSnapshot('object unique: valid');
36
+ await expect(rule.validate(['a', 'b', 'c', 'a'].map(ref), context)).resolves.toMatchSnapshot('object unique: duplicates');
37
+ });
38
+ test('unique constraint (default, array values)', async () => {
39
+ const rule = Rule.array().unique();
40
+ const refArr = (id) => [{ _ref: id, _type: 'reference' }];
41
+ await expect(rule.validate(['a', 'b', 'c', 'd'].map(refArr), context)).resolves.toMatchSnapshot('array unique: valid');
42
+ await expect(rule.validate(['a', 'a', 'c', 'd'].map(refArr), context)).resolves.toMatchSnapshot('array unique: duplicates');
43
+ });
44
+ test('unique constraint (default, bool values)', async () => {
45
+ const rule = Rule.array().unique();
46
+ await expect(rule.validate([true, false], context)).resolves.toMatchSnapshot('boolean unique: valid');
47
+ await expect(rule.validate([false, true, false], context)).resolves.toMatchSnapshot('boolean unique: duplicates');
48
+ });
49
+ test('unique constraint (default, numeric values)', async () => {
50
+ const rule = Rule.array().unique();
51
+ await expect(rule.validate([1, 3], context)).resolves.toMatchSnapshot('numeric unique: valid');
52
+ await expect(rule.validate([3, 1, 3], context)).resolves.toMatchSnapshot('numeric unique: duplicates');
53
+ });
54
+ });
55
+ //# sourceMappingURL=array.test.js.map
@@ -1,2 +1,2 @@
1
- export {}
2
- //# sourceMappingURL=children.test.d.ts.map
1
+ export {};
2
+ //# sourceMappingURL=children.test.d.ts.map