Skip to content

Commit 49c3963

Browse files
committed
refactor(tests): ♻️ Update tests to use OpenAPI types for better type safety
- Replace `any` type with `OpenAPI.Document` in test files - Improve type checking for schemas in test cases
1 parent 231d415 commit 49c3963

11 files changed

Lines changed: 34 additions & 33 deletions

package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
"vitest": "^3.2.1"
3939
},
4040
"dependencies": {
41-
"@hyperjump/json-pointer": "^1.1.1",
4241
"@hyperjump/json-schema": "^1.14.1",
4342
"commander": "^14.0.0",
4443
"handlebars": "^4.7.8",

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ program
9494
const template = Handlebars.compile(templateSource);
9595

9696
const schemaData = Object.entries(schemas).map(([name, schema]) => {
97-
const { zodString } = convertSchema(schema as any);
98-
const desc = (schema as any).description as string | undefined;
97+
const { zodString } = convertSchema(schema);
98+
const desc = schema.description as string | undefined;
9999
return {
100100
schemaName: name,
101101
zodString,
@@ -145,7 +145,7 @@ program
145145

146146
const typingImports = new Set<string>();
147147
const definitions = Object.entries(schemas).map(([name, schema]) => {
148-
const res = convertToTypedDict(name, schema as any);
148+
const res = convertToTypedDict(name, schema);
149149
res.typingImports.forEach((i) => typingImports.add(i));
150150
return { name, definition: res.definition };
151151
});

src/utils/collect-schema-refs.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
export type JsonValue = string | number | boolean | null | JsonObject | JsonValue[];
2-
export type JsonObject = { [key: string]: JsonValue };
3-
41
export function collectSchemaRefs(obj: unknown, refs: Set<string> = new Set()): Set<string> {
52
if (!obj || typeof obj !== 'object') {
63
return refs;

src/utils/filter-openapi-paths.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ import type { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
22
import { collectSchemaRefs } from './collect-schema-refs.js';
33
import { collectSchemas } from './collect-schemas.js';
44

5-
export type JsonValue = string | number | boolean | null | JsonObject | JsonValue[];
6-
export type JsonObject = { [key: string]: JsonValue };
7-
85
export function filterOpenApiPaths(doc: OpenAPI.Document, pathNames: string[]): OpenAPI.Document {
96
const filteredPaths: OpenAPI.PathsObject = {};
107
for (const pathName of pathNames) {

src/utils/validation.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
import type { Json } from '@hyperjump/json-pointer';
21
import { validate } from '@hyperjump/json-schema/openapi-3-1';
32

3+
export type Json = string | number | boolean | null | JsonObject | Json[];
4+
export type JsonObject = {
5+
[property: string]: Json;
6+
};
7+
48
export async function isValidOpenapiSchema(doc: unknown): Promise<boolean> {
59
const response = await validate('https://spec.openapis.org/oas/3.1/schema-base', doc as unknown as Json);
610
if (response.valid) {

tests/extract-schemas.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { describe, it, expect } from 'vitest';
22
import { extractSchemas } from '../src/utils/extract-schemas';
3+
import type { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
34

4-
const doc: any = {
5+
const doc: OpenAPI.Document = {
56
openapi: '3.1.0',
67
info: { title: 't', version: '1.0' },
78
paths: {

tests/filter-paths.spec.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { describe, it, expect, vi } from 'vitest';
22
import { filterOpenApiPaths } from '../src/utils/filter-openapi-paths';
3+
import type { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
34

4-
const openApiDoc = {
5+
const openApiDoc: OpenAPI.Document = {
56
openapi: '3.0.0',
67
info: { title: 'Test', version: '1.0.0' },
78
paths: {
@@ -108,7 +109,7 @@ const openApiDoc = {
108109

109110
describe('filterOpenApiPaths', () => {
110111
it('filters by a single path and includes only referenced schemas', () => {
111-
const filtered = filterOpenApiPaths(openApiDoc as any, ['/v1/models']);
112+
const filtered = filterOpenApiPaths(openApiDoc, ['/v1/models']);
112113
expect(filtered.paths).toHaveProperty('/v1/models');
113114
expect(filtered.paths).not.toHaveProperty('/v1/chat/completions');
114115
expect(filtered.paths).not.toHaveProperty('/v1/other');
@@ -117,7 +118,7 @@ describe('filterOpenApiPaths', () => {
117118
});
118119

119120
it('filters by multiple paths and includes all referenced schemas recursively', () => {
120-
const filtered = filterOpenApiPaths(openApiDoc as any, ['/v1/chat/completions', '/v1/models']);
121+
const filtered = filterOpenApiPaths(openApiDoc, ['/v1/chat/completions', '/v1/models']);
121122
expect(filtered.paths).toHaveProperty('/v1/chat/completions');
122123
expect(filtered.paths).toHaveProperty('/v1/models');
123124
expect(filtered.paths).not.toHaveProperty('/v1/other');
@@ -129,7 +130,7 @@ describe('filterOpenApiPaths', () => {
129130

130131
it('returns the original document if none match', () => {
131132
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
132-
const filtered = filterOpenApiPaths(openApiDoc as any, ['/notfound']);
133+
const filtered = filterOpenApiPaths(openApiDoc, ['/notfound']);
133134
// Should return the original doc if no paths matched
134135
expect(filtered).toEqual(openApiDoc);
135136
expect(warnSpy).toHaveBeenCalledWith('\x1b[33m[openapi-tools] Warning:\x1b[0m Path "/notfound" not found in the OpenAPI spec.');

tests/generate-zod.spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import fs from 'fs';
33
import path from 'path';
44
import Handlebars from 'handlebars';
55
import ts from 'typescript';
6+
import type { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
67
import { convertSchema } from '../src/utils/json-schema-to-zod';
78
import { extractSchemas } from '../src/utils/extract-schemas';
89

@@ -11,14 +12,14 @@ const schemaTemplate = Handlebars.compile(fs.readFileSync(path.join(templateDir,
1112

1213
describe('generate-zod', () => {
1314
it('generates a simple object schema', () => {
14-
const doc: any = {
15+
const doc: OpenAPI.Document = {
1516
openapi: '3.1.0',
1617
info: { title: 't', version: '1' },
1718
paths: {},
1819
components: { schemas: { User: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] } } }
1920
};
2021
const schemas = extractSchemas(doc, null);
21-
const { zodString } = convertSchema(schemas.User as any);
22+
const { zodString } = convertSchema(schemas.User as OpenAPI.SchemaObject);
2223
const content = schemaTemplate({
2324
schemas: [{ schemaName: 'User', zodString }]
2425
});
@@ -28,7 +29,7 @@ describe('generate-zod', () => {
2829
});
2930

3031
it('generates enums and nested arrays', () => {
31-
const doc: any = {
32+
const doc: OpenAPI.Document = {
3233
openapi: '3.1.0',
3334
info: { title: 't', version: '1' },
3435
paths: {},
@@ -40,7 +41,7 @@ describe('generate-zod', () => {
4041
}
4142
};
4243
const schemas = extractSchemas(doc, null);
43-
const { zodString } = convertSchema(schemas.Wrapper as any);
44+
const { zodString } = convertSchema(schemas.Wrapper as OpenAPI.SchemaObject);
4445
const content = schemaTemplate({
4546
schemas: [{ schemaName: 'Wrapper', zodString }]
4647
});
@@ -50,7 +51,7 @@ describe('generate-zod', () => {
5051
});
5152

5253
it('filters schemas by path prefixes', () => {
53-
const doc: any = {
54+
const doc: OpenAPI.Document = {
5455
openapi: '3.1.0',
5556
info: { title: 't', version: '1' },
5657
paths: {

tests/json-schema-to-typed-dict.spec.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@ import path from 'path';
44
import { convertToTypedDict } from '../src/utils/json-schema-to-typed-dict';
55
import { extractSchemas } from '../src/utils/extract-schemas';
66
import child_process from 'child_process';
7+
import type { OpenAPIV3_1 as OpenAPI } from 'openapi-types';
78

89
describe('generate-python-dict', () => {
910
it('generates a simple object schema', () => {
10-
const doc: any = {
11+
const doc: OpenAPI.Document = {
1112
openapi: '3.1.0',
1213
info: { title: 't', version: '1' },
1314
paths: {},
1415
components: { schemas: { User: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] } } }
1516
};
1617
const schemas = extractSchemas(doc, null);
17-
const { definition, typingImports } = convertToTypedDict('User', schemas.User as any);
18+
const { definition, typingImports } = convertToTypedDict('User', schemas.User as OpenAPI.SchemaObject);
1819
const typingLine = `from typing import ${Array.from(typingImports).join(', ')}`;
1920
const content = [typingLine, '', definition, ''].filter(Boolean).join('\n');
2021
const tmp = path.join(__dirname, 'tmp_user.py');
@@ -28,7 +29,7 @@ describe('generate-python-dict', () => {
2829
});
2930

3031
it('generates enums and nested arrays', () => {
31-
const doc: any = {
32+
const doc: OpenAPI.Document = {
3233
openapi: '3.1.0',
3334
info: { title: 't', version: '1' },
3435
paths: {},
@@ -40,7 +41,7 @@ describe('generate-python-dict', () => {
4041
}
4142
};
4243
const schemas = extractSchemas(doc, null);
43-
const { definition, typingImports } = convertToTypedDict('Wrapper', schemas.Wrapper as any);
44+
const { definition, typingImports } = convertToTypedDict('Wrapper', schemas.Wrapper as OpenAPI.SchemaObject);
4445
const typingLine = `from typing import ${Array.from(typingImports).join(', ')}`;
4546
const content = [typingLine, '', definition, ''].filter(Boolean).join('\n');
4647
const tmp = path.join(__dirname, 'tmp_wrapper.py');
@@ -51,7 +52,7 @@ describe('generate-python-dict', () => {
5152
});
5253

5354
it('adds descriptions as comments', () => {
54-
const doc: any = {
55+
const doc: OpenAPI.Document = {
5556
openapi: '3.1.0',
5657
info: { title: 't', version: '1' },
5758
paths: {},
@@ -69,12 +70,12 @@ describe('generate-python-dict', () => {
6970
}
7071
};
7172
const schemas = extractSchemas(doc, null);
72-
const { definition } = convertToTypedDict('User', schemas.User as any);
73+
const { definition } = convertToTypedDict('User', schemas.User as OpenAPI.SchemaObject);
7374
expect(definition).toMatchSnapshot();
7475
});
7576

7677
it('filters schemas by path prefixes', () => {
77-
const doc: any = {
78+
const doc: OpenAPI.Document = {
7879
openapi: '3.1.0',
7980
info: { title: 't', version: '1' },
8081
paths: {

0 commit comments

Comments
 (0)