Repository: capricorn86/happy-dom
Pull request #391 (2022-03-07 09:16:04)

#383@patch: Fixes issue with ":not" psuedo CSS selector when selectin…
…g attributes.


Patch:
diff --git a/package-lock.json b/package-lock.json
index b7873318..17afef3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2667,9 +2667,9 @@
 			}
 		},
 		"node_modules/@lit/reactive-element": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.2.3.tgz",
-			"integrity": "sha512-fu0HW3VpeQdTx2BxjcMD0pEXB6M3xYi7Cgmqr7+jtyN7hNZJGFWqqQFfyJRwP8cBGQz3WW1txBiPPf9dK2xdUg=="
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.3.0.tgz",
+			"integrity": "sha512-0TKSIuJHXNLM0k98fi0AdMIdUoHIYlDHTP+0Vruc2SOs4T6vU1FinXgSvYd8mSrkt+8R+qdRAXvjpqrMXMyBgw=="
 		},
 		"node_modules/@mrmlnc/readdir-enhanced": {
 			"version": "2.2.1",
@@ -11239,28 +11239,28 @@
 			"dev": true
 		},
 		"node_modules/lit": {
-			"version": "2.1.4",
-			"resolved": "https://registry.npmjs.org/lit/-/lit-2.1.4.tgz",
-			"integrity": "sha512-m1tHAZdXQhiBe0ReAjyVIUeKnHZpBfx+A5R5dkia8dtvIBwOR6KhD+RxaDnCwrEavRqkZAy5ntLv7chiOZCdNg==",
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/lit/-/lit-2.2.0.tgz",
+			"integrity": "sha512-FDyxUuczo6cJJY/2Bkgfh1872U4ikUvmK1Cb6+lYC1CW+QOo8CaWXCpvPKFzYsz0ojUxoruBLVrECc7VI2f1dQ==",
 			"dependencies": {
-				"@lit/reactive-element": "^1.1.0",
-				"lit-element": "^3.1.0",
-				"lit-html": "^2.1.0"
+				"@lit/reactive-element": "^1.3.0",
+				"lit-element": "^3.2.0",
+				"lit-html": "^2.2.0"
 			}
 		},
 		"node_modules/lit-element": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.1.2.tgz",
-			"integrity": "sha512-5VLn5a7anAFH7oz6d7TRG3KiTZQ5GEFsAgOKB8Yc+HDyuDUGOT2cL1CYTz/U4b/xlJxO+euP14pyji+z3Z3kOg==",
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz",
+			"integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==",
 			"dependencies": {
-				"@lit/reactive-element": "^1.1.0",
-				"lit-html": "^2.1.0"
+				"@lit/reactive-element": "^1.3.0",
+				"lit-html": "^2.2.0"
 			}
 		},
 		"node_modules/lit-html": {
-			"version": "2.1.3",
-			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.1.3.tgz",
-			"integrity": "sha512-WgvdwiNeuoT0mYEEJI+AAV2DEtlqzVM4lyDSaeQSg5ZwhS/CkGJBO/4n66alApEuSS9WXw9+ADBp8SPvtDEKSg==",
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.2.0.tgz",
+			"integrity": "sha512-dJnevgV8VkCuOXLWrjQopDE8nSy8CzipZ/ATfYQv7z7Dct4abblcKecf50gkIScuwCTzKvRLgvTgV0zzagW4gA==",
 			"dependencies": {
 				"@types/trusted-types": "^2.0.2"
 			}
@@ -19872,9 +19872,9 @@
 			}
 		},
 		"@lit/reactive-element": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.2.3.tgz",
-			"integrity": "sha512-fu0HW3VpeQdTx2BxjcMD0pEXB6M3xYi7Cgmqr7+jtyN7hNZJGFWqqQFfyJRwP8cBGQz3WW1txBiPPf9dK2xdUg=="
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.3.0.tgz",
+			"integrity": "sha512-0TKSIuJHXNLM0k98fi0AdMIdUoHIYlDHTP+0Vruc2SOs4T6vU1FinXgSvYd8mSrkt+8R+qdRAXvjpqrMXMyBgw=="
 		},
 		"@mrmlnc/readdir-enhanced": {
 			"version": "2.2.1",
@@ -26744,28 +26744,28 @@
 			"dev": true
 		},
 		"lit": {
-			"version": "2.1.4",
-			"resolved": "https://registry.npmjs.org/lit/-/lit-2.1.4.tgz",
-			"integrity": "sha512-m1tHAZdXQhiBe0ReAjyVIUeKnHZpBfx+A5R5dkia8dtvIBwOR6KhD+RxaDnCwrEavRqkZAy5ntLv7chiOZCdNg==",
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/lit/-/lit-2.2.0.tgz",
+			"integrity": "sha512-FDyxUuczo6cJJY/2Bkgfh1872U4ikUvmK1Cb6+lYC1CW+QOo8CaWXCpvPKFzYsz0ojUxoruBLVrECc7VI2f1dQ==",
 			"requires": {
-				"@lit/reactive-element": "^1.1.0",
-				"lit-element": "^3.1.0",
-				"lit-html": "^2.1.0"
+				"@lit/reactive-element": "^1.3.0",
+				"lit-element": "^3.2.0",
+				"lit-html": "^2.2.0"
 			}
 		},
 		"lit-element": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.1.2.tgz",
-			"integrity": "sha512-5VLn5a7anAFH7oz6d7TRG3KiTZQ5GEFsAgOKB8Yc+HDyuDUGOT2cL1CYTz/U4b/xlJxO+euP14pyji+z3Z3kOg==",
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.0.tgz",
+			"integrity": "sha512-HbE7yt2SnUtg5DCrWt028oaU4D5F4k/1cntAFHTkzY8ZIa8N0Wmu92PxSxucsQSOXlODFrICkQ5x/tEshKi13g==",
 			"requires": {
-				"@lit/reactive-element": "^1.1.0",
-				"lit-html": "^2.1.0"
+				"@lit/reactive-element": "^1.3.0",
+				"lit-html": "^2.2.0"
 			}
 		},
 		"lit-html": {
-			"version": "2.1.3",
-			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.1.3.tgz",
-			"integrity": "sha512-WgvdwiNeuoT0mYEEJI+AAV2DEtlqzVM4lyDSaeQSg5ZwhS/CkGJBO/4n66alApEuSS9WXw9+ADBp8SPvtDEKSg==",
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.2.0.tgz",
+			"integrity": "sha512-dJnevgV8VkCuOXLWrjQopDE8nSy8CzipZ/ATfYQv7z7Dct4abblcKecf50gkIScuwCTzKvRLgvTgV0zzagW4gA==",
 			"requires": {
 				"@types/trusted-types": "^2.0.2"
 			}
diff --git a/packages/happy-dom/src/query-selector/SelectorItem.ts b/packages/happy-dom/src/query-selector/SelectorItem.ts
index a1b57d71..09a2736d 100644
--- a/packages/happy-dom/src/query-selector/SelectorItem.ts
+++ b/packages/happy-dom/src/query-selector/SelectorItem.ts
@@ -8,7 +8,7 @@ const CLASS_REGEXP = /\.([a-zA-Z0-9-_$]+)/g;
 const TAG_NAME_REGEXP = /^[a-zA-Z0-9-]+/;
 
 /**
- *
+ * Selector item.
  */
 export default class SelectorItem {
 	public isAll: boolean;
@@ -27,11 +27,9 @@ export default class SelectorItem {
 	 * @param selector Selector.
 	 */
 	constructor(selector: string) {
-		const isNotPseudo = selector.includes(':not(');
-
 		this.isAll = selector === '*';
 		this.isID = !this.isAll ? selector.startsWith('#') : false;
-		this.isAttribute = !this.isAll && !this.isID && selector.includes('[') && !isNotPseudo;
+		this.isAttribute = !this.isAll && !this.isID && selector.includes('[');
 		this.isPseudo = !this.isAll && !this.isID && selector.includes(':');
 		this.isClass = !this.isAll && !this.isID && new RegExp(CLASS_REGEXP, 'g').test(selector);
 		this.tagName = !this.isAll && !this.isID ? selector.match(TAG_NAME_REGEXP) : null;
@@ -236,7 +234,7 @@ export default class SelectorItem {
 		let match: RegExpMatchArray;
 
 		while ((match = regexp.exec(selector))) {
-			const isPsuedo = match.index > 0 && selector[match.index] === '(';
+			const isPsuedo = match.index > 0 && selector[match.index - 1] === '(';
 			if (
 				!isPsuedo &&
 				((match[1] && !this.matchesAttributeName(element, match[1])) ||


Test patch:
diff --git a/packages/happy-dom/test/query-selector/QuerySelector.test.ts b/packages/happy-dom/test/query-selector/QuerySelector.test.ts
index 387f0132..ff8a1622 100644
--- a/packages/happy-dom/test/query-selector/QuerySelector.test.ts
+++ b/packages/happy-dom/test/query-selector/QuerySelector.test.ts
@@ -1,11 +1,13 @@
 import IHTMLElement from '../../src/nodes/html-element/IHTMLElement';
 import Window from '../../src/window/Window';
+import IWindow from '../../src/window/IWindow';
+import IDocument from '../../src/nodes/document/IDocument';
 import QuerySelectorHTML from './data/QuerySelectorHTML';
 import QuerySelectorNthChildHTML from './data/QuerySelectorNthChildHTML';
 
 describe('QuerySelector', () => {
-	let window;
-	let document;
+	let window: IWindow;
+	let document: IDocument;
 
 	beforeEach(() => {
 		window = new Window();
@@ -386,16 +388,15 @@ describe('QuerySelector', () => {
 		});
 
 		it('Returns all elements matching "[data-foo]:not([data-bar])".', () => {
-			const container = document.createElement('div');
-			container.innerHTML = `
+			document.body.innerHTML = `
 				<div data-foo data-bar class="foo bar"></div>
 				<div data-foo class="foo"></div>
 				<div data-bar class="bar"></div>
 			`;
-			const elements = container.querySelectorAll('[data-foo]:not([data-bar])');
+			const elements = document.querySelectorAll('[data-foo]:not([data-bar])');
 
 			expect(elements.length).toBe(1);
-			expect(elements[0]).toBe(container.children[1]);
+			expect(elements[0]).toBe(document.body.children[1]);
 		});
 
 		it('Returns all span elements matching span:nth-child(1) or span:nth-child(2).', () => {