diff --git a/library/CHANGELOG.md b/library/CHANGELOG.md index c7f435d64..e67929991 100644 --- a/library/CHANGELOG.md +++ b/library/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to the library will be documented in this file. ## vX.X.X (Month DD, YYYY) - Add `cuid2` validation (pull request #130) +- Fix bug in `strict` and `strictAsync` method for optional keys (issue #131) ## v0.13.1 (August 23, 2023) diff --git a/library/src/methods/strict/strict.test.ts b/library/src/methods/strict/strict.test.ts index 6456c7e62..5c4f84367 100644 --- a/library/src/methods/strict/strict.test.ts +++ b/library/src/methods/strict/strict.test.ts @@ -1,20 +1,37 @@ import { describe, expect, test } from 'vitest'; -import { number, object, string } from '../../schemas/index.ts'; -import { parse } from '../parse/index.ts'; +import { number, object, optional, string } from '../../schemas/index.ts'; import { strict } from './strict.ts'; describe('strict', () => { test('should detect unknown keys', () => { - const schema = strict(object({ key1: string(), key2: number() })); + const schema = strict(object({ key1: string(), key2: optional(number()) })); const input1 = { key1: 'test', key2: 123 }; - const output1 = parse(schema, input1); - expect(output1).toEqual(input1); - - const keysError = 'Invalid keys'; - const input2 = { key1: 'test', key2: 123, key3: 'unknown' }; - expect(() => parse(schema, input2)).toThrowError(keysError); - const input3 = { key1: 'test', key2: 123, key3: 'unknown', key4: 123 }; - expect(() => parse(schema, input3)).toThrowError(keysError); + const result1 = schema._parse(input1); + expect(result1.output).toEqual(input1); + + const input2 = { key1: 'test', key2: undefined }; + const result2 = schema._parse(input2); + expect(result2.output).toEqual(input2); + + const input3 = { key1: 'test' }; + const result3 = schema._parse(input3); + expect(result3.output).toEqual(input3); + + const input4 = { key1: 'test', key2: 123, key3: '' }; + const result4 = schema._parse(input4); + expect(result4.issues?.length).toBe(1); + + const input5 = { key1: 'test', key2: undefined, key3: '' }; + const result5 = schema._parse(input5); + expect(result5.issues?.length).toBe(1); + + const input6 = { key1: 'test', key3: '' }; + const result6 = schema._parse(input6); + expect(result6.issues?.length).toBe(1); + + const input7 = { key1: 'test', key2: 123, key3: '', key4: '' }; + const result7 = schema._parse(input7); + expect(result7.issues?.length).toBe(1); }); }); diff --git a/library/src/methods/strict/strict.ts b/library/src/methods/strict/strict.ts index 8e244e354..da444e152 100644 --- a/library/src/methods/strict/strict.ts +++ b/library/src/methods/strict/strict.ts @@ -28,9 +28,7 @@ export function strict>( _parse(input, info) { const result = schema._parse(input, info); return !result.issues && - // Check length of input and output keys - Object.keys(input as object).length !== - Object.keys(result.output).length + Object.keys(input as object).some((key) => !(key in result.output)) ? getIssues(info, 'object', 'strict', error || 'Invalid keys', input) : result; }, diff --git a/library/src/methods/strict/strictAsync.test.ts b/library/src/methods/strict/strictAsync.test.ts index 149872020..1638c2ef5 100644 --- a/library/src/methods/strict/strictAsync.test.ts +++ b/library/src/methods/strict/strictAsync.test.ts @@ -1,20 +1,39 @@ import { describe, expect, test } from 'vitest'; -import { number, objectAsync, string } from '../../schemas/index.ts'; -import { parseAsync } from '../parse/index.ts'; +import { number, objectAsync, optional, string } from '../../schemas/index.ts'; import { strictAsync } from './strictAsync.ts'; describe('strict', () => { test('should detect unknown keys', async () => { - const schema = strictAsync(objectAsync({ key1: string(), key2: number() })); + const schema = strictAsync( + objectAsync({ key1: string(), key2: optional(number()) }) + ); const input1 = { key1: 'test', key2: 123 }; - const output1 = await parseAsync(schema, input1); - expect(output1).toEqual(input1); - - const keysError = 'Invalid keys'; - const input2 = { key1: 'test', key2: 123, key3: 'unknown' }; - await expect(parseAsync(schema, input2)).rejects.toThrowError(keysError); - const input3 = { key1: 'test', key2: 123, key3: 'unknown', key4: 123 }; - await expect(parseAsync(schema, input3)).rejects.toThrowError(keysError); + const result1 = await schema._parse(input1); + expect(result1.output).toEqual(input1); + + const input2 = { key1: 'test', key2: undefined }; + const result2 = await schema._parse(input2); + expect(result2.output).toEqual(input2); + + const input3 = { key1: 'test' }; + const result3 = await schema._parse(input3); + expect(result3.output).toEqual(input3); + + const input4 = { key1: 'test', key2: 123, key3: '' }; + const result4 = await schema._parse(input4); + expect(result4.issues?.length).toBe(1); + + const input5 = { key1: 'test', key2: undefined, key3: '' }; + const result5 = await schema._parse(input5); + expect(result5.issues?.length).toBe(1); + + const input6 = { key1: 'test', key3: '' }; + const result6 = await schema._parse(input6); + expect(result6.issues?.length).toBe(1); + + const input7 = { key1: 'test', key2: 123, key3: '', key4: '' }; + const result7 = await schema._parse(input7); + expect(result7.issues?.length).toBe(1); }); }); diff --git a/library/src/methods/strict/strictAsync.ts b/library/src/methods/strict/strictAsync.ts index d10e38b36..17eb24b68 100644 --- a/library/src/methods/strict/strictAsync.ts +++ b/library/src/methods/strict/strictAsync.ts @@ -28,9 +28,7 @@ export function strictAsync>( async _parse(input, info) { const result = await schema._parse(input, info); return !result.issues && - // Check length of input and output keys - Object.keys(input as object).length !== - Object.keys(result.output).length + Object.keys(input as object).some((key) => !(key in result.output)) ? getIssues(info, 'object', 'strict', error || 'Invalid keys', input) : result; }, diff --git a/website/src/routes/guides/(main-concepts)/schemas/index.mdx b/website/src/routes/guides/(main-concepts)/schemas/index.mdx index b8a3a2bb8..d51778439 100644 --- a/website/src/routes/guides/(main-concepts)/schemas/index.mdx +++ b/website/src/routes/guides/(main-concepts)/schemas/index.mdx @@ -57,7 +57,7 @@ const LoginSchema = object({ ]), password: string('Your password must be a string.', [ minLength(1, 'Please enter your password.'), - minLength(8, 'You password must have 8 characters or more.'), + minLength(8, 'Your password must have 8 characters or more.'), ]), }); ```