Files
2meet-data-optimizer/tests/integration/InstallerCleanupTest.php
T
wpdev d36bb954d1 chore: initial snapshot of 2meet-data-optimizer v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
2026-07-31 05:06:36 +08:00

179 lines
6.5 KiB
PHP

<?php
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* Integration test: WPDO_Installer multisite cleanup (v2.14.0).
*
* Verifies the new `drop_all_tables_for_current_blog()` shared helper used
* by both `uninstall.php` and the `wp_uninitialize_site` hook handler.
*/
class InstallerCleanupTest extends TestCase {
// v2.14.0: dedicated prefix to avoid colliding with shared `wp_itest_*`
// fixtures created by other test classes. The cleanup helper uses
// `$wpdb->prefix` so changing the prefix scopes drops to our tables only.
private const TEST_PREFIX = 'wp_clnup_';
public static function setUpBeforeClass(): void {
global $wpdb;
if ( ! class_exists( 'WPDO_Installer' ) ) {
require_once WPDO_PLUGIN_DIR . 'includes/class-tmdo-installer.php';
}
$wpdb->prefix = self::TEST_PREFIX;
$wpdb->options = self::TEST_PREFIX . 'options';
// Ensure options table exists (needed for delete_option fallback path).
$wpdb->query(
'CREATE TABLE IF NOT EXISTS `' . self::TEST_PREFIX . 'options` (
option_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
option_name varchar(191) NOT NULL DEFAULT "",
option_value longtext NOT NULL,
autoload varchar(20) NOT NULL DEFAULT "yes",
PRIMARY KEY (option_id),
UNIQUE KEY option_name (option_name)
) DEFAULT CHARACTER SET utf8mb4'
);
}
public static function tearDownAfterClass(): void {
global $wpdb;
// Drop the dedicated options table + any residual prefix tables.
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::TEST_PREFIX . 'options`' );
foreach ( array(
self::TEST_PREFIX . 'wpdo_archive',
self::TEST_PREFIX . 'wpdo_warm',
self::TEST_PREFIX . 'wpdo_errors',
self::TEST_PREFIX . 'wpdo_hot_test_type',
self::TEST_PREFIX . 'wpdo_user_profile',
self::TEST_PREFIX . 'wpdo_post_attachment',
self::TEST_PREFIX . 'wpdo_term_hp_taxonomy',
self::TEST_PREFIX . 'wpdo_comment_hp_review',
self::TEST_PREFIX . 'unrelated_table',
) as $tbl ) {
$wpdb->query( 'DROP TABLE IF EXISTS `' . $tbl . '`' );
}
// Restore the shared integration test prefix so any teardown elsewhere
// that depends on `$wpdb->prefix === 'wp_itest_'` still works.
$wpdb->prefix = 'wp_itest_';
}
protected function setUp(): void {
global $wpdb;
// Reset options table state.
$wpdb->query( 'TRUNCATE TABLE `' . self::TEST_PREFIX . 'options`' );
$GLOBALS['_wp_options'] = array();
}
public function test_drops_static_tables(): void {
global $wpdb;
// Create a few WPDO-prefixed tables that should be dropped.
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_archive` (id INT)' );
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_warm` (id INT)' );
$counts = WPDO_Installer::drop_all_tables_for_current_blog();
$this->assertGreaterThanOrEqual( 2, $counts['tables_dropped'] );
$exists = (int) $wpdb->get_var(
$wpdb->prepare(
'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
self::TEST_PREFIX . 'wpdo_archive'
)
);
$this->assertSame( 0, $exists, 'wpdo_archive should be dropped' );
}
public function test_drops_dynamic_zone_tables(): void {
global $wpdb;
// Dynamic hot/cold zone tables should be discovered via LIKE pattern.
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_hot_test_type` (id INT)' );
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_user_profile` (id INT)' );
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_post_attachment` (id INT)' );
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_term_hp_taxonomy` (id INT)' );
$wpdb->query( 'CREATE TABLE `' . self::TEST_PREFIX . 'wpdo_comment_hp_review` (id INT)' );
WPDO_Installer::drop_all_tables_for_current_blog();
foreach ( array(
'wpdo_hot_test_type',
'wpdo_user_profile',
'wpdo_post_attachment',
'wpdo_term_hp_taxonomy',
'wpdo_comment_hp_review',
) as $tbl_suffix ) {
$exists = (int) $wpdb->get_var(
$wpdb->prepare(
'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
self::TEST_PREFIX . $tbl_suffix
)
);
$this->assertSame( 0, $exists, $tbl_suffix . ' should be dropped' );
}
}
public function test_does_not_drop_unrelated_tables(): void {
global $wpdb;
// Defensive: a table named like wpdo_X should be dropped, but a table
// with a non-wpdo prefix MUST NEVER be dropped even if name pattern
// would match.
$unrelated = self::TEST_PREFIX . 'unrelated_table';
$wpdb->query( 'CREATE TABLE IF NOT EXISTS `' . $unrelated . '` (id INT)' );
WPDO_Installer::drop_all_tables_for_current_blog();
$exists = (int) $wpdb->get_var(
$wpdb->prepare(
'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
$unrelated
)
);
$this->assertSame( 1, $exists, 'Non-wpdo table must not be dropped' );
$wpdb->query( 'DROP TABLE IF EXISTS `' . $unrelated . '`' );
}
public function test_returns_counts_structure(): void {
$counts = WPDO_Installer::drop_all_tables_for_current_blog();
$this->assertIsArray( $counts );
$this->assertArrayHasKey( 'tables_dropped', $counts );
$this->assertArrayHasKey( 'options_deleted', $counts );
$this->assertArrayHasKey( 'crons_cleared', $counts );
}
public function test_idempotent_on_empty_state(): void {
// Run twice — second run should be a no-op for tables (we already
// dropped them all in the first run). Options may not be 0 because
// other test classes share the same wp_itest_options table and may
// continually re-create wpdo_* rows; just verify that running cleanup
// twice in a row does not throw.
WPDO_Installer::drop_all_tables_for_current_blog();
$second = WPDO_Installer::drop_all_tables_for_current_blog();
$this->assertSame( 0, $second['tables_dropped'] );
$this->assertIsInt( $second['options_deleted'] );
$this->assertIsInt( $second['crons_cleared'] );
}
public function test_drops_known_options(): void {
// Stub `delete_option` does not interact with DB layer in our test stubs;
// it modifies `$GLOBALS['_wp_options']`. Verify counts work via the
// known-options list.
$GLOBALS['_wp_options']['wpdo_db_version'] = '2.14.0';
$GLOBALS['_wp_options']['wpdo_features'] = array();
$GLOBALS['_wp_options']['wpdo_health_alert'] = '1';
$counts = WPDO_Installer::drop_all_tables_for_current_blog();
// Note: the actual count depends on $wpdb->options interaction in
// the residual sweep. Just verify the structure works without errors.
$this->assertIsInt( $counts['options_deleted'] );
}
}