@senacor/azure-function-middleware
Version:
Middleware for azure functions to handle authentication, authorization, error handling and logging
241 lines (240 loc) • 13.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const functions_1 = require("@azure/functions");
const error_1 = require("./error");
const middleware_1 = require("./middleware");
describe('The middleware layer should', () => {
const httpRequest = new functions_1.HttpRequest({
url: 'http://localhost:8080',
method: 'GET',
});
let context = new functions_1.InvocationContext();
beforeEach(() => {
jest.restoreAllMocks();
context = new functions_1.InvocationContext();
jest.spyOn(context, 'error');
});
test('successfully call the passed functions without any middleware passed', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
yield (0, middleware_1.middleware)([], handlerMock, [])(httpRequest, new functions_1.InvocationContext());
expect(handlerMock).toHaveBeenCalledWith(httpRequest, new functions_1.InvocationContext());
}));
test('successfully call the middleware and the passed functions', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
}));
test('successfully call the pre middleware and post middleware and the passed functions', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
const middlewarePostMock = jest.fn();
yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [middlewarePostMock])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewarePostMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
}));
test('return an error when one middleware is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
middlewareOneMock.mockRejectedValue(Error());
const res = yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, {
$error: Error(),
$failed: true,
});
expect(handlerMock).not.toHaveBeenCalled();
expect(res).toEqual({
status: 500,
jsonBody: {
message: 'Internal server error',
},
});
expect(context.error).toHaveBeenCalled();
}));
test('return an error when second middleware is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
middlewareTwoMock.mockRejectedValue(Error());
const res = yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).not.toHaveBeenCalled();
expect(res).toEqual({
status: 500,
jsonBody: {
message: 'Internal server error',
},
});
expect(context.error).toHaveBeenCalled();
}));
test('return an error when the handler function is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
handlerMock.mockRejectedValue(Error());
const res = yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
expect(res).toEqual({
status: 500,
jsonBody: {
message: 'Internal server error',
},
});
expect(context.error).toHaveBeenCalled();
}));
test('return an error when the handler function is failing and a error with status is returned', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
handlerMock.mockRejectedValue(new error_1.ApplicationError('Validation Error', 401, 'test-body'));
const res = yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
expect(res).toEqual({
status: 401,
body: 'test-body',
});
expect(context.error).toHaveBeenCalled();
}));
test('return an error if the handler function is failing, but execute the post-execution-functions', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
handlerMock.mockRejectedValue(Error());
const res = yield (0, middleware_1.middleware)([middlewareOneMock], handlerMock, [middlewareTwoMock])(httpRequest, context);
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
expect(res).toEqual({
status: 500,
jsonBody: {
message: 'Internal server error',
},
});
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, {
$error: Error(),
$failed: true,
});
expect(context.error).toHaveBeenCalled();
}));
test('use the provided error-handle to create a response', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
const middlewarePostFunction = jest.fn();
handlerMock.mockRejectedValue(Error());
const errorResponseHandler = () => {
return {
status: 1337,
body: 'My custom error response',
};
};
const res = yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [middlewarePostFunction], {
errorResponseHandler,
})(httpRequest, context);
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
expect(res).toEqual({
status: 1337,
body: 'My custom error response',
});
expect(context.error).toHaveBeenCalled();
expect(middlewarePostFunction).toHaveBeenCalledWith(httpRequest, context, {
$error: Error(),
$failed: true,
});
}));
test('dynamically filter items, which resolve to false', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
const middlewarePostOneMock = jest.fn();
const middlewarePostTwoMock = jest.fn();
const excludeFunction = () => false;
const includeFunction = () => true;
yield (0, middleware_1.middleware)([excludeFunction() && middlewareOneMock, middlewareTwoMock], handlerMock, [
includeFunction() && middlewarePostOneMock,
excludeFunction() && middlewarePostTwoMock,
])(httpRequest, context);
expect(middlewareOneMock).not.toHaveBeenCalled();
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
expect(middlewarePostOneMock).toHaveBeenCalledWith(httpRequest, context, {
$failed: false,
$result: undefined,
});
expect(middlewarePostTwoMock).not.toHaveBeenCalled();
}));
describe('fail if error-handling is disabled and', () => {
test('the first middleware (beforeExecution) is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
middlewareOneMock.mockRejectedValue(new Error());
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [], { disableErrorHandling: true })(httpRequest, context);
})).rejects.toThrow();
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, {
$failed: true,
$error: Error(),
});
expect(handlerMock).not.toHaveBeenCalled();
}));
test('the second middleware (beforeExecution) is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
middlewareTwoMock.mockRejectedValue(Error());
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [], { disableErrorHandling: true })(httpRequest, context);
})).rejects.toThrow();
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).not.toHaveBeenCalled();
}));
test('the handler function is failing', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
handlerMock.mockRejectedValue(Error());
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [], { disableErrorHandling: true })(httpRequest, context);
})).rejects.toThrow();
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
}));
test('the handler function is failing and a error with status is returned', () => __awaiter(void 0, void 0, void 0, function* () {
const handlerMock = jest.fn();
const middlewareOneMock = jest.fn();
const middlewareTwoMock = jest.fn();
handlerMock.mockRejectedValue(new error_1.ApplicationError('Validation Error', 401, 'test-body'));
yield expect(() => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, middleware_1.middleware)([middlewareOneMock, middlewareTwoMock], handlerMock, [], { disableErrorHandling: true })(httpRequest, context);
})).rejects.toThrow();
expect(middlewareOneMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(middlewareTwoMock).toHaveBeenCalledWith(httpRequest, context, { $failed: false });
expect(handlerMock).toHaveBeenCalledWith(httpRequest, context);
}));
});
});