-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Reporting/Test] Add Functional test for download CSV #65401
Merged
tsullivan
merged 10 commits into
elastic:master
from
tsullivan:reporting/test-dashboard-csv-download
May 11, 2020
+203
−121
Merged
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
6154209
[Reporting/Test] Add Functional test for download CSV
tsullivan 5ff2716
add todo
tsullivan 0a4c07a
Merge branch 'master' into reporting/test-dashboard-csv-download
tsullivan 22bacd9
add fs.existsSync check to find download
tsullivan e455f7b
debug
tsullivan 9690315
handle timeout
tsullivan 7bea090
validate toast
tsullivan f40eead
different way of getting repo_root
tsullivan ac83451
Merge branch 'master' into reporting/test-dashboard-csv-download
tsullivan df1f185
Merge branch 'master' into reporting/test-dashboard-csv-download
tsullivan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
x-pack/test/functional/apps/dashboard/reporting/download_csv.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* 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 fs from 'fs'; | ||
import path from 'path'; | ||
import * as Rx from 'rxjs'; | ||
import { filter, first, map, timeout } from 'rxjs/operators'; | ||
import { FtrProviderContext } from '../../../ftr_provider_context'; | ||
|
||
const csvPath = path.resolve( | ||
__dirname, | ||
'../../../../../../target/functional-tests/downloads/Ecommerce Data.csv' | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Spencer showed me a nice way to do it
|
||
|
||
export default function({ getService, getPageObjects }: FtrProviderContext) { | ||
const esArchiver = getService('esArchiver'); | ||
const browser = getService('browser'); | ||
const dashboardPanelActions = getService('dashboardPanelActions'); | ||
const log = getService('log'); | ||
const testSubjects = getService('testSubjects'); | ||
const PageObjects = getPageObjects(['reporting', 'common', 'dashboard']); | ||
|
||
describe('Reporting Download CSV', () => { | ||
before('initialize tests', async () => { | ||
log.debug('ReportingPage:initTests'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce_kibana'); | ||
await browser.setWindowSize(1600, 850); | ||
}); | ||
|
||
after('clean up archives and previous file download', async () => { | ||
await esArchiver.unload('reporting/ecommerce'); | ||
await esArchiver.unload('reporting/ecommerce_kibana'); | ||
try { | ||
fs.unlinkSync(csvPath); | ||
} catch (e) { | ||
// nothing to worry | ||
} | ||
}); | ||
|
||
it('Downloads a CSV export of a saved search panel', async function() { | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); | ||
const savedSearchPanel = await testSubjects.find('embeddablePanelHeading-EcommerceData'); | ||
await dashboardPanelActions.toggleContextMenu(savedSearchPanel); | ||
|
||
await testSubjects.existOrFail('embeddablePanelAction-downloadCsvReport'); // wait for the full panel to display | ||
await testSubjects.click('embeddablePanelAction-downloadCsvReport'); | ||
|
||
// check every 100ms for the file to exist in the download dir | ||
// just wait up to 5 seconds | ||
const success$ = Rx.interval(100).pipe( | ||
map(() => fs.existsSync(csvPath)), | ||
filter(value => value === true), | ||
first(), | ||
timeout(5000) | ||
); | ||
|
||
const fileExists = await success$.toPromise(); | ||
expect(fileExists).to.be(true); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,125 +3,11 @@ | |
* 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 fs from 'fs'; | ||
import path from 'path'; | ||
import { promisify } from 'util'; | ||
import { FtrProviderContext } from '../../../ftr_provider_context'; | ||
import { checkIfPngsMatch } from './lib/compare_pngs'; | ||
|
||
const writeFileAsync = promisify(fs.writeFile); | ||
const mkdirAsync = promisify(fs.mkdir); | ||
|
||
const REPORTS_FOLDER = path.resolve(__dirname, 'reports'); | ||
|
||
export default function({ getService, getPageObjects }: FtrProviderContext) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. refactored these tests to |
||
const esArchiver = getService('esArchiver'); | ||
const browser = getService('browser'); | ||
const log = getService('log'); | ||
const config = getService('config'); | ||
const PageObjects = getPageObjects(['reporting', 'common', 'dashboard']); | ||
|
||
describe('Reporting', () => { | ||
before('initialize tests', async () => { | ||
log.debug('ReportingPage:initTests'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce_kibana'); | ||
await browser.setWindowSize(1600, 850); | ||
}); | ||
after('clean up archives', async () => { | ||
await esArchiver.unload('reporting/ecommerce'); | ||
await esArchiver.unload('reporting/ecommerce_kibana'); | ||
}); | ||
|
||
describe('Print PDF button', () => { | ||
it('is not available if new', async () => { | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.clickNewDashboard(); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); | ||
}); | ||
|
||
it('becomes available when saved', async () => { | ||
await PageObjects.dashboard.saveDashboard('My PDF Dashboard'); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); | ||
}); | ||
}); | ||
|
||
describe('Print Layout', () => { | ||
it('downloads a PDF file', async function() { | ||
// Generating and then comparing reports can take longer than the default 60s timeout because the comparePngs | ||
// function is taking about 15 seconds per comparison in jenkins. | ||
this.timeout(300000); | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
await PageObjects.reporting.checkUsePrintLayout(); | ||
await PageObjects.reporting.clickGenerateReportButton(); | ||
|
||
const url = await PageObjects.reporting.getReportURL(60000); | ||
const res = await PageObjects.reporting.getResponse(url); | ||
|
||
expect(res.statusCode).to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/pdf'); | ||
}); | ||
}); | ||
|
||
describe('Print PNG button', () => { | ||
it('is not available if new', async () => { | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.clickNewDashboard(); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); | ||
}); | ||
|
||
it('becomes available when saved', async () => { | ||
await PageObjects.dashboard.saveDashboard('My PNG Dash'); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); | ||
}); | ||
}); | ||
|
||
describe('Preserve Layout', () => { | ||
it('matches baseline report', async function() { | ||
const writeSessionReport = async (name: string, rawPdf: Buffer, reportExt: string) => { | ||
const sessionDirectory = path.resolve(REPORTS_FOLDER, 'session'); | ||
await mkdirAsync(sessionDirectory, { recursive: true }); | ||
const sessionReportPath = path.resolve(sessionDirectory, `${name}.${reportExt}`); | ||
await writeFileAsync(sessionReportPath, rawPdf); | ||
return sessionReportPath; | ||
}; | ||
const getBaselineReportPath = (fileName: string, reportExt: string) => { | ||
const baselineFolder = path.resolve(REPORTS_FOLDER, 'baseline'); | ||
const fullPath = path.resolve(baselineFolder, `${fileName}.${reportExt}`); | ||
log.debug(`getBaselineReportPath (${fullPath})`); | ||
return fullPath; | ||
}; | ||
|
||
this.timeout(300000); | ||
|
||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
await PageObjects.reporting.forceSharedItemsContainerSize({ width: 1405 }); | ||
await PageObjects.reporting.clickGenerateReportButton(); | ||
await PageObjects.reporting.removeForceSharedItemsContainerSize(); | ||
|
||
const url = await PageObjects.reporting.getReportURL(60000); | ||
const reportData = await PageObjects.reporting.getRawPdfReportData(url); | ||
const reportFileName = 'dashboard_preserve_layout'; | ||
const sessionReportPath = await writeSessionReport(reportFileName, reportData, 'png'); | ||
const percentSimilar = await checkIfPngsMatch( | ||
sessionReportPath, | ||
getBaselineReportPath(reportFileName, 'png'), | ||
config.get('screenshots.directory'), | ||
log | ||
); | ||
|
||
expect(percentSimilar).to.be.lessThan(0.1); | ||
}); | ||
}); | ||
export default function({ loadTestFile }: FtrProviderContext) { | ||
describe('Reporting', function() { | ||
loadTestFile(require.resolve('./screenshots')); | ||
loadTestFile(require.resolve('./download_csv')); | ||
}); | ||
} |
127 changes: 127 additions & 0 deletions
127
x-pack/test/functional/apps/dashboard/reporting/screenshots.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/* | ||
* 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 fs from 'fs'; | ||
import path from 'path'; | ||
import { promisify } from 'util'; | ||
import { FtrProviderContext } from '../../../ftr_provider_context'; | ||
import { checkIfPngsMatch } from './lib/compare_pngs'; | ||
|
||
const writeFileAsync = promisify(fs.writeFile); | ||
const mkdirAsync = promisify(fs.mkdir); | ||
|
||
const REPORTS_FOLDER = path.resolve(__dirname, 'reports'); | ||
|
||
export default function({ getService, getPageObjects }: FtrProviderContext) { | ||
const esArchiver = getService('esArchiver'); | ||
const browser = getService('browser'); | ||
const log = getService('log'); | ||
const config = getService('config'); | ||
const PageObjects = getPageObjects(['reporting', 'common', 'dashboard']); | ||
|
||
describe('Screenshots', () => { | ||
before('initialize tests', async () => { | ||
log.debug('ReportingPage:initTests'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce'); | ||
await esArchiver.loadIfNeeded('reporting/ecommerce_kibana'); | ||
await browser.setWindowSize(1600, 850); | ||
}); | ||
after('clean up archives', async () => { | ||
await esArchiver.unload('reporting/ecommerce'); | ||
await esArchiver.unload('reporting/ecommerce_kibana'); | ||
}); | ||
|
||
describe('Print PDF button', () => { | ||
it('is not available if new', async () => { | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.clickNewDashboard(); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); | ||
}); | ||
|
||
it('becomes available when saved', async () => { | ||
await PageObjects.dashboard.saveDashboard('My PDF Dashboard'); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); | ||
}); | ||
}); | ||
|
||
describe('Print Layout', () => { | ||
it('downloads a PDF file', async function() { | ||
// Generating and then comparing reports can take longer than the default 60s timeout because the comparePngs | ||
// function is taking about 15 seconds per comparison in jenkins. | ||
this.timeout(300000); | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); | ||
await PageObjects.reporting.openPdfReportingPanel(); | ||
await PageObjects.reporting.checkUsePrintLayout(); | ||
await PageObjects.reporting.clickGenerateReportButton(); | ||
|
||
const url = await PageObjects.reporting.getReportURL(60000); | ||
const res = await PageObjects.reporting.getResponse(url); | ||
|
||
expect(res.statusCode).to.equal(200); | ||
expect(res.headers['content-type']).to.equal('application/pdf'); | ||
}); | ||
}); | ||
|
||
describe('Print PNG button', () => { | ||
it('is not available if new', async () => { | ||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.clickNewDashboard(); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); | ||
}); | ||
|
||
it('becomes available when saved', async () => { | ||
await PageObjects.dashboard.saveDashboard('My PNG Dash'); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); | ||
}); | ||
}); | ||
|
||
describe('Preserve Layout', () => { | ||
it('matches baseline report', async function() { | ||
const writeSessionReport = async (name: string, rawPdf: Buffer, reportExt: string) => { | ||
const sessionDirectory = path.resolve(REPORTS_FOLDER, 'session'); | ||
await mkdirAsync(sessionDirectory, { recursive: true }); | ||
const sessionReportPath = path.resolve(sessionDirectory, `${name}.${reportExt}`); | ||
await writeFileAsync(sessionReportPath, rawPdf); | ||
return sessionReportPath; | ||
}; | ||
const getBaselineReportPath = (fileName: string, reportExt: string) => { | ||
const baselineFolder = path.resolve(REPORTS_FOLDER, 'baseline'); | ||
const fullPath = path.resolve(baselineFolder, `${fileName}.${reportExt}`); | ||
log.debug(`getBaselineReportPath (${fullPath})`); | ||
return fullPath; | ||
}; | ||
|
||
this.timeout(300000); | ||
|
||
await PageObjects.common.navigateToApp('dashboard'); | ||
await PageObjects.dashboard.loadSavedDashboard('Ecom Dashboard'); | ||
await PageObjects.reporting.openPngReportingPanel(); | ||
await PageObjects.reporting.forceSharedItemsContainerSize({ width: 1405 }); | ||
await PageObjects.reporting.clickGenerateReportButton(); | ||
await PageObjects.reporting.removeForceSharedItemsContainerSize(); | ||
|
||
const url = await PageObjects.reporting.getReportURL(60000); | ||
const reportData = await PageObjects.reporting.getRawPdfReportData(url); | ||
const reportFileName = 'dashboard_preserve_layout'; | ||
const sessionReportPath = await writeSessionReport(reportFileName, reportData, 'png'); | ||
const percentSimilar = await checkIfPngsMatch( | ||
sessionReportPath, | ||
getBaselineReportPath(reportFileName, 'png'), | ||
config.get('screenshots.directory'), | ||
log | ||
); | ||
|
||
expect(percentSimilar).to.be.lessThan(0.1); | ||
}); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting some flakiness in the tests, so I added this debug.
I think the flaky is coming from using
dashboardPanelActions.toggleContextMenu(savedSearchPanel)
to open the panel share menu.Let's see if this keeps turning out to be flaky.