Skip to content

Commit

Permalink
Combine common pdf png functions (#25152)
Browse files Browse the repository at this point in the history
* Create common routines for PDF and PNG report processing

* REmove Blacklisted headers not needed

* Changes for issues with PDF and PNG testing

As per Joel Griffith suggestion I added removal of toast notifications after each click download report.  And removed setting of image density to 300.

* removed uneccesary image compare routine

* Moved server from property on job to passed in parameter.

* consolidated PDF and PNG testing

Moved test code from PDF and PNG index.test.js into a common index.test.js that now tests the common functions.

* Typescripted the common functions and broke out tests to individual test files

* Create a common create mock server function that all new tests call

* Removed unnecessary exception check and removed test include from index.ts
  • Loading branch information
bgaddis56 authored and stacey-gammon committed Nov 14, 2018
1 parent aca3fe3 commit dc2953a
Show file tree
Hide file tree
Showing 25 changed files with 711 additions and 800 deletions.
12 changes: 12 additions & 0 deletions x-pack/plugins/reporting/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ export const WHITELISTED_JOB_CONTENT_TYPES = [
'image/png',
];

export const KBN_SCREENSHOT_HEADER_BLACKLIST = [
'accept-encoding',
'content-length',
'content-type',
'host',
'referer',
// `Transfer-Encoding` is hop-by-hop header that is meaningful
// only for a single transport-level connection, and shouldn't
// be stored by caches or forwarded by proxies.
'transfer-encoding',
];

export const UI_SETTINGS_CUSTOM_PDF_LOGO = 'xpackReporting:customPdfLogo';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* 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 { createMockServer } from '../../../test_helpers/create_mock_server';
import { addForceNowQuerystring } from './index';

let mockServer: any;
beforeEach(() => {
mockServer = createMockServer('');
});

test(`fails if no URL is passed`, async () => {
await expect(
addForceNowQuerystring({
job: {},
server: mockServer,
})
).rejects.toBeDefined();
});

test(`adds forceNow to hash's query, if it exists`, async () => {
const forceNow = '2000-01-01T00:00:00.000Z';
const { urls } = await addForceNowQuerystring({
job: { relativeUrl: '/app/kibana#/something', forceNow },
server: mockServer,
});

expect(urls[0]).toEqual(
'http://localhost:5601/sbp/app/kibana#/something?forceNow=2000-01-01T00%3A00%3A00.000Z'
);
});

test(`appends forceNow to hash's query, if it exists`, async () => {
const forceNow = '2000-01-01T00:00:00.000Z';

const { urls } = await addForceNowQuerystring({
job: {
relativeUrl: '/app/kibana#/something?_g=something',
forceNow,
},
server: mockServer,
});

expect(urls[0]).toEqual(
'http://localhost:5601/sbp/app/kibana#/something?_g=something&forceNow=2000-01-01T00%3A00%3A00.000Z'
);
});

test(`doesn't append forceNow query to url, if it doesn't exists`, async () => {
const { urls } = await addForceNowQuerystring({
job: {
relativeUrl: '/app/kibana#/something',
},
server: mockServer,
});

expect(urls[0]).toEqual('http://localhost:5601/sbp/app/kibana#/something');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.
*/
// @ts-ignore
import url from 'url';
import { ConditionalHeaders, KbnServer, ReportingJob } from '../../../types';
import { getAbsoluteUrlFactory } from './get_absolute_url';

function getSavedObjectAbsoluteUrl(job: ReportingJob, relativeUrl: string, server: KbnServer) {
const getAbsoluteUrl: any = getAbsoluteUrlFactory(server);

const { pathname: path, hash, search } = url.parse(relativeUrl);
return getAbsoluteUrl({ basePath: job.basePath, path, hash, search });
}

export const addForceNowQuerystring = async ({
job,
conditionalHeaders,
logo,
server,
}: {
job: ReportingJob;
conditionalHeaders?: ConditionalHeaders;
logo?: any;
server: KbnServer;
}) => {
// if no URLS then its from PNG which should only have one so put it in the array and process as PDF does
if (!job.urls) {
if (!job.relativeUrl) {
throw new Error(`Unable to generate report. Url is not defined.`);
}
job.urls = [getSavedObjectAbsoluteUrl(job, job.relativeUrl, server)];
}

const urls = job.urls.map(jobUrl => {
if (!job.forceNow) {
return jobUrl;
}

const parsed: any = url.parse(jobUrl, true);
const hash: any = url.parse(parsed.hash.replace(/^#/, ''), true);

const transformedHash = url.format({
pathname: hash.pathname,
query: {
...hash.query,
forceNow: job.forceNow,
},
});

return url.format({
...parsed,
hash: transformedHash,
});
});

return { job, conditionalHeaders, logo, urls, server };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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.
*/

// @ts-ignore
import { cryptoFactory } from '../../../server/lib/crypto';
import { createMockServer } from '../../../test_helpers/create_mock_server';
import { decryptJobHeaders } from './index';

let mockServer: any;
beforeEach(() => {
mockServer = createMockServer('');
});

const encryptHeaders = async (headers: Record<string, string>) => {
const crypto = cryptoFactory(mockServer);
return await crypto.encrypt(headers);
};

describe('headers', () => {
test(`fails if it can't decrypt headers`, async () => {
await expect(
decryptJobHeaders({
job: { relativeUrl: '/app/kibana#/something', timeRange: {} },
server: mockServer,
})
).rejects.toBeDefined();
});

test(`passes back decrypted headers that were passed in`, async () => {
const headers = {
foo: 'bar',
baz: 'quix',
};

const encryptedHeaders = await encryptHeaders(headers);
const { decryptedHeaders } = await decryptJobHeaders({
job: { relativeUrl: '/app/kibana#/something', headers: encryptedHeaders },
server: mockServer,
});
expect(decryptedHeaders).toEqual(headers);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.
*/
// @ts-ignore
import { cryptoFactory } from '../../../server/lib/crypto';
import { CryptoFactory, KbnServer, ReportingJob } from '../../../types';

export const decryptJobHeaders = async ({
job,
server,
}: {
job: ReportingJob;
server: KbnServer;
}) => {
const crypto: CryptoFactory = cryptoFactory(server);
const decryptedHeaders: string = await crypto.decrypt(job.headers);
return { job, decryptedHeaders, server };
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,118 +4,89 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { memoize } from 'lodash';
import { createMockServer } from '../../../test_helpers/create_mock_server';
import { getAbsoluteUrlFactory } from './get_absolute_url';

const createMockServer = ({ settings = {} } = {}) => {
const mockServer = {
expose: () => {},
config: memoize(() => {
return {
get: jest.fn()
};
}),
info: {
protocol: 'http'
}
};

const defaultSettings = {
'server.host': 'something',
'server.port': 8080,
'server.basePath': '/tst',
'xpack.reporting.kibanaServer': {}
};
mockServer.config().get.mockImplementation(key => {
return key in settings ? settings[key] : defaultSettings[key];
});

return mockServer;
};

test(`by default it builds url using information from server.info.protocol and the server.config`, () => {
const mockServer = createMockServer();

const mockServer = createMockServer('');
const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const absoluteUrl = getAbsoluteUrl();
expect(absoluteUrl).toBe(`http://something:8080/tst/app/kibana`);
expect(absoluteUrl).toBe(`http://localhost:5601/sbp/app/kibana`);
});

test(`uses kibanaServer.protocol if specified`, () => {
const settings = {
'xpack.reporting.kibanaServer.protocol': 'https'
'xpack.reporting.kibanaServer.protocol': 'https',
};
const mockServer = createMockServer({ settings });

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const absoluteUrl = getAbsoluteUrl();
expect(absoluteUrl).toBe(`https://something:8080/tst/app/kibana`);
expect(absoluteUrl).toBe(`https://localhost:5601/sbp/app/kibana`);
});

test(`uses kibanaServer.hostname if specified`, () => {
const settings = {
'xpack.reporting.kibanaServer.hostname': 'something-else'
'xpack.reporting.kibanaServer.hostname': 'something-else',
};
const mockServer = createMockServer({ settings });

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const absoluteUrl = getAbsoluteUrl();
expect(absoluteUrl).toBe(`http://something-else:8080/tst/app/kibana`);
expect(absoluteUrl).toBe(`http://something-else:5601/sbp/app/kibana`);
});

test(`uses kibanaServer.port if specified`, () => {
const settings = {
'xpack.reporting.kibanaServer.port': 8008
'xpack.reporting.kibanaServer.port': 8008,
};
const mockServer = createMockServer({ settings });

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const absoluteUrl = getAbsoluteUrl();
expect(absoluteUrl).toBe(`http://something:8008/tst/app/kibana`);
expect(absoluteUrl).toBe(`http://localhost:8008/sbp/app/kibana`);
});

test(`uses the provided hash`, () => {
const mockServer = createMockServer();
const mockServer = createMockServer('');

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const hash = '/hash';
const absoluteUrl = getAbsoluteUrl({ hash });
expect(absoluteUrl).toBe(`http://something:8080/tst/app/kibana#${hash}`);
expect(absoluteUrl).toBe(`http://localhost:5601/sbp/app/kibana#${hash}`);
});

test(`uses the provided hash with queryString`, () => {
const mockServer = createMockServer();
const mockServer = createMockServer('');

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const hash = '/hash?querystring';
const absoluteUrl = getAbsoluteUrl({ hash });
expect(absoluteUrl).toBe(`http://something:8080/tst/app/kibana#${hash}`);
expect(absoluteUrl).toBe(`http://localhost:5601/sbp/app/kibana#${hash}`);
});

test(`uses the provided basePath`, () => {
const mockServer = createMockServer();
const mockServer = createMockServer('');

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const absoluteUrl = getAbsoluteUrl({ basePath: '/s/marketing' });
expect(absoluteUrl).toBe(`http://something:8080/s/marketing/app/kibana`);
expect(absoluteUrl).toBe(`http://localhost:5601/s/marketing/app/kibana`);
});

test(`uses the path`, () => {
const mockServer = createMockServer();
const mockServer = createMockServer('');

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const path = '/app/canvas';
const absoluteUrl = getAbsoluteUrl({ path });
expect(absoluteUrl).toBe(`http://something:8080/tst${path}`);
expect(absoluteUrl).toBe(`http://localhost:5601/sbp${path}`);
});

test(`uses the search`, () => {
const mockServer = createMockServer();
const mockServer = createMockServer('');

const getAbsoluteUrl = getAbsoluteUrlFactory(mockServer);
const search = '_t=123456789';
const absoluteUrl = getAbsoluteUrl({ search });
expect(absoluteUrl).toBe(`http://something:8080/tst/app/kibana?${search}`);
expect(absoluteUrl).toBe(`http://localhost:5601/sbp/app/kibana?${search}`);
});


Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@
*/

import url from 'url';
// @ts-ignore
import { oncePerServer } from '../../../server/lib/once_per_server';
import { ConfigObject, KbnServer } from '../../../types';

function getAbsoluteUrlFn(server) {
const config = server.config();
function getAbsoluteUrlFn(server: KbnServer) {
const config: ConfigObject = server.config();

return function getAbsoluteUrl({
basePath = config.get('server.basePath'),
hash,
hash = '',
path = '/app/kibana',
search
search = '',
} = {}) {
return url.format({
protocol: config.get('xpack.reporting.kibanaServer.protocol') || server.info.protocol,
hostname: config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'),
port: config.get('xpack.reporting.kibanaServer.port') || config.get('server.port'),
pathname: basePath + path,
hash: hash,
search
hash,
search,
});
};
}
Expand Down
Loading

0 comments on commit dc2953a

Please sign in to comment.