mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
269 lines
7.5 KiB
TypeScript
269 lines
7.5 KiB
TypeScript
import { BadRequestException, Module, Post } from '@nestjs/common';
|
|
import { MODULE_PATH } from '@nestjs/common/constants';
|
|
import { expect } from 'chai';
|
|
import * as sinon from 'sinon';
|
|
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
|
import { Get } from '../../../common/decorators/http/request-mapping.decorator';
|
|
import { ApplicationConfig } from '../../application-config';
|
|
import { NestContainer } from '../../injector';
|
|
import { Injector } from '../../injector/injector';
|
|
import { InstanceWrapper } from '../../injector/instance-wrapper';
|
|
import { RoutesResolver } from '../../router/routes-resolver';
|
|
import { NoopHttpAdapter } from '../utils/noop-adapter.spec';
|
|
|
|
describe('RoutesResolver', () => {
|
|
@Controller('global')
|
|
class TestRoute {
|
|
@Get('test')
|
|
public getTest() {}
|
|
|
|
@Post('another-test')
|
|
public anotherTest() {}
|
|
}
|
|
|
|
@Controller({ host: 'api.example.com' })
|
|
class TestHostRoute {
|
|
@Get()
|
|
public getTest() {}
|
|
}
|
|
|
|
@Module({
|
|
controllers: [TestRoute],
|
|
})
|
|
class TestModule {}
|
|
|
|
@Module({
|
|
controllers: [TestRoute],
|
|
})
|
|
class TestModule2 {}
|
|
|
|
let router: any;
|
|
let routesResolver: RoutesResolver;
|
|
let container: NestContainer;
|
|
let modules: Map<string, any>;
|
|
let applicationRef: any;
|
|
|
|
beforeEach(() => {
|
|
modules = new Map();
|
|
applicationRef = {
|
|
use: () => ({}),
|
|
setNotFoundHandler: sinon.spy(),
|
|
setErrorHandler: sinon.spy(),
|
|
} as any;
|
|
container = {
|
|
getModules: () => modules,
|
|
getModuleByKey: (key: string) => modules.get(key),
|
|
getHttpAdapterRef: () => applicationRef,
|
|
} as any;
|
|
router = {
|
|
get() {},
|
|
post() {},
|
|
};
|
|
});
|
|
|
|
beforeEach(() => {
|
|
routesResolver = new RoutesResolver(
|
|
container,
|
|
new ApplicationConfig(),
|
|
new Injector(),
|
|
);
|
|
});
|
|
|
|
describe('registerRouters', () => {
|
|
it('should register controllers to router instance', () => {
|
|
const routes = new Map();
|
|
const routeWrapper = new InstanceWrapper({
|
|
instance: new TestRoute(),
|
|
metatype: TestRoute,
|
|
});
|
|
routes.set('TestRoute', routeWrapper);
|
|
|
|
const appInstance = new NoopHttpAdapter(router);
|
|
const exploreSpy = sinon.spy(
|
|
(routesResolver as any).routerExplorer,
|
|
'explore',
|
|
);
|
|
const moduleName = '';
|
|
modules.set(moduleName, {});
|
|
|
|
sinon
|
|
.stub((routesResolver as any).routerExplorer, 'extractRouterPath')
|
|
.callsFake(() => ['']);
|
|
routesResolver.registerRouters(routes, moduleName, '', appInstance);
|
|
|
|
expect(exploreSpy.called).to.be.true;
|
|
expect(exploreSpy.calledWith(routeWrapper, moduleName, appInstance, ''))
|
|
.to.be.true;
|
|
});
|
|
|
|
it('should register with host when specified', () => {
|
|
const routes = new Map();
|
|
const routeWrapper = new InstanceWrapper({
|
|
instance: new TestHostRoute(),
|
|
metatype: TestHostRoute,
|
|
});
|
|
routes.set('TestHostRoute', routeWrapper);
|
|
|
|
const appInstance = new NoopHttpAdapter(router);
|
|
const exploreSpy = sinon.spy(
|
|
(routesResolver as any).routerExplorer,
|
|
'explore',
|
|
);
|
|
const moduleName = '';
|
|
modules.set(moduleName, {});
|
|
|
|
sinon
|
|
.stub((routesResolver as any).routerExplorer, 'extractRouterPath')
|
|
.callsFake(() => ['']);
|
|
routesResolver.registerRouters(routes, moduleName, '', appInstance);
|
|
|
|
expect(exploreSpy.called).to.be.true;
|
|
expect(
|
|
exploreSpy.calledWith(
|
|
routeWrapper,
|
|
moduleName,
|
|
appInstance,
|
|
'',
|
|
'api.example.com',
|
|
),
|
|
).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('resolve', () => {
|
|
it('should call "registerRouters" for each module', () => {
|
|
const routes = new Map();
|
|
routes.set(
|
|
'TestRoute',
|
|
new InstanceWrapper({
|
|
instance: new TestRoute(),
|
|
metatype: TestRoute,
|
|
}),
|
|
);
|
|
modules.set('TestModule', { routes });
|
|
modules.set('TestModule2', { routes });
|
|
|
|
const registerRoutersStub = sinon
|
|
.stub(routesResolver, 'registerRouters')
|
|
.callsFake(() => undefined);
|
|
|
|
routesResolver.resolve({ use: sinon.spy() } as any, 'basePath');
|
|
expect(registerRoutersStub.calledTwice).to.be.true;
|
|
});
|
|
|
|
describe('registerRouters', () => {
|
|
it('should register each module with the base path and append the module path if present ', () => {
|
|
const routes = new Map();
|
|
routes.set('TestRoute', {
|
|
instance: new TestRoute(),
|
|
metatype: TestRoute,
|
|
});
|
|
|
|
Reflect.defineMetadata(MODULE_PATH, '/test', TestModule);
|
|
modules.set('TestModule', { routes, metatype: TestModule });
|
|
modules.set('TestModule2', { routes, metatype: TestModule2 });
|
|
|
|
const spy = sinon
|
|
.stub(routesResolver, 'registerRouters')
|
|
.callsFake(() => undefined);
|
|
|
|
routesResolver.resolve(applicationRef, 'api/v1');
|
|
|
|
// with module path
|
|
expect(
|
|
spy
|
|
.getCall(0)
|
|
.calledWith(
|
|
sinon.match.any,
|
|
sinon.match.any,
|
|
'api/v1/test',
|
|
sinon.match.any,
|
|
),
|
|
).to.be.true;
|
|
// without module path
|
|
expect(
|
|
spy
|
|
.getCall(1)
|
|
.calledWith(
|
|
sinon.match.any,
|
|
sinon.match.any,
|
|
'api/v1',
|
|
sinon.match.any,
|
|
),
|
|
).to.be.true;
|
|
});
|
|
|
|
it('should register each module with the module path if present', () => {
|
|
const routes = new Map();
|
|
routes.set('TestRoute', {
|
|
instance: new TestRoute(),
|
|
metatype: TestRoute,
|
|
});
|
|
|
|
Reflect.defineMetadata(MODULE_PATH, '/test', TestModule);
|
|
modules.set('TestModule', { routes, metatype: TestModule });
|
|
modules.set('TestModule2', { routes, metatype: TestModule2 });
|
|
|
|
const spy = sinon
|
|
.stub(routesResolver, 'registerRouters')
|
|
.callsFake(() => undefined);
|
|
|
|
routesResolver.resolve(applicationRef, '');
|
|
|
|
// with module path
|
|
expect(
|
|
spy
|
|
.getCall(0)
|
|
.calledWith(
|
|
sinon.match.any,
|
|
sinon.match.any,
|
|
'/test',
|
|
sinon.match.any,
|
|
),
|
|
).to.be.true;
|
|
// without module path
|
|
expect(
|
|
spy
|
|
.getCall(1)
|
|
.calledWith(sinon.match.any, sinon.match.any, '', sinon.match.any),
|
|
).to.be.true;
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('mapExternalExceptions', () => {
|
|
describe('when exception prototype is', () => {
|
|
describe('SyntaxError', () => {
|
|
it('should map to BadRequestException', () => {
|
|
const err = new SyntaxError();
|
|
const outputErr = routesResolver.mapExternalException(err);
|
|
expect(outputErr).to.be.instanceof(BadRequestException);
|
|
});
|
|
});
|
|
describe('other', () => {
|
|
it('should behave as an identity', () => {
|
|
const err = new Error();
|
|
const outputErr = routesResolver.mapExternalException(err);
|
|
expect(outputErr).to.be.eql(err);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('registerNotFoundHandler', () => {
|
|
it('should register not found handler', () => {
|
|
routesResolver.registerNotFoundHandler();
|
|
|
|
expect(applicationRef.setNotFoundHandler.called).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('registerExceptionHandler', () => {
|
|
it('should register exception handler', () => {
|
|
routesResolver.registerExceptionHandler();
|
|
|
|
expect(applicationRef.setErrorHandler.called).to.be.true;
|
|
});
|
|
});
|
|
});
|