forked from ant-design/pro-components
-
Notifications
You must be signed in to change notification settings - Fork 0
/
demo.tsx
115 lines (99 loc) · 3.56 KB
/
demo.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import React from 'react';
import glob from 'glob';
import type { render } from 'enzyme';
import { mount } from 'enzyme';
import MockDate from 'mockdate';
import moment from 'moment';
import { waitForComponentToPaint } from './util';
type CheerIO = ReturnType<typeof render>;
type CheerIOElement = CheerIO[0];
// We should avoid use it in 4.0. Reopen if can not handle this.
const USE_REPLACEMENT = false;
const testDist = process.env.LIB_DIR === 'dist';
/**
* Rc component will generate id for aria usage. It's created as `test-uuid` when env === 'test'. Or
* `f7fa7a3c-a675-47bc-912e-0c45fb6a74d9`(randomly) when not test env. So we need hack of this to
* modify the `aria-controls`.
*/
function ariaConvert(wrapper: CheerIO) {
if (!testDist || !USE_REPLACEMENT) return wrapper;
const matches = new Map();
function process(entry: any) {
const { attribs, children } = entry;
if (matches.has(entry)) return;
matches.set(entry, true);
// Change aria
if (attribs && attribs['aria-controls']) {
attribs['aria-controls'] = ''; // Remove all the aria to keep render sync in jest & jest node
}
// Loop children
if (!children) return;
(Array.isArray(children) ? children : [children]).forEach(process);
}
wrapper.each((_: any, entry: CheerIOElement) => process(entry));
return wrapper;
}
type Options = {
skip?: boolean;
};
function demoTest(component: string, options: Options = {}) {
const LINE_STR_COUNT = 20;
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {});
// Mock offsetHeight
// @ts-expect-error
const originOffsetHeight = Object.getOwnPropertyDescriptor(
HTMLElement.prototype,
'offsetHeight',
).get;
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
get() {
let html = this.innerHTML;
html = html.replace(/<[^>]*>/g, '');
const lines = Math.ceil(html.length / LINE_STR_COUNT);
return lines * 16;
},
});
// Mock getComputedStyle
const originGetComputedStyle = window.getComputedStyle;
window.getComputedStyle = (ele) => {
const style = originGetComputedStyle(ele);
style.lineHeight = '16px';
return style;
};
afterEach(() => {
logSpy.mockReset();
errorSpy.mockReset();
});
afterAll(() => {
errorSpy.mockRestore();
logSpy.mockReset();
Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
get: originOffsetHeight,
});
window.getComputedStyle = originGetComputedStyle;
});
// 支持 demos 下的所有非_开头的tsx文件
const files = glob.sync(`./packages/${component}/**/demos/**/[!_]*.tsx`);
files.push(...glob.sync(`./${component}/**/**/demos/[!_]*.tsx`));
describe(`${component} demos`, () => {
files.forEach((file) => {
let testMethod = options.skip === true ? test.skip : test;
if (Array.isArray(options.skip) && options.skip.some((c) => file.includes(c))) {
testMethod = test.skip;
}
testMethod(`📸 renders ${file} correctly`, async () => {
MockDate.set(moment('2016-11-22').valueOf());
const Demo = require(`.${file}`).default; // eslint-disable-line global-require, import/no-dynamic-require
const wrapper = mount(<Demo />);
await waitForComponentToPaint(wrapper, ['table', 'list'].includes(component) ? 1200 : 160);
// Convert aria related content
const dom = wrapper.render();
ariaConvert(dom);
expect(dom).toMatchSnapshot();
MockDate.reset();
});
});
});
}
export default demoTest;