Skip to content

Commit

Permalink
Merge pull request #1170 from btea/task/0-match-section-invalid-selector
Browse files Browse the repository at this point in the history
#0@patch: Matches a partially invalid selector and throws an error.
  • Loading branch information
capricorn86 committed Jan 15, 2024
2 parents 5faca75 + 61b3137 commit 35a0b3c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
33 changes: 30 additions & 3 deletions packages/happy-dom/src/query-selector/QuerySelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ type IDocumentPositionAndElement = {
element: IElement;
};

/**
* Invalid Selector RegExp.
*/
const INVALID_SELECTOR_REGEXP = /^[.#\[]?\d/;

/**
* Utility for query selection in an HTML element.
*
Expand All @@ -35,14 +40,20 @@ export default class QuerySelector {
): INodeList<IElement> {
if (selector === '') {
throw new Error(
"Failed to execute 'querySelectorAll' on 'Element': The provided selector is empty."
`Failed to execute 'querySelectorAll' on '${node.constructor.name}': The provided selector is empty.`
);
}

if (selector === null || selector === undefined) {
return new NodeList<IElement>();
}

if (INVALID_SELECTOR_REGEXP.test(selector)) {
throw new Error(
`Failed to execute 'querySelectorAll' on '${node.constructor.name}': '${selector}' is not a valid selector.`
);
}

const groups = SelectorParser.getSelectorGroups(selector);
let matches: IDocumentPositionAndElement[] = [];

Expand Down Expand Up @@ -79,17 +90,23 @@ export default class QuerySelector {
public static querySelector(
node: IElement | IDocument | IDocumentFragment,
selector: string
): IElement {
): IElement | null {
if (selector === '') {
throw new Error(
"Failed to execute 'querySelector' on 'Element': The provided selector is empty."
`Failed to execute 'querySelector' on '${node.constructor.name}': The provided selector is empty.`
);
}

if (selector === null || selector === undefined) {
return null;
}

if (INVALID_SELECTOR_REGEXP.test(selector)) {
throw new Error(
`Failed to execute 'querySelector' on '${node.constructor.name}': '${selector}' is not a valid selector.`
);
}

for (const items of SelectorParser.getSelectorGroups(selector)) {
const match =
node[PropertySymbol.nodeType] === NodeTypeEnum.elementNode
Expand All @@ -112,12 +129,22 @@ export default class QuerySelector {
* @returns Result.
*/
public static match(element: IElement, selector: string): ISelectorMatch | null {
if (!selector) {
return null;
}

if (selector === '*') {
return {
priorityWeight: 1
};
}

if (INVALID_SELECTOR_REGEXP.test(selector)) {
throw new Error(
`Failed to execute 'match' on '${element.constructor.name}': '${selector}' is not a valid selector.`
);
}

for (const items of SelectorParser.getSelectorGroups(selector)) {
const result = this.matchSelector(element, element, items.reverse());

Expand Down
32 changes: 32 additions & 0 deletions packages/happy-dom/test/query-selector/QuerySelector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,22 @@ describe('QuerySelector', () => {

expect(elements.length).toBe(0);
});

it('Throws an error when providing an invalid selector', () => {
const div = document.createElement('div');
expect(() => div.querySelectorAll('1')).toThrowError(
"Failed to execute 'querySelectorAll' on 'HTMLElement': '1' is not a valid selector."
);
expect(() => div.querySelectorAll('[1')).toThrowError(
"Failed to execute 'querySelectorAll' on 'HTMLElement': '[1' is not a valid selector."
);
expect(() => div.querySelectorAll('.1')).toThrowError(
"Failed to execute 'querySelectorAll' on 'HTMLElement': '.1' is not a valid selector."
);
expect(() => div.querySelectorAll('#1')).toThrowError(
"Failed to execute 'querySelectorAll' on 'HTMLElement': '#1' is not a valid selector."
);
});
});

describe('querySelector', () => {
Expand Down Expand Up @@ -1126,5 +1142,21 @@ describe('QuerySelector', () => {
expect(element === div.children[0]).toBe(true);
expect(element2 === div.children[0]).toBe(true);
});

it('Throws an error when providing an invalid selector', () => {
const div = document.createElement('div');
expect(() => div.querySelector('1')).toThrowError(
"Failed to execute 'querySelector' on 'HTMLElement': '1' is not a valid selector."
);
expect(() => div.querySelector('[1')).toThrowError(
"Failed to execute 'querySelector' on 'HTMLElement': '[1' is not a valid selector."
);
expect(() => div.querySelector('.1')).toThrowError(
"Failed to execute 'querySelector' on 'HTMLElement': '.1' is not a valid selector."
);
expect(() => div.querySelector('#1')).toThrowError(
"Failed to execute 'querySelector' on 'HTMLElement': '#1' is not a valid selector."
);
});
});
});

0 comments on commit 35a0b3c

Please sign in to comment.