mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
test: Update image snapshot logic (#46529)
* test: mix snapshot * test: clean up * test: fix order * test: fix test logic * test: fix reset * test: refactor code * test: clean fetch * chore: lint * test: clean up * test: delay check * chore: refactor fetch * docs: update diff html * test: add ssr support * chore: part use ssr * chore: update style * chore: slice of it * docs: fix cut
This commit is contained in:
parent
b071284027
commit
eff720837c
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
|||||||
|
|
||||||
// jest config for image snapshots
|
// jest config for image snapshots
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFiles: ['./tests/setup.js'],
|
setupFiles: ['./tests/setup.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||||
moduleNameMapper,
|
moduleNameMapper,
|
||||||
transform: {
|
transform: {
|
||||||
@ -19,5 +19,5 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
preset: 'jest-puppeteer',
|
preset: 'jest-puppeteer',
|
||||||
testTimeout: 10000,
|
testTimeout: 20000,
|
||||||
};
|
};
|
||||||
|
2
.jest.js
2
.jest.js
@ -32,7 +32,7 @@ function getTestRegex(libDir) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
verbose: true,
|
verbose: true,
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
setupFiles: ['./tests/setup.js', 'jest-canvas-mock'],
|
setupFiles: ['./tests/setup.ts', 'jest-canvas-mock'],
|
||||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'md'],
|
||||||
modulePathIgnorePatterns: ['/_site/'],
|
modulePathIgnorePatterns: ['/_site/'],
|
||||||
|
@ -2,7 +2,7 @@ const { moduleNameMapper, transformIgnorePatterns } = require('./.jest');
|
|||||||
|
|
||||||
// jest config for server render environment
|
// jest config for server render environment
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupFiles: ['./tests/setup.js'],
|
setupFiles: ['./tests/setup.ts'],
|
||||||
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
setupFilesAfterEnv: ['./tests/setupAfterEnv.ts'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'md'],
|
||||||
moduleNameMapper,
|
moduleNameMapper,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
||||||
|
|
||||||
describe('Carousel image', () => {
|
describe('Carousel image', () => {
|
||||||
imageDemoTest('carousel');
|
imageDemoTest('carousel', {
|
||||||
|
ssr: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import dayjs from 'dayjs';
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
import demoTest, { rootPropsTest } from '../../../tests/shared/demoTest';
|
import demoTest, { rootPropsTest } from '../../../tests/shared/demoTest';
|
||||||
|
|
||||||
demoTest('date-picker', { skip: ['locale.tsx', 'component-token.tsx'], testRootProps: false });
|
demoTest('date-picker', { skip: ['locale.tsx', 'component-token.tsx'], testRootProps: false });
|
||||||
@ -10,7 +11,7 @@ rootPropsTest('date-picker', (DatePicker, props) => <DatePicker {...props} value
|
|||||||
});
|
});
|
||||||
|
|
||||||
rootPropsTest(
|
rootPropsTest(
|
||||||
'date-picker',
|
['date-picker', 'RangePicker'],
|
||||||
(DatePicker, props) => <DatePicker.RangePicker {...props} value={dayjs()} />,
|
(DatePicker, props) => <DatePicker.RangePicker {...props} value={dayjs()} />,
|
||||||
{
|
{
|
||||||
findRootElements: () => document.querySelectorAll('.ant-picker-range, .ant-picker-dropdown'),
|
findRootElements: () => document.querySelectorAll('.ant-picker-range, .ant-picker-dropdown'),
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
import { imageDemoTest } from '../../../tests/shared/imageTest';
|
||||||
|
|
||||||
describe('Progress image', () => {
|
describe('Progress image', () => {
|
||||||
imageDemoTest('progress');
|
imageDemoTest('progress', {
|
||||||
|
ssr: true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -93,7 +93,7 @@
|
|||||||
"pretest": "npm run version && npm run component-changelog",
|
"pretest": "npm run version && npm run component-changelog",
|
||||||
"test": "jest --config .jest.js --no-cache",
|
"test": "jest --config .jest.js --no-cache",
|
||||||
"test-all": "sh -e ./scripts/test-all.sh",
|
"test-all": "sh -e ./scripts/test-all.sh",
|
||||||
"test-image": "jest --config .jest.image.js --no-cache -i -u",
|
"test-image": "jest --config .jest.image.js --no-cache -i -u --forceExit",
|
||||||
"test-node": "npm run version && jest --config .jest.node.js --no-cache",
|
"test-node": "npm run version && jest --config .jest.node.js --no-cache",
|
||||||
"test:update": "jest --config .jest.js --no-cache -u",
|
"test:update": "jest --config .jest.js --no-cache -u",
|
||||||
"token-meta": "tsx scripts/generate-token-meta.ts",
|
"token-meta": "tsx scripts/generate-token-meta.ts",
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
/* eslint-disable compat/compat */
|
/* eslint-disable compat/compat */
|
||||||
/* eslint-disable no-console, no-await-in-loop, import/no-extraneous-dependencies, lodash/import-scope, no-restricted-syntax */
|
/* eslint-disable no-console, no-await-in-loop, import/no-extraneous-dependencies, lodash/import-scope, no-restricted-syntax */
|
||||||
import path from 'path';
|
import { assert } from 'console';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
|
import path from 'path';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import { finished } from 'stream/promises';
|
import { finished } from 'stream/promises';
|
||||||
|
|
||||||
import { remark } from 'remark';
|
|
||||||
import remarkHtml from 'remark-html';
|
|
||||||
import remarkGfm from 'remark-gfm';
|
|
||||||
import minimist from 'minimist';
|
|
||||||
import tar from 'tar';
|
|
||||||
import fse from 'fs-extra';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
import fse from 'fs-extra';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import minimist from 'minimist';
|
||||||
import pixelmatch from 'pixelmatch';
|
import pixelmatch from 'pixelmatch';
|
||||||
import { PNG } from 'pngjs';
|
import { PNG } from 'pngjs';
|
||||||
|
import { remark } from 'remark';
|
||||||
|
import remarkGfm from 'remark-gfm';
|
||||||
|
import remarkHtml from 'remark-html';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { assert } from 'console';
|
import tar from 'tar';
|
||||||
|
|
||||||
const ALI_OSS_BUCKET = 'antd-visual-diff';
|
const ALI_OSS_BUCKET = 'antd-visual-diff';
|
||||||
|
|
||||||
@ -158,10 +157,7 @@ function generateReport(
|
|||||||
|
|
||||||
const htmlReportLink = `${publicPath}/visualRegressionReport/report.html`;
|
const htmlReportLink = `${publicPath}/visualRegressionReport/report.html`;
|
||||||
|
|
||||||
const addonFullReportDesc = `\n\nToo many visual-regression diffs found, please check <a href="${htmlReportLink}" target="_blank">Full Report</a> for details`;
|
const addonFullReportDesc = `\n\nCheck <a href="${htmlReportLink}" target="_blank">Full Report</a> for details`;
|
||||||
|
|
||||||
// github action pr comment has limit of 65536 4-byte unicode characters
|
|
||||||
const limit = 65536 - addonFullReportDesc.length;
|
|
||||||
|
|
||||||
let reportMdStr = `
|
let reportMdStr = `
|
||||||
${commonHeader}
|
${commonHeader}
|
||||||
@ -174,7 +170,7 @@ ${commonHeader}
|
|||||||
|
|
||||||
let fullVersionMd = reportMdStr;
|
let fullVersionMd = reportMdStr;
|
||||||
|
|
||||||
let addonFullReportDescAdded = false;
|
let diffCount = 0;
|
||||||
|
|
||||||
for (const badCase of badCases) {
|
for (const badCase of badCases) {
|
||||||
const { filename, type } = badCase;
|
const { filename, type } = badCase;
|
||||||
@ -199,16 +195,15 @@ ${commonHeader}
|
|||||||
lineReportMdStr += ' |\n';
|
lineReportMdStr += ' |\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineReportMdStr) {
|
diffCount += 1;
|
||||||
if (reportMdStr.length + lineReportMdStr.length < limit) {
|
if (diffCount <= 10) {
|
||||||
reportMdStr += lineReportMdStr;
|
reportMdStr += lineReportMdStr;
|
||||||
} else if (!addonFullReportDescAdded) {
|
|
||||||
reportMdStr += addonFullReportDesc;
|
|
||||||
addonFullReportDescAdded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fullVersionMd += lineReportMdStr;
|
fullVersionMd += lineReportMdStr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
reportMdStr += addonFullReportDesc;
|
||||||
|
|
||||||
// convert fullVersionMd to html
|
// convert fullVersionMd to html
|
||||||
return [reportMdStr, md2Html(fullVersionMd)];
|
return [reportMdStr, md2Html(fullVersionMd)];
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
th,
|
th,
|
||||||
@ -26,6 +27,20 @@
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th+th,
|
||||||
|
td+td {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
background-color: #f2f2f2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console, import/prefer-default-export */
|
||||||
const util = require('util');
|
import util from 'util';
|
||||||
|
import type { DOMWindow } from 'jsdom';
|
||||||
|
|
||||||
|
// import { fillWindowEnv } from './utils';
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
@ -20,17 +24,21 @@ console.error = (...args) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* eslint-disable global-require */
|
type Writeable<T> = { -readonly [P in keyof T]: T[P] };
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
global.window.resizeTo = (width, height) => {
|
// This function can not move to external file since jest setup not support
|
||||||
global.window.innerWidth = width || global.window.innerWidth;
|
export function fillWindowEnv(window: Window | DOMWindow) {
|
||||||
global.window.innerHeight = height || global.window.innerHeight;
|
const win = window as Writeable<Window> & typeof globalThis;
|
||||||
global.window.dispatchEvent(new Event('resize'));
|
|
||||||
|
win.resizeTo = (width, height) => {
|
||||||
|
win.innerWidth = width || win.innerWidth;
|
||||||
|
win.innerHeight = height || win.innerHeight;
|
||||||
|
win.dispatchEvent(new Event('resize'));
|
||||||
};
|
};
|
||||||
global.window.scrollTo = () => {};
|
win.scrollTo = () => {};
|
||||||
// ref: https://github.com/ant-design/ant-design/issues/18774
|
// ref: https://github.com/ant-design/ant-design/issues/18774
|
||||||
if (!window.matchMedia) {
|
if (!win.matchMedia) {
|
||||||
Object.defineProperty(global.window, 'matchMedia', {
|
Object.defineProperty(win, 'matchMedia', {
|
||||||
writable: true,
|
writable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
value: jest.fn((query) => ({
|
value: jest.fn((query) => ({
|
||||||
@ -44,11 +52,19 @@ if (typeof window !== 'undefined') {
|
|||||||
// Fix css-animation or rc-motion deps on these
|
// Fix css-animation or rc-motion deps on these
|
||||||
// https://github.com/react-component/motion/blob/9c04ef1a210a4f3246c9becba6e33ea945e00669/src/util/motion.ts#L27-L35
|
// https://github.com/react-component/motion/blob/9c04ef1a210a4f3246c9becba6e33ea945e00669/src/util/motion.ts#L27-L35
|
||||||
// https://github.com/yiminghe/css-animation/blob/a5986d73fd7dfce75665337f39b91483d63a4c8c/src/Event.js#L44
|
// https://github.com/yiminghe/css-animation/blob/a5986d73fd7dfce75665337f39b91483d63a4c8c/src/Event.js#L44
|
||||||
window.AnimationEvent = window.AnimationEvent || window.Event;
|
win.AnimationEvent = win.AnimationEvent || win.Event;
|
||||||
window.TransitionEvent = window.TransitionEvent || window.Event;
|
win.TransitionEvent = win.TransitionEvent || win.Event;
|
||||||
|
|
||||||
// ref: https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
// ref: https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||||
// ref: https://github.com/jsdom/jsdom/issues/2524
|
// ref: https://github.com/jsdom/jsdom/issues/2524
|
||||||
Object.defineProperty(window, 'TextEncoder', { writable: true, value: util.TextEncoder });
|
Object.defineProperty(win, 'TextEncoder', { writable: true, value: util.TextEncoder });
|
||||||
Object.defineProperty(window, 'TextDecoder', { writable: true, value: util.TextDecoder });
|
Object.defineProperty(win, 'TextDecoder', { writable: true, value: util.TextDecoder });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable global-require */
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
fillWindowEnv(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
global.requestAnimationFrame = global.requestAnimationFrame || global.setTimeout;
|
||||||
|
global.cancelAnimationFrame = global.cancelAnimationFrame || global.clearTimeout;
|
@ -1,15 +1,20 @@
|
|||||||
|
import path from 'path';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
// Reference: https://github.com/ant-design/ant-design/pull/24003#discussion_r427267386
|
// Reference: https://github.com/ant-design/ant-design/pull/24003#discussion_r427267386
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
|
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import path from 'path';
|
|
||||||
import { globSync } from 'glob';
|
import { globSync } from 'glob';
|
||||||
import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
|
import { configureToMatchImageSnapshot } from 'jest-image-snapshot';
|
||||||
|
import { JSDOM } from 'jsdom';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
import ReactDOMServer from 'react-dom/server';
|
import ReactDOMServer from 'react-dom/server';
|
||||||
|
|
||||||
import { App, ConfigProvider, theme } from '../../components';
|
import { App, ConfigProvider, theme } from '../../components';
|
||||||
|
import { fillWindowEnv } from '../setup';
|
||||||
|
import { render } from '../utils';
|
||||||
|
|
||||||
|
jest.mock('../../components/grid/hooks/useBreakpoint', () => () => ({}));
|
||||||
|
|
||||||
const toMatchImageSnapshot = configureToMatchImageSnapshot({
|
const toMatchImageSnapshot = configureToMatchImageSnapshot({
|
||||||
customSnapshotsDir: `${process.cwd()}/imageSnapshots`,
|
customSnapshotsDir: `${process.cwd()}/imageSnapshots`,
|
||||||
@ -27,6 +32,7 @@ const themes = {
|
|||||||
interface ImageTestOptions {
|
interface ImageTestOptions {
|
||||||
onlyViewport?: boolean;
|
onlyViewport?: boolean;
|
||||||
splitTheme?: boolean;
|
splitTheme?: boolean;
|
||||||
|
ssr?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line jest/no-export
|
// eslint-disable-next-line jest/no-export
|
||||||
@ -35,6 +41,74 @@ export default function imageTest(
|
|||||||
identifier: string,
|
identifier: string,
|
||||||
options: ImageTestOptions,
|
options: ImageTestOptions,
|
||||||
) {
|
) {
|
||||||
|
let doc: Document;
|
||||||
|
let container: HTMLDivElement;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
const dom = new JSDOM('<!DOCTYPE html><body></body></p>', {
|
||||||
|
url: 'http://localhost/',
|
||||||
|
});
|
||||||
|
const win = dom.window;
|
||||||
|
doc = win.document;
|
||||||
|
|
||||||
|
(global as any).window = win;
|
||||||
|
|
||||||
|
// Fill env
|
||||||
|
const keys = [
|
||||||
|
...Object.keys(win),
|
||||||
|
'HTMLElement',
|
||||||
|
'SVGElement',
|
||||||
|
'ShadowRoot',
|
||||||
|
'Element',
|
||||||
|
'File',
|
||||||
|
'Blob',
|
||||||
|
].filter((key) => !(global as any)[key]);
|
||||||
|
|
||||||
|
keys.forEach((key) => {
|
||||||
|
(global as any)[key] = win[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fake Resize Observer
|
||||||
|
global.ResizeObserver = function FakeResizeObserver() {
|
||||||
|
return {
|
||||||
|
observe() {},
|
||||||
|
unobserve() {},
|
||||||
|
disconnect() {},
|
||||||
|
};
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
// Fake promise not called
|
||||||
|
global.fetch = function mockFetch() {
|
||||||
|
return {
|
||||||
|
then() {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
catch() {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
finally() {
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
// Fake matchMedia
|
||||||
|
win.matchMedia = () =>
|
||||||
|
({
|
||||||
|
matches: false,
|
||||||
|
addListener: jest.fn(),
|
||||||
|
removeListener: jest.fn(),
|
||||||
|
}) as any;
|
||||||
|
|
||||||
|
// Fill window
|
||||||
|
fillWindowEnv(win);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
doc.body.innerHTML = `<div id="root"></div>`;
|
||||||
|
container = doc.querySelector<HTMLDivElement>('#root')!;
|
||||||
|
});
|
||||||
|
|
||||||
function test(name: string, suffix: string, themedComponent: React.ReactElement) {
|
function test(name: string, suffix: string, themedComponent: React.ReactElement) {
|
||||||
it(name, async () => {
|
it(name, async () => {
|
||||||
await jestPuppeteer.resetPage();
|
await jestPuppeteer.resetPage();
|
||||||
@ -55,14 +129,30 @@ export default function imageTest(
|
|||||||
|
|
||||||
const cache = createCache();
|
const cache = createCache();
|
||||||
|
|
||||||
|
const emptyStyleHolder = doc.createElement('div');
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<StyleProvider cache={cache}>
|
<StyleProvider cache={cache} container={emptyStyleHolder}>
|
||||||
<App>{themedComponent}</App>
|
<App>{themedComponent}</App>
|
||||||
</StyleProvider>
|
</StyleProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
const html = ReactDOMServer.renderToString(element);
|
let html: string;
|
||||||
const styleStr = extractStyle(cache);
|
let styleStr: string;
|
||||||
|
|
||||||
|
if (options.ssr) {
|
||||||
|
html = ReactDOMServer.renderToString(element);
|
||||||
|
styleStr = extractStyle(cache);
|
||||||
|
} else {
|
||||||
|
const { unmount } = render(element, {
|
||||||
|
container,
|
||||||
|
});
|
||||||
|
html = container.innerHTML;
|
||||||
|
styleStr = extractStyle(cache);
|
||||||
|
|
||||||
|
// We should extract style before unmount
|
||||||
|
unmount();
|
||||||
|
}
|
||||||
|
|
||||||
await page.evaluate(
|
await page.evaluate(
|
||||||
(innerHTML, ssrStyle) => {
|
(innerHTML, ssrStyle) => {
|
||||||
@ -141,6 +231,8 @@ type Options = {
|
|||||||
skip?: boolean | string[];
|
skip?: boolean | string[];
|
||||||
onlyViewport?: boolean | string[];
|
onlyViewport?: boolean | string[];
|
||||||
splitTheme?: boolean | string[];
|
splitTheme?: boolean | string[];
|
||||||
|
/** Use SSR render instead. Only used when the third part deps component */
|
||||||
|
ssr?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line jest/no-export
|
// eslint-disable-next-line jest/no-export
|
||||||
@ -168,6 +260,7 @@ export function imageDemoTest(component: string, options: Options = {}) {
|
|||||||
splitTheme:
|
splitTheme:
|
||||||
options.splitTheme === true ||
|
options.splitTheme === true ||
|
||||||
(Array.isArray(options.splitTheme) && options.splitTheme.some((c) => file.endsWith(c))),
|
(Array.isArray(options.splitTheme) && options.splitTheme.some((c) => file.endsWith(c))),
|
||||||
|
ssr: options.ssr,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable global-require, import/no-dynamic-require, jest/no-export */
|
/* eslint-disable global-require, import/no-dynamic-require, jest/no-export */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ConfigProvider from '../../components/config-provider';
|
import ConfigProvider from '../../components/config-provider';
|
||||||
import { render, waitFakeTimer } from '../utils';
|
import { render, waitFakeTimer } from '../utils';
|
||||||
import { TriggerMockContext } from './demoTestContext';
|
import { TriggerMockContext } from './demoTestContext';
|
||||||
@ -20,14 +21,17 @@ function isSingleNode(node: any): node is Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function rootPropsTest(
|
export default function rootPropsTest(
|
||||||
component: string,
|
component: string | string[],
|
||||||
customizeRender?: (
|
customizeRender?: (
|
||||||
component: React.ComponentType<any> & Record<string, any>,
|
component: React.ComponentType<any> & Record<string, any>,
|
||||||
props: any,
|
props: any,
|
||||||
) => React.ReactNode,
|
) => React.ReactNode,
|
||||||
options?: Options,
|
options?: Options,
|
||||||
) {
|
) {
|
||||||
const Component = require(`../../components/${component}`).default as any;
|
const componentNames = Array.isArray(component) ? component : [component];
|
||||||
|
const [componentName, subComponentName] = componentNames;
|
||||||
|
|
||||||
|
const Component = require(`../../components/${componentName}`).default as any;
|
||||||
const name = options?.name ? `(${options.name})` : '';
|
const name = options?.name ? `(${options.name})` : '';
|
||||||
|
|
||||||
describe(`RootProps${name}`, () => {
|
describe(`RootProps${name}`, () => {
|
||||||
@ -36,6 +40,7 @@ export default function rootPropsTest(
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
passed = false;
|
passed = false;
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
document.body.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -46,7 +51,7 @@ export default function rootPropsTest(
|
|||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rootClassName', async () => {
|
it(['rootClassName', subComponentName].filter((v) => v).join(' '), async () => {
|
||||||
const rootClassName = 'TEST_ROOT_CLS';
|
const rootClassName = 'TEST_ROOT_CLS';
|
||||||
|
|
||||||
if (options?.beforeRender) {
|
if (options?.beforeRender) {
|
||||||
@ -104,7 +109,7 @@ export default function rootPropsTest(
|
|||||||
|
|
||||||
expect(childList.length).toBeGreaterThan(0);
|
expect(childList.length).toBeGreaterThan(0);
|
||||||
if (options?.expectCount) {
|
if (options?.expectCount) {
|
||||||
expect(childList.length).toBe(options.expectCount);
|
expect(childList).toHaveLength(options.expectCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
childList.forEach((ele) => {
|
childList.forEach((ele) => {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import type { ReactElement } from 'react';
|
||||||
|
import React, { createRef, StrictMode } from 'react';
|
||||||
import type { RenderOptions } from '@testing-library/react';
|
import type { RenderOptions } from '@testing-library/react';
|
||||||
import { act, render } from '@testing-library/react';
|
import { act, render } from '@testing-library/react';
|
||||||
import MockDate from 'mockdate';
|
import MockDate from 'mockdate';
|
||||||
import { _rs as onEsResize } from 'rc-resize-observer/es/utils/observerUtil';
|
import { _rs as onEsResize } from 'rc-resize-observer/es/utils/observerUtil';
|
||||||
import { _rs as onLibResize } from 'rc-resize-observer/lib/utils/observerUtil';
|
import { _rs as onLibResize } from 'rc-resize-observer/lib/utils/observerUtil';
|
||||||
import type { ReactElement } from 'react';
|
|
||||||
import React, { StrictMode } from 'react';
|
|
||||||
|
|
||||||
export function assertsExist<T>(item?: T): asserts item is T {
|
export function assertsExist<T>(item?: T): asserts item is T {
|
||||||
expect(item).not.toBeUndefined();
|
expect(item).not.toBeUndefined();
|
||||||
@ -33,7 +33,7 @@ const customRender = (ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>
|
|||||||
render(ui, { wrapper: StrictMode, ...options });
|
render(ui, { wrapper: StrictMode, ...options });
|
||||||
|
|
||||||
export function renderHook<T>(func: () => T): { result: React.RefObject<T> } {
|
export function renderHook<T>(func: () => T): { result: React.RefObject<T> } {
|
||||||
const result = React.createRef<T>();
|
const result = createRef<T>();
|
||||||
|
|
||||||
const Demo: React.FC = () => {
|
const Demo: React.FC = () => {
|
||||||
(result as any).current = func();
|
(result as any).current = func();
|
||||||
@ -58,7 +58,7 @@ export { pureRender, customRender as render };
|
|||||||
export const triggerResize = (target: Element) => {
|
export const triggerResize = (target: Element) => {
|
||||||
const originGetBoundingClientRect = target.getBoundingClientRect;
|
const originGetBoundingClientRect = target.getBoundingClientRect;
|
||||||
|
|
||||||
target.getBoundingClientRect = () => ({ width: 510, height: 903 } as DOMRect);
|
target.getBoundingClientRect = () => ({ width: 510, height: 903 }) as DOMRect;
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
onLibResize([{ target } as ResizeObserverEntry]);
|
onLibResize([{ target } as ResizeObserverEntry]);
|
||||||
|
Loading…
Reference in New Issue
Block a user