From 3c081eaad4c62d2f0c33c6ce4d6eddfa0b726745 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 26 Oct 2021 15:03:16 -0700 Subject: [PATCH] [Reporting] Fix screenshot diagnostics (#116199) (#116360) * [Reporting] Fix screenshot diagnostics * update snapshots * fix test * tersify test assertions Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../export_types/common/generate_png.ts | 7 ++- .../lib/layouts/preserve_layout.test.ts | 59 +++++++++++++++++++ .../server/lib/layouts/preserve_layout.ts | 11 +++- .../server/routes/diagnostic/screenshot.ts | 1 + 4 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/reporting/server/lib/layouts/preserve_layout.test.ts diff --git a/x-pack/plugins/reporting/server/export_types/common/generate_png.ts b/x-pack/plugins/reporting/server/export_types/common/generate_png.ts index 85e9513c4a618..5ad39a3f91303 100644 --- a/x-pack/plugins/reporting/server/export_types/common/generate_png.ts +++ b/x-pack/plugins/reporting/server/export_types/common/generate_png.ts @@ -11,7 +11,7 @@ import { finalize, map, tap } from 'rxjs/operators'; import { ReportingCore } from '../../'; import { UrlOrUrlLocatorTuple } from '../../../common/types'; import { LevelLogger } from '../../lib'; -import { LayoutParams, PreserveLayout } from '../../lib/layouts'; +import { LayoutParams, LayoutSelectorDictionary, PreserveLayout } from '../../lib/layouts'; import { getScreenshots$, ScreenshotResults } from '../../lib/screenshots'; import { ConditionalHeaders } from '../common'; @@ -25,14 +25,15 @@ export async function generatePngObservableFactory(reporting: ReportingCore) { urlOrUrlLocatorTuple: UrlOrUrlLocatorTuple, browserTimezone: string | undefined, conditionalHeaders: ConditionalHeaders, - layoutParams: LayoutParams + layoutParams: LayoutParams & { selectors?: Partial } ): Rx.Observable<{ buffer: Buffer; warnings: string[] }> { const apmTrans = apm.startTransaction('reporting generate_png', 'reporting'); const apmLayout = apmTrans?.startSpan('create_layout', 'setup'); if (!layoutParams || !layoutParams.dimensions) { throw new Error(`LayoutParams.Dimensions is undefined.`); } - const layout = new PreserveLayout(layoutParams.dimensions); + const layout = new PreserveLayout(layoutParams.dimensions, layoutParams.selectors); + if (apmLayout) apmLayout.end(); const apmScreenshots = apmTrans?.startSpan('screenshots_pipeline', 'setup'); diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.test.ts b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.test.ts new file mode 100644 index 0000000000000..d78e877e526f5 --- /dev/null +++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.test.ts @@ -0,0 +1,59 @@ +/* + * 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. + */ + +import { PreserveLayout } from './preserve_layout'; + +it('preserve layout uses default layout selectors', () => { + const testPreserveLayout = new PreserveLayout({ width: 16, height: 16 }); + + expect(testPreserveLayout.getCssOverridesPath()).toMatch(`layouts/preserve_layout.css`); + expect(testPreserveLayout.getBrowserViewport()).toMatchObject({ height: 32, width: 32 }); + expect(testPreserveLayout.getBrowserZoom()).toBe(2); + expect(testPreserveLayout.getPdfImageSize()).toMatchObject({ height: 16, width: 16 }); + expect(testPreserveLayout.getPdfPageOrientation()).toBe(undefined); + expect( + testPreserveLayout.getPdfPageSize({ + pageMarginTop: 27, + pageMarginBottom: 27, + pageMarginWidth: 13, + tableBorderWidth: 67, + headingHeight: 82, + subheadingHeight: 96, + }) + ).toMatchObject({ height: 382, width: 176 }); + expect(testPreserveLayout.selectors).toMatchInlineSnapshot(` + Object { + "itemsCountAttribute": "data-shared-items-count", + "renderComplete": "[data-shared-item]", + "renderError": "[data-render-error]", + "renderErrorAttribute": "data-render-error", + "screenshot": "[data-shared-items-container]", + "timefilterDurationAttribute": "data-shared-timefilter-duration", + } + `); + expect(testPreserveLayout.groupCount).toBe(1); + expect(testPreserveLayout.height).toBe(16); + expect(testPreserveLayout.width).toBe(16); +}); + +it('preserve layout allows customizable selectors', () => { + const testPreserveLayout = new PreserveLayout( + { width: 16, height: 16 }, + { renderComplete: '[great-test-selectors]' } + ); + + expect(testPreserveLayout.selectors).toMatchInlineSnapshot(` + Object { + "itemsCountAttribute": "data-shared-items-count", + "renderComplete": "[great-test-selectors]", + "renderError": "[data-render-error]", + "renderErrorAttribute": "data-render-error", + "screenshot": "[data-shared-items-container]", + "timefilterDurationAttribute": "data-shared-timefilter-duration", + } + `); +}); diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts index 9833f340d47f3..424e85327c22b 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts @@ -9,26 +9,31 @@ import path from 'path'; import { CustomPageSize } from 'pdfmake/interfaces'; import { LAYOUT_TYPES } from '../../../common/constants'; import { PageSizeParams, Size } from '../../../common/types'; -import { getDefaultLayoutSelectors, LayoutInstance } from './'; +import { getDefaultLayoutSelectors, LayoutInstance, LayoutSelectorDictionary } from './'; import { Layout } from './layout'; // We use a zoom of two to bump up the resolution of the screenshot a bit. const ZOOM: number = 2; export class PreserveLayout extends Layout implements LayoutInstance { - public readonly selectors = getDefaultLayoutSelectors(); + public readonly selectors: LayoutSelectorDictionary; public readonly groupCount = 1; public readonly height: number; public readonly width: number; private readonly scaledHeight: number; private readonly scaledWidth: number; - constructor(size: Size) { + constructor(size: Size, selectors?: Partial) { super(LAYOUT_TYPES.PRESERVE_LAYOUT); this.height = size.height; this.width = size.width; this.scaledHeight = size.height * ZOOM; this.scaledWidth = size.width * ZOOM; + + this.selectors = { + ...getDefaultLayoutSelectors(), + ...selectors, + }; } public getCssOverridesPath() { diff --git a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts index 3a89c869542b4..f2002dd945882 100644 --- a/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts +++ b/x-pack/plugins/reporting/server/routes/diagnostic/screenshot.ts @@ -67,6 +67,7 @@ export const registerDiagnoseScreenshot = (reporting: ReportingCore, logger: Log .pipe() .toPromise() .then((screenshot) => { + // NOTE: the screenshot could be returned as a string using `data:image/png;base64,` + results.buffer.toString('base64') if (screenshot.warnings.length) { return res.ok({ body: {