capricorn86 / happy-dom

A JavaScript implementation of a web browser without its graphical user interface
MIT License
3.28k stars 200 forks source link

DOMException: Failed to execute 'insertBefore' on 'Node' #1429

Closed marcotas closed 3 months ago

marcotas commented 4 months ago

Describe the bug I'm getting this error inside radix-vue after updating the happy-dom package from 14.7.1 to 14.10.1. It seems to me that it's a change on the most recent version of happy-dom package that is breaking my unit tests.

Everything works as expected on the browser. How should I solve this? Any ideas?

Screenshots

image

Error text:

DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
 ❯ Function.insertBefore node_modules/.pnpm/happy-dom@14.8.3/node_modules/happy-dom/src/nodes/node/NodeUtility.ts:181:10
 ❯ Function.insertBefore node_modules/.pnpm/happy-dom@14.8.3/node_modules/happy-dom/src/nodes/element/ElementUtility.ts:215:16
 ❯ HTMLElement.[insertBefore] node_modules/.pnpm/happy-dom@14.8.3/node_modules/happy-dom/src/nodes/element/Element.ts:522:25
 ❯ HTMLElement.insertBefore node_modules/.pnpm/happy-dom@14.8.3/node_modules/happy-dom/src/nodes/node/Node.ts:367:43
 ❯ HTMLElement.insertAdjacentElement node_modules/.pnpm/happy-dom@14.8.3/node_modules/happy-dom/src/nodes/element/Element.ts:601:9
 ❯ node_modules/.pnpm/radix-vue@1.7.4_vue@3.4.27_typescript@5.4.5_/node_modules/radix-vue/dist/index.js:897:19
    895|       return;
    896|     const t = document.querySelectorAll("[data-radix-focus-guard]");
    897|     document.body.insertAdjacentElement(
       |                   ^
    898|       "afterbegin",
    899|       t[0] ?? Po()
 ❯ callWithErrorHandling node_modules/.pnpm/@vue+runtime-core@3.4.27/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:195:19
 ❯ callWithAsyncErrorHandling node_modules/.pnpm/@vue+runtime-core@3.4.27/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:202:17
 ❯ ReactiveEffect.getter [as fn] node_modules/.pnpm/@vue+runtime-core@3.4.27/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:1900:16
 ❯ ReactiveEffect.run node_modules/.pnpm/@vue+reactivity@3.4.27/node_modules/@vue/reactivity/dist/reactivity.cjs.js:181:19

Device:

btea commented 4 months ago

Can you provide a reproduction link?

sebdvd commented 4 months ago

Hi, I have the same issue caused by this recent fix: https://github.com/capricorn86/happy-dom/pull/1407 I created a repo to reproduce this issue: https://github.com/alk-sdavid/happy-dom-issue (install deps then run npm test).

It logs the same error as Marco commented:

DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.

Same test works with happy-dom@14.8.2, then it starts failing with happy-dom@14.8.3

I didn't have time to dig more, but in my use case it craches when I try to test a Radix select rendered in a Radix dialog which uses a React portal...

juandiegombr commented 4 months ago

It happens also to me using the Dialog component from Radix. It seems that happens because the focus guards functionality.

image

After some digging I have realized that it performs some radix utilities trigger document.body.insertAdjacentElement('afterbegin', element);:

I think this test should pass:

it('Does not insert a children that is already inserted', () => {
  const container = document.createElement('div');
  const child = document.createElement('p');
  child.textContent = 'A';
  container.appendChild(child);

  container.insertBefore(child, child);

  const elements = container.querySelectorAll('p');
  expect(elements.length).toBe(1);
});