Repository: capricorn86/happy-dom (ts)

Issue:
getByRole cannot query input type=text
Apparently, `happy-dom` thinks textboxes are searchboxes :-) 

It was reported over in `dom-testing-library` but they think it's a `happy-dom` bug: https://github.com/testing-library/dom-testing-library/issues/1137

## Environment

```
@testing-library/dom version: 8.11.3
jest: 27.4.7
DOM Environment: happy-dom@3.1.1
```

## Relevant code or config:

```
// UI
      <input
        defaultValue="hello"
        aria-label="name"
        id="name"
        style={{ maxWidth: "280px" }}
        type="text"
      />

// test
  expect(screen.getByRole("textbox", { name: /name/i }));
```

## What you did:

- If you switch to jsdom, it works!
- But with happy-dom, dom-testing-library says that the textbox is a searchbox
 
## What happened:

```
    TestingLibraryElementError: Unable to find an accessible element with the role "textbox" and name `/name/i`

    Here are the accessible roles:

      searchbox:

      Name "name":
      <input
        aria-label="name"
        defaultvalue="hello"
        id="name"
        style="max-width: 280px;"
        type="text"
      />
```

## Reproduction:
- https://gitlab.com/robotandkid/the-sandbox/-/tree/bug/happy-dom/happy-dom-test
- Run yarn jest

Note that checkboxes have the same problem


Pull request:
#513@patch: Selector item not factoring in selectors after a psuedo selector
Fixes #513 

The assumption that the code was making is that no additional selectors were appearing after a psuedo selector appears to be an incorrect one. As the selector that was mentioned failing in the issue is using the following `input:not([list])[type="search"]`.  

Replacing the psuedo selector instead, using the already available regex, seems to allow only checking against the base selector, but doesn't remove any additional selectors after the psuedo one(s).

Patch:
diff --git a/packages/happy-dom/src/query-selector/SelectorItem.ts b/packages/happy-dom/src/query-selector/SelectorItem.ts
index 8016fefe..a5aa0ead 100644
--- a/packages/happy-dom/src/query-selector/SelectorItem.ts
+++ b/packages/happy-dom/src/query-selector/SelectorItem.ts
@@ -28,12 +28,13 @@ export default class SelectorItem {
 	 * @param selector Selector.
 	 */
 	constructor(selector: string) {
-		const [baseSelector, psuedoSelector] = selector.split(':');
+		const baseSelector = selector.replace(new RegExp(PSUEDO_REGEXP, 'g'), '');
 
 		this.isAll = baseSelector === '*';
 		this.isID = !this.isAll ? selector.startsWith('#') : false;
 		this.isAttribute = !this.isAll && !this.isID && baseSelector.includes('[');
-		this.isPseudo = !this.isAll && !this.isID && psuedoSelector !== undefined;
+		// If baseSelector !== selector then some psuedo selector was replaced above
+		this.isPseudo = !this.isAll && !this.isID && baseSelector !== selector;
 		this.isClass = !this.isAll && !this.isID && new RegExp(CLASS_REGEXP, 'g').test(baseSelector);
 		this.tagName = !this.isAll && !this.isID ? baseSelector.match(TAG_NAME_REGEXP) : null;
 		this.tagName = this.tagName ? this.tagName[0].toUpperCase() : null;


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 84e99f1c..f95192bf 100644
--- a/packages/happy-dom/test/query-selector/QuerySelector.test.ts
+++ b/packages/happy-dom/test/query-selector/QuerySelector.test.ts
@@ -625,5 +625,14 @@ describe('QuerySelector', () => {
 
 			expect(div.querySelector('#id')).toEqual(div2);
 		});
+
+		it('Does not find input with selector of input:not([list])[type="search"]', () => {
+			const div = document.createElement('div');
+			const input = document.createElement('input');
+			input.setAttribute('type', 'text');
+			div.appendChild(input);
+
+			expect(div.querySelector('input:not([list])[type="search"]')).toBeNull();
+		});
 	});
 });