Skip to content

[CI smoke test - do not merge] verify the workflow runs - #1

Closed
coraislovely-code wants to merge 2 commits into
masterfrom
security/0-test-harness
Closed

[CI smoke test - do not merge] verify the workflow runs#1
coraislovely-code wants to merge 2 commits into
masterfrom
security/0-test-harness

Conversation

@coraislovely-code

Copy link
Copy Markdown
Owner

Opened against this fork purely to watch GitHub Actions execute for the first time. Do not merge.

The workflow has never run anywhere — it was written and verified locally, so this is its shakedown. Same approach as the comic-easel repo's PR #1.

Three jobs are expected to appear:

  • php -l (PHP 7.4 … 8.4) — six parallel syntax-lint jobs
  • PHPUnit (PHP 8.2 / 8.3 / 8.4) — the suite runs without WordPress or a database
  • PHPCS (advisory, changed lines) — reports only findings on lines this branch adds, and is deliberately non-blocking

The PHPCS job is the one worth watching. This theme carries several hundred pre-existing findings, so a per-file run would go red on any change to legacy code whether or not it made anything worse. It maps the report onto the diff and reports only added lines, printing a count of what it suppressed so the backlog stays visible.

Closing this once the run is green; the real pull request goes upstream.

coraislovely-code and others added 2 commits July 26, 2026 16:12
The theme has never had a test of any kind. The obstacle has always been that testing a
WordPress theme appears to require WordPress, and therefore a database.

It does not, for the part that matters. The theme's logic -- escaping decisions, SQL
construction, nonce and capability checks on the options screen -- depends only on its
arguments plus a small set of WordPress helpers. Stubbing those gives a suite that runs in
milliseconds with no database, no Docker and no WordPress checkout.

Several of the stubs have to be faithful or the tests they support quietly stop meaning
anything, and this is documented at the top of tests/stubs.php:

- esc_html()/esc_attr() call _wp_specialchars() with $double_encode = false, so they leave
  existing entities alone, while esc_textarea() double-encodes. Much of this theme's
  escaping behaviour turns on that difference, so a naive htmlspecialchars() stub would
  give the wrong answer.
- esc_url() drops a disallowed scheme and esc_attr() does not. An href escaped with
  esc_attr() is well-formed HTML and a working javascript: URL, and several places in the
  theme do exactly that, so the two stubs must not be interchangeable.
- wp_filter_nohtml_kses() is the only sanitiser the options screen uses. WordPress defines
  it as addslashes( wp_kses( stripslashes( $data ), array() ) ): it removes every tag and
  leaves quotes ALONE. A stub that also escaped quotes would make unescaped attribute
  output look safe.
- The nonce functions are a test-driven seam, not a reimplementation. A test can make
  verification pass, make it fail, and -- the part that matters -- see whether it was
  attempted at all, because a handler with no nonce check passes every happy-path test.
- current_user_can() defaults to false, so a missing capability check fails a test instead
  of sailing through one.

Also included is a $wpdb spy that records the SQL it is handed, which is what allows query
construction to be tested without a database. It answers $wpdb->escape() as well, removed
from WordPress in 5.3 but still called by widgets/calendar.php.

Loading theme code needs one wrinkle. functions.php cannot be required from a test: it
calls easel_themeinfo() before defining it, glob-autoloads all of functions/ and widgets/
through get_template_part(), and pulls in options.php under is_admin(). So tests require
one file at a time, and easel_themeinfo()/easel_load_options() are stubbed in the
bootstrap. Those two are worth testing themselves, so the stubs are dispatchers:
Easel_TestCase::loadRealThemeInfo() lifts the real bodies out of functions.php verbatim
and switches both over together. No theme file is modified -- the harness has to be able
to test the theme as shipped.

CI runs php -l across 7.4 through 8.4, PHPUnit on 8.2 through 8.4, and an advisory PHPCS
job scoped to the lines a pull request adds rather than the files it touches. The theme
carries roughly six hundred pre-existing findings; a per-file run would be red by default,
and a job that is always red is a job nobody reads.

HarnessTest.php asserts these properties of the harness itself. If it fails, nothing else
in the suite should be trusted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
These pin the theme's current behaviour rather than the behaviour it
ought to have, so that when the escaping, the request handling and the
option loading are changed the assertions have to be inverted rather
than merely kept passing. Every test says in its docblock what it is
recording and what the change will turn it into.

Covered: how author contact details and the menubar social links are
concatenated into markup, the order in which the options screen reads
the request against its form token, the sanitize_callback names the
customizer registers and the type of its three width settings, the
default array built on a site that has never pressed Save, and two
$_SERVER reads that assume the key is present.

The harness grows three things the new tests needed: a recorder that
stands in for $wp_customize, a helper that lifts a single function out
of functions.php, and a helper that buffers output and collects the
diagnostics a call raises so a test can assert on them instead of the
run failing on them. No theme file is touched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coraislovely-code

Copy link
Copy Markdown
Owner Author

All ten jobs green on the first run: six php -l (7.4 through 8.4, 69 files each), three PHPUnit runs (OK (48 tests, 178 assertions) on 8.2/8.3/8.4), and the advisory PHPCS pass reporting No PHPCS findings on added lines.

Worth noting what this run did not exercise: this branch adds only tests/ and config, and the ruleset excludes tests/, so the PHPCS job had nothing to find. The interesting case — findings on added lines in a legacy file — comes on the later pull requests.

Workflow verified. Closing; the real pull request goes upstream.

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.

1 participant