From 2b53db94a433188f3e0c91ff4d6fd3c832e12076 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 9 Nov 2021 12:37:02 +0100 Subject: [PATCH 1/7] mock and reduce the wait time for reading diagnoistic logs --- .../browsers/chromium/driver_factory/constants.ts | 10 ++++++++++ .../browsers/chromium/driver_factory/start_logs.ts | 4 ++-- .../reporting/server/routes/diagnostic/browser.test.ts | 6 +++++- 3 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts new file mode 100644 index 0000000000000..3fdbff2808696 --- /dev/null +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const BROWSER_LAUNCH_TIME_TO_WAIT = 5 * 1000; + +export const getBrowserLaunchTime = () => BROWSER_LAUNCH_TIME_TO_WAIT; diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts index 1a739488bf6ed..7f0a00623b89b 100644 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts @@ -20,9 +20,9 @@ import { ReportingCore } from '../../../'; import { LevelLogger } from '../../../lib'; import { ChromiumArchivePaths } from '../paths'; import { args } from './args'; +import { getBrowserLaunchTime } from './constants'; const paths = new ChromiumArchivePaths(); -const browserLaunchTimeToWait = 5 * 1000; // Default args used by pptr // https://github.com/puppeteer/puppeteer/blob/13ea347/src/node/Launcher.ts#L168 @@ -121,7 +121,7 @@ export const browserStartLogs = ( // logs as sometimes it's "bind" successfully for remote connections, but later emit // a log indicative of an issue (for example, no default font found). return merge(exit$, error$, log$).pipe( - takeUntil(timer(browserLaunchTimeToWait)), + takeUntil(timer(getBrowserLaunchTime())), reduce((acc, curr) => `${acc}${curr}\n`, ''), tap(() => { if (browserProcess && browserProcess.pid && !browserProcess.killed) { diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index 7b4cc2008a676..c56ffad3765fe 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -19,7 +19,9 @@ import { } from '../../test_helpers'; import type { ReportingRequestHandlerContext } from '../../types'; import { registerDiagnoseBrowser } from './browser'; +import { getBrowserLaunchTime } from '../../browsers/chromium/driver_factory/constants'; +jest.mock('../../browsers/chromium/driver_factory/constants'); jest.mock('child_process'); jest.mock('readline'); @@ -29,7 +31,7 @@ const devtoolMessage = 'DevTools listening on (ws://localhost:4000)'; const fontNotFoundMessage = 'Could not find the default font'; // FLAKY: https://github.com/elastic/kibana/issues/89369 -describe.skip('POST /diagnose/browser', () => { +describe('POST /diagnose/browser', () => { jest.setTimeout(6000); const reportingSymbol = Symbol('reporting'); const mockLogger = createMockLevelLogger(); @@ -46,6 +48,8 @@ describe.skip('POST /diagnose/browser', () => { }); beforeEach(async () => { + (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); + ({ server, httpSetup } = await setupServer(reportingSymbol)); httpSetup.registerRouteHandlerContext( reportingSymbol, From d6d403c304daf96876990da1c41066f472f5b655 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 9 Nov 2021 12:41:55 +0100 Subject: [PATCH 2/7] remove comment --- .../plugins/reporting/server/routes/diagnostic/browser.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index c56ffad3765fe..62cee21472a22 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -30,7 +30,6 @@ type SetupServerReturn = UnwrapPromise>; const devtoolMessage = 'DevTools listening on (ws://localhost:4000)'; const fontNotFoundMessage = 'Could not find the default font'; -// FLAKY: https://github.com/elastic/kibana/issues/89369 describe('POST /diagnose/browser', () => { jest.setTimeout(6000); const reportingSymbol = Symbol('reporting'); From f9474aa1dbc4f215708ba6bdcb5ede1ed72411bd Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 9 Nov 2021 14:40:10 +0100 Subject: [PATCH 3/7] run test suite 42 times - REVERT THIS --- .../server/routes/diagnostic/browser.test.ts | 459 +++++++++--------- 1 file changed, 231 insertions(+), 228 deletions(-) diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index 62cee21472a22..a5cd0436b2ca8 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -30,234 +30,237 @@ type SetupServerReturn = UnwrapPromise>; const devtoolMessage = 'DevTools listening on (ws://localhost:4000)'; const fontNotFoundMessage = 'Could not find the default font'; -describe('POST /diagnose/browser', () => { - jest.setTimeout(6000); - const reportingSymbol = Symbol('reporting'); - const mockLogger = createMockLevelLogger(); - - let server: SetupServerReturn['server']; - let httpSetup: SetupServerReturn['httpSetup']; - let core: ReportingCore; - const mockedSpawn: any = spawn; - const mockedCreateInterface: any = createInterface; - - const config = createMockConfigSchema({ - queue: { timeout: 120000 }, - capture: { browser: { chromium: { proxy: { enabled: false } } } }, - }); - - beforeEach(async () => { - (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); - - ({ server, httpSetup } = await setupServer(reportingSymbol)); - httpSetup.registerRouteHandlerContext( - reportingSymbol, - 'reporting', - () => ({ usesUiCapabilities: () => false }) - ); - - core = await createMockReportingCore( - config, - createMockPluginSetup({ - router: httpSetup.createRouter(''), - security: null, - }) - ); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - }); - - afterEach(async () => { - await server.stop(); - }); - - it('returns a 200 when successful', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body.success).toEqual(true); - expect(body.help).toEqual([]); - }); - }); - - it('returns logs when browser crashes + helpful links', async () => { - const logs = `Could not find the default font`; - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` - Object { - "help": Array [ - "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ], - "logs": "Could not find the default font - ", - "success": false, +// TODO: UNDO THIS FOR LOOP! +for (let x = 1; x < 43; x++) { + describe(`POST /diagnose/browser (${x})`, () => { + jest.setTimeout(6000); + const reportingSymbol = Symbol('reporting'); + const mockLogger = createMockLevelLogger(); + + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + let core: ReportingCore; + const mockedSpawn: any = spawn; + const mockedCreateInterface: any = createInterface; + + const config = createMockConfigSchema({ + queue: { timeout: 120000 }, + capture: { browser: { chromium: { proxy: { enabled: false } } } }, + }); + + beforeEach(async () => { + (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); + + ({ server, httpSetup } = await setupServer(reportingSymbol)); + httpSetup.registerRouteHandlerContext( + reportingSymbol, + 'reporting', + () => ({ usesUiCapabilities: () => false }) + ); + + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + }); + + afterEach(async () => { + await server.stop(); + }); + + it('returns a 200 when successful', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body.success).toEqual(true); + expect(body.help).toEqual([]); + }); + }); + + it('returns logs when browser crashes + helpful links', async () => { + const logs = `Could not find the default font`; + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` + Object { + "help": Array [ + "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", + ], + "logs": "Could not find the default font + ", + "success": false, + } + `); + }); + }); + + it('logs a message when the browser starts, but then has problems later', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(devtoolMessage), 0); + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` + Object { + "help": Array [ + "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", + ], + "logs": "DevTools listening on (ws://localhost:4000) + Could not find the default font + ", + "success": false, + } + `); + }); + }); + + it('logs a message when the browser starts, but then crashes', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: (e: string, cb: any) => { + if (e === 'exit') { + setTimeout(() => cb(), 5); } - `); - }); - }); - - it('logs a message when the browser starts, but then has problems later', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(devtoolMessage), 0); - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` - Object { - "help": Array [ + }, + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + const helpArray = [...body.help]; + helpArray.sort(); + expect(helpArray).toMatchInlineSnapshot(` + Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ], - "logs": "DevTools listening on (ws://localhost:4000) - Could not find the default font - ", - "success": false, - } - `); - }); - }); - - it('logs a message when the browser starts, but then crashes', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: (e: string, cb: any) => { - if (e === 'exit') { - setTimeout(() => cb(), 5); - } - }, - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - const helpArray = [...body.help]; - helpArray.sort(); - expect(helpArray).toMatchInlineSnapshot(` - Array [ - "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ] - `); - expect(body.logs).toMatch(/Could not find the default font/); - expect(body.logs).toMatch(/Browser exited abnormally during startup/); - expect(body.success).toBe(false); - }); - }); - - it('cleans up process and subscribers', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - const killMock = jest.fn(); - const spawnListenersMock = jest.fn(); - const createInterfaceListenersMock = jest.fn(); - const createInterfaceCloseMock = jest.fn(); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: spawnListenersMock, - kill: killMock, - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: createInterfaceListenersMock, - close: createInterfaceCloseMock, - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(() => { - expect(killMock.mock.calls.length).toBe(1); - expect(spawnListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceCloseMock.mock.calls.length).toBe(1); - }); + ] + `); + expect(body.logs).toMatch(/Could not find the default font/); + expect(body.logs).toMatch(/Browser exited abnormally during startup/); + expect(body.success).toBe(false); + }); + }); + + it('cleans up process and subscribers', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + const killMock = jest.fn(); + const spawnListenersMock = jest.fn(); + const createInterfaceListenersMock = jest.fn(); + const createInterfaceCloseMock = jest.fn(); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: spawnListenersMock, + kill: killMock, + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: createInterfaceListenersMock, + close: createInterfaceCloseMock, + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(() => { + expect(killMock.mock.calls.length).toBe(1); + expect(spawnListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceCloseMock.mock.calls.length).toBe(1); + }); + }); }); -}); +} From bf31a0cf64dfc0e3d18201abc9fe514adc8dc2e8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 9 Nov 2021 19:29:00 +0100 Subject: [PATCH 4/7] Revert "run test suite 42 times - REVERT THIS" This reverts commit f9474aa1dbc4f215708ba6bdcb5ede1ed72411bd. --- .../server/routes/diagnostic/browser.test.ts | 459 +++++++++--------- 1 file changed, 228 insertions(+), 231 deletions(-) diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index a5cd0436b2ca8..62cee21472a22 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -30,237 +30,234 @@ type SetupServerReturn = UnwrapPromise>; const devtoolMessage = 'DevTools listening on (ws://localhost:4000)'; const fontNotFoundMessage = 'Could not find the default font'; -// TODO: UNDO THIS FOR LOOP! -for (let x = 1; x < 43; x++) { - describe(`POST /diagnose/browser (${x})`, () => { - jest.setTimeout(6000); - const reportingSymbol = Symbol('reporting'); - const mockLogger = createMockLevelLogger(); - - let server: SetupServerReturn['server']; - let httpSetup: SetupServerReturn['httpSetup']; - let core: ReportingCore; - const mockedSpawn: any = spawn; - const mockedCreateInterface: any = createInterface; - - const config = createMockConfigSchema({ - queue: { timeout: 120000 }, - capture: { browser: { chromium: { proxy: { enabled: false } } } }, - }); - - beforeEach(async () => { - (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); - - ({ server, httpSetup } = await setupServer(reportingSymbol)); - httpSetup.registerRouteHandlerContext( - reportingSymbol, - 'reporting', - () => ({ usesUiCapabilities: () => false }) - ); - - core = await createMockReportingCore( - config, - createMockPluginSetup({ - router: httpSetup.createRouter(''), - security: null, - }) - ); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - }); - - afterEach(async () => { - await server.stop(); - }); - - it('returns a 200 when successful', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body.success).toEqual(true); - expect(body.help).toEqual([]); - }); - }); - - it('returns logs when browser crashes + helpful links', async () => { - const logs = `Could not find the default font`; - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` - Object { - "help": Array [ - "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ], - "logs": "Could not find the default font - ", - "success": false, - } - `); - }); - }); - - it('logs a message when the browser starts, but then has problems later', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(devtoolMessage), 0); - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` - Object { - "help": Array [ - "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ], - "logs": "DevTools listening on (ws://localhost:4000) - Could not find the default font - ", - "success": false, - } - `); - }); - }); - - it('logs a message when the browser starts, but then crashes', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: (e: string, cb: any) => { - if (e === 'exit') { - setTimeout(() => cb(), 5); +describe('POST /diagnose/browser', () => { + jest.setTimeout(6000); + const reportingSymbol = Symbol('reporting'); + const mockLogger = createMockLevelLogger(); + + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + let core: ReportingCore; + const mockedSpawn: any = spawn; + const mockedCreateInterface: any = createInterface; + + const config = createMockConfigSchema({ + queue: { timeout: 120000 }, + capture: { browser: { chromium: { proxy: { enabled: false } } } }, + }); + + beforeEach(async () => { + (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); + + ({ server, httpSetup } = await setupServer(reportingSymbol)); + httpSetup.registerRouteHandlerContext( + reportingSymbol, + 'reporting', + () => ({ usesUiCapabilities: () => false }) + ); + + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + }); + + afterEach(async () => { + await server.stop(); + }); + + it('returns a 200 when successful', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body.success).toEqual(true); + expect(body.help).toEqual([]); + }); + }); + + it('returns logs when browser crashes + helpful links', async () => { + const logs = `Could not find the default font`; + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` + Object { + "help": Array [ + "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", + ], + "logs": "Could not find the default font + ", + "success": false, } - }, - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - const helpArray = [...body.help]; - helpArray.sort(); - expect(helpArray).toMatchInlineSnapshot(` - Array [ + `); + }); + }); + + it('logs a message when the browser starts, but then has problems later', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(devtoolMessage), 0); + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` + Object { + "help": Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", - ] - `); - expect(body.logs).toMatch(/Could not find the default font/); - expect(body.logs).toMatch(/Browser exited abnormally during startup/); - expect(body.success).toBe(false); - }); - }); - - it('cleans up process and subscribers', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - const killMock = jest.fn(); - const spawnListenersMock = jest.fn(); - const createInterfaceListenersMock = jest.fn(); - const createInterfaceCloseMock = jest.fn(); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: spawnListenersMock, - kill: killMock, - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: createInterfaceListenersMock, - close: createInterfaceCloseMock, - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(() => { - expect(killMock.mock.calls.length).toBe(1); - expect(spawnListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceCloseMock.mock.calls.length).toBe(1); - }); - }); + ], + "logs": "DevTools listening on (ws://localhost:4000) + Could not find the default font + ", + "success": false, + } + `); + }); + }); + + it('logs a message when the browser starts, but then crashes', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: (e: string, cb: any) => { + if (e === 'exit') { + setTimeout(() => cb(), 5); + } + }, + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + const helpArray = [...body.help]; + helpArray.sort(); + expect(helpArray).toMatchInlineSnapshot(` + Array [ + "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", + ] + `); + expect(body.logs).toMatch(/Could not find the default font/); + expect(body.logs).toMatch(/Browser exited abnormally during startup/); + expect(body.success).toBe(false); + }); + }); + + it('cleans up process and subscribers', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + const killMock = jest.fn(); + const spawnListenersMock = jest.fn(); + const createInterfaceListenersMock = jest.fn(); + const createInterfaceCloseMock = jest.fn(); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: spawnListenersMock, + kill: killMock, + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: createInterfaceListenersMock, + close: createInterfaceCloseMock, + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(() => { + expect(killMock.mock.calls.length).toBe(1); + expect(spawnListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceCloseMock.mock.calls.length).toBe(1); + }); }); -} +}); From 50894619555a0c84241b6e9fb7f1c5f66f1a4b86 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 10 Nov 2021 14:32:51 +0100 Subject: [PATCH 5/7] mock Rx.timer instead, revert previous solution --- .../browsers/chromium/driver_factory/constants.ts | 10 ---------- .../browsers/chromium/driver_factory/start_logs.ts | 4 ++-- .../server/routes/diagnostic/browser.test.ts | 11 +++++++---- 3 files changed, 9 insertions(+), 16 deletions(-) delete mode 100644 x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts deleted file mode 100644 index 3fdbff2808696..0000000000000 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -const BROWSER_LAUNCH_TIME_TO_WAIT = 5 * 1000; - -export const getBrowserLaunchTime = () => BROWSER_LAUNCH_TIME_TO_WAIT; diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts index 7f0a00623b89b..1a739488bf6ed 100644 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/start_logs.ts @@ -20,9 +20,9 @@ import { ReportingCore } from '../../../'; import { LevelLogger } from '../../../lib'; import { ChromiumArchivePaths } from '../paths'; import { args } from './args'; -import { getBrowserLaunchTime } from './constants'; const paths = new ChromiumArchivePaths(); +const browserLaunchTimeToWait = 5 * 1000; // Default args used by pptr // https://github.com/puppeteer/puppeteer/blob/13ea347/src/node/Launcher.ts#L168 @@ -121,7 +121,7 @@ export const browserStartLogs = ( // logs as sometimes it's "bind" successfully for remote connections, but later emit // a log indicative of an issue (for example, no default font found). return merge(exit$, error$, log$).pipe( - takeUntil(timer(getBrowserLaunchTime())), + takeUntil(timer(browserLaunchTimeToWait)), reduce((acc, curr) => `${acc}${curr}\n`, ''), tap(() => { if (browserProcess && browserProcess.pid && !browserProcess.killed) { diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index 62cee21472a22..2af5874142b8b 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -10,6 +10,7 @@ import { spawn } from 'child_process'; import { createInterface } from 'readline'; import { setupServer } from 'src/core/server/test_utils'; import supertest from 'supertest'; +import * as Rx from 'rxjs'; import { ReportingCore } from '../..'; import { createMockConfigSchema, @@ -19,9 +20,7 @@ import { } from '../../test_helpers'; import type { ReportingRequestHandlerContext } from '../../types'; import { registerDiagnoseBrowser } from './browser'; -import { getBrowserLaunchTime } from '../../browsers/chromium/driver_factory/constants'; -jest.mock('../../browsers/chromium/driver_factory/constants'); jest.mock('child_process'); jest.mock('readline'); @@ -30,6 +29,9 @@ type SetupServerReturn = UnwrapPromise>; const devtoolMessage = 'DevTools listening on (ws://localhost:4000)'; const fontNotFoundMessage = 'Could not find the default font'; +const wait = (ms: number): Rx.Observable<0> => + Rx.from(new Promise<0>((resolve) => setTimeout(() => resolve(0), ms))); + describe('POST /diagnose/browser', () => { jest.setTimeout(6000); const reportingSymbol = Symbol('reporting'); @@ -47,8 +49,6 @@ describe('POST /diagnose/browser', () => { }); beforeEach(async () => { - (getBrowserLaunchTime as jest.Mock).mockReturnValue(500); - ({ server, httpSetup } = await setupServer(reportingSymbol)); httpSetup.registerRouteHandlerContext( reportingSymbol, @@ -56,6 +56,8 @@ describe('POST /diagnose/browser', () => { () => ({ usesUiCapabilities: () => false }) ); + jest.spyOn(Rx, 'timer').mockImplementation(() => wait(50)); + core = await createMockReportingCore( config, createMockPluginSetup({ @@ -82,6 +84,7 @@ describe('POST /diagnose/browser', () => { }); afterEach(async () => { + jest.restoreAllMocks(); await server.stop(); }); From c05c0c4c769ab6f195687102b2ecbe4d56d204af Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 10 Nov 2021 14:36:14 +0100 Subject: [PATCH 6/7] added comment --- .../server/routes/diagnostic/browser.test.ts | 419 +++++++++--------- 1 file changed, 211 insertions(+), 208 deletions(-) diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index 2af5874142b8b..bced211d21512 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -32,108 +32,110 @@ const fontNotFoundMessage = 'Could not find the default font'; const wait = (ms: number): Rx.Observable<0> => Rx.from(new Promise<0>((resolve) => setTimeout(() => resolve(0), ms))); -describe('POST /diagnose/browser', () => { - jest.setTimeout(6000); - const reportingSymbol = Symbol('reporting'); - const mockLogger = createMockLevelLogger(); - - let server: SetupServerReturn['server']; - let httpSetup: SetupServerReturn['httpSetup']; - let core: ReportingCore; - const mockedSpawn: any = spawn; - const mockedCreateInterface: any = createInterface; - - const config = createMockConfigSchema({ - queue: { timeout: 120000 }, - capture: { browser: { chromium: { proxy: { enabled: false } } } }, - }); - - beforeEach(async () => { - ({ server, httpSetup } = await setupServer(reportingSymbol)); - httpSetup.registerRouteHandlerContext( - reportingSymbol, - 'reporting', - () => ({ usesUiCapabilities: () => false }) - ); - - jest.spyOn(Rx, 'timer').mockImplementation(() => wait(50)); - - core = await createMockReportingCore( - config, - createMockPluginSetup({ - router: httpSetup.createRouter(''), - security: null, - }) - ); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - }); - - afterEach(async () => { - jest.restoreAllMocks(); - await server.stop(); - }); - - it('returns a 200 when successful', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body.success).toEqual(true); - expect(body.help).toEqual([]); - }); - }); - - it('returns logs when browser crashes + helpful links', async () => { - const logs = `Could not find the default font`; - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` +for (let x = 1; x <= 42; ++x) { + describe(`POST /diagnose/browser (${x})`, () => { + jest.setTimeout(6000); + const reportingSymbol = Symbol('reporting'); + const mockLogger = createMockLevelLogger(); + + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + let core: ReportingCore; + const mockedSpawn: any = spawn; + const mockedCreateInterface: any = createInterface; + + const config = createMockConfigSchema({ + queue: { timeout: 120000 }, + capture: { browser: { chromium: { proxy: { enabled: false } } } }, + }); + + beforeEach(async () => { + ({ server, httpSetup } = await setupServer(reportingSymbol)); + httpSetup.registerRouteHandlerContext( + reportingSymbol, + 'reporting', + () => ({ usesUiCapabilities: () => false }) + ); + + // Make all uses of 'Rx.timer' return an observable that completes in 50ms + jest.spyOn(Rx, 'timer').mockImplementation(() => wait(50)); + + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + }); + + afterEach(async () => { + jest.restoreAllMocks(); + await server.stop(); + }); + + it('returns a 200 when successful', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body.success).toEqual(true); + expect(body.help).toEqual([]); + }); + }); + + it('returns logs when browser crashes + helpful links', async () => { + const logs = `Could not find the default font`; + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` Object { "help": Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", @@ -143,36 +145,36 @@ describe('POST /diagnose/browser', () => { "success": false, } `); - }); - }); - - it('logs a message when the browser starts, but then has problems later', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(devtoolMessage), 0); - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` + }); + }); + + it('logs a message when the browser starts, but then has problems later', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(devtoolMessage), 0); + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` Object { "help": Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", @@ -183,84 +185,85 @@ describe('POST /diagnose/browser', () => { "success": false, } `); - }); - }); - - it('logs a message when the browser starts, but then crashes', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: (e: string, cb: any) => { - if (e === 'exit') { - setTimeout(() => cb(), 5); - } - }, - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - const helpArray = [...body.help]; - helpArray.sort(); - expect(helpArray).toMatchInlineSnapshot(` + }); + }); + + it('logs a message when the browser starts, but then crashes', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: (e: string, cb: any) => { + if (e === 'exit') { + setTimeout(() => cb(), 5); + } + }, + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + const helpArray = [...body.help]; + helpArray.sort(); + expect(helpArray).toMatchInlineSnapshot(` Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", ] `); - expect(body.logs).toMatch(/Could not find the default font/); - expect(body.logs).toMatch(/Browser exited abnormally during startup/); - expect(body.success).toBe(false); - }); - }); - - it('cleans up process and subscribers', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - const killMock = jest.fn(); - const spawnListenersMock = jest.fn(); - const createInterfaceListenersMock = jest.fn(); - const createInterfaceCloseMock = jest.fn(); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: spawnListenersMock, - kill: killMock, - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: createInterfaceListenersMock, - close: createInterfaceCloseMock, - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(() => { - expect(killMock.mock.calls.length).toBe(1); - expect(spawnListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceCloseMock.mock.calls.length).toBe(1); - }); + expect(body.logs).toMatch(/Could not find the default font/); + expect(body.logs).toMatch(/Browser exited abnormally during startup/); + expect(body.success).toBe(false); + }); + }); + + it('cleans up process and subscribers', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + const killMock = jest.fn(); + const spawnListenersMock = jest.fn(); + const createInterfaceListenersMock = jest.fn(); + const createInterfaceCloseMock = jest.fn(); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: spawnListenersMock, + kill: killMock, + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: createInterfaceListenersMock, + close: createInterfaceCloseMock, + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(() => { + expect(killMock.mock.calls.length).toBe(1); + expect(spawnListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceCloseMock.mock.calls.length).toBe(1); + }); + }); }); -}); +} From 26e82a589264cd0d7eedaed5fd9d135c65240954 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 10 Nov 2021 17:44:23 +0100 Subject: [PATCH 7/7] remove for loop --- .../server/routes/diagnostic/browser.test.ts | 420 +++++++++--------- 1 file changed, 209 insertions(+), 211 deletions(-) diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts index bced211d21512..a27ce6a49b1a2 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/browser.test.ts @@ -32,110 +32,109 @@ const fontNotFoundMessage = 'Could not find the default font'; const wait = (ms: number): Rx.Observable<0> => Rx.from(new Promise<0>((resolve) => setTimeout(() => resolve(0), ms))); -for (let x = 1; x <= 42; ++x) { - describe(`POST /diagnose/browser (${x})`, () => { - jest.setTimeout(6000); - const reportingSymbol = Symbol('reporting'); - const mockLogger = createMockLevelLogger(); - - let server: SetupServerReturn['server']; - let httpSetup: SetupServerReturn['httpSetup']; - let core: ReportingCore; - const mockedSpawn: any = spawn; - const mockedCreateInterface: any = createInterface; - - const config = createMockConfigSchema({ - queue: { timeout: 120000 }, - capture: { browser: { chromium: { proxy: { enabled: false } } } }, - }); - - beforeEach(async () => { - ({ server, httpSetup } = await setupServer(reportingSymbol)); - httpSetup.registerRouteHandlerContext( - reportingSymbol, - 'reporting', - () => ({ usesUiCapabilities: () => false }) - ); - - // Make all uses of 'Rx.timer' return an observable that completes in 50ms - jest.spyOn(Rx, 'timer').mockImplementation(() => wait(50)); - - core = await createMockReportingCore( - config, - createMockPluginSetup({ - router: httpSetup.createRouter(''), - security: null, - }) - ); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - }); - - afterEach(async () => { - jest.restoreAllMocks(); - await server.stop(); - }); - - it('returns a 200 when successful', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body.success).toEqual(true); - expect(body.help).toEqual([]); - }); - }); - - it('returns logs when browser crashes + helpful links', async () => { - const logs = `Could not find the default font`; - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` +describe('POST /diagnose/browser', () => { + jest.setTimeout(6000); + const reportingSymbol = Symbol('reporting'); + const mockLogger = createMockLevelLogger(); + + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + let core: ReportingCore; + const mockedSpawn: any = spawn; + const mockedCreateInterface: any = createInterface; + + const config = createMockConfigSchema({ + queue: { timeout: 120000 }, + capture: { browser: { chromium: { proxy: { enabled: false } } } }, + }); + + beforeEach(async () => { + ({ server, httpSetup } = await setupServer(reportingSymbol)); + httpSetup.registerRouteHandlerContext( + reportingSymbol, + 'reporting', + () => ({ usesUiCapabilities: () => false }) + ); + + // Make all uses of 'Rx.timer' return an observable that completes in 50ms + jest.spyOn(Rx, 'timer').mockImplementation(() => wait(50)); + + core = await createMockReportingCore( + config, + createMockPluginSetup({ + router: httpSetup.createRouter(''), + security: null, + }) + ); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + }); + + afterEach(async () => { + jest.restoreAllMocks(); + await server.stop(); + }); + + it('returns a 200 when successful', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body.success).toEqual(true); + expect(body.help).toEqual([]); + }); + }); + + it('returns logs when browser crashes + helpful links', async () => { + const logs = `Could not find the default font`; + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(logs), 0), + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` Object { "help": Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", @@ -145,36 +144,36 @@ for (let x = 1; x <= 42; ++x) { "success": false, } `); - }); - }); - - it('logs a message when the browser starts, but then has problems later', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(devtoolMessage), 0); - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - expect(body).toMatchInlineSnapshot(` + }); + }); + + it('logs a message when the browser starts, but then has problems later', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(devtoolMessage), 0); + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + expect(body).toMatchInlineSnapshot(` Object { "help": Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", @@ -185,85 +184,84 @@ for (let x = 1; x <= 42; ++x) { "success": false, } `); - }); - }); - - it('logs a message when the browser starts, but then crashes', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => { - setTimeout(() => cb(fontNotFoundMessage), 0); - }, - removeEventListener: jest.fn(), - removeAllListeners: jest.fn(), - close: jest.fn(), - })); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: jest.fn(), - kill: jest.fn(), - addEventListener: (e: string, cb: any) => { - if (e === 'exit') { - setTimeout(() => cb(), 5); - } - }, - removeEventListener: jest.fn(), - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(({ body }) => { - const helpArray = [...body.help]; - helpArray.sort(); - expect(helpArray).toMatchInlineSnapshot(` + }); + }); + + it('logs a message when the browser starts, but then crashes', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => { + setTimeout(() => cb(fontNotFoundMessage), 0); + }, + removeEventListener: jest.fn(), + removeAllListeners: jest.fn(), + close: jest.fn(), + })); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: jest.fn(), + kill: jest.fn(), + addEventListener: (e: string, cb: any) => { + if (e === 'exit') { + setTimeout(() => cb(), 5); + } + }, + removeEventListener: jest.fn(), + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(({ body }) => { + const helpArray = [...body.help]; + helpArray.sort(); + expect(helpArray).toMatchInlineSnapshot(` Array [ "The browser couldn't locate a default font. Please see https://www.elastic.co/guide/en/kibana/current/reporting-troubleshooting.html#reporting-troubleshooting-system-dependencies to fix this issue.", ] `); - expect(body.logs).toMatch(/Could not find the default font/); - expect(body.logs).toMatch(/Browser exited abnormally during startup/); - expect(body.success).toBe(false); - }); - }); - - it('cleans up process and subscribers', async () => { - registerDiagnoseBrowser(core, mockLogger); - - await server.start(); - const killMock = jest.fn(); - const spawnListenersMock = jest.fn(); - const createInterfaceListenersMock = jest.fn(); - const createInterfaceCloseMock = jest.fn(); - - mockedSpawn.mockImplementation(() => ({ - removeAllListeners: spawnListenersMock, - kill: killMock, - pid: 123, - stderr: 'stderr', - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - })); - - mockedCreateInterface.mockImplementation(() => ({ - addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), - removeEventListener: jest.fn(), - removeAllListeners: createInterfaceListenersMock, - close: createInterfaceCloseMock, - })); - - return supertest(httpSetup.server.listener) - .post('/api/reporting/diagnose/browser') - .expect(200) - .then(() => { - expect(killMock.mock.calls.length).toBe(1); - expect(spawnListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceListenersMock.mock.calls.length).toBe(1); - expect(createInterfaceCloseMock.mock.calls.length).toBe(1); - }); - }); + expect(body.logs).toMatch(/Could not find the default font/); + expect(body.logs).toMatch(/Browser exited abnormally during startup/); + expect(body.success).toBe(false); + }); + }); + + it('cleans up process and subscribers', async () => { + registerDiagnoseBrowser(core, mockLogger); + + await server.start(); + const killMock = jest.fn(); + const spawnListenersMock = jest.fn(); + const createInterfaceListenersMock = jest.fn(); + const createInterfaceCloseMock = jest.fn(); + + mockedSpawn.mockImplementation(() => ({ + removeAllListeners: spawnListenersMock, + kill: killMock, + pid: 123, + stderr: 'stderr', + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })); + + mockedCreateInterface.mockImplementation(() => ({ + addEventListener: (_e: string, cb: any) => setTimeout(() => cb(devtoolMessage), 0), + removeEventListener: jest.fn(), + removeAllListeners: createInterfaceListenersMock, + close: createInterfaceCloseMock, + })); + + return supertest(httpSetup.server.listener) + .post('/api/reporting/diagnose/browser') + .expect(200) + .then(() => { + expect(killMock.mock.calls.length).toBe(1); + expect(spawnListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceListenersMock.mock.calls.length).toBe(1); + expect(createInterfaceCloseMock.mock.calls.length).toBe(1); + }); }); -} +});