Repository: capricorn86/happy-dom
Pull request #864 (2023-04-15 16:17:48)

#421@patch: Fixes issue in Node.insertBefore() related to moving a No…
…de within the same parent.


Patch:
diff --git a/packages/happy-dom/src/nodes/element/HTMLCollection.ts b/packages/happy-dom/src/nodes/element/HTMLCollection.ts
index f2670a80..b9b6ac14 100644
--- a/packages/happy-dom/src/nodes/element/HTMLCollection.ts
+++ b/packages/happy-dom/src/nodes/element/HTMLCollection.ts
@@ -62,7 +62,7 @@ export default class HTMLCollection<T> extends Array implements IHTMLCollection<
 
 				if (this._namedItems[name].length === 0) {
 					delete this._namedItems[name];
-					if (this._isValidPropertyName(name)) {
+					if (this[name] && this._isValidPropertyName(name)) {
 						delete this[name];
 					}
 				} else if (this._isValidPropertyName(name)) {
diff --git a/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts b/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts
index 39b9a281..a45a7860 100644
--- a/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts
+++ b/packages/happy-dom/src/nodes/html-form-element/HTMLFormControlsCollection.ts
@@ -93,7 +93,7 @@ export default class HTMLFormControlsCollection
 
 				if (this._namedItems[name].length === 0) {
 					delete this._namedItems[name];
-					if (this._isValidPropertyName(name)) {
+					if (this[name] && this._isValidPropertyName(name)) {
 						delete this[name];
 					}
 				} else if (this._isValidPropertyName(name)) {
diff --git a/packages/happy-dom/src/nodes/node/Node.ts b/packages/happy-dom/src/nodes/node/Node.ts
index de12429c..c7a7cd8a 100644
--- a/packages/happy-dom/src/nodes/node/Node.ts
+++ b/packages/happy-dom/src/nodes/node/Node.ts
@@ -419,16 +419,14 @@ export default class Node extends EventTarget implements INode {
 			return newNode;
 		}
 
-		if (referenceNode === undefined) {
+		if (!referenceNode) {
 			throw new DOMException(
 				"Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only 1 present.",
 				'TypeError'
 			);
 		}
 
-		const index = referenceNode ? this.childNodes.indexOf(referenceNode) : 0;
-
-		if (index === -1) {
+		if (this.childNodes.indexOf(referenceNode) === -1) {
 			throw new 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."
 			);
@@ -445,7 +443,7 @@ export default class Node extends EventTarget implements INode {
 			}
 		}
 
-		this.childNodes.splice(index, 0, newNode);
+		this.childNodes.splice(this.childNodes.indexOf(referenceNode), 0, newNode);
 
 		(<Node>newNode)._connectToNode(this);
 


Test patch:
diff --git a/packages/happy-dom/test/nodes/element/Element.test.ts b/packages/happy-dom/test/nodes/element/Element.test.ts
index 12de1c12..7fe27f26 100644
--- a/packages/happy-dom/test/nodes/element/Element.test.ts
+++ b/packages/happy-dom/test/nodes/element/Element.test.ts
@@ -1090,6 +1090,21 @@ describe('Element', () => {
 			expect(element.children[2] === span).toBe(true);
 		});
 
+		it('Inserts elements of the same parent correctly.', () => {
+			const div = document.createElement('div');
+			div.innerHTML =
+				'<span id="a"></span><span id="b"></span><span id="c"></span><span id="d"></span>';
+
+			const a = div.querySelector('#a');
+			const b = div.querySelector('#b');
+
+			div.insertBefore(a, b);
+
+			expect(div.innerHTML).toBe(
+				'<span id="a"></span><span id="b"></span><span id="c"></span><span id="d"></span>'
+			);
+		});
+
 		it('After should add child element correctly', () => {
 			document.body.innerHTML = `<div class="container"></div>\n`;
 			expect(document.body.children.length).toBe(1);