Skip to content

Commit

Permalink
fix: If a name is defined, should be used the defined name (#564)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiho-kr authored Jun 4, 2024
1 parent 3b8fc3a commit d06ceb5
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 3 deletions.
152 changes: 152 additions & 0 deletions spec/exclude-swagger/exclude-swagger-resonse-name.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Controller, Module, type INestApplication } from '@nestjs/common';
import { OmitType, PickType } from '@nestjs/swagger';
import { Test } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';

import { Crud } from '../../src/lib/crud.decorator';
import { CrudController } from '../../src/lib/interface';
import { BaseEntity } from '../base/base.entity';
import { BaseService } from '../base/base.service';
import { TestHelper } from '../test.helper';

import type { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';
import type { DenormalizedDoc } from '@nestjs/swagger/dist/interfaces/denormalized-doc.interface';
import type { TestingModule } from '@nestjs/testing';

class OmitTypeDto extends OmitType(BaseEntity, ['description']) {}
class PickTypeDto extends PickType(BaseEntity, ['name']) {}

@Crud({
entity: BaseEntity,
routes: {
recover: { swagger: { hide: true } },
readOne: { swagger: { response: OmitTypeDto } },
create: { swagger: { body: PickTypeDto } },
update: { swagger: { response: OmitTypeDto } },
},
})
@Controller('exclude-swagger')
export class ExcludeSwaggerController implements CrudController<BaseEntity> {
constructor(public readonly crudService: BaseService) {}
}

@Module({
imports: [TypeOrmModule.forFeature([BaseEntity])],
controllers: [ExcludeSwaggerController],
providers: [BaseService],
})
export class ExcludeSwaggerModule {}

describe('exclude swagger > defined name', () => {
let app: INestApplication;
let controller: ExcludeSwaggerController;
let routeSet: Record<string, DenormalizedDoc>;

beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [ExcludeSwaggerModule, TestHelper.getTypeOrmMysqlModule([BaseEntity])],
}).compile();

app = moduleFixture.createNestApplication();
controller = moduleFixture.get<ExcludeSwaggerController>(ExcludeSwaggerController);

await app.init();

routeSet = TestHelper.getSwaggerExplorer({
instance: controller,
metatype: ExcludeSwaggerController,
} as InstanceWrapper<ExcludeSwaggerController>);
});

afterAll(async () => {
await TestHelper.dropTypeOrmEntityTables();
await app?.close();
});

it('should not generate recover route in swagger', async () => {
const recover = 'post /exclude-swagger/{id}/recover';
expect(routeSet[recover]).toBeUndefined();
});

it('Should be changed swagger readOne response interface', () => {
const readOne = 'get /exclude-swagger/{id}';
expect(routeSet[readOne].responses).toEqual({
'200': {
content: {
'application/json': {
schema: { $ref: '#/components/schemas/OmitTypeDto' },
},
},
description: 'Fetch one entity from Base table',
},
'400': {
description: 'Entity that does not exist',
},
'422': {
description: 'Invalid field',
},
});
expect(routeSet[readOne].root?.method).toEqual('get');
expect(routeSet[readOne].root?.summary).toEqual("Read one from 'Base' Table");
expect(routeSet[readOne].root?.description).toEqual("Fetch one entity in 'Base' Table");
});

it('Should be changed swagger update response interface', () => {
const update = 'patch /exclude-swagger/{id}';
expect(routeSet[update].responses).toEqual({
'200': {
content: {
'application/json': {
schema: { $ref: '#/components/schemas/OmitTypeDto' },
},
},
description: 'Updated ok',
},
'404': {
description: 'Not found entity',
},
'422': {
description: 'Invalid field',
},
});
expect(routeSet[update].root?.method).toEqual('patch');
expect(routeSet[update].root?.summary).toEqual("update one in 'Base' Table");
expect(routeSet[update].root?.description).toEqual("Update on entity in 'Base' Table");
});

it('Should be changed swagger Create request body interface', () => {
const create = 'post /exclude-swagger';
expect(routeSet[create].root).toEqual({
method: 'post',
path: '/exclude-swagger',
operationId: 'reservedCreate',
summary: "create one to 'Base' Table",
description: "Create an entity in 'Base' Table",
parameters: [],
requestBody: {
description: 'CreateBaseDto',
required: true,
content: {
'application/json': {
schema: {
$ref: '#/components/schemas/PickTypeDto',
anyOf: [
{
$ref: '#/components/schemas/PickTypeDto',
},
{
items: {
$ref: '#/components/schemas/PickTypeDto',
},
type: 'array',
},
],
type: 'object',
},
},
},
},
});
});
});
8 changes: 5 additions & 3 deletions src/lib/crud.route.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,11 @@ export class CrudRouteFactory {
}
if (CRUD_POLICY[method].useBody) {
const bodyType = (() => {
const routeConfig = this.crudOptions.routes?.[method];
if (routeConfig?.swagger?.body) {
return this.generalTypeGuard(routeConfig.swagger.body, method, 'body');
const customBody = this.crudOptions.routes?.[method]?.swagger?.body;
if (customBody) {
return ['PickTypeClass', 'OmitTypeClass'].includes(customBody.name)
? this.generalTypeGuard(customBody, method, 'body')
: customBody;
}
if (method === Method.SEARCH) {
return RequestSearchDto;
Expand Down

0 comments on commit d06ceb5

Please sign in to comment.