[Reporting] Fix screenshot diagnostics (#116199)

* [Reporting] Fix screenshot diagnostics

* update snapshots

* fix test

* tersify test assertions

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Tim Sullivan 2021-10-26 12:29:31 -07:00 committed by GitHub
parent f6dd54a00a
commit 1211149038
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 6 deletions

View file

@ -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<LayoutSelectorDictionary> }
): 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');

View file

@ -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",
}
`);
});

View file

@ -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<LayoutSelectorDictionary>) {
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() {

View file

@ -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: {