test: Search PHPUnit tests#213
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds PHPUnit unit tests for the Search module’s WordPress integration points and for the Algolia Index wrapper, helping validate hook registration and several “remote post” mapping behaviors.
Changes:
- Add
SearchTestcovering hook registration and selected behaviors for permalinks, author fields, term links, and rendered block rewriting. - Add
IndexTestcovering error returns when prerequisites are missing and verifyingIndex::get_index()caching behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| tests/php/Unit/Modules/Search/SearchTest.php | Introduces unit tests for OneSearch\Modules\Search\Search behaviors (hooks, mapping, block output). |
| tests/php/Unit/Modules/Search/IndexTest.php | Introduces unit tests for OneSearch\Modules\Search\Index error handling and caching. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sabbir1991
left a comment
There was a problem hiding this comment.
Please review the coverage HTML again and check the functions are fully covered which test you have written
… Index and Search modules
…s during delete, save, and search operations
…t, and WatcherTest
justlevine
left a comment
There was a problem hiding this comment.
Great first pass! 🙌 Especially a fan of daab8dc before I even asked ;-)
Just some minor cleanup and trying to cover the few areas the coverage report missed. We'll be refactoring soon though, so if something I asked for isn't easily testable, lmk and maybe we'll skip it.
…ling and remove unused code
…ges in SettingsTest and WatcherTest
… resets and updating settings test logic
justlevine
left a comment
There was a problem hiding this comment.
These look good!
I'm wondering if it's worth it for you to do one more pass through the coverage report, and see if there's some more low-hanging you can catch here, e.g. from a brand site, w. author info, composite scores, > 100 posts, etc. Still outcome based, nothing that requires elaborate stubbing.
Alternatively, we can skip them now add the coverage to the areas that we refactor, the missing areas aren't particularly important for back-compat, just catching unintentional breaks...
@Kallyan01 can you take a look at the report and let me know which - if any - you think are worth doing now vs later?
Sure, I've started looking into it, I'll let you know if I find something. |
|
@justlevine I think the key public methods are already well covered. If needed, we can add additional tests to cover the logic implemented in the private methods as well, like compute_algolia_score, extract_algolia_highlights, build_post_from_record, split_content_into_chunks, etc. Let me know your thoughts. |
Utsav-Ladani
left a comment
There was a problem hiding this comment.
CI checks are failing due to GH token issue else LGTM.
cc @justlevine |
|
|
||
| /** | ||
| * Ensures register_hooks adds expected actions. | ||
| */ | ||
| public function test_register_hooks_adds_expected_actions(): void { | ||
| $settings = new Search_Settings(); | ||
| $settings->register_hooks(); | ||
|
|
||
| $this->assertNotFalse( has_action( 'admin_init', [ $settings, 'register_settings' ] ) ); | ||
| $this->assertNotFalse( has_action( 'rest_api_init', [ $settings, 'register_settings' ] ) ); | ||
| } | ||
|
|
||
| /** | ||
| * Ensures register_hooks listens to site_type, shared_sites option updates. | ||
| */ | ||
| public function test_register_hooks_listens_to_site_type_changes(): void { | ||
| $settings = new Search_Settings(); | ||
| $settings->register_hooks(); | ||
|
|
||
| $this->assertNotFalse( | ||
| has_action( 'update_option_' . Settings::OPTION_SITE_TYPE, [ $settings, 'on_site_type_change' ] ) | ||
| ); | ||
| $this->assertNotFalse( | ||
| has_action( 'update_option_' . Settings::OPTION_GOVERNING_SHARED_SITES, [ $settings, 'on_shared_sites_change' ] ) | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Ensures register_hooks sets up cache purge hooks. | ||
| */ | ||
| public function test_register_hooks_sets_up_cache_purge_actions(): void { | ||
| $settings = new Search_Settings(); | ||
| $settings->register_hooks(); | ||
|
|
||
| $this->assertNotFalse( | ||
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_ALGOLIA_CREDENTIALS, [ $settings, 'purge_cache_on_update' ] ) | ||
| ); | ||
| $this->assertNotFalse( | ||
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_INDEXABLE_SITES, [ $settings, 'purge_cache_on_update' ] ) | ||
| ); | ||
| $this->assertNotFalse( | ||
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_SEARCH_SETTINGS, [ $settings, 'purge_cache_on_update' ] ) | ||
| ); | ||
| } |
There was a problem hiding this comment.
Unless the action is only conditionally enqueued, we never need to test that add_action() or add_filter() work. Checking if specific functions are hooked is fragile and unnecessary.
| /** | |
| * Ensures register_hooks adds expected actions. | |
| */ | |
| public function test_register_hooks_adds_expected_actions(): void { | |
| $settings = new Search_Settings(); | |
| $settings->register_hooks(); | |
| $this->assertNotFalse( has_action( 'admin_init', [ $settings, 'register_settings' ] ) ); | |
| $this->assertNotFalse( has_action( 'rest_api_init', [ $settings, 'register_settings' ] ) ); | |
| } | |
| /** | |
| * Ensures register_hooks listens to site_type, shared_sites option updates. | |
| */ | |
| public function test_register_hooks_listens_to_site_type_changes(): void { | |
| $settings = new Search_Settings(); | |
| $settings->register_hooks(); | |
| $this->assertNotFalse( | |
| has_action( 'update_option_' . Settings::OPTION_SITE_TYPE, [ $settings, 'on_site_type_change' ] ) | |
| ); | |
| $this->assertNotFalse( | |
| has_action( 'update_option_' . Settings::OPTION_GOVERNING_SHARED_SITES, [ $settings, 'on_shared_sites_change' ] ) | |
| ); | |
| } | |
| /** | |
| * Ensures register_hooks sets up cache purge hooks. | |
| */ | |
| public function test_register_hooks_sets_up_cache_purge_actions(): void { | |
| $settings = new Search_Settings(); | |
| $settings->register_hooks(); | |
| $this->assertNotFalse( | |
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_ALGOLIA_CREDENTIALS, [ $settings, 'purge_cache_on_update' ] ) | |
| ); | |
| $this->assertNotFalse( | |
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_INDEXABLE_SITES, [ $settings, 'purge_cache_on_update' ] ) | |
| ); | |
| $this->assertNotFalse( | |
| has_action( 'update_option_' . Search_Settings::OPTION_GOVERNING_SEARCH_SETTINGS, [ $settings, 'purge_cache_on_update' ] ) | |
| ); | |
| } | |
| /** | |
| * Ensures register_hooks adds expected actions. | |
| */ | |
| public function test_class_instantiation(): void { | |
| $settings = new Search_Settings(); | |
| $settings->register_hooks(); | |
| // If we made it here without erroring, we're good. | |
| $this->assertTrue( true ); | |
| } |
| /** | ||
| * Ensures register_hooks adds transition_post_status action. | ||
| */ | ||
| public function test_register_hooks_adds_transition_post_status_action(): void { | ||
| $watcher = new Watcher(); | ||
| $watcher->register_hooks(); | ||
|
|
||
| $this->assertNotFalse( has_action( 'transition_post_status', [ $watcher, 'on_post_transition' ] ) ); | ||
| } |
There was a problem hiding this comment.
| /** | |
| * Ensures register_hooks adds transition_post_status action. | |
| */ | |
| public function test_register_hooks_adds_transition_post_status_action(): void { | |
| $watcher = new Watcher(); | |
| $watcher->register_hooks(); | |
| $this->assertNotFalse( has_action( 'transition_post_status', [ $watcher, 'on_post_transition' ] ) ); | |
| } | |
| /** | |
| * Ensures the class is initialized correctly | |
| */ | |
| public function test_class_instantiation(): void { | |
| $watcher = new Watcher(); | |
| $watcher->register_hooks(); | |
| // If we made it this far, we're good. | |
| $this->assertTrue( true ); | |
| } |
justlevine
left a comment
There was a problem hiding this comment.
Last two open comments, and this should be good to merge.
If needed, we can add additional tests to cover the logic implemented in the private methods as well, like compute_algolia_score, extract_algolia_highlights, build_post_from_record, split_content_into_chunks, etc. Let me know your thoughts.
I think we've got enough in place for now, especially as its not fully clear to me which of those implementation details will be necessary in the future. We can backfill them as we update Algolia to v4 and our wrappers accordingly. 🚀
What
Added Search Module PHPUnit test cases.
Why
Improves development workflow by enabling faster and more reliable validation of REST functionality, reducing repetitive manual testing efforts.
Related Issue(s):
How
AI Disclosure
Hybrid approach = Written by Me + Copilot (Claude Opus 4.6, GPT 5.3) + Audited by me
Testing Instructions
Screenshots
Additional Info
Checklist