d36bb954d1
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
162 lines
6.1 KiB
PHP
162 lines
6.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Tests for WPDO_Zone_Hot — flat-column custom tables for search/filter fields.
|
|
*
|
|
* Uses an in-memory mock to intercept $wpdb calls.
|
|
*/
|
|
class ZoneHotTest extends TestCase {
|
|
|
|
/** Last SQL query string passed to $wpdb->query(). */
|
|
public static string $last_query = '';
|
|
|
|
/** Arguments passed to $wpdb->delete(). */
|
|
public static array $last_delete = [];
|
|
|
|
/** Return value for get_var mock. */
|
|
public static ?string $get_var_return = null;
|
|
|
|
/** Return value for get_row mock. */
|
|
public static mixed $get_row_return = null;
|
|
|
|
protected function setUp(): void {
|
|
self::$last_query = '';
|
|
self::$last_delete = [];
|
|
self::$get_var_return = null;
|
|
self::$get_row_return = null;
|
|
$this->setup_wpdb_mock();
|
|
}
|
|
|
|
private function setup_wpdb_mock(): void {
|
|
global $wpdb;
|
|
|
|
$wpdb = new class {
|
|
public string $prefix = 'wp_';
|
|
|
|
public function prepare( string $sql, ...$args ): string {
|
|
$i = 0;
|
|
return preg_replace_callback( '/%([sd])/', function ( $m ) use ( &$i, $args ) {
|
|
$val = $args[ $i++ ] ?? '';
|
|
return $m[1] === 'd' ? (string) (int) $val : "'" . addslashes( (string) $val ) . "'";
|
|
}, $sql );
|
|
}
|
|
|
|
public function get_var( string $sql ): ?string {
|
|
return ZoneHotTest::$get_var_return;
|
|
}
|
|
|
|
public function get_row( string $sql, $output = OBJECT ) {
|
|
return ZoneHotTest::$get_row_return;
|
|
}
|
|
|
|
public function get_results( string $sql, $output = OBJECT ): array {
|
|
return [];
|
|
}
|
|
|
|
public function insert( string $table, array $data, $format = null ): int|false {
|
|
return 1;
|
|
}
|
|
|
|
public function update( string $table, array $data, array $where, $format = null, $where_format = null ): int|false {
|
|
return 1;
|
|
}
|
|
|
|
public function delete( string $table, array $where, $format = null ): int|false {
|
|
ZoneHotTest::$last_delete = [ 'table' => $table, 'where' => $where ];
|
|
return 1;
|
|
}
|
|
|
|
public function query( string $sql ): int|bool {
|
|
ZoneHotTest::$last_query = $sql;
|
|
return 1;
|
|
}
|
|
};
|
|
}
|
|
|
|
// ── table() ──────────────────────────────────────────────────────────────
|
|
|
|
public function test_table_returns_prefixed_name(): void {
|
|
$this->assertSame( 'wp_wpdo_hot_hp_listing', WPDO_Zone_Hot::table( 'hp_listing' ) );
|
|
}
|
|
|
|
public function test_table_sanitizes_post_type(): void {
|
|
// The test sanitize_key stub strips non-[a-z0-9_-] chars then lowercases.
|
|
// 'HP Listing!' → strip uppercase H,P + space + '!' → 'isting' → lower → 'isting'.
|
|
$sanitized = sanitize_key( 'HP Listing!' );
|
|
$this->assertSame( 'wp_wpdo_hot_' . $sanitized, WPDO_Zone_Hot::table( 'HP Listing!' ) );
|
|
}
|
|
|
|
// ── get() ─────────────────────────────────────────────────────────────────
|
|
|
|
public function test_get_returns_null_when_row_missing(): void {
|
|
self::$get_var_return = null;
|
|
$result = WPDO_Zone_Hot::get( 1, 'hp_listing', 'hp_price' );
|
|
$this->assertNull( $result );
|
|
}
|
|
|
|
public function test_get_returns_value_from_db(): void {
|
|
self::$get_var_return = '42';
|
|
$result = WPDO_Zone_Hot::get( 1, 'hp_listing', 'hp_price' );
|
|
$this->assertSame( '42', $result );
|
|
}
|
|
|
|
// ── get_row() ────────────────────────────────────────────────────────────
|
|
|
|
public function test_get_row_returns_null_when_missing(): void {
|
|
self::$get_row_return = null;
|
|
$result = WPDO_Zone_Hot::get_row( 1, 'hp_listing' );
|
|
$this->assertNull( $result );
|
|
}
|
|
|
|
public function test_get_row_returns_array(): void {
|
|
$expected = [ 'post_id' => 1, 'hp_price' => '100', 'hp_location' => 'NYC' ];
|
|
self::$get_row_return = $expected;
|
|
$result = WPDO_Zone_Hot::get_row( 1, 'hp_listing' );
|
|
$this->assertSame( $expected, $result );
|
|
}
|
|
|
|
// ── set() ─────────────────────────────────────────────────────────────────
|
|
|
|
public function test_set_executes_upsert_query(): void {
|
|
WPDO_Zone_Hot::set( 5, 'hp_listing', 'hp_price', '99' );
|
|
$this->assertNotEmpty( self::$last_query, 'Expected $wpdb->query() to be called' );
|
|
$this->assertStringContainsString( 'ON DUPLICATE KEY UPDATE', self::$last_query );
|
|
}
|
|
|
|
// ── set_many() ───────────────────────────────────────────────────────────
|
|
|
|
public function test_set_many_includes_all_columns_in_upsert(): void {
|
|
WPDO_Zone_Hot::set_many( 7, 'hp_listing', [
|
|
'hp_price' => '150',
|
|
'hp_location' => 'LA',
|
|
'hp_category' => '3',
|
|
] );
|
|
$this->assertNotEmpty( self::$last_query );
|
|
$this->assertStringContainsString( 'hp_price', self::$last_query );
|
|
$this->assertStringContainsString( 'hp_location', self::$last_query );
|
|
$this->assertStringContainsString( 'hp_category', self::$last_query );
|
|
}
|
|
|
|
// ── delete() ─────────────────────────────────────────────────────────────
|
|
|
|
public function test_delete_calls_wpdb_delete(): void {
|
|
WPDO_Zone_Hot::delete( 42, 'hp_listing' );
|
|
$this->assertNotEmpty( self::$last_delete, 'Expected $wpdb->delete() to be called' );
|
|
$this->assertSame( 42, self::$last_delete['where']['post_id'] );
|
|
}
|
|
|
|
public function test_delete_table_name_contains_post_type(): void {
|
|
WPDO_Zone_Hot::delete( 5, 'hp_vendor' );
|
|
$this->assertStringContainsString( 'hp_vendor', self::$last_delete['table'] );
|
|
}
|
|
|
|
// ── Additional edge cases ─────────────────────────────────────────────────
|
|
|
|
public function test_table_for_different_post_type(): void {
|
|
$this->assertSame( 'wp_wpdo_hot_hp_vendor', WPDO_Zone_Hot::table( 'hp_vendor' ) );
|
|
}
|
|
}
|