Refactor OpenAPI plugin structure by consolidating parser and printer exports, enhancing type safety, and improving error handling in parsing functions. Update tests to reflect new structure and ensure consistent handling of OpenAPI file detection.

This commit is contained in:
Luke Hagar
2025-09-26 21:03:08 +00:00
parent 0901e96671
commit d34e24583b
12 changed files with 796 additions and 754 deletions

View File

@@ -1,12 +1,12 @@
import { describe, expect, it } from 'bun:test';
import plugin from '../src/index';
import { parsers } from '../src/index';
describe('File Detection Tests', () => {
it('should detect OpenAPI root files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
it('should detect OpenAPI root files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const testYaml = `openapi: 3.0.0
const testYaml = `openapi: 3.0.0
info:
title: Test API
version: 1.0.0
@@ -17,20 +17,20 @@ paths:
'200':
description: Success`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(testYaml, { filepath: 'openapi.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.openapi).toBe('3.0.0');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(testYaml, { filepath: 'openapi.yaml' });
it('should detect partial schema files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.openapi).toBe('3.0.0');
});
const schemaYaml = `type: object
it('should detect partial schema files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const schemaYaml = `type: object
properties:
id:
type: integer
@@ -40,40 +40,40 @@ required:
- id
- name`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(schemaYaml, { filepath: 'components/schemas/User.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.type).toBe('object');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(schemaYaml, { filepath: 'components/schemas/User.yaml' });
it('should detect parameter files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.type).toBe('object');
});
const parameterYaml = `name: id
it('should detect parameter files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const parameterYaml = `name: id
in: path
required: true
description: User ID
schema:
type: integer`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(parameterYaml, { filepath: 'components/parameters/UserId.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.name).toBe('id');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(parameterYaml, { filepath: 'components/parameters/UserId.yaml' });
it('should detect response files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.name).toBe('id');
});
const responseYaml = `description: User response
it('should detect response files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const responseYaml = `description: User response
content:
application/json:
schema:
@@ -84,20 +84,20 @@ content:
name:
type: string`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(responseYaml, { filepath: 'components/responses/UserResponse.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.description).toBe('User response');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(responseYaml, { filepath: 'components/responses/UserResponse.yaml' });
it('should detect path files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.description).toBe('User response');
});
const pathYaml = `get:
it('should detect path files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const pathYaml = `get:
summary: Get users
responses:
'200':
@@ -110,91 +110,100 @@ post:
schema:
type: object`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(pathYaml, { filepath: 'paths/users.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.get).toBeDefined();
expect(result?.content.post).toBeDefined();
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(pathYaml, { filepath: 'paths/users.yaml' });
it('should detect security scheme files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.get).toBeDefined();
expect(result?.content.post).toBeDefined();
});
const securityYaml = `type: http
it('should detect security scheme files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const securityYaml = `type: http
scheme: bearer
bearerFormat: JWT
description: JWT authentication`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(securityYaml, { filepath: 'components/securitySchemes/BearerAuth.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
expect(result?.content.type).toBe('http');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(securityYaml, { filepath: 'components/securitySchemes/BearerAuth.yaml' });
it('should reject non-OpenAPI files', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
expect(result?.content.type).toBe('http');
});
const nonOpenAPIYaml = `name: John
it('should handle non-OpenAPI files', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const nonOpenAPIYaml = `name: John
age: 30
city: New York`;
// @ts-expect-error We are mocking things here
expect(() => parser?.parse(nonOpenAPIYaml, { filepath: 'config/data.yaml' })).toThrow('Not an OpenAPI file');
});
const parsedYaml = {
name: 'John',
age: 30,
city: 'New York'
}
it('should accept files in OpenAPI directories even with simple content', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
// @ts-expect-error We are mocking things here
const parsedData = parser?.parse(nonOpenAPIYaml, { filepath: 'config/data.yaml' })
const simpleYaml = `name: John
expect(parsedData).toBeDefined()
expect(parsedData?.isOpenAPI).toBeFalse();
});
it('should accept files in OpenAPI directories even with simple content', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const simpleYaml = `name: John
age: 30
city: New York`;
// @ts-expect-error We are mocking things here
const result = parser?.parse(simpleYaml, { filepath: 'components/schemas/User.yaml' });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
});
// @ts-expect-error We are mocking things here
const result = parser?.parse(simpleYaml, { filepath: 'components/schemas/User.yaml' });
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
});
it('should support component directory patterns', () => {
const parser = plugin.parsers?.['openapi-parser'];
expect(parser).toBeDefined();
it('should support component directory patterns', () => {
const parser = parsers?.['openapi-parser'];
expect(parser).toBeDefined();
const componentYaml = `type: object
const componentYaml = `type: object
properties:
message:
type: string`;
// Test various component directory patterns
const paths = [
'components/schemas/Error.yaml',
'components/parameters/CommonPagination.yaml',
'components/responses/ErrorResponse.yaml',
'components/requestBodies/UserCreateBody.yaml',
'components/headers/RateLimitHeaders.yaml',
'components/examples/UserExample.yaml',
'components/securitySchemes/BearerAuth.yaml',
'components/links/UserCreatedLink.yaml',
'components/callbacks/NewMessageCallback.yaml',
'webhooks/messageCreated.yaml',
'paths/users.yaml'
];
// Test various component directory patterns
const paths = [
'components/schemas/Error.yaml',
'components/parameters/CommonPagination.yaml',
'components/responses/ErrorResponse.yaml',
'components/requestBodies/UserCreateBody.yaml',
'components/headers/RateLimitHeaders.yaml',
'components/examples/UserExample.yaml',
'components/securitySchemes/BearerAuth.yaml',
'components/links/UserCreatedLink.yaml',
'components/callbacks/NewMessageCallback.yaml',
'webhooks/messageCreated.yaml',
'paths/users.yaml'
];
paths.forEach(path => {
// @ts-expect-error We are mocking things here
const result = parser?.parse(componentYaml, { filepath: path });
expect(result).toBeDefined();
expect(result?.type).toBe('openapi');
expect(result?.format).toBe('yaml');
paths.forEach(path => {
// @ts-expect-error We are mocking things here
const result = parser?.parse(componentYaml, { filepath: path });
expect(result).toBeDefined();
expect(result?.isOpenAPI).toBeTrue();
expect(result?.format).toBe('yaml');
});
});
});
});