mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Reporting] Clean ups for deprecated export types (#188270)
Epic link: https://github.com/elastic/kibana-team/issues/720 ## Summary This PR solves a problem in Reporting code, in that most functional tests and API integration tests that cover PDF functionality were referencing the deprecated `printable_pdf` export type. As of this PR, the tests now use the `printable_pdf_v2` export type. List of clean up changes: * Fully remove PNGV1 (leftovers from #162517) * Update tests and documentation to use PDFV2 * Allow users to see removed types in the listing and download reports for removed types. This makes it possible to see `csv` and `png` job types in the current version, even though it's not possible to create new jobs of those types. Context: the reporting plugin has two deprecated export types which are still active in the code: * `printable_pdf` - this is actively replaced with `printable_pdf_v2' * `csv_searchsource` - this is replaced with `csv_v2' for certain applications such as ES|QL export. For general CSV export, `csv_v2' is currently only offered as an API`. ### Checklist Delete any items that are not applicable to this PR. - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b886fe850c
commit
88626a77ac
36 changed files with 234 additions and 356 deletions
|
@ -19,7 +19,7 @@ PUT _watcher/watch/error_report
|
|||
"attachments" : {
|
||||
"error_report.pdf" : {
|
||||
"reporting" : {
|
||||
"url": "http://0.0.0.0:5601/api/reporting/generate/printablePdf?jobParams=...", <2>
|
||||
"url": "http://0.0.0.0:5601/api/reporting/generate/printablePdfV2?jobParams=...", <2>
|
||||
"retries":40, <3>
|
||||
"interval":"15s", <4>
|
||||
"auth":{ <5>
|
||||
|
|
|
@ -60,9 +60,6 @@ export interface ReportOutput extends TaskRunResult {
|
|||
*/
|
||||
export type CsvPagingStrategy = 'pit' | 'scroll';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export interface BaseParams {
|
||||
browserTimezone: string; // to format dates in the user's time zone
|
||||
objectType: string;
|
||||
|
@ -80,9 +77,6 @@ export type BaseParamsV2 = BaseParams & {
|
|||
locatorParams: LocatorParams[];
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export interface BasePayload extends BaseParams {
|
||||
headers: string;
|
||||
spaceId?: string;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
"@kbn/reporting-common",
|
||||
"@kbn/screenshotting-plugin",
|
||||
"@kbn/reporting-server",
|
||||
"@kbn/licensing-plugin",
|
||||
"@kbn/reporting-export-types-pdf-common",
|
||||
"@kbn/reporting-mocks-server",
|
||||
"@kbn/licensing-plugin",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ export class PngExportType extends ExportType<JobParamsPNGV2, TaskPayloadPNGV2>
|
|||
* @returns jobParams
|
||||
*/
|
||||
public createJob = async ({ locatorParams, ...jobParams }: JobParamsPNGV2) => {
|
||||
// FIXME: validate that locatorParams exists, and contains an ID field and params object
|
||||
return {
|
||||
...jobParams,
|
||||
locatorParams: [locatorParams],
|
||||
|
|
|
@ -6,8 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const PNG_REPORT_TYPE = 'PNG';
|
||||
export const PNG_REPORT_TYPE_V2 = 'pngV2';
|
||||
|
||||
export const PNG_JOB_TYPE = 'PNG';
|
||||
export const PNG_JOB_TYPE_V2 = 'PNGV2';
|
||||
|
|
|
@ -22,17 +22,10 @@ import type {
|
|||
TaskRunResult,
|
||||
} from '@kbn/reporting-common/types';
|
||||
import { CSV_JOB_TYPE, CSV_JOB_TYPE_V2 } from '@kbn/reporting-export-types-csv-common';
|
||||
import { PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_JOB_TYPE, PNG_JOB_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
import { PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_JOB_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
|
||||
const jobTypes = [
|
||||
CSV_JOB_TYPE,
|
||||
CSV_JOB_TYPE_V2,
|
||||
PDF_JOB_TYPE,
|
||||
PDF_JOB_TYPE_V2,
|
||||
PNG_JOB_TYPE,
|
||||
PNG_JOB_TYPE_V2,
|
||||
];
|
||||
const jobTypes = [CSV_JOB_TYPE, CSV_JOB_TYPE_V2, PDF_JOB_TYPE_V2, PNG_JOB_TYPE_V2];
|
||||
|
||||
type JobTypeDeclaration = typeof jobTypes;
|
||||
type JobTypes = JobTypeDeclaration[keyof JobTypeDeclaration];
|
||||
|
|
|
@ -10,8 +10,8 @@ import React, { Component, ReactElement } from 'react';
|
|||
import * as Rx from 'rxjs';
|
||||
|
||||
import { CSV_REPORT_TYPE, CSV_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-csv-common';
|
||||
import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_REPORT_TYPE, PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
import { PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
|
||||
import {
|
||||
EuiAccordion,
|
||||
|
@ -248,15 +248,16 @@ class ReportingPanelContentUi extends Component<Props, State> {
|
|||
|
||||
private prettyPrintReportingType = () => {
|
||||
switch (this.props.reportType) {
|
||||
case PDF_REPORT_TYPE:
|
||||
case 'pdf':
|
||||
case PDF_REPORT_TYPE_V2:
|
||||
return 'PDF';
|
||||
case 'csv':
|
||||
case CSV_REPORT_TYPE:
|
||||
case CSV_REPORT_TYPE_V2:
|
||||
return 'CSV';
|
||||
case 'png':
|
||||
case PNG_REPORT_TYPE_V2:
|
||||
return PNG_REPORT_TYPE;
|
||||
return 'PNG';
|
||||
default:
|
||||
return this.props.reportType;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import React from 'react';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_REPORT_TYPE, PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
import { PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
|
||||
import { StartServices } from '..';
|
||||
import { ReportingAPIClient } from '../..';
|
||||
|
@ -47,8 +47,6 @@ export interface ReportingPublicComponents {
|
|||
/** Needed for Canvas PDF reports */
|
||||
ReportingPanelPDFV2(props: ApplicationProps): JSX.Element | null;
|
||||
ReportingPanelPNGV2(props: ApplicationProps): JSX.Element | undefined;
|
||||
ReportingModalPDF(props: ApplicationProps): JSX.Element | undefined;
|
||||
ReportingModalPNG(props: ApplicationProps): JSX.Element | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,33 +89,5 @@ export function getSharedComponents(
|
|||
);
|
||||
}
|
||||
},
|
||||
ReportingModalPDF(props: ApplicationProps) {
|
||||
if (props.layoutOption === 'canvas') {
|
||||
return (
|
||||
<ScreenCapturePanelContent
|
||||
requiresSavedState={false}
|
||||
reportType={PDF_REPORT_TYPE}
|
||||
apiClient={apiClient}
|
||||
layoutOption={'canvas' as const}
|
||||
startServices$={startServices$}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
ReportingModalPNG(props: ApplicationProps) {
|
||||
if (props.layoutOption === 'canvas') {
|
||||
return (
|
||||
<ScreenCapturePanelContent
|
||||
requiresSavedState={false}
|
||||
reportType={PNG_REPORT_TYPE}
|
||||
apiClient={apiClient}
|
||||
layoutOption={'canvas' as const}
|
||||
startServices$={startServices$}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,48 +7,23 @@
|
|||
|
||||
import {
|
||||
CSV_JOB_TYPE,
|
||||
CSV_JOB_TYPE_DEPRECATED,
|
||||
CSV_JOB_TYPE_V2,
|
||||
CSV_REPORT_TYPE,
|
||||
CSV_REPORT_TYPE_V2,
|
||||
} from '@kbn/reporting-export-types-csv-common';
|
||||
import {
|
||||
PDF_JOB_TYPE,
|
||||
PDF_JOB_TYPE_V2,
|
||||
PDF_REPORT_TYPE,
|
||||
PDF_REPORT_TYPE_V2,
|
||||
} from '@kbn/reporting-export-types-pdf-common';
|
||||
import {
|
||||
PNG_JOB_TYPE,
|
||||
PNG_JOB_TYPE_V2,
|
||||
PNG_REPORT_TYPE,
|
||||
PNG_REPORT_TYPE_V2,
|
||||
} from '@kbn/reporting-export-types-png-common';
|
||||
import { PDF_JOB_TYPE_V2, PDF_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_JOB_TYPE_V2, PNG_REPORT_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
|
||||
// Export Type Sets
|
||||
export const reportTypes = [
|
||||
CSV_REPORT_TYPE,
|
||||
CSV_REPORT_TYPE_V2,
|
||||
PDF_REPORT_TYPE,
|
||||
PDF_REPORT_TYPE_V2,
|
||||
PNG_REPORT_TYPE,
|
||||
PNG_REPORT_TYPE_V2,
|
||||
];
|
||||
|
||||
export const jobTypes = [
|
||||
CSV_JOB_TYPE,
|
||||
CSV_JOB_TYPE_V2,
|
||||
PDF_JOB_TYPE,
|
||||
PDF_JOB_TYPE_V2,
|
||||
PNG_JOB_TYPE,
|
||||
PNG_JOB_TYPE_V2,
|
||||
];
|
||||
export const jobTypes = [CSV_JOB_TYPE, CSV_JOB_TYPE_V2, PDF_JOB_TYPE_V2, PNG_JOB_TYPE_V2];
|
||||
|
||||
export const USES_HEADLESS_JOB_TYPES = [
|
||||
PDF_JOB_TYPE,
|
||||
PNG_JOB_TYPE,
|
||||
PDF_JOB_TYPE_V2,
|
||||
PNG_JOB_TYPE_V2,
|
||||
];
|
||||
export const USES_HEADLESS_JOB_TYPES = [PDF_JOB_TYPE_V2, PNG_JOB_TYPE_V2];
|
||||
|
||||
export const DEPRECATED_JOB_TYPES = [CSV_JOB_TYPE_DEPRECATED];
|
||||
export const DEPRECATED_JOB_TYPES = ['csv']; // Replaced with csv_searchsource and csv_v2
|
||||
|
|
|
@ -5,24 +5,25 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CSV_JOB_TYPE, CSV_JOB_TYPE_DEPRECATED } from '@kbn/reporting-export-types-csv-common';
|
||||
import { PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_JOB_TYPE, PNG_JOB_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
import { CSV_JOB_TYPE, CSV_JOB_TYPE_V2 } from '@kbn/reporting-export-types-csv-common';
|
||||
import { PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PNG_JOB_TYPE_V2 } from '@kbn/reporting-export-types-png-common';
|
||||
|
||||
// TODO: Remove this code once everyone is using the new PDF format, then we can also remove the legacy
|
||||
// export type entirely
|
||||
// TODO: Remove this code once the enabled CSV export type is using the new format
|
||||
export const isJobV2Params = ({ sharingData }: { sharingData: Record<string, unknown> }): boolean =>
|
||||
sharingData.locatorParams != null;
|
||||
|
||||
export const prettyPrintJobType = (type: string) => {
|
||||
switch (type) {
|
||||
case PDF_JOB_TYPE:
|
||||
case 'pdf':
|
||||
case 'printable_pdf':
|
||||
case PDF_JOB_TYPE_V2:
|
||||
return 'PDF';
|
||||
case 'csv':
|
||||
case CSV_JOB_TYPE:
|
||||
case CSV_JOB_TYPE_DEPRECATED:
|
||||
case CSV_JOB_TYPE_V2:
|
||||
return 'CSV';
|
||||
case PNG_JOB_TYPE:
|
||||
case 'png':
|
||||
case PNG_JOB_TYPE_V2:
|
||||
return 'PNG';
|
||||
default:
|
||||
|
|
|
@ -40,7 +40,7 @@ describe('ReportListing', () => {
|
|||
|
||||
it('renders a listing with some items', () => {
|
||||
const { find } = testBed;
|
||||
expect(find('reportDownloadLink').length).toBe(mockJobs.length);
|
||||
expect(find('reportJobRow').length).toBe(mockJobs.length);
|
||||
});
|
||||
|
||||
it('subscribes to license changes, and unsubscribes on dismount', async () => {
|
||||
|
|
|
@ -327,7 +327,7 @@ export class ReportListingTable extends Component<ListingPropsInternal, State> {
|
|||
actions: [
|
||||
{
|
||||
isPrimary: true,
|
||||
'data-test-subj': 'reportDownloadLink',
|
||||
'data-test-subj': (job) => `reportDownloadLink-${job.id}`,
|
||||
type: 'icon',
|
||||
icon: 'download',
|
||||
name: i18n.translate('xpack.reporting.listing.table.downloadReportButtonLabel', {
|
||||
|
|
|
@ -180,8 +180,14 @@ export class ReportingPublicPlugin
|
|||
core.application.register({
|
||||
id: 'reportingRedirect',
|
||||
mount: async (params) => {
|
||||
const { mountRedirectApp } = await import('./redirect');
|
||||
return mountRedirectApp({
|
||||
const [startServices, importParams] = await Promise.all([
|
||||
core.getStartServices(),
|
||||
import('./redirect'),
|
||||
]);
|
||||
const [coreStart] = startServices;
|
||||
const { mountRedirectApp } = importParams;
|
||||
|
||||
return mountRedirectApp(coreStart, {
|
||||
...params,
|
||||
apiClient,
|
||||
screenshotMode: screenshotModeSetup,
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiErrorBoundary } from '@elastic/eui';
|
||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import type { AppMountParameters } from '@kbn/core/public';
|
||||
import type { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public';
|
||||
import type { SharePluginSetup } from '@kbn/share-plugin/public';
|
||||
|
||||
|
@ -22,22 +22,19 @@ interface MountParams extends AppMountParameters {
|
|||
share: SharePluginSetup;
|
||||
}
|
||||
|
||||
export const mountRedirectApp = ({
|
||||
element,
|
||||
apiClient,
|
||||
history,
|
||||
screenshotMode,
|
||||
share,
|
||||
}: MountParams) => {
|
||||
export const mountRedirectApp = (
|
||||
coreStart: CoreStart,
|
||||
{ element, apiClient, history, screenshotMode, share }: MountParams
|
||||
) => {
|
||||
render(
|
||||
<EuiErrorBoundary>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<RedirectApp
|
||||
apiClient={apiClient}
|
||||
history={history}
|
||||
screenshotMode={screenshotMode}
|
||||
share={share}
|
||||
/>
|
||||
</EuiErrorBoundary>,
|
||||
</KibanaRenderContextProvider>,
|
||||
element
|
||||
);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import rison from '@kbn/rison';
|
|||
|
||||
import { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server';
|
||||
import { coreMock, httpServerMock, loggingSystemMock } from '@kbn/core/server/mocks';
|
||||
import { JobParamsPDFDeprecated, TaskPayloadPDFV2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { JobParamsPDFV2, TaskPayloadPDFV2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { createMockConfigSchema } from '@kbn/reporting-mocks-server';
|
||||
|
||||
import { ReportingCore } from '../../..';
|
||||
|
@ -54,13 +54,13 @@ const getMockResponseFactory = () =>
|
|||
} as unknown as KibanaResponseFactory);
|
||||
|
||||
const mockLogger = loggingSystemMock.createLogger();
|
||||
const mockJobParams: JobParamsPDFDeprecated = {
|
||||
const mockJobParams: JobParamsPDFV2 = {
|
||||
browserTimezone: 'UTC',
|
||||
objectType: 'cool_object_type',
|
||||
title: 'cool_title',
|
||||
version: 'unknown',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: [],
|
||||
locatorParams: [],
|
||||
};
|
||||
|
||||
describe('Handle request to generate', () => {
|
||||
|
@ -145,9 +145,8 @@ describe('Handle request to generate', () => {
|
|||
"layout": Object {
|
||||
"id": "preserve_layout",
|
||||
},
|
||||
"locatorParams": undefined,
|
||||
"locatorParams": Array [],
|
||||
"objectType": "cool_object_type",
|
||||
"relativeUrls": Array [],
|
||||
"spaceId": undefined,
|
||||
"title": "cool_title",
|
||||
"version": "unknown",
|
||||
|
@ -158,7 +157,7 @@ describe('Handle request to generate', () => {
|
|||
test('provides a default kibana version field for older POST URLs', async () => {
|
||||
// how do we handle the printable_pdf endpoint that isn't migrating to the class instance of export types?
|
||||
(mockJobParams as unknown as { version?: string }).version = undefined;
|
||||
const report = await requestHandler.enqueueJob('printablePdf', mockJobParams);
|
||||
const report = await requestHandler.enqueueJob('printablePdfV2', mockJobParams);
|
||||
|
||||
const { _id, created_at: _created_at, ...snapObj } = report;
|
||||
expect(snapObj.payload.version).toBe('7.14.0');
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Readable } from 'stream';
|
|||
import { JOB_STATUS } from '@kbn/reporting-common';
|
||||
import { ReportApiJSON } from '@kbn/reporting-common/types';
|
||||
import { CSV_JOB_TYPE } from '@kbn/reporting-export-types-csv-common';
|
||||
import { PDF_JOB_TYPE, PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { PDF_JOB_TYPE_V2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import { createMockConfigSchema } from '@kbn/reporting-mocks-server';
|
||||
|
||||
import { ReportingCore } from '../../..';
|
||||
|
@ -54,7 +54,7 @@ describe('getDocumentPayload', () => {
|
|||
id: 'id1',
|
||||
index: '.reporting-12345',
|
||||
status: JOB_STATUS.COMPLETED,
|
||||
jobtype: PDF_JOB_TYPE,
|
||||
jobtype: PDF_JOB_TYPE_V2,
|
||||
output: {
|
||||
content_type: 'application/pdf',
|
||||
size: 1024,
|
||||
|
|
|
@ -79,34 +79,6 @@ it(`should return 404 if the docId isn't resolve`, async function () {
|
|||
expect(handlerCalled).toBe(false);
|
||||
});
|
||||
|
||||
it(`should return forbidden if job type is unrecognized`, async function () {
|
||||
mockJobsQueryFactory.mockReturnValue({
|
||||
get: jest.fn(() => ({ jobtype: 'notARealJobType' })),
|
||||
});
|
||||
|
||||
let handlerCalled = false;
|
||||
const handler = async () => {
|
||||
handlerCalled = true;
|
||||
return {
|
||||
status: 200,
|
||||
options: {},
|
||||
};
|
||||
};
|
||||
|
||||
await jobManagementPreRouting(
|
||||
mockCore,
|
||||
mockResponseFactory,
|
||||
'doc123',
|
||||
mockUser,
|
||||
mockCounters,
|
||||
options,
|
||||
handler
|
||||
);
|
||||
|
||||
expect(mockResponseFactory.forbidden).toBeCalled();
|
||||
expect(handlerCalled).toBe(false);
|
||||
});
|
||||
|
||||
it(`should call callback when document is available`, async function () {
|
||||
mockJobsQueryFactory.mockReturnValue({
|
||||
get: jest.fn(() => ({ jobtype: 'csv_searchsource' })),
|
||||
|
|
|
@ -32,11 +32,6 @@ export const jobManagementPreRouting = async (
|
|||
{ isInternal }: { isInternal: boolean },
|
||||
cb: JobManagementResponseHandler
|
||||
) => {
|
||||
const licenseInfo = await reporting.getLicenseInfo();
|
||||
const {
|
||||
management: { jobTypes = [] },
|
||||
} = licenseInfo;
|
||||
|
||||
const jobsQuery = jobsQueryFactory(reporting, { isInternal });
|
||||
|
||||
const doc = await jobsQuery.get(user, jobId);
|
||||
|
@ -45,15 +40,6 @@ export const jobManagementPreRouting = async (
|
|||
}
|
||||
|
||||
const { jobtype } = doc;
|
||||
if (!jobTypes.includes(jobtype)) {
|
||||
return res.forbidden({
|
||||
body: i18n.translate('xpack.reporting.jobResponse.errorHandler.notAuthorized', {
|
||||
defaultMessage: `Sorry, you are not authorized to view or delete {jobtype} reports`,
|
||||
values: { jobtype },
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
counters.usageCounter(jobtype);
|
||||
|
||||
try {
|
||||
|
|
|
@ -37,8 +37,8 @@ describe('jobsQuery', () => {
|
|||
});
|
||||
|
||||
it('should pass parameters in the request body', async () => {
|
||||
await jobsQuery.list(['pdf'], { username: 'somebody' }, 1, 10, ['id1', 'id2']);
|
||||
await jobsQuery.list(['pdf'], { username: 'somebody' }, 1, 10, null);
|
||||
await jobsQuery.list({ username: 'somebody' }, 1, 10, ['id1', 'id2']);
|
||||
await jobsQuery.list({ username: 'somebody' }, 1, 10, null);
|
||||
|
||||
expect(client.search).toHaveBeenCalledTimes(2);
|
||||
expect(client.search).toHaveBeenNthCalledWith(
|
||||
|
@ -51,7 +51,6 @@ describe('jobsQuery', () => {
|
|||
{},
|
||||
'constant_score.filter.bool.must',
|
||||
expect.arrayContaining([
|
||||
{ terms: { jobtype: ['pdf'] } },
|
||||
{ term: { created_by: 'somebody' } },
|
||||
{ ids: { values: ['id1', 'id2'] } },
|
||||
])
|
||||
|
@ -75,7 +74,7 @@ describe('jobsQuery', () => {
|
|||
});
|
||||
|
||||
it('should return reports list', async () => {
|
||||
await expect(jobsQuery.list(['pdf'], { username: 'somebody' }, 0, 10, [])).resolves.toEqual(
|
||||
await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).resolves.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'id1', jobtype: 'pdf' }),
|
||||
expect.objectContaining({ id: 'id2', jobtype: 'csv' }),
|
||||
|
@ -86,9 +85,7 @@ describe('jobsQuery', () => {
|
|||
it('should return an empty array when there are no hits', async () => {
|
||||
client.search.mockResponse({} as Awaited<ReturnType<ElasticsearchClient['search']>>);
|
||||
|
||||
await expect(
|
||||
jobsQuery.list(['pdf'], { username: 'somebody' }, 0, 10, [])
|
||||
).resolves.toHaveLength(0);
|
||||
await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).resolves.toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should reject if the report source is missing', async () => {
|
||||
|
@ -96,9 +93,9 @@ describe('jobsQuery', () => {
|
|||
set<Awaited<ReturnType<ElasticsearchClient['search']>>>({}, 'hits.hits', [{}])
|
||||
);
|
||||
|
||||
await expect(
|
||||
jobsQuery.list(['pdf'], { username: 'somebody' }, 0, 10, [])
|
||||
).rejects.toBeInstanceOf(Error);
|
||||
await expect(jobsQuery.list({ username: 'somebody' }, 0, 10, [])).rejects.toBeInstanceOf(
|
||||
Error
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -108,7 +105,7 @@ describe('jobsQuery', () => {
|
|||
});
|
||||
|
||||
it('should pass parameters in the request body', async () => {
|
||||
await jobsQuery.count(['pdf'], { username: 'somebody' });
|
||||
await jobsQuery.count({ username: 'somebody' });
|
||||
|
||||
expect(client.count).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
|
@ -116,10 +113,7 @@ describe('jobsQuery', () => {
|
|||
query: set(
|
||||
{},
|
||||
'constant_score.filter.bool.must',
|
||||
expect.arrayContaining([
|
||||
{ terms: { jobtype: ['pdf'] } },
|
||||
{ term: { created_by: 'somebody' } },
|
||||
])
|
||||
expect.arrayContaining([{ term: { created_by: 'somebody' } }])
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
@ -127,7 +121,7 @@ describe('jobsQuery', () => {
|
|||
});
|
||||
|
||||
it('should return reports number', async () => {
|
||||
await expect(jobsQuery.count(['pdf'], { username: 'somebody' })).resolves.toBe(10);
|
||||
await expect(jobsQuery.count({ username: 'somebody' })).resolves.toBe(10);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -40,13 +40,12 @@ export type ReportContent = Pick<ReportSource, 'status' | 'jobtype' | 'output'>
|
|||
|
||||
export interface JobsQueryFactory {
|
||||
list(
|
||||
jobTypes: string[],
|
||||
user: ReportingUser,
|
||||
page: number,
|
||||
size: number,
|
||||
jobIds: string[] | null
|
||||
): Promise<ReportApiJSON[]>;
|
||||
count(jobTypes: string[], user: ReportingUser): Promise<number>;
|
||||
count(user: ReportingUser): Promise<number>;
|
||||
get(user: ReportingUser, id: string): Promise<ReportApiJSON | void>;
|
||||
getError(id: string): Promise<string>;
|
||||
getDocumentPayload(doc: ReportApiJSON): Promise<Payload>;
|
||||
|
@ -74,7 +73,7 @@ export function jobsQueryFactory(
|
|||
}
|
||||
|
||||
return {
|
||||
async list(jobTypes, user, page = 0, size = defaultSize, jobIds) {
|
||||
async list(user, page = 0, size = defaultSize, jobIds) {
|
||||
const username = getUsername(user);
|
||||
const body = getSearchBody({
|
||||
size,
|
||||
|
@ -84,7 +83,6 @@ export function jobsQueryFactory(
|
|||
filter: {
|
||||
bool: {
|
||||
must: [
|
||||
{ terms: { jobtype: jobTypes } },
|
||||
{ term: { created_by: username } },
|
||||
...(jobIds ? [{ ids: { values: jobIds } }] : []),
|
||||
],
|
||||
|
@ -111,14 +109,14 @@ export function jobsQueryFactory(
|
|||
);
|
||||
},
|
||||
|
||||
async count(jobTypes, user) {
|
||||
async count(user) {
|
||||
const username = getUsername(user);
|
||||
const body = {
|
||||
query: {
|
||||
constant_score: {
|
||||
filter: {
|
||||
bool: {
|
||||
must: [{ terms: { jobtype: jobTypes } }, { term: { created_by: username } }],
|
||||
must: [{ term: { created_by: username } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -120,7 +120,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.expect(400)
|
||||
.then(({ body }) =>
|
||||
expect(body.message).toMatchInlineSnapshot(
|
||||
|
@ -135,7 +135,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf?jobParams=foo:`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2?jobParams=foo:`)
|
||||
.expect(400)
|
||||
.then(({ body }) => expect(body.message).toMatchInlineSnapshot('"invalid rison: foo:"'));
|
||||
});
|
||||
|
@ -146,7 +146,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: `foo:` })
|
||||
.expect(400)
|
||||
.then(({ body }) => expect(body.message).toMatchInlineSnapshot('"invalid rison: foo:"'));
|
||||
|
@ -172,7 +172,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: rison.encode({ browserTimezone: 'America/Amsterdam', title: `abc` }) })
|
||||
.expect(400)
|
||||
.then(({ body }) =>
|
||||
|
@ -188,7 +188,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: rison.encode({ title: `abc` }) })
|
||||
.expect(500);
|
||||
});
|
||||
|
@ -199,11 +199,10 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
|
@ -216,19 +215,14 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
created_by: 'Tom Riddle',
|
||||
id: 'foo',
|
||||
index: 'foo-index',
|
||||
jobtype: 'printable_pdf',
|
||||
jobtype: 'printable_pdf_v2',
|
||||
payload: {
|
||||
forceNow: expect.any(String),
|
||||
isDeprecated: true,
|
||||
isDeprecated: false,
|
||||
layout: {
|
||||
id: 'test',
|
||||
},
|
||||
objectType: 'canvas workpad',
|
||||
objects: [
|
||||
{
|
||||
relativeUrl: 'test',
|
||||
},
|
||||
],
|
||||
title: 'abc',
|
||||
version: '7.14.0',
|
||||
},
|
||||
|
@ -246,11 +240,10 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
|
@ -259,7 +252,7 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
|
||||
expect(usageCounter.incrementCounter).toHaveBeenCalledTimes(1);
|
||||
expect(usageCounter.incrementCounter).toHaveBeenCalledWith({
|
||||
counterName: `post /internal/reporting/generate/printablePdf`,
|
||||
counterName: `post /internal/reporting/generate/printablePdfV2`,
|
||||
counterType: 'reportingApi',
|
||||
});
|
||||
});
|
||||
|
@ -271,11 +264,10 @@ describe(`POST ${INTERNAL_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${INTERNAL_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
|
|
|
@ -205,22 +205,6 @@ describe(`Reporting Job Management Routes: Internal`, () => {
|
|||
.expect(404);
|
||||
});
|
||||
|
||||
it('returns a 403 if not a valid job type', async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
jobtype: 'invalidJobType',
|
||||
payload: { title: 'invalid!' },
|
||||
})
|
||||
);
|
||||
registerJobInfoRoutes(reportingCore);
|
||||
|
||||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.get(`${INTERNAL_ROUTES.JOBS.DOWNLOAD_PREFIX}/poo`)
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it(`returns job's info`, async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
|
@ -238,23 +222,6 @@ describe(`Reporting Job Management Routes: Internal`, () => {
|
|||
.expect(200);
|
||||
});
|
||||
|
||||
it(`returns 403 if a user cannot view a job's info`, async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
jobtype: 'customForbiddenJobType',
|
||||
payload: {}, // payload is irrelevant
|
||||
})
|
||||
);
|
||||
|
||||
registerJobInfoRoutes(reportingCore);
|
||||
|
||||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.get(`${INTERNAL_ROUTES.JOBS.INFO_PREFIX}/test`)
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it('when a job is incomplete, "internal" API endpoint should return appropriate response', async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
|
|
|
@ -47,14 +47,11 @@ export function registerJobInfoRoutesInternal(reporting: ReportingCore) {
|
|||
return handleUnavailable(res);
|
||||
}
|
||||
|
||||
const {
|
||||
management: { jobTypes = [] },
|
||||
} = await reporting.getLicenseInfo();
|
||||
const { page: queryPage = '0', size: querySize = '10', ids: queryIds = null } = req.query;
|
||||
const page = parseInt(queryPage, 10) || 0;
|
||||
const size = Math.min(100, parseInt(querySize, 10) || 10);
|
||||
const jobIds = queryIds ? queryIds.split(',') : null;
|
||||
const results = await jobsQuery.list(jobTypes, user, page, size, jobIds);
|
||||
const results = await jobsQuery.list(user, page, size, jobIds);
|
||||
|
||||
counters.usageCounter();
|
||||
|
||||
|
@ -86,11 +83,7 @@ export function registerJobInfoRoutesInternal(reporting: ReportingCore) {
|
|||
return handleUnavailable(res);
|
||||
}
|
||||
|
||||
const {
|
||||
management: { jobTypes = [] },
|
||||
} = await reporting.getLicenseInfo();
|
||||
|
||||
const count = await jobsQuery.count(jobTypes, user);
|
||||
const count = await jobsQuery.count(user);
|
||||
|
||||
counters.usageCounter();
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.expect(400)
|
||||
.then(({ body }) =>
|
||||
expect(body.message).toMatchInlineSnapshot(
|
||||
|
@ -134,7 +134,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf?jobParams=foo:`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2?jobParams=foo:`)
|
||||
.expect(400)
|
||||
.then(({ body }) => expect(body.message).toMatchInlineSnapshot('"invalid rison: foo:"'));
|
||||
});
|
||||
|
@ -145,7 +145,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: `foo:` })
|
||||
.expect(400)
|
||||
.then(({ body }) => expect(body.message).toMatchInlineSnapshot('"invalid rison: foo:"'));
|
||||
|
@ -171,7 +171,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: rison.encode({ browserTimezone: 'America/Amsterdam', title: `abc` }) })
|
||||
.expect(400)
|
||||
.then(({ body }) =>
|
||||
|
@ -187,7 +187,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({ jobParams: rison.encode({ title: `abc` }) })
|
||||
.expect(500);
|
||||
});
|
||||
|
@ -197,13 +197,53 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
|
||||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
})
|
||||
.expect(200)
|
||||
.then(({ body }) => {
|
||||
expect(body).toMatchObject({
|
||||
job: {
|
||||
attempts: 0,
|
||||
created_by: 'Tom Riddle',
|
||||
id: 'foo',
|
||||
index: 'foo-index',
|
||||
jobtype: 'printable_pdf_v2',
|
||||
payload: {
|
||||
forceNow: expect.any(String),
|
||||
isDeprecated: false,
|
||||
layout: {
|
||||
id: 'test',
|
||||
},
|
||||
objectType: 'canvas workpad',
|
||||
title: 'abc',
|
||||
version: '7.14.0',
|
||||
},
|
||||
status: 'pending',
|
||||
},
|
||||
path: '/mock-server-basepath/api/reporting/jobs/download/foo',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('allows deprecated printablePdf request', async () => {
|
||||
registerGenerationRoutesPublic(reportingCore, mockLogger);
|
||||
|
||||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
relativeUrls: ['test'],
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
})
|
||||
|
@ -223,11 +263,6 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
id: 'test',
|
||||
},
|
||||
objectType: 'canvas workpad',
|
||||
objects: [
|
||||
{
|
||||
relativeUrl: 'test',
|
||||
},
|
||||
],
|
||||
title: 'abc',
|
||||
version: '7.14.0',
|
||||
},
|
||||
|
@ -245,11 +280,10 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
|
@ -258,7 +292,7 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
|
||||
expect(usageCounter.incrementCounter).toHaveBeenCalledTimes(1);
|
||||
expect(usageCounter.incrementCounter).toHaveBeenCalledWith({
|
||||
counterName: `post /api/reporting/generate/printablePdf`,
|
||||
counterName: `post /api/reporting/generate/printablePdfV2`,
|
||||
counterType: 'reportingApi',
|
||||
});
|
||||
});
|
||||
|
@ -269,11 +303,10 @@ describe(`POST ${PUBLIC_ROUTES.GENERATE_PREFIX}`, () => {
|
|||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdf`)
|
||||
.post(`${PUBLIC_ROUTES.GENERATE_PREFIX}/printablePdfV2`)
|
||||
.send({
|
||||
jobParams: rison.encode({
|
||||
title: `abc`,
|
||||
relativeUrls: ['test'],
|
||||
layout: { id: 'test' },
|
||||
objectType: 'canvas workpad',
|
||||
}),
|
||||
|
|
|
@ -194,22 +194,6 @@ describe(`Reporting Job Management Routes: Public`, () => {
|
|||
.expect(404);
|
||||
});
|
||||
|
||||
it('returns a 403 if not a valid job type', async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
jobtype: 'invalidJobType',
|
||||
payload: { title: 'invalid!' },
|
||||
})
|
||||
);
|
||||
registerJobInfoRoutesPublic(reportingCore);
|
||||
|
||||
await server.start();
|
||||
|
||||
await supertest(httpSetup.server.listener)
|
||||
.get(`${PUBLIC_ROUTES.JOBS.DOWNLOAD_PREFIX}/poo`)
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it('when a job is incomplete', async () => {
|
||||
mockEsClient.search.mockResponseOnce(
|
||||
getHits({
|
||||
|
|
|
@ -33971,7 +33971,6 @@
|
|||
"xpack.reporting.diagnostic.noUsableSandbox": "Impossible d'utiliser la sandbox Chromium. Vous pouvez la désactiver à vos risques et périls avec \"xpack.screenshotting.browser.chromium.disableSandbox\". Veuillez consulter {url}",
|
||||
"xpack.reporting.errorHandler.unknownError": "Erreur inconnue",
|
||||
"xpack.reporting.features.reportingFeatureName": "Reporting",
|
||||
"xpack.reporting.jobResponse.errorHandler.notAuthorized": "Désolé, vous n'êtes pas autorisé à afficher ou supprimer les rapports {jobtype}",
|
||||
"xpack.reporting.jobResponse.errorHandler.unknownError": "Erreur inconnue",
|
||||
"xpack.reporting.jobsQuery.deleteError": "Impossible de supprimer le rapport : {error}",
|
||||
"xpack.reporting.listing.diagnosticApiCallFailure": "Un problème est survenu lors de l'exécution du diagnostic : {error}",
|
||||
|
|
|
@ -33956,7 +33956,6 @@
|
|||
"xpack.reporting.diagnostic.noUsableSandbox": "Chromiumサンドボックスを使用できません。これは「xpack.screenshotting.browser.chromium.disableSandbox」で無効にすることができます。この作業はご自身の責任で行ってください。{url}を参照してください",
|
||||
"xpack.reporting.errorHandler.unknownError": "不明なエラー",
|
||||
"xpack.reporting.features.reportingFeatureName": "レポート",
|
||||
"xpack.reporting.jobResponse.errorHandler.notAuthorized": "{jobtype}レポートを表示または削除する権限がありません",
|
||||
"xpack.reporting.jobResponse.errorHandler.unknownError": "不明なエラー",
|
||||
"xpack.reporting.jobsQuery.deleteError": "レポートを削除できません:{error}",
|
||||
"xpack.reporting.listing.diagnosticApiCallFailure": "診断の実行中に問題が発生しました:{error}",
|
||||
|
|
|
@ -33997,7 +33997,6 @@
|
|||
"xpack.reporting.diagnostic.noUsableSandbox": "无法使用 Chromium 沙盒。您自行承担使用“xpack.screenshotting.browser.chromium.disableSandbox”禁用此项的风险。请参见 {url}",
|
||||
"xpack.reporting.errorHandler.unknownError": "未知错误",
|
||||
"xpack.reporting.features.reportingFeatureName": "Reporting",
|
||||
"xpack.reporting.jobResponse.errorHandler.notAuthorized": "抱歉,您无权查看或删除 {jobtype} 报告",
|
||||
"xpack.reporting.jobResponse.errorHandler.unknownError": "未知错误",
|
||||
"xpack.reporting.jobsQuery.deleteError": "无法删除报告:{error}",
|
||||
"xpack.reporting.listing.diagnosticApiCallFailure": "运行诊断时出现问题:{error}",
|
||||
|
|
66
x-pack/test/functional/apps/reporting_management/__snapshots__/report_listing.snap
generated
Normal file
66
x-pack/test/functional/apps/reporting_management/__snapshots__/report_listing.snap
generated
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`reporting management app Listing of Reports Displays types of report jobs 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 10:29 PM",
|
||||
"report": "Automated report",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:47 PM",
|
||||
"report": "Discover search [2021-07-19T11:47:35.995-07:00]",
|
||||
"status": "Done",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:46 PM",
|
||||
"report": "Discover search [2021-07-19T11:46:00.132-07:00]",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:44 PM",
|
||||
"report": "Discover search [2021-07-19T11:44:48.670-07:00]",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Pending",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Failed",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:38 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:38 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:38 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done",
|
||||
},
|
||||
]
|
||||
`;
|
|
@ -83,70 +83,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
|
||||
it('Displays types of report jobs', async () => {
|
||||
const list = await pageObjects.reporting.getManagementList();
|
||||
expectSnapshot(list).toMatchInline(`
|
||||
Array [
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:47 PM",
|
||||
"report": "Discover search [2021-07-19T11:47:35.995-07:00]",
|
||||
"status": "Done",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:46 PM",
|
||||
"report": "Discover search [2021-07-19T11:46:00.132-07:00]",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:44 PM",
|
||||
"report": "Discover search [2021-07-19T11:44:48.670-07:00]",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Pending",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Failed",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done, warnings detected",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:38 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 06:38 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Done",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2021-07-19 @ 02:41 PM",
|
||||
"report": "[Flights] Global Flight Dashboard",
|
||||
"status": "Failed",
|
||||
},
|
||||
Object {
|
||||
"actions": "",
|
||||
"createdAt": "2020-04-21 @ 07:01 PM",
|
||||
"report": "[Logs] File Type Scatter Plot",
|
||||
"status": "Done",
|
||||
},
|
||||
]
|
||||
`);
|
||||
expectSnapshot(list).toMatch();
|
||||
});
|
||||
|
||||
it('Exposes an action to see the ES query in console', async () => {
|
||||
|
|
Binary file not shown.
|
@ -28,7 +28,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
it('should fail job when page violates the network policy', async () => {
|
||||
const downloadPath = await reportingAPI.postJob(
|
||||
`/api/reporting/generate/printablePdf?jobParams=(layout:(dimensions:(height:720,width:1080),id:preserve_layout),objectType:'canvas%20workpad',relativeUrls:!(%2Fapp%2Fcanvas%23%2Fexport%2Fworkpad%2Fpdf%2Fworkpad-e7464259-0b75-4b8c-81c8-8422b15ff201%2Fpage%2F1),title:'My%20Canvas%20Workpad')`
|
||||
`/api/reporting/generate/printablePdfV2?jobParams=(layout:(dimensions:(height:720,width:1080),id:preserve_layout),locatorParams:!((id:CANVAS_APP_LOCATOR,params:(id:workpad-e7464259-0b75-4b8c-81c8-8422b15ff201,page:1,view:workpadPDF),version:'8.16.0')),objectType:'canvas workpad',title:'Workpad of Death',version:'8.16.0')`
|
||||
);
|
||||
|
||||
// Retry the download URL until a "failed" response status is returned
|
||||
|
|
|
@ -32,7 +32,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'dashboard',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'dashboard',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'visualization',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'visualization',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF disallowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'canvas',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
browserTimezone: 'UTC',
|
||||
title: 'test PDF allowed',
|
||||
layout: { id: 'preserve_layout' },
|
||||
relativeUrls: ['/fooyou'],
|
||||
locatorParams: [{ id: 'canvas', version: '7.14.0', params: {} }],
|
||||
objectType: 'canvas',
|
||||
version: '7.14.0',
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const downloadPath = await reportingAPI.postJobJSON(
|
||||
`/s/non_default_space/api/reporting/generate/pngV2`,
|
||||
{
|
||||
jobParams: `(browserTimezone:UTC,layout:(dimensions:(height:512,width:2402),id:png),objectType:dashboard,relativeUrl:'/s/non_default_space/app/dashboards#/view/3c9ee360-e7ee-11ea-a730-d58e9ea7581b?_g=(filters:!!(),refreshInterval:(pause:!!t,value:0),time:(from:!'2019-06-10T03:17:28.800Z!',to:!'2019-07-14T19:25:06.385Z!'))&_a=(description:!'!',filters:!!(),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),query:(language:kuery,query:!'!'),timeRestore:!!t,title:!'Ecom%20Dashboard%20Non%20Default%20Space!',viewMode:view)',title:'Ecom Dashboard Non Default Space')`,
|
||||
jobParams: `(browserTimezone:UTC,layout:(dimensions:(height:512,width:2402),id:png),locatorParams:(id:DASHBOARD_APP_LOCATOR,params:(dashboardId:e35742df-db88-5bd6-9d35-732b4b04a079,preserveSavedFilters:!t,timeRange:(from:'2019-06-10T03:17:28.800Z',to:'2019-07-14T19:25:06.385Z'),useHash:!f,viewMode:view)),objectType:dashboard,title:'Ecom Dashboard Non Default Space',version:'8.16.0')`,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -168,9 +168,9 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
it('should complete a job of PDF export of a dashboard in non-default space', async () => {
|
||||
const downloadPath = await reportingAPI.postJobJSON(
|
||||
`/s/non_default_space/api/reporting/generate/printablePdf`,
|
||||
`/s/non_default_space/api/reporting/generate/printablePdfV2`,
|
||||
{
|
||||
jobParams: `(browserTimezone:UTC,layout:(dimensions:(height:512,width:2402),id:preserve_layout),objectType:dashboard,relativeUrls:!('/s/non_default_space/app/dashboards#/view/3c9ee360-e7ee-11ea-a730-d58e9ea7581b?_g=(filters:!!(),refreshInterval:(pause:!!t,value:0),time:(from:!'2019-06-10T03:17:28.800Z!',to:!'2019-07-14T19:25:06.385Z!'))&_a=(description:!'!',filters:!!(),fullScreenMode:!!f,options:(hidePanelTitles:!!f,useMargins:!!t),query:(language:kuery,query:!'!'),timeRestore:!!t,title:!'Ecom%20Dashboard%20Non%20Default%20Space!',viewMode:view)'),title:'Ecom Dashboard Non Default Space')`,
|
||||
jobParams: `(browserTimezone:UTC,layout:(dimensions:(height:512,width:2402),id:preserve_layout),locatorParams:!((id:DASHBOARD_APP_LOCATOR,params:(dashboardId:e35742df-db88-5bd6-9d35-732b4b04a079,preserveSavedFilters:!t,timeRange:(from:'2019-06-10T03:17:28.800Z',to:'2019-07-14T19:25:06.385Z'),useHash:!f,viewMode:view))),objectType:dashboard,title:'Ecom Dashboard Non Default Space',version:'8.16.0')`,
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { LoadActionPerfOptions } from '@kbn/es-archiver';
|
||||
import { INTERNAL_ROUTES } from '@kbn/reporting-common';
|
||||
import type { JobParamsCSV } from '@kbn/reporting-export-types-csv-common';
|
||||
import type { JobParamsPDFDeprecated } from '@kbn/reporting-export-types-pdf-common';
|
||||
import type { JobParamsPDFV2 } from '@kbn/reporting-export-types-pdf-common';
|
||||
import type { JobParamsPNGV2 } from '@kbn/reporting-export-types-png-common';
|
||||
import {
|
||||
REPORTING_DATA_STREAM_WILDCARD,
|
||||
|
@ -142,10 +142,10 @@ export function createScenarios({ getService }: Pick<FtrProviderContext, 'getSer
|
|||
});
|
||||
};
|
||||
|
||||
const generatePdf = async (username: string, password: string, job: JobParamsPDFDeprecated) => {
|
||||
const generatePdf = async (username: string, password: string, job: JobParamsPDFV2) => {
|
||||
const jobParams = rison.encode(job);
|
||||
return await supertestWithoutAuth
|
||||
.post(`/api/reporting/generate/printablePdf`)
|
||||
.post(`/api/reporting/generate/printablePdfV2`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send({ jobParams });
|
||||
|
@ -183,7 +183,7 @@ export function createScenarios({ getService }: Pick<FtrProviderContext, 'getSer
|
|||
|
||||
const postJobJSON = async (apiPath: string, jobJSON: object = {}): Promise<string> => {
|
||||
log.debug(`ReportingAPI.postJobJSON((${apiPath}): ${JSON.stringify(jobJSON)})`);
|
||||
const { body } = await supertest.post(apiPath).set('kbn-xsrf', 'xxx').send(jobJSON);
|
||||
const { body } = await supertest.post(apiPath).set('kbn-xsrf', 'xxx').send(jobJSON).expect(200);
|
||||
return body.path;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => {
|
|||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
const reportingFunctional = getService('reportingFunctional');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('Access to Management > Reporting', () => {
|
||||
before(async () => {
|
||||
|
@ -54,5 +55,29 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => {
|
|||
|
||||
await PageObjects.dashboard.expectOnDashboard(dashboardTitle);
|
||||
});
|
||||
|
||||
describe('Download report', () => {
|
||||
// use archived reports to allow reporting_user to view report jobs they've created
|
||||
before(async () => {
|
||||
await esArchiver.load('x-pack/test/functional/es_archives/reporting/archived_reports');
|
||||
|
||||
await reportingFunctional.loginReportingUser();
|
||||
await PageObjects.common.navigateToApp('reporting');
|
||||
await testSubjects.existOrFail('reportJobListing');
|
||||
});
|
||||
after(async () => {
|
||||
await esArchiver.unload('x-pack/test/functional/es_archives/reporting/archived_reports');
|
||||
});
|
||||
|
||||
it('user can access download link', async () => {
|
||||
await testSubjects.existOrFail('reportDownloadLink-kraz9db6154g0763b5141viu');
|
||||
});
|
||||
|
||||
it('user can access download link for export type that is no longer supported', async () => {
|
||||
// The "csv" export type, aka CSV V1, was removed and can no longer be created.
|
||||
// Downloading a report of this export type does still work
|
||||
await testSubjects.existOrFail('reportDownloadLink-krb7arhe164k0763b50bjm31');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue