Skip to content

Commit

Permalink
[Reporting] Make usable default element posistions
Browse files Browse the repository at this point in the history
  • Loading branch information
tsullivan committed Apr 9, 2020
1 parent b73fe27 commit 1f8e959
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export abstract class Layout {

public abstract getPdfPageSize(pageSizeParams: PageSizeParams): string | Size;

public abstract getViewport(itemsCount: number): ViewZoomWidthHeight;
public abstract getViewport(itemsCount: number): ViewZoomWidthHeight | null;

public abstract getBrowserZoom(): number;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { LevelLogger } from '../../../../server/lib';
import { createMockBrowserDriverFactory, createMockLayoutInstance } from '../../../../test_helpers';
import { ConditionalHeaders, HeadlessChromiumDriver } from '../../../../types';
import { CaptureConfig } from '../../../../server/types';
import * as contexts from './constants';
import { screenshotsObservableFactory } from './observable';
import { ElementsPositionAndAttribute } from './types';

Expand Down Expand Up @@ -57,10 +58,30 @@ describe('Screenshot Observable Pipeline', () => {
expect(result).toMatchInlineSnapshot(`
Array [
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {
"description": "Default ",
"title": "Default Mock Title",
},
"position": Object {
"boundingClientRect": Object {
"height": 600,
"left": 0,
"top": 0,
"width": 800,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": undefined,
"screenshots": Array [
Object {
"base64EncodedData": "allyourBase64 of boundingClientRect,scroll",
"base64EncodedData": "allyourBase64",
"description": "Default ",
"title": "Default Mock Title",
},
Expand Down Expand Up @@ -95,6 +116,26 @@ describe('Screenshot Observable Pipeline', () => {
expect(result).toMatchInlineSnapshot(`
Array [
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {
"description": "Default ",
"title": "Default Mock Title",
},
"position": Object {
"boundingClientRect": Object {
"height": 600,
"left": 0,
"top": 0,
"width": 800,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": undefined,
"screenshots": Array [
Object {
Expand All @@ -106,6 +147,26 @@ describe('Screenshot Observable Pipeline', () => {
"timeRange": "Default GetTimeRange Result",
},
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {
"description": "Default ",
"title": "Default Mock Title",
},
"position": Object {
"boundingClientRect": Object {
"height": 600,
"left": 0,
"top": 0,
"width": 800,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": undefined,
"screenshots": Array [
Object {
Expand Down Expand Up @@ -150,21 +211,55 @@ describe('Screenshot Observable Pipeline', () => {
await expect(getScreenshot()).resolves.toMatchInlineSnapshot(`
Array [
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {},
"position": Object {
"boundingClientRect": Object {
"height": 200,
"left": 0,
"top": 0,
"width": 200,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": [Error: An error occurred when trying to read the page for visualization panel info. You may need to increase 'xpack.reporting.capture.timeouts.waitForElements'. Error: Mock error!],
"screenshots": Array [
Object {
"base64EncodedData": "allyourBase64 of boundingClientRect,scroll",
"base64EncodedData": "allyourBase64",
"description": undefined,
"title": undefined,
},
],
"timeRange": null,
},
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {},
"position": Object {
"boundingClientRect": Object {
"height": 200,
"left": 0,
"top": 0,
"width": 200,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": [Error: An error occurred when trying to read the page for visualization panel info. You may need to increase 'xpack.reporting.capture.timeouts.waitForElements'. Error: Mock error!],
"screenshots": Array [
Object {
"base64EncodedData": "allyourBase64 of boundingClientRect,scroll",
"base64EncodedData": "allyourBase64",
"description": undefined,
"title": undefined,
},
Expand Down Expand Up @@ -208,10 +303,27 @@ describe('Screenshot Observable Pipeline', () => {
await expect(getScreenshot()).resolves.toMatchInlineSnapshot(`
Array [
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {},
"position": Object {
"boundingClientRect": Object {
"height": 200,
"left": 0,
"top": 0,
"width": 200,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": "Instant timeout has fired!",
"screenshots": Array [
Object {
"base64EncodedData": "allyourBase64 of boundingClientRect,scroll",
"base64EncodedData": "allyourBase64",
"description": undefined,
"title": undefined,
},
Expand All @@ -221,5 +333,69 @@ describe('Screenshot Observable Pipeline', () => {
]
`);
});

it(`uses defaults for element positions and size when Kibana page is not ready`, async () => {
// mocks
const mockBrowserEvaluate = jest.fn();
mockBrowserEvaluate.mockImplementation(() => {
const lastCallIndex = mockBrowserEvaluate.mock.calls.length - 1;
const { context: mockCall } = mockBrowserEvaluate.mock.calls[lastCallIndex][1];

if (mockCall === contexts.CONTEXT_ELEMENTATTRIBUTES) {
return Promise.resolve(null);
} else {
return Promise.resolve();
}
});
mockBrowserDriverFactory = await createMockBrowserDriverFactory(logger, {
evaluate: mockBrowserEvaluate,
});
mockLayout.getViewport = () => null;

// test
const getScreenshots$ = screenshotsObservableFactory(mockConfig, mockBrowserDriverFactory);
const getScreenshot = async () => {
return await getScreenshots$({
logger,
urls: ['/welcome/home/start/index.php3?page=./home.php3'],
conditionalHeaders: {} as ConditionalHeaders,
layout: mockLayout,
browserTimezone: 'UTC',
}).toPromise();
};

await expect(getScreenshot()).resolves.toMatchInlineSnapshot(`
Array [
Object {
"elementsPositionAndAttributes": Array [
Object {
"attributes": Object {},
"position": Object {
"boundingClientRect": Object {
"height": 1200,
"left": 0,
"top": 0,
"width": 1800,
},
"scroll": Object {
"x": 0,
"y": 0,
},
},
},
],
"error": undefined,
"screenshots": Array [
Object {
"base64EncodedData": "allyourBase64",
"description": undefined,
"title": undefined,
},
],
"timeRange": undefined,
},
]
`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { ScreenSetupData, ScreenshotObservableOpts, ScreenshotResults } from './
import { waitForRenderComplete } from './wait_for_render';
import { waitForVisualizations } from './wait_for_visualizations';

const DEFAULT_SCREENSHOT_CLIP_HEIGHT = 1200;
const DEFAULT_SCREENSHOT_CLIP_WIDTH = 1800;

export function screenshotsObservableFactory(
captureConfig: CaptureConfig,
browserDriverFactory: HeadlessChromiumDriverFactory
Expand All @@ -42,7 +45,7 @@ export function screenshotsObservableFactory(
mergeMap(() => openUrl(captureConfig, driver, url, conditionalHeaders, logger)),
mergeMap(() => getNumberOfItems(captureConfig, driver, layout, logger)),
mergeMap(async itemsCount => {
const viewport = layout.getViewport(itemsCount);
const viewport = layout.getViewport(itemsCount) || getDefaultViewPort();
await Promise.all([
driver.setViewport(viewport, logger),
waitForVisualizations(captureConfig, driver, itemsCount, layout, logger),
Expand Down Expand Up @@ -83,7 +86,12 @@ export function screenshotsObservableFactory(
: getDefaultElementPosition(layout.getViewport(1));
const screenshots = await getScreenshots(driver, elements, logger);
const { timeRange, error: setupError } = data;
return { timeRange, screenshots, error: setupError };
return {
timeRange,
screenshots,
error: setupError,
elementsPositionAndAttributes: elements,
};
}
)
);
Expand All @@ -97,17 +105,30 @@ export function screenshotsObservableFactory(
};
}

/*
* If Kibana is showing a non-HTML error message, the viewport might not be
* provided by the browser.
*/
const getDefaultViewPort = () => ({
height: DEFAULT_SCREENSHOT_CLIP_HEIGHT,
width: DEFAULT_SCREENSHOT_CLIP_WIDTH,
zoom: 1,
});
/*
* If an error happens setting up the page, we don't know if there actually
* are any visualizations showing. These defaults should help capture the page
* enough for the user to see the error themselves
*/
const getDefaultElementPosition = ({ height, width }: { height: number; width: number }) => [
{
const getDefaultElementPosition = (dimensions: { height?: number; width?: number } | null) => {
const height = dimensions?.height || DEFAULT_SCREENSHOT_CLIP_HEIGHT;
const width = dimensions?.width || DEFAULT_SCREENSHOT_CLIP_WIDTH;

const defaultObject = {
position: {
boundingClientRect: { top: 0, left: 0, height, width },
scroll: { x: 0, y: 0 },
},
attributes: {},
},
];
};
return [defaultObject];
};
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ export interface ScreenshotResults {
timeRange: TimeRange | null;
screenshots: Screenshot[];
error?: Error;
elementsPositionAndAttributes?: ElementsPositionAndAttribute[]; // NOTE: for testing
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,14 @@ export class HeadlessChromiumDriver {
}

public async screenshot(elementPosition: ElementPosition): Promise<string> {
let clip;
if (elementPosition) {
const { boundingClientRect, scroll = { x: 0, y: 0 } } = elementPosition;
clip = {
const { boundingClientRect, scroll } = elementPosition;
const screenshot = await this.page.screenshot({
clip: {
x: boundingClientRect.left + scroll.x,
y: boundingClientRect.top + scroll.y,
height: boundingClientRect.height,
width: boundingClientRect.width,
};
}

const screenshot = await this.page.screenshot({
clip,
},
});

return screenshot.toString('base64');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type ViewportConfig = CaptureConfig['viewport'];
type BrowserConfig = CaptureConfig['browser']['chromium'];

interface LaunchArgs {
userDataDir: BrowserConfig['userDataDir'];
userDataDir: string;
viewport: ViewportConfig;
disableSandbox: BrowserConfig['disableSandbox'];
proxy: BrowserConfig['proxy'];
Expand Down
Loading

0 comments on commit 1f8e959

Please sign in to comment.