test: add PHPUnit harness and CI matrix (no behavior changes)#157
test: add PHPUnit harness and CI matrix (no behavior changes)#157dokun1 wants to merge 11 commits intogharlan:mainfrom
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a PHPUnit-based characterization test harness and CI execution for the existing Alfred GitHub Workflow code, establishing a green baseline before future behavioral changes (e.g., multi-account support).
Changes:
- Add PHPUnit dev dependency +
composer testscript, plus aphpunit.xml.distconfiguration. - Introduce a bootstrap and base test case to isolate
Workflow’s static state and per-test SQLite data dirs. - Add unit/characterization tests for
Workflow,Item::toXml, andCurlRequest, and run them in a GitHub Actions PHP version matrix.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
tests/bootstrap.php |
Loads production code for tests and provides helper functions to isolate/reset Workflow static state. |
tests/WorkflowTestCase.php |
Base PHPUnit test case that sets per-test temp alfred_workflow_data and resets Workflow. |
tests/WorkflowConfigTest.php |
Characterizes config set/get/remove behavior. |
tests/WorkflowTokenTest.php |
Characterizes github vs enterprise token slot isolation/removal behavior. |
tests/WorkflowSchemaTest.php |
Pins SQLite schema and idempotent init behavior. |
tests/WorkflowEnterpriseUrlTest.php |
Pins base/api/gist URL derivation rules and API URL query building. |
tests/CurlRequestTest.php |
Validates CurlRequest constructor field assignment and nullability. |
tests/ItemRenderTest.php |
Characterizes Item::toXml output rules (escaping, prefixes, arg rewriting, ordering). |
phpunit.xml.dist |
PHPUnit configuration (bootstrap, cache dir, strictness flags, suite discovery). |
composer.json |
Adds phpunit/phpunit to require-dev and a test script. |
.gitignore |
Ignores PHPUnit cache, vendor artifacts, and composer.phar. |
.github/workflows/test.yml |
Runs the PHPUnit suite on push/PR across PHP 8.2–8.4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ]; | ||
| foreach ($resets as $name => $value) { | ||
| if ($ref->hasProperty($name)) { | ||
| $prop = $ref->getProperty($name); |
There was a problem hiding this comment.
agw_test_reset_workflow() uses reflection to reset Workflow's private static properties, but it never makes the ReflectionProperty accessible. On PHP 8.2+ this will throw when calling setValue() for private/protected properties, causing the entire test suite to fail. Set $prop->setAccessible(true) (or use another visibility-bypassing approach) before setting values.
| $prop = $ref->getProperty($name); | |
| $prop = $ref->getProperty($name); | |
| $prop->setAccessible(true); |
| chdir(__DIR__.'/..'); | ||
| require __DIR__.'/../workflow.php'; |
There was a problem hiding this comment.
tests/bootstrap.php changes the process working directory via chdir(__DIR__.'/..') and leaves it there for the rest of the PHPUnit run. This can make future tests/order-dependent behavior fragile (any relative path access will now resolve from repo root). Consider capturing the original CWD and restoring it after requiring workflow.php so bootstrap has minimal global side effects.
| chdir(__DIR__.'/..'); | |
| require __DIR__.'/../workflow.php'; | |
| $originalCwd = getcwd(); | |
| chdir(__DIR__.'/..'); | |
| try { | |
| require __DIR__.'/../workflow.php'; | |
| } finally { | |
| if (false !== $originalCwd) { | |
| chdir($originalCwd); | |
| } | |
| } |
Summary
This PR introduces a test harness with zero behavior changes to the workflow itself. It adds PHPUnit as a dev dependency, a bootstrap + base test case for isolating
Workflow's static state, six test files that pin the current single/dual-slot behavior, and a GitHub Actions matrix that runs the suite on every push and pull request.No production files (
workflow.php,curl.php,item.php,search.php,action.php,server.php,info.plist,.php-cs-fixer.dist.php) are touched. The onlycomposer.jsonedit is addingphpunit/phpunit: ^11.0torequire-dev.My motivation is a follow-up PR to add multi-account support (multiple github.com tokens + multiple enterprise instances with an active-account switcher). That change will touch token storage,
request_cachepartitioning, and the OAuth callback — areas where characterization tests would catch regressions early. I wanted to land the harness first so the multi-account PR can be reviewed against a green baseline. This PR is independently useful even if the multi-account work never lands — the tests document current behavior and protect future refactors.What is pinned
tests/WorkflowConfigTest.phpsetConfig/getConfig/removeConfiground-trip, defaults, overwritetests/WorkflowTokenTest.phpaccess_tokenvsenterprise_access_tokenisolation, per-slot removetests/WorkflowSchemaTest.phpconfigandrequest_cachecolumn shapes,parent_urlindex, idempotent re-inittests/WorkflowEnterpriseUrlTest.phpbaseUrl/apiUrl/gistUrlderivation fromenterprise_urlconfig, per-page query buildingtests/CurlRequestTest.phpCurlRequestconstructor field assignment, nullable token/etagtests/ItemRenderTest.phpItem::toXmloutput — uid hashing, icon fallback, enterpriseeprefixing,baseUrlarg rewrite, autocomplete rules, HTML escaping, valid/invalid suffixingTotal: 30 tests, 59 assertions, <50ms locally.
Test-harness implementation notes
tests/bootstrap.phpchdirs into the repo root before requiringworkflow.php, becauseworkflow.phpuses relativerequire 'item.php'/require 'curl.php'. Touching those requires would be a behavior change and is out of scope.tests/WorkflowTestCase.phpgives each test its own tempalfred_workflow_datadirectory and uses reflection to resetWorkflow's static properties between tests. This is necessary becauseWorkflowis a static class and without it the SQLite handle and prepared statements leak across tests.CurlRequestis tested as a value object only.CI matrix
PHP 8.2 / 8.3 / 8.4 on
ubuntu-latest, viashivammathur/setup-php@v2. No coverage,composer:v2, extensions pinned to what the workflow actually imports (pdo,pdo_sqlite,sqlite3,curl,simplexml).I picked 8.2 as the floor because:
composer.jsondoes not declare a minimum PHP version, so there's nothing authoritative to defer to.?Curl $curl = nullinworkflow.php) that requires PHP 8.0+.Happy to adjust the matrix if you'd rather support older versions or drop 8.4 until it's more widely deployed.
What is explicitly NOT in this PR
.phpsource filecomposer.lock(already gitignored by the project)If you'd prefer a narrower first cut (e.g. only the
ItemRenderTestwithout theWorkflow*tests, or without CI), I'm happy to split it — just let me know.Test plan
vendor/bin/phpunitpasses locally on PHP 8.5 (30/30)git diff upstream/main...HEAD -- '*.php' ':!tests/*'is empty)