Skip to content

Commit

Permalink
Format invalid_literal issues
Browse files Browse the repository at this point in the history
  • Loading branch information
lo1tuma committed Mar 20, 2024
1 parent ca68c87 commit 48cc42e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
14 changes: 14 additions & 0 deletions integration-tests/zod-error-formatter/literals.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { test } from '@sondr3/minitest';
import assert from 'node:assert';
import { z } from 'zod';
import { safeParse } from '../../source/zod-error-formatter/formatter.js';

test('formats messages for invalid string literals correctly', () => {
const schema = z.literal('foo');
const result = safeParse(schema, 'bar');

assert.strictEqual(result.success, false);
assert.deepStrictEqual(result.error.issues, [
'invalid literal: expected "foo", but got string'
]);
});
11 changes: 11 additions & 0 deletions source/zod-error-formatter/format-issue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,14 @@ test('returns the formatted issue when an invalid_type issue is given', () => {
});
assert.strictEqual(formattedIssue, 'at foo: expected nan, but got float');
});

test('returns the formatted issue when an invalid_literal issue is given', () => {
const formattedIssue = formatIssue({
code: 'invalid_literal',
message: '',
expected: 'foo',
received: 'bar',
path: ['foo']
});
assert.strictEqual(formattedIssue, 'at foo: invalid literal: expected "foo", but got string');
});
4 changes: 3 additions & 1 deletion source/zod-error-formatter/format-issue.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ZodIssue, ZodIssueCode } from 'zod';
import { formatInvalidLiteralIssueMessage } from './issue-specific/invalid-literal.js';
import { formatInvalidTypeIssueMessage } from './issue-specific/invalid-type.js';
import { formatPath, isNonEmptyPath } from './path.js';

Expand All @@ -9,7 +10,8 @@ type FormatterMap = {
};

const issueCodeToFormatterMap: FormatterMap = {
invalid_type: formatInvalidTypeIssueMessage
invalid_type: formatInvalidTypeIssueMessage,
invalid_literal: formatInvalidLiteralIssueMessage
};

export function formatIssue(issue: ZodIssue): string {
Expand Down
47 changes: 47 additions & 0 deletions source/zod-error-formatter/issue-specific/invalid-literal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { test } from '@sondr3/minitest';
import assert from 'node:assert';
import { formatInvalidLiteralIssueMessage } from './invalid-literal.js';

test('formats the issue by using the expected value as is and only the type of the received value', () => {
const message = formatInvalidLiteralIssueMessage({
code: 'invalid_literal',
path: [],
message: '',
expected: 42,
received: { foo: 'bar' }
});
assert.strictEqual(message, 'invalid literal: expected 42, but got object');
});

test('wraps the expected value in double quotes when it is a string', () => {
const message = formatInvalidLiteralIssueMessage({
code: 'invalid_literal',
path: [],
message: '',
expected: 'foo',
received: null
});
assert.strictEqual(message, 'invalid literal: expected "foo", but got null');
});

test('correctly works with undefined as expected value', () => {
const message = formatInvalidLiteralIssueMessage({
code: 'invalid_literal',
path: [],
message: '',
expected: undefined,
received: null
});
assert.strictEqual(message, 'invalid literal: expected undefined, but got null');
});

test('correctly works with bigint as expected value', () => {
const message = formatInvalidLiteralIssueMessage({
code: 'invalid_literal',
path: [],
message: '',
expected: 9_007_199_254_740_993n,
received: null
});
assert.strictEqual(message, 'invalid literal: expected 9007199254740993, but got null');
});
14 changes: 14 additions & 0 deletions source/zod-error-formatter/issue-specific/invalid-literal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { getParsedType, type Primitive, type ZodInvalidLiteralIssue } from 'zod';

function formatPrimitiveValue(value: Primitive): string {
if (typeof value === 'bigint') {
return value.toString();
}
return JSON.stringify(value);
}

export function formatInvalidLiteralIssueMessage(issue: ZodInvalidLiteralIssue): string {
const received = getParsedType(issue.received);
const expected = formatPrimitiveValue(issue.expected as Primitive);
return `invalid literal: expected ${expected}, but got ${received}`;
}

0 comments on commit 48cc42e

Please sign in to comment.