f48df1a33f
- WooCommerce reads product meta directly and writes stock by SQL, so a flat copy drifted (R-2.1 V1 T4); product meta now stays in native only (plan decision 2). TMDO_Post_Fields registers wp_core, attachment and nav_menu_item. Existing wp_wpdo_post_wc_product tables are left in place and still dropped on uninstall; the orphan restore registers nothing for them while native meta holds the keys; `wp tmdo bridge-restore-native post --group=wc_product --retire` archives them. - Tests that route products register the former group themselves (tmdo_test_register_wc_product_group(), same name and table); live router Q06 runs on wp_core's _wp_page_template instead of _sku. The post stress tester already skips flat tables that do not exist. - Verify: PostFieldsRegistrationTest (RED before); dev36: wc_product absent from the registry and not restored as an orphan, a CLI order took stock 452 → 450 in native with no DB error (reverted), drift post 10 groups 0. - PR: PR-077
158 lines
6.8 KiB
PHP
158 lines
6.8 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Unit tests for WPDO_Post_Fields entity group registration (v2.9.1).
|
|
*
|
|
* Verifies that register_entity_fields() correctly registers all four
|
|
* post groups with the expected field counts, types, and post_type targets.
|
|
*
|
|
* Mirrors MemberFieldsRegistrationTest's structure.
|
|
*/
|
|
class PostFieldsRegistrationTest extends TestCase {
|
|
|
|
protected function setUp(): void {
|
|
if ( ! class_exists( 'WPDO_Post_Fields' ) ) {
|
|
require_once WPDO_PLUGIN_DIR . 'includes/integrations/class-tmdo-post-fields.php';
|
|
}
|
|
if ( ! class_exists( 'WPDO_Adapter_Post' ) ) {
|
|
require_once WPDO_PLUGIN_DIR . 'includes/adapters/class-tmdo-adapter-post.php';
|
|
}
|
|
|
|
WPDO_Entity_Registry::init();
|
|
WPDO_Entity_Registry::register_adapter( 'post', new WPDO_Adapter_Post() );
|
|
}
|
|
|
|
// ── Group presence ───────────────────────────────────────────────────────
|
|
|
|
public function test_register_entity_fields_does_not_throw_on_double_call(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
WPDO_Post_Fields::register_entity_fields(); // dedup guard
|
|
$this->assertTrue( true );
|
|
}
|
|
|
|
public function test_the_core_groups_are_registered(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
|
|
$expected = array(
|
|
'wp_core',
|
|
'attachment',
|
|
'nav_menu_item',
|
|
);
|
|
|
|
foreach ( $expected as $group ) {
|
|
$fields = WPDO_Entity_Registry::get_group_fields( 'post', $group );
|
|
$this->assertNotEmpty( $fields, "Group '{$group}' should have registered fields." );
|
|
}
|
|
}
|
|
|
|
public function test_user_entity_groups_are_not_touched(): void {
|
|
// 🔒 Frozen contract: post fields registration must not register
|
|
// any group under entity_type='user'.
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$user_groups = WPDO_Entity_Registry::get_groups_for_type( 'user' );
|
|
$this->assertEmpty( $user_groups, 'WPDO_Post_Fields must not touch user entity registry.' );
|
|
}
|
|
|
|
// ── wp_core group (cross post_type) ──────────────────────────────────────
|
|
|
|
public function test_wp_core_group_has_expected_keys(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$keys = $this->get_field_keys( 'wp_core' );
|
|
$this->assertContains( '_thumbnail_id', $keys );
|
|
$this->assertContains( '_wp_page_template', $keys );
|
|
$this->assertContains( '_edit_last', $keys );
|
|
}
|
|
|
|
public function test_wp_core_thumbnail_is_searchable(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$field = $this->find_field( 'wp_core', '_thumbnail_id' );
|
|
$this->assertNotNull( $field );
|
|
$this->assertSame( 'integer', $field['type'] );
|
|
$this->assertTrue( (bool) ( $field['searchable'] ?? false ) );
|
|
}
|
|
|
|
// ── attachment group ─────────────────────────────────────────────────────
|
|
|
|
public function test_attachment_group_has_expected_keys(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$keys = $this->get_field_keys( 'attachment' );
|
|
$this->assertContains( '_wp_attached_file', $keys );
|
|
$this->assertContains( '_wp_attachment_metadata', $keys );
|
|
$this->assertContains( '_wp_attachment_image_alt', $keys );
|
|
}
|
|
|
|
public function test_attachment_metadata_is_json_type(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$field = $this->find_field( 'attachment', '_wp_attachment_metadata' );
|
|
$this->assertNotNull( $field );
|
|
$this->assertSame( 'json', $field['type'] );
|
|
}
|
|
|
|
// ── WooCommerce products stay in native meta (2.2 PR-077) ───────────────
|
|
|
|
public function test_core_registers_no_woocommerce_product_group(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
|
|
$this->assertSame( array(), WPDO_Entity_Registry::get_group_fields( 'post', 'wc_product' ), 'WooCommerce reads and writes product meta directly (stock by SQL)' );
|
|
$this->assertNull( WPDO_Entity_Registry::get_field( 'post', '_price', 'product' ) );
|
|
$this->assertSame( array(), WPDO_Post_Fields::groups_for_post_type( 'product' ) );
|
|
}
|
|
|
|
// ── HivePress groups moved to the HivePress AddOn ───────────────────────
|
|
|
|
public function test_core_registers_no_hivepress_groups(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
foreach ( array( 'hp_listing_core', 'hp_request_core', 'hp_vendor_core' ) as $group ) {
|
|
$this->assertSame( array(), WPDO_Entity_Registry::get_group_fields( 'post', $group ), "{$group} is owned by the HivePress AddOn" );
|
|
}
|
|
}
|
|
|
|
// ── group ↔ post_type mapping ────────────────────────────────────────────
|
|
|
|
public function test_core_groups_map_to_their_post_types(): void {
|
|
$this->assertSame( 'attachment', WPDO_Post_Fields::post_type_for_group( 'attachment' ) );
|
|
$this->assertSame( 'nav_menu_item', WPDO_Post_Fields::post_type_for_group( 'nav_menu_item' ) );
|
|
$this->assertNull( WPDO_Post_Fields::post_type_for_group( 'wp_core' ), 'wp_core spans every post type' );
|
|
}
|
|
|
|
public function test_scoped_groups_map_through_the_registry(): void {
|
|
WPDO_Entity_Registry::register_group( 'post', 'x_core', array( array( 'key' => 'x_price', 'type' => 'decimal' ) ), array( 'post_types' => array( 'x_type' ) ) );
|
|
|
|
$this->assertSame( 'x_type', WPDO_Post_Fields::post_type_for_group( 'x_core' ) );
|
|
$this->assertSame( array( 'x_core' ), WPDO_Post_Fields::groups_for_post_type( 'x_type' ) );
|
|
$this->assertNull( WPDO_Post_Fields::post_type_for_group( 'hp_listing_core' ), 'unregistered HivePress group is unknown to core' );
|
|
}
|
|
|
|
// ── nav_menu_item group ──────────────────────────────────────────────────
|
|
|
|
public function test_nav_menu_item_has_8_keys(): void {
|
|
WPDO_Post_Fields::register_entity_fields();
|
|
$keys = $this->get_field_keys( 'nav_menu_item' );
|
|
$this->assertCount( 8, $keys );
|
|
$this->assertContains( '_menu_item_type', $keys );
|
|
$this->assertContains( '_menu_item_object_id', $keys );
|
|
$this->assertContains( '_menu_item_url', $keys );
|
|
}
|
|
|
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
|
|
/** @return string[] */
|
|
private function get_field_keys( string $group ): array {
|
|
$fields = WPDO_Entity_Registry::get_group_fields( 'post', $group );
|
|
return array_map( static fn( $f ) => $f['key'], $fields );
|
|
}
|
|
|
|
private function find_field( string $group, string $key ): ?array {
|
|
$fields = WPDO_Entity_Registry::get_group_fields( 'post', $group );
|
|
foreach ( $fields as $f ) {
|
|
if ( ( $f['key'] ?? '' ) === $key ) {
|
|
return $f;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|