Add Playground e2e tests and a "try in Playground" button on PRs - #56
Draft
roborourke wants to merge 3 commits into
Draft
Add Playground e2e tests and a "try in Playground" button on PRs#56roborourke wants to merge 3 commits into
roborourke wants to merge 3 commits into
Conversation
There were no tests. The filter blocks are almost entirely server-side behaviour driven by the query string, which is exactly the kind of thing that is cheap to break and expensive to notice. Follow the hm-query-loop harness: Playwright driving WordPress Playground via @wp-playground/cli, rather than wp-env and Docker. Playground boots in process, so there is no environment to start or stop, and the PHP and WordPress versions are just parameters — CI runs a PHP 8.2/8.3 x WP 6.8/latest matrix off the same blueprint developers use locally. blueprint.json describes the environment once and is shared between the test run and `npm run playground:start`. Fixture content is seeded by tests/seed.php, and tests/mu-plugins/register-test-content.php registers the post types and taxonomies the tests filter against, including deliberately private ones so the suite can prove they stay invisible. 16 tests covering the taxonomy filter (select, checkbox, multi-term, URL round-tripping), the post type filter, the search block, and the query string validation added in the previous commit. Also add a Playground preview button to every PR. build/ is gitignored, so pr-playground-preview.yml builds the PR and pushes the result to a throwaway pr-<n>-built branch that Playground installs from; pr-cleanup deletes the branch when the PR closes. Unlike the hm-query-loop version this skips fork PRs, whose read-only token cannot push that branch, and keeps the PR title out of the shell — it is attacker controlled. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015J9z6XLV1hT1FB1BSXPczo
Playwright — PHP 8.3 / WP latestDetails
|
Every unfiltered assertion failed on the same diff: WordPress ships with a "Hello world!" post, so the loop returned five titles where the fixtures define four. It also sat in Uncategorized, which put a third option in the taxonomy filter's derived term list. Delete all pre-existing posts and pages before seeding so the fixtures are the only content the loops can return. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015J9z6XLV1hT1FB1BSXPczo
Two things kept the taxonomy term list assertions red. wp_insert_post() assigns the default category when a post is created without one, so "Unfiled Post" — whose whole purpose is to belong to no category — landed in Uncategorized. That made Uncategorized non-empty and put a third option in the filter's derived term list. Clear it explicitly. The checkbox labels wrap their text across lines in the template, and toHaveText compares textContent verbatim, so the tabs and newlines came through. Compare innerText instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015J9z6XLV1hT1FB1BSXPczo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The repo had no tests. The filter blocks are almost entirely server-side behaviour driven by the query string, which is cheap to break and expensive to notice.
The harness
Playwright driving WordPress Playground via
@wp-playground/cli, following hm-query-loop's migration off wp-env. Playground boots in process, so:npm run test:e2eis the whole thing.blueprint.jsondescribes the environment once and is shared between the test run andnpm run playground:start(manual poking, no tests). Fixtures are seeded bytests/seed.php, andtests/mu-plugins/register-test-content.phpregisters the post types and taxonomies the tests filter against — including deliberately private ones, so the suite can prove they stay invisible./taxonomy-filter//taxonomy-checkboxes//post-type-filter/Unfiled Postbelongs to no category on purpose, so "filtered" is always distinguishable from "unfiltered".Secret Oneis published in the privateqf_secretpost type and must never reach the front end.The tests
16 tests in three specs:
alpha,beta.query-3-s) and narrows the loop; a term in the URL is reflected in the input.?query-3-post_type[]=, previously an uncaughtTypeError) are all ignored, andSecret Onenever appears.Filtering navigates through the Interactivity API router, which swaps the loop region in without a document navigation, so the
loop.expectTitles()helper polls the rendered titles rather than waiting on a load event.Playground preview button on PRs
pr-playground-preview.ymladds a Preview in WordPress Playground button to every PR description, booting that PR's build with demo content already seeded — a reviewer can try a change without a local checkout.build/is gitignored, so the preview needs somewhere to get compiled assets: the workflow builds the PR and force-pushes the result to a throwawaypr-<n>-builtbranch, which Playground installs from as a zip.pr-cleanup.ymldeletes that branch when the PR closes.Two deliberate differences from the hm-query-loop version:
if: head.repo.full_name == github.repository). A fork PR's token is read-only and cannot push the preview branch, so the step would hard-fail rather than being unavailable.github.event.pull_request.titleinto asedcommand; a PR title is attacker-controlled, so that is a command injection vector. This stamps0.0.0-pr<number>instead, with the number passed via env.Testing
Everything that can be checked without booting WordPress has been:
npm ciclean from the regenerated lockfile;npm run buildsucceeds.npx playwright test --listcollects all 16 tests across 3 files.wp-scripts lint-jsclean on the harness and specs.composer phpcsclean;php -lclean on the seed and mu-plugin, and on the PHP embedded in the preview workflow's blueprint.actions/checkoutv7.0.1,actions/setup-nodev7.0.0,actions/upload-artifactv7.0.1,daun/playwright-report-commentv4.1.0,WordPress/action-wp-playground-pr-previewv3.CI: 16/16 passing on all four matrix legs (PHP 8.2/8.3 × WP 6.8/latest), plus PHPCS and the preview job. Playground boots in ~20s per leg.
The suite could not be run locally — this environment's network policy blocks
wordpress.org, so Playground cannot download WordPress — so the first run was on CI, and it took three rounds to get green. Both fixes were to the fixtures, not the plugin:tests/seed.phpnow clears pre-existing posts and pages before seeding.wp_insert_post()assigns the default category when a post is created without one, so "Unfiled Post" — whose entire purpose is to belong to no category — was silently filed under Uncategorized, making it non-empty and adding a third option to the term list. Now cleared explicitly. Separately, the checkbox labels wrap their text across lines andtoHaveTextcomparestextContentverbatim, so that assertion comparesinnerText.The preview button path is also verified end to end:
pr-56-builtcarries the compiled assets and is stamped0.0.0-pr56.One thing to fold in on merge
#54 adds
.gitattributes, which controls what ships in the release ZIP. It doesn't exist on this branch, so adding the entries here would conflict. Whichever of #54 / this PR merges second needs these four lines added:(
/testsis already covered by #54's list.) Happy to push that once the merge order is settled.Generated by Claude Code
Generated by Claude Code