Skip to content

Commit

Permalink
test(serverless-builder): added tests to serverless builder
Browse files Browse the repository at this point in the history
  • Loading branch information
H4ad committed Mar 27, 2022
1 parent 5ace6ba commit d44e5bf
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 16 deletions.
65 changes: 49 additions & 16 deletions src/v2/serverless-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -83,7 +84,7 @@ export class ServerlessBuilder<
/**
* The list of adapters used to handle an event's request and response
*/
protected adapters: AdapterContract<TEvent, TContext>[] = [];
protected adapters: AdapterContract<TEvent, TContext, TResponse>[] = [];

/**
* The framework that will process requests
Expand All @@ -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
Expand All @@ -103,7 +110,8 @@ export class ServerlessBuilder<
TEvent,
TContext,
TCallback,
TResponse
TResponse,
TReturn
>;

//#endregion
Expand All @@ -115,7 +123,9 @@ export class ServerlessBuilder<
*
* @param app The instance of the app
*/
public static new<TApp>(app: TApp): Omit<ServerlessBuilder, 'new'> {
public static new<TApp, TEvent, TContext, TCallback, TResponse, TReturn>(
app: TApp,
): ServerlessBuilder<TApp, TEvent, TContext, TCallback, TResponse, TReturn> {
return new ServerlessBuilder(app);
}

Expand All @@ -129,8 +139,18 @@ export class ServerlessBuilder<
* @param handler The implementation of the handler contract
*/
public setHandler(
handler: HandlerContract<TApp, TEvent, TContext, TCallback, TResponse>,
handler: HandlerContract<
TApp,
TEvent,
TContext,
TCallback,
TResponse,
TReturn
>,
): Omit<this, 'setHandler'> {
if (this.handler)
throw new Error('SERVERLESS_ADAPTER: The handler should not set twice.');

this.handler = handler;

return this;
Expand All @@ -141,7 +161,12 @@ export class ServerlessBuilder<
*
* @param resolver The implementation of the resolver contract
*/
public setResolver(resolver: ResolverContract): Omit<this, 'setResolver'> {
public setResolver(
resolver: ResolverContract<TEvent, TContext, TCallback, TResponse, TReturn>,
): Omit<this, 'setResolver'> {
if (this.resolver)
throw new Error('SERVERLESS_ADAPTER: The resolver should not set twice.');

this.resolver = resolver;

return this;
Expand All @@ -155,6 +180,12 @@ export class ServerlessBuilder<
public setFramework(
framework: FrameworkContract<TApp>,
): Omit<this, 'setFramework'> {
if (this.framework) {
throw new Error(
'SERVERLESS_ADAPTER: The framework should not set twice.',
);
}

this.framework = framework;

return this;
Expand Down Expand Up @@ -202,7 +233,9 @@ export class ServerlessBuilder<
*
* @param adapter The implementation of the adapter contract
*/
public addAdapter(adapter: AdapterContract<TEvent, TContext>): this {
public addAdapter(
adapter: AdapterContract<TEvent, TContext, TResponse>,
): Pick<this, 'addAdapter' | 'build'> {
this.adapters.push(adapter);

return this;
Expand All @@ -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<TReturn> {
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.',
);
}

Expand Down
111 changes: 111 additions & 0 deletions test/serverless-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -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<any, any, any, any, any, any> = {
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');
});
});

0 comments on commit d44e5bf

Please sign in to comment.