beforeEach(done => { const tailor = createTailorInstance({ pipeDefinition: () => Buffer.from('') }); mockContext.returns(Promise.resolve({})); server = http.createServer(tailor.requestHandler); server.listen(8080, 'localhost', done); });
it('emits `error(request, error)` event on template error', done => { const onTemplateError = sinon.spy(); mockTemplate.returns(false); tailor.on('error', onTemplateError); http.get('http://localhost:8080/template', response => { const request = onTemplateError.args[0][0]; const error = onTemplateError.args[0][1]; assert.equal(request.url, '/template'); assert.equal(error, 'Error fetching template'); response.resume(); response.on('end', done); }); });
describe('#inspect', () => { it('should throw an error if inspect fails', () => { // We need this chain of stubs to send our call down an explicit line that // will eventually throw a solid exception. let bogusContainer = dummyContainer(); const inspectStub = sinon.stub(bogusContainer, 'inspect').throws(); const stub = sinon.stub(landerode, 'getContainer').returns(bogusContainer); // Throw needs a function to check rather than a function result const cptPhasma = () => landerode.inspect('fn-2187'); expect(cptPhasma).to.throw(); inspectStub.restore(); stub.restore(); }); });
it('forwards `fragment:start(request, fragment)` event from a fragment', done => { const onFragmentStart = sinon.spy(); nock('https://fragment') .get('/') .reply(200, 'hello'); mockTemplate.returns('<fragment src="https://fragment">'); tailor.on('fragment:start', onFragmentStart); http.get('http://localhost:8080/template', response => { const request = onFragmentStart.args[0][0]; const fragment = onFragmentStart.args[0][1]; assert.equal(request.url, '/template'); assert.equal(fragment.url, 'https://fragment'); response.resume(); response.on('end', done); }); });
beforeEach(done => { tailor = new Tailor({ fetchContext: mockContext, pipeDefinition: () => Buffer.from(''), fetchTemplate: (request, parseTemplate) => { const template = mockTemplate(request); if (template) { return parseTemplate(template); } else { return Promise.reject('Error fetching template'); } } }); mockContext.returns(Promise.resolve({})); server = http.createServer(tailor.requestHandler); server.listen(8080, 'localhost', done); });
describe('#remove', () => { it('should throw an error if remove fails', () => { const container = dummyContainer({Id: '1234'}); const getStub = sinon.stub(landerode, 'getContainer').returns(container); const removeStub = sinon.stub(container, 'remove') .usingPromise(Promise) .rejects('Oh No!'); landerode.remove('1234').should.be.rejectedWith('Oh No!') .then(() => { getStub.restore(); removeStub.restore(); }); }); });
it('should disable browser cache', done => { nock('https://fragment') .get('/1') .reply(200, 'hello'); mockTemplate.returns( '<fragment src="https://fragment/1"></fragment>' ); getResponse('http://localhost:8080/test') .then(response => { const headers = response.headers; assert.equal( 'no-cache, no-store, must-revalidate', headers['cache-control'] ); assert.equal('no-cache', headers['pragma']); }) .then(done, done); });
const getSample = () => { const getMock = sinon .stub() .onFirstCall() .resolves({data: 'some-token'}) .onSecondCall() .resolves({data: 'function-response'}); const axiosMock = {get: getMock}; const resMock = {}; resMock.status = sinon.stub().returns(resMock); resMock.send = sinon.stub().returns(resMock); return { sample: proxyquire('../', { axios: axiosMock, }), mocks: { res: resMock, axios: axiosMock, }, }; }
it('should return response code and location header of the 1st primary fragment', done => { nock('https://fragment') .get('/1') .reply(200, 'hello') .get('/2') .reply(300, 'world', { Location: 'https://redirect' }) .get('/3') .reply(500, '!'); mockTemplate.returns( '<fragment src="https://fragment/1"></fragment>' + '<fragment src="https://fragment/2" primary></fragment>' + '<fragment src="https://fragment/3" primary></fragment>' ); getResponse('http://localhost:8080/test') .then(response => { assert.equal(response.statusCode, 300); assert.equal(response.headers.location, 'https://redirect'); }) .then(done, done); });
it('emits `context:error(request, error)` event', done => { const onContextError = sinon.spy(); const rejectPrm = Promise.reject('Error fetching context'); rejectPrm.catch(() => {}); mockContext.returns(rejectPrm); tailor.on('context:error', onContextError); http.get('http://localhost:8080/template', response => { const request = onContextError.args[0][0]; const error = onContextError.args[0][1]; assert.equal(request.url, '/template'); assert.equal(error, 'Error fetching context'); response.resume(); response.on('end', done); }); });
describe('Custom async fragments', () => { it('should add async fragments from handleTag', done => { nock('https://fragment') .get('/1') .reply(200, 'hello'); mockTemplate.returns('<delayed-fragment></delayed-fragment>'); mockChildTemplate.returns(''); getResponse('http://localhost:8080/test') .then(response => { assert.equal( response.body, '<html><head></head><body><script data-pipe>p.placeholder(0)</script><script data-pipe>p.start(0)</script>hello<script data-pipe>p.end(0)</script></body></html>' ); }) .then(done, done); }); });
it('emits `start(request)` event', done => { const onStart = sinon.spy(); nock('https://fragment') .get('/') .reply(200, 'hello'); mockTemplate.returns('<fragment src="https://fragment">'); tailor.on('start', onStart); http.get('http://localhost:8080/template', response => { response.resume(); response.on('end', () => { const request = onStart.args[0][0]; assert.equal(request.url, '/template'); assert.equal(onStart.callCount, 1); done(); }); }); });
it('emits `response(request, statusCode, headers)` event', done => { const onResponse = sinon.spy(); mockTemplate.returns('<html>'); tailor.on('response', onResponse); http.get('http://localhost:8080/template', response => { response.resume(); response.on('end', () => { const request = onResponse.args[0][0]; const statusCode = onResponse.args[0][1]; const headers = onResponse.args[0][2]; assert.equal(request.url, '/template'); assert.equal(statusCode, 200); assert.deepEqual(headers, { 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Content-Type': 'text/html', Pragma: 'no-cache' }); assert.equal(onResponse.callCount, 1); done(); }); }); });
it('emits `end(request, contentSize)` event', done => { const onEnd = sinon.spy(); mockTemplate.returns( '<html><head></head><body><h2></h2></body></html>' ); tailor.on('end', onEnd); http.get('http://localhost:8080/template', response => { response.resume(); response.on('end', () => { const request = onEnd.args[0][0]; const contentSize = onEnd.args[0][1]; assert.equal(request.url, '/template'); assert.equal(contentSize, 48); assert.equal(onEnd.callCount, 1); done(); }); }); });
it('emits `error(request, error)` event on primary error/timeout', done => { const onPrimaryError = sinon.spy(); nock('https://fragment') .get('/') .reply(500); mockTemplate.returns('<fragment primary src="https://fragment">'); tailor.on('error', onPrimaryError); http.get('http://localhost:8080/template', response => { const request = onPrimaryError.args[0][0]; const error = onPrimaryError.args[0][1]; assert.equal(request.url, '/template'); assert.equal(error.message, 'Internal Server Error'); response.resume(); response.on('end', done); }); });