Skip to content

Commit 14df5f3

Browse files
committed
Increase test coverage
1 parent 1615aaa commit 14df5f3

File tree

5 files changed

+465
-115
lines changed

5 files changed

+465
-115
lines changed
Lines changed: 118 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { describe, expect, it } from 'vitest';
22

33
import * as utils from '../../src/core/utils.js';
4-
import { GeneratorConfig, SwaggerDefinition } from '../../src/core/types.js';
4+
import { GeneratorConfig, RequestBody, SwaggerDefinition } from '../../src/core/types.js';
55
import { branchCoverageSpec, typeGenSpec } from '../shared/specs.js';
66

77
/**
@@ -18,63 +18,142 @@ describe('Core: utils.ts (Coverage)', () => {
1818
};
1919
const configWithDate: GeneratorConfig = { ...config, options: { ...config.options, dateType: 'Date' } };
2020

21-
it('getRequestBodyType should return "any" for undefined requestBody', () => {
22-
expect(utils.getRequestBodyType(undefined, config, [])).toBe('any');
21+
describe('getRequestBodyType', () => {
22+
it('should return "any" if request body is undefined', () => {
23+
expect(utils.getRequestBodyType(undefined, config, [])).toBe('any');
24+
});
25+
26+
it('should return "any" if request body has no content property', () => {
27+
const requestBody: RequestBody = { required: false }; // no `content` key
28+
expect(utils.getRequestBodyType(requestBody, config, [])).toBe('any');
29+
});
30+
31+
it('should return the correct type for a valid request body', () => {
32+
const requestBody: RequestBody = {
33+
content: {
34+
'application/json': {
35+
schema: { type: 'number' },
36+
},
37+
},
38+
};
39+
expect(utils.getRequestBodyType(requestBody, config, [])).toBe('number');
40+
});
2341
});
2442

2543
it('getResponseType should return "any" for undefined response', () => {
2644
expect(utils.getResponseType(undefined, config, [])).toBe('any');
2745
});
2846

29-
it('getTypeScriptType should return "any" for null or undefined schema', () => {
30-
expect(utils.getTypeScriptType(undefined, config, [])).toBe('any');
31-
expect(utils.getTypeScriptType(null, config, [])).toBe('any');
32-
});
47+
describe('getTypeScriptType', () => {
48+
it('should return "any" for null or undefined schema', () => {
49+
expect(utils.getTypeScriptType(undefined, config, [])).toBe('any');
50+
expect(utils.getTypeScriptType(null, config, [])).toBe('any');
51+
});
3352

34-
it('getTypeScriptType should return "any" for unresolvable $ref', () => {
35-
const schema: SwaggerDefinition = { $ref: '#/components/schemas/NonExistentType' };
36-
const knownTypes: string[] = ['SomeOtherType'];
37-
expect(utils.getTypeScriptType(schema, config, knownTypes)).toBe('any');
38-
});
53+
it('should handle $ref ending in a slash resulting in an empty pop', () => {
54+
const schema: SwaggerDefinition = { $ref: '#/definitions/users/' };
55+
expect(utils.getTypeScriptType(schema, config, ['User'])).toBe('any');
56+
});
3957

40-
it('getTypeScriptType should handle empty `allOf` by returning `any`', () => {
41-
const schema: SwaggerDefinition = { allOf: [] };
42-
expect(utils.getTypeScriptType(schema, config, [])).toBe('any');
43-
});
58+
it('should return "any" for unresolvable $ref', () => {
59+
const schema: SwaggerDefinition = { $ref: '#/components/schemas/NonExistentType' };
60+
const knownTypes: string[] = ['SomeOtherType'];
61+
expect(utils.getTypeScriptType(schema, config, knownTypes)).toBe('any');
62+
});
4463

45-
it('getTypeScriptType should handle `additionalProperties: true`', () => {
46-
const schema = typeGenSpec.components.schemas.FreeObject;
47-
expect(utils.getTypeScriptType(schema, config, [])).toBe('Record<string, any>');
48-
});
64+
it('should handle empty `allOf` by returning `any`', () => {
65+
const schema: SwaggerDefinition = { allOf: [] };
66+
expect(utils.getTypeScriptType(schema, config, [])).toBe('any');
67+
});
4968

50-
it('extractPaths should handle undefined swaggerPaths', () => {
51-
expect(utils.extractPaths(undefined)).toEqual([]);
52-
});
69+
it('should handle empty `oneOf` by returning `any`', () => {
70+
const schema: SwaggerDefinition = { oneOf: [] };
71+
expect(utils.getTypeScriptType(schema, config, [])).toBe('any');
72+
});
5373

54-
it('extractPaths should handle operations with no request body or body param', () => {
55-
const paths = utils.extractPaths(branchCoverageSpec.paths);
56-
const op = paths.find(p => p.operationId === 'getNoBody');
57-
expect(op).toBeDefined();
58-
// This covers the `... : undefined` branch for `requestBody`
59-
expect(op!.requestBody).toBeUndefined();
60-
});
74+
it('should handle `additionalProperties: true`', () => {
75+
const schema = typeGenSpec.components.schemas.FreeObject;
76+
expect(utils.getTypeScriptType(schema, config, [])).toBe('Record<string, any>');
77+
});
6178

62-
it('extractPaths should handle responses with non-json content', () => {
63-
const paths = utils.extractPaths(branchCoverageSpec.paths);
64-
const op = paths.find(p => p.operationId === 'getNoBody');
65-
expect(op).toBeDefined();
66-
// The response should be normalized even if it's not JSON
67-
expect(op!.responses!['200'].content!['text/plain'].schema).toEqual({ type: 'string' });
79+
it('should handle array with no items', () => {
80+
const schema: SwaggerDefinition = { type: 'array' };
81+
expect(utils.getTypeScriptType(schema, config, [])).toBe('any[]');
82+
});
83+
84+
it('should handle property names that need quoting', () => {
85+
const schema: SwaggerDefinition = {
86+
type: 'object',
87+
properties: {
88+
'with-hyphen': { type: 'string' },
89+
},
90+
};
91+
expect(utils.getTypeScriptType(schema, config, [])).toBe("{ 'with-hyphen'?: string }");
92+
});
93+
94+
it('should correctly handle optional vs required properties', () => {
95+
const schema: SwaggerDefinition = {
96+
type: 'object',
97+
properties: {
98+
'required-prop': { type: 'string' },
99+
'optional-prop': { type: 'string' },
100+
},
101+
required: ['required-prop'],
102+
};
103+
const expected = "{ 'required-prop': string; 'optional-prop'?: string }";
104+
expect(utils.getTypeScriptType(schema, config, [])).toBe(expected);
105+
});
68106
});
69107

70-
it('getTypeScriptType should handle array with no items', () => {
71-
const schema: SwaggerDefinition = { type: 'array' };
72-
expect(utils.getTypeScriptType(schema, config, [])).toBe('any[]');
108+
describe('extractPaths', () => {
109+
it('should handle undefined swaggerPaths', () => {
110+
expect(utils.extractPaths(undefined)).toEqual([]);
111+
});
112+
113+
it('should handle operations with no request body or body param', () => {
114+
const paths = utils.extractPaths(branchCoverageSpec.paths);
115+
const op = paths.find(p => p.operationId === 'getNoBody');
116+
expect(op).toBeDefined();
117+
expect(op!.requestBody).toBeUndefined();
118+
});
119+
120+
it('should normalize Swagger 2.0 responses with a schema', () => {
121+
const swaggerPaths = {
122+
'/test': {
123+
get: {
124+
operationId: 'getTest',
125+
responses: {
126+
'200': {
127+
description: 'A successful response',
128+
schema: { type: 'string' },
129+
},
130+
},
131+
},
132+
},
133+
};
134+
const [pathInfo] = utils.extractPaths(swaggerPaths as any);
135+
expect(pathInfo).toBeDefined();
136+
expect(pathInfo.responses?.['200'].content).toEqual({
137+
'application/json': { schema: { type: 'string' } },
138+
});
139+
expect(pathInfo.responses?.['200'].description).toBe('A successful response');
140+
});
141+
142+
it('should handle responses with non-json content', () => {
143+
const paths = utils.extractPaths(branchCoverageSpec.paths);
144+
const op = paths.find(p => p.operationId === 'getNoBody');
145+
expect(op).toBeDefined();
146+
expect(op!.responses!['200'].content!['text/plain'].schema).toEqual({ type: 'string' });
147+
});
73148
});
74149

75150
it('isDataTypeInterface should return false for union types', () => {
76151
const schema: SwaggerDefinition = { type: 'string', format: 'date-time', nullable: true };
77152
const type: string = utils.getTypeScriptType(schema, configWithDate, []); // "Date | null"
78153
expect(utils.isDataTypeInterface(type)).toBe(false);
79154
});
155+
156+
it('getInterceptorsTokenName should use default client name when none is provided', () => {
157+
expect(utils.getInterceptorsTokenName()).toBe('HTTP_INTERCEPTORS_DEFAULT');
158+
});
80159
});

0 commit comments

Comments
 (0)