test: add comprehensive unit test suites for PHP and JS - #177
Conversation
…rify-sync failures Fills the highest-value zero-coverage zones found in the coverage audit. PHPUnit (70 -> 166 tests): - ColorResolverTest: golden light/dark hex maps, alias/step invariants, key-set parity, and override + malicious-fallback paths for the previously untested pure resolver. - CssGeneratorDerivedOverridesTest: radius/border/motion scale expansion and fmt_num() edges (reflection over the pure private helpers). - RestControllerSanitizeOverridesTest: the `--sf-` name gate and type-drop on the flat override map (complements the existing value-allowlist tests). - RestControllerSettingsValidatorsTest: html_font_size / css_bundle allowlists and the configurator_url http(s) gate (javascript:/data: breakout). - CategoryMapTest and TokenDefaultsShapeTest: pure lookup + data-shape invariants. JS (144 -> 151 tests): - verify-sync-failures.test.js: fixture-based proof that runChecks() actually fires on every version-metadata drift, not just that the committed tree passes. Enabling, behavior-preserving refactors: - Extract the three POST /settings validate_callbacks to public static predicates so they can be unit-tested in isolation. - Make verify-sync runChecks(root) honour a custom checkout root instead of throwing, so failure paths can be exercised against a fixture tree. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNzFE6py1whVTmrohL34Ra
|
Warning Review limit reached
Next review available in: 17 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughRefactors REST controller inline validation closures into static validator methods, parameterizes verify-sync.js helpers with an explicit root path, and adds extensive PHPUnit tests (Category Map, Color Resolver, CSS Generator, sanitize_overrides, settings validators, Token Defaults) plus Node tests for verify-sync failure paths. ChangesREST Controller Validator Refactor
Verify-Sync Root Parameterization
PHP Test Suite Additions
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
PR Summary by QodoAdd PHP unit tests and verify-sync failure-path JS tests
AI Description
Diagram
High-Level Assessment
Files changed (10)
|
There was a problem hiding this comment.
🧹 Nitpick comments (3)
tests-php/RestControllerSettingsValidatorsTest.php (1)
41-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
optimal-utilitiesto the bundles data provider.
Slashed_Token_Store::ALLOWED_CSS_BUNDLEScontains four values, but the positive cases only cover three. Addingoptimal-utilitieswould complete the allowlist coverage.As per coding guidelines,
tests-php/contains the PHPUnit suite for pure/near-pure PHP logic that does not require a WordPress runtime.♻️ Suggested addition
return array( 'optimal' => array( 'optimal', true ), 'optimal-components' => array( 'optimal-components', true ), + 'optimal-utilities' => array( 'optimal-utilities', true ), 'full' => array( 'full', true ), 'unknown' => array( 'kitchen-sink', false ), 'empty' => array( '', false ), );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests-php/RestControllerSettingsValidatorsTest.php` around lines 41 - 49, The bundles data provider in bundles() is missing coverage for the full allowlist exposed by Slashed_Token_Store::ALLOWED_CSS_BUNDLES. Add a positive case for optimal-utilities alongside the existing optimal, optimal-components, and full entries so the PHPUnit test fully exercises all allowed CSS bundle values.Source: Coding guidelines
tests/verify-sync-failures.test.js (2)
36-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove unused
cssNameparameter fromentryhelper.The second argument is passed
'x'at all three call sites but never referenced in the template string. Removing it eliminates a potential source of confusion for future maintainers.♻️ Proposed fix
- const entry = (cssRef, cssName, verName) => + const entry = (cssRef, verName) => `<?php\n/**\n * Version: ${PV}\n */\n` + `define( '${cssRef}', 'v${FW}' );\n` + `define( '${verName}', '${PV}' );\n`;And update call sites:
- write(root, `${PLUGIN}/slashed.php`, entry('SLASHED_CSS_REF', 'x', 'SLASHED_VERSION')); - write(root, `${PLUGIN}/integrations/bricks/slashed-bricks.php`, entry('SLASHED_BRICKS_CSS_REF', 'x', 'SLASHED_BRICKS_VERSION')); - write(root, `${PLUGIN}/integrations/gutenberg/slashed-gutenberg.php`, entry('SLASHED_GUTENBERG_CSS_REF', 'x', 'SLASHED_GUTENBERG_VERSION')); + write(root, `${PLUGIN}/slashed.php`, entry('SLASHED_CSS_REF', 'SLASHED_VERSION')); + write(root, `${PLUGIN}/integrations/bricks/slashed-bricks.php`, entry('SLASHED_BRICKS_CSS_REF', 'SLASHED_BRICKS_VERSION')); + write(root, `${PLUGIN}/integrations/gutenberg/slashed-gutenberg.php`, entry('SLASHED_GUTENBERG_CSS_REF', 'SLASHED_GUTENBERG_VERSION'));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/verify-sync-failures.test.js` around lines 36 - 39, The entry helper in verify-sync-failures.test.js has an unused cssName parameter that is passed as 'x' at every call site but never used in the template. Remove cssName from the entry function signature and update each call site to pass only the two referenced arguments. Keep the helper name entry and the existing cssRef/verName usage intact so the intent stays clear.
31-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding null-path ("cannot find") failure tests.
The suite covers drift/mismatch scenarios well, but
runChecksalso has null-return paths that aren't exercised: missing dist header (line 103), missing CSS_REF define (line 122), missing Version: header (line 148), and missing VERSION constant define (line 153). Adding tests for these would fully prove that every error branch fires, strengthening the PR's stated goal.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/verify-sync-failures.test.js` around lines 31 - 110, Add test coverage for the null-return “cannot find” branches in runChecks so every error path is exercised. Extend verify-sync-failures.test.js with cases that remove the dist header, the CSS_REF define, the Version: header, and the VERSION constant define, then assert the resulting errors mention the corresponding missing symbol or file. Use the existing runChecks helper and the fixture setup in buildFixture to keep the tests aligned with the current drift/mismatch coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests-php/RestControllerSettingsValidatorsTest.php`:
- Around line 41-49: The bundles data provider in bundles() is missing coverage
for the full allowlist exposed by Slashed_Token_Store::ALLOWED_CSS_BUNDLES. Add
a positive case for optimal-utilities alongside the existing optimal,
optimal-components, and full entries so the PHPUnit test fully exercises all
allowed CSS bundle values.
In `@tests/verify-sync-failures.test.js`:
- Around line 36-39: The entry helper in verify-sync-failures.test.js has an
unused cssName parameter that is passed as 'x' at every call site but never used
in the template. Remove cssName from the entry function signature and update
each call site to pass only the two referenced arguments. Keep the helper name
entry and the existing cssRef/verName usage intact so the intent stays clear.
- Around line 31-110: Add test coverage for the null-return “cannot find”
branches in runChecks so every error path is exercised. Extend
verify-sync-failures.test.js with cases that remove the dist header, the CSS_REF
define, the Version: header, and the VERSION constant define, then assert the
resulting errors mention the corresponding missing symbol or file. Use the
existing runChecks helper and the fixture setup in buildFixture to keep the
tests aligned with the current drift/mismatch coverage.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: ef20fd22-3788-4baa-b207-3413681f077f
📒 Files selected for processing (10)
SLASHED-for-WP/includes/class-rest-controller.phpscripts/verify-sync.jstests-php/CategoryMapTest.phptests-php/ColorResolverTest.phptests-php/CssGeneratorDerivedOverridesTest.phptests-php/RestControllerSanitizeOverridesTest.phptests-php/RestControllerSettingsValidatorsTest.phptests-php/TokenDefaultsShapeTest.phptests-php/bootstrap.phptests/verify-sync-failures.test.js
Code Review by Qodo
Context used✅ Compliance rules (platform):
8 rules 1. runChecks throws on ENOENT
|
| function read(root, rel) { | ||
| return fs.readFileSync(path.join(root, rel), 'utf8'); | ||
| } | ||
|
|
||
| function sha256(rel) { | ||
| return crypto.createHash('sha256').update(fs.readFileSync(path.join(ROOT, rel))).digest('hex'); | ||
| function sha256(root, rel) { | ||
| return crypto.createHash('sha256').update(fs.readFileSync(path.join(root, rel))).digest('hex'); | ||
| } |
There was a problem hiding this comment.
1. Runchecks throws on enoent 🐞 Bug ☼ Reliability
runChecks(root) now supports custom roots, but it still uses synchronous readFileSync()/hash reads without try/catch, so a missing file under a fixture root aborts the entire check instead of returning errors[]. This makes the new test/fixture-based usage less robust and can turn simple drift into a hard crash.
Agent Prompt
### Issue description
`runChecks(root)` is intentionally callable against fixture trees now, but missing or unreadable required files (ENOENT/EACCES/etc.) cause an immediate synchronous throw from `fs.readFileSync()`, preventing `runChecks()` from returning a complete structured `{ errors, info }` report.
### Issue Context
This behavior was less likely when `root` was effectively fixed to the repo checkout. With custom roots supported, partial fixtures or intentionally broken trees (or future callers) can hit missing paths.
### Fix Focus Areas
- Add safe file read helpers that catch fs errors and push descriptive messages into `errors` instead of throwing.
- Ensure all required reads/hashes in `runChecks()` use the safe helpers.
- Prefer continuing checks to collect as many inconsistencies as possible.
### Fix Focus Areas (code references)
- scripts/verify-sync.js[59-87]
- scripts/verify-sync.js[95-155]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| public function test_source_and_hex_hint_groups_share_identical_keys( $source_group, $hint_group ) { | ||
| $colors = Slashed_Token_Defaults::get_colors(); | ||
| $this->assertArrayHasKey( $source_group, $colors ); | ||
| $this->assertArrayHasKey( $hint_group, $colors ); | ||
| $this->assertSame( | ||
| array_keys( $colors[ $source_group ] ), | ||
| array_keys( $colors[ $hint_group ] ), | ||
| "$hint_group keys must mirror $source_group" | ||
| ); |
There was a problem hiding this comment.
2. Order-sensitive keys assertion 🐞 Bug ⚙ Maintainability
TokenDefaultsShapeTest::test_source_and_hex_hint_groups_share_identical_keys() compares array_keys() with assertSame(), which also asserts insertion order, not just key-set equality. This can fail on harmless reordering even though the test comment describes only “identical keys”.
Agent Prompt
### Issue description
The test intends to ensure the source and *_hex_hints groups cover the same families, but it currently fails if the two arrays contain the same keys in different insertion order.
### Issue Context
Order can change during refactors (e.g., formatting/reordering defaults) without changing semantics, so enforcing order here increases brittleness.
### Fix Focus Areas
- Sort both `array_keys(...)` results before comparing, or use PHPUnit canonicalizing assertions.
### Fix Focus Areas (code references)
- tests-php/TokenDefaultsShapeTest.php[40-48]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Extends the plain-PHP suite past the "pure logic only" boundary using hand-rolled in-memory get_option/update_option/delete_option/apply_filters stubs (in the spirit of the existing sanitize_key stub — no mocking framework, no WordPress install), turning two previously WP-runtime-only classes into covered ones: - TokenStoreTest: overrides round-trip, corrupt-option recovery, plugin- settings default merge, retired-key stripping, and standalone-mode css_bundle. - CssGeneratorEmissionTest: the store -> re-validate -> @layer emission path, proving the emitter drops unsafe/misnamed stored values, keeps has_overrides() in agreement, and expands scale knobs (with explicit tokens winning). PHPUnit: 166 -> 180 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNzFE6py1whVTmrohL34Ra
The class/variable hint generators had no unit tests, so a future change to the framework's CSS section-comment format or api-index.json shape would produce wrong hints that the drift check can only flag as *changed*, never as *wrong*. Extract the pure transforms and guard the CLI side effects behind a main-module check (like verify-sync.js) so the modules are importable: - gen-class-hints.js: export parseCss(src, category), applyCuratedHints(parsed), MANUAL_HINTS, OVERRIDE_HINTS. - gen-variables-hints.js: export buildVariableHints(apiIndex). Add tests against synthetic fixtures (no framework checkout needed): - parseCss: section-desc → base+modifier inheritance, multi-section split, is-* capture, title fallback, comment-only and pre-section classes ignored. - applyCuratedHints: override-wins / manual-fills-gap / manual-doesn't-override precedence, input not mutated. - buildVariableHints: token+--sf- filtering, `--` stripping, category default, empty/malformed input tolerance. CLI output is unchanged: `npm run check` still emits 67 class + 729 variable hints and passes. JS suite: 151 -> 164 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YNzFE6py1whVTmrohL34Ra
Summary
Adds comprehensive unit test coverage for pure/near-pure logic across the plugin:
PHP tests (
tests-php/):ColorResolverTest— golden-value + invariant tests forSlashed_Color_Resolver(light/dark mode, scale derivation, semantic aliases)CssGeneratorDerivedOverridesTest— scale-knob expansion logic (--sf-radius-scale,--sf-border-scale,--sf-motion-scale) via reflectionTokenDefaultsShapeTest— structural invariants forSlashed_Token_Defaults(section routing, hex-hint pairing, fluid ramp ordering)CategoryMapTest— first-segment → category-label lookup and display-order listRestControllerSanitizeOverridesTest— override name/value sanitization (property-name gate, type coercion, injection prevention)RestControllerSettingsValidatorsTest— POST/settingsallowlists (font sizes, CSS bundles, configurator URL scheme gate)JS tests (
tests/verify-sync-failures.test.js):verify-sync'srunChecks()— builds minimal fixture checkouts, confirms clean state passes, then mutates version metadata one piece at a time to prove each check actually fires (dist bundle versions, CSS_REF constants, inventory.json copies, readme.txt Stable tag, plugin Version: headers, *_VERSION constants)Refactoring:
validate_callbackclosures fromSlashed_REST_Controller::register_routes()into public static methods (is_allowed_html_font_size(),is_allowed_css_bundle(),is_valid_configurator_url()) so the allowlists are testable in isolationverify-sync.jsto accept an optionalrootparameter (defaults toROOT) so tests can point the same logic at fixture trees with deliberately broken metadataAll tests are pure (no WordPress runtime except stubs in
tests-php/bootstrap.php) and cover the dependency-free approximations and invariants that guard against silent visual/functional drift.Type
Checklist
feat:,fix:,docs:, …)npm testpassesnpm run lintpasses (stylelint +php -l)npm run verifypasses (version metadata in sync)CHANGELOG.mdupdated (no user-facing changes)editor-app/admin-appsource changed (N/A)Notes
composer phpunit(wired into CI'squalityjob)node --test tests/verify-sync-failures.test.jsnpm testand CIhttps://claude.ai/code/session_01YNzFE6py1whVTmrohL34Ra
Summary by CodeRabbit