Skip to content

Commit 4692a70

Browse files
Chuanyi SuChuanyi Su
authored andcommitted
test(sdk): add PolyVValidationError tests, improve coverage to 100%
1 parent 986ee6d commit 4692a70

1 file changed

Lines changed: 155 additions & 0 deletions

File tree

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { PolyVValidationError } from './polyv-validation-error.js';
3+
4+
describe('PolyVValidationError', () => {
5+
describe('constructor', () => {
6+
it('should create with message only', () => {
7+
const err = new PolyVValidationError('test error');
8+
expect(err.message).toBe('test error');
9+
expect(err.name).toBe('PolyVValidationError');
10+
expect(err.code).toBe('ERR_VALIDATION');
11+
expect(err.field).toBeUndefined();
12+
expect(err.invalidValue).toBeUndefined();
13+
expect(err.constraints).toBeUndefined();
14+
});
15+
16+
it('should create with field', () => {
17+
const err = new PolyVValidationError('test', 'myField');
18+
expect(err.field).toBe('myField');
19+
expect(err.details).toEqual({ field: 'myField' });
20+
});
21+
22+
it('should create with invalidValue', () => {
23+
const err = new PolyVValidationError('test', 'myField', 'bad');
24+
expect(err.invalidValue).toBe('bad');
25+
expect(err.details).toEqual({ field: 'myField', invalidValue: 'bad' });
26+
});
27+
28+
it('should create with constraints', () => {
29+
const constraints = { min: 1, max: 10 };
30+
const err = new PolyVValidationError('test', 'n', 0, constraints);
31+
expect(err.constraints).toEqual(constraints);
32+
});
33+
34+
it('should create with custom code', () => {
35+
const err = new PolyVValidationError('test', undefined, undefined, undefined, 'CUSTOM');
36+
expect(err.code).toBe('CUSTOM');
37+
});
38+
39+
it('should not set details when no extra fields', () => {
40+
const err = new PolyVValidationError('simple error');
41+
expect(err.details).toBeUndefined();
42+
});
43+
44+
it('should be instanceof PolyVValidationError', () => {
45+
const err = new PolyVValidationError('test');
46+
expect(err).toBeInstanceOf(PolyVValidationError);
47+
});
48+
});
49+
50+
describe('toJSON', () => {
51+
it('should serialize with all fields', () => {
52+
const err = new PolyVValidationError('test', 'f', 'v', { min: 1 });
53+
const json = err.toJSON();
54+
expect(json).toEqual({
55+
name: 'PolyVValidationError',
56+
message: 'test',
57+
code: 'ERR_VALIDATION',
58+
details: undefined,
59+
field: 'f',
60+
invalidValue: 'v',
61+
constraints: { min: 1 },
62+
});
63+
});
64+
65+
it('should serialize minimal error', () => {
66+
const err = new PolyVValidationError('minimal');
67+
const json = err.toJSON();
68+
expect(json.field).toBeUndefined();
69+
expect(json.invalidValue).toBeUndefined();
70+
expect(json.constraints).toBeUndefined();
71+
});
72+
});
73+
74+
describe('toString', () => {
75+
it('should include field when present', () => {
76+
const err = new PolyVValidationError('bad', 'myField');
77+
expect(err.toString()).toBe('PolyVValidationError [field=myField]: bad');
78+
});
79+
80+
it('should exclude field when absent', () => {
81+
const err = new PolyVValidationError('bad');
82+
expect(err.toString()).toBe('PolyVValidationError: bad');
83+
});
84+
});
85+
86+
describe('static factory methods', () => {
87+
it('required() should create required error', () => {
88+
const err = PolyVValidationError.required('name');
89+
expect(err.message).toBe('name is required');
90+
expect(err.field).toBe('name');
91+
expect(err.code).toBe('ERR_REQUIRED');
92+
});
93+
94+
it('invalidType() should create type error', () => {
95+
const err = PolyVValidationError.invalidType('age', 'number', 'abc');
96+
expect(err.message).toContain('must be of type number');
97+
expect(err.field).toBe('age');
98+
expect(err.invalidValue).toBe('abc');
99+
expect(err.constraints).toEqual({ expectedType: 'number' });
100+
});
101+
102+
it('outOfRange() with min and max', () => {
103+
const err = PolyVValidationError.outOfRange('val', 15, { min: 1, max: 10 });
104+
expect(err.message).toContain('between 1 and 10');
105+
expect(err.invalidValue).toBe(15);
106+
});
107+
108+
it('outOfRange() with only min', () => {
109+
const err = PolyVValidationError.outOfRange('val', -1, { min: 0 });
110+
expect(err.message).toContain('at least 0');
111+
});
112+
113+
it('outOfRange() with only max', () => {
114+
const err = PolyVValidationError.outOfRange('val', 100, { max: 50 });
115+
expect(err.message).toContain('at most 50');
116+
});
117+
118+
it('outOfRange() with no constraints', () => {
119+
const err = PolyVValidationError.outOfRange('val', 5, {});
120+
expect(err.message).toContain('out of range');
121+
});
122+
123+
it('patternMismatch() should create pattern error', () => {
124+
const pattern = /^\d+$/;
125+
const err = PolyVValidationError.patternMismatch('code', 'abc', pattern);
126+
expect(err.message).toContain('does not match expected pattern');
127+
expect(err.field).toBe('code');
128+
expect(err.constraints).toEqual({ pattern: '^\\d+$' });
129+
});
130+
131+
it('aggregate() should return null for empty array', () => {
132+
expect(PolyVValidationError.aggregate([])).toBeNull();
133+
});
134+
135+
it('aggregate() should aggregate multiple errors', () => {
136+
const errors = [
137+
PolyVValidationError.required('name'),
138+
PolyVValidationError.required('email'),
139+
];
140+
const agg = PolyVValidationError.aggregate(errors);
141+
expect(agg).not.toBeNull();
142+
expect(agg!.message).toContain('2 error(s)');
143+
expect(agg!.errors).toHaveLength(2);
144+
expect(agg!.errors![0].field).toBe('name');
145+
expect(agg!.errors![1].field).toBe('email');
146+
});
147+
148+
it('aggregate() should aggregate single error', () => {
149+
const errors = [PolyVValidationError.required('name')];
150+
const agg = PolyVValidationError.aggregate(errors);
151+
expect(agg!.message).toContain('1 error(s)');
152+
expect(agg!.errors).toHaveLength(1);
153+
});
154+
});
155+
});

0 commit comments

Comments
 (0)