@webscale-networks/cloudedge-handlers
Version:
Webscale Networks CloudEDGE Handlers for cloud-agnostic edge function execution
206 lines (182 loc) • 6.88 kB
JavaScript
const _ = require('lodash');
const objects = require('./objects.js');
// Runs a handler function directly.
async function call(type, underTest, request, response) {
let result = {};
if (type == 'handleRequest') {
result = underTest(request);
} else if (type == 'handleResponse') {
result = underTest(request, response);
}
return result;
};
// Headers can be updated and removed but not reassigned.
reassignedRequestHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const oldHeaders = request.headers;
const result = await call(type, underTest, request, null);
if (result && result.request) {
expect(oldHeaders).toEqual(result.request.headers);
}
};
invalidSettingOfHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const result = await call(type, underTest, request, null);
if (_.get(result, 'request.headers')) {
expect(Object.keys(result.request.headers)).toHaveLength(0);
}
};
invalidSettingOfOriginHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const result = await call(type, underTest, request, null);
if (_.get(result, 'request.originRequest.headers')) {
expect(Object.keys(result.request.originRequest.headers)).toHaveLength(0);
}
};
// Headers can be updated and removed but not reassigned.
reassignedOriginHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const oldHeaders = request.originRequest.headers;
const result = await call(type, underTest, request, null);
if (result && result.request && result.request.originRequest) {
expect(oldHeaders).toEqual(result.request.originRequest.headers);
}
};
// A request body is always generated and should always include the relevant
// properties.
malformedRequestBody = async function(type, underTest) {
const request = objects.mockRequest();
const result = await call(type, underTest, request, null);
if (result && result.request) {
expect(result.request.body).toHaveProperty('modified');
expect(result.request.body).toHaveProperty('encoding');
expect(result.request.body).toHaveProperty('data');
expect(result.request.body).toHaveProperty('truncated');
}
};
// A origin request is always generated.
missingOriginRequest = async function(type, underTest) {
const request = objects.mockRequest();
const result = await call(type, underTest, request, null);
if (result && result.request) {
expect(result.request).toHaveProperty('originRequest');
}
};
// If the request body is modified, the modified flag must be set to true.
unsetModified = async function(type, underTest){
const request = objects.mockRequest();
const oldBody = _.cloneDeep(request.body.data);
const result = await call(type, underTest, request, null);
if (result &&
result.request &&
oldBody != result.request.body.data) {
expect(request.body.modified).toBe(true);
}
};
// All responses must include a status code.
missingStatusCode = async function(type, underTest) {
const request = objects.mockRequest();
const response = objects.mockResponse();
const result = await call(type, underTest, request, response);
if (result && result.response) {
expect(result.response.statusCode).toEqual(expect.any(Number));
}
};
// Response headers can be updated and deleted but not reassigned.
reassignedResponseHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const response = objects.mockResponse();
const oldHeaders = response.headers;
const result = await call(type, underTest, request, response);
if (result && result.response) {
expect(oldHeaders).toEqual(result.response.headers);
}
};
invalidSettingOfResponseHeaders = async function(type, underTest) {
const request = objects.mockRequest();
const response = objects.mockResponse();
const result = await call(type, underTest, request, response);
if (_.get(result, 'response.headers')) {
expect(Object.keys(result.response.headers)).toHaveLength(0);
}
};
bodyEncodingNotSet = async function(type, underTest) {
const request = objects.mockRequest();
const response = objects.mockResponse();
const result = await call(type, underTest, request, response);
if (_.get(result, 'response.body.data')) {
expect(result.response.body.encoding).not.toBeUndefined();
}
};
invalidResponseObject = async function(type, underTest) {
const request = objects.mockRequest();
const response = objects.mockResponse();
const result = await call(type, underTest, request, response);
if (result) {
expect(result.request).toBeUndefined();
}
}
exports.tests = {
'handleRequest': [
{
name: 'Headers cannot be reassigned',
expectFunction: reassignedRequestHeaders,
},
{
name: 'Uses wRequest.headers.set(<name>, <value>) to set HTTP request headers',
expectFunction: invalidSettingOfHeaders,
},
{
name: 'Uses wRequest.originRequest.headers.set(<name>, <value>) to set origin request HTTP request headers',
expectFunction: invalidSettingOfOriginHeaders,
},
{
name: 'Origin request custom headers cannot be reassigned',
expectFunction: reassignedOriginHeaders,
},
{
name: 'Malformed request body',
expectFunction: malformedRequestBody,
},
{
name: 'Missing origin request',
expectFunction: missingOriginRequest,
},
{
name: 'Modified not set',
expectFunction: unsetModified,
}
],
'handleResponse': [
{
name: 'Missing status code',
expectFunction: missingStatusCode,
},
{
name: 'Response headers cannot be reassigned',
expectFunction: reassignedResponseHeaders,
},
{
name: 'Uses wResponse.headers.set(<name>, <value>) to set HTTP response headers',
expectFunction: invalidSettingOfResponseHeaders,
},
{
name: 'If body.data is set, body.encoding must be set',
expectFunction: bodyEncodingNotSet,
},
{
name: 'Cannot set a request object on a response handler',
expectFunction: invalidResponseObject,
}
],
'compute': [
{
name: 'Missing status code',
expectFunction: missingStatusCode,
},
{
name: 'If body.data is set, body.encoding must be set',
expectFunction: bodyEncodingNotSet,
},
]
};