Files
2meet-data-optimizer/tests/integration/InstallerV2Test.php
wpdev fc0f018a94 fix(2meet-data-optimizer): stop auto-activating entity bridge on install
- install() no longer switches the Hook Bus on or puts user/term/comment
  into dual_write; the now-unused maybe_autoactivate_entity_bridge() is gone
- Hook Bus and Mode_Manager defaults are off/disabled; sites with stored
  modes (incl. aeav_only) keep them since only unset keys use defaults
- Guard run_dbdelta()'s upgrade.php require like install_v2_tables() so
  install() can run under the integration test stub

Verify: InstallerV2Test::test_install_does_not_enable_entity_bridge,
  ModeManagerDefaultsTest; unit 602 OK, integration 421 OK
PR: PR-007
2026-09-25 21:48:23 +08:00

132 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* Integration test for WPDO_Installer::install_v2_tables() — PR-2 v2.0.0 schema.
*
* Verifies idempotent table creation for:
* - wp_*_wpdo_audit
* - wp_*_wpdo_shadow_diffs
* - wp_*_wpdo_site_metrics
* - wp_*_wpdo_uni_options
*
* @covers WPDO_Installer::install_v2_tables
* @covers WPDO_Installer::v2_tables_status
*/
class InstallerV2Test extends TestCase {
public static function setUpBeforeClass(): void {
// Drop v2 tables for a clean slate.
global $wpdb;
$p = $wpdb->prefix;
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_audit`" );
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_shadow_diffs`" );
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_site_metrics`" );
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_uni_options`" );
}
public function test_v2_tables_initially_absent(): void {
$status = WPDO_Installer::v2_tables_status();
foreach ( $status as $table => $exists ) {
$this->assertFalse( $exists, "Expected {$table} to NOT exist initially" );
}
}
public function test_install_v2_tables_creates_all_four(): void {
WPDO_Installer::install_v2_tables();
$status = WPDO_Installer::v2_tables_status();
foreach ( $status as $table => $exists ) {
$this->assertTrue( $exists, "Expected {$table} to exist after install_v2_tables()" );
}
}
public function test_install_v2_tables_is_idempotent(): void {
WPDO_Installer::install_v2_tables();
WPDO_Installer::install_v2_tables(); // Second call must not error.
WPDO_Installer::install_v2_tables(); // Third for good measure.
$status = WPDO_Installer::v2_tables_status();
$this->assertCount( 4, $status );
$this->assertTrue( array_reduce( $status, static fn( $carry, $v ) => $carry && $v, true ) );
}
public function test_audit_table_has_required_columns(): void {
global $wpdb;
$p = $wpdb->prefix;
$cols = $wpdb->get_col( "SHOW COLUMNS FROM `{$p}wpdo_audit`" );
// PR-2 spec: op, value_before, value_after, source, trace_id are required.
foreach ( array( 'op', 'value_before', 'value_after', 'source', 'trace_id' ) as $required ) {
$this->assertContains( $required, $cols, "wpdo_audit missing column {$required}" );
}
}
public function test_shadow_diffs_table_has_required_columns(): void {
global $wpdb;
$p = $wpdb->prefix;
$cols = $wpdb->get_col( "SHOW COLUMNS FROM `{$p}wpdo_shadow_diffs`" );
foreach ( array( 'entity_type', 'entity_id', 'meta_key', 'postmeta_value', 'zone_value', 'diff_hash' ) as $required ) {
$this->assertContains( $required, $cols, "wpdo_shadow_diffs missing column {$required}" );
}
}
public function test_uni_options_has_unique_index_on_option_name(): void {
global $wpdb;
$p = $wpdb->prefix;
$indexes = $wpdb->get_results(
$wpdb->prepare(
'SELECT INDEX_NAME, COLUMN_NAME, NON_UNIQUE FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
$p . 'wpdo_uni_options'
),
ARRAY_A
);
$found_unique = false;
foreach ( $indexes as $idx ) {
if ( 'option_name' === $idx['COLUMN_NAME'] && '0' === (string) $idx['NON_UNIQUE'] ) {
$found_unique = true;
break;
}
}
$this->assertTrue( $found_unique, 'Expected UNIQUE index on wpdo_uni_options.option_name' );
}
public function test_audit_table_indexes_for_query_performance(): void {
global $wpdb;
$p = $wpdb->prefix;
$indexes = $wpdb->get_col(
$wpdb->prepare(
'SELECT DISTINCT INDEX_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
$p . 'wpdo_audit'
)
);
// Performance-critical indexes per Part F.3 schema spec.
foreach ( array( 'idx_entity', 'idx_meta_key', 'idx_ts', 'idx_trace' ) as $required ) {
$this->assertContains( $required, $indexes, "wpdo_audit missing index {$required}" );
}
}
public function test_install_does_not_enable_entity_bridge(): void {
delete_option( 'wpdo_hook_bus_enabled' );
delete_option( 'wpdo_bridge_modes' );
delete_option( 'wpdo_entity_bridge_autoactivated_v2' );
// Skip the crypto step: it queries $wpdb->options, which InstallerCleanupTest leaves pointing at its own prefix.
update_option( 'wpdo_crypto_migrated_v2', '1' );
TMDO_Installer::install();
$this->assertFalse( get_option( 'wpdo_hook_bus_enabled' ), 'install() must not switch the Hook Bus on' );
$this->assertFalse( get_option( 'wpdo_bridge_modes' ), 'install() must not write bridge modes' );
}
public static function tearDownAfterClass(): void {
// Leave v2 tables in place for subsequent tests / dev convenience.
// Cleanup happens via wp wpdo cleanup-uae-tables --confirm in real upgrades.
}
}