increase test coverage (#117)

70% test coverage
remove socialite
This commit is contained in:
Saeed Vaziry
2024-03-15 22:23:45 +01:00
committed by GitHub
parent 4f12de9586
commit a406491160
62 changed files with 1102 additions and 639 deletions

View File

@ -184,4 +184,70 @@ public function test_update_env_file(): void
SSH::assertExecutedContains('echo "APP_ENV=production" | tee /home/vito/'.$this->site->domain.'/.env');
}
public function test_git_hook_deployment(): void
{
SSH::fake();
Http::fake([
'github.com/*' => Http::response([
'sha' => '123',
'commit' => [
'message' => 'test commit message',
'name' => 'test commit name',
'email' => 'user@example.com',
'url' => 'https://github.com',
],
], 200),
]);
$hook = GitHook::factory()->create([
'site_id' => $this->site->id,
'source_control_id' => $this->site->source_control_id,
'secret' => 'secret',
'events' => ['push'],
'actions' => ['deploy'],
]);
$this->site->deploymentScript->update([
'content' => 'git pull',
]);
$this->post(route('git-hooks'), [
'secret' => 'secret',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('deployments', [
'site_id' => $this->site->id,
'deployment_script_id' => $this->site->deploymentScript->id,
'status' => DeploymentStatus::FINISHED,
]);
}
public function test_git_hook_deployment_invalid_secret(): void
{
SSH::fake();
Http::fake();
$hook = GitHook::factory()->create([
'site_id' => $this->site->id,
'source_control_id' => $this->site->source_control_id,
'secret' => 'secret',
'events' => ['push'],
'actions' => ['deploy'],
]);
$this->site->deploymentScript->update([
'content' => 'git pull',
]);
$this->post(route('git-hooks'), [
'secret' => 'invalid-secret',
])->assertNotFound();
$this->assertDatabaseMissing('deployments', [
'site_id' => $this->site->id,
'deployment_script_id' => $this->site->deploymentScript->id,
'status' => DeploymentStatus::FINISHED,
]);
}
}

View File

@ -37,4 +37,11 @@ public function test_users_can_not_authenticate_with_invalid_password(): void
$this->assertGuest();
}
public function test_redirect_if_not_authenticated(): void
{
$response = $this->get('/servers');
$response->assertRedirect('/login');
}
}

View File

@ -2,6 +2,7 @@
namespace Tests\Feature;
use App\Actions\Database\RunBackup;
use App\Enums\BackupFileStatus;
use App\Enums\BackupStatus;
use App\Facades\SSH;
@ -9,6 +10,7 @@
use App\Models\Database;
use App\Models\StorageProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
@ -48,6 +50,34 @@ public function test_create_backup(): void
]);
}
public function test_create_custom_interval_backup(): void
{
Bus::fake();
$this->actingAs($this->user);
$database = Database::factory()->create([
'server_id' => $this->server,
]);
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
]);
$this->post(route('servers.databases.backups.store', $this->server), [
'backup_database' => $database->id,
'backup_storage' => $storage->id,
'backup_interval' => 'custom',
'backup_custom' => '* * * * *',
'backup_keep' => '10',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backups', [
'status' => BackupStatus::RUNNING,
]);
}
public function test_see_backups_list(): void
{
$this->actingAs($this->user);
@ -97,4 +127,43 @@ public function test_delete_backup(): void
'id' => $backup->id,
]);
}
public function test_restore_backup(): void
{
Http::fake();
SSH::fake();
$this->actingAs($this->user);
$database = Database::factory()->create([
'server_id' => $this->server,
]);
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
]);
$backup = Backup::factory()->create([
'server_id' => $this->server->id,
'database_id' => $database->id,
'storage_id' => $storage->id,
]);
$backupFile = app(RunBackup::class)->run($backup);
$this->post(route('servers.databases.backups.files.restore', [
'server' => $this->server,
'backup' => $backup,
'backupFile' => $backupFile,
]), [
'database' => $database->id,
])
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backup_files', [
'id' => $backupFile->id,
'status' => BackupFileStatus::RESTORED,
]);
}
}

View File

@ -3,6 +3,7 @@
namespace Tests\Feature;
use App\Enums\DatabaseStatus;
use App\Enums\DatabaseUserStatus;
use App\Facades\SSH;
use App\Models\Database;
use Illuminate\Foundation\Testing\RefreshDatabase;
@ -28,6 +29,34 @@ public function test_create_database(): void
]);
}
public function test_create_database_with_user(): void
{
$this->actingAs($this->user);
SSH::fake();
$this->post(route('servers.databases.store', $this->server), [
'name' => 'database',
'user' => 'on',
'username' => 'user',
'password' => 'password',
'remote' => 'on',
'host' => '%',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('databases', [
'name' => 'database',
'status' => DatabaseStatus::READY,
]);
$this->assertDatabaseHas('database_users', [
'username' => 'user',
'databases' => json_encode(['database']),
'host' => '%',
'status' => DatabaseUserStatus::READY,
]);
}
public function test_see_databases_list(): void
{
$this->actingAs($this->user);

View File

@ -29,6 +29,26 @@ public function test_create_database_user(): void
]);
}
public function test_create_database_user_with_remote(): void
{
$this->actingAs($this->user);
SSH::fake();
$this->post(route('servers.databases.users.store', $this->server), [
'username' => 'user',
'password' => 'password',
'remote' => 'on',
'host' => '%',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('database_users', [
'username' => 'user',
'host' => '%',
'status' => DatabaseUserStatus::READY,
]);
}
public function test_see_database_users_list(): void
{
$this->actingAs($this->user);
@ -58,4 +78,26 @@ public function test_delete_database_user(): void
'id' => $databaseUser->id,
]);
}
public function test_unlink_database(): void
{
$this->actingAs($this->user);
SSH::fake();
$databaseUser = DatabaseUser::factory()->create([
'server_id' => $this->server,
]);
$this->post(route('servers.databases.users.link', [
'server' => $this->server,
'databaseUser' => $databaseUser,
]), [])
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('database_users', [
'username' => $databaseUser->username,
'databases' => json_encode([]),
]);
}
}

View File

@ -26,12 +26,35 @@ public function test_add_email_channel(): void
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::EMAIL)
->where('label', 'Email')
->first();
$this->assertEquals('email@example.com', $channel->data['email']);
$this->assertTrue($channel->connected);
}
public function test_cannot_add_email_channel(): void
{
config()->set('mail.default', 'smtp');
config()->set('mail.mailers.smtp.host', '127.0.0.1'); // invalid host
$this->actingAs($this->user);
$this->post(route('notification-channels.add'), [
'provider' => NotificationChannel::EMAIL,
'email' => 'email@example.com',
'label' => 'Email',
])->assertSessionHasErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::EMAIL)
->where('label', 'Email')
->first();
$this->assertNull($channel);
}
public function test_add_slack_channel(): void
{
$this->actingAs($this->user);
@ -53,6 +76,28 @@ public function test_add_slack_channel(): void
$this->assertTrue($channel->connected);
}
public function test_cannot_add_slack_channel(): void
{
$this->actingAs($this->user);
Http::fake([
'slack.com/*' => Http::response(['ok' => false], 401),
]);
$this->post(route('notification-channels.add'), [
'provider' => NotificationChannel::SLACK,
'webhook_url' => 'https://hooks.slack.com/services/123/token',
'label' => 'Slack',
])->assertSessionHasErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::SLACK)
->first();
$this->assertNull($channel);
}
public function test_add_discord_channel(): void
{
$this->actingAs($this->user);
@ -74,9 +119,27 @@ public function test_add_discord_channel(): void
$this->assertTrue($channel->connected);
}
/*
* @TODO fix json comparison
*/
public function test_cannot_add_discord_channel(): void
{
$this->actingAs($this->user);
Http::fake([
'discord.com/*' => Http::response(['ok' => false], 401),
]);
$this->post(route('notification-channels.add'), [
'provider' => NotificationChannel::DISCORD,
'webhook_url' => 'https://discord.com/api/webhooks/123/token',
'label' => 'Discord',
])->assertSessionHasErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::DISCORD)
->first();
$this->assertNull($channel);
}
public function test_add_telegram_channel(): void
{
@ -101,6 +164,29 @@ public function test_add_telegram_channel(): void
$this->assertTrue($channel->connected);
}
public function test_cannot_add_telegram_channel(): void
{
$this->actingAs($this->user);
Http::fake([
'api.telegram.org/*' => Http::response(['ok' => false], 401),
]);
$this->post(route('notification-channels.add'), [
'provider' => NotificationChannel::TELEGRAM,
'bot_token' => 'token',
'chat_id' => '123',
'label' => 'Telegram',
])->assertSessionHasErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::TELEGRAM)
->first();
$this->assertNull($channel);
}
public function test_see_channels_list(): void
{
$this->actingAs($this->user);

View File

@ -135,4 +135,32 @@ public function test_extension_already_installed(): void
'extension' => 'gmp',
]))->assertSessionHasErrors();
}
public function test_get_php_ini(): void
{
SSH::fake('[PHP ini]');
$this->actingAs($this->user);
$this->get(route('servers.php.get-ini', [
'server' => $this->server,
'version' => '8.2',
]))->assertSessionHas('ini');
}
public function test_update_php_ini(): void
{
SSH::fake();
$this->actingAs($this->user);
$this->post(route('servers.php.update-ini', [
'server' => $this->server,
'version' => '8.2',
'ini' => 'new ini',
]))
->assertSessionDoesntHaveErrors()
->assertSessionHas('toast.type', 'success')
->assertSessionHas('toast.message', 'PHP ini updated!');
}
}

View File

@ -68,4 +68,16 @@ public function test_edit_project(): void
'name' => 'new-name',
]);
}
public function test_cannot_delete_last_project(): void
{
$this->actingAs($this->user);
$this->delete(route('projects.delete', [
'project' => $this->user->currentProject,
]))
->assertSessionDoesntHaveErrors()
->assertSessionHas('toast.type', 'error')
->assertSessionHas('toast.message', 'Cannot delete the last project.');
}
}

View File

@ -86,4 +86,85 @@ public function test_create_queue()
'status' => QueueStatus::RUNNING,
]);
}
public function test_start_queue(): void
{
SSH::fake();
$this->actingAs($this->user);
$queue = Queue::factory()->create([
'server_id' => $this->server->id,
'site_id' => $this->site->id,
'status' => QueueStatus::STOPPED,
]);
$this->post(
route('servers.sites.queues.action', [
'action' => 'start',
'server' => $this->server,
'site' => $this->site,
'queue' => $queue,
])
)->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('queues', [
'id' => $queue->id,
'status' => QueueStatus::RUNNING,
]);
}
public function test_stop_queue(): void
{
SSH::fake();
$this->actingAs($this->user);
$queue = Queue::factory()->create([
'server_id' => $this->server->id,
'site_id' => $this->site->id,
'status' => QueueStatus::RUNNING,
]);
$this->post(
route('servers.sites.queues.action', [
'action' => 'stop',
'server' => $this->server,
'site' => $this->site,
'queue' => $queue,
])
)->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('queues', [
'id' => $queue->id,
'status' => QueueStatus::STOPPED,
]);
}
public function test_restart_queue(): void
{
SSH::fake();
$this->actingAs($this->user);
$queue = Queue::factory()->create([
'server_id' => $this->server->id,
'site_id' => $this->site->id,
'status' => QueueStatus::RUNNING,
]);
$this->post(
route('servers.sites.queues.action', [
'action' => 'restart',
'server' => $this->server,
'site' => $this->site,
'queue' => $queue,
])
)->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('queues', [
'id' => $queue->id,
'status' => QueueStatus::RUNNING,
]);
}
}

View File

@ -11,20 +11,52 @@ class ServerProvidersTest extends TestCase
{
use RefreshDatabase;
public function test_connect_hetzner(): void
/**
* @dataProvider data
*/
public function test_connect_provider(string $provider, array $input): void
{
$this->actingAs($this->user);
Http::fake();
$this->post(route('server-providers.connect'), [
'provider' => ServerProvider::HETZNER,
'name' => 'profile',
'token' => 'token',
])->assertSessionDoesntHaveErrors();
$data = array_merge(
[
'provider' => $provider,
'name' => 'profile',
],
$input
);
$this->post(route('server-providers.connect'), $data)->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('server_providers', [
'provider' => ServerProvider::HETZNER,
'provider' => $provider,
'profile' => 'profile',
]);
}
/**
* @dataProvider data
*/
public function test_cannot_connect_to_provider(string $provider, array $input): void
{
$this->actingAs($this->user);
Http::fake([
'*' => Http::response([], 401),
]);
$data = array_merge(
[
'provider' => $provider,
'name' => 'profile',
],
$input
);
$this->post(route('server-providers.connect'), $data)->assertSessionHasErrors();
$this->assertDatabaseMissing('server_providers', [
'provider' => $provider,
'profile' => 'profile',
]);
}
@ -41,19 +73,86 @@ public function test_see_providers_list(): void
->assertSee($provider->profile);
}
public function test_delete_provider(): void
/**
* @dataProvider data
*/
public function test_delete_provider(string $provider): void
{
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
$this->delete(route('server-providers.delete', $provider->id))
$this->delete(route('server-providers.delete', $provider))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseMissing('server_providers', [
'id' => $provider->id,
]);
}
/**
* @dataProvider data
*/
public function test_cannot_delete_provider(string $provider): void
{
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
$this->server->update([
'provider_id' => $provider->id,
]);
$this->delete(route('server-providers.delete', $provider))
->assertSessionDoesntHaveErrors()
->assertSessionHas('toast.type', 'error')
->assertSessionHas('toast.message', 'This server provider is being used by a server.');
$this->assertDatabaseHas('server_providers', [
'id' => $provider->id,
]);
}
public static function data(): array
{
return [
// [
// ServerProvider::AWS,
// [
// 'key' => 'key',
// 'secret' => 'secret',
// ],
// ],
[
ServerProvider::LINODE,
[
'token' => 'token',
],
],
[
ServerProvider::DIGITALOCEAN,
[
'token' => 'token',
],
],
[
ServerProvider::VULTR,
[
'token' => 'token',
],
],
[
ServerProvider::HETZNER,
[
'token' => 'token',
],
],
];
}
}

View File

@ -10,17 +10,17 @@
use App\Enums\ServiceStatus;
use App\Enums\Webserver;
use App\Facades\SSH;
use App\NotificationChannels\Email\NotificationMail;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
/**
* @TODO add more tests
*/
class ServerTest extends TestCase
{
use RefreshDatabase;
public function test_create_custom_server(): void
public function test_create_regular_server(): void
{
$this->actingAs($this->user);
@ -76,6 +76,62 @@ public function test_create_custom_server(): void
]);
}
public function test_create_database_server(): void
{
$this->actingAs($this->user);
SSH::fake('Active: active'); // fake output for service installations
$this->post(route('servers.create'), [
'type' => ServerType::DATABASE,
'provider' => ServerProvider::CUSTOM,
'name' => 'test',
'ip' => '2.2.2.2',
'port' => '22',
'os' => OperatingSystem::UBUNTU22,
'database' => Database::MYSQL80,
])->assertSessionDoesntHaveErrors();
$server = \App\Models\Server::query()->where('ip', '2.2.2.2')->first();
$this->assertDatabaseHas('servers', [
'name' => 'test',
'ip' => '2.2.2.2',
'status' => ServerStatus::READY,
]);
$this->assertDatabaseMissing('services', [
'server_id' => $server->id,
'type' => 'php',
'version' => '8.2',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseMissing('services', [
'server_id' => $server->id,
'type' => 'webserver',
'name' => 'nginx',
'version' => 'latest',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => $server->id,
'type' => 'database',
'name' => 'mysql',
'version' => '8.0',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => $server->id,
'type' => 'firewall',
'name' => 'ufw',
'version' => 'latest',
'status' => ServiceStatus::READY,
]);
}
public function test_delete_server(): void
{
$this->actingAs($this->user);
@ -89,4 +145,139 @@ public function test_delete_server(): void
'id' => $this->server->id,
]);
}
public function test_cannot_delete_on_provider(): void
{
Mail::fake();
Http::fake([
'*' => Http::response([], 401),
]);
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => ServerProvider::HETZNER,
'credentials' => [
'token' => 'token',
],
]);
$this->server->update([
'provider' => ServerProvider::HETZNER,
'provider_id' => $provider->id,
'provider_data' => [
'hetzner_id' => 1,
'ssh_key_id' => 1,
],
]);
$this->delete(route('servers.delete', $this->server))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseMissing('servers', [
'id' => $this->server->id,
]);
Mail::assertSent(NotificationMail::class);
}
public function test_check_connection_is_ready(): void
{
SSH::fake();
$this->actingAs($this->user);
$this->server->update(['status' => ServerStatus::DISCONNECTED]);
$this->post(route('servers.settings.check-connection', $this->server))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'status' => ServerStatus::READY,
]);
}
public function test_connection_failed(): void
{
SSH::fake()->connectionWillFail();
$this->actingAs($this->user);
$this->server->update(['status' => ServerStatus::READY]);
$this->post(route('servers.settings.check-connection', $this->server))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'status' => ServerStatus::DISCONNECTED,
]);
}
public function test_reboot_server(): void
{
SSH::fake();
$this->actingAs($this->user);
$this->post(route('servers.settings.reboot', $this->server))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'status' => ServerStatus::DISCONNECTED,
]);
}
public function test_edit_server(): void
{
$this->actingAs($this->user);
$this->post(route('servers.settings.edit', $this->server), [
'name' => 'new-name',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'name' => 'new-name',
]);
}
public function test_edit_server_ip_address(): void
{
SSH::fake();
$this->actingAs($this->user);
$this->post(route('servers.settings.edit', $this->server), [
'ip' => '2.2.2.2',
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'ip' => '2.2.2.2',
'status' => ServerStatus::READY,
]);
}
public function test_edit_server_ip_address_and_disconnect(): void
{
SSH::fake()->connectionWillFail();
$this->actingAs($this->user);
$this->post(route('servers.settings.edit', $this->server), [
'ip' => '2.2.2.2',
'port' => 2222,
])->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'ip' => '2.2.2.2',
'port' => 2222,
'status' => ServerStatus::DISCONNECTED,
]);
}
}

View File

@ -160,4 +160,16 @@ public static function create_data(): array
],
];
}
public function test_see_logs(): void
{
$this->actingAs($this->user);
$this->get(route('servers.sites.logs', [
'server' => $this->server,
'site' => $this->site,
]))
->assertOk()
->assertSee('Logs');
}
}

View File

@ -5,7 +5,6 @@
use App\Models\SourceControl;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use JsonException;
use Tests\TestCase;
class SourceControlsTest extends TestCase
@ -14,8 +13,6 @@ class SourceControlsTest extends TestCase
/**
* @dataProvider data
*
* @throws JsonException
*/
public function test_connect_provider(string $provider, ?string $customUrl): void
{
@ -43,8 +40,6 @@ public function test_connect_provider(string $provider, ?string $customUrl): voi
/**
* @dataProvider data
*
* @throws JsonException
*/
public function test_delete_provider(string $provider): void
{
@ -64,6 +59,33 @@ public function test_delete_provider(string $provider): void
]);
}
/**
* @dataProvider data
*/
public function test_cannot_delete_provider(string $provider): void
{
$this->actingAs($this->user);
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => $provider,
'profile' => 'test',
]);
$this->site->update([
'source_control_id' => $sourceControl->id,
]);
$this->delete(route('source-controls.delete', $sourceControl->id))
->assertSessionDoesntHaveErrors()
->assertSessionHas('toast.type', 'error')
->assertSessionHas('toast.message', 'This source control is being used by a site.');
$this->assertDatabaseHas('source_controls', [
'id' => $sourceControl->id,
]);
}
public static function data(): array
{
return [

View File

@ -3,6 +3,8 @@
namespace Tests\Feature;
use App\Enums\StorageProvider;
use App\Models\Backup;
use App\Models\Database;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
@ -57,4 +59,32 @@ public function test_delete_provider(): void
'id' => $provider->id,
]);
}
public function test_cannot_delete_provider(): void
{
$this->actingAs($this->user);
$database = Database::factory()->create([
'server_id' => $this->server,
]);
$provider = \App\Models\StorageProvider::factory()->create([
'user_id' => $this->user->id,
]);
Backup::factory()->create([
'server_id' => $this->server->id,
'database_id' => $database->id,
'storage_id' => $provider->id,
]);
$this->delete(route('storage-providers.delete', $provider->id))
->assertSessionDoesntHaveErrors()
->assertSessionHas('toast.type', 'error')
->assertSessionHas('toast.message', 'This storage provider is being used by a backup.');
$this->assertDatabaseHas('storage_providers', [
'id' => $provider->id,
]);
}
}

View File

@ -3,6 +3,7 @@
namespace Tests;
use App\Enums\Database;
use App\Enums\NotificationChannel;
use App\Enums\ServiceStatus;
use App\Enums\Webserver;
use App\Models\Server;
@ -31,6 +32,14 @@ public function setUp(): void
$this->user = User::factory()->create();
\App\Models\NotificationChannel::factory()->create([
'provider' => NotificationChannel::EMAIL,
'connected' => true,
'data' => [
'email' => 'user@example.com',
],
]);
$this->setupServer();
$this->setupSite();
@ -38,6 +47,15 @@ public function setUp(): void
$this->setupKeys();
}
public function tearDown(): void
{
parent::tearDown();
if (File::exists(storage_path('app/key-pairs-test'))) {
File::deleteDirectory(storage_path('app/key-pairs-test'));
}
}
private function setupServer(): void
{
$this->server = Server::factory()->create([

View File

@ -0,0 +1,42 @@
<?php
namespace Tests\Unit\Commands;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class CreateUserCommandTest extends TestCase
{
use RefreshDatabase;
public function test_create_user(): void
{
$this->artisan('user:create', [
'name' => 'John Doe',
'email' => 'john@doe.com',
'password' => 'password',
])->expectsOutput('User created!');
$this->assertDatabaseHas('users', [
'name' => 'John Doe',
'email' => 'john@doe.com',
]);
/** @var User $user */
$user = User::query()->where('email', 'john@doe.com')->first();
$this->assertDatabaseHas('projects', [
'user_id' => $user->id,
]);
}
public function test_skip_existing_user(): void
{
$this->artisan('user:create', [
'name' => 'John Doe',
'email' => $this->user->email,
'password' => 'password',
])->expectsOutput('User already exists. Skipping...');
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Tests\Unit\Commands;
use App\Facades\SSH;
use App\Models\Backup;
use App\Models\Database;
use App\Models\StorageProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RunBackupCommandTest extends TestCase
{
use RefreshDatabase;
public function test_run_without_any_backups(): void
{
$this->artisan('backups:run "* * * * *"')
->expectsOutput('0 backups started');
}
public function test_run_backups(): void
{
SSH::fake();
$database = Database::factory()->create([
'server_id' => $this->server,
]);
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
]);
$backup = Backup::factory()->create([
'server_id' => $this->server->id,
'database_id' => $database->id,
'storage_id' => $storage->id,
'interval' => '1 * * * *',
'keep_backups' => 10,
]);
$this->artisan('backups:run "1 * * * *"')
->expectsOutput('1 backups started');
}
}

View File

@ -2,6 +2,8 @@
namespace Tests\Unit\Models;
use App\Enums\ServerStatus;
use App\Facades\SSH;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@ -17,4 +19,32 @@ public function test_should_have_default_service()
$php->refresh();
$this->assertTrue($php->is_default);
}
public function test_check_connection_is_ready(): void
{
SSH::fake();
$this->server->update(['status' => ServerStatus::DISCONNECTED]);
$this->server->checkConnection();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'status' => ServerStatus::READY,
]);
}
public function test_connection_failed(): void
{
SSH::fake()->connectionWillFail();
$this->server->update(['status' => ServerStatus::READY]);
$this->server->checkConnection();
$this->assertDatabaseHas('servers', [
'id' => $this->server->id,
'status' => ServerStatus::DISCONNECTED,
]);
}
}