diff --git a/x-pack/plugins/reporting/public/components/__snapshots__/report_listing.test.tsx.snap b/x-pack/plugins/reporting/public/components/__snapshots__/report_listing.test.tsx.snap
index ddba7842f1199..66c3aea8acc13 100644
--- a/x-pack/plugins/reporting/public/components/__snapshots__/report_listing.test.tsx.snap
+++ b/x-pack/plugins/reporting/public/components/__snapshots__/report_listing.test.tsx.snap
@@ -30,6 +30,7 @@ Array [
},
]
}
+ data-test-page={0}
data-test-subj="reportJobListing"
isSelectable={true}
itemId="id"
@@ -56,6 +57,7 @@ Array [
>
@@ -366,6 +368,7 @@ Array [
,
diff --git a/x-pack/plugins/reporting/public/components/report_listing.tsx b/x-pack/plugins/reporting/public/components/report_listing.tsx
index afcae93a8db16..80ef9311fd0e5 100644
--- a/x-pack/plugins/reporting/public/components/report_listing.tsx
+++ b/x-pack/plugins/reporting/public/components/report_listing.tsx
@@ -513,6 +513,7 @@ class ReportListingUi extends Component
{
isSelectable={true}
onChange={this.onTableChange}
data-test-subj="reportJobListing"
+ data-test-page={this.state.page}
/>
{this.state.selectedJobs.length > 0 ? this.renderDeleteButton() : null}
diff --git a/x-pack/plugins/reporting/server/routes/jobs.ts b/x-pack/plugins/reporting/server/routes/jobs.ts
index 4033719b053ba..e8eac9e577beb 100644
--- a/x-pack/plugins/reporting/server/routes/jobs.ts
+++ b/x-pack/plugins/reporting/server/routes/jobs.ts
@@ -35,7 +35,13 @@ export function registerJobInfoRoutes(reporting: ReportingCore) {
router.get(
{
path: `${MAIN_ENTRY}/list`,
- validate: false,
+ validate: {
+ query: schema.object({
+ page: schema.string({ defaultValue: '0' }),
+ size: schema.string({ defaultValue: '10' }),
+ ids: schema.maybe(schema.string()),
+ }),
+ },
},
userHandler(async (user, context, req, res) => {
// ensure the async dependencies are loaded
@@ -50,7 +56,7 @@ export function registerJobInfoRoutes(reporting: ReportingCore) {
page: queryPage = '0',
size: querySize = '10',
ids: queryIds = null,
- } = req.query as ListQuery;
+ } = req.query as ListQuery; // NOTE: type inference is not working here. userHandler breaks it?
const page = parseInt(queryPage, 10) || 0;
const size = Math.min(100, parseInt(querySize, 10) || 10);
const jobIds = queryIds ? queryIds.split(',') : null;
diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts
index da1131d051581..cf70e5a7b8b6c 100644
--- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts
+++ b/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts
@@ -16,12 +16,13 @@ const mkdirAsync = promisify(fs.mkdir);
const REPORTS_FOLDER = path.resolve(__dirname, 'reports');
-export default function ({ getService, getPageObjects }: FtrProviderContext) {
+export default function ({ getPageObjects, getService }: FtrProviderContext) {
+ const PageObjects = getPageObjects(['reporting', 'common', 'dashboard']);
const esArchiver = getService('esArchiver');
const browser = getService('browser');
const log = getService('log');
const config = getService('config');
- const PageObjects = getPageObjects(['reporting', 'common', 'dashboard']);
+ const es = getService('es');
describe('Screenshots', () => {
before('initialize tests', async () => {
@@ -33,6 +34,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
after('clean up archives', async () => {
await esArchiver.unload('reporting/ecommerce');
await esArchiver.unload('reporting/ecommerce_kibana');
+ await es.deleteByQuery({
+ index: '.reporting-*',
+ refresh: true,
+ body: { query: { match_all: {} } },
+ });
});
describe('Print PDF button', () => {
diff --git a/x-pack/test/functional/apps/discover/reporting.ts b/x-pack/test/functional/apps/discover/reporting.ts
index 32ccc59913dbc..7181bf0c74271 100644
--- a/x-pack/test/functional/apps/discover/reporting.ts
+++ b/x-pack/test/functional/apps/discover/reporting.ts
@@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const log = getService('log');
+ const es = getService('es');
const esArchiver = getService('esArchiver');
const browser = getService('browser');
const PageObjects = getPageObjects(['reporting', 'common', 'discover']);
@@ -22,6 +23,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
after('clean up archives', async () => {
await esArchiver.unload('reporting/ecommerce');
+ await es.deleteByQuery({
+ index: '.reporting-*',
+ refresh: true,
+ body: { query: { match_all: {} } },
+ });
});
describe('Generate CSV button', () => {
diff --git a/x-pack/test/functional/apps/lens/lens_reporting.ts b/x-pack/test/functional/apps/lens/lens_reporting.ts
index 3e3d217b9d8d7..4974b63be6f72 100644
--- a/x-pack/test/functional/apps/lens/lens_reporting.ts
+++ b/x-pack/test/functional/apps/lens/lens_reporting.ts
@@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const PageObjects = getPageObjects(['common', 'dashboard', 'reporting']);
+ const es = getService('es');
const esArchiver = getService('esArchiver');
const listingTable = getService('listingTable');
@@ -19,6 +20,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
after(async () => {
await esArchiver.unload('lens/reporting');
+ await es.deleteByQuery({
+ index: '.reporting-*',
+ refresh: true,
+ body: { query: { match_all: {} } },
+ });
});
it('should not cause PDF reports to fail', async () => {
diff --git a/x-pack/test/functional/apps/reporting_management/index.ts b/x-pack/test/functional/apps/reporting_management/index.ts
index f44d5858d53a1..8606c46053ab0 100644
--- a/x-pack/test/functional/apps/reporting_management/index.ts
+++ b/x-pack/test/functional/apps/reporting_management/index.ts
@@ -9,6 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default ({ loadTestFile }: FtrProviderContext) => {
describe('reporting management app', function () {
this.tags('ciGroup7');
- loadTestFile(require.resolve('./report_delete_pagination'));
+ loadTestFile(require.resolve('./report_listing'));
});
};
diff --git a/x-pack/test/functional/apps/reporting_management/report_delete_pagination.ts b/x-pack/test/functional/apps/reporting_management/report_delete_pagination.ts
deleted file mode 100644
index 488314030085f..0000000000000
--- a/x-pack/test/functional/apps/reporting_management/report_delete_pagination.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 expect from '@kbn/expect';
-import { FtrProviderContext } from '../../ftr_provider_context';
-
-export default ({ getPageObjects, getService }: FtrProviderContext) => {
- const pageObjects = getPageObjects(['common', 'reporting']);
- const log = getService('log');
- const retry = getService('retry');
- const security = getService('security');
-
- const testSubjects = getService('testSubjects');
- const esArchiver = getService('esArchiver');
-
- describe('Delete reports', function () {
- before(async () => {
- await security.testUser.setRoles(['kibana_admin', 'reporting_user']);
- await esArchiver.load('empty_kibana');
- await esArchiver.load('reporting/archived_reports');
- await pageObjects.common.navigateToApp('reporting');
- await testSubjects.existOrFail('reportJobListing', { timeout: 200000 });
- });
-
- after(async () => {
- await esArchiver.unload('empty_kibana');
- await esArchiver.unload('reporting/archived_reports');
- await security.testUser.restoreDefaults();
- });
-
- it('Confirm single report deletion works', async () => {
- log.debug('Checking for reports.');
- await retry.try(async () => {
- await testSubjects.click('checkboxSelectRow-k9a9xlwl0gpe1457b10rraq3');
- });
- const deleteButton = await testSubjects.find('deleteReportButton');
- await retry.waitFor('delete button to become enabled', async () => {
- return await deleteButton.isEnabled();
- });
- await deleteButton.click();
- await testSubjects.exists('confirmModalBodyText');
- await testSubjects.click('confirmModalConfirmButton');
- await retry.try(async () => {
- await testSubjects.waitForDeleted('checkboxSelectRow-k9a9xlwl0gpe1457b10rraq3');
- });
- });
-
- // functional test for report pagination: https://github.com/elastic/kibana/pull/62881
- it('Report pagination', async () => {
- const previousButton = await testSubjects.find('pagination-button-previous');
- expect(await previousButton.getAttribute('disabled')).to.be('true');
- await testSubjects.click('pagination-button-1');
- expect(await previousButton.getAttribute('disabled')).to.be(null);
- });
- });
-};
diff --git a/x-pack/test/functional/apps/reporting_management/report_listing.ts b/x-pack/test/functional/apps/reporting_management/report_listing.ts
new file mode 100644
index 0000000000000..5bb36103fc6f6
--- /dev/null
+++ b/x-pack/test/functional/apps/reporting_management/report_listing.ts
@@ -0,0 +1,121 @@
+/*
+ * 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 expect from '@kbn/expect';
+import { WebElementWrapper } from 'test/functional/services/lib/web_element_wrapper';
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+const getTableTextFromElement = async (tableEl: WebElementWrapper) => {
+ const rows = await tableEl.findAllByCssSelector('tbody tr');
+ return (
+ await Promise.all(
+ rows.map(async (row) => {
+ return await row.getVisibleText();
+ })
+ )
+ ).join('\n');
+};
+
+export default ({ getPageObjects, getService }: FtrProviderContext) => {
+ const pageObjects = getPageObjects(['common', 'reporting']);
+ const log = getService('log');
+ const retry = getService('retry');
+ const security = getService('security');
+
+ const testSubjects = getService('testSubjects');
+ const findInstance = getService('find');
+ const esArchiver = getService('esArchiver');
+
+ describe('Listing of Reports', function () {
+ before(async () => {
+ await security.testUser.setRoles(['kibana_admin', 'reporting_user']);
+ await esArchiver.load('empty_kibana');
+ });
+
+ beforeEach(async () => {
+ // to reset the data after deletion testing
+ await esArchiver.load('reporting/archived_reports');
+ await pageObjects.common.navigateToApp('reporting');
+ await testSubjects.existOrFail('reportJobListing', { timeout: 200000 });
+ });
+
+ after(async () => {
+ await esArchiver.unload('empty_kibana');
+ await security.testUser.restoreDefaults();
+ });
+
+ afterEach(async () => {
+ await esArchiver.unload('reporting/archived_reports');
+ });
+
+ it('Confirm single report deletion works', async () => {
+ log.debug('Checking for reports.');
+ await retry.try(async () => {
+ await testSubjects.click('checkboxSelectRow-k9a9xlwl0gpe1457b10rraq3');
+ });
+ const deleteButton = await testSubjects.find('deleteReportButton');
+ await retry.waitFor('delete button to become enabled', async () => {
+ return await deleteButton.isEnabled();
+ });
+ await deleteButton.click();
+ await testSubjects.exists('confirmModalBodyText');
+ await testSubjects.click('confirmModalConfirmButton');
+ await retry.try(async () => {
+ await testSubjects.waitForDeleted('checkboxSelectRow-k9a9xlwl0gpe1457b10rraq3');
+ });
+ });
+
+ it('Paginates content', async () => {
+ const previousButton = await testSubjects.find('pagination-button-previous');
+
+ // previous CAN NOT be clicked
+ expect(await previousButton.getAttribute('disabled')).to.be('true');
+
+ // scan page 1
+ let tableText = await getTableTextFromElement(await testSubjects.find('reportJobListing'));
+ const PAGE_CONTENT_1 = `[Logs] File Type Scatter Plot\nvisualization\n2020-04-21 @ 07:01 PM\ntest_user\nCompleted at 2020-04-21 @ 07:02 PM
+[Logs] File Type Scatter Plot\nvisualization\n2020-04-21 @ 07:01 PM\ntest_user\nCompleted at 2020-04-21 @ 07:02 PM
+[Logs] Heatmap\nvisualization\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:01 PM
+[Logs] Heatmap\nvisualization\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:01 PM
+[Flights] Flight Delays\nvisualization\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:01 PM
+[Flights] Flight Delays\nvisualization\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:01 PM
+pdf\ndashboard\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:00 PM
+pdf\ndashboard\n2020-04-21 @ 07:00 PM\ntest_user\nCompleted at 2020-04-21 @ 07:00 PM
+[Flights] Flight Cancellations\nvisualization\n2020-04-21 @ 06:59 PM\ntest_user\nCompleted at 2020-04-21 @ 07:00 PM
+[Flights] Markdown Instructions\nvisualization\n2020-04-21 @ 06:59 PM\ntest_user\nCompleted at 2020-04-21 @ 07:00 PM`;
+ expect(tableText).to.be(PAGE_CONTENT_1);
+
+ // click page 2
+ await testSubjects.click('pagination-button-1');
+ await findInstance.byCssSelector('[data-test-page="1"]');
+
+ // previous CAN be clicked
+ expect(await previousButton.getAttribute('disabled')).to.be(null);
+
+ // scan page 2
+ tableText = await getTableTextFromElement(await testSubjects.find('reportJobListing'));
+ const PAGE_CONTENT_2 = `[eCommerce] Revenue Tracking\ncanvas workpad\n2020-04-21 @ 06:58 PM\ntest_user\nCompleted at 2020-04-21 @ 06:59 PM
+[Logs] Web Traffic\ncanvas workpad\n2020-04-21 @ 06:58 PM\ntest_user\nCompleted at 2020-04-21 @ 06:59 PM
+[Flights] Overview\ncanvas workpad\n2020-04-21 @ 06:58 PM\ntest_user\nCompleted at 2020-04-21 @ 06:59 PM
+[eCommerce] Revenue Dashboard\ndashboard\n2020-04-21 @ 06:57 PM\ntest_user\nCompleted at 2020-04-21 @ 06:58 PM
+[Logs] Web Traffic\ndashboard\n2020-04-21 @ 06:57 PM\ntest_user\nCompleted at 2020-04-21 @ 06:58 PM
+[Flights] Global Flight Dashboard\ndashboard\n2020-04-21 @ 06:56 PM\ntest_user\nCompleted at 2020-04-21 @ 06:57 PM
+[Flights] Global Flight Dashboard\ndashboard\n2020-04-21 @ 06:56 PM\ntest_user\nCompleted at 2020-04-21 @ 06:57 PM
+report4csv\n2020-04-21 @ 06:55 PM\ntest_user\nCompleted at 2020-04-21 @ 06:56 PM - Max size reached\nreport3csv\n2020-04-21 @ 06:55 PM
+test_user\nCompleted at 2020-04-21 @ 06:55 PM - Max size reached\nreport2csv\n2020-04-21 @ 06:54 PM\ntest_user\nCompleted at 2020-04-21 @ 06:55 PM - Max size reached`;
+ expect(tableText).to.be(PAGE_CONTENT_2);
+
+ // click page 3
+ await testSubjects.click('pagination-button-2');
+ await findInstance.byCssSelector('[data-test-page="2"]');
+
+ // scan page 3
+ tableText = await getTableTextFromElement(await testSubjects.find('reportJobListing'));
+ const PAGE_CONTENT_3 = `report1csv\n2020-04-21 @ 06:54 PM\ntest_user\nCompleted at 2020-04-21 @ 06:54 PM - Max size reached`;
+ expect(tableText).to.be(PAGE_CONTENT_3);
+ });
+ });
+};
diff --git a/x-pack/test/functional/apps/visualize/reporting.ts b/x-pack/test/functional/apps/visualize/reporting.ts
index 02fd74e9480f7..d1cea5a4481b1 100644
--- a/x-pack/test/functional/apps/visualize/reporting.ts
+++ b/x-pack/test/functional/apps/visualize/reporting.ts
@@ -8,6 +8,7 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
+ const es = getService('es');
const esArchiver = getService('esArchiver');
const browser = getService('browser');
const log = getService('log');
@@ -29,6 +30,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
after('clean up archives', async () => {
await esArchiver.unload('reporting/ecommerce');
await esArchiver.unload('reporting/ecommerce_kibana');
+ await es.deleteByQuery({
+ index: '.reporting-*',
+ refresh: true,
+ body: { query: { match_all: {} } },
+ });
});
describe('Print PDF button', () => {