Repository: capricorn86/happy-dom
Pull request #398 (2022-03-10 12:31:11)

#394@patch: Adds support for target in MutationRecord when using Muta…
…tionObserver.


Patch:
diff --git a/packages/happy-dom/src/nodes/character-data/CharacterData.ts b/packages/happy-dom/src/nodes/character-data/CharacterData.ts
index e69f7de1..0eec299b 100644
--- a/packages/happy-dom/src/nodes/character-data/CharacterData.ts
+++ b/packages/happy-dom/src/nodes/character-data/CharacterData.ts
@@ -61,6 +61,7 @@ export default abstract class CharacterData extends Node implements ICharacterDa
 			for (const observer of this._observers) {
 				if (observer.options.characterData) {
 					const record = new MutationRecord();
+					record.target = this;
 					record.type = MutationTypeEnum.characterData;
 					record.oldValue = observer.options.characterDataOldValue ? oldValue : null;
 					observer.callback([record]);
diff --git a/packages/happy-dom/src/nodes/element/Element.ts b/packages/happy-dom/src/nodes/element/Element.ts
index d2406b0e..ee717314 100644
--- a/packages/happy-dom/src/nodes/element/Element.ts
+++ b/packages/happy-dom/src/nodes/element/Element.ts
@@ -801,6 +801,7 @@ export default class Element extends Node implements IElement {
 					(!observer.options.attributeFilter || observer.options.attributeFilter.includes(name))
 				) {
 					const record = new MutationRecord();
+					record.target = this;
 					record.type = MutationTypeEnum.attributes;
 					record.attributeName = name;
 					record.oldValue = observer.options.attributeOldValue ? oldValue : null;
@@ -877,6 +878,7 @@ export default class Element extends Node implements IElement {
 						observer.options.attributeFilter.includes(attribute.name))
 				) {
 					const record = new MutationRecord();
+					record.target = this;
 					record.type = MutationTypeEnum.attributes;
 					record.attributeName = attribute.name;
 					record.oldValue = observer.options.attributeOldValue ? attribute.value : null;
diff --git a/packages/happy-dom/src/nodes/node/Node.ts b/packages/happy-dom/src/nodes/node/Node.ts
index 3d54ab8a..11ca3d27 100644
--- a/packages/happy-dom/src/nodes/node/Node.ts
+++ b/packages/happy-dom/src/nodes/node/Node.ts
@@ -267,6 +267,7 @@ export default class Node extends EventTarget implements INode {
 		// MutationObserver
 		if (this._observers.length > 0) {
 			const record = new MutationRecord();
+			record.target = this;
 			record.type = MutationTypeEnum.childList;
 			record.addedNodes = [node];
 
@@ -303,6 +304,7 @@ export default class Node extends EventTarget implements INode {
 		// MutationObserver
 		if (this._observers.length > 0) {
 			const record = new MutationRecord();
+			record.target = this;
 			record.type = MutationTypeEnum.childList;
 			record.removedNodes = [node];
 
@@ -368,6 +370,7 @@ export default class Node extends EventTarget implements INode {
 		// MutationObserver
 		if (this._observers.length > 0) {
 			const record = new MutationRecord();
+			record.target = this;
 			record.type = MutationTypeEnum.childList;
 			record.addedNodes = [newNode];
 


Test patch:
diff --git a/packages/happy-dom/test/mutation-observer/MutationObserver.test.ts b/packages/happy-dom/test/mutation-observer/MutationObserver.test.ts
index 85d517f3..24447413 100644
--- a/packages/happy-dom/test/mutation-observer/MutationObserver.test.ts
+++ b/packages/happy-dom/test/mutation-observer/MutationObserver.test.ts
@@ -28,7 +28,7 @@ describe('MutationObserver', () => {
 					oldValue: null,
 					previousSibling: null,
 					removedNodes: [],
-					target: null,
+					target: div,
 					type: 'attributes'
 				}
 			]);
@@ -52,7 +52,7 @@ describe('MutationObserver', () => {
 					oldValue: 'old',
 					previousSibling: null,
 					removedNodes: [],
-					target: null,
+					target: div,
 					type: 'attributes'
 				}
 			]);
@@ -83,7 +83,7 @@ describe('MutationObserver', () => {
 						oldValue: 'old',
 						previousSibling: null,
 						removedNodes: [],
-						target: null,
+						target: div,
 						type: 'attributes'
 					}
 				]
@@ -108,7 +108,7 @@ describe('MutationObserver', () => {
 						oldValue: 'old',
 						previousSibling: null,
 						removedNodes: [],
-						target: null,
+						target: text,
 						type: 'characterData'
 					}
 				]
@@ -135,11 +135,82 @@ describe('MutationObserver', () => {
 						oldValue: 'old',
 						previousSibling: null,
 						removedNodes: [],
-						target: null,
+						target: text,
 						type: 'characterData'
 					}
 				]
 			]);
 		});
+
+		it('Observers added and removed nodes.', () => {
+			const records = [];
+			const div = document.createElement('div');
+			const span = document.createElement('span');
+			const article = document.createElement('article');
+			const text = document.createTextNode('old');
+			const observer = new MutationObserver(mutationRecords => {
+				records.push(mutationRecords);
+			});
+			observer.observe(div, { subtree: true, childList: true });
+			div.appendChild(text);
+			div.appendChild(span);
+			span.appendChild(article);
+			span.removeChild(article);
+
+			expect(records).toEqual([
+				[
+					{
+						addedNodes: [text],
+						attributeName: null,
+						attributeNamespace: null,
+						nextSibling: null,
+						oldValue: null,
+						previousSibling: null,
+						removedNodes: [],
+						target: div,
+						type: 'childList'
+					}
+				],
+				[
+					{
+						addedNodes: [span],
+						attributeName: null,
+						attributeNamespace: null,
+						nextSibling: null,
+						oldValue: null,
+						previousSibling: null,
+						removedNodes: [],
+						target: div,
+						type: 'childList'
+					}
+				],
+				[
+					{
+						addedNodes: [article],
+						attributeName: null,
+						attributeNamespace: null,
+						nextSibling: null,
+						oldValue: null,
+						previousSibling: null,
+						removedNodes: [],
+						target: span,
+						type: 'childList'
+					}
+				],
+				[
+					{
+						addedNodes: [],
+						attributeName: null,
+						attributeNamespace: null,
+						nextSibling: null,
+						oldValue: null,
+						previousSibling: null,
+						removedNodes: [article],
+						target: span,
+						type: 'childList'
+					}
+				]
+			]);
+		});
 	});
 });