mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Typings for chromium driver (#22688)
* Typings for chromium driver * buffer => base64 * remove unused param. consolidate imports
This commit is contained in:
parent
54ab5a7374
commit
c9b1d7ad7f
10 changed files with 142 additions and 96 deletions
|
@ -233,6 +233,7 @@
|
|||
"@types/minimatch": "^2.0.29",
|
||||
"@types/node": "^8.10.20",
|
||||
"@types/prop-types": "^15.5.3",
|
||||
"@types/puppeteer": "^1.6.2",
|
||||
"@types/react": "^16.3.14",
|
||||
"@types/react-dom": "^16.0.5",
|
||||
"@types/react-redux": "^6.0.6",
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { Size } from '../../../../../types';
|
||||
import { ViewZoomWidthHeight } from './types';
|
||||
import { Size, ViewZoomWidthHeight } from '../../../../../types';
|
||||
|
||||
export interface PageSizeParams {
|
||||
pageMarginTop: number;
|
||||
|
|
|
@ -7,6 +7,7 @@ import path from 'path';
|
|||
import { Size } from '../../../../../types';
|
||||
import { Layout, PageSizeParams } 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 {
|
||||
|
|
|
@ -4,19 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import path from 'path';
|
||||
import { KbnServer, Size } from '../../../../../types';
|
||||
import { EvaluateOptions, KbnServer, Size } from '../../../../../types';
|
||||
import { Layout } from './layout';
|
||||
import { CaptureConfig } from './types';
|
||||
|
||||
type EvalArgs = any[];
|
||||
|
||||
interface EvaluateOptions {
|
||||
// 'fn' is a function in string form to avoid tslint from auto formatting it into a version not
|
||||
// underfood by transform_fn safeWrap.
|
||||
fn: ((...evalArgs: EvalArgs) => any);
|
||||
args: EvalArgs; // Arguments to be passed into the function defined by fn.
|
||||
}
|
||||
|
||||
interface BrowserClient {
|
||||
evaluate: (evaluateOptions: EvaluateOptions) => void;
|
||||
}
|
||||
|
|
|
@ -9,9 +9,3 @@ export interface CaptureConfig {
|
|||
zoom: number;
|
||||
viewport: Size;
|
||||
}
|
||||
|
||||
export interface ViewZoomWidthHeight {
|
||||
zoom: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import * as Chrome from 'puppeteer';
|
||||
import {
|
||||
ElementPosition,
|
||||
EvalArgs,
|
||||
EvalFn,
|
||||
EvaluateOptions,
|
||||
Logger,
|
||||
ViewZoomWidthHeight,
|
||||
} from '../../../../types';
|
||||
|
||||
export interface ChromiumDriverOptions {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
const WAIT_FOR_DELAY_MS: number = 100;
|
||||
|
||||
export class HeadlessChromiumDriver {
|
||||
private readonly page: Chrome.Page;
|
||||
private readonly logger: Logger;
|
||||
|
||||
constructor(page: Chrome.Page, { logger }: ChromiumDriverOptions) {
|
||||
this.page = page;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async open(
|
||||
url: string,
|
||||
{ headers, waitForSelector }: { headers: Record<string, string>; waitForSelector: string }
|
||||
) {
|
||||
this.logger.debug(`HeadlessChromiumDriver:opening url ${url}`);
|
||||
|
||||
await this.page.setExtraHTTPHeaders(headers);
|
||||
await this.page.goto(url, { waitUntil: 'networkidle0' });
|
||||
await this.page.waitFor(waitForSelector);
|
||||
}
|
||||
|
||||
public async screenshot(elementPosition: ElementPosition) {
|
||||
let clip;
|
||||
if (elementPosition) {
|
||||
const { boundingClientRect, scroll = { x: 0, y: 0 } } = elementPosition;
|
||||
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');
|
||||
}
|
||||
|
||||
public async evaluate({ fn, args = [] }: EvaluateOptions) {
|
||||
const result = await this.page.evaluate(fn, ...args);
|
||||
return result;
|
||||
}
|
||||
|
||||
public waitForSelector(selector: string) {
|
||||
return this.page.waitFor(selector);
|
||||
}
|
||||
|
||||
public async waitFor<T>({ fn, args, toEqual }: { fn: EvalFn<T>; args: EvalArgs; toEqual: T }) {
|
||||
while (true) {
|
||||
const result = await this.evaluate({ fn, args });
|
||||
if (result === toEqual) {
|
||||
return;
|
||||
}
|
||||
|
||||
await new Promise(r => setTimeout(r, WAIT_FOR_DELAY_MS));
|
||||
}
|
||||
}
|
||||
|
||||
public async setViewport({ width, height, zoom }: ViewZoomWidthHeight) {
|
||||
this.logger.debug(`Setting viewport to width: ${width}, height: ${height}, zoom: ${zoom}`);
|
||||
|
||||
await this.page.setViewport({
|
||||
width: Math.floor(width / zoom),
|
||||
height: Math.floor(height / zoom),
|
||||
deviceScaleFactor: zoom,
|
||||
isMobile: false,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,78 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export class HeadlessChromiumDriver {
|
||||
constructor(page, { maxScreenshotDimension, logger }) {
|
||||
this._page = page;
|
||||
this._maxScreenshotDimension = maxScreenshotDimension;
|
||||
this._waitForDelayMs = 100;
|
||||
this._zoom = 1;
|
||||
this._logger = logger;
|
||||
}
|
||||
|
||||
async open(url, { headers, waitForSelector }) {
|
||||
this._logger.debug(`HeadlessChromiumDriver:opening url ${url}`);
|
||||
|
||||
await this._page.setExtraHTTPHeaders(headers);
|
||||
await this._page.goto(url, { waitUntil: 'networkidle0' });
|
||||
|
||||
this.documentNode = await this._page.evaluateHandle(() => document);
|
||||
await this._page.waitFor(waitForSelector);
|
||||
}
|
||||
|
||||
async screenshot(elementPosition = null) {
|
||||
let clip;
|
||||
if (elementPosition) {
|
||||
const { boundingClientRect, scroll = { x: 0, y: 0 } } = elementPosition;
|
||||
clip = {
|
||||
x: boundingClientRect.left + scroll.x,
|
||||
y: boundingClientRect.top + scroll.y,
|
||||
height: boundingClientRect.height,
|
||||
width: boundingClientRect.width,
|
||||
};
|
||||
}
|
||||
|
||||
const screenshot = await this._page.screenshot({
|
||||
encoding: 'base64',
|
||||
clip,
|
||||
});
|
||||
|
||||
return screenshot;
|
||||
}
|
||||
|
||||
async evaluate({ fn, args = [] }) {
|
||||
const result = await this._page.evaluate(fn, ...args);
|
||||
return result;
|
||||
}
|
||||
|
||||
waitForSelector(selector) {
|
||||
return this._page.waitFor(selector);
|
||||
}
|
||||
|
||||
async waitFor({ fn, args, toEqual }) {
|
||||
while (true) {
|
||||
const result = await this.evaluate({ fn, args });
|
||||
if (result === toEqual) {
|
||||
return;
|
||||
}
|
||||
|
||||
await new Promise(r => setTimeout(r, this._waitForDelayMs));
|
||||
}
|
||||
}
|
||||
|
||||
async setViewport({ width, height, zoom }) {
|
||||
this._logger.debug(`Setting viewport to width: ${width}, height: ${height}, zoom: ${zoom}`);
|
||||
|
||||
await this._page.setViewport({
|
||||
width: Math.floor(width / zoom),
|
||||
height: Math.floor(height / zoom),
|
||||
deviceScaleFactor: zoom,
|
||||
isMobile: false,
|
||||
});
|
||||
|
||||
this._zoom = zoom;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { HeadlessChromiumDriver } from './chromium_driver';
|
32
x-pack/plugins/reporting/types.d.ts
vendored
32
x-pack/plugins/reporting/types.d.ts
vendored
|
@ -21,3 +21,35 @@ export interface Logger {
|
|||
error: (message: string) => void;
|
||||
warning: (message: string) => void;
|
||||
}
|
||||
|
||||
export interface ViewZoomWidthHeight {
|
||||
zoom: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export type EvalArgs = any[];
|
||||
export type EvalFn<T> = ((...evalArgs: EvalArgs) => T);
|
||||
|
||||
export interface EvaluateOptions {
|
||||
fn: EvalFn<any>;
|
||||
args: EvalArgs; // Arguments to be passed into the function defined by fn.
|
||||
}
|
||||
|
||||
export interface ElementPosition {
|
||||
boundingClientRect: {
|
||||
// modern browsers support x/y, but older ones don't
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
scroll: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface HeadlessElementInfo {
|
||||
position: ElementPosition;
|
||||
}
|
||||
|
|
|
@ -488,6 +488,13 @@
|
|||
version "15.5.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.3.tgz#bef071852dca2a2dbb65fecdb7bfb30cedae2de2"
|
||||
|
||||
"@types/puppeteer@^1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-1.6.2.tgz#9b4ba40a67abad3c729a021ffd259d929d00c5e0"
|
||||
dependencies:
|
||||
"@types/events" "*"
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/react-dom@^16.0.5":
|
||||
version "16.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.5.tgz#a757457662e3819409229e8f86795ff37b371f96"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue