mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
254 lines
7.5 KiB
TypeScript
254 lines
7.5 KiB
TypeScript
import { expect } from 'chai';
|
|
import * as sinon from 'sinon';
|
|
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
|
import {
|
|
All,
|
|
Get,
|
|
Post,
|
|
} from '../../../common/decorators/http/request-mapping.decorator';
|
|
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
|
import { Injector } from '../../../core/injector/injector';
|
|
import { ApplicationConfig } from '../../application-config';
|
|
import { ExecutionContextHost } from '../../helpers/execution-context-host';
|
|
import { NestContainer } from '../../injector/container';
|
|
import { InstanceWrapper } from '../../injector/instance-wrapper';
|
|
import { MetadataScanner } from '../../metadata-scanner';
|
|
import { RouterExceptionFilters } from '../../router/router-exception-filters';
|
|
import { RouterExplorer } from '../../router/router-explorer';
|
|
|
|
describe('RouterExplorer', () => {
|
|
@Controller('global')
|
|
class TestRoute {
|
|
@Get('test')
|
|
public getTest() {}
|
|
|
|
@Post('test')
|
|
public postTest() {}
|
|
|
|
@All('another-test')
|
|
public anotherTest() {}
|
|
|
|
@Get(['foo', 'bar'])
|
|
public getTestUsingArray() {}
|
|
}
|
|
|
|
@Controller(['global', 'global-alias'])
|
|
class TestRouteAlias {
|
|
@Get('test')
|
|
public getTest() {}
|
|
|
|
@Post('test')
|
|
public postTest() {}
|
|
|
|
@All('another-test')
|
|
public anotherTest() {}
|
|
|
|
@Get(['foo', 'bar'])
|
|
public getTestUsingArray() {}
|
|
}
|
|
|
|
let routerBuilder: RouterExplorer;
|
|
let injector: Injector;
|
|
let exceptionsFilter: RouterExceptionFilters;
|
|
|
|
beforeEach(() => {
|
|
const container = new NestContainer();
|
|
|
|
injector = new Injector();
|
|
exceptionsFilter = new RouterExceptionFilters(
|
|
container,
|
|
new ApplicationConfig(),
|
|
null,
|
|
);
|
|
routerBuilder = new RouterExplorer(
|
|
new MetadataScanner(),
|
|
container,
|
|
injector,
|
|
null,
|
|
exceptionsFilter,
|
|
);
|
|
});
|
|
|
|
describe('scanForPaths', () => {
|
|
it('should method return expected list of route paths', () => {
|
|
const paths = routerBuilder.scanForPaths(new TestRoute());
|
|
|
|
expect(paths).to.have.length(4);
|
|
|
|
expect(paths[0].path).to.eql(['/test']);
|
|
expect(paths[1].path).to.eql(['/test']);
|
|
expect(paths[2].path).to.eql(['/another-test']);
|
|
expect(paths[3].path).to.eql(['/foo', '/bar']);
|
|
|
|
expect(paths[0].requestMethod).to.eql(RequestMethod.GET);
|
|
expect(paths[1].requestMethod).to.eql(RequestMethod.POST);
|
|
expect(paths[2].requestMethod).to.eql(RequestMethod.ALL);
|
|
expect(paths[3].requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
|
|
it('should method return expected list of route paths alias', () => {
|
|
const paths = routerBuilder.scanForPaths(new TestRouteAlias());
|
|
|
|
expect(paths).to.have.length(4);
|
|
|
|
expect(paths[0].path).to.eql(['/test']);
|
|
expect(paths[1].path).to.eql(['/test']);
|
|
expect(paths[2].path).to.eql(['/another-test']);
|
|
expect(paths[3].path).to.eql(['/foo', '/bar']);
|
|
|
|
expect(paths[0].requestMethod).to.eql(RequestMethod.GET);
|
|
expect(paths[1].requestMethod).to.eql(RequestMethod.POST);
|
|
expect(paths[2].requestMethod).to.eql(RequestMethod.ALL);
|
|
expect(paths[3].requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
});
|
|
|
|
describe('exploreMethodMetadata', () => {
|
|
it('should method return expected object which represent single route', () => {
|
|
const instance = new TestRoute();
|
|
const instanceProto = Object.getPrototypeOf(instance);
|
|
|
|
const route = routerBuilder.exploreMethodMetadata(
|
|
new TestRoute(),
|
|
instanceProto,
|
|
'getTest',
|
|
);
|
|
|
|
expect(route.path).to.eql(['/test']);
|
|
expect(route.requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
|
|
it('should method return expected object which represent single route with alias', () => {
|
|
const instance = new TestRouteAlias();
|
|
const instanceProto = Object.getPrototypeOf(instance);
|
|
|
|
const route = routerBuilder.exploreMethodMetadata(
|
|
new TestRouteAlias(),
|
|
instanceProto,
|
|
'getTest',
|
|
);
|
|
|
|
expect(route.path).to.eql(['/test']);
|
|
expect(route.requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
|
|
it('should method return expected object which represent multiple routes', () => {
|
|
const instance = new TestRoute();
|
|
const instanceProto = Object.getPrototypeOf(instance);
|
|
|
|
const route = routerBuilder.exploreMethodMetadata(
|
|
new TestRoute(),
|
|
instanceProto,
|
|
'getTestUsingArray',
|
|
);
|
|
|
|
expect(route.path).to.eql(['/foo', '/bar']);
|
|
expect(route.requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
|
|
it('should method return expected object which represent multiple routes with alias', () => {
|
|
const instance = new TestRouteAlias();
|
|
const instanceProto = Object.getPrototypeOf(instance);
|
|
|
|
const route = routerBuilder.exploreMethodMetadata(
|
|
new TestRouteAlias(),
|
|
instanceProto,
|
|
'getTestUsingArray',
|
|
);
|
|
|
|
expect(route.path).to.eql(['/foo', '/bar']);
|
|
expect(route.requestMethod).to.eql(RequestMethod.GET);
|
|
});
|
|
});
|
|
|
|
describe('applyPathsToRouterProxy', () => {
|
|
it('should method return expected object which represent single route', () => {
|
|
const bindStub = sinon.stub(
|
|
routerBuilder,
|
|
'applyCallbackToRouter' as any,
|
|
);
|
|
const paths = [
|
|
{ path: [''], requestMethod: RequestMethod.GET },
|
|
{ path: ['test'], requestMethod: RequestMethod.GET },
|
|
{ path: ['foo', 'bar'], requestMethod: RequestMethod.GET },
|
|
];
|
|
|
|
routerBuilder.applyPathsToRouterProxy(
|
|
null,
|
|
paths as any,
|
|
null,
|
|
'',
|
|
'',
|
|
'',
|
|
);
|
|
|
|
expect(bindStub.calledWith(null, paths[0], null)).to.be.true;
|
|
expect(bindStub.callCount).to.be.eql(paths.length);
|
|
});
|
|
});
|
|
|
|
describe('extractRouterPath', () => {
|
|
it('should return expected path', () => {
|
|
expect(routerBuilder.extractRouterPath(TestRoute)).to.be.eql(['/global']);
|
|
expect(routerBuilder.extractRouterPath(TestRoute, '/module')).to.be.eql([
|
|
'/module/global',
|
|
]);
|
|
});
|
|
|
|
it('should return expected path with alias', () => {
|
|
expect(routerBuilder.extractRouterPath(TestRouteAlias)).to.be.eql([
|
|
'/global',
|
|
'/global-alias',
|
|
]);
|
|
expect(
|
|
routerBuilder.extractRouterPath(TestRouteAlias, '/module'),
|
|
).to.be.eql(['/module/global', '/module/global-alias']);
|
|
});
|
|
});
|
|
|
|
describe('createRequestScopedHandler', () => {
|
|
let nextSpy: sinon.SinonSpy;
|
|
|
|
beforeEach(() => {
|
|
sinon.stub(injector, 'loadPerContext').callsFake(() => {
|
|
throw new Error();
|
|
});
|
|
nextSpy = sinon.spy();
|
|
sinon.stub(exceptionsFilter, 'create').callsFake(
|
|
() =>
|
|
({
|
|
next: nextSpy,
|
|
} as any),
|
|
);
|
|
});
|
|
|
|
describe('when "loadPerContext" throws', () => {
|
|
const moduleKey = 'moduleKey';
|
|
const methodKey = 'methodKey';
|
|
const module = {
|
|
controllers: new Map(),
|
|
} as any;
|
|
const wrapper = new InstanceWrapper({
|
|
instance: { [methodKey]: {} },
|
|
});
|
|
|
|
it('should delegete error to exception filters', async () => {
|
|
const handler = routerBuilder.createRequestScopedHandler(
|
|
wrapper,
|
|
RequestMethod.ALL,
|
|
module,
|
|
moduleKey,
|
|
methodKey,
|
|
);
|
|
await handler(null, null, null);
|
|
|
|
expect(nextSpy.called).to.be.true;
|
|
expect(nextSpy.getCall(0).args[0]).to.be.instanceOf(Error);
|
|
expect(nextSpy.getCall(0).args[1]).to.be.instanceOf(
|
|
ExecutionContextHost,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
});
|