Skip to content

Add comprehensive PSR-16 cache tests for SSO#368

Merged
superdav42 merged 2 commits intomainfrom
add-sso-cache-tests
Mar 12, 2026
Merged

Add comprehensive PSR-16 cache tests for SSO#368
superdav42 merged 2 commits intomainfrom
add-sso-cache-tests

Conversation

@superdav42
Copy link
Collaborator

@superdav42 superdav42 commented Mar 12, 2026

Summary

This PR adds comprehensive unit and integration tests for the WordPress_Simple_Cache class and fixes the implementation to properly handle all data types including false.

Background

The WordPress_Simple_Cache class was added to replace the symfony/cache dependency which was causing a fatal error due to incompatibility with psr/simple-cache v3.0+.

Changes

Implementation Fixes

  • Use site transients (get_site_transient, set_site_transient, delete_site_transient) for network-wide SSO session storage in multisite
  • Wrap values in array structure ['v' => $value] to properly distinguish false values from missing keys (WordPress returns false for non-existent transients)
  • Update has() to check for wrapped structure
  • Update clear() to use wp_sitemeta table for site transients

New Test Files

  • tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php - PHPUnit test suite (20+ tests)
  • tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php - Standalone integration tests

Test Coverage

WordPress_Simple_Cache_Test.php covers:

  • PSR-16 interface compliance (implements CacheInterface)
  • Basic CRUD operations (get, set, delete)
  • Default value handling
  • Multiple operations (getMultiple, setMultiple, deleteMultiple)
  • Data type preservation including false, null, 0, and empty string
  • TTL handling (null, integer seconds, DateInterval objects)
  • Cache clearing
  • Key existence checking (has())
  • Prefix isolation between cache instances
  • Error cases and edge cases

Fixes

test_stores_different_data_types: The previous implementation couldn't distinguish between a missing key and a false value because WordPress transients return false for both. The fix wraps values in an array structure, allowing proper detection of cached false values.

Notes

Testing

Run with:

vendor/bin/phpunit tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php

Or for standalone integration tests:

php tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php

Add unit tests and integration tests for WordPress_Simple_Cache:
- WordPress_Simple_Cache_Test.php: 20+ PHPUnit tests covering
  all PSR-16 interface methods (get, set, delete, clear, has,
  getMultiple, setMultiple, deleteMultiple)
- WordPress_Simple_Cache_Integration_Test.php: Standalone tests
  that can run without full WordPress test suite

Tests cover:
- Basic CRUD operations
- TTL handling (integer, null, DateInterval)
- Data type preservation (string, int, float, bool, array, object)
- Cache prefix isolation
- Error cases and edge cases
- PSR-16 interface compliance

Cherry-picked from PR #357
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Two comprehensive test suites were added to validate WordPress_Simple_Cache functionality: a PHPUnit-based test class with 15 test methods covering PSR-16 interface compliance, CRUD operations, bulk operations, TTL handling, data types, and prefix isolation; and a standalone integration test class with internal mocks for CLI execution and self-contained testing.

Changes

Cohort / File(s) Summary
WordPress_Simple_Cache Test Suite
tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php, tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php
Added comprehensive test coverage for WordPress_Simple_Cache including PSR-16 interface compliance, basic CRUD operations (get, set, delete, has, clear), bulk operations (getMultiple, setMultiple, deleteMultiple), TTL handling with integer seconds/null/DateInterval, multiple data types (strings, integers, floats, booleans, arrays, objects), cache prefix isolation, and SSO/Jasny SSO integration scenarios. Includes both PHPUnit test class and standalone integration test runner with WordPress transient function mocks.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A warren of tests now guards the cache,
Each scenario checked, each edge case smashed,
PSR-16 compliance shines so bright,
TTLs, prefixes, data types—all right!
This cache integration hops with delight!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add comprehensive PSR-16 cache tests for SSO' accurately reflects the main purpose of the PR, which is adding test coverage for the WordPress_Simple_Cache class with PSR-16 compliance.
Docstring Coverage ✅ Passed Docstring coverage is 91.18% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-sso-cache-tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

Update WordPress_Simple_Cache to:
- Use site transients (get_site_transient, set_site_transient, delete_site_transient)
  for network-wide SSO session storage in multisite
- Wrap values in array structure ['v' => value] to distinguish false values
  from missing keys (WordPress returns false for non-existent transients)
- Update has() to check for wrapped structure
- Update clear() to use wp_sitemeta table

Fixes failing test: test_stores_different_data_types
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php`:
- Around line 42-55: The test harness's mock_wordpress_functions currently only
stubs the *_site_transient variants but WordPress_Simple_Cache calls
get_transient, set_transient, delete_transient and uses clear() which iterates
$wpdb->options, so the standalone runner bypasses the mock store; update
mock_wordpress_functions (or the test runner) to also stub get_transient,
set_transient, delete_transient and a clear implementation that either directly
resets the backing mock array or provide a fake $wpdb->options with the expected
structure so calls from WordPress_Simple_Cache hit the in-memory store instead
of undefined/real WP functions, and ensure tests that call clear() reset that
backing array rather than relying on real DB operations.

In `@tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php`:
- Around line 61-63: The test currently only asserts the cache implements
CacheInterface but doesn't exercise validateKey(), so add explicit tests that
call $this->cache methods to trigger validateKey(): check that empty string
keys, non-string keys (e.g. arrays/objects), and keys containing PSR-16 reserved
characters throw InvalidArgumentException. Extend or add methods in
WordPress_Simple_Cache_Test (e.g. test_invalid_keys_throw) that call
$this->cache->get/set/delete/has with those invalid keys and assert an
InvalidArgumentException is thrown, ensuring validateKey() is covered.
- Around line 216-260: Update the three tests to assert the transient timeout
was recorded rather than only the value: after calling $this->cache->set(...) in
test_ttl_with_integer_seconds and test_ttl_with_date_interval, read the WP
transient timeout option using get_option('_transient_timeout_'.$key) and assert
it exists and is roughly time() + $ttl (for integer) or time() +
$interval_in_seconds (for DateInterval) allowing a small delta; in
test_ttl_with_null assert that get_option('_transient_timeout_'.$key) is false
or not set to confirm no expiration was written. Use the existing test names
(test_ttl_with_integer_seconds, test_ttl_with_date_interval, test_ttl_with_null)
and keep the retrieval/assertion immediately after the set()/get() checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 60fa0b45-7436-4956-93da-e2a41a6df40d

📥 Commits

Reviewing files that changed from the base of the PR and between 60d58dc and 994c71e.

📒 Files selected for processing (2)
  • tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php
  • tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php

Comment on lines +42 to +55
// Mock WordPress functions if they don't exist.
self::mock_wordpress_functions();

// Run tests.
self::test_implements_psr16_interface();
self::test_basic_set_and_get();
self::test_get_with_default();
self::test_delete();
self::test_has();
self::test_clear();
self::test_multiple_operations();
self::test_data_types();
self::test_prefix_isolation();
self::test_ttl_handling();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Mock the transient APIs that the adapter actually calls.

WordPress_Simple_Cache uses get_transient(), set_transient(), delete_transient(), and clear() walks $wpdb->options. This harness only defines the *_site_transient() variants, so the advertised standalone command will bypass the mock store and hit undefined or real WordPress functions as soon as the first cache operation or clear() runs. Either stub the non-site APIs and $wpdb, or reset the backing array directly instead of calling clear() in this runner.

Also applies to: 75-109

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Integration_Test.php` around lines
42 - 55, The test harness's mock_wordpress_functions currently only stubs the
*_site_transient variants but WordPress_Simple_Cache calls get_transient,
set_transient, delete_transient and uses clear() which iterates $wpdb->options,
so the standalone runner bypasses the mock store; update
mock_wordpress_functions (or the test runner) to also stub get_transient,
set_transient, delete_transient and a clear implementation that either directly
resets the backing mock array or provide a fake $wpdb->options with the expected
structure so calls from WordPress_Simple_Cache hit the in-memory store instead
of undefined/real WP functions, and ensure tests that call clear() reset that
backing array rather than relying on real DB operations.

Comment on lines +61 to +63
public function test_implements_psr16_cache_interface(): void {
$this->assertInstanceOf(CacheInterface::class, $this->cache);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add explicit invalid-key coverage.

This suite never exercises validateKey(). Empty keys, non-string keys, and reserved-character keys can regress without failing the current "PSR-16 compliance" test.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php` around lines 61 - 63,
The test currently only asserts the cache implements CacheInterface but doesn't
exercise validateKey(), so add explicit tests that call $this->cache methods to
trigger validateKey(): check that empty string keys, non-string keys (e.g.
arrays/objects), and keys containing PSR-16 reserved characters throw
InvalidArgumentException. Extend or add methods in WordPress_Simple_Cache_Test
(e.g. test_invalid_keys_throw) that call $this->cache->get/set/delete/has with
those invalid keys and assert an InvalidArgumentException is thrown, ensuring
validateKey() is covered.

Comment on lines +216 to +260
public function test_ttl_with_integer_seconds(): void {
$key = 'ttl_test_key';
$value = 'ttl_test_value';
$ttl = 60; // 60 seconds.

$result = $this->cache->set($key, $value, $ttl);
$this->assertTrue($result);

// Value should be retrievable.
$retrieved = $this->cache->get($key);
$this->assertSame($value, $retrieved);

// Note: We can't easily test expiration in unit tests without time manipulation.
// The transient is set with the correct expiration time.
}

/**
* Test TTL with null (no expiration).
*/
public function test_ttl_with_null(): void {
$key = 'no_ttl_key';
$value = 'no_ttl_value';

$result = $this->cache->set($key, $value, null);
$this->assertTrue($result);

// Value should be retrievable.
$retrieved = $this->cache->get($key);
$this->assertSame($value, $retrieved);
}

/**
* Test TTL with DateInterval.
*/
public function test_ttl_with_date_interval(): void {
$key = 'dateinterval_key';
$value = 'dateinterval_value';
$interval = new \DateInterval('PT1H'); // 1 hour.

$result = $this->cache->set($key, $value, $interval);
$this->assertTrue($result);

// Value should be retrievable.
$retrieved = $this->cache->get($key);
$this->assertSame($value, $retrieved);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

These TTL tests don't verify that a timeout was actually written.

Each case only checks that the value is readable immediately after set(). If the adapter ignored the supplied TTL and stored everything with no expiration, all three tests would still pass. Please assert the transient timeout for the integer / DateInterval cases and the absence of a timeout for null.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/WP_Ultimo/SSO/WordPress_Simple_Cache_Test.php` around lines 216 - 260,
Update the three tests to assert the transient timeout was recorded rather than
only the value: after calling $this->cache->set(...) in
test_ttl_with_integer_seconds and test_ttl_with_date_interval, read the WP
transient timeout option using get_option('_transient_timeout_'.$key) and assert
it exists and is roughly time() + $ttl (for integer) or time() +
$interval_in_seconds (for DateInterval) allowing a small delta; in
test_ttl_with_null assert that get_option('_transient_timeout_'.$key) is false
or not set to confirm no expiration was written. Use the existing test names
(test_ttl_with_integer_seconds, test_ttl_with_date_interval, test_ttl_with_null)
and keep the retrieval/assertion immediately after the set()/get() checks.

@github-actions
Copy link

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@superdav42 superdav42 merged commit e97ded0 into main Mar 12, 2026
8 of 9 checks passed
@superdav42 superdav42 deleted the add-sso-cache-tests branch March 12, 2026 23:34
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