Skip to content

Match rule-template rows by cell text, not direct text node - #1297

Merged
travagliad merged 3 commits into
mainfrom
claude/jolly-curie-4halfz
Sep 3, 2026
Merged

Match rule-template rows by cell text, not direct text node#1297
travagliad merged 3 commits into
mainfrom
claude/jolly-curie-4halfz

Conversation

@travagliad

@travagliad travagliad commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Failures fixed (investigator)

  • source: Percona-Lab/pmm-submodules PR #4449 — run 33649010825, check @fb-alerting|@fb-settings UI tests
  • tests: all 13 actionable failures in codeceptjs-e2e/tests/ia/ruleTemplates_test.js / @fb-alerting
    • PMM-T1514 — Verify that alert rule templates has only 1 exit button
    • PMM-T1786 — Edit bulk uploaded rule template
    • PMM-T1787 — Delete bulk uploaded rule template
    • PMM-T1993 — verify editor can create alert rule template
    • PMM-T483 + PMM-T699 + PMM-T1994 — Verify user can edit UI-created IA rule template (both data rows)
    • PMM-T500 + PMM-T595 + PMM-T596 — Add rule templates with different units, empty range (3 data rows)
    • PMM-T553 — Verify rule template can be deleted if there is a rule based on it
    • PMM-T562 + PMM-T1995 — Verify user can delete User-defined (UI) rule templates (both data rows)
    • PMM-T825 + PMM-T821 — Verify User can add Alert rule template in the file system

Note: GitHub strips raw markup from a PR body even inside a code fence, so the DOM shapes below are written in CSS-selector notation rather than as literal tags.

What failed

13 of 13 actionable failures (Launchable gate: 13 actionable, 0 quarantined; 42 tests, 29 passed)
came from one file and one locator shape — a row-action button addressed through the template's
name cell:

Error: element (//td[contains(text(), "Template bulk 1")]/following-sibling::td
                //button[@data-testid="edit-template-button"]) still not present on page after 30 sec

Root cause — the pmm-qa locator, not the product

grafana#912 (PMM-14912, still an open draft) gives the Name column a Cell renderer: it wraps the
value in a Stack holding a span with the template name, followed by a conditional Badge
labelled Dynamic when the template's YAML contains overridable: true.

On percona/grafana main that column has no Cell at all, so react-table renders the name as the
cell's own text and XPath text() — which only sees a node's direct text children — matches.
With the renderer the name moves one level down, and every *ByName lookup matches nothing:

build name cell renders as //td[contains(text(), NAME)]
main the name directly inside td 1 match
with grafana#912 td > div.css-6hq8f5 > span holding the name 0 matches

Reproduced on a throwaway Linode VM running the FB build perconalab/pmm-server-fb:PR-4449-3eded28
(3.10.0-PMM-14912-dynamic-thresholds-3eded285c), evaluating locators against the live templates
table on each build:

locator FB build main build
//td[contains(text(), "PMM agent down")] 0 1
//td[contains(., "PMM agent down")] 1 1
…/following-sibling::td//a[@data-testid="create-from-template-button"] (before) 0 1
row-scoped create-from-template-button (this PR) 1 1

The product is behaving as the feature intends; the assertions are all still right.

Fix

The three *ByName button locators now resolve through templateRow(), which matches the name
column
(td[1]) exactly — against either the cell's own text (the main shape) or a nested
element's text (the grafana#912 shape). That matches both DOM shapes, so this is not blocked
on grafana#912: it works against main today and against the FB build.

PMM-T1514 needed one more line. It grabs the first name cell and feeds that text back into a name
locator, and the new cell also renders the Dynamic badge for an overridable template — on the FB
build //tr/td[1] reads as "Node high CPU load\nDynamic" (exactly one template carries it,
node_high_cpu_load.yml, which gained overridable: true in pmm#5878). The test now takes the
cell's first line, which is a no-op on the current main shape.

Folded in from review:

  • templateRow() scopes to td[1] and matches exactly. An earlier revision matched any cell by
    substring, which could resolve to more than one row — a name contained in another
    (Template bulk 1 also matching Template bulk 1_updated), or one appearing in the Source column
    (Built-in matching every built-in row). Not reachable by the current tests, since
    clearAllTemplates() runs per scenario in Before, but the any-cell part was new here and worth
    closing.
  • templateRowByName was a zero-caller pass-through to the same helper and is gone.
  • The two comments over editButtonByName / deleteButtonByName are gone — they restated the line
    and the first named the wrong button.
  • grabFirstTemplateName() had a single caller and is inlined at it.

Deliberately unchanged: the *BySource locators already match through descendant::div
(verified — 42 rows for Built-in), and elements.addedTemplate uses td[text()=…] but is
referenced by no test.

Verification

Same VM, same suite (codeceptjs run -c pr.codecept.js tests/ia/ruleTemplates_test.js --grep '@fb-alerting'),
brought up the way runner-e2e-tests-codeceptjs.yml does (codeceptjs-e2e/docker-compose.yml,
testdata/db_setup.sh, pmm3-client-setup.sh, pmm-framework --database mysql):

run server image result
before the fix perconalab/pmm-server-fb:PR-4449-3eded28 13 passed, 13 failed, 1 skipped — 23m
after the fix perconalab/pmm-server-fb:PR-4449-3eded28 26 passed, 0 failed, 1 skipped — 7m
after the fix perconalab/pmm-server:3-dev-latest (no PMM-14912) 26 passed, 0 failed, 1 skipped — 7m

The 13 red scenarios are exactly the 13 Launchable reported as actionable on the FB run, and every
one of their step traces names a //td[contains(text(), …)] locator. The third row is the
backward-compatibility check, and this PR's own CI confirms it independently: the
FB E2E tests / Alerting and Settings UI tests / e2e tests: @fb-alerting|@fb-settings job is green
here, on a build without PMM-14912. So the change is safe to merge before grafana#912.

The later templateRow() tightening was re-checked against both DOM shapes rebuilt as fixtures from
the markup captured on each live build, driving the shipped locators: every template name the
suite uses resolves to exactly one row and one button on both shapes, edit/delete stay at 1 for
user-defined rows and 0 for built-in/file rows (what PMM-T825's dontSeeElement relies on), and an
absent name yields 0.

The one skipped scenario is PMM-T510, Scenario.skip on main already.

Host port 443 on the repro VM belongs to the exec channel, so PMM's 443:8443 publish was remapped
to 8443; the tests drive http://127.0.0.1/ (port 80) exactly as CI does, so nothing under test
was affected.

What only a real FB run can confirm: the local runs executed the whole ruleTemplates_test.js
file rather than Launchable's subset, and against a single FB build; the templateRow() tightening
that came out of review was verified against DOM fixtures plus this PR's CI, not against a second
live FB server. The FB check going green end-to-end is for the next FB run on a PR carrying
grafana#912.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KL3FgMrwzE9PjV5dZ6eFUX

The Alert Rule Templates name cell now renders the name inside a
<div><span>, so `//td[contains(text(), NAME)]` matches nothing and every
row-action lookup by name times out. Scope the three *ByName button
locators to the row instead, reusing the templateRow() helper that
already matches on the cell's string value.

PMM-T1514 grabs the first name cell and feeds it back into such a
locator, so it now takes only the cell's first line -- an overridable
template renders a "Dynamic" badge in the same cell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KL3FgMrwzE9PjV5dZ6eFUX
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The page object now builds edit, delete, and add-rule locators from the shared templateRow(name) helper. The unused templateRowByName locator was removed. The PMM-T1514 test now splits the template-name cell text by newlines and trims the first line before calling openAddDialog, excluding the Dynamic badge text.

Merge Risk: 🔵 Low · up to 43a99

The change makes rule-template actions work with nested name-cell markup, but the row selector can still match unrelated or partially matching cell text and potentially act on the wrong template when names overlap. The PR is mergeable with explicit owner awareness and follow-up to scope matching to the template-name cell.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main locator change: matching rule-template rows by cell content instead of direct text nodes.
Description check ✅ Passed The description is directly related to the changes. It explains the locator failure, the fix, the Dynamic badge handling, and verification results.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread codeceptjs-e2e/tests/ia/pages/ruleTemplatesPage.js Outdated
Comment thread codeceptjs-e2e/tests/ia/pages/ruleTemplatesPage.js Outdated
Comment thread codeceptjs-e2e/tests/ia/pages/ruleTemplatesPage.js
- Inline grabFirstTemplateName() at its single call site (PMM-T1514) and
  delete the method; the comment explaining the split travels with it.
- Drop the two comments over editButtonByName/deleteButtonByName. They
  restated the line, and the first named the wrong button ("Delete
  template button" over editButtonByName).
- Drop templateRowByName, a zero-caller pass-through to templateRow()
  that the three *ByName locators now call directly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KL3FgMrwzE9PjV5dZ6eFUX

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: ec70c8ee-46c8-485b-a705-5b0927a12d5f

📥 Commits

Reviewing files that changed from the base of the PR and between 2e1c4ec and 43a996f.

📒 Files selected for processing (2)
  • codeceptjs-e2e/tests/ia/pages/ruleTemplatesPage.js
  • codeceptjs-e2e/tests/ia/ruleTemplates_test.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • percona/pmm-qa (manual)
  • percona/pmm (manual)

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread codeceptjs-e2e/tests/ia/pages/ruleTemplatesPage.js
templateRow() matched any cell by substring, so a lookup could resolve to
more than one row: a name contained in another ("Template bulk 1" also
matching "Template bulk 1_updated"), or one that happens to appear in the
Source column ("Built-in" matching every built-in row). Scoping to any
cell was new here, since the previous locators keyed off the name cell's
own text node.

Match td[1] exactly instead, against either the cell's own text or a
nested element's, so both DOM shapes still resolve.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KL3FgMrwzE9PjV5dZ6eFUX
@travagliad
travagliad merged commit 5fdce76 into main Sep 3, 2026
38 checks passed
@travagliad
travagliad deleted the claude/jolly-curie-4halfz branch September 3, 2026 15:02
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.

2 participants