1 |
|
2 |
|
3 | import React from 'react'
|
4 | import ReactWrapper from 'enzyme/build/ReactWrapper'
|
5 | import { createWaitForElement } from '@oskarer/enzyme-wait'
|
6 | import Enzyme, { mount } from 'enzyme'
|
7 | import Adapter from 'enzyme-adapter-react-16'
|
8 | import TestRenderer from 'react-test-renderer'
|
9 | import isArray from 'lodash/isArray'
|
10 |
|
11 | const DEPRECATED = process.env.DEPRECATED
|
12 |
|
13 | init()
|
14 |
|
15 | function init () {
|
16 | Enzyme.configure({ adapter: new Adapter() })
|
17 |
|
18 | ReactWrapper.prototype.waitFor = function (selector) {
|
19 | return createWaitForElement(selector)(this)
|
20 | }
|
21 | }
|
22 |
|
23 | export function unmount () {
|
24 | if (globalEnzymeNode && globalEnzymeNode.unmount) {
|
25 | globalEnzymeNode.unmount()
|
26 | globalEnzymeNode = undefined
|
27 | }
|
28 | if (globalTestRenderer && globalTestRenderer.unmount) {
|
29 | globalTestRenderer.unmount()
|
30 | globalTestRenderer = undefined
|
31 | }
|
32 | }
|
33 |
|
34 | export function convertToOldSubscribeParams (fn) {
|
35 | return (...args) => {
|
36 | let data = fn(...args)
|
37 | let res = {}
|
38 | for (let key in data) {
|
39 | if (data[key] == null) continue
|
40 | if (data[key].__subscriptionType) {
|
41 | res[key] = data[key].params
|
42 | } else {
|
43 | throw new Error('No __subscriptionType specified')
|
44 | }
|
45 | }
|
46 | return res
|
47 | }
|
48 | }
|
49 |
|
50 | export function convertToHooksSubscribeParams (fn) {
|
51 | return (...args) => {
|
52 | let { items: { __subscriptionType: type, params } } = fn(...args)
|
53 | let useFn
|
54 | switch (type) {
|
55 | case 'Doc':
|
56 | useFn = useDoc
|
57 | break
|
58 | case 'Query':
|
59 | case 'QueryExtra':
|
60 | useFn = useQuery
|
61 | break
|
62 | case 'Local':
|
63 | useFn = useLocal
|
64 | break
|
65 | case 'Value':
|
66 | useFn = useValue
|
67 | break
|
68 | case 'Api':
|
69 | useFn = useApi
|
70 | break
|
71 | default:
|
72 | throw new Error('Unknown useFn type: ' + type)
|
73 | }
|
74 | if (!isArray(params)) params = [params]
|
75 | return useFn(...params)
|
76 | }
|
77 | }
|
78 |
|
79 | export async function initSimple (initialProps, subscribeFn) {
|
80 | if (typeof initialProps === 'function') {
|
81 | subscribeFn = initialProps
|
82 | initialProps = {}
|
83 | }
|
84 | if (DEPRECATED) subscribeFn = convertToOldSubscribeParams(subscribeFn)
|
85 | let Subscribed = subscribe(subscribeFn)(Simple())
|
86 | let w = mount(<Subscribed {...initialProps} />)
|
87 | globalEnzymeNode = w
|
88 | await w.waitFor('.Simple')
|
89 | w.getItems = function () {
|
90 | return getSimpleItems(this)
|
91 | }
|
92 | Object.defineProperty(w, 'items', {
|
93 | get: function () {
|
94 | return this.getItems()
|
95 | }
|
96 | })
|
97 | w.nextRender = function (...args) {
|
98 | return nextRender(this, ...args)
|
99 | }
|
100 | return w
|
101 | }
|
102 |
|
103 | export function getSimpleItems (w) {
|
104 | let text = w.find('.Simple').text()
|
105 | if (!text) return []
|
106 | return text.split(',')
|
107 | }
|
108 |
|
109 | export async function initComplex (initialProps, subscribeFn) {
|
110 | if (typeof initialProps === 'function') {
|
111 | subscribeFn = initialProps
|
112 | initialProps = {}
|
113 | }
|
114 | if (DEPRECATED) subscribeFn = convertToOldSubscribeParams(subscribeFn)
|
115 | let Subscribed = subscribe(subscribeFn)(Complex())
|
116 | let w = mount(<Subscribed {...initialProps} />)
|
117 | globalEnzymeNode = w
|
118 |
|
119 | await w.waitFor('.Complex')
|
120 | w.getItems = function () {
|
121 | return getComplexItems(this)
|
122 | }
|
123 | Object.defineProperty(w, 'items', {
|
124 | get: function () {
|
125 | return this.getItems()
|
126 | }
|
127 | })
|
128 | w.nextRender = function (...args) {
|
129 | return nextRender(this, ...args)
|
130 | }
|
131 | return w
|
132 | }
|
133 |
|
134 | export function getComplexItems (w) {
|
135 | let res = []
|
136 | for (let i = 0; i < 10; i++) {
|
137 | let el = w.find(`.items${i}`)
|
138 | if (!el.exists()) break
|
139 | let text = el.text()
|
140 | let value
|
141 | if (!text) {
|
142 | value = []
|
143 | } else {
|
144 | value = text.split(',')
|
145 | }
|
146 | res.push(value)
|
147 | }
|
148 | return res
|
149 | }
|
150 |
|
151 | export async function tInitHooksComplex (initialProps = {}) {
|
152 | let Component = HooksComplex()
|
153 | globalTestRenderer = TestRenderer.create(<Component {...initialProps} />)
|
154 | let t = globalTestRenderer
|
155 | t.getItems = function () {
|
156 | return tGetHooksComplexItems(this)
|
157 | }
|
158 | Object.defineProperty(t, 'items', {
|
159 | get: function () {
|
160 | return this.getItems()
|
161 | }
|
162 | })
|
163 | t.nextRender = function (...args) {
|
164 | return tNextRender(this, ...args)
|
165 | }
|
166 | return t
|
167 | }
|
168 |
|
169 | export function tGetHooksComplexItems (t) {
|
170 | let res = {}
|
171 | t.root.findAllByProps({ className: 'items' }).forEach(node => {
|
172 | let name = node.props.title
|
173 | let text = (node.children && node.children[0]) || ''
|
174 | res[name] = text.split(',')
|
175 | })
|
176 | return res
|
177 | }
|
178 |
|
179 | export async function tInitHooksSimple (initialProps, useFn) {
|
180 | if (typeof initialProps === 'function') {
|
181 | useFn = initialProps
|
182 | initialProps = {}
|
183 | }
|
184 | let Component = HooksSimple(useFn)
|
185 | globalTestRenderer = TestRenderer.create(<Component {...initialProps} />)
|
186 | let t = globalTestRenderer
|
187 | t.getItems = function () {
|
188 | return tGetSimpleItems(this)
|
189 | }
|
190 | Object.defineProperty(t, 'items', {
|
191 | get: function () {
|
192 | return this.getItems()
|
193 | }
|
194 | })
|
195 | t.nextRender = function (...args) {
|
196 | return tNextRender(this, ...args)
|
197 | }
|
198 | t.setProps = function (props = {}) {
|
199 | t.update(<Component {...props} />)
|
200 | }
|
201 | return t
|
202 | }
|
203 |
|
204 | export function tGetSimpleItems (t) {
|
205 | let node = t.root.findByProps({ className: 'items' })
|
206 | let text = (node.children && node.children[0]) || ''
|
207 | return text.split(',').filter(Boolean)
|
208 | }
|
209 |
|
210 | export async function tNextRender (t, count = 1, fn, params) {
|
211 | if (typeof count === 'function') {
|
212 | params = fn
|
213 | fn = count
|
214 | count = 1
|
215 | }
|
216 | if (fn && typeof fn !== 'function') {
|
217 | params = fn
|
218 | fn = undefined
|
219 | }
|
220 | if (count && typeof count !== 'number') {
|
221 | params = count
|
222 | count = 1
|
223 | }
|
224 | let { index } = params || {}
|
225 | if (index == null) {
|
226 | let currentRender = t.root.findByProps({ className: 'root' }).props.title
|
227 | if (!currentRender) throw new Error("Component didn't render")
|
228 | currentRender = ~~currentRender
|
229 | index = currentRender + count
|
230 | }
|
231 | let selector = { className: 'root', title: '' + index }
|
232 | typeof DEBUG !== 'undefined' && console.log('wait for:', selector)
|
233 | if (fn) fn()
|
234 | let found = false
|
235 | while (!found) {
|
236 | try {
|
237 | t.root.findByProps(selector)
|
238 | found = true
|
239 | } catch (e) {
|
240 | await new Promise(resolve => setTimeout(resolve, 10))
|
241 | }
|
242 | }
|
243 | }
|
244 |
|
245 | export async function nextRender (w, count = 1, fn, params) {
|
246 | if (typeof count === 'function') {
|
247 | params = fn
|
248 | fn = count
|
249 | count = 1
|
250 | }
|
251 | if (fn && typeof fn !== 'function') {
|
252 | params = fn
|
253 | fn = undefined
|
254 | }
|
255 | if (count && typeof count !== 'number') {
|
256 | params = count
|
257 | count = 1
|
258 | }
|
259 | let { index } = params || {}
|
260 | if (index == null) {
|
261 | let currentRender = w.html().match(/RENDER-(\d+)/)[1]
|
262 | if (!currentRender) throw new Error("Component didn't render")
|
263 | currentRender = ~~currentRender
|
264 | index = currentRender + count
|
265 | }
|
266 | let selector = `.RENDER-${index}`
|
267 | typeof DEBUG !== 'undefined' && console.log('wait for:', selector)
|
268 | if (fn) fn()
|
269 | await w.waitFor(selector)
|
270 | }
|