Files
2meet-data-optimizer/tests/unit/EntityRegistryCollisionTest.php
T
wpdev e9d8696c93 fix(2meet-data-optimizer): report entity group name collisions instead of silently dropping
- register_group() keeps the first definition but records a field diff (added/removed/changed) when the same entity/group is re-registered differently; identical re-registration stays silent
- Surface collisions via Site Health (wpdo_entity_group_collisions), the admin Doctor tab, and wp wpdo doctor; warning log throttled to once a day
- Verify: EntityRegistryCollisionTest (7); core unit 613 / integration 432, HP 141/49, WC 10/22 OK
- PR: PR-017
2026-09-25 23:27:05 +08:00

98 lines
4.2 KiB
PHP

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* Entity group name collisions.
*
* Two providers registering the same entity/group name used to have the
* second definition dropped with no trace. Identical re-registration (core
* re-fires the registration hooks on init:1) stays silent; a different
* definition is recorded with a field diff and surfaced in Site Health.
*/
class EntityRegistryCollisionTest extends TestCase {
protected function setUp(): void {
if ( ! class_exists( 'TMDO_Site_Health' ) ) {
require_once TMDO_PATH . 'includes/diagnostic/class-tmdo-site-health.php';
}
TMDO_Entity_Registry::init();
TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) );
$GLOBALS['_wp_options'] = array();
}
private function first_definition(): array {
return array(
array( 'key' => 'hp_price', 'type' => 'decimal', 'searchable' => true ),
array( 'key' => 'hp_featured', 'type' => 'boolean' ),
);
}
public function test_identical_reregistration_is_silent(): void {
$this->assertTrue( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() ) );
$this->assertFalse( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() ) );
$this->assertSame( array(), TMDO_Entity_Registry::get_collisions() );
}
public function test_different_definition_is_recorded_with_field_diff(): void {
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
$second = array(
array( 'key' => 'hp_price', 'type' => 'integer', 'searchable' => true ),
array( 'key' => 'hp_vendor', 'type' => 'integer' ),
);
$this->assertFalse( TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $second ) );
$collisions = TMDO_Entity_Registry::get_collisions();
$this->assertCount( 1, $collisions );
$this->assertSame( 'post', $collisions[0]['entity_type'] );
$this->assertSame( 'hp_listing_core', $collisions[0]['group'] );
$this->assertSame( array( 'hp_vendor' ), $collisions[0]['added'] );
$this->assertSame( array( 'hp_featured' ), $collisions[0]['removed'] );
$this->assertSame( array( 'hp_price' ), $collisions[0]['changed'] );
}
public function test_first_definition_wins(): void {
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', array( array( 'key' => 'hp_vendor', 'type' => 'integer' ) ) );
$this->assertSame( array( 'hp_price', 'hp_featured' ), TMDO_Entity_Registry::get_group_keys( 'post', 'hp_listing_core' ) );
$this->assertNull( TMDO_Entity_Registry::get_field( 'post', 'hp_vendor' ) );
}
public function test_same_collision_is_recorded_once_per_request(): void {
TMDO_Entity_Registry::register_group( 'post', 'g', $this->first_definition() );
$other = array( array( 'key' => 'x', 'type' => 'text' ) );
TMDO_Entity_Registry::register_group( 'post', 'g', $other );
TMDO_Entity_Registry::register_group( 'post', 'g', $other );
$this->assertCount( 1, TMDO_Entity_Registry::get_collisions() );
}
public function test_init_clears_collisions(): void {
TMDO_Entity_Registry::register_group( 'post', 'g', $this->first_definition() );
TMDO_Entity_Registry::register_group( 'post', 'g', array( array( 'key' => 'x', 'type' => 'text' ) ) );
TMDO_Entity_Registry::init();
$this->assertSame( array(), TMDO_Entity_Registry::get_collisions() );
}
public function test_site_health_reports_collisions(): void {
$this->assertSame( 'good', TMDO_Site_Health::check_entity_group_collisions()['status'] );
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', $this->first_definition() );
TMDO_Entity_Registry::register_group( 'post', 'hp_listing_core', array( array( 'key' => 'x', 'type' => 'text' ) ) );
$result = TMDO_Site_Health::check_entity_group_collisions();
$this->assertSame( 'recommended', $result['status'] );
$this->assertStringContainsString( 'post/hp_listing_core', $result['description'] );
}
public function test_site_health_registers_the_collision_test(): void {
$tests = TMDO_Site_Health::register_tests( array() );
$this->assertArrayHasKey( 'wpdo_entity_group_collisions', $tests['direct'] );
}
}