|
1 |
| -import React from 'react' |
2 |
| -import ReactDOM from 'react-dom' |
3 |
| -import { |
4 |
| - getQueriesForElement, |
5 |
| - prettyDOM, |
6 |
| - fireEvent as dtlFireEvent, |
7 |
| - configure as configureDTL, |
8 |
| -} from '@testing-library/dom' |
9 |
| -import act, {asyncAct} from './act-compat' |
10 |
| - |
11 |
| -configureDTL({ |
12 |
| - asyncWrapper: async cb => { |
13 |
| - let result |
14 |
| - await asyncAct(async () => { |
15 |
| - result = await cb() |
16 |
| - }) |
17 |
| - return result |
18 |
| - }, |
19 |
| -}) |
20 |
| - |
21 |
| -const mountedContainers = new Set() |
22 |
| - |
23 |
| -function render( |
24 |
| - ui, |
25 |
| - { |
26 |
| - container, |
27 |
| - baseElement = container, |
28 |
| - queries, |
29 |
| - hydrate = false, |
30 |
| - wrapper: WrapperComponent, |
31 |
| - } = {}, |
32 |
| -) { |
33 |
| - if (!baseElement) { |
34 |
| - // default to document.body instead of documentElement to avoid output of potentially-large |
35 |
| - // head elements (such as JSS style blocks) in debug output |
36 |
| - baseElement = document.body |
37 |
| - } |
38 |
| - if (!container) { |
39 |
| - container = baseElement.appendChild(document.createElement('div')) |
40 |
| - } |
41 |
| - |
42 |
| - // we'll add it to the mounted containers regardless of whether it's actually |
43 |
| - // added to document.body so the cleanup method works regardless of whether |
44 |
| - // they're passing us a custom container or not. |
45 |
| - mountedContainers.add(container) |
46 |
| - |
47 |
| - const wrapUiIfNeeded = innerElement => |
48 |
| - WrapperComponent |
49 |
| - ? React.createElement(WrapperComponent, null, innerElement) |
50 |
| - : innerElement |
51 |
| - |
52 |
| - act(() => { |
53 |
| - if (hydrate) { |
54 |
| - ReactDOM.hydrate(wrapUiIfNeeded(ui), container) |
55 |
| - } else { |
56 |
| - ReactDOM.render(wrapUiIfNeeded(ui), container) |
57 |
| - } |
58 |
| - }) |
59 |
| - |
60 |
| - return { |
61 |
| - container, |
62 |
| - baseElement, |
63 |
| - // eslint-disable-next-line no-console |
64 |
| - debug: (el = baseElement) => console.log(prettyDOM(el)), |
65 |
| - unmount: () => ReactDOM.unmountComponentAtNode(container), |
66 |
| - rerender: rerenderUi => { |
67 |
| - render(wrapUiIfNeeded(rerenderUi), {container, baseElement}) |
68 |
| - // Intentionally do not return anything to avoid unnecessarily complicating the API. |
69 |
| - // folks can use all the same utilities we return in the first place that are bound to the container |
70 |
| - }, |
71 |
| - asFragment: () => { |
72 |
| - /* istanbul ignore if (jsdom limitation) */ |
73 |
| - if (typeof document.createRange === 'function') { |
74 |
| - return document |
75 |
| - .createRange() |
76 |
| - .createContextualFragment(container.innerHTML) |
77 |
| - } |
78 |
| - |
79 |
| - const template = document.createElement('template') |
80 |
| - template.innerHTML = container.innerHTML |
81 |
| - return template.content |
82 |
| - }, |
83 |
| - ...getQueriesForElement(baseElement, queries), |
84 |
| - } |
85 |
| -} |
86 |
| - |
87 |
| -function cleanup() { |
88 |
| - mountedContainers.forEach(cleanupAtContainer) |
89 |
| -} |
90 |
| - |
91 |
| -// maybe one day we'll expose this (perhaps even as a utility returned by render). |
92 |
| -// but let's wait until someone asks for it. |
93 |
| -function cleanupAtContainer(container) { |
94 |
| - ReactDOM.unmountComponentAtNode(container) |
95 |
| - if (container.parentNode === document.body) { |
96 |
| - document.body.removeChild(container) |
97 |
| - } |
98 |
| - mountedContainers.delete(container) |
99 |
| -} |
100 |
| - |
101 |
| -// react-testing-library's version of fireEvent will call |
102 |
| -// dom-testing-library's version of fireEvent wrapped inside |
103 |
| -// an "act" call so that after all event callbacks have been |
104 |
| -// been called, the resulting useEffect callbacks will also |
105 |
| -// be called. |
106 |
| -function fireEvent(...args) { |
107 |
| - let returnValue |
108 |
| - act(() => { |
109 |
| - returnValue = dtlFireEvent(...args) |
110 |
| - }) |
111 |
| - return returnValue |
112 |
| -} |
113 |
| - |
114 |
| -Object.keys(dtlFireEvent).forEach(key => { |
115 |
| - fireEvent[key] = (...args) => { |
116 |
| - let returnValue |
117 |
| - act(() => { |
118 |
| - returnValue = dtlFireEvent[key](...args) |
119 |
| - }) |
120 |
| - return returnValue |
121 |
| - } |
122 |
| -}) |
123 |
| - |
124 |
| -// React event system tracks native mouseOver/mouseOut events for |
125 |
| -// running onMouseEnter/onMouseLeave handlers |
126 |
| -// @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/EnterLeaveEventPlugin.js#L24-L31 |
127 |
| -fireEvent.mouseEnter = fireEvent.mouseOver |
128 |
| -fireEvent.mouseLeave = fireEvent.mouseOut |
129 |
| - |
130 |
| -fireEvent.select = (node, init) => { |
131 |
| - // React tracks this event only on focused inputs |
132 |
| - node.focus() |
133 |
| - |
134 |
| - // React creates this event when one of the following native events happens |
135 |
| - // - contextMenu |
136 |
| - // - mouseUp |
137 |
| - // - dragEnd |
138 |
| - // - keyUp |
139 |
| - // - keyDown |
140 |
| - // so we can use any here |
141 |
| - // @link https://github.com/facebook/react/blob/b87aabdfe1b7461e7331abb3601d9e6bb27544bc/packages/react-dom/src/events/SelectEventPlugin.js#L203-L224 |
142 |
| - fireEvent.keyUp(node, init) |
143 |
| -} |
| 1 | +import {asyncAct} from './act-compat' |
| 2 | +import {cleanup} from './pure' |
144 | 3 |
|
145 | 4 | // if we're running in a test runner that supports afterEach
|
146 | 5 | // then we'll automatically run cleanup afterEach test
|
147 | 6 | // this ensures that tests run in isolation from each other
|
148 |
| -if (typeof afterEach === 'function' && !process.env.RTL_SKIP_CLEANUP) { |
| 7 | +// if you don't like this then either import the `pure` module |
| 8 | +// or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'. |
| 9 | +if (typeof afterEach === 'function' && !process.env.RTL_SKIP_AUTO_CLEANUP) { |
149 | 10 | afterEach(async () => {
|
150 | 11 | await asyncAct(async () => {})
|
151 | 12 | cleanup()
|
152 | 13 | })
|
153 | 14 | }
|
154 | 15 |
|
155 |
| -// just re-export everything from dom-testing-library |
156 |
| -export * from '@testing-library/dom' |
157 |
| -export {render, cleanup, fireEvent, act} |
158 |
| - |
159 |
| -// NOTE: we're not going to export asyncAct because that's our own compatibility |
160 |
| -// thing for people using [email protected]. Anyone else doesn't need it and |
161 |
| -// people should just upgrade anyway. |
162 |
| - |
163 |
| -/* eslint func-name-matching:0 */ |
| 16 | +export * from './pure' |
0 commit comments