@bbc/spartacus
Version:
396 lines (310 loc) • 13.2 kB
JavaScript
;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _supertest = require('supertest');
var _supertest2 = _interopRequireDefault(_supertest);
var _server = require('react-dom/server');
var reactDomServer = _interopRequireWildcard(_server);
var _styledComponents = require('styled-components');
var styledComponents = _interopRequireWildcard(_styledComponents);
var _reactHelmet = require('react-helmet');
var _loadInitialData = require('../utilities/loadInitialData');
var _loadInitialData2 = _interopRequireDefault(_loadInitialData);
var _Document = require('./Document');
var _Document2 = _interopRequireDefault(_Document);
var _ResourceHints = require('../helpers/tests/mocks/ResourceHints');
var _ResourceHints2 = _interopRequireDefault(_ResourceHints);
var _component = require('./Document/component');
var _component2 = _interopRequireDefault(_component);
var _index = require('./index');
var _index2 = _interopRequireDefault(_index);
var _routes = require('../helpers/tests/mocks/routes');
var _routes2 = _interopRequireDefault(_routes);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var validateHttpHeader = function validateHttpHeader(headers, headerKey, expectedHeaderValue) {
var headerKeys = Object.keys(headers);
var headerValues = Object.values(headers);
var indexOfXFrame = headerKeys.indexOf(headerKey);
expect(headerKeys).toContain(headerKey);
expect(headerValues[indexOfXFrame]).toEqual(expectedHeaderValue);
};
jest.mock('react-dom/server', function () {
return {
renderToString: jest.fn().mockImplementation(function () {
return '<h1>Mock app</h1>';
}),
renderToStaticMarkup: jest.fn().mockImplementation(function () {
return '<html><body><h1>Mock app</h1></body></html>';
})
};
});
jest.mock('react-helmet', function () {
return {
Helmet: {
renderStatic: jest.fn().mockReturnValue({ head: 'tags' })
}
};
});
jest.mock('../utilities/loadInitialData');
styledComponents.ServerStyleSheet = jest.fn().mockImplementation(function () {
return {
collectStyles: jest.fn().mockReturnValue(_react2.default.createElement(
'h1',
null,
'Mock app'
)),
getStyleElement: jest.fn().mockReturnValue(_react2.default.createElement('style', null))
};
});
var ServerStyleSheet = styledComponents.ServerStyleSheet;
describe('Server', function () {
// open a route on the server
_index2.default.get('/test-url', function () {
var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(_ref, res) {
var url = _ref.url;
var data, status;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return (0, _loadInitialData2.default)(url, _routes2.default);
case 2:
data = _context.sent;
status = data.status;
_context.t0 = res.status(status);
_context.next = 7;
return (0, _Document2.default)(url, data, _routes2.default, _ResourceHints2.default, ServerStyleSheet, _reactHelmet.Helmet);
case 7:
_context.t1 = _context.sent;
_context.t0.send.call(_context.t0, _context.t1);
case 9:
case 'end':
return _context.stop();
}
}
}, _callee, undefined);
}));
return function (_x, _x2) {
return _ref2.apply(this, arguments);
};
}());
var makeRequest = function () {
var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(path) {
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
return _context2.abrupt('return', (0, _supertest2.default)(_index2.default).get(path));
case 1:
case 'end':
return _context2.stop();
}
}
}, _callee2, undefined);
}));
return function makeRequest(_x3) {
return _ref3.apply(this, arguments);
};
}();
describe('/status', function () {
it('should respond with a 200', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
var _ref5, statusCode;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return makeRequest('/status');
case 2:
_ref5 = _context3.sent;
statusCode = _ref5.statusCode;
expect(statusCode).toBe(200);
case 5:
case 'end':
return _context3.stop();
}
}
}, _callee3, undefined);
})));
});
describe('Successful render', function () {
var successDataResponse = {
isAmp: false,
data: { some: 'data' },
service: 'someService',
status: 200
};
var notFoundDataResponse = {
isAmp: false,
data: { some: 'data' },
service: 'someService',
status: 404
};
describe('200 status code', function () {
beforeEach(function () {
_loadInitialData2.default.mockImplementationOnce(function () {
return Promise.resolve(successDataResponse);
});
});
it('should respond with rendered data', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
var _ref7, text, status;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return makeRequest('/test-url');
case 2:
_ref7 = _context4.sent;
text = _ref7.text;
status = _ref7.status;
expect(status).toBe(200);
expect(reactDomServer.renderToString).toHaveBeenCalledWith(_react2.default.createElement(
'h1',
null,
'Mock app'
));
expect(reactDomServer.renderToStaticMarkup).toHaveBeenCalledWith(_react2.default.createElement(_component2.default, {
app: '<h1>Mock app</h1>',
assets: ['one.js'],
data: successDataResponse,
helmet: { head: 'tags' },
ResourceHints: _ResourceHints2.default,
styleTags: _react2.default.createElement('style', null)
}));
expect(text).toEqual('<!doctype html><html><body><h1>Mock app</h1></body></html>');
case 9:
case 'end':
return _context4.stop();
}
}
}, _callee4, undefined);
})));
});
// TODO: handle this 404 test better - https://github.com/bbc/SPArtacus/issues/40
describe('404 status code', function () {
beforeEach(function () {
_loadInitialData2.default.mockImplementationOnce(function () {
return Promise.resolve(notFoundDataResponse);
});
});
it('should respond with a rendered 404', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
var _ref9, status, text;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
_context5.next = 2;
return makeRequest('/some-unknown-url');
case 2:
_ref9 = _context5.sent;
status = _ref9.status;
text = _ref9.text;
expect(status).toBe(404);
expect(text).toEqual('<!DOCTYPE html>\n<html lang="en">\n<head>\n<meta charset="utf-8">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /some-unknown-url</pre>\n</body>\n</html>\n');
case 7:
case 'end':
return _context5.stop();
}
}
}, _callee5, undefined);
})));
});
});
});
describe('Server HTTP Headers', function () {
var statusRequest = void 0;
beforeAll(_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
return regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
_context6.next = 2;
return (0, _supertest2.default)(_index2.default).get('/status');
case 2:
statusRequest = _context6.sent;
case 3:
case 'end':
return _context6.stop();
}
}
}, _callee6, undefined);
})));
it('should not contain \'x-powered-by\'', function () {
var headerKeys = Object.keys(statusRequest.headers);
expect(headerKeys).not.toContain('x-powered-by');
});
it('should have \'x-frame-options\' set to \'DENY\'', function () {
validateHttpHeader(statusRequest.headers, 'x-frame-options', 'DENY');
});
it('should have X-DNS-Prefetch-Control set to \'off\' ', function () {
validateHttpHeader(statusRequest.headers, 'x-dns-prefetch-control', 'off');
});
it('should have Strict-Transport-Security set to \'max-age=15552000; includeSubDomains\' ', function () {
validateHttpHeader(statusRequest.headers, 'strict-transport-security', 'max-age=15552000; includeSubDomains');
});
it('should have X-Download-Options set to \'noopen\' ', function () {
validateHttpHeader(statusRequest.headers, 'x-download-options', 'noopen');
});
it('should have X-Content-Type-Options set to \'nosniff\' ', function () {
validateHttpHeader(statusRequest.headers, 'x-content-type-options', 'nosniff');
});
it('should have X-XSS-Protection set to \'1; mode=block\' ', function () {
validateHttpHeader(statusRequest.headers, 'x-xss-protection', '1; mode=block');
});
describe("should set 'x-clacks-overhead' header", function () {
it('should send the message on', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
return regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
validateHttpHeader(statusRequest.headers, 'x-clacks-overhead', 'GNU Terry Pratchett');
case 1:
case 'end':
return _context7.stop();
}
}
}, _callee7, undefined);
})));
it('should not log the message', _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9() {
var makeRequest;
return regeneratorRuntime.wrap(function _callee9$(_context9) {
while (1) {
switch (_context9.prev = _context9.next) {
case 0:
global.console.log = jest.fn();
makeRequest = function () {
var _ref13 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(path) {
return regeneratorRuntime.wrap(function _callee8$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
return _context8.abrupt('return', (0, _supertest2.default)(_index2.default).get(path));
case 1:
case 'end':
return _context8.stop();
}
}
}, _callee8, undefined);
}));
return function makeRequest(_x4) {
return _ref13.apply(this, arguments);
};
}();
_context9.next = 4;
return makeRequest('/status');
case 4:
expect(global.console.log).not.toHaveBeenCalledWith('GNU Terry Pratchett');
case 5:
case 'end':
return _context9.stop();
}
}
}, _callee9, undefined);
})));
// It should turn the message around at the end of the line and send it back again (Currently untested)
});
});