mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
272 lines
8.5 KiB
TypeScript
272 lines
8.5 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { RoutePathFactory } from '@nestjs/core/router/route-path-factory';
|
|
import * as chai from 'chai';
|
|
import { expect } from 'chai';
|
|
import * as chaiAsPromised from 'chai-as-promised';
|
|
import * as sinon from 'sinon';
|
|
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
|
import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator';
|
|
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
|
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
|
|
import { ApplicationConfig } from '../../application-config';
|
|
import { InvalidMiddlewareException } from '../../errors/exceptions/invalid-middleware.exception';
|
|
import { RuntimeException } from '../../errors/exceptions/runtime.exception';
|
|
import { NestContainer } from '../../injector/container';
|
|
import { InstanceWrapper } from '../../injector/instance-wrapper';
|
|
import { Module } from '../../injector/module';
|
|
import { GraphInspector } from '../../inspector/graph-inspector';
|
|
import { MiddlewareBuilder } from '../../middleware/builder';
|
|
import { MiddlewareContainer } from '../../middleware/container';
|
|
import { MiddlewareModule } from '../../middleware/middleware-module';
|
|
import { RouterExceptionFilters } from '../../router/router-exception-filters';
|
|
import { NoopHttpAdapter } from '../utils/noop-adapter.spec';
|
|
|
|
chai.use(chaiAsPromised);
|
|
|
|
describe('MiddlewareModule', () => {
|
|
let middlewareModule: MiddlewareModule;
|
|
let graphInspector: GraphInspector;
|
|
|
|
@Controller('test')
|
|
class BasicController {}
|
|
|
|
@Controller('test')
|
|
class BaseController {
|
|
@RequestMapping({ path: 'test' })
|
|
public getTest() {}
|
|
|
|
@RequestMapping({ path: 'another', method: RequestMethod.DELETE })
|
|
public getAnother() {}
|
|
}
|
|
|
|
@Injectable()
|
|
class TestMiddleware implements NestMiddleware {
|
|
public use(req, res, next) {}
|
|
}
|
|
|
|
beforeEach(() => {
|
|
const container = new NestContainer();
|
|
const appConfig = new ApplicationConfig();
|
|
|
|
graphInspector = new GraphInspector(container);
|
|
middlewareModule = new MiddlewareModule(new RoutePathFactory(appConfig));
|
|
middlewareModule['routerExceptionFilter'] = new RouterExceptionFilters(
|
|
container,
|
|
appConfig,
|
|
new NoopHttpAdapter({}),
|
|
);
|
|
middlewareModule['config'] = appConfig;
|
|
middlewareModule['graphInspector'] = graphInspector;
|
|
});
|
|
|
|
describe('loadConfiguration', () => {
|
|
it('should call "configure" method if method is implemented', async () => {
|
|
const stubContainer = new NestContainer();
|
|
stubContainer
|
|
.getModules()
|
|
.set('Test', new Module(class {}, stubContainer));
|
|
|
|
const configureSpy = sinon.spy();
|
|
const mockModule = {
|
|
instance: {
|
|
configure: configureSpy,
|
|
},
|
|
};
|
|
|
|
(middlewareModule as any).container = stubContainer;
|
|
await middlewareModule.loadConfiguration(
|
|
new MiddlewareContainer(stubContainer),
|
|
mockModule as any,
|
|
'Test',
|
|
);
|
|
|
|
expect(configureSpy.calledOnce).to.be.true;
|
|
expect(
|
|
configureSpy.calledWith(
|
|
new MiddlewareBuilder(
|
|
(middlewareModule as any).routesMapper,
|
|
undefined,
|
|
),
|
|
),
|
|
).to.be.true;
|
|
});
|
|
});
|
|
|
|
describe('registerRouteMiddleware', () => {
|
|
class TestModule {}
|
|
|
|
let nestContainer: NestContainer;
|
|
|
|
beforeEach(() => {
|
|
nestContainer = new NestContainer();
|
|
nestContainer
|
|
.getModules()
|
|
.set('Test', new Module(TestModule, nestContainer));
|
|
});
|
|
it('should throw "RuntimeException" exception when middleware is not stored in container', () => {
|
|
const route = { path: 'Test' };
|
|
const configuration = {
|
|
middleware: [TestMiddleware],
|
|
forRoutes: [BaseController],
|
|
};
|
|
const useSpy = sinon.spy();
|
|
const app = { use: useSpy };
|
|
|
|
middlewareModule['container'] = nestContainer;
|
|
|
|
expect(
|
|
middlewareModule.registerRouteMiddleware(
|
|
new MiddlewareContainer(nestContainer),
|
|
route as any,
|
|
configuration,
|
|
'Test',
|
|
app,
|
|
),
|
|
).to.eventually.be.rejectedWith(RuntimeException);
|
|
});
|
|
|
|
it('should throw "InvalidMiddlewareException" exception when middleware does not have "use" method', () => {
|
|
@Injectable()
|
|
class InvalidMiddleware {}
|
|
|
|
const route = { path: 'Test' };
|
|
const configuration = {
|
|
middleware: [InvalidMiddleware],
|
|
forRoutes: [BaseController],
|
|
};
|
|
|
|
const useSpy = sinon.spy();
|
|
const app = { use: useSpy };
|
|
|
|
const container = new MiddlewareContainer(nestContainer);
|
|
const moduleKey = 'Test';
|
|
container.insertConfig([configuration], moduleKey);
|
|
|
|
const instance = new InvalidMiddleware();
|
|
container.getMiddlewareCollection(moduleKey).set('InvalidMiddleware', {
|
|
metatype: InvalidMiddleware,
|
|
instance,
|
|
} as any);
|
|
|
|
expect(
|
|
middlewareModule.registerRouteMiddleware(
|
|
container,
|
|
route as any,
|
|
configuration,
|
|
moduleKey,
|
|
app,
|
|
),
|
|
).to.be.rejectedWith(InvalidMiddlewareException);
|
|
});
|
|
|
|
it('should mount middleware when is stored in container', async () => {
|
|
const route = 'testPath';
|
|
const configuration = {
|
|
middleware: [TestMiddleware],
|
|
forRoutes: ['test', BasicController, BaseController],
|
|
};
|
|
|
|
const createMiddlewareFactoryStub = sinon
|
|
.stub()
|
|
.callsFake(() => () => null);
|
|
const app = {
|
|
createMiddlewareFactory: createMiddlewareFactoryStub,
|
|
};
|
|
|
|
const stubContainer = new NestContainer();
|
|
stubContainer
|
|
.getModules()
|
|
.set('Test', new Module(TestModule, stubContainer));
|
|
|
|
const container = new MiddlewareContainer(stubContainer);
|
|
const moduleKey = 'Test';
|
|
container.insertConfig([configuration], moduleKey);
|
|
|
|
const instance = new TestMiddleware();
|
|
container.getMiddlewareCollection(moduleKey).set(
|
|
TestMiddleware,
|
|
new InstanceWrapper({
|
|
metatype: TestMiddleware,
|
|
instance,
|
|
}),
|
|
);
|
|
sinon
|
|
.stub(stubContainer, 'getModuleByKey')
|
|
.callsFake(() => new Module(class {}, stubContainer));
|
|
middlewareModule['container'] = stubContainer;
|
|
|
|
await middlewareModule.registerRouteMiddleware(
|
|
container,
|
|
{ path: route, method: RequestMethod.ALL },
|
|
configuration,
|
|
moduleKey,
|
|
app,
|
|
);
|
|
expect(createMiddlewareFactoryStub.calledOnce).to.be.true;
|
|
});
|
|
|
|
it('should insert the expected middleware definition', async () => {
|
|
const route = 'testPath';
|
|
const configuration = {
|
|
middleware: [TestMiddleware],
|
|
forRoutes: ['test', BasicController, BaseController],
|
|
};
|
|
const instance = new TestMiddleware();
|
|
const instanceWrapper = new InstanceWrapper({
|
|
metatype: TestMiddleware,
|
|
instance,
|
|
name: TestMiddleware.name,
|
|
});
|
|
const createMiddlewareFactoryStub = sinon
|
|
.stub()
|
|
.callsFake(() => () => null);
|
|
const app = {
|
|
createMiddlewareFactory: createMiddlewareFactoryStub,
|
|
};
|
|
|
|
const stubContainer = new NestContainer();
|
|
stubContainer
|
|
.getModules()
|
|
.set('Test', new Module(TestModule, stubContainer));
|
|
const container = new MiddlewareContainer(stubContainer);
|
|
const moduleKey = 'Test';
|
|
container.insertConfig([configuration], moduleKey);
|
|
container
|
|
.getMiddlewareCollection(moduleKey)
|
|
.set(TestMiddleware, instanceWrapper);
|
|
sinon
|
|
.stub(stubContainer, 'getModuleByKey')
|
|
.callsFake(() => new Module(class {}, stubContainer));
|
|
middlewareModule['container'] = stubContainer;
|
|
|
|
const insertEntrypointDefinitionSpy = sinon.spy(
|
|
graphInspector,
|
|
'insertEntrypointDefinition',
|
|
);
|
|
|
|
await middlewareModule.registerRouteMiddleware(
|
|
container,
|
|
{ path: route, method: RequestMethod.ALL },
|
|
configuration,
|
|
moduleKey,
|
|
app,
|
|
);
|
|
|
|
expect(createMiddlewareFactoryStub.calledOnce).to.be.true;
|
|
expect(
|
|
insertEntrypointDefinitionSpy.calledWith({
|
|
type: 'middleware',
|
|
methodName: 'use',
|
|
className: instanceWrapper.name,
|
|
classNodeId: instanceWrapper.id,
|
|
metadata: {
|
|
path: route,
|
|
requestMethod: 'ALL',
|
|
version: undefined,
|
|
},
|
|
}),
|
|
).to.be.true;
|
|
});
|
|
});
|
|
});
|