-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
/
TestViewer.js
85 lines (76 loc) · 2.71 KB
/
TestViewer.js
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
import React from 'react';
import PropTypes from 'prop-types';
import { useFakeTimers } from 'sinon';
import { withStyles } from '@material-ui/core/styles';
const styles = (theme) => ({
'@global': {
html: {
WebkitFontSmoothing: 'antialiased', // Antialiasing.
MozOsxFontSmoothing: 'grayscale', // Antialiasing.
// Do the opposite of the docs in order to help catching issues.
boxSizing: 'content-box',
},
'*, *::before, *::after': {
boxSizing: 'inherit',
// Disable transitions to avoid flaky screenshots
transition: 'none !important',
animation: 'none !important',
},
body: {
margin: 0,
overflowX: 'hidden',
},
},
root: {
backgroundColor: theme.palette.background.default,
display: 'inline-block',
padding: theme.spacing(1),
},
});
function TestViewer(props) {
const { children, classes } = props;
// We're simulating `act(() => ReactDOM.render(children))`
// In the end children passive effects should've been flushed.
// React doesn't have any such guarantee outside of `act()` so we're approximating it.
const [ready, setReady] = React.useState(false);
React.useEffect(() => {
function handleFontsEvent(event) {
if (event.type === 'loading') {
setReady(false);
} else if (event.type === 'loadingdone') {
// Don't know if there could be multiple loaded events after we started loading multiple times.
// So make sure we're only ready if fonts are actually ready.
if (document.fonts.status === 'loaded') {
setReady(true);
}
}
}
document.fonts.addEventListener('loading', handleFontsEvent);
document.fonts.addEventListener('loadingdone', handleFontsEvent);
// Use a "real timestamp" so that we see a useful date instead of "00:00"
// eslint-disable-next-line react-hooks/rules-of-hooks -- not a React hook
const clock = useFakeTimers(new Date('Mon Aug 18 14:11:54 2014 -0500'));
// and wait `load-css` timeouts to be flushed
clock.runToLast();
// In case the child triggered font fetching we're not ready yet.
// The fonts event handler will mark the test as ready on `loadingdone`
if (document.fonts.status === 'loaded') {
setReady(true);
}
return () => {
document.fonts.removeEventListener('loading', handleFontsEvent);
document.fonts.removeEventListener('loadingdone', handleFontsEvent);
clock.restore();
};
}, []);
return (
<div aria-busy={!ready} data-testid="testcase" className={classes.root}>
{children}
</div>
);
}
TestViewer.propTypes = {
children: PropTypes.node.isRequired,
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(TestViewer);