2020-05-20 19:47:49 +08:00
|
|
|
import React from 'react';
|
|
|
|
// Reference: https://github.com/ant-design/ant-design/pull/24003#discussion_r427267386
|
|
|
|
// eslint-disable-next-line import/no-unresolved
|
2022-06-28 19:28:26 +08:00
|
|
|
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
|
|
|
|
import dayjs from 'dayjs';
|
2023-04-12 11:40:09 +08:00
|
|
|
import { globSync } from 'glob';
|
2022-06-28 19:28:26 +08:00
|
|
|
import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
|
2020-10-28 16:16:31 +08:00
|
|
|
import MockDate from 'mockdate';
|
2022-06-28 19:28:26 +08:00
|
|
|
import ReactDOMServer from 'react-dom/server';
|
2023-09-17 23:32:14 +08:00
|
|
|
|
2023-03-10 11:50:12 +08:00
|
|
|
import { App, ConfigProvider, theme } from '../../components';
|
2020-10-23 18:50:46 +08:00
|
|
|
|
|
|
|
const toMatchImageSnapshot = configureToMatchImageSnapshot({
|
|
|
|
customSnapshotsDir: `${process.cwd()}/imageSnapshots`,
|
|
|
|
customDiffDir: `${process.cwd()}/imageDiffSnapshots`,
|
|
|
|
});
|
2020-05-20 19:47:49 +08:00
|
|
|
|
|
|
|
expect.extend({ toMatchImageSnapshot });
|
|
|
|
|
2023-05-23 17:10:19 +08:00
|
|
|
const themes = {
|
|
|
|
default: theme.defaultAlgorithm,
|
|
|
|
dark: theme.darkAlgorithm,
|
|
|
|
compact: theme.compactAlgorithm,
|
|
|
|
};
|
|
|
|
|
2023-09-14 16:59:11 +08:00
|
|
|
interface ImageTestOptions {
|
|
|
|
onlyViewport?: boolean;
|
|
|
|
splitTheme?: boolean;
|
|
|
|
}
|
|
|
|
|
2023-06-07 21:59:21 +08:00
|
|
|
// eslint-disable-next-line jest/no-export
|
2023-09-14 16:59:11 +08:00
|
|
|
export default function imageTest(component: React.ReactElement, options: ImageTestOptions) {
|
|
|
|
function test(name: string, themedComponent: React.ReactElement) {
|
|
|
|
it(name, async () => {
|
|
|
|
await jestPuppeteer.resetPage();
|
|
|
|
await page.setRequestInterception(true);
|
|
|
|
const onRequestHandle = (request: any) => {
|
|
|
|
if (['image'].includes(request.resourceType())) {
|
|
|
|
request.abort();
|
|
|
|
} else {
|
|
|
|
request.continue();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
MockDate.set(dayjs('2016-11-22').valueOf());
|
|
|
|
page.on('request', onRequestHandle);
|
|
|
|
await page.goto(`file://${process.cwd()}/tests/index.html`);
|
|
|
|
await page.addStyleTag({ path: `${process.cwd()}/components/style/reset.css` });
|
|
|
|
await page.addStyleTag({ content: '*{animation: none!important;}' });
|
|
|
|
|
|
|
|
const cache = createCache();
|
|
|
|
|
|
|
|
const element = (
|
|
|
|
<StyleProvider cache={cache}>
|
|
|
|
<App>{themedComponent}</App>
|
|
|
|
</StyleProvider>
|
|
|
|
);
|
|
|
|
|
|
|
|
const html = ReactDOMServer.renderToString(element);
|
|
|
|
const styleStr = extractStyle(cache);
|
|
|
|
|
|
|
|
await page.evaluate(
|
|
|
|
(innerHTML, ssrStyle) => {
|
|
|
|
document.querySelector('#root')!.innerHTML = innerHTML;
|
|
|
|
|
|
|
|
const head = document.querySelector('head')!;
|
|
|
|
head.innerHTML += ssrStyle;
|
|
|
|
},
|
|
|
|
html,
|
|
|
|
styleStr,
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!options.onlyViewport) {
|
|
|
|
// Get scroll height of the rendered page and set viewport
|
|
|
|
const bodyHeight = await page.evaluate(() => document.body.scrollHeight);
|
|
|
|
await page.setViewport({ width: 800, height: bodyHeight });
|
2023-05-23 17:10:19 +08:00
|
|
|
}
|
|
|
|
|
2023-09-14 16:59:11 +08:00
|
|
|
const image = await page.screenshot({
|
|
|
|
fullPage: !options.onlyViewport,
|
|
|
|
});
|
2023-05-23 17:10:19 +08:00
|
|
|
|
2023-09-14 16:59:11 +08:00
|
|
|
expect(image).toMatchImageSnapshot();
|
2023-05-23 17:10:19 +08:00
|
|
|
|
2023-09-14 16:59:11 +08:00
|
|
|
MockDate.reset();
|
|
|
|
page.off('request', onRequestHandle);
|
2023-09-04 17:58:51 +08:00
|
|
|
});
|
2023-09-14 16:59:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (options.splitTheme) {
|
|
|
|
Object.entries(themes).forEach(([key, algorithm]) => {
|
|
|
|
test(
|
|
|
|
`component image screenshot should correct ${key}`,
|
|
|
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
|
|
|
<ConfigProvider theme={{ algorithm }}>{component}</ConfigProvider>
|
|
|
|
</div>,
|
|
|
|
);
|
2023-11-22 20:53:48 +08:00
|
|
|
test(
|
|
|
|
`[CSS Var] component image screenshot should correct ${key}`,
|
|
|
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
|
|
|
<div>CSS Var</div>
|
|
|
|
<ConfigProvider theme={{ algorithm, cssVar: true }}>{component}</ConfigProvider>
|
|
|
|
</div>,
|
|
|
|
);
|
2023-05-23 17:10:19 +08:00
|
|
|
});
|
2023-09-14 16:59:11 +08:00
|
|
|
} else {
|
|
|
|
test(
|
|
|
|
`component image screenshot should correct`,
|
|
|
|
<>
|
|
|
|
{Object.entries(themes).map(([key, algorithm]) => (
|
|
|
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
|
|
|
<ConfigProvider theme={{ algorithm }}>{component}</ConfigProvider>
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</>,
|
|
|
|
);
|
2023-11-22 20:53:48 +08:00
|
|
|
test(
|
|
|
|
`[CSS Var] component image screenshot should correct`,
|
|
|
|
<>
|
|
|
|
<div>CSS Var</div>
|
|
|
|
{Object.entries(themes).map(([key, algorithm]) => (
|
|
|
|
<div style={{ background: key === 'dark' ? '#000' : '', padding: `24px 12px` }} key={key}>
|
2023-11-29 17:23:45 +08:00
|
|
|
<ConfigProvider theme={{ algorithm, cssVar: true }}>{component}</ConfigProvider>
|
2023-11-22 20:53:48 +08:00
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</>,
|
|
|
|
);
|
2023-09-14 16:59:11 +08:00
|
|
|
}
|
2020-05-20 19:47:49 +08:00
|
|
|
}
|
2020-10-23 18:50:46 +08:00
|
|
|
|
|
|
|
type Options = {
|
|
|
|
skip?: boolean | string[];
|
2023-09-14 16:59:11 +08:00
|
|
|
onlyViewport?: boolean | string[];
|
|
|
|
splitTheme?: boolean | string[];
|
2020-10-23 18:50:46 +08:00
|
|
|
};
|
|
|
|
|
2023-06-07 21:59:21 +08:00
|
|
|
// eslint-disable-next-line jest/no-export
|
2020-10-23 18:50:46 +08:00
|
|
|
export function imageDemoTest(component: string, options: Options = {}) {
|
2022-12-05 12:14:05 +08:00
|
|
|
let describeMethod = options.skip === true ? describe.skip : describe;
|
2023-04-12 11:40:09 +08:00
|
|
|
const files = globSync(`./components/${component}/demo/*.tsx`);
|
2020-10-23 18:50:46 +08:00
|
|
|
|
2022-11-19 13:47:33 +08:00
|
|
|
files.forEach((file) => {
|
2023-09-14 16:59:11 +08:00
|
|
|
if (Array.isArray(options.skip) && options.skip.some((c) => file.endsWith(c))) {
|
2022-12-05 12:14:05 +08:00
|
|
|
describeMethod = describe.skip;
|
|
|
|
} else {
|
|
|
|
describeMethod = describe;
|
2020-10-23 18:50:46 +08:00
|
|
|
}
|
2023-06-07 21:59:21 +08:00
|
|
|
describeMethod(`Test ${file} image`, () => {
|
2020-10-23 18:50:46 +08:00
|
|
|
// eslint-disable-next-line global-require,import/no-dynamic-require
|
2023-06-07 21:59:21 +08:00
|
|
|
let Demo = require(`../../${file}`).default;
|
2022-04-03 23:27:45 +08:00
|
|
|
if (typeof Demo === 'function') {
|
|
|
|
Demo = <Demo />;
|
|
|
|
}
|
2023-09-14 16:59:11 +08:00
|
|
|
imageTest(Demo, {
|
|
|
|
onlyViewport:
|
|
|
|
options.onlyViewport === true ||
|
|
|
|
(Array.isArray(options.onlyViewport) &&
|
|
|
|
options.onlyViewport.some((c) => file.endsWith(c))),
|
|
|
|
splitTheme:
|
|
|
|
options.splitTheme === true ||
|
|
|
|
(Array.isArray(options.splitTheme) && options.splitTheme.some((c) => file.endsWith(c))),
|
|
|
|
});
|
2020-10-23 18:50:46 +08:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|