react-component-snapshot 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,30 +8,71 @@ import snapshotOf from 'react-component-snapshot'
8
8
 
9
9
  ## With `@testing-library/react`
10
10
 
11
+ Get a snapshot of the component element from the `render` result
12
+
11
13
  ```javascript
12
14
  import {
13
15
  render
14
16
  } from '@testing-library/react'
15
17
 
16
- import snapshotOf from 'react-component-snapshot'
18
+ import {
19
+ toSnapshot
20
+ } from 'react-component-snapshot'
17
21
 
18
- describe('snapshotOf', () => {
19
- class Component extends React.Component {
20
- render () {
21
- return <div />
22
+ describe('`toSnapshot`', () => {
23
+ it('matches the snapshot', () => {
24
+ function Component () {
25
+ return (
26
+ <div className='grand-parent'>
27
+ <div className='parent'>
28
+ <div className='child'>
29
+ TEXT
30
+ </div>
31
+ </div>
32
+ </div>
33
+ )
22
34
  }
35
+
36
+ expect(toSnapshot(render(
37
+ <Component />
38
+ )))
39
+ .toMatchSnapshot()
40
+ })
41
+ })
42
+ ```
43
+
44
+ Get a snapshot of any component element
45
+
46
+ ```javascript
47
+ import {
48
+ render
49
+ } from '@testing-library/react'
50
+
51
+ import {
52
+ snapshotOf
53
+ } from 'react-component-snapshot'
54
+
55
+ describe('`snapshotOf`', () => {
56
+ function Component () {
57
+ return (
58
+ <div className='grand-parent'>
59
+ <div className='parent'>
60
+ <div className='child'>
61
+ TEXT
62
+ </div>
63
+ </div>
64
+ </div>
65
+ )
23
66
  }
24
67
 
25
68
  it('matches the snapshot', () => {
26
69
  const {
27
- container: {
28
- firstElementChild: element
29
- }
70
+ container
30
71
  } = render(
31
72
  <Component />
32
73
  )
33
74
 
34
- expect(snapshotOf(element))
75
+ expect(snapshotOf(container.querySelector('.child')))
35
76
  .toMatchSnapshot()
36
77
  })
37
78
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-component-snapshot",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Transform a React component to match its snapshot in Jest",
5
5
  "keywords": [
6
6
  "react",
@@ -0,0 +1,239 @@
1
+ /**
2
+ * @typedef {import('@testing-library/react').RenderResult} RenderType
3
+ * @typedef {ReactComponentSnapshotTypes.FiberNode} FiberNode
4
+ */
5
+
6
+ import {
7
+ getComponentNameFromFiber as getType
8
+ } from 'react-component-name'
9
+
10
+ import {
11
+ REACT_COMPONENT_SNAPSHOT
12
+ } from './symbols.mjs'
13
+
14
+ /**
15
+ * @param {unknown} v
16
+ * @returns {v is object}
17
+ */
18
+ function isObject (v) {
19
+ return (v || false) instanceof Object && !Array.isArray(v)
20
+ }
21
+
22
+ /**
23
+ * @param {PropertyKey} key
24
+ * @returns {boolean}
25
+ */
26
+ function isReactFiberKey (key) {
27
+ return String(key).startsWith('__reactFiber$')
28
+ }
29
+
30
+ /**
31
+ * @param {PropertyKey} key
32
+ * @returns {boolean}
33
+ */
34
+ function isReactPropsKey (key) {
35
+ return String(key).startsWith('__reactProps$')
36
+ }
37
+
38
+ /**
39
+ * @param {Element | Text | React.Component<any, any, any>} stateNode
40
+ * @returns {string | undefined}
41
+ */
42
+ function getReactFiberKey (stateNode) {
43
+ return (
44
+ Object.keys(stateNode)
45
+ .find(isReactFiberKey)
46
+ )
47
+ }
48
+
49
+ /**
50
+ * @param {Element | Text | React.Component<any, any, any>} stateNode
51
+ * @returns {string | undefined}
52
+ */
53
+ function getReactPropsKey (stateNode) {
54
+ return (
55
+ Object.keys(stateNode)
56
+ .find(isReactPropsKey)
57
+ )
58
+ }
59
+
60
+ /**
61
+ * @param {Element | Text | React.Component<any, any, any>} stateNode
62
+ * @returns {Record<PropertyKey, unknown> | null}
63
+ */
64
+ export function getStateNodeFiber (stateNode) {
65
+ const key = getReactFiberKey(stateNode)
66
+
67
+ if (key) {
68
+ const { // @ts-expect-error
69
+ [key]: fiber = null
70
+ } = stateNode
71
+
72
+ return fiber
73
+ }
74
+
75
+ return null
76
+ }
77
+
78
+ /**
79
+ * @param {React.Component<any, any, any> | Element | Text} stateNode
80
+ * @returns {Record<PropertyKey, unknown> | null}
81
+ */
82
+ export function getStateNodeProps (stateNode) {
83
+ const key = getReactPropsKey(stateNode)
84
+
85
+ if (key) {
86
+ const { // @ts-expect-error
87
+ [key]: props = null
88
+ } = stateNode
89
+
90
+ return props
91
+ }
92
+
93
+ return null
94
+ }
95
+
96
+ /**
97
+ * @param {Element} element
98
+ * @returns {FiberNode | null}
99
+ */
100
+ export function getFiber (element) {
101
+ const key = getReactFiberKey(element)
102
+
103
+ if (key) {
104
+ const { // @ts-expect-error
105
+ [key]: fiber = null
106
+ } = element
107
+
108
+ return fiber
109
+ }
110
+
111
+ return null
112
+ }
113
+
114
+ /**
115
+ * @param {FiberNode} fiberNode
116
+ * @returns {FiberNode[]}
117
+ */
118
+ function getSiblings (fiberNode) {
119
+ const siblings = []
120
+
121
+ let sibling = fiberNode.sibling
122
+ while (sibling) {
123
+ siblings.push(sibling)
124
+ sibling = sibling.sibling
125
+ }
126
+
127
+ return siblings
128
+ }
129
+
130
+ /**
131
+ * @param {FiberNode} fiberNode
132
+ * @returns {Record<PropertyKey, unknown>}
133
+ */
134
+ function getProps (fiberNode) {
135
+ const stateNode = fiberNode.stateNode
136
+
137
+ /**
138
+ * State node may be null on class components
139
+ */
140
+ if (stateNode) {
141
+ const props = getStateNodeProps(stateNode) ?? {}
142
+
143
+ return (
144
+ Object.fromEntries(
145
+ Object.entries(props)
146
+ .filter(([key]) => key !== 'children')
147
+ .filter(([key, value]) => {
148
+ if (isObject(value)) return !('current' in value)
149
+ return true
150
+ })
151
+ )
152
+ )
153
+ }
154
+
155
+ return {}
156
+ }
157
+
158
+ /**
159
+ * @param {FiberNode} fiberNode
160
+ * @returns {Array<string | FiberNode>}
161
+ */
162
+ function getChildrenOf (fiberNode) {
163
+ const child = fiberNode.child
164
+
165
+ if (child) {
166
+ const siblings = getSiblings(child)
167
+
168
+ return [child].concat(siblings).map((child) => {
169
+ const stateNode = child.stateNode
170
+
171
+ if (stateNode instanceof Text) {
172
+ return stateNode.data
173
+ }
174
+
175
+ return child
176
+ })
177
+ }
178
+
179
+ const stateNode = fiberNode.stateNode
180
+
181
+ if (stateNode) {
182
+ /**
183
+ * Get the text as a prop from the instance
184
+ */
185
+ const {
186
+ children
187
+ } = getStateNodeProps(stateNode) ?? {}
188
+
189
+ if (typeof children === 'string') {
190
+ return [children]
191
+ }
192
+ }
193
+
194
+ return []
195
+ }
196
+
197
+ /**
198
+ * @param {FiberNode | string} child
199
+ * @returns {string | Record<PropertyKey, unknown>}
200
+ */
201
+ function toChildren (child) {
202
+ if (typeof child === 'string') return child
203
+
204
+ return (
205
+ getSnapshot(child)
206
+ )
207
+ }
208
+
209
+ /**
210
+ * @param {FiberNode} fiberNode
211
+ * @returns {Array<string | Record<PropertyKey, unknown>>}
212
+ */
213
+ function getChildren (fiberNode) {
214
+ return (
215
+ getChildrenOf(fiberNode)
216
+ .map(toChildren)
217
+ )
218
+ }
219
+
220
+ /**
221
+ * @param {FiberNode} fiberNode
222
+ * @returns {Record<PropertyKey, unknown>}
223
+ */
224
+ export default function getSnapshot (fiberNode) {
225
+ const type = getType(fiberNode)
226
+ const props = getProps(fiberNode)
227
+ const children = getChildren(fiberNode)
228
+
229
+ return (
230
+ Object.defineProperty({
231
+ type,
232
+ props,
233
+ children
234
+ },
235
+ '$$typeof', {
236
+ value: REACT_COMPONENT_SNAPSHOT
237
+ })
238
+ )
239
+ }
package/src/index.mjs CHANGED
@@ -3,95 +3,9 @@
3
3
  * @typedef {ReactComponentSnapshotTypes.FiberNode} FiberNode
4
4
  */
5
5
 
6
- import {
7
- getComponentNameFromFiber as getType
8
- } from 'react-component-name'
9
-
10
- import {
11
- REACT_COMPONENT_SNAPSHOT
12
- } from './symbols.mjs'
13
-
14
- /**
15
- * @param {unknown} v
16
- * @returns {v is object}
17
- */
18
- function isObject (v) {
19
- return (v || false) instanceof Object && !Array.isArray(v)
20
- }
21
-
22
- /**
23
- * @param {PropertyKey} key
24
- * @returns {boolean}
25
- */
26
- export function isReactFiberKey (key) {
27
- return String(key).startsWith('__reactFiber$')
28
- }
29
-
30
- /**
31
- * @param {PropertyKey} key
32
- * @returns {boolean}
33
- */
34
- export function isReactPropsKey (key) {
35
- return String(key).startsWith('__reactProps$')
36
- }
37
-
38
- /**
39
- * @param {Element | Text | React.Component<any, any, any>} stateNode
40
- * @returns {string | undefined}
41
- */
42
- export function getReactFiberKey (stateNode) {
43
- return (
44
- Object.keys(stateNode)
45
- .find(isReactFiberKey)
46
- )
47
- }
48
-
49
- /**
50
- * @param {Element | Text | React.Component<any, any, any>} stateNode
51
- * @returns {string | undefined}
52
- */
53
- export function getReactPropsKey (stateNode) {
54
- return (
55
- Object.keys(stateNode)
56
- .find(isReactPropsKey)
57
- )
58
- }
59
-
60
- /**
61
- * @param {Element | Text | React.Component<any, any, any>} stateNode
62
- * @returns {Record<PropertyKey, unknown> | null}
63
- */
64
- export function getStateNodeFiber (stateNode) {
65
- const key = getReactFiberKey(stateNode)
66
-
67
- if (key) {
68
- const { // @ts-expect-error
69
- [key]: fiber = null
70
- } = stateNode
71
-
72
- return fiber
73
- }
74
-
75
- return null
76
- }
77
-
78
- /**
79
- * @param {React.Component<any, any, any> | Element | Text} stateNode
80
- * @returns {Record<PropertyKey, unknown> | null}
81
- */
82
- export function getStateNodeProps (stateNode) {
83
- const key = getReactPropsKey(stateNode)
84
-
85
- if (key) {
86
- const { // @ts-expect-error
87
- [key]: props = null
88
- } = stateNode
89
-
90
- return props
91
- }
92
-
93
- return null
94
- }
6
+ import getSnapshot, {
7
+ getFiber
8
+ } from './fiber/index.mjs'
95
9
 
96
10
  /**
97
11
  * @param {RenderType} render
@@ -149,7 +63,7 @@ export function toSnapshotFromRender (render) {
149
63
 
150
64
  if (fiberNode) {
151
65
  return (
152
- transform(fiberNode)
66
+ getSnapshot(fiberNode)
153
67
  )
154
68
  }
155
69
  }
@@ -169,7 +83,7 @@ export function toSnapshotFromContainerElement (containerElement) {
169
83
 
170
84
  if (fiberNode) {
171
85
  return (
172
- transform(fiberNode)
86
+ getSnapshot(fiberNode)
173
87
  )
174
88
  }
175
89
  }
@@ -178,7 +92,7 @@ export function toSnapshotFromContainerElement (containerElement) {
178
92
  }
179
93
 
180
94
  /**
181
- * @param {Element | null} componentElement
95
+ * @param {Element | null} [componentElement]
182
96
  * @returns {Record<PropertyKey, unknown> | null}
183
97
  */
184
98
  export function toSnapshotFromComponentElement (componentElement) {
@@ -187,7 +101,7 @@ export function toSnapshotFromComponentElement (componentElement) {
187
101
 
188
102
  if (fiberNode) {
189
103
  return (
190
- transform(fiberNode)
104
+ getSnapshot(fiberNode)
191
105
  )
192
106
  }
193
107
  }
@@ -196,164 +110,23 @@ export function toSnapshotFromComponentElement (componentElement) {
196
110
  }
197
111
 
198
112
  /**
199
- * @param {Element} element
200
- * @returns {FiberNode | null}
201
- */
202
- function getFiber (element) {
203
- const key = getReactFiberKey(element)
204
-
205
- if (key) {
206
- const { // @ts-expect-error
207
- [key]: fiber = null
208
- } = element
209
-
210
- return fiber
211
- }
212
-
213
- return null
214
- }
215
-
216
- /**
217
- * @param {FiberNode} fiberNode
218
- * @returns {FiberNode[]}
219
- */
220
- function getSiblings (fiberNode) {
221
- const siblings = []
222
-
223
- let sibling = fiberNode.sibling
224
- while (sibling) {
225
- siblings.push(sibling)
226
- sibling = sibling.sibling
227
- }
228
-
229
- return siblings
230
- }
231
-
232
- /**
233
- * @param {FiberNode} fiberNode
234
- * @returns {Record<PropertyKey, unknown>}
235
- */
236
- function getProps (fiberNode) {
237
- const stateNode = fiberNode.stateNode
238
-
239
- /**
240
- * State node may be null on class components
241
- */
242
- if (stateNode) {
243
- const props = getStateNodeProps(stateNode) ?? {}
244
-
245
- return (
246
- Object.fromEntries(
247
- Object.entries(props)
248
- .filter(([key]) => key !== 'children')
249
- .filter(([key, value]) => {
250
- if (isObject(value)) return !('current' in value)
251
- return true
252
- })
253
- )
254
- )
255
- }
256
-
257
- return {}
258
- }
259
-
260
- /**
261
- * @param {FiberNode} fiberNode
262
- * @returns {Array<string | FiberNode>}
263
- */
264
- function getChildrenOf (fiberNode) {
265
- const child = fiberNode.child
266
-
267
- if (child) {
268
- const siblings = getSiblings(child)
269
-
270
- return [child].concat(siblings).map((child) => {
271
- const stateNode = child.stateNode
272
-
273
- if (stateNode instanceof Text) {
274
- return stateNode.data
275
- }
276
-
277
- return child
278
- })
279
- }
280
-
281
- const stateNode = fiberNode.stateNode
282
-
283
- if (stateNode) {
284
- /**
285
- * Get the text as a prop from the instance
286
- */
287
- const {
288
- children
289
- } = getStateNodeProps(stateNode) ?? {}
290
-
291
- if (typeof children === 'string') {
292
- return [children]
293
- }
294
- }
295
-
296
- return []
297
- }
298
-
299
- /**
300
- * @param {FiberNode | string} child
301
- * @returns {string | Record<PropertyKey, unknown>}
302
- */
303
- function toChildren (child) {
304
- if (typeof child === 'string') return child
305
-
306
- return (
307
- transform(child)
308
- )
309
- }
310
-
311
- /**
312
- * @param {FiberNode} fiberNode
313
- * @returns {Array<string | Record<PropertyKey, unknown>>}
314
- */
315
- function getChildren (fiberNode) {
316
- return (
317
- getChildrenOf(fiberNode)
318
- .map(toChildren)
319
- )
320
- }
321
-
322
- /**
323
- * @param {FiberNode} fiberNode
324
- * @returns {Record<PropertyKey, unknown>}
325
- */
326
- function transform (fiberNode) {
327
- const type = getType(fiberNode)
328
- const props = getProps(fiberNode)
329
- const children = getChildren(fiberNode)
330
-
331
- return (
332
- Object.defineProperty({
333
- type,
334
- props,
335
- children
336
- },
337
- '$$typeof', {
338
- value: REACT_COMPONENT_SNAPSHOT
339
- })
340
- )
341
- }
342
-
343
- /**
344
- * @param {Element | null | undefined} element
113
+ * @param {Element | null} [element]
345
114
  * @returns {Record<PropertyKey, unknown> | null}
346
115
  */
347
- export default function snapshotOf (element) {
116
+ export function snapshotOf (element) {
348
117
  if (element instanceof HTMLElement) {
349
118
  const fiberNode = getFiber(element)
350
119
 
351
120
  if (fiberNode) {
352
121
  return (
353
- transform(fiberNode)
122
+ getSnapshot(fiberNode)
354
123
  )
355
124
  }
356
125
  }
357
126
 
358
127
  return null
359
128
  }
129
+
130
+ export {
131
+ toSnapshotFromRender as toSnapshot
132
+ }
File without changes