From 5e2558523bbda644cf0ff837126f4ea025a5980a Mon Sep 17 00:00:00 2001 From: Jason Chafin <1000543+Herm71@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:39:28 -0700 Subject: [PATCH] docs: rewrite ROADMAP section 3 around what is actually automatable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Section 3 described a test harness that did not exist and recommended a sequence that was wrong in two ways. Both are now settled, so it is rewritten to describe what landed and why it took the shape it did. Drops the .wp-env.json recommendation: ucsc/wp-dev.ucsc is already the org's shared Docker local environment, so committing one would add a second, competing definition of a solved problem. Records the constraint the original section missed. The fund URL path reads an ACF Pro options page registered by the ucsc-2022 theme, so integration testing it in CI would need a commercial licence key as a repository secret. Full-stack integration testing is now listed as an explicit non-goal rather than an unstated gap. Also corrects CLAUDE.md and .github/copilot-instructions.md, which both still stated there was no automated test suite — untrue since #131, and actively misleading to anyone reading them for guidance. Closes #129 Co-Authored-By: Claude Opus 5 (1M context) --- .github/copilot-instructions.md | 6 +++-- CLAUDE.md | 7 ++++-- ROADMAP.md | 44 ++++++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 939304c..3b03b31 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -125,9 +125,11 @@ Fund search results are returned using the archive template via `ucscgiving_fund - UCSC-2022 theme (template parts referenced in block templates) ## Testing -There is no automated test suite. Validate changes manually: +`composer test` runs a PHPUnit suite; `composer lint` runs PHPCS. Both run on every pull request via `.github/workflows/ci.yml` on PHP 8.1 and 8.4. + +The suite stubs WordPress (`tests/bootstrap.php`) rather than running inside it, so it covers only functions that are pure once WordPress is stubbed. Everything else still needs manual validation: - Test both Priority and Standard fund types for correct linking behavior - Verify block bindings render correct URLs in the block editor and on the front end - Check the "Fund Search" block variation appears in the block inserter - Validate ACF fields save correctly and that values appear in templates -- Run `composer lint` before committing to ensure WordPress Coding Standards compliance \ No newline at end of file +- Run `composer lint` and `composer test` before committing; CI runs both and will fail the PR otherwise \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index c6b6fc4..213411a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,15 +10,18 @@ npm install # Node dev deps (@wordpress/scripts, commit-and-tag-versio composer lint # PHPCS across the repo composer lint-fix # PHPCBF auto-fix +composer test # PHPUnit (needs ext-mbstring) npm run zip # Build distributable ZIP (wp-scripts plugin-zip) npm run dryrun # Preview version bump + changelog npm run release # Tag a release and update CHANGELOG.md ``` -There is **no automated test suite** — no PHPUnit, no wp-env config, no JS tests. `composer lint` is the only mechanical gate. Validate behavior by hand against a WordPress install with ACF Pro and the `ucsc-2022` theme active. +`composer lint` and `composer test` both run on every pull request via `.github/workflows/ci.yml` (PHP 8.1 and 8.4). `release.yml` still only fires on tags. -`composer lint` runs on every pull request via `.github/workflows/ci.yml` (PHP 8.1 and 8.4), so a style regression fails the PR. `release.yml` still only fires on tags. +**The PHPUnit suite stubs WordPress rather than running inside it.** `tests/bootstrap.php` supplies WordPress stand-ins, so the suite needs no WordPress, no database, no ACF Pro licence and no theme — but it therefore only covers functions that are pure once WordPress is stubbed. There is no wp-env config and no JS test suite, both deliberately; see ROADMAP §3. + +Anything touching a running WordPress — block template registration, the ACF JSON round-trip, the fund-type save cycle — still has to be validated by hand against an install with ACF Pro and the `ucsc-2022` theme active. ## Repository shape diff --git a/ROADMAP.md b/ROADMAP.md index b61e53c..3b9f05d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,6 +1,6 @@ # Roadmap -Engineering roadmap for the UCSC Giving Functionality plugin, derived from the state of the repository as of **2026-07-31** (v0.5.8). +Engineering roadmap for the UCSC Giving Functionality plugin, derived from the state of the repository as of **2026-08-04** (v0.5.8). This is a technical roadmap, not a product plan. Items are grounded in open issues, in-flight pull requests, and observed characteristics of the codebase — it does not attempt to set feature direction, which is the University Advancement web team's call. Sequencing below reflects dependency order and risk, not committed dates. @@ -11,7 +11,6 @@ This is a technical roadmap, not a product plan. Items are grounded in open issu | Item | Tracking | State | |---|---|---| | Dual source of truth for fund type | [#3](https://github.com/ucsc/ucsc-giving-functionality/issues/3) | Open, **needs a decision** — see [§1](#1-resolve-the-dual-source-of-truth-for-fund-type) | -| `CLAUDE.md` / `ROADMAP.md` project context | [#122](https://github.com/ucsc/ucsc-giving-functionality/issues/122) | Landed in [#125](https://github.com/ucsc/ucsc-giving-functionality/pull/125) | ### Needs a decision @@ -19,7 +18,10 @@ This is a technical roadmap, not a product plan. Items are grounded in open issu ### Recently landed -- [#121](https://github.com/ucsc/ucsc-giving-functionality/pull/121) — seven correctness and hygiene fixes: a `search_template` filter that had never applied, an unguarded `get_current_screen()` fatal, and a permalink filter that read loop state instead of its own `$post` argument. Also repaired `composer lint`, which failed outright with no path argument. +- [#131](https://github.com/ucsc/ucsc-giving-functionality/pull/131) ([#128](https://github.com/ucsc/ucsc-giving-functionality/issues/128)) — the PHPUnit harness described in §3. First automated behavioral coverage in the repo. +- [#130](https://github.com/ucsc/ucsc-giving-functionality/pull/130) ([#127](https://github.com/ucsc/ucsc-giving-functionality/issues/127)) — `ci.yml`, so pull requests are validated at all. Also declared the PHP floor (8.1), which had been recorded in neither `composer.json` nor the plugin header, and aligned the WPCS target version with `Requires at least`. +- [#125](https://github.com/ucsc/ucsc-giving-functionality/pull/125) ([#122](https://github.com/ucsc/ucsc-giving-functionality/issues/122)) — `CLAUDE.md` and this roadmap. +- [#121](https://github.com/ucsc/ucsc-giving-functionality/pull/121) — seven correctness and hygiene fixes: a `search_template` filter that had never applied, an unguarded `get_current_screen()` fatal, and a permalink filter that read loop state instead of its own `$post` argument. Also repaired `composer lint`, which failed outright with no path argument. Two of these now have regression tests, added in #131. - [#124](https://github.com/ucsc/ucsc-giving-functionality/pull/124) — the plugin header version updater matched a single digit per segment, so it would have silently corrupted the `Version:` header at 0.5.10 and could not parse the `v*.*.*-rc.*` tags `release.yml` already triggers on. --- @@ -57,22 +59,41 @@ Options range from cheap to thorough: The middle option also gives the existing settings page a reason to exist beyond displaying the plugin description. -## 3. Establish a test harness +## 3. Test harness -There is currently **no automated test coverage of any kind** — no PHPUnit, no `.wp-env.json`, no JS tests. `composer lint` is the only mechanical gate, and it checks style, not behavior. +**Largely done.** [#127](https://github.com/ucsc/ucsc-giving-functionality/pull/130) and [#128](https://github.com/ucsc/ucsc-giving-functionality/pull/131) landed on 2026-08-04. What exists now: -This is what makes items 1 and 2 risky: the fund-linking logic has several branches (fund type, empty `base_url`, missing designation, non-`fund` post types, in-loop vs out-of-loop) that today can only be verified by hand. +- **PR checks.** `.github/workflows/ci.yml` runs `composer lint` and `composer test` on every pull request, across PHP 8.1 and 8.4. Previously `release.yml` only fired on tags, so nothing validated a PR at all. +- **A PHPUnit suite** — 24 tests over `ucscgiving_link_filter()` (all six branches), `ucscgiving_fund_url()`, `ucscgiving_fund_search_template()`, `ucscgiving_create_fund_search_variation()` and the two ACF JSON points. -Suggested order: +### Why the tests stub WordPress rather than run inside it -1. Add a `.wp-env.json` so contributors get a reproducible environment from the repo instead of configuring one externally. -2. Add PHPUnit with a small suite around `ucscgiving_link_filter()` and `ucscgiving_fund_url()` — the two functions that independently compute the same URL and are the most likely to drift. -3. Wire lint and tests into CI on pull requests. Today `.github/workflows/release.yml` only runs on tags, so **nothing validates a PR automatically.** +This is the constraint the first version of this section missed, and it drove the whole shape of the harness. + +`ucscgiving_fund_url()` reads `get_field( 'base_url', 'option' )` — an ACF **Pro** options page, registered by the `ucsc-2022` theme rather than by this plugin. Testing it against a real WordPress install therefore needs WordPress **plus** ACF Pro **plus** the theme. ACF Pro is commercial and not on WP.org, so it cannot be installed in GitHub Actions without a licence key held as a repository secret. + +`tests/bootstrap.php` supplies WordPress stand-ins instead, so the suite runs on bare PHP and Composer — no WordPress, no database, no licence, no theme, and no bearing on how anyone runs WordPress locally. It follows the dual-mode bootstrap in [`ucsc/ucsc-blocks`](https://github.com/ucsc/ucsc-blocks): set `WP_TESTS_DIR` and it uses a real WordPress test suite instead. + +### No `.wp-env.json` + +An earlier version of this section recommended committing one. It should not be. [`ucsc/wp-dev.ucsc`](https://github.com/ucsc/wp-dev.ucsc) — a Docker WordPress environment with HTTPS and LDAP — is already the org's shared local environment, and team members use other setups besides. A committed `.wp-env.json` would be a second, competing definition of something already solved, and the unit suite needs no WordPress anyway. Local environment choice stays a per-developer matter. + +### What is still hand-verified + +The suite covers functions that are pure once WordPress is stubbed. Anything needing a running WordPress still has to be checked by hand against an install with ACF Pro and the `ucsc-2022` theme active: + +- block template registration and the markup under `lib/templates/`, +- the ACF JSON save/load round-trip, +- the fund-type save cycle in §1. + +### Org-wide context + +`ucsc-blocks` has had a PHPUnit harness for some time that **no workflow ever runs**, and no sibling repo (`ucsc-communications-functionality`, `ucsc-events-functionality`, `ucsc-news-functionality`, `ucsc-www-functionality`) has a PR check at all. `ci.yml` here is deliberately repo-local for now, and is a good candidate to promote into `ucsc/actions` — which already hosts the shared release workflow — once it has run for a release cycle. ## 4. Harden packaging and templates - **Relative `require` in block templates.** `lib/templates/*.php` use `require 'parts/…'`, which resolves only because PHP falls back to the calling file's directory. Change to `__DIR__`-relative paths. Low effort, removes a latent break. -- **Single URL-construction path.** `ucscgiving_fund_url()` (block binding) and `ucscgiving_link_filter()` (permalink) build the same URL independently. Extract one helper so they cannot diverge. +- **Single URL-construction path.** `ucscgiving_fund_url()` (block binding) and `ucscgiving_link_filter()` (permalink) build the same URL independently. Extract one helper so they cannot diverge. Both now have characterization tests (§3), so the extraction can be made and shown to preserve behavior — this is the cheapest remaining item. ## 5. Maintenance @@ -84,6 +105,7 @@ Suggested order: ## Non-goals +- **Integration tests against a real WordPress install.** Deliberate, not an oversight — see §3. The fund URL path depends on an ACF Pro options page registered by the `ucsc-2022` theme, so automating it in CI would mean holding a commercial licence key as a repository secret. The unit suite covers the logic; the rest is hand-verified. - Rewriting the plugin as class-based / namespaced. The procedural structure is small and consistent; churn here would buy little. - Registering the post type and taxonomies in PHP. `acf-json/` is the working source of truth and the ACF admin round-trips to it. - Shipping a build step for front-end assets. The plugin ships no JavaScript, and `@wordpress/scripts` is used only for `plugin-zip`.