testing-library / dom-testing-library

🐙 Simple and complete DOM testing utilities that encourage good testing practices.
https://testing-library.com/dom
MIT License
3.26k stars 466 forks source link

Serializing anonymous classes of custom elements doesnt work with prettyDOM. #1191

Closed KonnorRogers closed 2 months ago

KonnorRogers commented 1 year ago

Relevant code or config:

https://github.com/testing-library/dom-testing-library/blob/edffb7c5ec2e4afd7f6bedf842c669ddbfb73297/src/DOMElementFilter.ts#L178

What you did:

calling screen.debug()

What happened:

Large console.log ``` Object { "__reactFiber$q3h0d1euq2": FiberNode { "_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": FiberNode { "_debugHookTypes": Array [ "useState", ], "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": Object { "columnNumber": 10, "fileName": "/Users/konnorrogers/projects/oss/shadow-dom-testing-library/__tests__/pretty-shadow-dom.test.tsx", "lineNumber": 28, }, "actualDuration": 0, "actualStartTime": -1, "alternate": null, "child": [Circular], "childLanes": 0, "deletions": null, "dependencies": null, "elementType": [Function], "flags": 1, "index": 0, "key": null, "lanes": 0, "memoizedProps": Object {}, "memoizedState": Object { "baseQueue": null, "baseState": 0, "memoizedState": 0, "next": null, "queue": Object { "dispatch": [Function], "interleaved": null, "lanes": 0, "lastRenderedReducer": [Function], "lastRenderedState": 0, "pending": null, }, }, "mode": 1, "pendingProps": Object {}, "ref": null, "return": FiberNode { "_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": null, "actualDuration": 0, "actualStartTime": -1, "alternate": FiberNode { "_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": null, "actualDuration": 0, "actualStartTime": -1, "alternate": [Circular], "child": null, "childLanes": 0, "deletions": null, "dependencies": null, "elementType": null, "flags": 0, "index": 0, "key": null, "lanes": 16, "memoizedProps": null, "memoizedState": Object { "cache": null, "element": null, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "mode": 1, "pendingProps": null, "ref": null, "return": null, "selfBaseDuration": 0, "sibling": null, "stateNode": FiberRootNode { "_debugRootType": "createRoot()", "callbackNode": null, "callbackPriority": 0, "containerInfo":
[Circular]
, "context": Object {}, "current": [Circular], "effectDuration": 0, "entangledLanes": 0, "entanglements": Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "eventTimes": Array [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "expirationTimes": Array [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ], "expiredLanes": 0, "finishedLanes": 0, "finishedWork": null, "identifierPrefix": "", "memoizedUpdaters": Set {}, "mutableReadLanes": 0, "mutableSourceEagerHydrationData": null, "onRecoverableError": [Function], "passiveEffectDuration": 0, "pendingChildren": null, "pendingContext": null, "pendingLanes": 0, "pendingUpdatersLaneMap": Array [ Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, ], "pingCache": null, "pingedLanes": 0, "suspendedLanes": 0, "tag": 1, "timeoutHandle": -1, }, "subtreeFlags": 0, "tag": 3, "treeBaseDuration": 0, "type": null, "updateQueue": Object { "baseState": Object { "cache": null, "element": null, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "effects": null, "firstBaseUpdate": Object { "callback": null, "eventTime": 1218.221125125885, "lane": 16, "next": null, "payload": Object { "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, }, "tag": 0, }, "lastBaseUpdate": Object { "callback": null, "eventTime": 1218.221125125885, "lane": 16, "next": null, "payload": Object { "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, }, "tag": 0, }, "shared": Object { "interleaved": null, "lanes": 0, "pending": null, }, }, }, "child": [Circular], "childLanes": 0, "deletions": null, "dependencies": null, "elementType": null, "flags": 1024, "index": 0, "key": null, "lanes": 0, "memoizedProps": null, "memoizedState": Object { "cache": null, "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "mode": 1, "pendingProps": null, "ref": null, "return": null, "selfBaseDuration": 0, "sibling": null, "stateNode": FiberRootNode { "_debugRootType": "createRoot()", "callbackNode": null, "callbackPriority": 0, "containerInfo":
[Circular]
, "context": Object {}, "current": [Circular], "effectDuration": 0, "entangledLanes": 0, "entanglements": Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "eventTimes": Array [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "expirationTimes": Array [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ], "expiredLanes": 0, "finishedLanes": 0, "finishedWork": null, "identifierPrefix": "", "memoizedUpdaters": Set {}, "mutableReadLanes": 0, "mutableSourceEagerHydrationData": null, "onRecoverableError": [Function], "passiveEffectDuration": 0, "pendingChildren": null, "pendingContext": null, "pendingLanes": 0, "pendingUpdatersLaneMap": Array [ Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, ], "pingCache": null, "pingedLanes": 0, "suspendedLanes": 0, "tag": 1, "timeoutHandle": -1, }, "subtreeFlags": 3, "tag": 3, "treeBaseDuration": 0, "type": null, "updateQueue": Object { "baseState": Object { "cache": null, "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "effects": null, "firstBaseUpdate": null, "lastBaseUpdate": null, "shared": Object { "interleaved": null, "lanes": 0, "pending": null, }, }, }, "selfBaseDuration": 0, "sibling": null, "stateNode": null, "subtreeFlags": 0, "tag": 0, "treeBaseDuration": 0, "type": [Function], "updateQueue": null, }, "_debugSource": Object { "columnNumber": 5, "fileName": "/Users/konnorrogers/projects/oss/shadow-dom-testing-library/components.tsx", "lineNumber": 214, }, "actualDuration": 0, "actualStartTime": -1, "alternate": null, "child": null, "childLanes": 0, "deletions": null, "dependencies": null, "elementType": "my-button", "flags": 0, "index": 0, "key": null, "lanes": 0, "memoizedProps": Object { "children": 0, "onClick": [Function], }, "memoizedState": null, "mode": 1, "pendingProps": Object { "children": 0, "onClick": [Function], }, "ref": null, "return": FiberNode { "_debugHookTypes": Array [ "useState", ], "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": Object { "columnNumber": 10, "fileName": "/Users/konnorrogers/projects/oss/shadow-dom-testing-library/__tests__/pretty-shadow-dom.test.tsx", "lineNumber": 28, }, "actualDuration": 0, "actualStartTime": -1, "alternate": null, "child": [Circular], "childLanes": 0, "deletions": null, "dependencies": null, "elementType": [Function], "flags": 1, "index": 0, "key": null, "lanes": 0, "memoizedProps": Object {}, "memoizedState": Object { "baseQueue": null, "baseState": 0, "memoizedState": 0, "next": null, "queue": Object { "dispatch": [Function], "interleaved": null, "lanes": 0, "lastRenderedReducer": [Function], "lastRenderedState": 0, "pending": null, }, }, "mode": 1, "pendingProps": Object {}, "ref": null, "return": FiberNode { "_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": null, "actualDuration": 0, "actualStartTime": -1, "alternate": FiberNode { "_debugHookTypes": null, "_debugNeedsRemount": false, "_debugOwner": null, "_debugSource": null, "actualDuration": 0, "actualStartTime": -1, "alternate": [Circular], "child": null, "childLanes": 0, "deletions": null, "dependencies": null, "elementType": null, "flags": 0, "index": 0, "key": null, "lanes": 16, "memoizedProps": null, "memoizedState": Object { "cache": null, "element": null, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "mode": 1, "pendingProps": null, "ref": null, "return": null, "selfBaseDuration": 0, "sibling": null, "stateNode": FiberRootNode { "_debugRootType": "createRoot()", "callbackNode": null, "callbackPriority": 0, "containerInfo":
[Circular]
, "context": Object {}, "current": [Circular], "effectDuration": 0, "entangledLanes": 0, "entanglements": Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "eventTimes": Array [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "expirationTimes": Array [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ], "expiredLanes": 0, "finishedLanes": 0, "finishedWork": null, "identifierPrefix": "", "memoizedUpdaters": Set {}, "mutableReadLanes": 0, "mutableSourceEagerHydrationData": null, "onRecoverableError": [Function], "passiveEffectDuration": 0, "pendingChildren": null, "pendingContext": null, "pendingLanes": 0, "pendingUpdatersLaneMap": Array [ Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, ], "pingCache": null, "pingedLanes": 0, "suspendedLanes": 0, "tag": 1, "timeoutHandle": -1, }, "subtreeFlags": 0, "tag": 3, "treeBaseDuration": 0, "type": null, "updateQueue": Object { "baseState": Object { "cache": null, "element": null, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "effects": null, "firstBaseUpdate": Object { "callback": null, "eventTime": 1218.221125125885, "lane": 16, "next": null, "payload": Object { "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, }, "tag": 0, }, "lastBaseUpdate": Object { "callback": null, "eventTime": 1218.221125125885, "lane": 16, "next": null, "payload": Object { "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, }, "tag": 0, }, "shared": Object { "interleaved": null, "lanes": 0, "pending": null, }, }, }, "child": [Circular], "childLanes": 0, "deletions": null, "dependencies": null, "elementType": null, "flags": 1024, "index": 0, "key": null, "lanes": 0, "memoizedProps": null, "memoizedState": Object { "cache": null, "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "mode": 1, "pendingProps": null, "ref": null, "return": null, "selfBaseDuration": 0, "sibling": null, "stateNode": FiberRootNode { "_debugRootType": "createRoot()", "callbackNode": null, "callbackPriority": 0, "containerInfo":
[Circular]
, "context": Object {}, "current": [Circular], "effectDuration": 0, "entangledLanes": 0, "entanglements": Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "eventTimes": Array [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], "expirationTimes": Array [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ], "expiredLanes": 0, "finishedLanes": 0, "finishedWork": null, "identifierPrefix": "", "memoizedUpdaters": Set {}, "mutableReadLanes": 0, "mutableSourceEagerHydrationData": null, "onRecoverableError": [Function], "passiveEffectDuration": 0, "pendingChildren": null, "pendingContext": null, "pendingLanes": 0, "pendingUpdatersLaneMap": Array [ Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, Set {}, ], "pingCache": null, "pingedLanes": 0, "suspendedLanes": 0, "tag": 1, "timeoutHandle": -1, }, "subtreeFlags": 3, "tag": 3, "treeBaseDuration": 0, "type": null, "updateQueue": Object { "baseState": Object { "cache": null, "element": Object { "$$typeof": Symbol(react.element), "_owner": null, "_store": Object {}, "key": null, "props": Object {}, "ref": null, "type": [Function], }, "isDehydrated": false, "pendingSuspenseBoundaries": null, "transitions": null, }, "effects": null, "firstBaseUpdate": null, "lastBaseUpdate": null, "shared": Object { "interleaved": null, "lanes": 0, "pending": null, }, }, }, "selfBaseDuration": 0, "sibling": null, "stateNode": null, "subtreeFlags": 0, "tag": 0, "treeBaseDuration": 0, "type": [Function], "updateQueue": null, }, "selfBaseDuration": 0, "sibling": null, "stateNode": [Circular], "subtreeFlags": 0, "tag": 5, "treeBaseDuration": 0, "type": "my-button", "updateQueue": null, }, "__reactProps$q3h0d1euq2": Object { "children": 0, "onClick": [Function], }, } ```

Reproduction:

Tried to make a sandbox, but the sandbox is outdated and doesnt work with custom elements.

Small snippet:

class MyElement extends HTMLElement {}
window.customElements.define("my-element", class extends MyElement {})
window.customElements.get("my-element").name // => ""

export default () => <my-element></my-element>

test("Render app", () => {
  render(<App />)
  screen.debug()
})

Problem description:

Current behavior is a massive string is printed out because it fails serialization

Suggested solution:

Don't check for "constructor.name" since you can have anonymous custom element class definitions.