mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Screenshotting] fix server crash with non-numeric width or height (#132384)
* throw error early if invalid layout * add layout id test * add new error type * add error type to usage tracking * fix tweak * add comment note * fix telemetry check * fix ts * fix moot change * fix ts * Update x-pack/plugins/screenshotting/server/layouts/create_layout.ts Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com> * fix ts * fix snapshots * fix bundling issue in canvas * convert LayoutTypes to a string literal union * cleanup * remove screenshotting from reporting plugin example required bundles * export as type * fix ts * fix more ts Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com>
This commit is contained in:
parent
fc76e0c8c6
commit
53688bf336
34 changed files with 309 additions and 109 deletions
|
@ -17,6 +17,5 @@
|
|||
"navigation",
|
||||
"screenshotMode",
|
||||
"share"
|
||||
],
|
||||
"requiredBundles": ["screenshotting"]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@ import type {
|
|||
JobParamsPNGV2,
|
||||
} from '@kbn/reporting-plugin/common/types';
|
||||
import type { ReportingStart } from '@kbn/reporting-plugin/public';
|
||||
import { LayoutTypes } from '@kbn/screenshotting-plugin/public';
|
||||
import { REPORTING_EXAMPLE_LOCATOR_ID } from '../../common';
|
||||
import { useApplicationContext } from '../application_context';
|
||||
import { ROUTES } from '../constants';
|
||||
|
@ -85,9 +84,7 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp
|
|||
|
||||
const getPDFJobParamsDefault = (): JobAppParamsPDF => {
|
||||
return {
|
||||
layout: {
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
},
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/app/reportingExample#/intended-visualization'],
|
||||
objectType: 'develeloperExample',
|
||||
title: 'Reporting Developer Example',
|
||||
|
@ -97,9 +94,7 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp
|
|||
const getPDFJobParamsDefaultV2 = (): JobParamsPDFV2 => {
|
||||
return {
|
||||
version: '8.0.0',
|
||||
layout: {
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
},
|
||||
layout: { id: 'preserve_layout' },
|
||||
locatorParams: [
|
||||
{ id: REPORTING_EXAMPLE_LOCATOR_ID, version: '0.5.0', params: { myTestState: {} } },
|
||||
],
|
||||
|
@ -112,9 +107,7 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp
|
|||
const getPNGJobParamsDefaultV2 = (): JobParamsPNGV2 => {
|
||||
return {
|
||||
version: '8.0.0',
|
||||
layout: {
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
},
|
||||
layout: { id: 'preserve_layout' },
|
||||
locatorParams: {
|
||||
id: REPORTING_EXAMPLE_LOCATOR_ID,
|
||||
version: '0.5.0',
|
||||
|
@ -129,9 +122,7 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp
|
|||
const getCaptureTestPNGJobParams = (): JobParamsPNGV2 => {
|
||||
return {
|
||||
version: '8.0.0',
|
||||
layout: {
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
},
|
||||
layout: { id: 'preserve_layout' },
|
||||
locatorParams: {
|
||||
id: REPORTING_EXAMPLE_LOCATOR_ID,
|
||||
version: '0.5.0',
|
||||
|
@ -147,7 +138,7 @@ export const Main = ({ basename, reporting, screenshotMode }: ReportingExampleAp
|
|||
return {
|
||||
version: '8.0.0',
|
||||
layout: {
|
||||
id: print ? LayoutTypes.PRINT : LayoutTypes.PRESERVE_LAYOUT,
|
||||
id: print ? 'print' : 'preserve_layout',
|
||||
dimensions: {
|
||||
// Magic numbers based on height of components not rendered on this screen :(
|
||||
height: 2400,
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { RedirectOptions } from '@kbn/share-plugin/public';
|
||||
import { JobAppParamsPDFV2 } from '@kbn/reporting-plugin/common/types';
|
||||
import type { RedirectOptions } from '@kbn/share-plugin/public';
|
||||
import { CanvasAppLocatorParams, CANVAS_APP_LOCATOR } from '../../../../common/locator';
|
||||
import { CanvasWorkpad } from '../../../../types';
|
||||
|
||||
|
@ -45,10 +45,7 @@ export function getPdfJobParams(
|
|||
}
|
||||
|
||||
return {
|
||||
layout: {
|
||||
dimensions: { width, height },
|
||||
id: 'canvas',
|
||||
},
|
||||
layout: { dimensions: { width, height }, id: 'canvas' },
|
||||
objectType: 'canvas workpad',
|
||||
locatorParams,
|
||||
title,
|
||||
|
|
|
@ -33,6 +33,16 @@ export abstract class ReportingError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* While validating the page layout parameters for a screenshot type report job
|
||||
*/
|
||||
export class InvalidLayoutParametersError extends ReportingError {
|
||||
static code = 'invalid_layout_parameters_error' as const;
|
||||
public get code() {
|
||||
return InvalidLayoutParametersError.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* While performing some reporting action, like fetching data from ES, our
|
||||
* access token expired.
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
BrowserCouldNotLaunchError,
|
||||
BrowserUnexpectedlyClosedError,
|
||||
BrowserScreenshotError,
|
||||
InvalidLayoutParametersError,
|
||||
} from '.';
|
||||
|
||||
describe('mapToReportingError', () => {
|
||||
|
@ -22,6 +23,9 @@ describe('mapToReportingError', () => {
|
|||
});
|
||||
|
||||
test('Screenshotting error', () => {
|
||||
expect(mapToReportingError(new errors.InvalidLayoutParametersError())).toBeInstanceOf(
|
||||
InvalidLayoutParametersError
|
||||
);
|
||||
expect(mapToReportingError(new errors.BrowserClosedUnexpectedly())).toBeInstanceOf(
|
||||
BrowserUnexpectedlyClosedError
|
||||
);
|
||||
|
|
|
@ -14,13 +14,25 @@ import {
|
|||
BrowserScreenshotError,
|
||||
PdfWorkerOutOfMemoryError,
|
||||
VisualReportingSoftDisabledError,
|
||||
InvalidLayoutParametersError,
|
||||
} from '.';
|
||||
|
||||
/**
|
||||
* Map an error object from the Screenshotting plugin into an error type of the Reporting domain.
|
||||
*
|
||||
* NOTE: each type of ReportingError code must be referenced in each applicable `errorCodesSchema*` object in
|
||||
* x-pack/plugins/reporting/server/usage/schema.ts
|
||||
*
|
||||
* @param {unknown} error - a kind of error object
|
||||
* @returns {ReportingError} - the converted error object
|
||||
*/
|
||||
export function mapToReportingError(error: unknown): ReportingError {
|
||||
if (error instanceof ReportingError) {
|
||||
return error;
|
||||
}
|
||||
switch (true) {
|
||||
case error instanceof errors.InvalidLayoutParametersError:
|
||||
return new InvalidLayoutParametersError((error as Error).message);
|
||||
case error instanceof errors.BrowserClosedUnexpectedly:
|
||||
return new BrowserUnexpectedlyClosedError((error as Error).message);
|
||||
case error instanceof errors.FailedToCaptureScreenshot:
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { ReportApiJSON } from '../types';
|
||||
import type { ReportMock } from './types';
|
||||
|
||||
const buildMockReport = (baseObj: ReportMock) => ({
|
||||
const buildMockReport = (baseObj: ReportMock): ReportApiJSON => ({
|
||||
index: '.reporting-2020.04.12',
|
||||
migration_version: '7.15.0',
|
||||
max_attempts: 1,
|
||||
|
|
|
@ -9,7 +9,6 @@ import apm from 'elastic-apm-node';
|
|||
import type { Logger } from '@kbn/core/server';
|
||||
import * as Rx from 'rxjs';
|
||||
import { finalize, map, tap } from 'rxjs/operators';
|
||||
import { LayoutTypes } from '@kbn/screenshotting-plugin/common';
|
||||
import type { ReportingCore } from '../..';
|
||||
import { REPORTING_TRANSACTION_TYPE } from '../../../common/constants';
|
||||
import type { PngMetrics } from '../../../common/types';
|
||||
|
@ -38,10 +37,7 @@ export function generatePngObservable(
|
|||
.getScreenshots({
|
||||
...options,
|
||||
format: 'png',
|
||||
layout: {
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
...options.layout,
|
||||
},
|
||||
layout: { id: 'preserve_layout', ...options.layout },
|
||||
})
|
||||
.pipe(
|
||||
tap(({ metrics }) => {
|
||||
|
|
|
@ -10,8 +10,8 @@ import * as Rx from 'rxjs';
|
|||
import { finalize, map, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { REPORTING_TRANSACTION_TYPE } from '../../../../common/constants';
|
||||
import { TaskRunResult } from '../../../lib/tasks';
|
||||
import { PngScreenshotOptions, RunTaskFn, RunTaskFnFactory } from '../../../types';
|
||||
import { decryptJobHeaders, getFullUrls, generatePngObservable } from '../../common';
|
||||
import { RunTaskFn, RunTaskFnFactory } from '../../../types';
|
||||
import { decryptJobHeaders, generatePngObservable, getFullUrls } from '../../common';
|
||||
import { TaskPayloadPNG } from '../types';
|
||||
|
||||
export const runTaskFnFactory: RunTaskFnFactory<RunTaskFn<TaskPayloadPNG>> =
|
||||
|
@ -39,10 +39,8 @@ export const runTaskFnFactory: RunTaskFnFactory<RunTaskFn<TaskPayloadPNG>> =
|
|||
browserTimezone: job.browserTimezone,
|
||||
layout: {
|
||||
...job.layout,
|
||||
// TODO: We do not do a runtime check for supported layout id types for now. But technically
|
||||
// we should.
|
||||
id: job.layout?.id,
|
||||
} as PngScreenshotOptions['layout'],
|
||||
id: 'preserve_layout',
|
||||
},
|
||||
});
|
||||
}),
|
||||
tap(({ buffer }) => stream.write(buffer)),
|
||||
|
|
|
@ -10,7 +10,7 @@ import * as Rx from 'rxjs';
|
|||
import { finalize, map, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { REPORTING_TRANSACTION_TYPE } from '../../../common/constants';
|
||||
import { TaskRunResult } from '../../lib/tasks';
|
||||
import { PngScreenshotOptions, RunTaskFn, RunTaskFnFactory } from '../../types';
|
||||
import { RunTaskFn, RunTaskFnFactory } from '../../types';
|
||||
import { decryptJobHeaders, generatePngObservable } from '../common';
|
||||
import { getFullRedirectAppUrl } from '../common/v2/get_full_redirect_app_url';
|
||||
import { TaskPayloadPNGV2 } from './types';
|
||||
|
@ -38,12 +38,7 @@ export const runTaskFnFactory: RunTaskFnFactory<RunTaskFn<TaskPayloadPNGV2>> =
|
|||
return generatePngObservable(reporting, jobLogger, {
|
||||
headers,
|
||||
browserTimezone: job.browserTimezone,
|
||||
layout: {
|
||||
...job.layout,
|
||||
// TODO: We do not do a runtime check for supported layout id types for now. But technically
|
||||
// we should.
|
||||
id: job.layout?.id,
|
||||
} as PngScreenshotOptions['layout'],
|
||||
layout: { ...job.layout, id: 'preserve_layout' },
|
||||
urls: [[url, locatorParams]],
|
||||
});
|
||||
}),
|
||||
|
|
|
@ -10,8 +10,8 @@ import * as Rx from 'rxjs';
|
|||
import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { REPORTING_TRANSACTION_TYPE } from '../../../../common/constants';
|
||||
import { TaskRunResult } from '../../../lib/tasks';
|
||||
import { PdfScreenshotOptions, RunTaskFn, RunTaskFnFactory } from '../../../types';
|
||||
import { decryptJobHeaders, getFullUrls, getCustomLogo } from '../../common';
|
||||
import { RunTaskFn, RunTaskFnFactory } from '../../../types';
|
||||
import { decryptJobHeaders, getCustomLogo, getFullUrls } from '../../common';
|
||||
import { generatePdfObservable } from '../lib/generate_pdf';
|
||||
import { TaskPayloadPDF } from '../types';
|
||||
|
||||
|
@ -43,12 +43,7 @@ export const runTaskFnFactory: RunTaskFnFactory<RunTaskFn<TaskPayloadPDF>> =
|
|||
urls,
|
||||
browserTimezone,
|
||||
headers,
|
||||
layout: {
|
||||
...layout,
|
||||
// TODO: We do not do a runtime check for supported layout id types for now. But technically
|
||||
// we should.
|
||||
id: layout?.id,
|
||||
} as PdfScreenshotOptions['layout'],
|
||||
layout,
|
||||
});
|
||||
}),
|
||||
tap(({ buffer }) => {
|
||||
|
|
|
@ -9,7 +9,6 @@ import apm from 'elastic-apm-node';
|
|||
import * as Rx from 'rxjs';
|
||||
import { catchError, map, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { REPORTING_TRANSACTION_TYPE } from '../../../common/constants';
|
||||
import type { PdfScreenshotOptions } from '../../types';
|
||||
import { TaskRunResult } from '../../lib/tasks';
|
||||
import { RunTaskFn, RunTaskFnFactory } from '../../types';
|
||||
import { decryptJobHeaders, getCustomLogo } from '../common';
|
||||
|
@ -41,12 +40,7 @@ export const runTaskFnFactory: RunTaskFnFactory<RunTaskFn<TaskPayloadPDFV2>> =
|
|||
logo,
|
||||
browserTimezone,
|
||||
headers,
|
||||
layout: {
|
||||
...layout,
|
||||
// TODO: We do not do a runtime check for supported layout id types for now. But technically
|
||||
// we should.
|
||||
id: layout?.id,
|
||||
} as PdfScreenshotOptions['layout'],
|
||||
layout,
|
||||
});
|
||||
}),
|
||||
tap(({ buffer }) => {
|
||||
|
|
|
@ -39,6 +39,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -143,6 +146,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -413,6 +419,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -517,6 +526,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -803,6 +815,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -935,6 +950,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -1540,6 +1558,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
@ -1672,6 +1693,9 @@ Object {
|
|||
"browser_unexpectedly_closed_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"invalid_layout_parameters_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
"kibana_shutting_down_error": Object {
|
||||
"type": "long",
|
||||
},
|
||||
|
|
|
@ -332,6 +332,7 @@ test('Incorporate error code stats', () => {
|
|||
browser_unexpectedly_closed_error: 8,
|
||||
browser_screenshot_error: 27,
|
||||
visual_reporting_soft_disabled_error: 1,
|
||||
invalid_layout_parameters_error: 0,
|
||||
},
|
||||
},
|
||||
printable_pdf_v2: {
|
||||
|
@ -351,6 +352,7 @@ test('Incorporate error code stats', () => {
|
|||
browser_unexpectedly_closed_error: 8,
|
||||
browser_screenshot_error: 27,
|
||||
visual_reporting_soft_disabled_error: 1,
|
||||
invalid_layout_parameters_error: 0,
|
||||
},
|
||||
},
|
||||
csv_searchsource_immediate: {
|
||||
|
@ -377,6 +379,7 @@ test('Incorporate error code stats', () => {
|
|||
"browser_could_not_launch_error": 2,
|
||||
"browser_screenshot_error": 27,
|
||||
"browser_unexpectedly_closed_error": 8,
|
||||
"invalid_layout_parameters_error": 0,
|
||||
"kibana_shutting_down_error": 1,
|
||||
"queue_timeout_error": 1,
|
||||
"unknown_error": 0,
|
||||
|
@ -389,6 +392,7 @@ test('Incorporate error code stats', () => {
|
|||
"browser_could_not_launch_error": 2,
|
||||
"browser_screenshot_error": 27,
|
||||
"browser_unexpectedly_closed_error": 8,
|
||||
"invalid_layout_parameters_error": 0,
|
||||
"kibana_shutting_down_error": 1,
|
||||
"pdf_worker_out_of_memory_error": 99,
|
||||
"queue_timeout_error": 1,
|
||||
|
|
|
@ -36,6 +36,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"PNG.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"PNG.error_codes.browser_screenshot_error.type": "long",
|
||||
"PNG.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"PNG.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"PNG.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"PNG.error_codes.queue_timeout_error.type": "long",
|
||||
"PNG.error_codes.unknown_error.type": "long",
|
||||
|
@ -66,6 +67,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"PNGV2.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"PNGV2.error_codes.browser_screenshot_error.type": "long",
|
||||
"PNGV2.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"PNGV2.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"PNGV2.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"PNGV2.error_codes.queue_timeout_error.type": "long",
|
||||
"PNGV2.error_codes.unknown_error.type": "long",
|
||||
|
@ -143,6 +145,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"last7Days.PNG.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"last7Days.PNG.error_codes.browser_screenshot_error.type": "long",
|
||||
"last7Days.PNG.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"last7Days.PNG.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"last7Days.PNG.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"last7Days.PNG.error_codes.queue_timeout_error.type": "long",
|
||||
"last7Days.PNG.error_codes.unknown_error.type": "long",
|
||||
|
@ -173,6 +176,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"last7Days.PNGV2.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.browser_screenshot_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.queue_timeout_error.type": "long",
|
||||
"last7Days.PNGV2.error_codes.unknown_error.type": "long",
|
||||
|
@ -255,6 +259,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"last7Days.printable_pdf.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.browser_screenshot_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.pdf_worker_out_of_memory_error.type": "long",
|
||||
"last7Days.printable_pdf.error_codes.queue_timeout_error.type": "long",
|
||||
|
@ -293,6 +298,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"last7Days.printable_pdf_v2.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.browser_screenshot_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.pdf_worker_out_of_memory_error.type": "long",
|
||||
"last7Days.printable_pdf_v2.error_codes.queue_timeout_error.type": "long",
|
||||
|
@ -463,6 +469,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"printable_pdf.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"printable_pdf.error_codes.browser_screenshot_error.type": "long",
|
||||
"printable_pdf.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"printable_pdf.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"printable_pdf.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"printable_pdf.error_codes.pdf_worker_out_of_memory_error.type": "long",
|
||||
"printable_pdf.error_codes.queue_timeout_error.type": "long",
|
||||
|
@ -501,6 +508,7 @@ describe('Reporting telemetry schema', () => {
|
|||
"printable_pdf_v2.error_codes.browser_could_not_launch_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.browser_screenshot_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.browser_unexpectedly_closed_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.invalid_layout_parameters_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.kibana_shutting_down_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.pdf_worker_out_of_memory_error.type": "long",
|
||||
"printable_pdf_v2.error_codes.queue_timeout_error.type": "long",
|
||||
|
|
|
@ -89,6 +89,7 @@ const errorCodesSchemaPng: MakeSchemaFrom<JobTypes['PNGV2']['error_codes']> = {
|
|||
browser_unexpectedly_closed_error: { type: 'long' },
|
||||
browser_screenshot_error: { type: 'long' },
|
||||
visual_reporting_soft_disabled_error: { type: 'long' },
|
||||
invalid_layout_parameters_error: { type: 'long' },
|
||||
};
|
||||
const errorCodesSchemaPdf: MakeSchemaFrom<JobTypes['printable_pdf_v2']['error_codes']> = {
|
||||
pdf_worker_out_of_memory_error: { type: 'long' },
|
||||
|
@ -100,6 +101,7 @@ const errorCodesSchemaPdf: MakeSchemaFrom<JobTypes['printable_pdf_v2']['error_co
|
|||
browser_unexpectedly_closed_error: { type: 'long' },
|
||||
browser_screenshot_error: { type: 'long' },
|
||||
visual_reporting_soft_disabled_error: { type: 'long' },
|
||||
invalid_layout_parameters_error: { type: 'long' },
|
||||
};
|
||||
|
||||
const availableTotalSchema: MakeSchemaFrom<AvailableTotal> = {
|
||||
|
|
|
@ -198,6 +198,7 @@ export interface ErrorCodeStats {
|
|||
authentication_expired_error: number | null;
|
||||
queue_timeout_error: number | null;
|
||||
unknown_error: number | null;
|
||||
invalid_layout_parameters_error: number | null;
|
||||
pdf_worker_out_of_memory_error: number | null;
|
||||
browser_could_not_launch_error: number | null;
|
||||
browser_unexpectedly_closed_error: number | null;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
|
||||
/* eslint-disable max-classes-per-file */
|
||||
export class InvalidLayoutParametersError extends Error {}
|
||||
|
||||
export class PdfWorkerOutOfMemoryError extends Error {}
|
||||
|
||||
export class FailedToSpawnBrowserError extends Error {}
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export type { LayoutParams } from './layout';
|
||||
export { LayoutTypes } from './layout';
|
||||
import * as errors from './errors';
|
||||
export { errors };
|
||||
export {
|
||||
SCREENSHOTTING_APP_ID,
|
||||
SCREENSHOTTING_EXPRESSION,
|
||||
SCREENSHOTTING_EXPRESSION_INPUT,
|
||||
} from './expression';
|
||||
export type { LayoutParams, LayoutType } from './layout';
|
||||
export { errors };
|
||||
import * as errors from './errors';
|
||||
|
||||
export const PLUGIN_ID = 'screenshotting';
|
||||
|
|
|
@ -40,7 +40,7 @@ export interface LayoutSelectorDictionary {
|
|||
/**
|
||||
* Screenshot layout parameters.
|
||||
*/
|
||||
export type LayoutParams<Id = string> = Ensure<
|
||||
export type LayoutParams<Id = LayoutType> = Ensure<
|
||||
{
|
||||
/**
|
||||
* Unique layout name.
|
||||
|
@ -68,8 +68,4 @@ export type LayoutParams<Id = string> = Ensure<
|
|||
/**
|
||||
* Supported layout types.
|
||||
*/
|
||||
export enum LayoutTypes {
|
||||
PRESERVE_LAYOUT = 'preserve_layout',
|
||||
PRINT = 'print',
|
||||
CANVAS = 'canvas',
|
||||
}
|
||||
export type LayoutType = 'preserve_layout' | 'print' | 'canvas';
|
||||
|
|
|
@ -12,4 +12,3 @@ export function plugin() {
|
|||
}
|
||||
|
||||
export type { LayoutParams } from '../common';
|
||||
export { LayoutTypes } from '../common';
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
// we should get rid of this lib.
|
||||
import * as PDFJS from 'pdfjs-dist/legacy/build/pdf.js';
|
||||
|
||||
import type { Values } from '@kbn/utility-types';
|
||||
import { groupBy } from 'lodash';
|
||||
import type { PackageInfo } from '@kbn/core/server';
|
||||
import type { LayoutParams } from '../../../common';
|
||||
import { LayoutTypes } from '../../../common';
|
||||
import { groupBy } from 'lodash';
|
||||
import type { LayoutParams, LayoutType } from '../../../common';
|
||||
import type { Layout } from '../../layouts';
|
||||
import type { CaptureMetrics, CaptureOptions, CaptureResult } from '../../screenshots';
|
||||
import { EventLogger, Transactions } from '../../screenshots/event_logger';
|
||||
|
@ -25,9 +23,7 @@ import { pngsToPdf } from './pdf_maker';
|
|||
* => When creating a PDF intended for print multiple PNGs will be spread out across pages
|
||||
* => When creating a PDF from a Canvas workpad, each page in the workpad will be placed on a separate page
|
||||
*/
|
||||
export type PdfLayoutParams = LayoutParams<
|
||||
Values<Pick<typeof LayoutTypes, 'PRESERVE_LAYOUT' | 'CANVAS' | 'PRINT'>>
|
||||
>;
|
||||
export type PdfLayoutParams = LayoutParams<LayoutType>;
|
||||
|
||||
/**
|
||||
* Options that should be provided to a PDF screenshot request.
|
||||
|
@ -105,7 +101,7 @@ export async function toPdf(
|
|||
): Promise<PdfScreenshotResult> {
|
||||
let buffer: Buffer;
|
||||
let pages: number;
|
||||
const shouldConvertPngsToPdf = layout.id !== LayoutTypes.PRINT;
|
||||
const shouldConvertPngsToPdf = layout.id !== 'print';
|
||||
if (shouldConvertPngsToPdf) {
|
||||
const timeRange = getTimeRange(results);
|
||||
try {
|
||||
|
|
|
@ -7,12 +7,11 @@
|
|||
|
||||
import type { CaptureResult, CaptureOptions } from '../screenshots';
|
||||
import type { LayoutParams } from '../../common';
|
||||
import { LayoutTypes } from '../../common';
|
||||
|
||||
/**
|
||||
* The layout parameters that are accepted by PNG screenshots
|
||||
*/
|
||||
export type PngLayoutParams = LayoutParams<LayoutTypes.PRESERVE_LAYOUT>;
|
||||
export type PngLayoutParams = LayoutParams<'preserve_layout'>;
|
||||
|
||||
/**
|
||||
* Options that should be provided to a screenshot PNG request
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { CustomPageSize, PredefinedPageSize } from 'pdfmake/interfaces';
|
||||
import type { Size } from '../../common/layout';
|
||||
import type { LayoutType, Size } from '../../common/layout';
|
||||
|
||||
export interface ViewZoomWidthHeight {
|
||||
zoom: number;
|
||||
|
@ -29,14 +29,14 @@ export interface PageSizeParams {
|
|||
}
|
||||
|
||||
export abstract class BaseLayout {
|
||||
public id: string = '';
|
||||
public id: LayoutType;
|
||||
public groupCount: number = 0;
|
||||
|
||||
public hasHeader: boolean = true;
|
||||
public hasFooter: boolean = true;
|
||||
public useReportingBranding: boolean = true;
|
||||
|
||||
constructor(id: string) {
|
||||
constructor(id: LayoutType) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import type { LayoutSelectorDictionary, Size } from '../../common/layout';
|
||||
import { LayoutTypes } from '../../common';
|
||||
import { DEFAULT_SELECTORS } from '.';
|
||||
import type { Layout } from '.';
|
||||
import { BaseLayout } from './base_layout';
|
||||
|
@ -33,7 +32,7 @@ export class CanvasLayout extends BaseLayout implements Layout {
|
|||
public useReportingBranding: boolean = false;
|
||||
|
||||
constructor(size: Size) {
|
||||
super(LayoutTypes.CANVAS);
|
||||
super('canvas');
|
||||
this.height = size.height;
|
||||
this.width = size.width;
|
||||
this.scaledHeight = size.height * ZOOM;
|
||||
|
|
|
@ -5,28 +5,47 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { map as mapRecord } from 'fp-ts/lib/Record';
|
||||
import type { LayoutParams } from '../../common/layout';
|
||||
import { LayoutTypes } from '../../common';
|
||||
import { InvalidLayoutParametersError } from '../../common/errors';
|
||||
import type { LayoutParams, LayoutType } from '../../common/layout';
|
||||
import type { Layout } from '.';
|
||||
import { CanvasLayout } from './canvas_layout';
|
||||
import { PreserveLayout } from './preserve_layout';
|
||||
import { PrintLayout } from './print_layout';
|
||||
|
||||
// utility for validating the layout type from user's job params
|
||||
const LAYOUTS: LayoutType[] = ['canvas', 'print', 'preserve_layout'];
|
||||
|
||||
/**
|
||||
* We naively round all numeric values in the object, this will break screenshotting
|
||||
* if ever a have a non-number set as a value, but this points to an issue
|
||||
* in the code responsible for creating the dimensions object.
|
||||
* Layout dimensions must be sanitized as they are passed in the args that spawn the
|
||||
* Chromium process. Width and height must be int32 value.
|
||||
*
|
||||
*/
|
||||
const roundNumbers = mapRecord(Math.round);
|
||||
const sanitizeLayout = (dimensions: { width: number; height: number }) => {
|
||||
const { width, height } = dimensions;
|
||||
if (isNaN(width) || isNaN(height)) {
|
||||
throw new InvalidLayoutParametersError(`Invalid layout width or height`);
|
||||
}
|
||||
return {
|
||||
width: Math.round(width),
|
||||
height: Math.round(height),
|
||||
};
|
||||
};
|
||||
|
||||
export function createLayout({ id, dimensions, selectors, ...config }: LayoutParams): Layout {
|
||||
if (dimensions && id === LayoutTypes.PRESERVE_LAYOUT) {
|
||||
return new PreserveLayout(roundNumbers(dimensions), selectors);
|
||||
const layoutId = id ?? 'print';
|
||||
|
||||
if (!LAYOUTS.includes(layoutId)) {
|
||||
throw new InvalidLayoutParametersError(`Invalid layout type`);
|
||||
}
|
||||
|
||||
if (dimensions && id === LayoutTypes.CANVAS) {
|
||||
return new CanvasLayout(roundNumbers(dimensions));
|
||||
if (dimensions) {
|
||||
if (layoutId === 'preserve_layout') {
|
||||
return new PreserveLayout(sanitizeLayout(dimensions), selectors);
|
||||
}
|
||||
|
||||
if (layoutId === 'canvas') {
|
||||
return new CanvasLayout(sanitizeLayout(dimensions));
|
||||
}
|
||||
}
|
||||
|
||||
// layoutParams is optional as PrintLayout doesn't use it
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { LayoutTypes } from '../../common';
|
||||
import { createLayout, Layout } from '.';
|
||||
|
||||
export function createMockLayout(): Layout {
|
||||
const layout = createLayout({
|
||||
id: LayoutTypes.PRESERVE_LAYOUT,
|
||||
id: 'preserve_layout',
|
||||
dimensions: { height: 100, width: 100 },
|
||||
zoom: 1,
|
||||
}) as Layout;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import path from 'path';
|
||||
import type { CustomPageSize } from 'pdfmake/interfaces';
|
||||
import type { LayoutSelectorDictionary, Size } from '../../common/layout';
|
||||
import { LayoutTypes } from '../../common';
|
||||
import { DEFAULT_SELECTORS } from '.';
|
||||
import type { Layout } from '.';
|
||||
import { BaseLayout } from './base_layout';
|
||||
|
@ -25,7 +24,7 @@ export class PreserveLayout extends BaseLayout implements Layout {
|
|||
private readonly scaledWidth: number;
|
||||
|
||||
constructor(size: Size, selectors?: Partial<LayoutSelectorDictionary>) {
|
||||
super(LayoutTypes.PRESERVE_LAYOUT);
|
||||
super('preserve_layout');
|
||||
this.height = size.height;
|
||||
this.width = size.width;
|
||||
this.scaledHeight = size.height * ZOOM;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import { PageOrientation, PredefinedPageSize } from 'pdfmake/interfaces';
|
||||
import type { Layout } from '.';
|
||||
import { DEFAULT_SELECTORS } from '.';
|
||||
import { LayoutTypes } from '../../common';
|
||||
import type { LayoutParams, LayoutSelectorDictionary } from '../../common/layout';
|
||||
import { DEFAULT_VIEWPORT } from '../browsers';
|
||||
import { BaseLayout } from './base_layout';
|
||||
|
@ -23,7 +22,7 @@ export class PrintLayout extends BaseLayout implements Layout {
|
|||
private zoom: number;
|
||||
|
||||
constructor({ zoom = 1 }: Pick<LayoutParams, 'zoom'>) {
|
||||
super(LayoutTypes.PRINT);
|
||||
super('print');
|
||||
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { Headers } from '@kbn/core/server';
|
||||
import { defer, forkJoin, Observable, throwError } from 'rxjs';
|
||||
import { catchError, mergeMap, switchMapTo, timeoutWith } from 'rxjs/operators';
|
||||
import { errors, LayoutTypes } from '../../common';
|
||||
import { errors } from '../../common';
|
||||
import {
|
||||
Context,
|
||||
DEFAULT_VIEWPORT,
|
||||
|
@ -242,10 +242,7 @@ export class ScreenshotObservableHandler {
|
|||
}
|
||||
|
||||
private shouldCapturePdf(): boolean {
|
||||
return (
|
||||
this.layout.id === LayoutTypes.PRINT &&
|
||||
(this.options as PdfScreenshotOptions).format === 'pdf'
|
||||
);
|
||||
return this.layout.id === 'print' && (this.options as PdfScreenshotOptions).format === 'pdf';
|
||||
}
|
||||
|
||||
public getScreenshots() {
|
||||
|
|
|
@ -7000,6 +7000,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7118,6 +7121,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7268,6 +7274,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7418,6 +7427,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8275,6 +8287,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8393,6 +8408,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8543,6 +8561,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8693,6 +8714,9 @@
|
|||
},
|
||||
"visual_reporting_soft_disabled_error": {
|
||||
"type": "long"
|
||||
},
|
||||
"invalid_layout_parameters_error": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,5 +28,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./usage'));
|
||||
loadTestFile(require.resolve('./ilm_migration_apis'));
|
||||
loadTestFile(require.resolve('./error_codes'));
|
||||
loadTestFile(require.resolve('./validation'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'dashboard',
|
||||
version: '7.14.0',
|
||||
|
@ -83,7 +83,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'dashboard',
|
||||
version: '7.14.0',
|
||||
|
@ -101,7 +101,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'visualization',
|
||||
version: '7.14.0',
|
||||
|
@ -117,7 +117,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'visualization',
|
||||
version: '7.14.0',
|
||||
|
@ -135,7 +135,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'canvas',
|
||||
version: '7.14.0',
|
||||
|
@ -151,7 +151,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
{
|
||||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve' },
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
objectType: 'canvas',
|
||||
version: '7.14.0',
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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 supertest from 'supertest';
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const reportingAPI = getService('reportingAPI');
|
||||
const retry = getService('retry');
|
||||
const log = getService('log');
|
||||
const supertestSvc = getService('supertest');
|
||||
|
||||
const status = (downloadReportPath: string, response: supertest.Response) => {
|
||||
if (response.status === 503) {
|
||||
log.debug(`Report at path ${downloadReportPath} is pending`);
|
||||
} else if (response.status === 200) {
|
||||
log.debug(`Report at path ${downloadReportPath} is complete`);
|
||||
} else {
|
||||
log.debug(`Report at path ${downloadReportPath} returned code ${response.status}`);
|
||||
}
|
||||
};
|
||||
|
||||
describe('Job parameter validation', () => {
|
||||
before(async () => {
|
||||
await reportingAPI.initEcommerce();
|
||||
});
|
||||
after(async () => {
|
||||
await reportingAPI.teardownEcommerce();
|
||||
await reportingAPI.deleteAllReports();
|
||||
});
|
||||
|
||||
describe('printablePdfV2', () => {
|
||||
it('allows width and height to have decimal', async () => {
|
||||
const downloadReportPath = await reportingAPI.postJobJSON(
|
||||
'/api/reporting/generate/printablePdfV2',
|
||||
{ jobParams: createPdfV2Params(1541.5999755859375) }
|
||||
);
|
||||
|
||||
await retry.tryForTime(18000, async () => {
|
||||
const response: supertest.Response = await supertestSvc
|
||||
.get(downloadReportPath)
|
||||
.responseType('blob')
|
||||
.set('kbn-xsrf', 'xxx');
|
||||
status(downloadReportPath, response);
|
||||
|
||||
expect(response.status).equal(200);
|
||||
});
|
||||
});
|
||||
|
||||
it('fails if width or height are non-numeric', async () => {
|
||||
const downloadReportPath = await reportingAPI.postJobJSON(
|
||||
'/api/reporting/generate/printablePdfV2',
|
||||
{ jobParams: createPdfV2Params('cucucachoo') }
|
||||
);
|
||||
await retry.tryForTime(18000, async () => {
|
||||
const response: supertest.Response = await supertestSvc
|
||||
.get(downloadReportPath)
|
||||
.responseType('blob')
|
||||
.set('kbn-xsrf', 'xxx');
|
||||
|
||||
expect(response.status).equal(500);
|
||||
});
|
||||
});
|
||||
|
||||
it('fails if there is an invalid layout ID', async () => {
|
||||
const downloadReportPath = await reportingAPI.postJobJSON(
|
||||
'/api/reporting/generate/printablePdfV2',
|
||||
{ jobParams: createPdfV2Params(1541, 'landscape') }
|
||||
);
|
||||
await retry.tryForTime(18000, async () => {
|
||||
const response: supertest.Response = await supertestSvc
|
||||
.get(downloadReportPath)
|
||||
.responseType('blob')
|
||||
.set('kbn-xsrf', 'xxx');
|
||||
|
||||
expect(response.status).equal(500);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('pngV2', () => {
|
||||
it('fails if width or height are non-numeric', async () => {
|
||||
const downloadReportPath = await reportingAPI.postJobJSON('/api/reporting/generate/pngV2', {
|
||||
jobParams: createPngV2Params('cucucachoo'),
|
||||
});
|
||||
await retry.tryForTime(18000, async () => {
|
||||
const response: supertest.Response = await supertestSvc
|
||||
.get(downloadReportPath)
|
||||
.responseType('blob')
|
||||
.set('kbn-xsrf', 'xxx');
|
||||
|
||||
expect(response.status).equal(500);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const createPdfV2Params = (testWidth: number | string, layoutId = 'preserve_layout') =>
|
||||
`(browserTimezone:UTC,layout:` +
|
||||
`(dimensions:(height:1492,width:${testWidth}),id:${layoutId}),` +
|
||||
`locatorParams:\u0021((id:DASHBOARD_APP_LOCATOR,params:` +
|
||||
`(dashboardId:\'6c263e00-1c6d-11ea-a100-8589bb9d7c6b\',` +
|
||||
`preserveSavedFilters:\u0021t,` +
|
||||
`timeRange:(from:\'2019-03-23T03:06:17.785Z\',to:\'2019-10-04T02:33:16.708Z\'),` +
|
||||
`useHash:\u0021f,` +
|
||||
`viewMode:view),` +
|
||||
`version:\'8.2.0\')),` +
|
||||
`objectType:dashboard,` +
|
||||
`title:\'Ecom Dashboard\',` +
|
||||
`version:\'8.2.0\')`;
|
||||
|
||||
const createPngV2Params = (testWidth: number | string) =>
|
||||
`(browserTimezone:UTC,layout:` +
|
||||
`(dimensions:(height:648,width:${testWidth}),id:preserve_layout),` +
|
||||
`locatorParams:(id:VISUALIZE_APP_LOCATOR,params:` +
|
||||
`(filters:\u0021(),` +
|
||||
`indexPattern:\'5193f870-d861-11e9-a311-0fa548c5f953\',` +
|
||||
`linked:\u0021t,` +
|
||||
`query:(language:kuery,query:\'\'),` +
|
||||
`savedSearchId:\'6091ead0-1c6d-11ea-a100-8589bb9d7c6b\',` +
|
||||
`timeRange:(from:\'2019-03-23T03:06:17.785Z\',to:\'2019-10-04T02:33:16.708Z\'),` +
|
||||
`uiState:(),` +
|
||||
`vis:(aggs:\u0021((enabled:\u0021t,id:\'1\',params:(emptyAsNull:\u0021f),schema:metric,type:count),` +
|
||||
`(enabled:\u0021t,` +
|
||||
`id:\'2\',` +
|
||||
`params:(field:customer_first_name.keyword,missingBucket:\u0021f,missingBucketLabel:Missing,order:desc,orderBy:\'1\',otherBucket:\u0021f,otherBucketLabel:Other,size:10),` +
|
||||
`schema:segment,type:terms)),` +
|
||||
`params:(maxFontSize:72,minFontSize:18,orientation:single,palette:(name:kibana_palette,type:palette),scale:linear,showLabel:\u0021t),` +
|
||||
`title:\'Tag Cloud of Names\',` +
|
||||
`type:tagcloud),` +
|
||||
`visId:\'1bba55f0-507e-11eb-9c0d-97106882b997\'),` +
|
||||
`version:\'8.2.0\'),` +
|
||||
`objectType:visualization,` +
|
||||
`title:\'Tag Cloud of Names\',` +
|
||||
`version:\'8.2.0\')`;
|
Loading…
Add table
Add a link
Reference in a new issue