From ea95946dad73fe5b205b5896611f7e8a6c0e8c89 Mon Sep 17 00:00:00 2001 From: Miralem Drek Date: Mon, 16 Dec 2019 18:09:11 +0100 Subject: [PATCH] test: snapshooter (#243) --- .../src/__tests__/renderer.spec.js | 131 ++++++++++++++++++ apis/snapshooter/src/renderer.js | 25 ++-- 2 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 apis/snapshooter/src/__tests__/renderer.spec.js diff --git a/apis/snapshooter/src/__tests__/renderer.spec.js b/apis/snapshooter/src/__tests__/renderer.spec.js new file mode 100644 index 000000000..a73042802 --- /dev/null +++ b/apis/snapshooter/src/__tests__/renderer.spec.js @@ -0,0 +1,131 @@ +import renderer from '../renderer'; + +describe('snapshooter', () => { + let sandbox; + let nucleus; + let nebbie; + before(() => { + sandbox = sinon.createSandbox(); + global.window = { location: { search: '?snapshot=abc' } }; + }); + after(() => { + global.window = undefined; + }); + + beforeEach(() => { + nucleus = sandbox.stub(); + nucleus.config = { + snapshot: { + get: sandbox.stub(), + }, + }; + + nebbie = { + get: sandbox.stub().returns(Promise.resolve()), + }; + nucleus.returns(nebbie); + + nucleus.config.snapshot.get.returns( + Promise.resolve({ + meta: { theme: 'dark', language: 'sv' }, + layout: { + cube: 'c', + qInfo: { + qId: 'xyz', + }, + }, + }) + ); + }); + + afterEach(() => { + sandbox.reset(); + }); + + it('should get snapshot with id "abc"', async () => { + await renderer({ nucleus }); + expect(nucleus.config.snapshot.get).to.have.been.calledWithExactly('abc'); + }); + + it('should catch snapshot get errors and render the error', async () => { + nucleus.config.snapshot.get.throws(new Error('meh')); + const element = { + setAttribute: sandbox.stub(), + }; + try { + await renderer({ nucleus, element }); + expect(1).to.equal('a'); // just to make sure this test fails if error is not trown + } catch (e) { + /* */ + } + expect(element.setAttribute).to.have.been.calledWithExactly('data-njs-error', 'meh'); + expect(element.innerHTML).to.eql('

meh

'); + }); + + it('should call nucleus with context theme and language', async () => { + await renderer({ nucleus }); + expect(nucleus.firstCall.args[1]).to.eql({ + context: { + theme: 'dark', + language: 'sv', + }, + }); + }); + + it('should mock an app that returns a mocked model', async () => { + await renderer({ nucleus }); + const app = nucleus.firstCall.args[0]; + const model = await app.getObject('xyz'); + expect(model.getLayout).to.be.a('function'); + expect(model.on).to.be.a('function'); + expect(model.once).to.be.a('function'); + }); + + it('the mocked model should return the snapshot as layout', async () => { + await renderer({ nucleus }); + const app = nucleus.firstCall.args[0]; + const model = await app.getObject('xyz'); + const ly = await model.getLayout(); + expect(ly).to.eql({ + cube: 'c', + qInfo: { + qId: 'xyz', + }, + }); + }); + + it('should reject mocked getObject when id is not matching qId', async () => { + await renderer({ nucleus }); + const app = nucleus.firstCall.args[0]; + try { + await app.getObject('unknown'); + expect(1).to.equal(0); // should never reach this point + } catch (e) { + expect(e.message).to.equal('Could not find an object with id: unknown'); + } + }); + + it('should call nebbie.get()', async () => { + const el = 'el'; + await renderer({ nucleus, element: el }); + expect(nebbie.get).to.have.been.calledWithExactly( + { + id: 'xyz', + }, + { element: el } + ); + }); + + it('should render error when nebbie.get() throws', async () => { + const el = { + setAttribute: sandbox.stub(), + }; + nebbie.get.throws(new Error('aaaaaaah!')); + try { + await renderer({ nucleus, element: el }); + } catch (e) { + expect(e.message).to.eql('aaaaaaah!'); + } + expect(el.setAttribute).to.have.been.calledWithExactly('data-njs-error', 'aaaaaaah!'); + }); +}); diff --git a/apis/snapshooter/src/renderer.js b/apis/snapshooter/src/renderer.js index c3d4e5312..37819bb37 100644 --- a/apis/snapshooter/src/renderer.js +++ b/apis/snapshooter/src/renderer.js @@ -2,11 +2,6 @@ async function renderSnapshot({ nucleus, element }) { const params = (() => { const opts = {}; - const { pathname } = window.location; - const am = pathname.match(/\/app\/([^/?&]+)/); - if (am) { - opts.app = decodeURIComponent(am[1]); - } window.location.search .substring(1) .split('&') @@ -22,9 +17,7 @@ async function renderSnapshot({ nucleus, element }) { let snapshot = {}; const renderError = e => { - element.innerHTML = ` -

${e.message}

- `; + element.innerHTML = `

${e.message}

`; element.setAttribute('data-njs-error', e.message); }; try { @@ -52,7 +45,7 @@ async function renderSnapshot({ nucleus, element }) { if (id === layout.qInfo.qId) { return objectModel; } - return Promise.reject(); + return Promise.reject(new Error(`Could not find an object with id: ${id}`)); }, }; @@ -63,19 +56,19 @@ async function renderSnapshot({ nucleus, element }) { }, }); - nebbie - .get( + try { + await nebbie.get( { id: layout.qInfo.qId, }, { element, } - ) - .catch(e => { - renderError(e || { message: 'Failed to render supernova' }); - throw e; - }); + ); + } catch (e) { + renderError(e || { message: 'Failed to render supernova' }); + throw e; + } } export default renderSnapshot;