diff --git a/src/visits/services/VisitsExporter.ts b/src/visits/services/VisitsExporter.ts index 5f63d8bd..77eb07e5 100644 --- a/src/visits/services/VisitsExporter.ts +++ b/src/visits/services/VisitsExporter.ts @@ -1,5 +1,4 @@ import { CsvJson } from 'csvjson'; -import { head, keys } from 'ramda'; import { NormalizedVisit } from '../types'; import { saveCsv } from '../../utils/helpers/csv'; @@ -10,15 +9,15 @@ export class VisitsExporter { ) {} public readonly exportVisits = (filename: string, visits: NormalizedVisit[]) => { - try { - const csv = this.csvjson.toCSV(visits, { - headers: keys(head(visits)).join(','), - }); - - saveCsv(this.window, csv, filename); - } catch (e) { - // FIXME Handle error - console.error(e); + if (!visits.length) { + return; } + + const [ firstVisit ] = visits; + const csv = this.csvjson.toCSV(visits, { + headers: Object.keys(firstVisit).join(','), + }); + + saveCsv(this.window, csv, filename); }; } diff --git a/test/servers/services/ServersExporter.test.ts b/test/servers/services/ServersExporter.test.ts index a695373e..cf0fd386 100644 --- a/test/servers/services/ServersExporter.test.ts +++ b/test/servers/services/ServersExporter.test.ts @@ -11,9 +11,9 @@ describe('ServersExporter', () => { }); const appendChild = jest.fn(); const removeChild = jest.fn(); - const createWindowMock = () => Mock.of({ + const windowMock = Mock.of({ document: { - createElement: jest.fn(() => createLinkMock()), + createElement: jest.fn(createLinkMock), body: { appendChild, removeChild }, }, }); @@ -50,12 +50,11 @@ describe('ServersExporter', () => { }); afterEach(() => { global.console = originalConsole; - jest.clearAllMocks(); }); it('logs an error if something fails', () => { const csvjsonMock = createCsvjsonMock(true); - const exporter = new ServersExporter(storageMock, createWindowMock(), csvjsonMock); + const exporter = new ServersExporter(storageMock, windowMock, csvjsonMock); exporter.exportServers(); @@ -64,7 +63,6 @@ describe('ServersExporter', () => { }); it('makes use of download link API', () => { - const windowMock = createWindowMock(); const exporter = new ServersExporter(storageMock, windowMock, createCsvjsonMock()); const { document: { createElement } } = windowMock; diff --git a/test/visits/services/VisitsExporter.test.ts b/test/visits/services/VisitsExporter.test.ts new file mode 100644 index 00000000..a0d66acb --- /dev/null +++ b/test/visits/services/VisitsExporter.test.ts @@ -0,0 +1,58 @@ +import { Mock } from 'ts-mockery'; +import { CsvJson } from 'csvjson'; +import { VisitsExporter } from '../../../src/visits/services/VisitsExporter'; +import { NormalizedVisit } from '../../../src/visits/types'; + +describe('VisitsExporter', () => { + const createLinkMock = () => ({ + setAttribute: jest.fn(), + click: jest.fn(), + style: {}, + }); + const windowMock = Mock.of({ + document: { + createElement: jest.fn(createLinkMock), + body: { appendChild: jest.fn(), removeChild: jest.fn() }, + }, + }); + const toCSV = jest.fn(); + const csvToJsonMock = Mock.of({ toCSV }); + let exporter: VisitsExporter; + + beforeEach(jest.clearAllMocks); + beforeEach(() => { + (global as any).Blob = class Blob {}; // eslint-disable-line @typescript-eslint/no-extraneous-class + (global as any).URL = { createObjectURL: () => '' }; + + exporter = new VisitsExporter(windowMock, csvToJsonMock); + }); + + describe('exportVisits', () => { + it('parses provided visits to CSV', () => { + const visits: NormalizedVisit[] = [ + { + browser: 'browser', + city: 'city', + country: 'country', + date: 'date', + latitude: 0, + longitude: 0, + os: 'os', + referer: 'referer', + }, + ]; + + exporter.exportVisits('my_visits.csv', visits); + + expect(toCSV).toHaveBeenCalledWith(visits, { + headers: 'browser,city,country,date,latitude,longitude,os,referer', + }); + }); + + it('skips execution when list of visits is empty', () => { + exporter.exportVisits('my_visits.csv', []); + + expect(toCSV).not.toHaveBeenCalled(); + }); + }); +});