&1', escapeshellarg(self::PLUGIN_ROOT), escapeshellarg($zip) ); exec($cmd, $output, $rc); if ($rc !== 0) { self::fail("git archive failed: rc=$rc output=" . implode("\n", $output)); } return $zip; } /** @return array */ private static function listZip(string $zipPath): array { exec('unzip -Z1 ' . escapeshellarg($zipPath), $list, $rc); if ($rc !== 0) self::fail("unzip -Z1 failed: rc=$rc"); return $list; } public function test_git_archive_includes_runtime_files(): void { $zip = self::buildTestZip(); $entries = self::listZip($zip); $joined = implode("\n", $entries); self::assertStringContainsString('cf7-spam-to-telegram/cf7-spam-to-telegram.php', $joined); self::assertStringContainsString('cf7-spam-to-telegram/includes/class-plugin.php', $joined); self::assertStringContainsString('cf7-spam-to-telegram/includes/lib/plugin-update-checker/plugin-update-checker.php', $joined); self::assertStringContainsString('cf7-spam-to-telegram/admin/', $joined); self::assertStringContainsString('cf7-spam-to-telegram/wp-plugin-info.json', $joined); self::assertStringContainsString('cf7-spam-to-telegram/readme.txt', $joined); unlink($zip); } public function test_git_archive_excludes_dev_files(): void { $zip = self::buildTestZip(); $entries = self::listZip($zip); $joined = implode("\n", $entries); foreach (['tests/', 'docs/', 'composer.json', 'composer.lock', 'phpunit.xml', 'release.sh', '.gitattributes', '.gitignore', 'CLAUDE.md', 'AGENTS.md', '.phpunit.result.cache', '.beads/', '.claude/', 'dist/', '.DS_Store'] as $devPath) { self::assertStringNotContainsString( "cf7-spam-to-telegram/$devPath", $joined, "dev file must be excluded: $devPath" ); } unlink($zip); } }