Skip to content

Commit 83fbd66

Browse files
committed
test: add comprehensive tests for arrow function fallback behavior
Adds test coverage for parseFunctionBody error handling to validate that the fallback mechanism works correctly. These tests ensure: - Parameter-less arrow functions are successfully parsed and inlined - Arrow functions with parameters gracefully fallback to refs (no errors) - BlockStatement arrow functions are handled correctly - All edge cases that previously caused 'Unknown identifier' errors now fall back gracefully Test scenarios: 1. Parameter-less arrow function → parsed successfully 2. Parameter-less with BlockStatement → parsed successfully 3. Arrow function with parameters → fallback to ref 4. Nested parameter-less calling function with params → fallback to ref 5. BlockStatement without return → fallback to ref Without the fallback, 3 of these tests fail with errors. With the fallback, all tests pass.
1 parent 97bb096 commit 83fbd66

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import { testCase } from './testHarness';
2+
3+
// SUCCESS CASE: Parameter-less arrow function should be parsed
4+
testCase(
5+
'parameter-less arrow function is parsed and inlined',
6+
`
7+
import * as t from 'io-ts';
8+
9+
const StringFactory = () => t.string;
10+
11+
export const MyCodec = t.type({
12+
field: StringFactory(),
13+
});
14+
`,
15+
{
16+
openapi: '3.0.3',
17+
info: {
18+
title: 'Test',
19+
version: '1.0.0',
20+
},
21+
paths: {},
22+
components: {
23+
schemas: {
24+
MyCodec: {
25+
title: 'MyCodec',
26+
type: 'object',
27+
properties: {
28+
field: {
29+
type: 'string',
30+
},
31+
},
32+
required: ['field'],
33+
},
34+
StringFactory: {
35+
title: 'StringFactory',
36+
},
37+
},
38+
},
39+
},
40+
);
41+
42+
// SUCCESS CASE: Parameter-less with BlockStatement
43+
testCase(
44+
'parameter-less arrow function with BlockStatement is parsed',
45+
`
46+
import * as t from 'io-ts';
47+
48+
const ComplexFactory = () => {
49+
return t.union([t.literal('true'), t.literal('false')]);
50+
};
51+
52+
export const MyCodec = t.type({
53+
field: ComplexFactory(),
54+
});
55+
`,
56+
{
57+
openapi: '3.0.3',
58+
info: {
59+
title: 'Test',
60+
version: '1.0.0',
61+
},
62+
paths: {},
63+
components: {
64+
schemas: {
65+
MyCodec: {
66+
title: 'MyCodec',
67+
type: 'object',
68+
properties: {
69+
field: {
70+
type: 'string',
71+
enum: ['true', 'false'],
72+
},
73+
},
74+
required: ['field'],
75+
},
76+
ComplexFactory: {
77+
title: 'ComplexFactory',
78+
},
79+
},
80+
},
81+
},
82+
);
83+
84+
// FALLBACK CASE: Arrow function with parameters should fallback to ref (not error)
85+
testCase(
86+
'arrow function with parameters falls back to ref without error',
87+
`
88+
import * as t from 'io-ts';
89+
90+
const optional = (codec) => t.union([codec, t.undefined]);
91+
92+
export const MyCodec = t.type({
93+
field: optional(t.string),
94+
});
95+
`,
96+
{
97+
openapi: '3.0.3',
98+
info: {
99+
title: 'Test',
100+
version: '1.0.0',
101+
},
102+
paths: {},
103+
components: {
104+
schemas: {
105+
MyCodec: {
106+
title: 'MyCodec',
107+
type: 'object',
108+
properties: {
109+
field: {
110+
$ref: '#/components/schemas/optional',
111+
},
112+
},
113+
required: ['field'],
114+
},
115+
optional: {
116+
title: 'optional',
117+
},
118+
},
119+
},
120+
},
121+
);
122+
123+
// FALLBACK CASE: Parameter-less calling function with parameters
124+
testCase(
125+
'parameter-less function calling function with parameters falls back gracefully',
126+
`
127+
import * as t from 'io-ts';
128+
129+
const optional = (codec) => t.union([codec, t.undefined]);
130+
const makeOptionalString = () => optional(t.string);
131+
132+
export const MyCodec = t.type({
133+
field: makeOptionalString(),
134+
});
135+
`,
136+
{
137+
openapi: '3.0.3',
138+
info: {
139+
title: 'Test',
140+
version: '1.0.0',
141+
},
142+
paths: {},
143+
components: {
144+
schemas: {
145+
MyCodec: {
146+
title: 'MyCodec',
147+
type: 'object',
148+
properties: {
149+
field: {
150+
$ref: '#/components/schemas/optional',
151+
},
152+
},
153+
required: ['field'],
154+
},
155+
makeOptionalString: {
156+
title: 'makeOptionalString',
157+
},
158+
optional: {
159+
title: 'optional',
160+
},
161+
},
162+
},
163+
},
164+
);
165+
166+
// FALLBACK CASE: BlockStatement without return should fallback (not error)
167+
testCase(
168+
'BlockStatement without return falls back to ref without error',
169+
`
170+
import * as t from 'io-ts';
171+
172+
const NoReturnFactory = () => {
173+
const x = t.string;
174+
};
175+
176+
export const MyCodec = t.type({
177+
field: NoReturnFactory(),
178+
});
179+
`,
180+
{
181+
openapi: '3.0.3',
182+
info: {
183+
title: 'Test',
184+
version: '1.0.0',
185+
},
186+
paths: {},
187+
components: {
188+
schemas: {
189+
MyCodec: {
190+
title: 'MyCodec',
191+
type: 'object',
192+
properties: {
193+
field: {
194+
$ref: '#/components/schemas/NoReturnFactory',
195+
},
196+
},
197+
required: ['field'],
198+
},
199+
NoReturnFactory: {
200+
title: 'NoReturnFactory',
201+
},
202+
},
203+
},
204+
},
205+
);

0 commit comments

Comments
 (0)