Repository navigation
Name the controls the journeys and the screenshots share in one helper - #566
Conversation
Fourth step of the redesign's groundwork (#542, #551). The journeys and the documentation screenshots find the app's controls by the words and roles on screen, and each file wrote those out itself: the ticket field in ten files, "Link ticket" in ten, the site menu in five. A renamed button, or a menu rebuilt as a dialog, was an edit to every one of them. tests/e2e/helpers/ui.cjs holds them now: the controls more than one file reaches, and the two locators that depend on how the screen is built rather than on what it says, the sidebar entry and the card. It also takes the three things the journeys had copied between themselves: the link-a-ticket steps, five times over, and the document-order check, twice. A sentence only one journey asserts stays in that journey. Every locator is the one that was written inline. Two differ in how strictly they match: the screenshots named four buttons by part of their name and now name them exactly, and the patch-file button is matched by part of its name everywhere, as the journeys asserting its absence already did. The screenshots' card() moves with the rest, unchanged. It still reads the shape of the markup; the point is that it does so in one place. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…hat its rule says Three findings from the review of the previous commit. The five clicks on the patch-file button matched its whole name before the move and part of it after, and nothing else states that name. They match it exactly again. The two assertions that the button is absent keep the looser match, under a name of its own. The rule for what belongs in the helper said more than the helper held: "Continue working on #N" was reached from two journeys and left inline, and the ticket row reads the markup the same way the card does. Both move in. The rule now names the four structural locators it holds and says a selector only one file needs stays in that file, in one wording, in TESTING.md, which the review standard points to. sidebarEntry's comment says which sites it cannot find: one with a staleness or an incomplete-update dot, and one being deleted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 23 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configurationConfiguration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (17)
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. Comment |
|
@coderabbitai review |
|
… their own (#567) ## Why `src/renderer/index.jsx` is 6,420 lines, and the redesign in #542 has to change almost all of it. Between its imports and the two components that are most of the file sat seven components that take props and nothing else, and five hooks. They can be changed one at a time once they are files of their own, and what is left in `index.jsx` afterwards is the part that still has to be taken apart. ## What changes The twelve move, verbatim, and `index.jsx` imports them back: - `src/renderer/components/`: `ReasonedButton`, `DiscardChangesLink`, `DiffText`, `LogText`, `Destination` and `DestinationGroup` (one file), `TerminalCommandLink`. - `src/renderer/hooks/`: `useDetectedEditors`, `useContributorProvenance`, `useNextActionCue`, `useSites`, and `useConfirmation` with `ConfirmationContext`. Nothing is rewritten. Each function gains `export`, each file gains the imports it needs, and five comments that pointed "above" or "below" now name the file they mean. `index.jsx` is 6,085 lines. Two things follow from there being more than one renderer source: - **`build.files` excludes every `.jsx` under `src/renderer/`**, where it excluded `index.jsx` alone. In that directory `.jsx` now means "bundled by esbuild", and without this the new files would ship uncompiled beside the bundle that already contains them. The hooks are named `.jsx` for that reason, although they hold no JSX. The packaged smoke test reads the same rule. - **The review standard and TESTING.md** said a decision made in `index.jsx` is one the suite cannot reach. That is as true of a component or a hook beside it, and they say so. Deliberately not in this PR: any change to what a component renders or a hook does, the five modals (#553), and `SiteRow`'s state (#554). ## How to test this Platforms: any. Use the Buildkite build for the current head of this branch. The journeys carry this: `npm run test:e2e`, from the repository root, drives every flow the moved components and hooks take part in. The packaged smoke test, after `npm run build:once && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack:dir`, proves the app boots from an archive without the sources: `npm run test:e2e:packaged`. It is red if `build.files` excludes only `index.jsx`; that was checked by putting the old pattern back. Nothing on screen should differ, so a manual pass is a look for what the journeys do not reach: **Starting state:** the app open on a site that has finished setup, with an edited file. 1. Hover a disabled button, for example "Unlink" while a command runs in the terminal. The tooltip with the reason appears. 2. Click "Review & submit changes". The diff is coloured, and the destinations are grouped in cards. 3. Start the dev server and open the "Logs" tabs. Log lines are coloured by severity. 4. Under the terminal, click one of the command links in the hints. The command is typed at the prompt and not run. 5. Click "Open directory in". The list of editors on this machine appears. **What must not have happened:** - No confirmation toast is missing after an action that shows one ("Updated to the latest trunk" after an update, "Patch saved to …" after saving a patch, "Local changes discarded." after a discard): they come through the context that moved. - The page still scrolls to the next step when it changes. ## Risks and limitations - **One journey failed once and could not be reproduced.** In the first full run after rebasing onto #541, "a failed review reports an error instead of claiming there are no changes" failed. It passed in the next two full runs, in 25 isolated repeats and in 4 repeats of its whole file. The failure output was not kept, so its cause is unknown; nothing the test exercises changed in this PR. - **`npm test` was not rerun on the last commit.** It changes two comments, the README and two smoke-test assertions. The unit suites ran on the commit before it. - ~~**Checked on macOS only.** Windows is covered by CI's journeys and packaged smoke.~~ Checked on Windows also - **The moved code keeps `index.jsx`'s two-space indentation**, where `.editorconfig` asks for tabs in new code, so that the diff reads as a move. `.editorconfig` steers editors and fails nothing. - Review: no findings; three style notes, applied. ## Related Closes #552 Part of #542. Follows #566. --- <details> <summary>Design decisions and alternatives considered</summary> **`hooks/` beside `components/`**, where the issue's title names `components/` for both. The step that splits `SiteRow`'s state (#554) will add a hook per domain, and they are not components. **Kebab-case file names**, like every other file under `src/`, rather than the `PascalCase.tsx` of the prototype. **One pattern, `!src/renderer/**/*.jsx`**, rather than a line per directory. A directory list has to be remembered the next time one is added; the extension is a rule a new file follows by being what it is. The `.cjs` modules beside them are not covered, deliberately: the main process requires some of them. **No rewrite on the way.** `formatEmailDate`, the style constants and the labels at the top of `index.jsx` stay where they are; they are not components, and moving them is not what the issue asks. </details> <details> <summary>Review outcome (required — see AGENTS.md)</summary> **0 [fix here] · 0 [follow-up]** — no findings across the five dimensions. The review checked the move mechanically: it stripped each new file's imports and `export`, found the rest as an exact substring of `trunk`'s `index.jsx`, and diffed what remained against the branch's. All eleven files are byte-identical to `trunk` apart from the comment edits. It also confirmed no circular import, one shared `ConfirmationContext`, an unchanged order of style registration, that the packaging pattern matches all twelve `.jsx` and nothing that must ship, and that the translation extraction script still sees the new files. Style notes, applied in the second commit: two comments in `index.jsx` still pointed at a note that had moved; the smoke test's directory checks were written through `arrayContaining` where `toContain` says it; the README named `index.jsx` alone as the bundle's source. Style notes, left alone as unrelated to this change: `.editorconfig` and `eslint.config.mjs` say `index.jsx` uses four spaces, and the review standard still says "4000-line component". - **Review:** completed — fresh agent context, local, before the PR existed, read-only; head 1ab1520 / base 1f3808a; committed work only, working tree clean; outcome above. CodeRabbit: not run yet. - **Since review:** `1ab1520 → 4c98b4c` checked. The difference is the three style notes. It was not reviewed again by a fresh context. Checks, macOS, local: | Check | On | Result | |---|---|---| | `eslint . --max-warnings=0` | 4c98b4c | clean (run with a local agent worktree under `.claude/worktrees/` ignored; it is not part of the repository) | | `npm test` | 1ab1520 | 1691 pass, 2 skipped, 0 fail | | `npm run test:electron` | 1ab1520 | 1693 pass, 0 fail | | `npm run test:e2e` | 4c98b4c | 34 of 34 pass | | `npm run test:e2e:packaged` | 4c98b4c | 15 of 15 pass | </details> <details> <summary>Implementation notes</summary> How the move was checked before the review: every line that left `index.jsx` was looked up in the new files. Of 335, all but eight are there unchanged; the eight are five import lines and three comments, each rewritten. `@wordpress/i18n`'s extraction (`scripts/generate-pot.cjs`, from #541) walks `src/` and picks up `.jsx`, so a string wrapped in a component later is found without a change there. </details> <details> <summary>Screenshots or recording</summary> Nothing on screen changed, and no images are attached. The twelve shots `npm run shots` captures were taken on `trunk` and on this branch with a two-second settle before each capture. Eleven are pixel-identical. The twelfth, `gutenberg-site-view`, differed once in its terminal, which is an intermittent rendering problem on `trunk` itself: eight captures of that shot on unchanged `trunk` code showed it twice, and eight on this branch not at all. It is being looked at separately. With the harness's own 300ms settle, one shot differs from `trunk` by 14 corner pixels of a sidebar entry: a transition caught part-way, which is why the comparison was repeated with a longer settle. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Why
The journeys and the documentation screenshots find the app's controls by the words and roles on screen, and each file wrote those out itself: the ticket field in ten files, "Link ticket" in ten, the site menu in five. The redesign in #542 renames controls and rebuilds the parts of the screen they sit in, and today each of those is an edit to every file that mentions it. This puts the names in one place before the screen starts to move.
What changes
tests/e2e/helpers/ui.cjsis new. It names what is on screen for the journeys, the other end-to-end specs andscripts/screenshots/alike, and they all read it.It holds:
card()is one of these, moved unchanged.It does not hold a sentence one journey asserts, a button only one journey presses, or a selector only one file needs. About 120 locators stay in their journeys for that reason: they are what the journey is about. TESTING.md states the rule, and the review standard points to it.
Deliberately not in this PR: any change to what the app renders, and any new assertion. The screenshots' own crops (
.patch-diff, the parent hops) stay inshots.cjs, since nothing else uses them.How to test this
Platforms: any. There is no user-visible surface: this is test and screenshot code only.
From the repository root:
npm run lintis clean.npm run test:e2epasses, the same 33 journeys as ontrunk.npm run build:once && CSC_IDENTITY_AUTO_DISCOVERY=false npm run pack:dir, thennpm run test:e2e:packaged, passes.npm run shotscaptures all twelve fixture shots. Discard them afterwards withgit checkout -- docs/public/screenshots.What must not have happened:
anyPatchFileButtonexists only to assert that no such button is there, and the button it would find is the onechoosePatchFileButtonclicks.Risks and limitations
linkTicketreports a timeout differently. The inline version ended inexpect(…).toBeVisible({ timeout: 30_000 }); the shared one ends inwaitFor({ timeout: 30_000 }), so the helper needs noexpectand loads withplaywright-corealone. Same condition, same limit, and it still fails the test, as a timeout rather than as an assertion.sidebarEntryfinds only a site with nothing to report. A stale site, one with an incomplete update and one being deleted have longer names. That was true of the locator before it was shared; its comment now says so.Related
Closes #551
Part of #542. Follows #565.
Design decisions and alternatives considered
Locators, not strings. A file of label constants would leave the role and the match in every caller, and the redesign changes those too: a menu item can become a dialog button. A function that returns the locator takes all three with it.
Not every label. There are 152 distinct locators across these files and about 30 are used in more than one. Moving the rest would turn each journey into a list of names defined elsewhere, and TESTING.md's audit depends on reading a journey as a description of what it does. A one-off is already a one-file change.
No
.first(), no waiting, noexpectin the helper. Each locator is what the caller would have written, and the caller adds what it needs where a reader can see it.linkTicketis the one function that waits, because the wait is the flow.The helper lives under
tests/e2e/helpers/, andscripts/screenshots/shots.cjsrequires it from there. The journeys are its main user, and TESTING.md already describes that directory.card()still reads the markup's shape. Giving the cards a role and a name would make it a real landmark, and that is a change to the app that belongs with the redesigned cards.Review outcome (required — see AGENTS.md)
2 [fix here] · 1 [follow-up] — all 3 fixed.
anyPatchFileButton.sidebarEntry's comment did not say which sites it cannot find.The review compared every replaced locator with what the helper returns and found the rest identical, with the same
.first(),.last()and timeouts, and no step dropped or reordered.03a7ea2 → 00261a2checked. The difference is the three fixes. It was not reviewed again by a fresh context; it was verified by the runs below.Checks on 00261a2, macOS, local:
npm run lintnpm testnpm run test:electronnpm run test:e2enpm run test:e2e:packagednpm run shots, fixture tierAgainst
trunk, eleven of the twelve shots are pixel-identical. The twelfth,stale-site-notice, reads "121 days old" where it read "120": the fixture's date is fixed, and a day boundary passed between the two captures (#326).One mutation, to show the helper is what the journeys read: naming "Unlink" wrongly in
ui.cjsfails the journeys that press it.🤖 Generated with Claude Code