Skip to content

Conversation

@jelly
Copy link
Member

@jelly jelly commented Nov 7, 2025

This PR does two things to support cockpit-machines:

  • Allow () inside :contains() needed for ":contains("Console(1)")
  • Allow matching elements after :contains(), needed for this .pf-v6-c-menu__item:contains('SpiceOnly') input:checked

The changes are run here cockpit-project/cockpit-machines#2387

jelly added 2 commits November 7, 2025 17:51
In cockpit-machines there are selectors like `.pf-v6-c-menu button:contains('Serial (serial0)')`,
the previous regex did not match brackets.
To support cockpit-machines which has a selector after :contains()
such as for example:

```
b.click(f"#os-select li:contains('{dialog.os_name}') button")
```
if (!window.Sizzle) {
// Best effort support `:contains()`
const re = /:contains\(([\s\S]*?)\)/g;
const re = /:contains\(((?:[^()]*|\([^()]*\))*)\)/g;

Check failure

Code scanning / CodeQL

Inefficient regular expression High test

This part of the regular expression may cause exponential backtracking on strings starting with ':contains(' and containing many repetitions of '''.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah only thing here is that it will have exponential backtrack when we're missing a ).

.pf-v6-c-menu__item:contains('SpiceOnly' input:checked

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, so I guess not really a problem for us. Honestly not a regex expert so welcome to improvements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required to have quotes for :contains()? If so that will make it a lot easier as we can check for start and end better

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be, currently we allow non-quotes. If we want to enforce quotes we need to accept both '/" ofcourse and have a way to mass convert tests where needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a middle ground: could we continue to allow simple strings without quotes, and anything which contains parentheses etc. has to be quoted? Something like /:contains\( ([a-zA-Z0-9]+) | '([^']+)' \) (of course without the extra spaces, just to make it a bit more readable)? If you care, we could add another alternative for double quotes of course.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #22663

return elem_contains_text(elems, searchText);
// everything after :contains()
const leftover = sel.substring(matches.index + matches[1].length + ":contains()".length, sel.length).trim();
const base = sel.replace(re, '').replace(leftover, '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels brittle. I'd prefer if you could compute the index after :contains() once, and split the string into base and leftover at that point.

martinpitt added a commit to martinpitt/cockpit that referenced this pull request Dec 8, 2025
See cockpit-project#22581 (review)

This commit was done entirely with Claude Code:

> in test/, find all instances of `:contains` selectors with an unquoted value, like
> b.click("#account-expiration .pf-v6-c-modal-box__footer button:contains(Change)")
> quote all these; prefer `'` unless it collides with the outer quoting
martinpitt added a commit to martinpitt/cockpit that referenced this pull request Dec 8, 2025
See cockpit-project#22581 (review)

This commit was done entirely with Claude Code:

> in test/, find all instances of `:contains` selectors with an unquoted value, like
> b.click("#account-expiration .pf-v6-c-modal-box__footer button:contains(Change)")
> quote all these; prefer `'` unless it collides with the outer quoting
martinpitt added a commit that referenced this pull request Dec 8, 2025
See #22581 (review)

This commit was done entirely with Claude Code:

> in test/, find all instances of `:contains` selectors with an unquoted value, like
> b.click("#account-expiration .pf-v6-c-modal-box__footer button:contains(Change)")
> quote all these; prefer `'` unless it collides with the outer quoting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants