Skip to content

Commit

Permalink
[test] Take screenshot of the print export (#2881)
Browse files Browse the repository at this point in the history
  • Loading branch information
m4theushw committed Oct 19, 2021
1 parent 71be844 commit c1f4202
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 75 deletions.
1 change: 0 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
"stylis": "^4.0.10",
"stylis-plugin-rtl": "^2.1.0",
"stylis-plugin-rtl-sc": "npm:stylis-plugin-rtl@^2.1.0",
"webfontloader": "^1.6.28",
"webpack-bundle-analyzer": "^4.5.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ export const useGridPrintExport = (
typeof normalizeOptions.pageStyle === 'function'
? normalizeOptions.pageStyle()
: normalizeOptions.pageStyle;
if (typeof defaultPageStyle !== 'string') {
if (typeof defaultPageStyle === 'string') {
// TODO custom styles should always win
const styleElement = printDoc.createElement('style');
styleElement.appendChild(printDoc.createTextNode(defaultPageStyle));
printDoc.head.appendChild(styleElement);
Expand Down
23 changes: 21 additions & 2 deletions packages/storybook/src/stories/grid-toolbar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { DataGrid } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';
import * as React from 'react';
import { DataGridPro, GridToolbar } from '@mui/x-data-grid-pro';
import {
DataGridPro,
GridToolbar,
GridToolbarContainer,
GridToolbarExport,
gridClasses,
} from '@mui/x-data-grid-pro';
import '../style/grid-stories.css';
import { useData } from '../hooks/useData';

Expand Down Expand Up @@ -70,6 +76,19 @@ export const Export = () => {
);
};

function CustomToolbar() {
return (
<GridToolbarContainer className={gridClasses.toolbarContainer}>
<GridToolbarExport
printOptions={{
pageStyle: '@page { margin: 0; }', // Zero the margin to hide the header and footer
}}
disableRipple // Prevent printing the Export button with the ripple visible
/>
</GridToolbarContainer>
);
}

export const PrintExportSnap = () => {
const { data } = useDemoData({
dataSet: 'Commodity',
Expand All @@ -84,7 +103,7 @@ export const PrintExportSnap = () => {
{...data}
checkboxSelection
components={{
Toolbar: GridToolbar,
Toolbar: CustomToolbar,
}}
/>
</div>
Expand Down
29 changes: 3 additions & 26 deletions test/regressions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
import { LicenseInfo } from '@mui/x-data-grid-pro';
import { withStyles } from '@mui/styles';
import webfontloader from 'webfontloader';
import TestViewer from 'test/regressions/TestViewer';
import { useFakeTimers } from 'sinon';
import addons, { mockChannel } from '@storybook/addons';
Expand Down Expand Up @@ -159,25 +158,6 @@ function App() {
};
}, []);

// Using <link rel="stylesheet" /> does not apply the google Roboto font in chromium headless/headfull.
const [fontState, setFontState] = React.useState('pending');
React.useEffect(() => {
webfontloader.load({
google: {
families: ['Roboto:300,400,500,700'],
},
timeout: 20000,
active: () => {
setFontState('active');
},
inactive: () => {
setFontState('inactive');
},
});
}, []);

const testPrepared = fontState !== 'pending';

function computePath(test) {
return `/${test.suite}/${test.name}`;
}
Expand All @@ -201,17 +181,14 @@ function App() {

return (
<Route key={path} exact path={path}>
{testPrepared && (
<TestViewer dataGridContainer={dataGridContainer}>
<TestCase />
</TestViewer>
)}
<TestViewer dataGridContainer={dataGridContainer}>
<TestCase />
</TestViewer>
</Route>
);
})}
</Switch>
<div hidden={!isDev}>
<div data-webfontloader={fontState}>webfontloader: {fontState}</div>
<p>
Devtools can be enabled by appending <code>#dev</code> in the addressbar or disabled by
appending <code>#no-dev</code>.
Expand Down
84 changes: 44 additions & 40 deletions test/regressions/index.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fse from 'fs-extra';
import { expect } from 'chai';
import * as path from 'path';
import * as childProcess from 'child_process';
import * as playwright from 'playwright';

function sleep(timeoutMS) {
Expand Down Expand Up @@ -45,8 +46,6 @@ async function main() {
// Wait for all requests to finish.
// This should load shared ressources such as fonts.
await page.goto(`${baseUrl}#no-dev`, { waitUntil: 'networkidle0' });
// If we still get flaky fonts after awaiting this try `document.fonts.ready`
await page.waitForSelector('[data-webfontloader="active"]', { state: 'attached' });

// Simulate portrait mode for date pickers.
// See `useIsLandscape`.
Expand Down Expand Up @@ -104,44 +103,10 @@ async function main() {
const screenshotPath = path.resolve(screenshotDir, `${route.replace(baseUrl, '.')}.png`);
await fse.ensureDir(path.dirname(screenshotPath));

let testcase;
if (pathURL === '/stories-grid-toolbar/PrintExportSnap') {
// Capture the content of the print dialog. Because there is no easy way to navigate the.
// print window/dialog with playwrite a hacky aproach is needed.
this.timeout(6000);
let printGrid;
// Click the export button in the toolbar.
await page.$eval(`button[aria-label="Export"]`, (exportButton) => {
exportButton.click();
});
// Click the print export option from the export menu in the toolbar.
await page.$eval(`li[role="menuitem"]:last-child`, (printButton) => {
printButton.click();
});
// Delay the main thread with some time to alow the iframe content to be loaded.
await sleep(2000);
// Grab the content of the print iframe.
await page.$eval(`#grid-print-window`, (printWindow) => {
printGrid = printWindow.contentWindow.document.querySelector('[role="grid"]');
});
// Append the content of the print iframe to a element in the page.
await page.$eval(`#grid-print-container`, (printContainer) => {
printContainer.appendChild(printGrid);
});
// Because there is now other way of closing the iframe, set the src back to ''.
// This will close the print dialog/window. If not done the test will timeout.
await page.$eval(`#grid-print-window`, (printWindow) => {
printWindow.src = '';
});

// Select the element from the page that has the print iframe contant and
// make the screenshot.
testcase = await page.waitForSelector('#grid-print-container');
await testcase.screenshot({ path: screenshotPath, type: 'png' });
} else {
testcase = await page.waitForSelector('[data-testid="testcase"]:not([aria-busy="true"])');
await testcase.screenshot({ path: screenshotPath, type: 'png' });
}
const testcase = await page.waitForSelector(
'[data-testid="testcase"]:not([aria-busy="true"])',
);
await testcase.screenshot({ path: screenshotPath, type: 'png' });
});

it(`should have no errors rendering ${pathURL}`, () => {
Expand All @@ -150,6 +115,45 @@ async function main() {
expect(msg).to.equal(undefined);
});
});

it('should take a screenshot of the print preview', async function test() {
this.timeout(10000);

const route = `${baseUrl}/stories-grid-toolbar/PrintExportSnap`;
const screenshotPath = path.resolve(screenshotDir, `${route.replace(baseUrl, '.')}Print.png`);
await fse.ensureDir(path.dirname(screenshotPath));

const testcaseIndex = routes.indexOf(route);
await page.$eval(`#tests li:nth-of-type(${testcaseIndex + 1}) a`, (link) => {
link.click();
});

// Click the export button in the toolbar.
await page.$eval(`button[aria-label="Export"]`, (exportButton) => {
exportButton.click();
});

// Click the print export option from the export menu in the toolbar.
await page.$eval(`li[role="menuitem"]:last-child`, (printButton) => {
printButton.click();
});

await sleep(2000);

return new Promise((resolve, reject) => {
// See https://ffmpeg.org/ffmpeg-devices.html#x11grab
const args = `-y -f x11grab -framerate 1 -video_size 460x400 -i :99.0+90,81 -vframes 1 ${screenshotPath}`;
const ffmpeg = childProcess.spawn('ffmpeg', args.split(' '));

ffmpeg.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject();
}
});
});
});
});

run();
Expand Down
4 changes: 4 additions & 0 deletions test/regressions/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
background-color: white;
}
</style>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="react-root"></div>
Expand Down
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18726,11 +18726,6 @@ web-namespaces@^1.0.0:
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec"
integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==

webfontloader@^1.6.28:
version "1.6.28"
resolved "https://registry.yarnpkg.com/webfontloader/-/webfontloader-1.6.28.tgz#db786129253cb6e8eae54c2fb05f870af6675bae"
integrity sha1-23hhKSU8tujq5UwvsF+HCvZnW64=

webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
Expand Down

0 comments on commit c1f4202

Please sign in to comment.