yakbak-enhanced
Version:
Record and playback HTTP responses
259 lines (226 loc) • 8.44 kB
JavaScript
// Copyright 2019 SmugMug, Inc.
// Licensed under the terms of the MIT license. Please see LICENSE file in the project root for terms.
/* eslint-env mocha */
var subject = require('..');
var createServer = require('./helpers/server');
var createTmpdir = require('./helpers/tmpdir');
var request = require('supertest');
var assert = require('assert');
var fs = require('fs');
var crypto = require('crypto');
var url = require('url');
describe('yakbak', function () {
var server, tmpdir, yakbak;
beforeEach(function (done) {
server = createServer(done);
});
afterEach(function (done) {
server.teardown(done);
});
beforeEach(function () {
tmpdir = createTmpdir();
});
afterEach(function () {
tmpdir.teardown();
});
describe('record', function () {
describe('when recording is enabled', function () {
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname });
});
it('proxies the request to the server', function (done) {
request(yakbak)
.get('/record/1')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '1a574e91da6cf00ac18bc97abaed139e')
.expect('Content-Type', 'text/html')
.expect(201, 'OK')
.end(function (err) {
assert.ifError(err);
assert.equal(server.requests.length, 1);
done();
});
});
it('writes the tape to disk', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '3234ee470c8605a1837e08f218494326')
.expect('Content-Type', 'text/html')
.expect(201, 'OK')
.end(function (err) {
assert.ifError(err);
assert(fs.existsSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js')));
done();
});
});
describe('when given a custom hashing function', function () {
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname, hash: customHash });
// customHash creates a MD5 of the request, ignoring its querystring, headers, etc.
function customHash(req, body) {
var hash = crypto.createHash('md5');
var parts = url.parse(req.url, true);
hash.update(req.method);
hash.update(parts.pathname);
hash.write(body);
return hash.digest('hex');
}
});
it('uses the custom hash to create the tape name', function (done) {
request(yakbak)
.get('/record/1')
.query({ foo: 'bar' })
.query({ date: new Date() }) // without the custom hash, this would always cause 404s
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '3f142e515cb24d1af9e51e6869bf666f')
.expect('Content-Type', 'text/html')
.expect(201, 'OK')
.end(function (err) {
assert.ifError(err);
assert(fs.existsSync(tmpdir.join('3f142e515cb24d1af9e51e6869bf666f.js')));
done();
});
});
});
});
describe("when recording is not enabled", function () {
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname, noRecord: true });
});
it('returns a 404 error', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect(404)
.end(done);
});
it('does not make a request to the server', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.end(function (err) {
assert.ifError(err);
assert.equal(server.requests.length, 0);
done();
});
});
it('does not write the tape to disk', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.end(function (err) {
assert.ifError(err);
assert(!fs.existsSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js')));
done();
});
});
});
describe("when onlySuccessResponse is enabled", function () {
beforeEach(function (done) {
/* tear down the server created in global scope as we
need different server object which can send response with failed status code*/
server.teardown(done);
});
beforeEach(function (done) {
/* Send the failed response for the requests this server handles */
server = createServer(done, true);
});
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname, recordOnlySuccess: true });
});
it('does not write the tape to disk if response statusCode is not 2XX', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.expect(404)
.end(function (err) {
assert.ifError(err);
assert(!fs.existsSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js')));
done();
});
});
});
describe("when override is enabled", function () {
beforeEach(function (done) {
/* tear down the server created in global scope as we
need different server object which can send response with failed status code*/
server.teardown(done);
});
beforeEach(function (done) {
/* Send the failed response for the requests this server handles */
server = createServer(done, true);
});
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname, override: true });
});
it('write the tape to disk always', function (done) {
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '3234ee470c8605a1837e08f218494326')
.expect('Content-Type', 'text/html')
.expect(404)
.end(function (err) {
assert.ifError(err);
assert(fs.existsSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js')));
var stats = fs.statSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js'));
var ctime = stats.ctime;
request(yakbak)
.get('/record/2')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '3234ee470c8605a1837e08f218494326')
.expect('Content-Type', 'text/html')
.expect(404)
.end(function (err) {
assert.ifError(err);
var newStats = fs.statSync(tmpdir.join('3234ee470c8605a1837e08f218494326.js'));
assert(ctime !== newStats.ctime);
done();
});
});
});
});
});
describe('playback', function () {
beforeEach(function () {
yakbak = subject(server.host, { dirname: tmpdir.dirname });
});
beforeEach(function (done) {
var file = '305c77b0a3ad7632e51c717408d8be0f.js';
var tape = [
'var path = require("path");',
'module.exports = function (req, res) {',
' res.statusCode = 201;',
' res.setHeader("content-type", "text/html")',
' res.setHeader("x-yakbak-tape", path.basename(__filename, ".js"));',
' res.end("YAY");',
'}',
''
].join('\n');
fs.writeFile(tmpdir.join(file), tape, done);
});
it('does not make a request to the server', function (done) {
request(yakbak)
.get('/playback/1')
.set('host', 'localhost:3001')
.set('user-agent', 'node-superagent/0.21.0')
.expect('X-Yakbak-Tape', '305c77b0a3ad7632e51c717408d8be0f')
.expect('Content-Type', 'text/html')
.expect(201, 'YAY')
.end(function (err) {
assert.ifError(err);
assert.equal(server.requests.length, 0);
done();
});
});
});
});