Skip to content

Commit 019febc

Browse files
committed
test: add edge-case branch tests for collect-routes and reach full function coverage
1 parent 38ec6b1 commit 019febc

6 files changed

Lines changed: 118 additions & 100 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ dist/
44
.DS_Store
55
.idea
66
src/assets-inline.ts
7-
/.prettierrc
87
preview.html
8+
9+
bun.lock

.prettierrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"printWidth": 100,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": true,
6+
"singleQuote": true,
7+
"trailingComma": "none",
8+
"bracketSpacing": true,
9+
"arrowParens": "avoid",
10+
"requirePragma": false,
11+
"insertPragma": false,
12+
"proseWrap": "always"
13+
}

bun.lock

Lines changed: 0 additions & 97 deletions
This file was deleted.

bunfig.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
# Multiple patterns
66
coveragePathIgnorePatterns = [
7-
"**/*.ts",
7+
"tests/**/*.ts",
88
"*.config.js",
99
]

src/collect-routes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,3 +500,15 @@ function traverseRouter(router: AnyRouter): RouteInfo[] {
500500
export function collectRoutes(router: AnyRouter): RouteInfo[] {
501501
return traverseRouter(router);
502502
}
503+
504+
// Internal helpers exported for white-box tests of branch behavior.
505+
export const __internal = {
506+
extractOptionalFields,
507+
generateExampleFromSchema,
508+
generateJSONExample,
509+
generateTypeScriptExample,
510+
generateTypeScriptFromSchema,
511+
getOptionalFields,
512+
isZodDateSchema,
513+
zodSchemaToString
514+
};

tests/edge-cases.test.ts

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, test, expect } from 'bun:test';
22
import { initTRPC } from '@trpc/server';
33
import { z } from 'zod';
4-
import { collectRoutes } from '../src/collect-routes';
4+
import { collectRoutes, __internal } from '../src/collect-routes';
55
import { getRoute, inputSchema, inputExample } from './_helpers';
66

77
const t = initTRPC.create();
@@ -54,4 +54,93 @@ describe('edge cases', () => {
5454
const dateVariant = variants.find((s: any) => s.format === 'date-time');
5555
expect(dateVariant).toMatchObject({ type: 'string', format: 'date-time' });
5656
});
57+
58+
test('example generator returns undefined for invalid JSON schema string', () => {
59+
expect(__internal.generateExampleFromSchema('{')).toBeUndefined();
60+
});
61+
62+
test('TypeScript generator returns undefined for invalid JSON schema string', () => {
63+
expect(__internal.generateTypeScriptFromSchema('{')).toBeUndefined();
64+
});
65+
66+
test('optional-fields extractor returns undefined for invalid JSON schema string', () => {
67+
expect(__internal.extractOptionalFields('{')).toBeUndefined();
68+
});
69+
70+
test('allOf optional-field extraction includes non-required keys', () => {
71+
const fields = __internal.getOptionalFields({
72+
allOf: [
73+
{
74+
type: 'object',
75+
properties: {
76+
id: { type: 'number' },
77+
nickname: { type: 'string' }
78+
},
79+
required: ['id']
80+
}
81+
]
82+
});
83+
84+
expect(fields).toEqual([{ name: 'nickname', example: '"string"' }]);
85+
});
86+
87+
test('JSON example handles oneOf by choosing first branch', () => {
88+
expect(
89+
__internal.generateJSONExample({ oneOf: [{ type: 'number' }, { type: 'string' }] })
90+
).toBe('0');
91+
});
92+
93+
test('JSON example handles array schema without items', () => {
94+
expect(__internal.generateJSONExample({ type: 'array' })).toBe('[]');
95+
});
96+
97+
test('JSON example handles date format and unknown schemas', () => {
98+
expect(__internal.generateJSONExample({ type: 'string', format: 'date' })).toBe('"2024-01-01"');
99+
expect(__internal.generateJSONExample({ allOf: [{ type: 'string' }] })).toBe('"value"');
100+
});
101+
102+
test('TypeScript generation handles allOf object and non-object intersections', () => {
103+
const ts = __internal.generateTypeScriptExample({
104+
allOf: [
105+
{
106+
type: 'object',
107+
properties: { id: { type: 'number' } },
108+
required: ['id']
109+
},
110+
{
111+
oneOf: [{ type: 'string' }, { type: 'number' }]
112+
}
113+
]
114+
});
115+
116+
expect(ts).toContain('id: number');
117+
expect(ts).toContain('& (string | number)');
118+
});
119+
120+
test('TypeScript generation handles allOf with only non-objects', () => {
121+
expect(
122+
__internal.generateTypeScriptExample({ allOf: [{ type: 'string' }, { type: 'number' }] })
123+
).toBe('string & number');
124+
});
125+
126+
test('TypeScript generation handles oneOf, arrays without items, and unknown schema', () => {
127+
expect(
128+
__internal.generateTypeScriptExample({ oneOf: [{ type: 'string' }, { type: 'number' }] })
129+
).toBe('string | number');
130+
expect(__internal.generateTypeScriptExample({ type: 'array' })).toBe('any[]');
131+
expect(__internal.generateTypeScriptExample({ foo: 'bar' })).toBe('any');
132+
});
133+
134+
test('zodSchemaToString returns undefined when toJSONSchema is not callable', () => {
135+
expect(__internal.zodSchemaToString({ toJSONSchema: 123 })).toBeUndefined();
136+
});
137+
138+
test('zodSchemaToString catches conversion errors', () => {
139+
const schema = {
140+
toJSONSchema() {
141+
throw new Error('boom');
142+
}
143+
};
144+
expect(__internal.zodSchemaToString(schema)).toBeUndefined();
145+
});
57146
});

0 commit comments

Comments
 (0)