|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "strings" |
| 4 | + "slices" |
5 | 5 | "testing" |
6 | 6 |
|
7 | 7 | "github.com/coder/guts/bindings" |
@@ -86,12 +86,7 @@ func TestTopoSort(t *testing.T) { |
86 | 86 | order := topoSort(nodes) |
87 | 87 |
|
88 | 88 | indexOf := func(name string) int { |
89 | | - for i, n := range order { |
90 | | - if n == name { |
91 | | - return i |
92 | | - } |
93 | | - } |
94 | | - return -1 |
| 89 | + return slices.Index(order, name) |
95 | 90 | } |
96 | 91 |
|
97 | 92 | if indexOf("C") > indexOf("B") { |
@@ -172,250 +167,6 @@ func TestCollectRefsArrayLiteralType(t *testing.T) { |
172 | 167 | } |
173 | 168 | } |
174 | 169 |
|
175 | | -func TestExprToZodNullableUnion(t *testing.T) { |
176 | | - t.Parallel() |
177 | | - |
178 | | - expr := bindings.Union(kw(bindings.KeywordString), &bindings.Null{}) |
179 | | - result := exprToZod(expr, "") |
180 | | - |
181 | | - if result != "z.string().nullable()" { |
182 | | - t.Errorf("expected z.string().nullable(), got %q", result) |
183 | | - } |
184 | | -} |
185 | | - |
186 | | -func TestExprToZodSingleMemberUnion(t *testing.T) { |
187 | | - t.Parallel() |
188 | | - |
189 | | - expr := bindings.Union(kw(bindings.KeywordString)) |
190 | | - result := exprToZod(expr, "") |
191 | | - |
192 | | - if result != "z.string()" { |
193 | | - t.Errorf("expected z.string(), got %q", result) |
194 | | - } |
195 | | -} |
196 | | - |
197 | | -func TestExprToZodRecord(t *testing.T) { |
198 | | - t.Parallel() |
199 | | - |
200 | | - expr := bindings.Reference( |
201 | | - bindings.Identifier{Name: "Record"}, |
202 | | - kw(bindings.KeywordString), |
203 | | - kw(bindings.KeywordString), |
204 | | - ) |
205 | | - result := exprToZod(expr, "") |
206 | | - |
207 | | - if result != "z.record(z.string(), z.string())" { |
208 | | - t.Errorf("expected z.record(...), got %q", result) |
209 | | - } |
210 | | -} |
211 | | - |
212 | | -func TestExprToZodSelfReference(t *testing.T) { |
213 | | - t.Parallel() |
214 | | - |
215 | | - expr := ref("Tree") |
216 | | - result := exprToZod(expr, "Tree") |
217 | | - |
218 | | - if !strings.Contains(result, "z.lazy") { |
219 | | - t.Errorf("expected z.lazy() for self-reference, got %q", result) |
220 | | - } |
221 | | -} |
222 | | - |
223 | | -func TestExprToZodNonSelfReference(t *testing.T) { |
224 | | - t.Parallel() |
225 | | - |
226 | | - expr := ref("Other") |
227 | | - result := exprToZod(expr, "Tree") |
228 | | - |
229 | | - if result != "OtherSchema" { |
230 | | - t.Errorf("expected OtherSchema, got %q", result) |
231 | | - } |
232 | | -} |
233 | | - |
234 | | -func TestSerializeNodeInterface(t *testing.T) { |
235 | | - t.Parallel() |
236 | | - |
237 | | - node := &bindings.Interface{ |
238 | | - Name: bindings.Identifier{Name: "Foo"}, |
239 | | - Fields: []*bindings.PropertySignature{ |
240 | | - {Name: "name", Type: kw(bindings.KeywordString)}, |
241 | | - }, |
242 | | - } |
243 | | - |
244 | | - result := serializeNode("Foo", node) |
245 | | - |
246 | | - if !strings.Contains(result, "export const FooSchema = z.object(") { |
247 | | - t.Errorf("expected z.object declaration, got:\n%s", result) |
248 | | - } |
249 | | - if !strings.Contains(result, "name: z.string()") { |
250 | | - t.Errorf("expected name field, got:\n%s", result) |
251 | | - } |
252 | | -} |
253 | | - |
254 | | -func TestSerializeNodeAlias(t *testing.T) { |
255 | | - t.Parallel() |
256 | | - |
257 | | - node := &bindings.Alias{ |
258 | | - Name: bindings.Identifier{Name: "MyString"}, |
259 | | - Type: kw(bindings.KeywordString), |
260 | | - } |
261 | | - |
262 | | - result := serializeNode("MyString", node) |
263 | | - |
264 | | - if !strings.Contains(result, "export const MyStringSchema = z.string()") { |
265 | | - t.Errorf("expected z.string() alias, got:\n%s", result) |
266 | | - } |
267 | | - if !strings.Contains(result, "export type MyString = z.infer<typeof MyStringSchema>") { |
268 | | - t.Errorf("expected type export, got:\n%s", result) |
269 | | - } |
270 | | -} |
271 | | - |
272 | | -func TestSerializeNodeUnknownReturnsEmpty(t *testing.T) { |
273 | | - t.Parallel() |
274 | | - |
275 | | - // LiteralKeyword is a Node but not Interface or Alias. |
276 | | - kword := bindings.KeywordString |
277 | | - result := serializeNode("X", &kword) |
278 | | - |
279 | | - if result != "" { |
280 | | - t.Errorf("expected empty string for unknown node type, got %q", result) |
281 | | - } |
282 | | -} |
283 | | - |
284 | | -func TestSerializeInterfaceWithHeritage(t *testing.T) { |
285 | | - t.Parallel() |
286 | | - |
287 | | - iface := &bindings.Interface{ |
288 | | - Name: bindings.Identifier{Name: "Child"}, |
289 | | - Heritage: []*bindings.HeritageClause{ |
290 | | - bindings.HeritageClauseExtends(ref("Parent")), |
291 | | - }, |
292 | | - Fields: []*bindings.PropertySignature{ |
293 | | - {Name: "extra", Type: kw(bindings.KeywordString)}, |
294 | | - }, |
295 | | - } |
296 | | - |
297 | | - result := serializeInterface("Child", iface) |
298 | | - |
299 | | - if !strings.Contains(result, "ParentSchema.extend") { |
300 | | - t.Errorf("expected ParentSchema.extend, got:\n%s", result) |
301 | | - } |
302 | | - if !strings.Contains(result, "extra: z.string()") { |
303 | | - t.Errorf("expected extra field, got:\n%s", result) |
304 | | - } |
305 | | -} |
306 | | - |
307 | | -func TestSerializeStringEnum(t *testing.T) { |
308 | | - t.Parallel() |
309 | | - |
310 | | - union := &bindings.UnionType{ |
311 | | - Types: []bindings.ExpressionType{ |
312 | | - &bindings.LiteralType{Value: "a"}, |
313 | | - &bindings.LiteralType{Value: "b"}, |
314 | | - }, |
315 | | - } |
316 | | - |
317 | | - result := serializeStringEnum("Status", union) |
318 | | - |
319 | | - if !strings.Contains(result, `z.enum([`) { |
320 | | - t.Errorf("expected z.enum, got:\n%s", result) |
321 | | - } |
322 | | - if !strings.Contains(result, `"a"`) || !strings.Contains(result, `"b"`) { |
323 | | - t.Errorf("expected enum values, got:\n%s", result) |
324 | | - } |
325 | | -} |
326 | | - |
327 | | -func TestObjectLiteralToZod(t *testing.T) { |
328 | | - t.Parallel() |
329 | | - |
330 | | - tl := &bindings.TypeLiteralNode{ |
331 | | - Members: []*bindings.PropertySignature{ |
332 | | - {Name: "x", Type: kw(bindings.KeywordNumber)}, |
333 | | - {Name: "y", Type: kw(bindings.KeywordString), QuestionToken: true}, |
334 | | - }, |
335 | | - } |
336 | | - |
337 | | - result := objectLiteralToZod(tl, "") |
338 | | - |
339 | | - if !strings.Contains(result, "z.object(") { |
340 | | - t.Errorf("expected z.object, got:\n%s", result) |
341 | | - } |
342 | | - if !strings.Contains(result, "x: z.number()") { |
343 | | - t.Errorf("expected x field, got:\n%s", result) |
344 | | - } |
345 | | - if !strings.Contains(result, "y: z.string().optional()") { |
346 | | - t.Errorf("expected optional y field, got:\n%s", result) |
347 | | - } |
348 | | -} |
349 | | - |
350 | | -func TestIntersectionToZod(t *testing.T) { |
351 | | - t.Parallel() |
352 | | - |
353 | | - t.Run("empty", func(t *testing.T) { |
354 | | - t.Parallel() |
355 | | - inter := &bindings.TypeIntersection{} |
356 | | - if got := intersectionToZod(inter, ""); got != "z.unknown()" { |
357 | | - t.Errorf("expected z.unknown(), got %q", got) |
358 | | - } |
359 | | - }) |
360 | | - |
361 | | - t.Run("single", func(t *testing.T) { |
362 | | - t.Parallel() |
363 | | - inter := &bindings.TypeIntersection{ |
364 | | - Types: []bindings.ExpressionType{kw(bindings.KeywordString)}, |
365 | | - } |
366 | | - if got := intersectionToZod(inter, ""); got != "z.string()" { |
367 | | - t.Errorf("expected z.string(), got %q", got) |
368 | | - } |
369 | | - }) |
370 | | - |
371 | | - t.Run("two types", func(t *testing.T) { |
372 | | - t.Parallel() |
373 | | - inter := &bindings.TypeIntersection{ |
374 | | - Types: []bindings.ExpressionType{ |
375 | | - ref("A"), |
376 | | - ref("B"), |
377 | | - }, |
378 | | - } |
379 | | - got := intersectionToZod(inter, "") |
380 | | - if !strings.Contains(got, "z.intersection(ASchema, BSchema)") { |
381 | | - t.Errorf("expected z.intersection(ASchema, BSchema), got %q", got) |
382 | | - } |
383 | | - }) |
384 | | - |
385 | | - t.Run("three types nested", func(t *testing.T) { |
386 | | - t.Parallel() |
387 | | - inter := &bindings.TypeIntersection{ |
388 | | - Types: []bindings.ExpressionType{ |
389 | | - ref("A"), |
390 | | - ref("B"), |
391 | | - ref("C"), |
392 | | - }, |
393 | | - } |
394 | | - got := intersectionToZod(inter, "") |
395 | | - expected := "z.intersection(z.intersection(ASchema, BSchema), CSchema)" |
396 | | - if got != expected { |
397 | | - t.Errorf("expected %q, got %q", expected, got) |
398 | | - } |
399 | | - }) |
400 | | -} |
401 | | - |
402 | | -func TestSerializeNodeSelfReferenceUsesLazy(t *testing.T) { |
403 | | - t.Parallel() |
404 | | - |
405 | | - node := &bindings.Interface{ |
406 | | - Name: bindings.Identifier{Name: "Tree"}, |
407 | | - Fields: []*bindings.PropertySignature{ |
408 | | - {Name: "children", Type: bindings.Array(ref("Tree"))}, |
409 | | - }, |
410 | | - } |
411 | | - |
412 | | - result := serializeNode("Tree", node) |
413 | | - |
414 | | - if !strings.Contains(result, "z.lazy(") { |
415 | | - t.Errorf("expected z.lazy for self-reference, got:\n%s", result) |
416 | | - } |
417 | | -} |
418 | | - |
419 | 170 | func ref(name string) *bindings.ReferenceType { |
420 | 171 | return bindings.Reference(bindings.Identifier{Name: name}) |
421 | 172 | } |
|
0 commit comments