diff options
Diffstat (limited to 'spec/frontend/blob')
-rw-r--r-- | spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js b/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js new file mode 100644 index 00000000000..3b64e4910e2 --- /dev/null +++ b/spec/frontend/blob/balsamiq/balsamiq_viewer_spec.js @@ -0,0 +1,361 @@ +import sqljs from 'sql.js'; +import axios from '~/lib/utils/axios_utils'; +import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer'; +import ClassSpecHelper from '../../helpers/class_spec_helper'; + +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('<ul></ul><ul></ul>'); + }); + + 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 = '<a>innerHTML</a>'; + previewElement = { + outerHTML: '<p>outerHTML</p>', + 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 = ` + <div class="card"> + <div class="card-header">name</div> + <div class="card-body"> + <img class="img-thumbnail" src="data:image/png;base64,image"/> + </div> + </div> + `; + + 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'); + }); + }); +}); |