Skip to content

Commit

Permalink
[Reporting] Prettier up common/lib/screenshots and generate_pdf.js (e…
Browse files Browse the repository at this point in the history
  • Loading branch information
tsullivan committed Jul 18, 2019
1 parent b2cd01e commit b9e1cff
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { LevelLogger } from '../../../server/lib/level_logger';
import { i18n } from '@kbn/i18n';

const fsp = {
readFile: promisify(fs.readFile, fs)
readFile: promisify(fs.readFile, fs),
};

export function screenshotsObservableFactory(server) {
Expand Down Expand Up @@ -43,7 +43,7 @@ export function screenshotsObservableFactory(server) {
const filePath = layout.getCssOverridesPath();
const buffer = await fsp.readFile(filePath);
await browser.evaluate({
fn: function (css) {
fn: (css) => {
const node = document.createElement('style');
node.type = 'text/css';
node.innerHTML = css; // eslint-disable-line no-unsanitized/property
Expand All @@ -57,28 +57,36 @@ export function screenshotsObservableFactory(server) {
// the dashboard is using the `itemsCountAttribute` attribute to let us
// know how many items to expect since gridster incrementally adds panels
// we have to use this hint to wait for all of them
await browser.waitForSelector(`${layout.selectors.renderComplete},[${layout.selectors.itemsCountAttribute}]`);
await browser.waitForSelector(
`${layout.selectors.renderComplete},[${layout.selectors.itemsCountAttribute}]`
);
};

const checkForToastMessage = async (browser, layout) => {
await browser.waitForSelector(layout.selectors.toastHeader, { silent: true });
const toastHeaderText = await browser.evaluate({
fn: function (selector) {
fn: (selector) => {
const nodeList = document.querySelectorAll(selector);
return nodeList.item(0).innerText;
},
args: [layout.selectors.toastHeader],
});
throw new Error(i18n.translate('xpack.reporting.exportTypes.printablePdf.screenshots.unexpectedErrorMessage', {
defaultMessage: 'Encountered an unexpected message on the page: {toastHeaderText}', values: { toastHeaderText }
}));
throw new Error(
i18n.translate(
'xpack.reporting.exportTypes.printablePdf.screenshots.unexpectedErrorMessage',
{
defaultMessage: 'Encountered an unexpected message on the page: {toastHeaderText}',
values: { toastHeaderText },
}
)
);
};

const getNumberOfItems = async (browser, layout) => {
// returns the value of the `itemsCountAttribute` if it's there, otherwise
// we just count the number of `itemSelector`
const itemsCount = await browser.evaluate({
fn: function (selector, countAttribute) {
fn: (selector, countAttribute) => {
const elementWithCount = document.querySelector(`[${countAttribute}]`);
if (elementWithCount) {
return parseInt(elementWithCount.getAttribute(countAttribute));
Expand All @@ -93,11 +101,11 @@ export function screenshotsObservableFactory(server) {

const waitForElementsToBeInDOM = async (browser, itemsCount, layout) => {
await browser.waitFor({
fn: function (selector) {
fn: (selector) => {
return document.querySelectorAll(selector).length;
},
args: [layout.selectors.renderComplete],
toEqual: itemsCount
toEqual: itemsCount,
});
};

Expand All @@ -114,20 +122,20 @@ export function screenshotsObservableFactory(server) {

const waitForRenderComplete = async (browser, layout) => {
await browser.evaluate({
fn: function (selector, visLoadDelay) {
fn: (selector, visLoadDelay) => {
// wait for visualizations to finish loading
const visualizations = document.querySelectorAll(selector);
const visCount = visualizations.length;
const renderedTasks = [];

function waitForRender(visualization) {
return new Promise(function (resolve) {
return new Promise((resolve) => {
visualization.addEventListener('renderComplete', () => resolve());
});
}

function waitForRenderDelay() {
return new Promise(function (resolve) {
return new Promise((resolve) => {
setTimeout(resolve, visLoadDelay);
});
}
Expand All @@ -151,7 +159,6 @@ export function screenshotsObservableFactory(server) {
// bumping to 250.
const hackyWaitForVisualizations = () => new Promise(r => setTimeout(r, 250));


return Promise.all(renderedTasks).then(hackyWaitForVisualizations);
},
args: [layout.selectors.renderComplete, captureConfig.loadDelay],
Expand All @@ -161,7 +168,7 @@ export function screenshotsObservableFactory(server) {

const getTimeRange = async (browser, layout) => {
const timeRange = await browser.evaluate({
fn: function (fromAttribute, toAttribute) {
fn: (fromAttribute, toAttribute) => {
const fromElement = document.querySelector(`[${fromAttribute}]`);
const toElement = document.querySelector(`[${toAttribute}]`);

Expand All @@ -185,7 +192,7 @@ export function screenshotsObservableFactory(server) {

const getElementPositionAndAttributes = async (browser, layout) => {
const elementsPositionAndAttributes = await browser.evaluate({
fn: function (selector, attributes) {
fn: (selector, attributes) => {
const elements = document.querySelectorAll(selector);

// NodeList isn't an array, just an iterator, unable to use .map/.forEach
Expand All @@ -203,18 +210,17 @@ export function screenshotsObservableFactory(server) {
},
scroll: {
x: window.scrollX,
y: window.scrollY
}
y: window.scrollY,
},
},
attributes: Object.keys(attributes).reduce((result, key) => {
const attribute = attributes[key];
result[key] = element.getAttribute(attribute);
return result;
}, {})
}, {}),
});
}
return results;

},
args: [layout.selectors.screenshot, { title: 'data-title', description: 'data-description' }],
returnByValue: true,
Expand All @@ -225,19 +231,21 @@ export function screenshotsObservableFactory(server) {
const getScreenshots = async ({ browser, elementsPositionAndAttributes }) => {
const screenshots = [];
for (const item of elementsPositionAndAttributes) {
const base64EncodedData = await asyncDurationLogger('screenshot', browser.screenshot(item.position));
const base64EncodedData = await asyncDurationLogger(
'screenshot',
browser.screenshot(item.position)
);

screenshots.push({
base64EncodedData,
title: item.attributes.title,
description: item.attributes.description
description: item.attributes.description,
});
}
return screenshots;
};

return function screenshotsObservable(url, conditionalHeaders, layout, browserTimezone) {

return Rx.defer(async () => await getPort()).pipe(
mergeMap(bridgePort => {
logger.debug(`Creating browser driver factory`);
Expand All @@ -251,7 +259,6 @@ export function screenshotsObservableFactory(server) {
}),
tap(() => logger.debug('Driver factory created')),
mergeMap(({ driver$, exit$, message$, consoleMessage$ }) => {

message$.subscribe(line => {
logger.debug(line, ['browser']);
});
Expand All @@ -262,16 +269,16 @@ export function screenshotsObservableFactory(server) {

const screenshot$ = driver$.pipe(
tap(() => logger.debug(`opening ${url}`)),
mergeMap(
browser => openUrl(browser, url, conditionalHeaders),
browser => browser
mergeMap(browser => openUrl(browser, url, conditionalHeaders), browser => browser),
tap(() =>
logger.debug('waiting for elements or items count attribute; or not found to interrupt')
),
tap(() => logger.debug('waiting for elements or items count attribute; or not found to interrupt')),
mergeMap(
browser => Rx.race(
Rx.from(waitForElementOrItemsCountAttribute(browser, layout)),
Rx.from(checkForToastMessage(browser, layout))
),
browser =>
Rx.race(
Rx.from(waitForElementOrItemsCountAttribute(browser, layout)),
Rx.from(checkForToastMessage(browser, layout))
),
browser => browser
),
tap(() => logger.debug('determining how many items we have')),
Expand All @@ -282,7 +289,7 @@ export function screenshotsObservableFactory(server) {
tap(() => logger.debug('setting viewport')),
mergeMap(
({ browser, itemsCount }) => setViewport(browser, itemsCount, layout),
({ browser, itemsCount }) => ({ browser, itemsCount }),
({ browser, itemsCount }) => ({ browser, itemsCount })
),
tap(({ itemsCount }) => logger.debug(`waiting for ${itemsCount} to be in the DOM`)),
mergeMap(
Expand All @@ -297,21 +304,19 @@ export function screenshotsObservableFactory(server) {
({ browser }) => ({ browser })
),
tap(() => logger.debug('positioning elements')),
mergeMap(
({ browser }) => positionElements(browser, layout),
({ browser }) => browser
),
mergeMap(({ browser }) => positionElements(browser, layout), ({ browser }) => browser),
tap(() => logger.debug('waiting for rendering to complete')),
mergeMap(
browser => waitForRenderComplete(browser, layout),
browser => browser
),
mergeMap(browser => waitForRenderComplete(browser, layout), browser => browser),
tap(() => logger.debug('rendering is complete')),
mergeMap(
browser => getTimeRange(browser, layout),
(browser, timeRange) => ({ browser, timeRange })
),
tap(({ timeRange }) => logger.debug(timeRange ? `timeRange from ${timeRange.from} to ${timeRange.to}` : 'no timeRange')),
tap(({ timeRange }) =>
logger.debug(
timeRange ? `timeRange from ${timeRange.from} to ${timeRange.to}` : 'no timeRange'
)
),
mergeMap(
({ browser }) => getElementPositionAndAttributes(browser, layout),
({ browser, timeRange }, elementsPositionAndAttributes) => {
Expand All @@ -320,7 +325,8 @@ export function screenshotsObservableFactory(server) {
),
tap(() => logger.debug(`taking screenshots`)),
mergeMap(
({ browser, elementsPositionAndAttributes }) => getScreenshots({ browser, elementsPositionAndAttributes }),
({ browser, elementsPositionAndAttributes }) =>
getScreenshots({ browser, elementsPositionAndAttributes }),
({ timeRange }, screenshots) => ({ timeRange, screenshots })
)
);
Expand All @@ -331,4 +337,3 @@ export function screenshotsObservableFactory(server) {
);
};
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { oncePerServer } from '../../../../server/lib/once_per_server';
import { screenshotsObservableFactory } from '../../../common/lib/screenshots';
import { createLayout } from '../../../common/layouts';

const getTimeRange = (urlScreenshots) => {
const getTimeRange = urlScreenshots => {
const grouped = groupBy(urlScreenshots.map(u => u.timeRange));
const values = Object.values(grouped);
if (values.length === 1) {
Expand All @@ -27,26 +27,36 @@ const formatDate = (date, timezone) => {
return moment.tz(date, timezone).format('llll');
};


function generatePdfObservableFn(server) {
const screenshotsObservable = screenshotsObservableFactory(server);
const captureConcurrency = 1;

const urlScreenshotsObservable = (urls, conditionalHeaders, layout, browserTimezone) => {
return Rx.from(urls).pipe(
mergeMap(url => screenshotsObservable(url, conditionalHeaders, layout, browserTimezone),
mergeMap(
url => screenshotsObservable(url, conditionalHeaders, layout, browserTimezone),
captureConcurrency
)
);
};


const createPdfWithScreenshots = async ({ title, browserTimezone, urlScreenshots, layout, logo }) => {
const createPdfWithScreenshots = async ({
title,
browserTimezone,
urlScreenshots,
layout,
logo,
}) => {
const pdfOutput = pdf.create(layout, logo);

if (title) {
const timeRange = getTimeRange(urlScreenshots);
title += (timeRange) ? ` — ${formatDate(timeRange.from, browserTimezone)} to ${formatDate(timeRange.to, browserTimezone)}` : '';
title += timeRange
? ` — ${formatDate(timeRange.from, browserTimezone)} to ${formatDate(
timeRange.to,
browserTimezone
)}`
: '';
pdfOutput.setTitle(title);
}

Expand All @@ -64,16 +74,28 @@ function generatePdfObservableFn(server) {
return buffer;
};


return function generatePdfObservable(title, urls, browserTimezone, conditionalHeaders, layoutParams, logo) {

return function generatePdfObservable(
title,
urls,
browserTimezone,
conditionalHeaders,
layoutParams,
logo
) {
const layout = createLayout(server, layoutParams);

const screenshots$ = urlScreenshotsObservable(urls, conditionalHeaders, layout, browserTimezone);
const screenshots$ = urlScreenshotsObservable(
urls,
conditionalHeaders,
layout,
browserTimezone
);

return screenshots$.pipe(
toArray(),
mergeMap(urlScreenshots => createPdfWithScreenshots({ title, browserTimezone, urlScreenshots, layout, logo }))
mergeMap(urlScreenshots =>
createPdfWithScreenshots({ title, browserTimezone, urlScreenshots, layout, logo })
)
);
};
}
Expand Down

0 comments on commit b9e1cff

Please sign in to comment.