diff --git a/tests/unit/HivePressEntityGroupsTest.php b/tests/unit/HivePressEntityGroupsTest.php index fa917d2..dc4be8a 100644 --- a/tests/unit/HivePressEntityGroupsTest.php +++ b/tests/unit/HivePressEntityGroupsTest.php @@ -7,74 +7,63 @@ use PHPUnit\Framework\TestCase; * The AddOn owns the HivePress entity groups core used to register. * * Their definitions are persisted (wpdo_registry_meta schema hash) and the - * flat tables on live sites were built from core's version, so the AddOn must - * register byte-identical definitions: any drift changes the schema hash and - * would ALTER tables that hold aeav_only data once core stops registering - * them (PR-020). + * flat tables on live sites were built from them, so they are pinned to the + * persisted hashes: any drift would ALTER flat tables that may hold + * aeav_only data. (Values recorded on dev20, 2026-09-25.) */ class HivePressEntityGroupsTest extends TestCase { - private const GROUPS = array( - array( 'post', 'hp_listing_core' ), - array( 'post', 'hp_request_core' ), - array( 'post', 'hp_vendor_core' ), - array( 'user', 'hp_user' ), + private const PERSISTED_HASHES = array( + 'post/hp_listing_core' => 'fb5ab760', + 'post/hp_request_core' => '27d6f4f5', + 'post/hp_vendor_core' => '5366e5c8', + 'user/hp_user' => '61ac526f', ); - private function fresh_registry(): void { + /** + * Keys shared by several post groups resolve to the LAST group registered + * (the post entity has a single field index, not one per post_type). + * + * ⚠️ This pins current behaviour, not desired behaviour: a listing's + * hp_rating is routed to the hp_vendor_core table, its hp_status to + * hp_request_core, etc. It is pinned so that moving the registration + * between plugins cannot change routing silently; fixing the routing is + * tracked separately in the backlog. + */ + private const SHARED_KEY_OWNERS = array( + 'hp_status' => 'hp_request_core', + 'hp_expired_time' => 'hp_request_core', + 'hp_view_count' => 'hp_request_core', + 'hp_verified' => 'hp_vendor_core', + 'hp_rating' => 'hp_vendor_core', + 'hp_rating_count' => 'hp_vendor_core', + 'hp_hourly_rate' => 'hp_vendor_core', + 'hp_user' => 'hp_vendor_core', + ); + + protected function setUp(): void { TMDO_Entity_Registry::init(); TMDO_Entity_Registry::register_adapter( 'post', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); TMDO_Entity_Registry::register_adapter( 'user', $this->createMock( TMDO_Entity_Adapter_Interface::class ) ); - } - - private function register_core(): void { - TMDO_Post_Fields::register_entity_fields(); - TMDO_Member_Fields::register_entity_fields(); - } - - public function test_definitions_match_core_exactly(): void { - $this->fresh_registry(); - $this->register_core(); - $core = array(); - foreach ( self::GROUPS as $g ) { - $core[ $g[1] ] = TMDO_Entity_Registry::get_group_fields( $g[0], $g[1] ); - } - - $this->fresh_registry(); TMDO_HivePress_Entity_Groups::register_entity_fields(); + } - foreach ( self::GROUPS as $g ) { - $this->assertNotEmpty( $core[ $g[1] ], "core no longer registers {$g[1]}" ); - $this->assertSame( $core[ $g[1] ], TMDO_Entity_Registry::get_group_fields( $g[0], $g[1] ), "{$g[0]}/{$g[1]} drifted from core" ); + public function test_definitions_match_persisted_schema_hashes(): void { + foreach ( self::PERSISTED_HASHES as $id => $hash ) { + list( $type, $group ) = explode( '/', $id ); + $fields = TMDO_Entity_Registry::get_group_fields( $type, $group ); + $this->assertNotEmpty( $fields, "{$id} not registered" ); + $this->assertSame( $hash, substr( TMDO_Schema_Manager::calculate_schema_hash( $fields ), 0, 8 ), "{$id} drifted from the persisted definition" ); } } - public function test_shared_keys_resolve_to_the_same_group_as_core(): void { - // hp_status / hp_user / hp_view_count … appear in several post groups and - // field_index is last-registered-wins, so registration order matters. - $this->fresh_registry(); - $this->register_core(); - $core = array(); - foreach ( self::GROUPS as $g ) { - foreach ( TMDO_Entity_Registry::get_group_keys( $g[0], $g[1] ) as $key ) { - $core[ $g[0] . ':' . $key ] = TMDO_Entity_Registry::get_field( $g[0], $key )['group']; - } - } - - $this->fresh_registry(); - TMDO_HivePress_Entity_Groups::register_entity_fields(); - - foreach ( $core as $id => $group ) { - list( $type, $key ) = explode( ':', $id, 2 ); - $this->assertSame( $group, TMDO_Entity_Registry::get_field( $type, $key )['group'], $id ); + public function test_shared_keys_keep_their_current_owner(): void { + foreach ( self::SHARED_KEY_OWNERS as $key => $group ) { + $this->assertSame( $group, TMDO_Entity_Registry::get_field( 'post', $key )['group'], $key ); } } - public function test_registering_alongside_core_raises_no_collision(): void { - $this->fresh_registry(); - $this->register_core(); - - TMDO_HivePress_Entity_Groups::register_entity_fields(); + public function test_core_adapter_does_not_register_a_conflicting_group(): void { ( new TMDO_HivePress_Core_Adapter() )->on_register_entity_fields(); $this->assertSame( array(), TMDO_Entity_Registry::get_collisions() );