From d9ce4024ecde27974046dc5ae4ecf27a5580f308 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Tue, 7 Apr 2020 08:31:58 -0700 Subject: [PATCH 1/3] [Reporting] convert all server unit tests to TypeScript --- ...{index.test.js.snap => index.test.ts.snap} | 0 ...xecute_job.test.js => execute_job.test.ts} | 219 +++++++++++------- .../{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} | 56 +++-- .../create_mock_browserdriverfactory.ts | 2 +- x-pack/legacy/plugins/reporting/types.d.ts | 2 +- 9 files changed, 268 insertions(+), 162 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 93dbe598b367c..6ea4e20bed755 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,35 +14,39 @@ 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'; -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: { @@ -77,7 +82,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'defaultScrollId', }; clusterStub = { - callAsCurrentUser: function() {}, + callAsCurrentUser() {}, }; callAsCurrentUserStub = sinon @@ -88,17 +93,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); }, }); }); @@ -108,7 +115,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); @@ -122,14 +133,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); @@ -151,7 +162,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 ); @@ -165,7 +180,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 ); @@ -195,7 +214,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 ); @@ -230,7 +253,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 ); @@ -256,12 +283,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]`); @@ -283,12 +310,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, @@ -308,12 +335,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, @@ -333,12 +360,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, @@ -358,12 +385,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, @@ -378,11 +405,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]`); @@ -397,11 +424,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]`); @@ -418,11 +445,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( @@ -439,11 +466,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( @@ -467,11 +494,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( @@ -495,11 +522,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( @@ -533,7 +560,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 ); @@ -548,13 +579,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? } }); @@ -562,7 +597,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); @@ -578,11 +617,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`); }); @@ -590,11 +629,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`); }); @@ -602,11 +641,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`); }); @@ -614,11 +653,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`); }); @@ -632,11 +671,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]; @@ -652,12 +691,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]; @@ -679,12 +718,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'); @@ -701,7 +740,7 @@ describe('CSV Execute Job', function() { _scroll_id: 'scrollId', }); - const jobParams = { + const jobParams = getJobDocPayload({ headers: encryptedHeaders, fields: ['one', 'two'], conflictedTypesFields: [], @@ -715,7 +754,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'); @@ -729,18 +768,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', @@ -759,18 +798,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', @@ -789,8 +828,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); @@ -803,12 +842,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', @@ -827,8 +866,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; @@ -842,12 +881,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', @@ -879,12 +918,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); @@ -905,12 +944,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); @@ -931,12 +970,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..2c3f732ce44f0 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 { 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 From 0d4c2ad29a3dc83d3ded404c15360c2cd4cdf260 Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Wed, 8 Apr 2020 10:41:19 -0700 Subject: [PATCH 2/3] fix ts --- .../reporting/server/usage/reporting_usage_collector.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts index 2c3f732ce44f0..dbc674ce36ec8 100644 --- a/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts +++ b/x-pack/legacy/plugins/reporting/server/usage/reporting_usage_collector.test.ts @@ -424,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; From 1e0105e673607b9b2581b2a47a24653fe545f97e Mon Sep 17 00:00:00 2001 From: Timothy Sullivan Date: Thu, 9 Apr 2020 14:31:58 -0700 Subject: [PATCH 3/3] revert unrelated change --- .../plugins/reporting/export_types/csv/server/execute_job.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index 1db5ab270e481..376a398da274f 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -17,7 +17,7 @@ import { fieldFormatMapFactory } from './lib/field_format_map'; import { createGenerateCsv } from './lib/generate_csv'; export const executeJobFactory: ExecuteJobFactory + JobDocPayloadDiscoverCsv >> = async function executeJobFactoryFn(reporting: ReportingCore, parentLogger: Logger) { const config = reporting.getConfig(); const crypto = cryptoFactory(config.get('encryptionKey'));