Skip to content

Commit 3b0227e

Browse files
Copilotstreamich
andcommitted
feat: implement comprehensive test fixtures using type builder
Co-authored-by: streamich <[email protected]>
1 parent c02ce75 commit 3b0227e

File tree

1 file changed

+246
-42
lines changed

1 file changed

+246
-42
lines changed

src/__tests__/fixtures.ts

Lines changed: 246 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,261 @@
11
/**
2-
* Fixture schemas for testing random value generation.
3-
* These schemas represent different JSON Type configurations that can be used
4-
* across multiple test modules.
2+
* Fixture schemas for testing using the type builder.
3+
* These schemas represent realistic scenarios covering all node types.
54
*/
65

7-
import {s} from '../schema';
6+
import {t} from '../type';
87

98
/**
10-
* Basic primitive type schemas
9+
* User profile schema with nested objects and optional fields
10+
*/
11+
export const User = t
12+
.object({
13+
id: t.str,
14+
name: t.object({
15+
first: t.str,
16+
last: t.str,
17+
}),
18+
email: t.String({format: 'ascii'}),
19+
age: t.Number({gte: 0, lte: 150}),
20+
verified: t.bool,
21+
})
22+
.opt('avatar', t.String({format: 'ascii'}));
23+
24+
/**
25+
* Product catalog schema with arrays and formatted numbers
26+
*/
27+
export const Product = t.Object(
28+
t.prop('id', t.String({format: 'ascii'})),
29+
t.prop('name', t.String({min: 1, max: 100})),
30+
t.prop('price', t.Number({format: 'f64', gte: 0})),
31+
t.prop('inStock', t.bool),
32+
t.prop('categories', t.Array(t.str, {min: 1})),
33+
t.prop('tags', t.Array(t.str)),
34+
t.propOpt('description', t.String({max: 1000})),
35+
t.propOpt('discount', t.Number({gte: 0, lte: 1})),
36+
);
37+
38+
/**
39+
* Blog post schema with timestamps and rich content
40+
*/
41+
export const BlogPost = t.Object(
42+
t.prop('id', t.str),
43+
t.prop('title', t.String({min: 1, max: 200})),
44+
t.prop('content', t.str),
45+
t.prop('author', t.Ref<typeof User>('User')),
46+
t.prop('publishedAt', t.Number({format: 'u64'})),
47+
t.prop('status', t.enum('draft', 'published', 'archived')),
48+
t.propOpt('updatedAt', t.Number({format: 'u64'})),
49+
t.propOpt('tags', t.Array(t.str)),
50+
);
51+
52+
/**
53+
* API response schema with discriminated unions
54+
*/
55+
export const ApiResponse = t.Or(
56+
t.object({
57+
success: t.Const(true),
58+
data: t.any,
59+
timestamp: t.Number({format: 'u64'}),
60+
}),
61+
t.object({
62+
success: t.Const(false),
63+
error: t.object({
64+
code: t.String({format: 'ascii'}),
65+
message: t.str,
66+
}),
67+
timestamp: t.Number({format: 'u64'}),
68+
}),
69+
);
70+
71+
/**
72+
* File metadata schema with binary data
73+
*/
74+
export const FileMetadata = t.Object(
75+
t.prop('name', t.str),
76+
t.prop('size', t.Number({format: 'u64', gte: 0})),
77+
t.prop('mimeType', t.str),
78+
t.prop('data', t.Binary(t.any)),
79+
t.prop('checksum', t.String({format: 'ascii', min: 64, max: 64})),
80+
t.prop('uploadedAt', t.Number({format: 'u64'})),
81+
t.propOpt('metadata', t.Map(t.str)),
82+
);
83+
84+
/**
85+
* Configuration schema with maps and default values
86+
*/
87+
export const Configuration = t.Object(
88+
t.prop('environment', t.enum('development', 'staging', 'production')),
89+
t.prop(
90+
'database',
91+
t.object({
92+
host: t.str,
93+
port: t.Number({format: 'u16', gte: 1, lte: 65535}),
94+
name: t.str,
95+
}),
96+
),
97+
t.prop('features', t.Map(t.bool)),
98+
t.prop('secrets', t.Map(t.str)),
99+
t.propOpt(
100+
'logging',
101+
t.object({
102+
level: t.enum('debug', 'info', 'warn', 'error'),
103+
output: t.str,
104+
}),
105+
),
106+
);
107+
108+
/**
109+
* Event data schema with tuples and coordinates
110+
*/
111+
export const Event = t.Object(
112+
t.prop('id', t.String({format: 'ascii'})),
113+
t.prop('type', t.enum('click', 'view', 'purchase', 'signup')),
114+
t.prop('timestamp', t.Number({format: 'u64'})),
115+
t.prop('userId', t.maybe(t.str)),
116+
t.prop('location', t.Tuple([t.Number({format: 'f64'}), t.Number({format: 'f64'})])),
117+
t.prop('metadata', t.Map(t.Or(t.str, t.num, t.bool))),
118+
t.propOpt('sessionId', t.str),
119+
);
120+
121+
/**
122+
* Contact information schema with formatted strings
123+
*/
124+
export const ContactInfo = t.Object(
125+
t.prop(
126+
'name',
127+
t.object({
128+
first: t.String({min: 1}),
129+
last: t.String({min: 1}),
130+
}),
131+
),
132+
t.prop('emails', t.Array(t.String({format: 'ascii'}), {min: 1})),
133+
t.prop('phones', t.Array(t.tuple(t.enum('home', 'work', 'mobile'), t.str))),
134+
t.propOpt(
135+
'address',
136+
t.object({
137+
street: t.str,
138+
city: t.str,
139+
country: t.String({format: 'ascii', min: 2, max: 2}),
140+
postalCode: t.str,
141+
}),
142+
),
143+
t.propOpt('socialMedia', t.Map(t.String({format: 'ascii'}))),
144+
);
145+
146+
/**
147+
* Database record schema with references
148+
*/
149+
export const DatabaseRecord = t.Object(
150+
t.prop('id', t.String({format: 'ascii'})),
151+
t.prop('createdAt', t.Number({format: 'u64'})),
152+
t.prop('updatedAt', t.Number({format: 'u64'})),
153+
t.prop('version', t.Number({format: 'u32', gte: 1})),
154+
t.prop('createdBy', t.Ref<typeof User>('User')),
155+
t.propOpt('updatedBy', t.Ref<typeof User>('User')),
156+
t.propOpt('deletedAt', t.Number({format: 'u64'})),
157+
);
158+
159+
/**
160+
* Function type schema
161+
*/
162+
export const UserValidator = t.Function(
163+
t.object({
164+
userData: t.any,
165+
strict: t.bool,
166+
}),
167+
t.object({
168+
valid: t.bool,
169+
errors: t.Array(t.str),
170+
}),
171+
{title: 'User Validation Function'},
172+
);
173+
174+
/**
175+
* Streaming API schema
176+
*/
177+
export const EventStream = t.Function$(
178+
t.object({
179+
filter: t.maybe(t.str),
180+
limit: t.maybe(t.Number({format: 'u32'})),
181+
}),
182+
t.Ref<typeof Event>('Event'),
183+
{title: 'Event Streaming Function'},
184+
);
185+
186+
/**
187+
* Complex nested schema
188+
*/
189+
export const ComplexNested = t.Object(
190+
t.prop(
191+
'data',
192+
t.Map(
193+
t.Or(
194+
t.str,
195+
t.num,
196+
t.Array(
197+
t.Map(
198+
t.object({
199+
key: t.str,
200+
value: t.Or(t.str, t.num, t.bool, t.nil),
201+
nested: t.maybe(t.Map(t.any)),
202+
}),
203+
),
204+
),
205+
),
206+
),
207+
),
208+
t.prop(
209+
'metadata',
210+
t.object({
211+
version: t.str,
212+
schema: t.String({format: 'ascii'}),
213+
checksum: t.String({format: 'ascii'}),
214+
}),
215+
),
216+
);
217+
218+
/**
219+
* Basic primitive type schemas for backward compatibility
11220
*/
12221
export const primitiveSchemas = {
13-
string: s.String(),
14-
stringWithMinMax: s.String({min: 5, max: 10}),
15-
number: s.Number(),
16-
numberWithFormat: s.Number({format: 'u32'}),
17-
numberWithRange: s.Number({gte: 0, lte: 100}),
18-
boolean: s.Boolean(),
19-
const: s.Const('fixed-value' as const),
20-
any: s.Any(),
222+
string: t.str.getSchema(),
223+
stringWithMinMax: t.String({min: 5, max: 10}).getSchema(),
224+
number: t.num.getSchema(),
225+
numberWithFormat: t.Number({format: 'u32'}).getSchema(),
226+
numberWithRange: t.Number({gte: 0, lte: 100}).getSchema(),
227+
boolean: t.bool.getSchema(),
228+
const: t.Const('fixed-value' as const).getSchema(),
229+
any: t.any.getSchema(),
21230
} as const;
22231

23232
/**
24-
* Complex composite type schemas
233+
* Complex composite type schemas for backward compatibility
25234
*/
26235
export const compositeSchemas = {
27-
simpleArray: s.Array(s.String()),
28-
arrayWithBounds: s.Array(s.Number(), {min: 2, max: 5}),
29-
simpleObject: s.Object([s.prop('id', s.String()), s.prop('name', s.String()), s.prop('active', s.Boolean())]),
30-
objectWithOptionalFields: s.Object([
31-
s.prop('id', s.String()),
32-
s.propOpt('name', s.String()),
33-
s.propOpt('count', s.Number()),
34-
]),
35-
nestedObject: s.Object([
36-
s.prop(
37-
'user',
38-
s.Object([
39-
s.prop('id', s.Number()),
40-
s.prop('profile', s.Object([s.prop('name', s.String()), s.prop('email', s.String())])),
41-
]),
42-
),
43-
s.prop('tags', s.Array(s.String())),
44-
]),
45-
tuple: s.Tuple([s.String(), s.Number(), s.Boolean()]),
46-
map: s.Map(s.String()),
47-
mapWithComplexValue: s.Map(s.Object([s.prop('value', s.Number()), s.prop('label', s.String())])),
48-
union: s.Or(s.String(), s.Number(), s.Boolean()),
49-
complexUnion: s.Or(
50-
s.String(),
51-
s.Object([s.prop('type', s.Const('object' as const)), s.prop('data', s.Any())]),
52-
s.Array(s.Number()),
53-
),
54-
binary: s.bin,
236+
simpleArray: t.Array(t.str).getSchema(),
237+
arrayWithBounds: t.Array(t.num, {min: 2, max: 5}).getSchema(),
238+
simpleObject: t.Object(t.prop('id', t.str), t.prop('name', t.str), t.prop('active', t.bool)).getSchema(),
239+
objectWithOptionalFields: t
240+
.Object(t.prop('id', t.str), t.propOpt('name', t.str), t.propOpt('count', t.num))
241+
.getSchema(),
242+
nestedObject: t
243+
.Object(
244+
t.prop(
245+
'user',
246+
t.Object(t.prop('id', t.num), t.prop('profile', t.Object(t.prop('name', t.str), t.prop('email', t.str)))),
247+
),
248+
t.prop('tags', t.Array(t.str)),
249+
)
250+
.getSchema(),
251+
tuple: t.tuple(t.str, t.num, t.bool).getSchema(),
252+
map: t.Map(t.str).getSchema(),
253+
mapWithComplexValue: t.Map(t.Object(t.prop('value', t.num), t.prop('label', t.str))).getSchema(),
254+
union: t.Or(t.str, t.num, t.bool).getSchema(),
255+
complexUnion: t
256+
.Or(t.str, t.Object(t.prop('type', t.Const('object' as const)), t.prop('data', t.any)), t.Array(t.num))
257+
.getSchema(),
258+
binary: t.bin.getSchema(),
55259
} as const;
56260

57261
/**

0 commit comments

Comments
 (0)