From ee1abf3ab9a0ef82d776c5a6636c44d490cc7173 Mon Sep 17 00:00:00 2001 From: PatrickePatate Date: Thu, 22 Jan 2026 16:24:01 +0100 Subject: [PATCH] Add tests for FetchDataFromOzu command --- src/Console/FetchDataFromOzu.php | 36 +++--- src/Support/ZipExtractor.php | 21 ++++ tests/Console/FetchDataFromOzuTest.php | 157 +++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 21 deletions(-) create mode 100644 src/Support/ZipExtractor.php create mode 100644 tests/Console/FetchDataFromOzuTest.php diff --git a/src/Console/FetchDataFromOzu.php b/src/Console/FetchDataFromOzu.php index 10d7d53..4257fcc 100644 --- a/src/Console/FetchDataFromOzu.php +++ b/src/Console/FetchDataFromOzu.php @@ -3,11 +3,11 @@ namespace Code16\OzuClient\Console; use Code16\OzuClient\Client; +use Code16\OzuClient\Support\ZipExtractor; use Illuminate\Console\Command; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Cache; -use Symfony\Component\Process\Process; -use ZipArchive; +use Illuminate\Support\Facades\Process; use function Laravel\Prompts\confirm; @@ -102,21 +102,19 @@ private function importDatabase(): bool $this->info('๐Ÿ›  Importing Ozu database...'); $config = config('database.connections.mysql'); - $process = Process::fromShellCommandline(sprintf( - 'mysql -h%s -P%s -u%s %s < %s', - $config['host'], - $config['port'], - $config['username'], - $config['database'], - $this->databaseDumpPath - )); - - $process->setEnv(['MYSQL_PWD' => $config['password']]); - $process->run(); - - if (!$process->isSuccessful()) { + $result = Process::env(['MYSQL_PWD' => $config['password']]) + ->run(sprintf( + 'mysql -h%s -P%s -u%s %s < %s', + $config['host'], + $config['port'], + $config['username'], + $config['database'], + $this->databaseDumpPath + )); + + if (!$result->successful()) { $this->error('โŒ Error importing the database:'); - $this->error($process->getErrorOutput()); + $this->error($result->errorOutput()); return false; } @@ -147,11 +145,7 @@ private function extractAssets(): bool $this->info('๐Ÿ“ฆ Extracting Ozu assets...'); try { - $zip = new ZipArchive(); - if ($zip->open($this->assetsZipPath) === true) { - $zip->extractTo($this->assetsExtractPath); - $zip->close(); - + if (app(ZipExtractor::class)->extract($this->assetsZipPath, $this->assetsExtractPath)) { return true; } diff --git a/src/Support/ZipExtractor.php b/src/Support/ZipExtractor.php new file mode 100644 index 0000000..829b74b --- /dev/null +++ b/src/Support/ZipExtractor.php @@ -0,0 +1,21 @@ +open($zipPath) === true) { + $zip->extractTo($extractPath); + $zip->close(); + + return true; + } + + return false; + } +} diff --git a/tests/Console/FetchDataFromOzuTest.php b/tests/Console/FetchDataFromOzuTest.php new file mode 100644 index 0000000..0c9c3aa --- /dev/null +++ b/tests/Console/FetchDataFromOzuTest.php @@ -0,0 +1,157 @@ + Http::response('SQL DUMP', 200), + '*/api/v1/websites/assets' => Http::response('ZIP CONTENT', 200), + '*/api/v1/settings/fetch' => Http::response(['key' => 'value'], 200), + '*/api/v1/website' => Http::response(['key' => 'test-website'], 200), + ]); + + config([ + 'ozu-client.api_host' => 'https://ozu.test', + 'ozu-client.api_version' => 'v1', + 'ozu-client.website_key' => 'test-website', + 'database.connections.mysql' => [ + 'host' => '127.0.0.1', + 'port' => '3306', + 'username' => 'root', + 'database' => 'forge', + 'password' => '', + ], + ]); + + // Mock Artisan::call('db:wipe') + // We can't easily mock Artisan facade here because it's final in Testbench + // But we can check if it was called if we really need to. + // For now let's just let it be or use a partial mock if possible. + + // Mock Process for mysql import + Process::fake([ + 'mysql *' => Process::result('', '', 0), + ]); + + // Mock ZipExtractor + $this->mock(ZipExtractor::class, function ($mock) { + $mock->shouldReceive('extract')->once()->andReturn(true); + }); + + $this->artisan('ozu:import', ['--force' => true]) + ->expectsOutput('โฌ‡๏ธ Downloading Ozu database...') + ->expectsOutput('๐Ÿงน Wiping local database...') + ->expectsOutput('๐Ÿ›  Importing Ozu database...') + ->expectsOutput('โœ… Database imported successfully.') + ->expectsOutput('โฌ‡๏ธ Downloading Ozu assets...') + ->expectsOutput('๐Ÿ“ฆ Extracting Ozu assets...') + ->expectsOutput('โœ… Ozu data successfully imported.') + ->assertExitCode(FetchDataFromOzu::SUCCESS); +}); + +it('can skip assets import', function () { + Storage::fake('local'); + Http::fake([ + '*/api/v1/websites/database' => Http::response('SQL DUMP', 200), + '*/api/v1/website' => Http::response(['key' => 'test-website'], 200), + ]); + + config([ + 'ozu-client.api_host' => 'https://ozu.test', + 'ozu-client.api_version' => 'v1', + 'ozu-client.website_key' => 'test-website', + 'database.connections.mysql' => [ + 'host' => '127.0.0.1', + 'port' => '3306', + 'username' => 'root', + 'database' => 'forge', + 'password' => '', + ], + ]); + + Process::fake([ + 'mysql *' => Process::result('', '', 0), + ]); + + $this->artisan('ozu:import', ['--force' => true, '--withoutAssets' => true]) + ->expectsOutput('โฌ‡๏ธ Downloading Ozu database...') + ->expectsOutput('๐Ÿงน Wiping local database...') + ->expectsOutput('๐Ÿ›  Importing Ozu database...') + ->expectsOutput('โœ… Database imported successfully.') + ->doesntExpectOutput('โฌ‡๏ธ Downloading Ozu assets...') + ->expectsOutput('โœ… Ozu data successfully imported.') + ->assertExitCode(FetchDataFromOzu::SUCCESS); +}); + +it('handles database download failure', function () { + Storage::fake('local'); + + $this->mock(Client::class, function ($mock) { + $mock->shouldReceive('downloadOzuDatabase')->once()->andReturn(null); + }); + + $this->artisan('ozu:import', ['--force' => true]) + ->expectsOutput('โฌ‡๏ธ Downloading Ozu database...') + ->expectsOutput('โŒ Failed to download the Ozu database.') + ->assertExitCode(FetchDataFromOzu::FAILURE); +}); + +it('asks for confirmation when force option is not present', function () { + Storage::fake('local'); + Http::fake([ + '*/api/v1/website' => Http::response(['key' => 'test-website'], 200), + ]); + + $this->artisan('ozu:import') + ->expectsConfirmation('Are you sure you want to continue? This cannot be undone.', 'no') + ->assertExitCode(FetchDataFromOzu::SUCCESS); +}); + +it('handles asset extraction failure', function () { + Storage::fake('local'); + Http::fake([ + '*/api/v1/websites/database' => Http::response('SQL DUMP', 200), + '*/api/v1/websites/assets' => Http::response('ZIP CONTENT', 200), + '*/api/v1/website' => Http::response(['key' => 'test-website'], 200), + ]); + + config([ + 'ozu-client.api_host' => 'https://ozu.test', + 'ozu-client.api_version' => 'v1', + 'ozu-client.website_key' => 'test-website', + 'database.connections.mysql' => [ + 'host' => '127.0.0.1', + 'port' => '3306', + 'username' => 'root', + 'database' => 'forge', + 'password' => '', + ], + ]); + + Process::fake([ + 'mysql *' => Process::result('', '', 0), + ]); + + $this->mock(ZipExtractor::class, function ($mock) { + $mock->shouldReceive('extract')->once()->andReturn(false); + }); + + $this->artisan('ozu:import', ['--force' => true]) + ->expectsOutput('โฌ‡๏ธ Downloading Ozu database...') + ->expectsOutput('๐Ÿงน Wiping local database...') + ->expectsOutput('๐Ÿ›  Importing Ozu database...') + ->expectsOutput('โœ… Database imported successfully.') + ->expectsOutput('โฌ‡๏ธ Downloading Ozu assets...') + ->expectsOutput('๐Ÿ“ฆ Extracting Ozu assets...') + ->expectsOutput('โŒ Failed to open the zip file.') + ->assertExitCode(FetchDataFromOzu::FAILURE); +});