[Reporting] convert all server unit tests to TypeScript

This commit is contained in:
Timothy Sullivan 2020-04-07 08:31:58 -07:00
parent 898504dc8f
commit d9ce4024ec
9 changed files with 268 additions and 162 deletions

View file

@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
// @ts-ignore
import Puid from 'puid';
import sinon from 'sinon';
import nodeCrypto from '@elastic/node-crypto';
@ -13,35 +14,39 @@ import { createMockReportingCore } from '../../../test_helpers';
import { LevelLogger } from '../../../server/lib/level_logger';
import { setFieldFormats } from '../../../server/services';
import { executeJobFactory } from './execute_job';
import { JobDocPayloadDiscoverCsv } from '../types';
const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms));
const delay = (ms: number) => new Promise(resolve => setTimeout(() => resolve(), ms));
const puid = new Puid();
const getRandomScrollId = () => {
return puid.generate();
};
const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadDiscoverCsv;
describe('CSV Execute Job', function() {
const encryptionKey = 'testEncryptionKey';
const headers = {
sid: 'test',
};
const mockLogger = new LevelLogger({
get: () => ({
debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
}),
get: () =>
({
debug: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
} as any),
});
let defaultElasticsearchResponse;
let encryptedHeaders;
let defaultElasticsearchResponse: any;
let encryptedHeaders: any;
let clusterStub;
let configGetStub;
let mockReportingConfig;
let mockReportingPlugin;
let callAsCurrentUserStub;
let cancellationToken;
let clusterStub: any;
let configGetStub: any;
let mockReportingConfig: any;
let mockReportingPlugin: any;
let callAsCurrentUserStub: any;
let cancellationToken: any;
const mockElasticsearch = {
dataClient: {
@ -77,7 +82,7 @@ describe('CSV Execute Job', function() {
_scroll_id: 'defaultScrollId',
};
clusterStub = {
callAsCurrentUser: function() {},
callAsCurrentUser() {},
};
callAsCurrentUserStub = sinon
@ -88,17 +93,19 @@ describe('CSV Execute Job', function() {
mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true);
setFieldFormats({
fieldFormatServiceFactory: function() {
fieldFormatServiceFactory() {
const uiConfigMock = {};
uiConfigMock['format:defaultTypeMap'] = {
(uiConfigMock as any)['format:defaultTypeMap'] = {
_default_: { id: 'string', params: {} },
};
const fieldFormatsRegistry = new fieldFormats.FieldFormatsRegistry();
fieldFormatsRegistry.init(key => uiConfigMock[key], {}, [fieldFormats.StringFormat]);
fieldFormatsRegistry.init(key => (uiConfigMock as any)[key], {}, [
fieldFormats.StringFormat,
]);
return fieldFormatsRegistry;
return Promise.resolve(fieldFormatsRegistry);
},
});
});
@ -108,7 +115,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
await executeJob(
'job456',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
expect(callAsCurrentUserStub.called).toBe(true);
@ -122,14 +133,14 @@ describe('CSV Execute Job', function() {
};
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const job = {
const job = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: {
index,
body,
},
};
});
await executeJob('job777', job, cancellationToken);
@ -151,7 +162,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
await executeJob(
'job456',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
@ -165,7 +180,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
await executeJob(
'job456',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
@ -195,7 +214,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
await executeJob(
'job456',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
@ -230,7 +253,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
await executeJob(
'job456',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
@ -256,12 +283,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: undefined,
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(`[TypeError: Cannot read property 'indexOf' of undefined]`);
@ -283,12 +310,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { csv_contains_formulas: csvContainsFormulas } = await executeJob(
'job123',
jobParams,
@ -308,12 +335,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['=SUM(A1:A2)', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { csv_contains_formulas: csvContainsFormulas } = await executeJob(
'job123',
jobParams,
@ -333,12 +360,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { csv_contains_formulas: csvContainsFormulas } = await executeJob(
'job123',
jobParams,
@ -358,12 +385,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { csv_contains_formulas: csvContainsFormulas } = await executeJob(
'job123',
jobParams,
@ -378,11 +405,11 @@ describe('CSV Execute Job', function() {
it('should reject Promise if search call errors out', async function() {
callAsCurrentUserStub.rejects(new Error());
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(`[Error]`);
@ -397,11 +424,11 @@ describe('CSV Execute Job', function() {
});
callAsCurrentUserStub.onSecondCall().rejects(new Error());
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(`[Error]`);
@ -418,11 +445,11 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(
@ -439,11 +466,11 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(
@ -467,11 +494,11 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(
@ -495,11 +522,11 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
};
});
await expect(
executeJob('job123', jobParams, cancellationToken)
).rejects.toMatchInlineSnapshot(
@ -533,7 +560,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
executeJob(
'job345',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
@ -548,13 +579,17 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
executeJob(
'job345',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
cancellationToken.cancel();
for (let i = 0; i < callAsCurrentUserStub.callCount; ++i) {
expect(callAsCurrentUserStub.getCall(i).args[1]).to.not.be('clearScroll');
expect(callAsCurrentUserStub.getCall(i).args[1]).not.toBe('clearScroll'); // dead code?
}
});
@ -562,7 +597,11 @@ describe('CSV Execute Job', function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
executeJob(
'job345',
{ headers: encryptedHeaders, fields: [], searchRequest: { index: null, body: null } },
getJobDocPayload({
headers: encryptedHeaders,
fields: [],
searchRequest: { index: null, body: null },
}),
cancellationToken
);
await delay(100);
@ -578,11 +617,11 @@ describe('CSV Execute Job', function() {
describe('csv content', function() {
it('should write column headers to output, even if there are no results', async function() {
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
expect(content).toBe(`one,two\n`);
});
@ -590,11 +629,11 @@ describe('CSV Execute Job', function() {
it('should use custom uiSettings csv:separator for header', async function() {
mockUiSettingsClient.get.withArgs('csv:separator').returns(';');
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
expect(content).toBe(`one;two\n`);
});
@ -602,11 +641,11 @@ describe('CSV Execute Job', function() {
it('should escape column headers if uiSettings csv:quoteValues is true', async function() {
mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(true);
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one and a half', 'two', 'three-and-four', 'five & six'],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
expect(content).toBe(`"one and a half",two,"three-and-four","five & six"\n`);
});
@ -614,11 +653,11 @@ describe('CSV Execute Job', function() {
it(`shouldn't escape column headers if uiSettings csv:quoteValues is false`, async function() {
mockUiSettingsClient.get.withArgs('csv:quoteValues').returns(false);
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one and a half', 'two', 'three-and-four', 'five & six'],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
expect(content).toBe(`one and a half,two,three-and-four,five & six\n`);
});
@ -632,11 +671,11 @@ describe('CSV Execute Job', function() {
_scroll_id: 'scrollId',
});
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
const lines = content.split('\n');
const headerLine = lines[0];
@ -652,12 +691,12 @@ describe('CSV Execute Job', function() {
_scroll_id: 'scrollId',
});
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
const lines = content.split('\n');
const valuesLine = lines[1];
@ -679,12 +718,12 @@ describe('CSV Execute Job', function() {
_scroll_id: 'scrollId',
});
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
const lines = content.split('\n');
@ -701,7 +740,7 @@ describe('CSV Execute Job', function() {
_scroll_id: 'scrollId',
});
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
@ -715,7 +754,7 @@ describe('CSV Execute Job', function() {
fieldFormatMap: '{"one":{"id":"string","params":{"transform": "upper"}}}',
},
},
};
});
const { content } = await executeJob('job123', jobParams, cancellationToken);
const lines = content.split('\n');
@ -729,18 +768,18 @@ describe('CSV Execute Job', function() {
// tests use these 'simple' characters to make the math easier
describe('when only the headers exceed the maxSizeBytes', function() {
let content;
let maxSizeReached;
let content: string;
let maxSizeReached: boolean;
beforeEach(async function() {
configGetStub.withArgs('csv', 'maxSizeBytes').returns(1);
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
searchRequest: { index: null, body: null },
};
});
({ content, max_size_reached: maxSizeReached } = await executeJob(
'job123',
@ -759,18 +798,18 @@ describe('CSV Execute Job', function() {
});
describe('when headers are equal to maxSizeBytes', function() {
let content;
let maxSizeReached;
let content: string;
let maxSizeReached: boolean;
beforeEach(async function() {
configGetStub.withArgs('csv', 'maxSizeBytes').returns(9);
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
searchRequest: { index: null, body: null },
};
});
({ content, max_size_reached: maxSizeReached } = await executeJob(
'job123',
@ -789,8 +828,8 @@ describe('CSV Execute Job', function() {
});
describe('when the data exceeds the maxSizeBytes', function() {
let content;
let maxSizeReached;
let content: string;
let maxSizeReached: boolean;
beforeEach(async function() {
configGetStub.withArgs('csv', 'maxSizeBytes').returns(9);
@ -803,12 +842,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
({ content, max_size_reached: maxSizeReached } = await executeJob(
'job123',
@ -827,8 +866,8 @@ describe('CSV Execute Job', function() {
});
describe('when headers and data equal the maxSizeBytes', function() {
let content;
let maxSizeReached;
let content: string;
let maxSizeReached: boolean;
beforeEach(async function() {
mockReportingPlugin.getUiSettingsServiceFactory = () => mockUiSettingsClient;
@ -842,12 +881,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
({ content, max_size_reached: maxSizeReached } = await executeJob(
'job123',
@ -879,12 +918,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
await executeJob('job123', jobParams, cancellationToken);
@ -905,12 +944,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
await executeJob('job123', jobParams, cancellationToken);
@ -931,12 +970,12 @@ describe('CSV Execute Job', function() {
});
const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger);
const jobParams = {
const jobParams = getJobDocPayload({
headers: encryptedHeaders,
fields: ['one', 'two'],
conflictedTypesFields: [],
searchRequest: { index: null, body: null },
};
});
await executeJob('job123', jobParams, cancellationToken);

View file

@ -5,19 +5,22 @@
*/
import * as Rx from 'rxjs';
import { createMockReportingCore } from '../../../../test_helpers';
import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers';
import { cryptoFactory } from '../../../../server/lib/crypto';
import { executeJobFactory } from './index';
import { generatePngObservableFactory } from '../lib/generate_png';
import { CancellationToken } from '../../../../common/cancellation_token';
import { LevelLogger } from '../../../../server/lib';
import { ReportingCore, CaptureConfig } from '../../../../server/types';
import { JobDocPayloadPNG } from '../../types';
jest.mock('../lib/generate_png', () => ({ generatePngObservableFactory: jest.fn() }));
let mockReporting;
let mockReporting: ReportingCore;
const cancellationToken = {
const cancellationToken = ({
on: jest.fn(),
};
} as unknown) as CancellationToken;
const mockLoggerFactory = {
get: jest.fn().mockImplementation(() => ({
@ -28,12 +31,16 @@ const mockLoggerFactory = {
};
const getMockLogger = () => new LevelLogger(mockLoggerFactory);
const captureConfig = {} as CaptureConfig;
const mockEncryptionKey = 'abcabcsecuresecret';
const encryptHeaders = async headers => {
const encryptHeaders = async (headers: Record<string, string>) => {
const crypto = cryptoFactory(mockEncryptionKey);
return await crypto.encrypt(headers);
};
const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPNG;
beforeEach(async () => {
const kbnConfig = {
'server.basePath': '/sbp',
@ -45,8 +52,8 @@ beforeEach(async () => {
'kibanaServer.protocol': 'http',
};
const mockReportingConfig = {
get: (...keys) => reportingConfig[keys.join('.')],
kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] },
get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')],
kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] },
};
mockReporting = await createMockReportingCore(mockReportingConfig);
@ -60,22 +67,30 @@ beforeEach(async () => {
mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch));
mockReporting.getElasticsearchService = mockGetElasticsearch;
generatePngObservableFactory.mockReturnValue(jest.fn());
(generatePngObservableFactory as jest.Mock).mockReturnValue(jest.fn());
});
afterEach(() => generatePngObservableFactory.mockReset());
afterEach(() => (generatePngObservableFactory as jest.Mock).mockReset());
test(`passes browserTimezone to generatePng`, async () => {
const encryptedHeaders = await encryptHeaders({});
const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger());
const generatePngObservable = generatePngObservableFactory();
generatePngObservable.mockReturnValue(Rx.of(Buffer.from('')));
const generatePngObservable = generatePngObservableFactory(
captureConfig,
mockBrowserDriverFactory
);
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from('')));
const executeJob = await executeJobFactory(mockReporting, getMockLogger());
const browserTimezone = 'UTC';
await executeJob(
'pngJobId',
{ relativeUrl: '/app/kibana#/something', browserTimezone, headers: encryptedHeaders },
getJobDocPayload({
relativeUrl: '/app/kibana#/something',
browserTimezone,
headers: encryptedHeaders,
}),
cancellationToken
);
@ -92,12 +107,17 @@ test(`returns content_type of application/png`, async () => {
const executeJob = await executeJobFactory(mockReporting, getMockLogger());
const encryptedHeaders = await encryptHeaders({});
const generatePngObservable = generatePngObservableFactory();
generatePngObservable.mockReturnValue(Rx.of(Buffer.from('')));
const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger());
const generatePngObservable = generatePngObservableFactory(
captureConfig,
mockBrowserDriverFactory
);
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from('')));
const { content_type: contentType } = await executeJob(
'pngJobId',
{ relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders },
getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }),
cancellationToken
);
expect(contentType).toBe('image/png');
@ -106,14 +126,19 @@ test(`returns content_type of application/png`, async () => {
test(`returns content of generatePng getBuffer base64 encoded`, async () => {
const testContent = 'test content';
const generatePngObservable = generatePngObservableFactory();
generatePngObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) }));
const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger());
const generatePngObservable = generatePngObservableFactory(
captureConfig,
mockBrowserDriverFactory
);
(generatePngObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) }));
const executeJob = await executeJobFactory(mockReporting, getMockLogger());
const encryptedHeaders = await encryptHeaders({});
const { content } = await executeJob(
'pngJobId',
{ relativeUrl: '/app/kibana#/something', timeRange: {}, headers: encryptedHeaders },
getJobDocPayload({ relativeUrl: '/app/kibana#/something', headers: encryptedHeaders }),
cancellationToken
);

View file

@ -5,19 +5,24 @@
*/
import * as Rx from 'rxjs';
import { createMockReportingCore } from '../../../../test_helpers';
import { createMockReportingCore, createMockBrowserDriverFactory } from '../../../../test_helpers';
import { cryptoFactory } from '../../../../server/lib/crypto';
import { executeJobFactory } from './index';
import { generatePdfObservableFactory } from '../lib/generate_pdf';
import { LevelLogger } from '../../../../server/lib';
import { CancellationToken } from '../../../../types';
import { ReportingCore, CaptureConfig } from '../../../../server/types';
import { generatePdfObservableFactory } from '../lib/generate_pdf';
import { JobDocPayloadPDF } from '../../types';
import { executeJobFactory } from './index';
jest.mock('../lib/generate_pdf', () => ({ generatePdfObservableFactory: jest.fn() }));
let mockReporting;
let mockReporting: ReportingCore;
const cancellationToken = {
const cancellationToken = ({
on: jest.fn(),
};
} as unknown) as CancellationToken;
const captureConfig = {} as CaptureConfig;
const mockLoggerFactory = {
get: jest.fn().mockImplementation(() => ({
@ -29,11 +34,13 @@ const mockLoggerFactory = {
const getMockLogger = () => new LevelLogger(mockLoggerFactory);
const mockEncryptionKey = 'testencryptionkey';
const encryptHeaders = async headers => {
const encryptHeaders = async (headers: Record<string, string>) => {
const crypto = cryptoFactory(mockEncryptionKey);
return await crypto.encrypt(headers);
};
const getJobDocPayload = (baseObj: any) => baseObj as JobDocPayloadPDF;
beforeEach(async () => {
const kbnConfig = {
'server.basePath': '/sbp',
@ -45,8 +52,8 @@ beforeEach(async () => {
'kibanaServer.protocol': 'http',
};
const mockReportingConfig = {
get: (...keys) => reportingConfig[keys.join('.')],
kbnConfig: { get: (...keys) => kbnConfig[keys.join('.')] },
get: (...keys: string[]) => (reportingConfig as any)[keys.join('.')],
kbnConfig: { get: (...keys: string[]) => (kbnConfig as any)[keys.join('.')] },
};
mockReporting = await createMockReportingCore(mockReportingConfig);
@ -60,21 +67,26 @@ beforeEach(async () => {
mockGetElasticsearch.mockImplementation(() => Promise.resolve(mockElasticsearch));
mockReporting.getElasticsearchService = mockGetElasticsearch;
generatePdfObservableFactory.mockReturnValue(jest.fn());
(generatePdfObservableFactory as jest.Mock).mockReturnValue(jest.fn());
});
afterEach(() => generatePdfObservableFactory.mockReset());
afterEach(() => (generatePdfObservableFactory as jest.Mock).mockReset());
test(`returns content_type of application/pdf`, async () => {
const executeJob = await executeJobFactory(mockReporting, getMockLogger());
const logger = getMockLogger();
const executeJob = await executeJobFactory(mockReporting, logger);
const mockBrowserDriverFactory = await createMockBrowserDriverFactory(logger);
const encryptedHeaders = await encryptHeaders({});
const generatePdfObservable = generatePdfObservableFactory();
generatePdfObservable.mockReturnValue(Rx.of(Buffer.from('')));
const generatePdfObservable = generatePdfObservableFactory(
captureConfig,
mockBrowserDriverFactory
);
(generatePdfObservable as jest.Mock).mockReturnValue(Rx.of(Buffer.from('')));
const { content_type: contentType } = await executeJob(
'pdfJobId',
{ relativeUrls: [], timeRange: {}, headers: encryptedHeaders },
getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }),
cancellationToken
);
expect(contentType).toBe('application/pdf');
@ -82,15 +94,19 @@ test(`returns content_type of application/pdf`, async () => {
test(`returns content of generatePdf getBuffer base64 encoded`, async () => {
const testContent = 'test content';
const mockBrowserDriverFactory = await createMockBrowserDriverFactory(getMockLogger());
const generatePdfObservable = generatePdfObservableFactory();
generatePdfObservable.mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) }));
const generatePdfObservable = generatePdfObservableFactory(
captureConfig,
mockBrowserDriverFactory
);
(generatePdfObservable as jest.Mock).mockReturnValue(Rx.of({ buffer: Buffer.from(testContent) }));
const executeJob = await executeJobFactory(mockReporting, getMockLogger());
const encryptedHeaders = await encryptHeaders({});
const { content } = await executeJob(
'pdfJobId',
{ relativeUrls: [], timeRange: {}, headers: encryptedHeaders },
getJobDocPayload({ relativeUrls: [], headers: encryptedHeaders }),
cancellationToken
);

View file

@ -27,7 +27,7 @@ const describeWithContext = describe.each([
describeWithContext('config schema with context %j', context => {
it('produces correct config', async () => {
const schema = await getConfigSchema(reporting);
const value = await schema.validate({}, { context });
const value: any = await schema.validate({}, { context });
value.capture.browser.chromium.disableSandbox = '<platform dependent>';
await expect(value).toMatchSnapshot();
});

View file

@ -6,7 +6,10 @@
import Hapi from 'hapi';
import { createMockReportingCore } from '../../test_helpers';
import { ExportTypeDefinition } from '../../types';
import { ExportTypesRegistry } from '../lib/export_types_registry';
import { LevelLogger } from '../lib/level_logger';
import { ReportingConfig, ReportingCore, ReportingSetupDeps } from '../types';
jest.mock('./lib/authorized_user_pre_routing', () => ({
authorizedUserPreRoutingFactory: () => () => ({}),
@ -19,14 +22,14 @@ jest.mock('./lib/reporting_feature_pre_routing', () => ({
import { registerJobInfoRoutes } from './jobs';
let mockServer;
let exportTypesRegistry;
let mockReportingPlugin;
let mockReportingConfig;
const mockLogger = {
let mockServer: any;
let exportTypesRegistry: ExportTypesRegistry;
let mockReportingPlugin: ReportingCore;
let mockReportingConfig: ReportingConfig;
const mockLogger = ({
error: jest.fn(),
debug: jest.fn(),
};
} as unknown) as LevelLogger;
beforeEach(async () => {
mockServer = new Hapi.Server({ debug: false, port: 8080, routes: { log: { collect: true } } });
@ -35,38 +38,39 @@ beforeEach(async () => {
id: 'unencoded',
jobType: 'unencodedJobType',
jobContentExtension: 'csv',
});
} as ExportTypeDefinition<unknown, unknown, unknown, unknown>);
exportTypesRegistry.register({
id: 'base64Encoded',
jobType: 'base64EncodedJobType',
jobContentEncoding: 'base64',
jobContentExtension: 'pdf',
});
} as ExportTypeDefinition<unknown, unknown, unknown, unknown>);
mockReportingConfig = { get: jest.fn(), kbnConfig: { get: jest.fn() } };
mockReportingPlugin = await createMockReportingCore(mockReportingConfig);
mockReportingPlugin.getExportTypesRegistry = () => exportTypesRegistry;
});
const mockPlugins = {
const mockPlugins = ({
elasticsearch: {
adminClient: { callAsInternalUser: jest.fn() },
},
security: null,
};
} as unknown) as ReportingSetupDeps;
const getHits = (...sources) => {
const getHits = (...sources: any) => {
return {
hits: {
hits: sources.map(source => ({ _source: source })),
hits: sources.map((source: object) => ({ _source: source })),
},
};
};
const getErrorsFromRequest = request =>
request.logs.filter(log => log.tags.includes('error')).map(log => log.error);
const getErrorsFromRequest = (request: any) =>
request.logs.filter((log: any) => log.tags.includes('error')).map((log: any) => log.error);
test(`returns 404 if job not found`, async () => {
// @ts-ignore
mockPlugins.elasticsearch.adminClient = {
callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(getHits())),
};
@ -84,6 +88,7 @@ test(`returns 404 if job not found`, async () => {
});
test(`returns 401 if not valid job type`, async () => {
// @ts-ignore
mockPlugins.elasticsearch.adminClient = {
callAsInternalUser: jest
.fn()
@ -103,6 +108,7 @@ test(`returns 401 if not valid job type`, async () => {
describe(`when job is incomplete`, () => {
const getIncompleteResponse = async () => {
// @ts-ignore
mockPlugins.elasticsearch.adminClient = {
callAsInternalUser: jest
.fn()
@ -149,6 +155,7 @@ describe(`when job is failed`, () => {
status: 'failed',
output: { content: 'job failure message' },
});
// @ts-ignore
mockPlugins.elasticsearch.adminClient = {
callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)),
};
@ -194,6 +201,7 @@ describe(`when job is completed`, () => {
title,
},
});
// @ts-ignore
mockPlugins.elasticsearch.adminClient = {
callAsInternalUser: jest.fn().mockReturnValue(Promise.resolve(hits)),
};

View file

@ -11,18 +11,21 @@ import {
registerReportingUsageCollector,
getReportingUsageCollector,
} from './reporting_usage_collector';
import { ReportingConfig } from '../types';
const exportTypesRegistry = getExportTypesRegistry();
function getMockUsageCollection() {
class MockUsageCollector {
constructor(_server, { fetch }) {
// @ts-ignore fetch is not used
private fetch: any;
constructor(_server: any, { fetch }: any) {
this.fetch = fetch;
}
}
return {
makeUsageCollector: options => {
return new MockUsageCollector(this, options);
makeUsageCollector: (options: any) => {
return new MockUsageCollector(null, options);
},
registerCollector: sinon.stub(),
};
@ -51,7 +54,7 @@ function getPluginsMock(
xpack_main: mockXpackMain,
},
},
};
} as any;
}
const getMockReportingConfig = () => ({
@ -61,13 +64,13 @@ const getMockReportingConfig = () => ({
const getResponseMock = (customization = {}) => customization;
describe('license checks', () => {
let mockConfig;
let mockConfig: ReportingConfig;
beforeAll(async () => {
mockConfig = getMockReportingConfig();
});
describe('with a basic license', () => {
let usageStats;
let usageStats: any;
beforeAll(async () => {
const plugins = getPluginsMock({ license: 'basic' });
const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock()));
@ -75,9 +78,12 @@ describe('license checks', () => {
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
exportTypesRegistry
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
}
);
usageStats = await fetch(callClusterMock, exportTypesRegistry);
usageStats = await fetch(callClusterMock as any);
});
test('sets enables to true', async () => {
@ -94,7 +100,7 @@ describe('license checks', () => {
});
describe('with no license', () => {
let usageStats;
let usageStats: any;
beforeAll(async () => {
const plugins = getPluginsMock({ license: 'none' });
const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock()));
@ -102,9 +108,12 @@ describe('license checks', () => {
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
exportTypesRegistry
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
}
);
usageStats = await fetch(callClusterMock, exportTypesRegistry);
usageStats = await fetch(callClusterMock as any);
});
test('sets enables to true', async () => {
@ -121,7 +130,7 @@ describe('license checks', () => {
});
describe('with platinum license', () => {
let usageStats;
let usageStats: any;
beforeAll(async () => {
const plugins = getPluginsMock({ license: 'platinum' });
const callClusterMock = jest.fn(() => Promise.resolve(getResponseMock()));
@ -129,9 +138,12 @@ describe('license checks', () => {
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
exportTypesRegistry
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
}
);
usageStats = await fetch(callClusterMock, exportTypesRegistry);
usageStats = await fetch(callClusterMock as any);
});
test('sets enables to true', async () => {
@ -148,7 +160,7 @@ describe('license checks', () => {
});
describe('with no usage data', () => {
let usageStats;
let usageStats: any;
beforeAll(async () => {
const plugins = getPluginsMock({ license: 'basic' });
const callClusterMock = jest.fn(() => Promise.resolve({}));
@ -156,9 +168,12 @@ describe('license checks', () => {
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
exportTypesRegistry
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
}
);
usageStats = await fetch(callClusterMock, exportTypesRegistry);
usageStats = await fetch(callClusterMock as any);
});
test('sets enables to true', async () => {
@ -179,7 +194,10 @@ describe('data modeling', () => {
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
exportTypesRegistry
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
}
);
const callClusterMock = jest.fn(() =>
Promise.resolve(
@ -303,7 +321,7 @@ describe('data modeling', () => {
)
);
const usageStats = await fetch(callClusterMock);
const usageStats = await fetch(callClusterMock as any);
expect(usageStats).toMatchInlineSnapshot(`
Object {
"PNG": Object {

View file

@ -92,7 +92,7 @@ const defaultOpts: CreateMockBrowserDriverFactoryOpts = {
export const createMockBrowserDriverFactory = async (
logger: Logger,
opts: Partial<CreateMockBrowserDriverFactoryOpts>
opts: Partial<CreateMockBrowserDriverFactoryOpts> = {}
): Promise<HeadlessChromiumDriverFactory> => {
const captureConfig = {
timeouts: { openUrl: 30000, waitForElements: 30000, renderComplete: 30000 },

View file

@ -186,7 +186,7 @@ export type ESQueueWorkerExecuteFn<JobDocPayloadType> = (
jobId: string,
job: JobDocPayloadType,
cancellationToken?: CancellationToken
) => void;
) => Promise<any>;
/*
* ImmediateExecuteFn receives the job doc payload because the payload was