| 1 |
<?php |
| 2 |
/** |
| 3 |
* Integration tests for plugin activation — table creation and default options. |
| 4 |
* |
| 5 |
* @package Custom_404_Pro |
| 6 |
*/ |
| 7 |
|
| 8 |
/** |
| 9 |
* Tests that ActivateClass creates the correct database schema and seeds defaults. |
| 10 |
*/ |
| 11 |
class C404P_Integration_ActivationTest extends WP_UnitTestCase { |
| 12 |
|
| 13 |
/** |
| 14 |
* Tear down: drop the logs table so DDL does not leak between tests. |
| 15 |
* |
| 16 |
* dbDelta issues DDL (CREATE TABLE), which implicitly commits any open |
| 17 |
* transaction. The logs table must therefore be dropped manually rather |
| 18 |
* than relying on WP_UnitTestCase's transaction rollback. |
| 19 |
*/ |
| 20 |
public function tearDown(): void { |
| 21 |
global $wpdb; |
| 22 |
$helpers = new Helpers(); |
| 23 |
$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $helpers->table_logs ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared |
| 24 |
delete_option( Helpers::OPTION_KEY ); |
| 25 |
parent::tearDown(); |
| 26 |
} |
| 27 |
|
| 28 |
/** |
| 29 |
* create_tables() should create the logs table. |
| 30 |
*/ |
| 31 |
public function test_create_tables_creates_logs_table() { |
| 32 |
global $wpdb; |
| 33 |
ActivateClass::create_tables(); |
| 34 |
$helpers = new Helpers(); |
| 35 |
$wpdb->suppress_errors( true ); |
| 36 |
$result = $wpdb->get_var( 'SELECT COUNT(*) FROM ' . $wpdb->prefix . $helpers->table_logs ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared |
| 37 |
$wpdb->suppress_errors( false ); |
| 38 |
$this->assertNotNull( $result, 'Logs table should exist after create_tables().' ); |
| 39 |
} |
| 40 |
|
| 41 |
/** |
| 42 |
* Logs table should have the expected columns. |
| 43 |
*/ |
| 44 |
public function test_logs_table_has_correct_columns() { |
| 45 |
global $wpdb; |
| 46 |
ActivateClass::create_tables(); |
| 47 |
$helpers = new Helpers(); |
| 48 |
$columns = $wpdb->get_col( 'SHOW COLUMNS FROM ' . $wpdb->prefix . $helpers->table_logs ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared |
| 49 |
$expected = array( 'id', 'ip', 'path', 'referer', 'user_agent', 'created', 'updated' ); |
| 50 |
foreach ( $expected as $col ) { |
| 51 |
$this->assertContains( $col, $columns, "Logs table should have column '{$col}'." ); |
| 52 |
} |
| 53 |
} |
| 54 |
|
| 55 |
/** |
| 56 |
* initialize_options() should create the wp_options entry. |
| 57 |
*/ |
| 58 |
public function test_initialize_options_creates_wp_options_entry() { |
| 59 |
ActivateClass::initialize_options(); |
| 60 |
$stored = get_option( Helpers::OPTION_KEY ); |
| 61 |
$this->assertIsArray( $stored, 'initialize_options() should create a wp_options entry.' ); |
| 62 |
} |
| 63 |
|
| 64 |
/** |
| 65 |
* initialize_options() should store all default setting keys. |
| 66 |
*/ |
| 67 |
public function test_initialize_options_stores_all_default_keys() { |
| 68 |
ActivateClass::initialize_options(); |
| 69 |
$helpers = new Helpers(); |
| 70 |
$stored = get_option( Helpers::OPTION_KEY ); |
| 71 |
$expected = array_keys( $helpers->defaults() ); |
| 72 |
foreach ( $expected as $key ) { |
| 73 |
$this->assertArrayHasKey( $key, $stored, "Default key '{$key}' should be present after initialize_options()." ); |
| 74 |
} |
| 75 |
} |
| 76 |
|
| 77 |
/** |
| 78 |
* initialize_options() should not overwrite existing settings on re-activation. |
| 79 |
*/ |
| 80 |
public function test_initialize_options_does_not_overwrite_existing_settings() { |
| 81 |
// Simulate a saved setting from a previous activation. |
| 82 |
update_option( Helpers::OPTION_KEY, array( 'mode' => 'url', 'mode_url' => 'https://example.com' ) ); |
| 83 |
ActivateClass::initialize_options(); |
| 84 |
$stored = get_option( Helpers::OPTION_KEY ); |
| 85 |
$this->assertSame( 'url', $stored['mode'], 'Re-activation should not overwrite existing settings.' ); |
| 86 |
} |
| 87 |
|
| 88 |
/** |
| 89 |
* maybe_migrate_legacy_options() should be a no-op when no legacy table exists. |
| 90 |
*/ |
| 91 |
public function test_maybe_migrate_legacy_options_is_noop_when_no_legacy_table() { |
| 92 |
ActivateClass::maybe_migrate_legacy_options(); |
| 93 |
// No exception and no wp_options entry created means the no-op path ran. |
| 94 |
$this->assertFalse( get_option( Helpers::OPTION_KEY ), 'No wp_options entry should be created when there is nothing to migrate.' ); |
| 95 |
} |
| 96 |
} |
| 97 |
|