From 734513ce7adfe7e14515d81fa40d74f402654877 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 10 Apr 2020 09:57:59 -0700 Subject: [PATCH] [Reporting] convert all server unit tests to TypeScript (#62873) * [Reporting] convert all server unit tests to TypeScript * fix ts * revert unrelated change --- ...{index.test.js.snap => index.test.ts.snap} | 0 ...xecute_job.test.js => execute_job.test.ts} | 227 ++++++++++-------- .../{index.test.js => index.test.ts} | 61 +++-- .../{index.test.js => index.test.ts} | 52 ++-- .../{index.test.js => index.test.ts} | 2 +- .../routes/{jobs.test.js => jobs.test.ts} | 36 +-- ...t.js => reporting_usage_collector.test.ts} | 58 +++-- .../create_mock_browserdriverfactory.ts | 2 +- x-pack/legacy/plugins/reporting/types.d.ts | 2 +- 9 files changed, 273 insertions(+), 167 deletions(-) rename x-pack/legacy/plugins/reporting/__snapshots__/{index.test.js.snap => index.test.ts.snap} (100%) rename x-pack/legacy/plugins/reporting/export_types/csv/server/{execute_job.test.js => execute_job.test.ts} (88%) rename x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/{index.test.js => index.test.ts} (58%) rename x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/{index.test.js => index.test.ts} (57%) rename x-pack/legacy/plugins/reporting/{index.test.js => index.test.ts} (94%) rename x-pack/legacy/plugins/reporting/server/routes/{jobs.test.js => jobs.test.ts} (91%) rename x-pack/legacy/plugins/reporting/server/usage/{reporting_usage_collector.test.js => reporting_usage_collector.test.ts} (90%) diff --git a/x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap b/x-pack/legacy/plugins/reporting/__snapshots__/index.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/reporting/__snapshots__/index.test.js.snap rename to x-pack/legacy/plugins/reporting/__snapshots__/index.test.ts.snap diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts similarity index 88% rename from x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js rename to x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts index 4870e1e35cdaf..f0afade8629ab 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +// @ts-ignore import Puid from 'puid'; import sinon from 'sinon'; import nodeCrypto from '@elastic/node-crypto'; @@ -13,36 +14,40 @@ import { createMockReportingCore } from '../../../test_helpers'; import { LevelLogger } from '../../../server/lib/level_logger'; import { setFieldFormats } from '../../../server/services'; import { executeJobFactory } from './execute_job'; +import { JobDocPayloadDiscoverCsv } from '../types'; import { CSV_BOM_CHARS } from '../../../common/constants'; -const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)); +const delay = (ms: number) => new Promise(resolve => setTimeout(() => resolve(), ms)); const puid = new Puid(); const getRandomScrollId = () => { return puid.generate(); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadDiscoverCsv; + describe('CSV Execute Job', function() { const encryptionKey = 'testEncryptionKey'; const headers = { sid: 'test', }; const mockLogger = new LevelLogger({ - get: () => ({ - debug: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }), + get: () => + ({ + debug: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + } as any), }); - let defaultElasticsearchResponse; - let encryptedHeaders; + let defaultElasticsearchResponse: any; + let encryptedHeaders: any; - let clusterStub; - let configGetStub; - let mockReportingConfig; - let mockReportingPlugin; - let callAsCurrentUserStub; - let cancellationToken; + let clusterStub: any; + let configGetStub: any; + let mockReportingConfig: any; + let mockReportingPlugin: any; + let callAsCurrentUserStub: any; + let cancellationToken: any; const mockElasticsearch = { dataClient: { @@ -78,7 +83,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'defaultScrollId', }; clusterStub = { - callAsCurrentUser: function() {}, + callAsCurrentUser() {}, }; callAsCurrentUserStub = sinon @@ -89,17 +94,19 @@ describe('CSV Execute Job', function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); setFieldFormats({ - fieldFormatServiceFactory: function() { + fieldFormatServiceFactory() { const uiConfigMock = {}; - uiConfigMock['format:defaultTypeMap'] = { + (uiConfigMock as any)['format:defaultTypeMap'] = { _default_: { id: 'string', params: {} }, }; const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry(); - fieldFormatsRegistry.init(key => uiConfigMock[key], {}, [fieldFormats.StringFormat]); + fieldFormatsRegistry.init(key => (uiConfigMock as any)[key], {}, [ + fieldFormats.StringFormat, + ]); - return fieldFormatsRegistry; + return Promise.resolve(fieldFormatsRegistry); }, }); }); @@ -109,7 +116,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); expect(callAsCurrentUserStub.called).toBe(true); @@ -123,14 +134,14 @@ describe('CSV Execute Job', function() { }; const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const job = { + const job = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index, body, }, - }; + }); await executeJob('job777', job, cancellationToken); @@ -152,7 +163,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -166,7 +181,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -196,7 +215,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -231,7 +254,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); await executeJob( 'job456', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -257,12 +284,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: undefined, searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[TypeError: Cannot read property 'indexOf' of undefined]`); @@ -284,12 +311,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -309,12 +336,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['=SUM(A1:A2)', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -334,12 +361,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -359,12 +386,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { csv_contains_formulas: csvContainsFormulas } = await executeJob( 'job123', jobParams, @@ -386,12 +413,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toEqual(`${CSV_BOM_CHARS}one,two\none,bar\n`); @@ -407,12 +434,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toEqual('one,two\none,bar\n'); @@ -423,11 +450,11 @@ describe('CSV Execute Job', function() { it('should reject Promise if search call errors out', async function() { callAsCurrentUserStub.rejects(new Error()); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[Error]`); @@ -442,11 +469,11 @@ describe('CSV Execute Job', function() { }); callAsCurrentUserStub.onSecondCall().rejects(new Error()); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot(`[Error]`); @@ -463,11 +490,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -484,11 +511,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -512,11 +539,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -540,11 +567,11 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null }, - }; + }); await expect( executeJob('job123', jobParams, cancellationToken) ).rejects.toMatchInlineSnapshot( @@ -578,7 +605,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); @@ -593,13 +624,17 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); cancellationToken.cancel(); for (let i = 0; i < callAsCurrentUserStub.callCount; ++i) { - expect(callAsCurrentUserStub.getCall(i).args[1]).to.not.be('clearScroll'); + expect(callAsCurrentUserStub.getCall(i).args[1]).not.toBe('clearScroll'); // dead code? } }); @@ -607,7 +642,11 @@ describe('CSV Execute Job', function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); executeJob( 'job345', - { headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } }, + getJobDocPayload({ + headers: encryptedHeaders, + fields: [], + searchRequest: { index: null, body: null }, + }), cancellationToken ); await delay(100); @@ -623,11 +662,11 @@ describe('CSV Execute Job', function() { describe('csv content', function() { it('should write column headers to output, even if there are no results', async function() { const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one,two\n`); }); @@ -635,11 +674,11 @@ describe('CSV Execute Job', function() { it('should use custom uiSettings csv:separator for header', async function() { mockUiSettingsClient.get.withArgs('csv:separator').returns(';'); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one;two\n`); }); @@ -647,11 +686,11 @@ describe('CSV Execute Job', function() { it('should escape column headers if uiSettings csv:quoteValues is true', async function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`"one and a half",two,"three-and-four","five & six"\n`); }); @@ -659,11 +698,11 @@ describe('CSV Execute Job', function() { it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() { mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(false); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one and a half', 'two', 'three-and-four', 'five & six'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); expect(content).toBe(`one and a half,two,three-and-four,five & six\n`); }); @@ -677,11 +716,11 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); const headerLine = lines[0]; @@ -697,12 +736,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); const valuesLine = lines[1]; @@ -724,12 +763,12 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); @@ -746,7 +785,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], @@ -760,7 +799,7 @@ describe('CSV Execute Job', function() { fieldFormatMap: '{"one":{"id":"string","params":{"transform": "upper"}}}', }, }, - }; + }); const { content } = await executeJob('job123', jobParams, cancellationToken); const lines = content.split('\n'); @@ -774,18 +813,18 @@ describe('CSV Execute Job', function() { // tests use these 'simple' characters to make the math easier describe('when only the headers exceed the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(1); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -804,18 +843,18 @@ describe('CSV Execute Job', function() { }); describe('when headers are equal to maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(9); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -834,8 +873,8 @@ describe('CSV Execute Job', function() { }); describe('when the data exceeds the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { configGetStub.withArgs('csv', 'maxSizeBytes').returns(9); @@ -848,12 +887,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -872,8 +911,8 @@ describe('CSV Execute Job', function() { }); describe('when headers and data equal the maxSizeBytes', function() { - let content; - let maxSizeReached; + let content: string; + let maxSizeReached: boolean; beforeEach(async function() { mockReportingPlugin.getUiSettingsServiceFactory = () => mockUiSettingsClient; @@ -887,12 +926,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); ({ content, max_size_reached: maxSizeReached } = await executeJob( 'job123', @@ -924,12 +963,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); @@ -950,12 +989,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); @@ -976,12 +1015,12 @@ describe('CSV Execute Job', function() { }); const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - }; + }); await executeJob('job123', jobParams, cancellationToken); diff --git a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts similarity index 58% rename from x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js rename to x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts index cb63e7dad2fdf..c9cba64a732b6 100644 --- a/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/png/server/execute_job/index.test.ts @@ -5,19 +5,22 @@ */ import * as Rx from 'rxjs'; -import { createMockReportingCore } from '../../../../test_helpers'; +import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; import { executeJobFactory } from './index'; import { generatePngObservableFactory } from '../lib/generate_png'; +import { CancellationToken } from '../../../../common/cancellation_token'; import { LevelLogger } from '../../../../server/lib'; +import { ReportingCore, CaptureConfig } from '../../../../server/types'; +import { JobDocPayloadPNG } from '../../types'; jest.mock('../lib/generate_png', () => ({ generatePngObservableFactory: jest.fn() })); -let mockReporting; +let mockReporting: ReportingCore; -const cancellationToken = { +const cancellationToken = ({ on: jest.fn(), -}; +} as unknown) as CancellationToken; const mockLoggerFactory = { get: jest.fn().mockImplementation(() => ({ @@ -28,12 +31,16 @@ const mockLoggerFactory = { }; const getMockLogger = () => new LevelLogger(mockLoggerFactory); +const captureConfig = {} as CaptureConfig; + const mockEncryptionKey = 'abcabcsecuresecret'; -const encryptHeaders = async headers => { +const encryptHeaders = async (headers: Record) => { const crypto = cryptoFactory(mockEncryptionKey); return await crypto.encrypt(headers); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPNG; + beforeEach(async () => { const kbnConfig = { 'server.basePath': '/sbp', @@ -45,8 +52,8 @@ beforeEach(async () => { 'kibanaServer.protocol': 'http', }; const mockReportingConfig = { - get: (...keys) => reportingConfig[keys.join('.')], - kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] }, + get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')], + kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] }, }; mockReporting = await createMockReportingCore(mockReportingConfig); @@ -60,22 +67,30 @@ beforeEach(async () => { mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch)); mockReporting.getElasticsearchService = mockGetElasticsearch; - generatePngObservableFactory.mockReturnValue(jest.fn()); + (generatePngObservableFactory as jest.Mock).mockReturnValue(jest.fn()); }); -afterEach(() => generatePngObservableFactory.mockReset()); +afterEach(() => (generatePngObservableFactory as jest.Mock).mockReset()); test(`passes browserTimezone to generatePng`, async () => { const encryptedHeaders = await encryptHeaders({}); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const browserTimezone = 'UTC'; await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', browserTimezone, headers: encryptedHeaders }, + getJobDocPayload({ + relativeUrl: '/app/kibana#/something', + browserTimezone, + headers: encryptedHeaders, + }), cancellationToken ); @@ -92,12 +107,17 @@ test(`returns content_type of application/png`, async () => { const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); + + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const { content_type: contentType } = await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }), cancellationToken ); expect(contentType).toBe('image/png'); @@ -106,14 +126,19 @@ test(`returns content_type of application/png`, async () => { test(`returns content of generatePng getBuffer base64 encoded`, async () => { const testContent = 'test content'; - const generatePngObservable = generatePngObservableFactory(); - generatePngObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); + + const generatePngObservable = generatePngObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pngJobId', - { relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }), cancellationToken ); diff --git a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts similarity index 57% rename from x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js rename to x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts index c6f07f8ad2d34..c3c0d38584bc1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.js +++ b/x-pack/legacy/plugins/reporting/export_types/printable_pdf/server/execute_job/index.test.ts @@ -5,19 +5,24 @@ */ import * as Rx from 'rxjs'; -import { createMockReportingCore } from '../../../../test_helpers'; +import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers'; import { cryptoFactory } from '../../../../server/lib/crypto'; -import { executeJobFactory } from './index'; -import { generatePdfObservableFactory } from '../lib/generate_pdf'; import { LevelLogger } from '../../../../server/lib'; +import { CancellationToken } from '../../../../types'; +import { ReportingCore, CaptureConfig } from '../../../../server/types'; +import { generatePdfObservableFactory } from '../lib/generate_pdf'; +import { JobDocPayloadPDF } from '../../types'; +import { executeJobFactory } from './index'; jest.mock('../lib/generate_pdf', () => ({ generatePdfObservableFactory: jest.fn() })); -let mockReporting; +let mockReporting: ReportingCore; -const cancellationToken = { +const cancellationToken = ({ on: jest.fn(), -}; +} as unknown) as CancellationToken; + +const captureConfig = {} as CaptureConfig; const mockLoggerFactory = { get: jest.fn().mockImplementation(() => ({ @@ -29,11 +34,13 @@ const mockLoggerFactory = { const getMockLogger = () => new LevelLogger(mockLoggerFactory); const mockEncryptionKey = 'testencryptionkey'; -const encryptHeaders = async headers => { +const encryptHeaders = async (headers: Record) => { const crypto = cryptoFactory(mockEncryptionKey); return await crypto.encrypt(headers); }; +const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPDF; + beforeEach(async () => { const kbnConfig = { 'server.basePath': '/sbp', @@ -45,8 +52,8 @@ beforeEach(async () => { 'kibanaServer.protocol': 'http', }; const mockReportingConfig = { - get: (...keys) => reportingConfig[keys.join('.')], - kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] }, + get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')], + kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] }, }; mockReporting = await createMockReportingCore(mockReportingConfig); @@ -60,21 +67,26 @@ beforeEach(async () => { mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch)); mockReporting.getElasticsearchService = mockGetElasticsearch; - generatePdfObservableFactory.mockReturnValue(jest.fn()); + (generatePdfObservableFactory as jest.Mock).mockReturnValue(jest.fn()); }); -afterEach(() => generatePdfObservableFactory.mockReset()); +afterEach(() => (generatePdfObservableFactory as jest.Mock).mockReset()); test(`returns content_type of application/pdf`, async () => { - const executeJob = await executeJobFactory(mockReporting, getMockLogger()); + const logger = getMockLogger(); + const executeJob = await executeJobFactory(mockReporting, logger); + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(logger); const encryptedHeaders = await encryptHeaders({}); - const generatePdfObservable = generatePdfObservableFactory(); - generatePdfObservable.mockReturnValue(Rx.of(Buffer.from(''))); + const generatePdfObservable = generatePdfObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from(''))); const { content_type: contentType } = await executeJob( 'pdfJobId', - { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }), cancellationToken ); expect(contentType).toBe('application/pdf'); @@ -82,15 +94,19 @@ test(`returns content_type of application/pdf`, async () => { test(`returns content of generatePdf getBuffer base64 encoded`, async () => { const testContent = 'test content'; + const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger()); - const generatePdfObservable = generatePdfObservableFactory(); - generatePdfObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); + const generatePdfObservable = generatePdfObservableFactory( + captureConfig, + mockBrowserDriverFactory + ); + (generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) })); const executeJob = await executeJobFactory(mockReporting, getMockLogger()); const encryptedHeaders = await encryptHeaders({}); const { content } = await executeJob( 'pdfJobId', - { relativeUrls: [], timeRange: {}, headers: encryptedHeaders }, + getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }), cancellationToken ); diff --git a/x-pack/legacy/plugins/reporting/index.test.js b/x-pack/legacy/plugins/reporting/index.test.ts similarity index 94% rename from x-pack/legacy/plugins/reporting/index.test.js rename to x-pack/legacy/plugins/reporting/index.test.ts index 0d9a717bd7d81..8148adab67874 100644 --- a/x-pack/legacy/plugins/reporting/index.test.js +++ b/x-pack/legacy/plugins/reporting/index.test.ts @@ -27,7 +27,7 @@ const describeWithContext = describe.each([ describeWithContext('config schema with context %j', context => { it('produces correct config', async () => { const schema = await getConfigSchema(reporting); - const value = await schema.validate({}, { context }); + const value: any = await schema.validate({}, { context }); value.capture.browser.chromium.disableSandbox = ''; await expect(value).toMatchSnapshot(); }); diff --git a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts similarity index 91% rename from x-pack/legacy/plugins/reporting/server/routes/jobs.test.js rename to x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts index 9f0de844df369..5c58a7dfa0110 100644 --- a/x-pack/legacy/plugins/reporting/server/routes/jobs.test.js +++ b/x-pack/legacy/plugins/reporting/server/routes/jobs.test.ts @@ -6,7 +6,10 @@ import Hapi from 'hapi'; import { createMockReportingCore } from '../../test_helpers'; +import { ExportTypeDefinition } from '../../types'; import { ExportTypesRegistry } from '../lib/export_types_registry'; +import { LevelLogger } from '../lib/level_logger'; +import { ReportingConfig, ReportingCore, ReportingSetupDeps } from '../types'; jest.mock('./lib/authorized_user_pre_routing', () => ({ authorizedUserPreRoutingFactory: () => () => ({}), @@ -19,14 +22,14 @@ jest.mock('./lib/reporting_feature_pre_routing', () => ({ import { registerJobInfoRoutes } from './jobs'; -let mockServer; -let exportTypesRegistry; -let mockReportingPlugin; -let mockReportingConfig; -const mockLogger = { +let mockServer: any; +let exportTypesRegistry: ExportTypesRegistry; +let mockReportingPlugin: ReportingCore; +let mockReportingConfig: ReportingConfig; +const mockLogger = ({ error: jest.fn(), debug: jest.fn(), -}; +} as unknown) as LevelLogger; beforeEach(async () => { mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } }); @@ -35,38 +38,39 @@ beforeEach(async () => { id: 'unencoded', jobType: 'unencodedJobType', jobContentExtension: 'csv', - }); + } as ExportTypeDefinition); exportTypesRegistry.register({ id: 'base64Encoded', jobType: 'base64EncodedJobType', jobContentEncoding: 'base64', jobContentExtension: 'pdf', - }); + } as ExportTypeDefinition); mockReportingConfig = { get: jest.fn(), kbnConfig: { get: jest.fn() } }; mockReportingPlugin = await createMockReportingCore(mockReportingConfig); mockReportingPlugin.getExportTypesRegistry = () => exportTypesRegistry; }); -const mockPlugins = { +const mockPlugins = ({ elasticsearch: { adminClient: { callAsInternalUser: jest.fn() }, }, security: null, -}; +} as unknown) as ReportingSetupDeps; -const getHits = (...sources) => { +const getHits = (...sources: any) => { return { hits: { - hits: sources.map(source => ({ _source: source })), + hits: sources.map((source: object) => ({ _source: source })), }, }; }; -const getErrorsFromRequest = request => - request.logs.filter(log => log.tags.includes('error')).map(log => log.error); +const getErrorsFromRequest = (request: any) => + request.logs.filter((log: any) => log.tags.includes('error')).map((log: any) => log.error); test(`returns 404 if job not found`, async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(getHits())), }; @@ -84,6 +88,7 @@ test(`returns 404 if job not found`, async () => { }); test(`returns 401 if not valid job type`, async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest .fn() @@ -103,6 +108,7 @@ test(`returns 401 if not valid job type`, async () => { describe(`when job is incomplete`, () => { const getIncompleteResponse = async () => { + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest .fn() @@ -149,6 +155,7 @@ describe(`when job is failed`, () => { status: 'failed', output: { content: 'job failure message' }, }); + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; @@ -194,6 +201,7 @@ describe(`when job is completed`, () => { title, }, }); + // @ts-ignore mockPlugins.elasticsearch.adminClient = { callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)), }; diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts similarity index 90% rename from x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js rename to x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts index 929109e66914d..dbc674ce36ec8 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.js +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts @@ -11,18 +11,21 @@ import { registerReportingUsageCollector, getReportingUsageCollector, } from './reporting_usage_collector'; +import { ReportingConfig } from '../types'; const exportTypesRegistry = getExportTypesRegistry(); function getMockUsageCollection() { class MockUsageCollector { - constructor(_server, { fetch }) { + // @ts-ignore fetch is not used + private fetch: any; + constructor(_server: any, { fetch }: any) { this.fetch = fetch; } } return { - makeUsageCollector: options => { - return new MockUsageCollector(this, options); + makeUsageCollector: (options: any) => { + return new MockUsageCollector(null, options); }, registerCollector: sinon.stub(), }; @@ -51,7 +54,7 @@ function getPluginsMock( xpack_main: mockXpackMain, }, }, - }; + } as any; } const getMockReportingConfig = () => ({ @@ -61,13 +64,13 @@ const getMockReportingConfig = () => ({ const getResponseMock = (customization = {}) => customization; describe('license checks', () => { - let mockConfig; + let mockConfig: ReportingConfig; beforeAll(async () => { mockConfig = getMockReportingConfig(); }); describe('with a basic license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'basic' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -75,9 +78,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -94,7 +100,7 @@ describe('license checks', () => { }); describe('with no license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'none' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -102,9 +108,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -121,7 +130,7 @@ describe('license checks', () => { }); describe('with platinum license', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'platinum' }); const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock())); @@ -129,9 +138,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -148,7 +160,7 @@ describe('license checks', () => { }); describe('with no usage data', () => { - let usageStats; + let usageStats: any; beforeAll(async () => { const plugins = getPluginsMock({ license: 'basic' }); const callClusterMock = jest.fn(() => Promise.resolve({})); @@ -156,9 +168,12 @@ describe('license checks', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); - usageStats = await fetch(callClusterMock, exportTypesRegistry); + usageStats = await fetch(callClusterMock as any); }); test('sets enables to true', async () => { @@ -179,7 +194,10 @@ describe('data modeling', () => { mockConfig, plugins.usageCollection, plugins.__LEGACY.plugins.xpack_main.info, - exportTypesRegistry + exportTypesRegistry, + function isReady() { + return Promise.resolve(true); + } ); const callClusterMock = jest.fn(() => Promise.resolve( @@ -303,7 +321,7 @@ describe('data modeling', () => { ) ); - const usageStats = await fetch(callClusterMock); + const usageStats = await fetch(callClusterMock as any); expect(usageStats).toMatchInlineSnapshot(` Object { "PNG": Object { @@ -406,7 +424,7 @@ describe('Ready for collection observable', () => { const makeCollectorSpy = sinon.spy(); usageCollection.makeUsageCollector = makeCollectorSpy; - const plugins = getPluginsMock({ usageCollection }); + const plugins = getPluginsMock({ usageCollection } as any); registerReportingUsageCollector(mockReporting, plugins); const [args] = makeCollectorSpy.firstCall.args; diff --git a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts index 930aa7601b8cb..6e95bed2ecf92 100644 --- a/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts +++ b/x-pack/legacy/plugins/reporting/test_helpers/create_mock_browserdriverfactory.ts @@ -92,7 +92,7 @@ const defaultOpts: CreateMockBrowserDriverFactoryOpts = { export const createMockBrowserDriverFactory = async ( logger: Logger, - opts: Partial + opts: Partial = {} ): Promise => { const captureConfig = { timeouts: { openUrl: 30000, waitForElements: 30000, renderComplete: 30000 }, diff --git a/x-pack/legacy/plugins/reporting/types.d.ts b/x-pack/legacy/plugins/reporting/types.d.ts index 7334a859005e0..eec7da7dc6733 100644 --- a/x-pack/legacy/plugins/reporting/types.d.ts +++ b/x-pack/legacy/plugins/reporting/types.d.ts @@ -186,7 +186,7 @@ export type ESQueueWorkerExecuteFn = ( jobId: string, job: JobDocPayloadType, cancellationToken?: CancellationToken -) => void; +) => Promise; /* * ImmediateExecuteFn receives the job doc payload because the payload was