141 lines
4.0 KiB
JavaScript
141 lines
4.0 KiB
JavaScript
/**
|
|
* @fileOverview End-to-end testing of the swagger API security middleware
|
|
*/
|
|
'use strict';
|
|
/* eslint-disable max-nested-callbacks */
|
|
// eslint-disable-next-line no-unused-vars
|
|
const testGlobals = require('../../tools/test/testGlobals.js');
|
|
|
|
const _ = require('lodash');
|
|
const request = require('supertest');
|
|
const express = require('express');
|
|
const sinon = require('sinon');
|
|
const chai = require('chai');
|
|
const initDevApi = require('../dev_server.js');
|
|
|
|
const config = require(global.configFile);
|
|
|
|
/**
|
|
* Use fake timers so we can control the timing of the rate-limit window
|
|
*/
|
|
const fakeTimer = sinon.useFakeTimers();
|
|
|
|
const expect = chai.expect;
|
|
|
|
/**
|
|
* Test values
|
|
*/
|
|
const oldRateLimits = _.cloneDeep(config.rateLimits.api);
|
|
const TEST_RATE_WINDOW_MS = 500;
|
|
|
|
// Correct auth method (Bearer), correct token
|
|
const TOKEN_VALID = 'YTM2ZGQ1NzUtOWFmNS01MjMyLTg5MjYtM2NkZjA5ZDU2ZGU1';
|
|
const HEADER_VALID = 'Bearer ' + TOKEN_VALID;
|
|
|
|
/**
|
|
* Use supertest to make an authenticated request to the server
|
|
*
|
|
* @param {Object} app - The express app to make the request to
|
|
*
|
|
* @returns {Promise} - Promise for the result of making the request
|
|
*/
|
|
function makeAuthenticatedRequest(app) {
|
|
return request(app)
|
|
.get('/dev/v0/test')
|
|
.set('Accept', 'application/json')
|
|
.set('Authorization', HEADER_VALID);
|
|
}
|
|
|
|
/**
|
|
* Tests
|
|
*/
|
|
describe('E2E: rate limiting test', () => {
|
|
let app;
|
|
before(() => {
|
|
//
|
|
// Change the config to reduce the rate limit limits for testing
|
|
//
|
|
config.rateLimits.api.windowMs = TEST_RATE_WINDOW_MS;
|
|
config.rateLimits.api.max = 2;
|
|
|
|
//
|
|
// Initialise the test app
|
|
//
|
|
app = express();
|
|
const devApiRouter = initDevApi.init();
|
|
app.use('/dev', devApiRouter);
|
|
});
|
|
|
|
/**
|
|
* Put the old limits and real timers back after all the tests are complete
|
|
*/
|
|
after(() => {
|
|
_.merge(config.rateLimits.api, oldRateLimits);
|
|
fakeTimer.restore();
|
|
});
|
|
|
|
/**
|
|
* Advance the fakeTimer after each test so we get a new rate-limit window
|
|
*/
|
|
afterEach(() => {
|
|
fakeTimer.tick(TEST_RATE_WINDOW_MS + 1);
|
|
});
|
|
|
|
describe('requests that don\'t exceed the limit', () => {
|
|
it('are allowed', () => {
|
|
const req1 = makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
|
|
return req1.then(() => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
});
|
|
});
|
|
|
|
it('inform the caller how many requests are left', () => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(200)
|
|
.expect('x-ratelimit-limit', '2')
|
|
.expect('x-ratelimit-remaining', '1');
|
|
});
|
|
});
|
|
|
|
describe('requests that exceed the limit', () => {
|
|
it('respond with 429 Too Many Requests', () => {
|
|
const req1 = makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
|
|
const req2 = req1.then(() => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
});
|
|
|
|
return req2.then(() => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(429);
|
|
});
|
|
});
|
|
|
|
it('return an error code and description in the body', () => {
|
|
const req1 = makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
|
|
const req2 = req1.then(() => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(200);
|
|
});
|
|
|
|
return req2.then(() => {
|
|
return makeAuthenticatedRequest(app)
|
|
.expect(429)
|
|
.then((response) => {
|
|
return expect(response.body).to.deep.equal({
|
|
code: 30500,
|
|
description: 'Rate limit reached. Please wait and try again.'
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|