Skip to content

Commit

Permalink
Pseudo DI: Allow to override GenGen services (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
sevaru authored Mar 16, 2022
1 parent 272da60 commit 93baa54
Show file tree
Hide file tree
Showing 23 changed files with 9,435 additions and 18,277 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:

steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.19.0
uses: actions/setup-node@v1
- name: Use Node.js 16.14.0
uses: actions/setup-node@v2
with:
node-version: 12.19.0
node-version: '16.14.0'
- run: npm ci
- run: npm run build
- run: npm t
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/setup-node@v2
with:
node-version: 12
node-version: '16.14.0'
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm run build
Expand Down
14 changes: 13 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
__mocks__/
__tests__/
.generated/
.github/
.output/
.snapshot/
.vscode/
.generated/
e2e/
src/
.eslintignore
.eslintrc
.prettierignore
.prettierrc
jest.config.js
swagger.json
tsconfig.json
9 changes: 5 additions & 4 deletions __mocks__/MockOpenAPIService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { IOpenAPI3ObjectSchema } from '../src/swagger/v3/schemas/object-schema';

export class MockOpenAPIService extends OpenAPIService {
constructor(
typesGuard: OpenAPITypesGuard,
public getRefSchemaResult: IOpenAPI3ObjectSchema | IOpenAPI3EnumSchema | undefined = undefined) {
super('{ "openapi": "3.0.1" }', typesGuard);
typesGuard: OpenAPITypesGuard,
public getRefSchemaResult: IOpenAPI3ObjectSchema | IOpenAPI3EnumSchema | undefined = undefined
) {
super(JSON.parse('{ "openapi": "3.0.1" }'), typesGuard);
}

public getRefSchema(reference: IOpenAPI3Reference): IOpenAPI3ObjectSchema | IOpenAPI3EnumSchema | undefined {
return this.getRefSchemaResult;
}
}
}
21 changes: 13 additions & 8 deletions __tests__/services/EndpointsService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { OpenAPIService } from '../../src/swagger/OpenAPIService';
import { OpenAPITypesGuard } from '../../src/swagger/OpenAPITypesGuard';

describe('EndpointsService tests', () => {
function getService(spec: string): EndpointsService {
const openApiService = new OpenAPIService(spec, new OpenAPITypesGuard());
function getService(specJson: string): EndpointsService {
const openApiService = new OpenAPIService(JSON.parse(specJson), new OpenAPITypesGuard());
return new EndpointsService(openApiService, new EndpointNameResolver());
}

Expand All @@ -28,10 +28,10 @@ describe('EndpointsService tests', () => {
};

const expected = {
Category: { addCategory: "/api/v1/Category/AddCategory" },
Category: { addCategory: '/api/v1/Category/AddCategory' },
Product: {
getProducts: "/Product/GetProducts",
searchProducts: "/Product/SearchProducts",
getProducts: '/Product/GetProducts',
searchProducts: '/Product/SearchProducts'
}
};

Expand Down Expand Up @@ -85,8 +85,13 @@ describe('EndpointsService tests', () => {
get: { tags: ['Product'] }
}
}
}
const expected = new Set(['/Product/GetProducts', '/Product/SearchProducts', '/api/v1/Category/AddCategory', '/api/v1/Product/Product/{id}']);
};
const expected = new Set([
'/Product/GetProducts',
'/Product/SearchProducts',
'/api/v1/Category/AddCategory',
'/api/v1/Product/Product/{id}'
]);
const service = getService(JSON.stringify(spec));

// Act
Expand All @@ -108,7 +113,7 @@ describe('EndpointsService tests', () => {
const service = getService(JSON.stringify(spec));

// Act
const result = service.parse('/Product/SearchProducts')
const result = service.parse('/Product/SearchProducts');

// Assert
expect(result).toMatchObject({
Expand Down
91 changes: 54 additions & 37 deletions __tests__/swagger/OpenAPIService.spec.ts
Original file line number Diff line number Diff line change
@@ -1,79 +1,86 @@
import { MethodOperation } from '../../src/models/kinds/MethodOperation';
import { OpenAPIService } from '../../src/swagger/OpenAPIService';
import { OpenAPITypesGuard } from '../../src/swagger/OpenAPITypesGuard';
import { IOpenAPI3 } from '../../src/swagger/v3/open-api';

describe('OpenAPIService tests', () => {
let guard: OpenAPITypesGuard;
beforeEach(() => (guard = new OpenAPITypesGuard()));
const defaultSpec: IOpenAPI3 = {
components: { schemas: {} },
openapi: '',
paths: {}
};

describe('ctor', () => {
test('old OpenApi version', () => {
const spec = { version: '1.0.1' };
expect(() => new OpenAPIService(JSON.stringify(spec), guard)).toThrow('Only OpenApi version 3 supported yet.');
const spec = { ...defaultSpec, openapi: '1.0.1' };
expect(() => new OpenAPIService(spec, guard)).toThrow('Only OpenApi version 3 supported yet.');
});

test('future OpenApi version', () => {
const spec = { openapi: '4.0.1' };
expect(() => new OpenAPIService(JSON.stringify(spec), guard)).toThrow('Only OpenApi version 3 supported yet.');
const spec = { ...defaultSpec, openapi: '4.0.1' };
expect(() => new OpenAPIService(spec, guard)).toThrow('Only OpenApi version 3 supported yet.');
});
});

test('getSchemaKey', () => {
const spec = { openapi: '3.0.1' };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1' };
const service = new OpenAPIService(spec, guard);
expect(service.getSchemaKey({ $ref: '#/components/schemas/Product' })).toEqual('Product');
});

describe('getEndpoints', () => {
test('not found', () => {
const spec = { openapi: '3.0.1' };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1' };
const service = new OpenAPIService(spec, guard);
expect(service.getEndpoints()).toEqual([]);
});

test('sorted', () => {
const spec = {
const spec: IOpenAPI3 = {
openapi: '3.0.1',
paths: { '/product/SearchProducts': {}, '/api/v1/Category/AddCategory': {}, '/product/GetProducts': {} }
paths: { '/product/SearchProducts': {}, '/api/v1/Category/AddCategory': {}, '/product/GetProducts': {} },
components: { schemas: {} }
};
const service = new OpenAPIService(JSON.stringify(spec), guard);
const service = new OpenAPIService(spec, guard);
expect(service.getEndpoints()).toEqual(['/api/v1/Category/AddCategory', '/product/GetProducts', '/product/SearchProducts']);
});
});

describe('getTagsByEndpoint', () => {
test('not found path', () => {
const spec = { openapi: '3.0.1' };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1' };
const service = new OpenAPIService(spec, guard);
expect(service.getTagsByEndpoint('test')).toEqual([]);
});

test('not found path item', () => {
const spec = { openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(spec, guard);
expect(service.getTagsByEndpoint('test')).toEqual([]);
});

test.each(['get', 'post', 'put', 'delete'])('find', (operation) => {
const operationObject: Record<string, { tags: string[] }> = {};
operationObject[operation] = { tags: ['1', '2'] };

const spec = { openapi: '3.0.1', paths: { test: operationObject } };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1', paths: { test: operationObject } };
const service = new OpenAPIService(spec, guard);
expect(service.getTagsByEndpoint('test')).toEqual(['1', '2']);
});
});

describe('getOperationsByEndpoints', () => {
test('not found path', () => {
const spec = { openapi: '3.0.1' };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1' };
const service = new OpenAPIService(spec, guard);
expect(service.getOperationsByEndpoints(new Set('test'))).toEqual({});
});

test('not found path item', () => {
const spec = { openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(spec, guard);
expect(service.getOperationsByEndpoints(new Set('test'))).toEqual({});
});

Expand All @@ -86,8 +93,8 @@ describe('OpenAPIService tests', () => {
const operationObject: Record<string, { tags: string[] }> = {};
operationObject[operation] = { tags: ['1', '2'] };

const spec = { openapi: '3.0.1', paths: { test: operationObject, test2: operationObject } };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1', paths: { test: operationObject, test2: operationObject } };
const service = new OpenAPIService(spec, guard);
expect(service.getOperationsByEndpoints(new Set(['test', 'test2']))).toMatchObject({
test: [{ operation: operationObject[operation], method: method }],
test2: [{ operation: operationObject[operation], method: method }]
Expand All @@ -97,13 +104,13 @@ describe('OpenAPIService tests', () => {

describe('getSchemasByEndpoints', () => {
test('undefined', () => {
const spec = { openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(JSON.stringify(spec), guard);
const spec = { ...defaultSpec, openapi: '3.0.1', paths: { '/product/SearchProducts': {} } };
const service = new OpenAPIService(spec, guard);
expect(service.getSchemasByEndpoints(new Set<string>())).toEqual({});
});

test('recursion', () => {
const spec = {
const spec: IOpenAPI3 = {
openapi: '3.0.1',
paths: {
'/product/test': {
Expand All @@ -112,9 +119,9 @@ describe('OpenAPIService tests', () => {
200: {
description: 'Success',
content: {
"application/json": {
'application/json': {
schema: {
$ref: "#/components/schemas/SimpleObject"
$ref: '#/components/schemas/SimpleObject'
}
}
}
Expand All @@ -130,9 +137,9 @@ describe('OpenAPIService tests', () => {
properties: {
id: { type: 'string', format: 'uuid' },
children: {
type: "array",
type: 'array',
items: {
$ref: "#/components/schemas/SimpleObject"
$ref: '#/components/schemas/SimpleObject'
},
nullable: true
}
Expand All @@ -142,27 +149,32 @@ describe('OpenAPIService tests', () => {
}
};

const service = new OpenAPIService(JSON.stringify(spec), guard);
const service = new OpenAPIService(spec, guard);
const endpoints = service.getEndpoints();
expect(service.getSchemasByEndpoints(new Set<string>(endpoints))).toEqual(spec.components.schemas);
});

test('all', () => {
const spec = {
const spec: IOpenAPI3 = {
openapi: '3.0.1',
paths: {
'/product/Get': {
get: {
parameters: [
{
in: 'query',
name: 'id',
schema: {
type: 'string',
format: 'uuid'
}
},
{
$ref: '#/components/schemas/FistEnum'
in: 'query',
name: 'name2',
schema: {
$ref: '#/components/schemas/FistEnum'
}
}
],
responses: {
Expand All @@ -182,13 +194,18 @@ describe('OpenAPIService tests', () => {
post: {
parameters: [
{
in: 'path',
name: 'name',
schema: {
type: 'string'
}
},
{
$ref: '#/components/schemas/FistEnum'
name: 'name2',
in: 'query',
schema: {
$ref: '#/components/schemas/FistEnum'
}
}
],
requestBody: {
Expand Down Expand Up @@ -253,7 +270,7 @@ describe('OpenAPIService tests', () => {
delete: {
requestBody: {
content: {
'application/json-patch+json': {
'application/json': {
schema: {
$ref: '#/components/schemas/SimpleObject'
}
Expand Down Expand Up @@ -321,13 +338,13 @@ describe('OpenAPIService tests', () => {
},
EmptyObject: {
type: 'object',
additionalProperties: false
properties: {}
}
}
}
};

const service = new OpenAPIService(JSON.stringify(spec), guard);
const service = new OpenAPIService(spec, guard);
const endpoints = service.getEndpoints();
expect(service.getSchemasByEndpoints(new Set<string>(endpoints))).toMatchObject(spec.components.schemas);
});
Expand Down
Loading

0 comments on commit 93baa54

Please sign in to comment.