docs(locators): align leftover ranking with generated policy - #994
Conversation
Closes #992 and #993. Related to ShaftHQ/SHAFT_ENGINE#5147.
MohabMohie
left a comment
There was a problem hiding this comment.
Independent adversarial review
Bound to 58f5032. Event is COMMENT only. Do not merge.
Writer claim checked: Element_Identification.md + LoginPage.java + Locators_And_Self_Healing.md ranking table, with RED then GREEN
ode tests/docs-quality.test.js, closing #992 and #993.
What actually landed: three files. Best Practices and the LoginPage.java snippet inside Element_Identification.md were rewritten. The ranking table now shows hasNormalizedText. I ran
ode tests/docs-quality.test.js on this HEAD: it printed Documentation quality checks passed. Overlaying this HEAD test on the pre-change pages fails first on Prefer ID locators, so the new asserts are RED against those exact strings. That is not enough to close the leftover class.
Engine contract used as the spec: LocatorPolicy.java emits hasAnyTagName().hasId(...), then hasRole(...).hasNormalizedText(...), then native relative By.xpath(...) only. Official generated/repo policy on this same HEAD still says that. docs/testing/web.mdx is the page Element_Identification tells readers to start with.
F1 Fail / Blocking
Where: PR body, commit message Closes #992 / Closes #993; gh pr view --json files is only docs/reference/actions/GUI/Element_Identification.md, docs/reference/actions/GUI/Locators_And_Self_Healing.md, ests/docs-quality.test.js. No LoginPage.java file.
Scenario: A closer treats #992 and #993 as done because the PR says Closes. A reader searches for LoginPage.java and still copies raw By.id.
Evidence: #992 acceptance is Best Practices plus the Element_Identification page-object form. Those two spots in this file did change (Element_Identification.md:758-767, :821-824). Credit stops there. #992's own problem statement also named Supported Locator Types ranking raw By.id first; the catalog still does (:22-27). #993 acceptance is table vs official policy on Locators_And_Self_Healing. The table line changed (Locators_And_Self_Healing.md:206). The official user-facing ladder on docs/testing/web.mdx:80 still teaches hasText("Create Account") and the file contains zero hasNormalizedText. docs/reference/guides/Solution_Design.md:18-26 is still a titled LoginPage.java sample with By.id("username").
Class: Credit-not-in-diff / incomplete close.
Fix: Do not close #992 or #993 from this SHA. Either expand the PR to the official web.mdx ladder and the remaining titled LoginPage.java samples, or drop Closes and open one standalone leftover issue per remaining site. The snippet rewrite in Element_Identification is real; the close credit is not.
F2 Fail / Blocking
Where: docs/testing/web.mdx:79-80; docs/reference/guides/Solution_Design.md:18-26; docs/features/test-automation-pillars.mdx:159; docs/reference/actions/GUI/Element_Identification.md:14-16 (sends readers to web.mdx first).
Scenario: New-test author follows Element_Identification Overview to the web locator strategy, copies the official second rung, and ships hasText while codegen emits hasNormalizedText. Same leftover #993 named, on a more important page, not in the diff.
Evidence: HEAD web.mdx:80 is SHAFT.GUI.Locator.hasRole(Role.BUTTON).hasText("Create Account").build().
g hasNormalizedText docs/testing/web.mdx is empty. Solution_Design.md POM sample still recommends By.id as the default page-object form. est-automation-pillars.mdx:159 is a generated-looking login click with hasText("Log in"). None of these files are in the PR. I searched ShaftHQ/shafthq.github.io issues for this leftover class; only #992/#993 are open, both scoped to the two edited pages.
Class: Missing-adoption leftover. Same observable contract as #992/#993, sibling official pages not updated, no test flags the omission.
Fix: Change web.mdx:80 to hasNormalizedText. Update or fence every titled LoginPage.java sample that still teaches raw By.id as the generated/repo form. Do not treat #989 follow-up leftovers as done while the first-link official ladder still disagrees with LocatorPolicy.
F3 Fail / Blocking
Where: docs/reference/actions/GUI/Element_Identification.md:24-27, :67-68, :119, :187, :775-781.
Scenario: Reader sees the new fence at :20, then immediately copies numbered example 1 By.id("username") or the builder start SHAFT.GUI.Locator.hasId("submit-btn").build().
Evidence: :24 still says ID is "the most reliable and fastest method when available" — the same Prefer-ID ranking with different words. :27 is still By.id("username"). :67-68 still show By.xpath("//input[@id='username']") after :65 says use xpath only when there is no unique author-written id. :119 and :187 still start the builder at SHAFT.GUI.Locator.hasId(...) instead of the official hasAnyTagName().hasId(...) emission. Dynamic locators still lead with By.cssSelector. Official ban is SHAFT.GUI.Locator.id/name/cssSelector/className/tagName(...) and SHAFT.GUI.Locator.xpath(...); those raw factories are not newly introduced. The leftover is worse: the page this PR claims to align still teaches raw By.id / hasId(...) start / xpath-by-id as the samples.
Class: Same-page policy contradiction / non-official factory samples.
Fix: Keep raw Selenium By only behind an explicit existing-locator fence. Generated/repo samples on this page must be hasAnyTagName().hasId(...), then hasRole(...).hasNormalizedText(...), then relative By.xpath(...) that does not target an id that should have taken tier 1.
F4 Fail / Blocking
Where: ests/docs-quality.test.js:268-307.
Scenario: Demonstration 1 — keep :24 "most reliable and fastest" and the By.id catalog; test stays green. Demonstration 2 — leave web.mdx:80 as hasText; test stays green. Demonstration 3 — change loginButton to hasRole(...).hasText("Log In") while leaving hasAnyTagName().hasId("username"); test stays green. Demonstration 4 — add hasRole(Role.BUTTON).hasNormalizedText("Log In") anywhere on Locators_And_Self_Healing.md and restore the table to hasText; the page-wide positive assert still passes. The negative table-row regex does bind that one markdown row (I confirmed it matches master Locators_And_Self_Healing.md:206 and not HEAD).
Evidence: Test only reads the two files the writer already edited. Asserts are exact-phrase locks (Prefer ID locators, Avoid XPath when possible, CSS selectors are generally faster, private final By loginButton = By.cssSelector). They do not assert loginButton uses hasRole + hasNormalizedText. They do not read docs/testing/web.mdx, Solution_Design.md, or other LoginPage.java fences. HEAD still contains "most reliable and fastest" and SHAFT.GUI.Locator.hasId(. History is one commit; there is no RED commit, only a property I reproduced by overlaying the new test on the old pages.
Class: Broken-verification / missing-adoption gap. Phrase lock, not leftover-class coverage.
Fix: Pin the official ladder on docs/testing/web.mdx to hasNormalizedText. Fail if Element_Identification still ranks raw ID as fastest or still shows catalog By.id / Locator.hasId( as the generated form. Assert the LoginPage loginButton line. Scan titled LoginPage.java snippets. A synonym of Prefer ID must fail.
Narrow credit (not a close): Best Practices list and the Element_Identification LoginPage snippet no longer contain the three banned phrases or By.cssSelector for loginButton. Ranking table line now matches LocatorPolicy on that one page.
Merge: no. Blocking leftovers remain on the official first-link ladder and on the same page this PR claims to fix. Independent review of 58f5032 is COMMENT only.
|
Orchestrator: independent review confirmed SHA 58f5032. Merge blocked (F1–F4: leftover official pages + credit-not-in-diff + thin quality test). New writer dispatched on this PR. Do not merge this SHA. |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
shaft-engine | 062bf8d | Commit Preview URL Branch Preview URL |
Aug 18 2026, 04:59 PM |
|
Writer patched review 4963447427 (F1-F4) on this branch. New HEAD:
Writer stops. No merge. No approve. |
MohabMohie
left a comment
There was a problem hiding this comment.
Independent adversarial review
Bound to 7cf94527774d9a1170218d4caadae905f3945384. Event is COMMENT only. Do not merge.
Isolated checkout: %TEMP%\shaft-docs-994-review2 at that exact SHA. node tests/docs-quality.test.js printed Documentation quality checks passed. Engine contract used as spec: LocatorPolicy.java emits hasRole(...).hasNormalizedText(...) for a verified named role (shaft-capture/src/main/java/com/shaft/capture/generate/LocatorPolicy.java:139-142).
Prior F1–F4 named sites: fixed
docs/testing/web.mdx:80official second rung ishasNormalizedText("Create Account").docs/features/test-automation-pillars.mdx:159login click ishasNormalizedText("Log in").docs/reference/guides/Solution_Design.mdtitledLoginPage.java/FluentLoginPage.javausehasAnyTagName().hasId(...).docs/reference/actions/GUI/Element_Identification.mddropped Prefer-ID / "most reliable and fastest", catalogBy.id("username"),Locator.hasId(start, xpath-by-id, and DynamicLocators CSS lead. Best Practices now match the three-tier ladder. Smart Locators stay fenced as throwaway.docs/reference/actions/GUI/Locators_And_Self_Healing.md:206ranking table ishasNormalizedText.tests/docs-quality.test.jsnow reads those leftover official pages and locks the strings the last review named.#992/#993acceptance text is met on the pages those tickets named.
That is not enough to merge. Official pages still teach hasText as the generated ARIA matcher. Repo-wide hasRole(...).hasText( now remains only on the two sites below. No open issue covers them (only #992/#993, both page-scoped).
F1 Fail / Blocking
Where: docs/reference/actions/GUI/Locators_And_Self_Healing.md:61-75 (ARIALocators.java); docs/testing/flakiness.mdx:41-65 (SemanticLocators.java).
Scenario: Reader follows the official locator policy page's ARIA section, or the testing "Semantic Locators" ladder that restates generated/repo policy, copies the first working sample, and ships hasText while codegen emits hasNormalizedText.
Evidence: Same HEAD policy section (Locators_And_Self_Healing.md:21-22) and ranking table (:206) say hasNormalizedText. Forty lines later the titled generated/repo ARIA sample is SHAFT.GUI.Locator.hasRole(Role.BUTTON).hasText("Submit").build(). The tip at :73-75 tells generated/repo authors to chain hasRole(...) with text and does not name hasNormalizedText. flakiness.mdx:37-45 restates the generated locator policy, then lists the second rung as hasRole(Role.BUTTON).hasText("Sign in"). Titled SemanticLocators.java at :61 repeats it. This file is not in the PR. rg of hasRole\(Role\.[A-Z]+\)\.hasText\( on docs/ hits only these two pages.
Class: Missing-adoption leftover. Same official-matcher contract as #993, now on the first copy-paste ARIA sample of the official policy page this PR edited, plus a sibling official testing page. No test flags either site.
Fix: Change those official generated/repo samples to hasNormalizedText. Keep hasText only in the builder method catalog / existing-API list, not as the official second-rung matcher. Open one leftover issue if this SHA will not expand; do not treat the leftover class as exhausted because #992/#993 acceptance is met.
F2 Fail / Blocking
Where: tests/docs-quality.test.js:268-280, :351-353, :384-393.
Scenario: Demonstration 1 — leave ARIALocators.java as hasText("Submit"); current test stays green (observed: this HEAD already did that and printed passed). Demonstration 2 — leave flakiness.mdx as hasText("Sign in") / hasText("Apply filter"); test stays green because officialLocatorPages does not read that file. Demonstration 3 — restore the ranking table to hasText("Log In") while adding hasRole(Role.BUTTON).hasNormalizedText("Log In") anywhere else on the page; the page-wide positive still passes and only the exact table-row negative would fail.
Evidence: officialLocatorPages is web.mdx, pillars, Solution_Design, Element_Identification, Locators_And_Self_Healing. web/pillars negatives are exact-phrase locks (hasText("Create Account"), hasText("Log in")), not a leftover-class scan. Locators_And_Self_Healing only bans the markdown table row ARIA role | \SHAFT.GUI.Locator.hasRole(Role.BUTTON).hasText("Log In").build()`. It never asserts the titled ARIALocators.javafence. F4's requested named-site pins landed; the leftover class still has no failing check. **Class:** Broken-verification / missing-adoption gap. Phrase lock, not official-matcher coverage. **Fix:** Fail if an official locator-strategy page teacheshasRole(...).hasText(as the generated/repo form. Includedocs/testing/flakiness.mdx. Bind the ARIALocators.java/SemanticLocators.java` fences, not only the ranking-table row.
Narrow credit: Prior blocking F1–F4 named sites on this SHA are actually in the diff and match LocatorPolicy. #992 Best Practices / catalog / page-object form and #993 table-vs-policy acceptance are met. Closes #992 / Closes #993 may stay for those tickets. They do not cover F1/F2 here.
Non-blocking hunt result: No remaining Prefer-ID / "most reliable and fastest" ranking. Action-API samples still use raw By.id (Element_Actions, TestData, Test_Structure, JUnit, etc.); those do not rank locators. Solution_Design.md titled InlineTest.java still uses By.id behind an anonymous/prototype warning — not the official generated form.
Merge: no. Zero blocking required. Independent review of 7cf94527774d9a1170218d4caadae905f3945384 is COMMENT only.
|
Orchestrator: review of 7cf9452 is blocked (F1–F2: ARIALocators.java and flakiness.mdx still teach hasRole().hasText; quality test missed them). New writer dispatched to fix all official hasRole().hasText leftovers and tighten the test. Do not merge this SHA. |
Closes #992 Closes #993 Related to ShaftHQ/SHAFT_ENGINE#5147. Official ARIALocators.java and flakiness SemanticLocators samples now use hasNormalizedText as the generated second rung. The quality test fails if any public docs page teaches hasRole(...).hasText( and binds those titled fences.
|
Writer patched review 4963577044 (F1-F2) on this branch. New HEAD:
Writer stops. No merge. No approve. |
MohabMohie
left a comment
There was a problem hiding this comment.
Independent adversarial review
Bound to 062bf8d8b831603396ca25d19b2a626429ea2a0c. Event is COMMENT only. Do not merge.
Isolated checkout: %TEMP%\shaft-docs-994-review3 at that exact SHA. node tests/docs-quality.test.js printed Documentation quality checks passed. Engine contract used as spec: LocatorPolicy.java emits hasRole(...).hasNormalizedText(...) for a verified named role (shaft-capture/src/main/java/com/shaft/capture/generate/LocatorPolicy.java:139-142).
Prior blocked-SHA F1–F2: fixed
docs/reference/actions/GUI/Locators_And_Self_Healing.md:65titledARIALocators.javaishasRole(Role.BUTTON).hasNormalizedText("Submit").- Tip at
:73-75now nameshasNormalizedText,hasAttribute, or context. docs/testing/flakiness.mdx:44ladder and:61titledSemanticLocators.javausehasNormalizedText.tests/docs-quality.test.js:283-289walks every public docs page and failshasRole(...).hasText(.- Same file binds the titled
ARIALocators.java/SemanticLocators.javafences (:405-437). - Diff vs blocked
7cf94527774d9a1170218d4caadae905f3945384is exactly those three files.
Claims checked
- Repo-wide
rg hasRole\(.*\)\.hasText\(on this HEAD hits only the three quality-test assertion strings (tests/docs-quality.test.js:288,:419,:436). - No official leftover Prefer-ID / "most reliable and fastest" / "Avoid XPath when possible" / "CSS selectors are generally faster" ranking in
docs/. - No
Locator.hasId(start.SHAFT.GUI.Locator.id/xpath(...)remains only in "never emit" prose. #992Best Practices / catalog / page-object form and#993table-vs-policy acceptance remain met.Closes #992/Closes #993stay honest.
Findings
Zero blocking. No F-items.
Verification-gap demonstrations that now fail: restore ARIALocators.java or SemanticLocators.java to hasRole(...).hasText(, or restore the ranking-table hasText("Log In") row. The public-docs scan and the titled-fence pins would throw. I did not mutate the tree; the regex is the same leftover class the last review named.
Non-blocking hunt
hasText remains in the builder method catalog, Shadow DOM / axis samples, and Playwright_Backend.md PortableLocator.java (hasTagName("button").hasText("Save")). Those are existing-API / portable-builder docs, not hasRole(...).hasText( as the generated second rung. Action-API pages and Solution_Design.md InlineTest.java still use raw By.id behind action-syntax or prototype warnings, not official ranking.
Merge: allowed on blocking count (zero). This review is COMMENT only and does not merge.
Summary
Closes #992
Closes #993
Related to ShaftHQ/SHAFT_ENGINE#5147.
Leftover teaching after #989 still ranked raw
By.id/ CSS over native relative xpath, and official locator-strategy pages taughthasTextas the generated second rung.LoginPage.javasamples now follow unique author-written id viahasAnyTagName().hasId(...), then ARIA role withhasNormalizedText, then native relativeBy.xpath(...)only.docs/testing/web.mdxnow useshasNormalizedText.test-automation-pillars.mdxlogin click useshasNormalizedText.LoginPage.javasamples onSolution_Design.mduse the SHAFT locator builder.hasId(start / xpath-by-id / dynamic CSS samples now follow generated policy.ARIALocators.javaandflakiness.mdxSemantic Locators ladder /SemanticLocators.javanow usehasNormalizedText.Bystays a reference for existing locators, not the generated-code default.LocatorPolicy/ the official policy section:hasNormalizedText.hasTextas an existing builder method.tests/docs-quality.test.jsfails if any public docs page teacheshasRole(...).hasText(as the generated form, and binds the titledARIALocators.java/SemanticLocators.javafences.Checks
node tests/docs-quality.test.jshasRole(.*).hasText(leftovers remain only in the quality-test assertion strings.docs/locator-leftovers-992-993). Primary checkout was not used.Continuation
062bf8d8b831603396ca25d19b2a626429ea2a0c062bf8d8b831603396ca25d19b2a626429ea2a0c. Writer does not merge.