import sqljs from 'sql.js'; import ClassSpecHelper from 'helpers/class_spec_helper'; import axios from '~/lib/utils/axios_utils'; import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer'; jest.mock('sql.js'); describe('BalsamiqViewer', () => { const mockArrayBuffer = new ArrayBuffer(10); let balsamiqViewer; let viewer; describe('class constructor', () => { beforeEach(() => { viewer = {}; balsamiqViewer = new BalsamiqViewer(viewer); }); it('should set .viewer', () => { expect(balsamiqViewer.viewer).toBe(viewer); }); }); describe('loadFile', () => { let bv; const endpoint = 'endpoint'; const requestSuccess = Promise.resolve({ data: mockArrayBuffer, status: 200, }); beforeEach(() => { viewer = {}; bv = new BalsamiqViewer(viewer); }); it('should call `axios.get` on `endpoint` param with responseType set to `arraybuffer', () => { jest.spyOn(axios, 'get').mockReturnValue(requestSuccess); jest.spyOn(bv, 'renderFile').mockReturnValue(); bv.loadFile(endpoint); expect(axios.get).toHaveBeenCalledWith( endpoint, expect.objectContaining({ responseType: 'arraybuffer', }), ); }); it('should call `renderFile` on request success', (done) => { jest.spyOn(axios, 'get').mockReturnValue(requestSuccess); jest.spyOn(bv, 'renderFile').mockImplementation(() => {}); bv.loadFile(endpoint) .then(() => { expect(bv.renderFile).toHaveBeenCalledWith(mockArrayBuffer); }) .then(done) .catch(done.fail); }); it('should not call `renderFile` on request failure', (done) => { jest.spyOn(axios, 'get').mockReturnValue(Promise.reject()); jest.spyOn(bv, 'renderFile').mockImplementation(() => {}); bv.loadFile(endpoint) .then(() => { done.fail('Expected loadFile to throw error!'); }) .catch(() => { expect(bv.renderFile).not.toHaveBeenCalled(); }) .then(done) .catch(done.fail); }); }); describe('renderFile', () => { let container; let previews; beforeEach(() => { viewer = { appendChild: jest.fn(), }; previews = [document.createElement('ul'), document.createElement('ul')]; balsamiqViewer = { initDatabase: jest.fn(), getPreviews: jest.fn(), renderPreview: jest.fn(), }; balsamiqViewer.viewer = viewer; balsamiqViewer.getPreviews.mockReturnValue(previews); balsamiqViewer.renderPreview.mockImplementation((preview) => preview); viewer.appendChild.mockImplementation((containerElement) => { container = containerElement; }); BalsamiqViewer.prototype.renderFile.call(balsamiqViewer, mockArrayBuffer); }); it('should call .initDatabase', () => { expect(balsamiqViewer.initDatabase).toHaveBeenCalledWith(mockArrayBuffer); }); it('should call .getPreviews', () => { expect(balsamiqViewer.getPreviews).toHaveBeenCalled(); }); it('should call .renderPreview for each preview', () => { const allArgs = balsamiqViewer.renderPreview.mock.calls; expect(allArgs.length).toBe(2); previews.forEach((preview, i) => { expect(allArgs[i][0]).toBe(preview); }); }); it('should set the container HTML', () => { expect(container.innerHTML).toBe(''); }); it('should add inline preview classes', () => { expect(container.classList[0]).toBe('list-inline'); expect(container.classList[1]).toBe('previews'); }); it('should call viewer.appendChild', () => { expect(viewer.appendChild).toHaveBeenCalledWith(container); }); }); describe('initDatabase', () => { let uint8Array; let data; beforeEach(() => { uint8Array = {}; data = 'data'; balsamiqViewer = {}; window.Uint8Array = jest.fn(); window.Uint8Array.mockReturnValue(uint8Array); BalsamiqViewer.prototype.initDatabase.call(balsamiqViewer, data); }); it('should instantiate Uint8Array', () => { expect(window.Uint8Array).toHaveBeenCalledWith(data); }); it('should call sqljs.Database', () => { expect(sqljs.Database).toHaveBeenCalledWith(uint8Array); }); it('should set .database', () => { expect(balsamiqViewer.database).not.toBe(null); }); }); describe('getPreviews', () => { let database; let thumbnails; let getPreviews; beforeEach(() => { database = { exec: jest.fn(), }; thumbnails = [{ values: [0, 1, 2] }]; balsamiqViewer = { database, }; jest .spyOn(BalsamiqViewer, 'parsePreview') .mockImplementation((preview) => preview.toString()); database.exec.mockReturnValue(thumbnails); getPreviews = BalsamiqViewer.prototype.getPreviews.call(balsamiqViewer); }); it('should call database.exec', () => { expect(database.exec).toHaveBeenCalledWith('SELECT * FROM thumbnails'); }); it('should call .parsePreview for each value', () => { const allArgs = BalsamiqViewer.parsePreview.mock.calls; expect(allArgs.length).toBe(3); thumbnails[0].values.forEach((value, i) => { expect(allArgs[i][0]).toBe(value); }); }); it('should return an array of parsed values', () => { expect(getPreviews).toEqual(['0', '1', '2']); }); }); describe('getResource', () => { let database; let resourceID; let resource; let getResource; beforeEach(() => { database = { exec: jest.fn(), }; resourceID = 4; resource = ['resource']; balsamiqViewer = { database, }; database.exec.mockReturnValue(resource); getResource = BalsamiqViewer.prototype.getResource.call(balsamiqViewer, resourceID); }); it('should call database.exec', () => { expect(database.exec).toHaveBeenCalledWith( `SELECT * FROM resources WHERE id = '${resourceID}'`, ); }); it('should return the selected resource', () => { expect(getResource).toBe(resource[0]); }); }); describe('renderPreview', () => { let previewElement; let innerHTML; let preview; let renderPreview; beforeEach(() => { innerHTML = 'innerHTML'; previewElement = { outerHTML: '

outerHTML

', classList: { add: jest.fn(), }, }; preview = {}; balsamiqViewer = { renderTemplate: jest.fn(), }; jest.spyOn(document, 'createElement').mockReturnValue(previewElement); balsamiqViewer.renderTemplate.mockReturnValue(innerHTML); renderPreview = BalsamiqViewer.prototype.renderPreview.call(balsamiqViewer, preview); }); it('should call classList.add', () => { expect(previewElement.classList.add).toHaveBeenCalledWith('preview'); }); it('should call .renderTemplate', () => { expect(balsamiqViewer.renderTemplate).toHaveBeenCalledWith(preview); }); it('should set .innerHTML', () => { expect(previewElement.innerHTML).toBe(innerHTML); }); it('should return element', () => { expect(renderPreview).toBe(previewElement); }); }); describe('renderTemplate', () => { let preview; let name; let resource; let template; let renderTemplate; beforeEach(() => { preview = { resourceID: 1, image: 'image' }; name = 'name'; resource = 'resource'; template = `
name
`; balsamiqViewer = { getResource: jest.fn(), }; jest.spyOn(BalsamiqViewer, 'parseTitle').mockReturnValue(name); balsamiqViewer.getResource.mockReturnValue(resource); renderTemplate = BalsamiqViewer.prototype.renderTemplate.call(balsamiqViewer, preview); }); it('should call .getResource', () => { expect(balsamiqViewer.getResource).toHaveBeenCalledWith(preview.resourceID); }); it('should call .parseTitle', () => { expect(BalsamiqViewer.parseTitle).toHaveBeenCalledWith(resource); }); it('should return the template string', () => { expect(renderTemplate.replace(/\s/g, '')).toEqual(template.replace(/\s/g, '')); }); }); describe('parsePreview', () => { let preview; let parsePreview; beforeEach(() => { preview = ['{}', '{ "id": 1 }']; jest.spyOn(JSON, 'parse'); parsePreview = BalsamiqViewer.parsePreview(preview); }); ClassSpecHelper.itShouldBeAStaticMethod(BalsamiqViewer, 'parsePreview'); it('should return the parsed JSON', () => { expect(parsePreview).toEqual(JSON.parse('{ "id": 1 }')); }); }); describe('parseTitle', () => { let title; let parseTitle; beforeEach(() => { title = { values: [['{}', '{}', '{"name":"name"}']] }; jest.spyOn(JSON, 'parse'); parseTitle = BalsamiqViewer.parseTitle(title); }); ClassSpecHelper.itShouldBeAStaticMethod(BalsamiqViewer, 'parsePreview'); it('should return the name value', () => { expect(parseTitle).toBe('name'); }); }); });