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
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for WPDO_CLI_V2::lint_directory() — Anti-EAV strict lint (PR-6).
|
||||
*
|
||||
* @covers WPDO_CLI_V2::lint_directory
|
||||
*/
|
||||
class CliLintTest extends TestCase {
|
||||
|
||||
private string $fixture_dir;
|
||||
|
||||
public static function setUpBeforeClass(): void {
|
||||
// Stub WP_CLI just enough so the cli-v2 file can be require'd without errors.
|
||||
if ( ! class_exists( 'WP_CLI' ) ) {
|
||||
eval( 'class WP_CLI { public static function add_command( $name, $callable ) {} public static function log( $msg ) {} public static function warning( $msg ) {} public static function error( $msg ) { throw new \RuntimeException( $msg ); } public static function success( $msg ) {} }' ); // phpcs:ignore Squiz.PHP.Eval -- test-only stub.
|
||||
}
|
||||
if ( ! class_exists( 'TMDO_CLI_V2' ) ) {
|
||||
require_once dirname( __DIR__, 2 ) . '/cli/class-tmdo-cli-v2.php';
|
||||
}
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
$this->fixture_dir = sys_get_temp_dir() . '/wpdo-lint-fixture-' . uniqid();
|
||||
mkdir( $this->fixture_dir, 0777, true );
|
||||
}
|
||||
|
||||
protected function tearDown(): void {
|
||||
// Recursive rmdir.
|
||||
$this->rrmdir( $this->fixture_dir );
|
||||
}
|
||||
|
||||
private function rrmdir( string $dir ): void {
|
||||
if ( ! is_dir( $dir ) ) {
|
||||
return;
|
||||
}
|
||||
foreach ( scandir( $dir ) as $f ) {
|
||||
if ( '.' === $f || '..' === $f ) {
|
||||
continue;
|
||||
}
|
||||
$path = $dir . '/' . $f;
|
||||
is_dir( $path ) ? $this->rrmdir( $path ) : unlink( $path );
|
||||
}
|
||||
rmdir( $dir );
|
||||
}
|
||||
|
||||
private function write( string $relative, string $content ): void {
|
||||
$path = $this->fixture_dir . '/' . $relative;
|
||||
$dir = dirname( $path );
|
||||
if ( ! is_dir( $dir ) ) {
|
||||
mkdir( $dir, 0777, true );
|
||||
}
|
||||
file_put_contents( $path, $content );
|
||||
}
|
||||
|
||||
// ── happy path ──────────────────────────────────────────────────────────
|
||||
|
||||
public function test_clean_plugin_passes_lint(): void {
|
||||
$this->write( 'main.php', "<?php\nfunction foo() { return 'bar'; }\n" );
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertEmpty( $findings );
|
||||
}
|
||||
|
||||
// ── direct postmeta SELECT ─────────────────────────────────────────────
|
||||
|
||||
public function test_direct_postmeta_select_flagged(): void {
|
||||
$this->write(
|
||||
'bad.php',
|
||||
"<?php\n\$rows = \$wpdb->get_results( \"SELECT meta_value FROM {\$wpdb->prefix}postmeta WHERE meta_key='foo'\" );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertGreaterThanOrEqual( 1, count( $findings ) );
|
||||
$this->assertSame( 'no-direct-postmeta-select', $findings[0]['rule'] );
|
||||
}
|
||||
|
||||
public function test_direct_usermeta_select_flagged(): void {
|
||||
$this->write(
|
||||
'user.php',
|
||||
"<?php\n\$wpdb->get_var( \"SELECT meta_value FROM wp_usermeta WHERE meta_key='foo'\" );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertGreaterThanOrEqual( 1, count( $findings ) );
|
||||
$this->assertSame( 'no-direct-usermeta-select', $findings[0]['rule'] );
|
||||
}
|
||||
|
||||
// ── autoload=yes ───────────────────────────────────────────────────────
|
||||
|
||||
public function test_autoload_yes_flagged(): void {
|
||||
$this->write(
|
||||
'opt.php',
|
||||
"<?php\nadd_option( 'mykey', 'val', '', 'yes' );\n\$x = array( 'autoload' => 'yes' );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$autoload_findings = array_filter( $findings, static fn( $f ) => 'autoload-yes' === $f['rule'] );
|
||||
$this->assertGreaterThanOrEqual( 1, count( $autoload_findings ) );
|
||||
}
|
||||
|
||||
// ── ignore comment ─────────────────────────────────────────────────────
|
||||
|
||||
public function test_phpcs_ignore_comment_skips_finding(): void {
|
||||
$this->write(
|
||||
'fallback.php',
|
||||
"<?php\n// phpcs:ignore WPDO.AntiEAV.PostmetaFallback -- legacy fallback path\n\$rows = \$wpdb->get_results( \"SELECT meta_value FROM wp_postmeta WHERE meta_key='x'\" );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertEmpty( $findings, 'phpcs:ignore WPDO.AntiEAV must suppress findings' );
|
||||
}
|
||||
|
||||
// ── skip dirs ──────────────────────────────────────────────────────────
|
||||
|
||||
public function test_skips_vendor_and_node_modules(): void {
|
||||
// Bad code inside vendor/ MUST be ignored.
|
||||
$this->write(
|
||||
'vendor/lib/bad.php',
|
||||
"<?php\n\$wpdb->get_results( \"SELECT meta_value FROM wp_postmeta\" );\n"
|
||||
);
|
||||
$this->write(
|
||||
'node_modules/foo/bad.php',
|
||||
"<?php\n\$wpdb->get_results( \"SELECT meta_value FROM wp_usermeta\" );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertEmpty( $findings );
|
||||
}
|
||||
|
||||
// ── reports file + line ────────────────────────────────────────────────
|
||||
|
||||
public function test_finding_includes_file_and_line(): void {
|
||||
$this->write(
|
||||
'multi.php',
|
||||
"<?php\n\n\$x = 1;\n\$wpdb->get_var( \"SELECT meta_value FROM wp_postmeta\" );\n"
|
||||
);
|
||||
$findings = WPDO_CLI_V2::lint_directory( $this->fixture_dir );
|
||||
$this->assertNotEmpty( $findings );
|
||||
$this->assertStringEndsWith( 'multi.php', $findings[0]['file'] );
|
||||
$this->assertSame( 4, $findings[0]['line'] );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user