Skip to content

Commit 7e25c97

Browse files
mixelburgmixelburg
andauthored
fix: [#2194] Fix ~= attribute selector matching hyphenated substrings (#2205)
Co-authored-by: mixelburg <mixelburg@gmail.com>
1 parent b334a12 commit 7e25c97

2 files changed

Lines changed: 17 additions & 1 deletion

File tree

packages/happy-dom/src/query-selector/SelectorParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ export default class SelectorParser {
474474
switch (attribute.operator) {
475475
// [attribute~="value"] - Contains a specified word.
476476
case '~':
477-
return new RegExp(`[- ]${escapedValue}|${escapedValue}[- ]|^${escapedValue}$`, modifier);
477+
return new RegExp(`(^|\\s)${escapedValue}(\\s|$)`, modifier);
478478
// [attribute|="value"] - Starts with the specified word.
479479
case '|':
480480
return new RegExp(`^${escapedValue}[- ]|^${escapedValue}$`, modifier);

packages/happy-dom/test/query-selector/QuerySelector.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,22 @@ describe('QuerySelector', () => {
706706
expect(elements[1] === container.children[0].children[1].children[1]).toBe(true);
707707
});
708708

709+
it('Does not match hyphenated substrings with "~=" selector.', () => {
710+
const container = document.createElement('div');
711+
container.innerHTML =
712+
'<div data-controller="modal"><div data-controller="modal-auto-close"></div></div>';
713+
const parent = container.children[0];
714+
const child = container.children[0].children[0];
715+
716+
expect(parent.matches('[data-controller~="modal"]')).toBe(true);
717+
expect(child.matches('[data-controller~="modal"]')).toBe(false);
718+
expect(child.matches('[data-controller~="modal-auto"]')).toBe(false);
719+
expect(child.matches('[data-controller~="auto"]')).toBe(false);
720+
expect(child.matches('[data-controller~="odal"]')).toBe(false);
721+
expect(child.matches('[data-controller~="modal-auto-close"]')).toBe(true);
722+
expect(container.querySelector('[data-controller~="modal"]')).toBe(parent);
723+
});
724+
709725
it('Returns all elements with an attribute value starting with the specified word using "[class|="class1"]".', () => {
710726
const container = document.createElement('div');
711727
container.innerHTML = QuerySelectorHTML;

0 commit comments

Comments
 (0)