From d44e5bf9494466937ee14de816f13911e409a09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Sat, 26 Mar 2022 22:14:37 -0300 Subject: [PATCH] test(serverless-builder): added tests to serverless builder --- src/v2/serverless-builder.ts | 65 ++++++++++++++----- test/serverless-builder.spec.ts | 111 ++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 16 deletions(-) create mode 100644 test/serverless-builder.spec.ts diff --git a/src/v2/serverless-builder.ts b/src/v2/serverless-builder.ts index 2809c4fb..5469e250 100644 --- a/src/v2/serverless-builder.ts +++ b/src/v2/serverless-builder.ts @@ -29,11 +29,12 @@ import { DEFAULT_BINARY_ENCODINGS, ILogger, createDefaultLogger } from './core'; * ``` */ export class ServerlessBuilder< - TApp = any, - TEvent = any, - TContext = any, - TCallback = any, - TResponse = any, + TApp, + TEvent, + TContext, + TCallback, + TResponse, + TReturn, > { //#region Constructor @@ -83,7 +84,7 @@ export class ServerlessBuilder< /** * The list of adapters used to handle an event's request and response */ - protected adapters: AdapterContract[] = []; + protected adapters: AdapterContract[] = []; /** * The framework that will process requests @@ -93,7 +94,13 @@ export class ServerlessBuilder< /** * The resolver that aims to resolve the response to serverless and stop its execution when the request ends */ - protected resolver?: ResolverContract; + protected resolver?: ResolverContract< + TEvent, + TContext, + TCallback, + TResponse, + TReturn + >; /** * The handler that will get the event, context and callback and pass it to the adapter and framework @@ -103,7 +110,8 @@ export class ServerlessBuilder< TEvent, TContext, TCallback, - TResponse + TResponse, + TReturn >; //#endregion @@ -115,7 +123,9 @@ export class ServerlessBuilder< * * @param app The instance of the app */ - public static new(app: TApp): Omit { + public static new( + app: TApp, + ): ServerlessBuilder { return new ServerlessBuilder(app); } @@ -129,8 +139,18 @@ export class ServerlessBuilder< * @param handler The implementation of the handler contract */ public setHandler( - handler: HandlerContract, + handler: HandlerContract< + TApp, + TEvent, + TContext, + TCallback, + TResponse, + TReturn + >, ): Omit { + if (this.handler) + throw new Error('SERVERLESS_ADAPTER: The handler should not set twice.'); + this.handler = handler; return this; @@ -141,7 +161,12 @@ export class ServerlessBuilder< * * @param resolver The implementation of the resolver contract */ - public setResolver(resolver: ResolverContract): Omit { + public setResolver( + resolver: ResolverContract, + ): Omit { + if (this.resolver) + throw new Error('SERVERLESS_ADAPTER: The resolver should not set twice.'); + this.resolver = resolver; return this; @@ -155,6 +180,12 @@ export class ServerlessBuilder< public setFramework( framework: FrameworkContract, ): Omit { + if (this.framework) { + throw new Error( + 'SERVERLESS_ADAPTER: The framework should not set twice.', + ); + } + this.framework = framework; return this; @@ -202,7 +233,9 @@ export class ServerlessBuilder< * * @param adapter The implementation of the adapter contract */ - public addAdapter(adapter: AdapterContract): this { + public addAdapter( + adapter: AdapterContract, + ): Pick { this.adapters.push(adapter); return this; @@ -211,22 +244,22 @@ export class ServerlessBuilder< /** * The builder method that returns the handler function to be exported for serverless consumption */ - public build(): ServerlessHandler { + public build(): ServerlessHandler { if (!this.resolver) { throw new Error( - 'SERVERLESS_ADAPTER: Is required to set a resolver before build the handler.', + 'SERVERLESS_ADAPTER: Is required to set a resolver before build.', ); } if (!this.framework) { throw new Error( - 'SERVERLESS_ADAPTER: Is required to set a framework before build the handler.', + 'SERVERLESS_ADAPTER: Is required to set a framework before build.', ); } if (!this.handler) { throw new Error( - 'SERVERLESS_ADAPTER: Is required to set a framework before build the handler.', + 'SERVERLESS_ADAPTER: Is required to set a handler before build.', ); } diff --git a/test/serverless-builder.spec.ts b/test/serverless-builder.spec.ts new file mode 100644 index 00000000..7d20a176 --- /dev/null +++ b/test/serverless-builder.spec.ts @@ -0,0 +1,111 @@ +import { ServerlessBuilder } from '../src/v2'; +import { BinarySettings } from '../src/v2/@types'; +import { ApiGatewayV2Adapter } from '../src/v2/adapters/aws'; +import { HandlerContract } from '../src/v2/contracts'; +import { NO_OP, createDefaultLogger } from '../src/v2/core'; +import { DefaultHandler } from '../src/v2/handlers'; +import { PromiseResolver } from '../src/v2/resolvers'; +import { FrameworkMock } from './mocks/framework.mock'; + +describe('ServerlessBuilder', () => { + it('should can create a pipeline of handlers', () => { + const statusCode = 200; + const response = { body: true }; + const app = null; + + const mockedHandler: HandlerContract = { + getHandler: jest.fn(() => NO_OP), + }; + + const adapter = new ApiGatewayV2Adapter(); + const logger = createDefaultLogger(); + const respondWithErrors = false; + const resolver = new PromiseResolver(); + const framework = new FrameworkMock(statusCode, response); + const binarySettings: BinarySettings = { isBinary: () => true }; + + const handler = ServerlessBuilder.new(app) + .setHandler(mockedHandler) + .setLogger(logger) + .setRespondWithErrors(respondWithErrors) + .setResolver(resolver) + .setFramework(framework) + .setBinarySettings(binarySettings) + .addAdapter(adapter) + .build(); + + expect(handler).toBe(NO_OP); + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(mockedHandler.getHandler).toHaveBeenCalledWith( + app, + framework, + [adapter], + resolver, + binarySettings, + respondWithErrors, + logger, + ); + }); + + it('should CANNOT set handler twice', () => { + const handler = new DefaultHandler(); + + expect(() => + ServerlessBuilder.new(null) + .setHandler(handler) + .setRespondWithErrors(true) + .setHandler(handler), + ).toThrow('twice'); + }); + + it('should CANNOT set framework twice', () => { + const framework = new FrameworkMock(200, {}); + + expect(() => + ServerlessBuilder.new(null) + .setFramework(framework) + .setRespondWithErrors(true) + .setFramework(framework), + ).toThrow('twice'); + }); + + it('should CANNOT set resolver twice', () => { + const resolver = new PromiseResolver(); + + expect(() => + ServerlessBuilder.new(null) + .setResolver(resolver) + .setRespondWithErrors(true) + .setResolver(resolver), + ).toThrow('twice'); + }); + + it('should CANNOT build without set resolver', () => { + expect(() => ServerlessBuilder.new(null).build()).toThrow('set a resolver'); + }); + + it('should CANNOT build without set framework', () => { + expect(() => + ServerlessBuilder.new(null).setResolver(new PromiseResolver()).build(), + ).toThrow('set a framework'); + }); + + it('should CANNOT build without set handler', () => { + expect(() => + ServerlessBuilder.new(null) + .setResolver(new PromiseResolver()) + .setFramework(new FrameworkMock(200, {})) + .build(), + ).toThrow('set a handler'); + }); + + it('should CANNOT build without set at least one adapter', () => { + expect(() => + ServerlessBuilder.new(null) + .setResolver(new PromiseResolver()) + .setFramework(new FrameworkMock(200, {})) + .setHandler(new DefaultHandler()) + .build(), + ).toThrow('one adapter'); + }); +});