diff --git a/src/fields/validations.ts b/src/fields/validations.ts index d6c866a9b..1220062bc 100644 --- a/src/fields/validations.ts +++ b/src/fields/validations.ts @@ -30,11 +30,11 @@ export const number: Validate = (value: string, { return 'Please enter a valid number.'; } - if (max && parsedValue > max) { + if (typeof max === 'number' && parsedValue > max) { return `"${value}" is greater than the max allowed value of ${max}.`; } - if (min && parsedValue < min) { + if (typeof min === 'number' && parsedValue < min) { return `"${value}" is less than the min allowed value of ${min}.`; } diff --git a/test/fields/collections/Number/index.ts b/test/fields/collections/Number/index.ts new file mode 100644 index 000000000..34bc86a3a --- /dev/null +++ b/test/fields/collections/Number/index.ts @@ -0,0 +1,63 @@ +import type { CollectionConfig } from '../../../../src/collections/config/types'; + +export const defaultNumber = 5; + +const NumberFields: CollectionConfig = { + slug: 'number-fields', + admin: { + useAsTitle: 'number', + }, + fields: [ + { + name: 'number', + type: 'number', + }, + { + name: 'min', + type: 'number', + min: 10, + }, + { + name: 'max', + type: 'number', + max: 10, + }, + { + name: 'positiveNumber', + type: 'number', + min: 0, + }, + { + name: 'negativeNumber', + type: 'number', + max: 0, + }, + { + name: 'decimalMin', + type: 'number', + min: 0.5, + }, + { + name: 'decimalMax', + type: 'number', + max: 0.5, + }, + { + name: 'defaultNumber', + type: 'number', + defaultValue: defaultNumber, + }, + ], +}; + +export const numberDoc = { + number: 5, + min: 15, + max: 5, + positiveNumber: 5, + negativeNumber: -5, + decimalMin: 1.25, + decimalMax: 0.25, +}; + +export default NumberFields; diff --git a/test/fields/config.ts b/test/fields/config.ts index cb6128c6b..f361cef2d 100644 --- a/test/fields/config.ts +++ b/test/fields/config.ts @@ -15,6 +15,7 @@ import GroupFields, { groupDoc } from './collections/Group'; import getFileByPath from '../../src/uploads/getFileByPath'; import Uploads, { uploadsDoc } from './collections/Upload'; import IndexedFields from './collections/Indexed'; +import NumberFields, { numberDoc } from './collections/Number'; export default buildConfig({ admin: { @@ -40,6 +41,7 @@ export default buildConfig({ SelectFields, TabsFields, TextFields, + NumberFields, Uploads, IndexedFields, ], @@ -85,5 +87,7 @@ export default buildConfig({ richTextDocWithRelationship.richText[richTextUploadIndex].value = { id: createdUploadDoc.id }; await payload.create({ collection: 'rich-text-fields', data: richTextDocWithRelationship }); + + await payload.create({ collection: 'number-fields', data: numberDoc }); }, }); diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts index 48ac06067..660b33bd4 100644 --- a/test/fields/int.spec.ts +++ b/test/fields/int.spec.ts @@ -4,11 +4,12 @@ import { RESTClient } from '../helpers/rest'; import config from '../uploads/config'; import payload from '../../src'; import { pointDoc } from './collections/Point'; -import type { ArrayField, BlockField, GroupField } from './payload-types'; +import type { ArrayField, GroupField } from './payload-types'; import { arrayFieldsSlug, arrayDefaultValue, arrayDoc } from './collections/Array'; import { groupFieldsSlug, groupDefaultChild, groupDefaultValue, groupDoc } from './collections/Group'; import { defaultText } from './collections/Text'; import { blocksFieldSeedData } from './collections/Blocks'; +import { defaultNumber, numberDoc } from './collections/Number'; let client; @@ -38,6 +39,79 @@ describe('Fields', () => { }); }); + describe('number', () => { + let doc; + beforeAll(async () => { + doc = await payload.create({ + collection: 'number-fields', + data: numberDoc, + }); + }); + + it('creates with default values', async () => { + expect(doc.number).toEqual(numberDoc.number); + expect(doc.min).toEqual(numberDoc.min); + expect(doc.max).toEqual(numberDoc.max); + expect(doc.positiveNumber).toEqual(numberDoc.positiveNumber); + expect(doc.negativeNumber).toEqual(numberDoc.negativeNumber); + expect(doc.decimalMin).toEqual(numberDoc.decimalMin); + expect(doc.decimalMax).toEqual(numberDoc.decimalMax); + expect(doc.defaultNumber).toEqual(defaultNumber); + }); + + it('should not create number below minimum', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + min: 5, + }, + })).rejects.toThrow('The following field is invalid: min'); + }); + it('should not create number above max', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + max: 15, + }, + })).rejects.toThrow('The following field is invalid: max'); + }); + + it('should not create number below 0', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + positiveNumber: -5, + }, + })).rejects.toThrow('The following field is invalid: positiveNumber'); + }); + + it('should not create number above 0', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + negativeNumber: 5, + }, + })).rejects.toThrow('The following field is invalid: negativeNumber'); + }); + it('should not create a decimal number below min', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + decimalMin: -0.25, + }, + })).rejects.toThrow('The following field is invalid: decimalMin'); + }); + + it('should not create a decimal number above max', async () => { + await expect(async () => payload.create({ + collection: 'number-fields', + data: { + decimalMax: 1.5, + }, + })).rejects.toThrow('The following field is invalid: decimalMax'); + }); + }); + describe('indexes', () => { let indexes; const definitions: Record = {}; diff --git a/test/fields/payload-types.ts b/test/fields/payload-types.ts index e1abaf44b..7b0f6cbf5 100644 --- a/test/fields/payload-types.ts +++ b/test/fields/payload-types.ts @@ -221,6 +221,8 @@ export interface TabsField { group: { number: number; }; + textInRow: string; + numberInRow: number; textarea?: string; anotherText: string; createdAt: string; @@ -238,17 +240,58 @@ export interface TextField { createdAt: string; updatedAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "number-fields". + */ +export interface NumberField { + id: string; + number?: number; + min?: number; + max?: number; + positiveNumber?: number; + negativeNumber?: number; + decimalMin?: number; + decimalMax?: number; + defaultNumber?: number; + createdAt: string; + updatedAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "uploads". */ export interface Upload { id: string; + text?: string; url?: string; filename?: string; mimeType?: string; filesize?: number; - text?: string; + createdAt: string; + updatedAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "indexed-fields". + */ +export interface IndexedField { + id: string; + text: string; + uniqueText?: string; + /** + * @minItems 2 + * @maxItems 2 + */ + point?: [number, number]; + group: { + localizedUnique?: string; + /** + * @minItems 2 + * @maxItems 2 + */ + point?: [number, number]; + }; createdAt: string; updatedAt: string; }