Plugins base (#613)

* wip

* wip

* cleanup

* notification channels

* phpstan

* services

* remove server types

* refactoring

* refactoring
This commit is contained in:
Saeed Vaziry
2025-06-14 14:35:18 +02:00
committed by GitHub
parent adc0653d15
commit 131b828807
311 changed files with 3976 additions and 2660 deletions

View File

@ -2,7 +2,11 @@
namespace Tests\Feature\API;
use App\Enums\ServerProvider;
use App\Models\ServerProvider;
use App\ServerProviders\DigitalOcean;
use App\ServerProviders\Hetzner;
use App\ServerProviders\Linode;
use App\ServerProviders\Vultr;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Sanctum\Sanctum;
@ -70,8 +74,8 @@ public function test_see_providers_list(): void
{
Sanctum::actingAs($this->user, ['read', 'write']);
/** @var \App\Models\ServerProvider $provider */
$provider = \App\Models\ServerProvider::factory()->create([
/** @var ServerProvider $provider */
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
]);
@ -90,8 +94,8 @@ public function test_delete_provider(string $provider): void
{
Sanctum::actingAs($this->user, ['read', 'write']);
/** @var \App\Models\ServerProvider $provider */
$provider = \App\Models\ServerProvider::factory()->create([
/** @var ServerProvider $provider */
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
@ -108,8 +112,8 @@ public function test_cannot_delete_provider(string $provider): void
{
Sanctum::actingAs($this->user, ['read', 'write']);
/** @var \App\Models\ServerProvider $provider */
$provider = \App\Models\ServerProvider::factory()->create([
/** @var ServerProvider $provider */
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
@ -141,32 +145,32 @@ public static function data(): array
// ],
// ],
[
ServerProvider::LINODE,
Linode::id(),
[
'token' => 'token',
],
],
[
ServerProvider::LINODE,
Linode::id(),
[
'token' => 'token',
'global' => 1,
],
],
[
ServerProvider::DIGITALOCEAN,
DigitalOcean::id(),
[
'token' => 'token',
],
],
[
ServerProvider::VULTR,
Vultr::id(),
[
'token' => 'token',
],
],
[
ServerProvider::HETZNER,
Hetzner::id(),
[
'token' => 'token',
],

View File

@ -2,12 +2,9 @@
namespace Tests\Feature\API;
use App\Enums\Database;
use App\Enums\OperatingSystem;
use App\Enums\ServerProvider;
use App\Enums\ServerType;
use App\Enums\Webserver;
use App\Facades\SSH;
use App\ServerProviders\Custom;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
@ -52,44 +49,15 @@ public function test_create_server(): void
$this->json('POST', route('api.projects.servers.create', [
'project' => $this->user->current_project_id,
]), [
'provider' => ServerProvider::CUSTOM,
'provider' => Custom::id(),
'name' => 'test',
'ip' => '1.1.1.1',
'port' => '22',
'os' => OperatingSystem::UBUNTU22,
'webserver' => Webserver::NGINX,
'database' => Database::MYSQL80,
'php' => '8.2',
])
->assertSuccessful()
->assertJsonFragment([
'name' => 'test',
'type' => ServerType::REGULAR,
]);
}
public function test_create_server_with_caddy(): void
{
Sanctum::actingAs($this->user, ['read', 'write']);
SSH::fake('Active: active'); // fake output for service installations
$this->json('POST', route('api.projects.servers.create', [
'project' => $this->user->current_project_id,
]), [
'provider' => ServerProvider::CUSTOM,
'name' => 'test',
'ip' => '1.1.1.1',
'port' => '22',
'os' => OperatingSystem::UBUNTU22,
'webserver' => Webserver::CADDY,
'database' => Database::MYSQL80,
'php' => '8.2',
])
->assertSuccessful()
->assertJsonFragment([
'name' => 'test',
'type' => ServerType::REGULAR,
]);
}

View File

@ -4,10 +4,11 @@
use App\Enums\DeploymentStatus;
use App\Enums\LoadBalancerMethod;
use App\Enums\SourceControl;
use App\Facades\SSH;
use App\Models\Server;
use App\Models\Site;
use App\Models\SourceControl;
use App\SourceControlProviders\Github;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Sanctum\Sanctum;
@ -42,9 +43,9 @@ public function test_create_site(array $inputs): void
Sanctum::actingAs($this->user, ['read', 'write']);
/** @var \App\Models\SourceControl $sourceControl */
$sourceControl = \App\Models\SourceControl::factory()->create([
'provider' => SourceControl::GITHUB,
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => Github::id(),
]);
$inputs['source_control'] = $sourceControl->id;

View File

@ -3,6 +3,9 @@
namespace Tests\Feature\API;
use App\Models\SourceControl;
use App\SourceControlProviders\Bitbucket;
use App\SourceControlProviders\Github;
use App\SourceControlProviders\Gitlab;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Sanctum\Sanctum;
@ -137,11 +140,11 @@ public function test_edit_source_control(string $provider, array $input): void
public static function data(): array
{
return [
['github', ['token' => 'test']],
['github', ['token' => 'test', 'global' => '1']],
['gitlab', ['token' => 'test']],
['gitlab', ['token' => 'test', 'url' => 'https://git.example.com/']],
['bitbucket', ['username' => 'test', 'password' => 'test']],
[Github::id(), ['token' => 'test']],
[Github::id(), ['token' => 'test', 'global' => '1']],
[Gitlab::id(), ['token' => 'test']],
[Gitlab::id(), ['token' => 'test', 'url' => 'https://git.example.com/']],
[Bitbucket::id(), ['username' => 'test', 'password' => 'test']],
];
}
}

View File

@ -2,11 +2,12 @@
namespace Tests\Feature\API;
use App\Enums\StorageProvider;
use App\Facades\FTP;
use App\Models\Backup;
use App\Models\Database;
use App\Models\StorageProvider as StorageProviderModel;
use App\StorageProviders\Dropbox;
use App\StorageProviders\Local;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Sanctum\Sanctum;
@ -25,11 +26,11 @@ public function test_create(array $input): void
{
Sanctum::actingAs($this->user, ['read', 'write']);
if ($input['provider'] === StorageProvider::DROPBOX) {
if ($input['provider'] === Dropbox::id()) {
Http::fake();
}
if ($input['provider'] === StorageProvider::FTP) {
if ($input['provider'] === \App\StorageProviders\FTP::id()) {
FTP::fake();
}
@ -50,7 +51,7 @@ public function test_see_providers_list(): void
/** @var StorageProviderModel $provider */
$provider = StorageProviderModel::factory()->create([
'user_id' => $this->user->id,
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$this->json('GET', route('api.projects.storage-providers', [
@ -115,14 +116,14 @@ public static function createData(): array
return [
[
[
'provider' => StorageProvider::LOCAL,
'provider' => Local::id(),
'name' => 'local-test',
'path' => '/home/vito/backups',
],
],
[
[
'provider' => StorageProvider::LOCAL,
'provider' => Local::id(),
'name' => 'local-test',
'path' => '/home/vito/backups',
'global' => 1,
@ -130,7 +131,7 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::FTP,
'provider' => \App\StorageProviders\FTP::id(),
'name' => 'ftp-test',
'host' => '1.2.3.4',
'port' => '22',
@ -143,7 +144,7 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::FTP,
'provider' => \App\StorageProviders\FTP::id(),
'name' => 'ftp-test',
'host' => '1.2.3.4',
'port' => '22',
@ -157,14 +158,14 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
'name' => 'dropbox-test',
'token' => 'token',
],
],
[
[
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
'name' => 'dropbox-test',
'token' => 'token',
'global' => 1,

View File

@ -9,10 +9,10 @@
use App\Models\Backup;
use App\Models\Database;
use App\Models\StorageProvider;
use App\StorageProviders\Dropbox;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Http;
use JsonException;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;
@ -21,12 +21,12 @@ class DatabaseBackupTest extends TestCase
use RefreshDatabase;
#[DataProvider('data')]
public function test_create_backup(string $db): void
public function test_create_backup(string $db, string $version): void
{
SSH::fake();
Http::fake();
$this->setupDatabase($db);
$this->setupDatabase($db, $version);
$this->actingAs($this->user);
@ -36,7 +36,7 @@ public function test_create_backup(string $db): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$this->post(route('backups.store', [
@ -47,7 +47,7 @@ public function test_create_backup(string $db): void
'interval' => '0 * * * *',
'keep' => '10',
])
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backups', [
'status' => BackupStatus::RUNNING,
@ -58,9 +58,6 @@ public function test_create_backup(string $db): void
]);
}
/**
* @throws JsonException
*/
public function test_create_custom_interval_backup(): void
{
Bus::fake();
@ -73,7 +70,7 @@ public function test_create_custom_interval_backup(): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$this->post(route('backups.store', ['server' => $this->server]), [
@ -83,7 +80,7 @@ public function test_create_custom_interval_backup(): void
'custom_interval' => '* * * * *',
'keep' => '10',
])
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backups', [
'status' => BackupStatus::RUNNING,
@ -100,7 +97,7 @@ public function test_see_backups_list(): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
Backup::factory()->create([
@ -113,9 +110,6 @@ public function test_see_backups_list(): void
->assertSuccessful();
}
/**
* @throws JsonException
*/
public function test_update_backup(): void
{
$this->actingAs($this->user);
@ -126,7 +120,7 @@ public function test_update_backup(): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$backup = Backup::factory()->create([
@ -144,7 +138,7 @@ public function test_update_backup(): void
'interval' => '0 0 * * *',
'keep' => 10,
])
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backups', [
'id' => $backup->id,
@ -154,9 +148,9 @@ public function test_update_backup(): void
}
#[DataProvider('data')]
public function test_delete_backup(string $db): void
public function test_delete_backup(string $db, string $version): void
{
$this->setupDatabase($db);
$this->setupDatabase($db, $version);
$this->actingAs($this->user);
@ -166,7 +160,7 @@ public function test_delete_backup(string $db): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$backup = Backup::factory()->create([
@ -176,7 +170,7 @@ public function test_delete_backup(string $db): void
]);
$this->delete(route('backups.destroy', ['server' => $this->server, 'backup' => $backup]))
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseMissing('backups', [
'id' => $backup->id,
@ -184,12 +178,12 @@ public function test_delete_backup(string $db): void
}
#[DataProvider('data')]
public function test_restore_backup(string $db): void
public function test_restore_backup(string $db, string $version): void
{
Http::fake();
SSH::fake();
$this->setupDatabase($db);
$this->setupDatabase($db, $version);
$this->actingAs($this->user);
@ -199,7 +193,7 @@ public function test_restore_backup(string $db): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$backup = Backup::factory()->create([
@ -217,7 +211,7 @@ public function test_restore_backup(string $db): void
]), [
'database' => $database->id,
])
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('backup_files', [
'id' => $backupFile->id,
@ -225,14 +219,14 @@ public function test_restore_backup(string $db): void
]);
}
private function setupDatabase(string $database): void
private function setupDatabase(string $database, string $version): void
{
$this->server->services()->where('type', 'database')->delete();
$this->server->services()->create([
'type' => 'database',
'name' => config('core.databases_name.'.$database),
'version' => config('core.databases_version.'.$database),
'name' => $database,
'version' => $version,
]);
}
@ -242,9 +236,9 @@ private function setupDatabase(string $database): void
public static function data(): array
{
return [
[\App\Enums\Database::MYSQL80],
[\App\Enums\Database::MARIADB104],
[\App\Enums\Database::POSTGRESQL16],
['mysql', '8.4'],
['mariadb', '10.4'],
['postgresql', '16'],
];
}
}

View File

@ -2,7 +2,6 @@
namespace Tests\Feature;
use App\Enums\NodeJS;
use App\Enums\ServiceStatus;
use App\Facades\SSH;
use App\Models\Service;
@ -25,7 +24,7 @@ public function test_change_default_nodejs_cli(): void
'type' => 'nodejs',
'type_data' => [],
'name' => 'nodejs',
'version' => NodeJS::V16,
'version' => '16',
'status' => ServiceStatus::READY,
'is_default' => false,
]);
@ -34,7 +33,7 @@ public function test_change_default_nodejs_cli(): void
'server' => $this->server->id,
'service' => $service->id,
]), [
'version' => NodeJS::V16,
'version' => '16',
])
->assertSessionDoesntHaveErrors();

View File

@ -2,7 +2,11 @@
namespace Tests\Feature;
use App\Enums\NotificationChannel;
use App\Models\NotificationChannel;
use App\NotificationChannels\Discord;
use App\NotificationChannels\Email;
use App\NotificationChannels\Slack;
use App\NotificationChannels\Telegram;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Http;
@ -19,16 +23,16 @@ public function test_add_email_channel(): void
$this->actingAs($this->user);
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::EMAIL,
'provider' => Email::id(),
'email' => 'email@example.com',
'name' => 'Email',
'global' => true,
])
->assertSessionDoesntHaveErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::EMAIL)
/** @var NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Email::id())
->where('label', 'Email')
->whereNull('project_id')
->first();
@ -45,15 +49,15 @@ public function test_cannot_add_email_channel(): void
$this->actingAs($this->user);
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::EMAIL,
'provider' => Email::id(),
'email' => 'email@example.com',
'name' => 'Email',
'global' => true,
]);
/** @var ?\App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::EMAIL)
/** @var ?NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Email::id())
->where('label', 'Email')
->first();
@ -67,15 +71,15 @@ public function test_add_slack_channel(): void
Http::fake();
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::SLACK,
'provider' => Slack::id(),
'webhook_url' => 'https://hooks.slack.com/services/123/token',
'name' => 'Slack',
])
->assertSessionDoesntHaveErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::SLACK)
/** @var NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Slack::id())
->first();
$this->assertEquals('https://hooks.slack.com/services/123/token', $channel->data['webhook_url']);
@ -91,7 +95,7 @@ public function test_cannot_add_slack_channel(): void
]);
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::SLACK,
'provider' => Slack::id(),
'webhook_url' => 'https://hooks.slack.com/services/123/token',
'name' => 'Slack',
])
@ -99,9 +103,9 @@ public function test_cannot_add_slack_channel(): void
'provider' => 'Could not connect',
]);
/** @var ?\App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::SLACK)
/** @var ?NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Slack::id())
->first();
$this->assertNull($channel);
@ -114,15 +118,15 @@ public function test_add_discord_channel(): void
Http::fake();
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::DISCORD,
'provider' => Discord::id(),
'webhook_url' => 'https://discord.com/api/webhooks/123/token',
'name' => 'Discord',
])
->assertSessionDoesntHaveErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::DISCORD)
/** @var NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Discord::id())
->first();
$this->assertEquals('https://discord.com/api/webhooks/123/token', $channel->data['webhook_url']);
@ -138,7 +142,7 @@ public function test_cannot_add_discord_channel(): void
]);
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::DISCORD,
'provider' => Discord::id(),
'webhook_url' => 'https://discord.com/api/webhooks/123/token',
'name' => 'Slack',
])
@ -146,9 +150,9 @@ public function test_cannot_add_discord_channel(): void
'provider' => 'Could not connect',
]);
/** @var ?\App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::DISCORD)
/** @var ?NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Discord::id())
->first();
$this->assertNull($channel);
@ -161,16 +165,16 @@ public function test_add_telegram_channel(): void
Http::fake();
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::TELEGRAM,
'provider' => Telegram::id(),
'bot_token' => 'token',
'chat_id' => '123',
'name' => 'Telegram',
])
->assertSessionDoesntHaveErrors();
/** @var \App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::TELEGRAM)
/** @var NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Telegram::id())
->first();
$this->assertEquals('123', $channel->data['chat_id']);
@ -187,7 +191,7 @@ public function test_cannot_add_telegram_channel(): void
]);
$this->post(route('notification-channels.store'), [
'provider' => NotificationChannel::TELEGRAM,
'provider' => Telegram::id(),
'bot_token' => 'token',
'chat_id' => '123',
'name' => 'Telegram',
@ -196,9 +200,9 @@ public function test_cannot_add_telegram_channel(): void
'provider' => 'Could not connect',
]);
/** @var ?\App\Models\NotificationChannel $channel */
$channel = \App\Models\NotificationChannel::query()
->where('provider', NotificationChannel::TELEGRAM)
/** @var ?NotificationChannel $channel */
$channel = NotificationChannel::query()
->where('provider', Telegram::id())
->first();
$this->assertNull($channel);
@ -208,7 +212,7 @@ public function test_see_channels_list(): void
{
$this->actingAs($this->user);
\App\Models\NotificationChannel::factory()->create();
NotificationChannel::factory()->create();
$this->get(route('notification-channels'))
->assertInertia(fn (AssertableInertia $page) => $page->component('notification-channels/index'));
@ -218,7 +222,7 @@ public function test_delete_channel(): void
{
$this->actingAs($this->user);
$channel = \App\Models\NotificationChannel::factory()->create();
$channel = NotificationChannel::factory()->create();
$this->delete(route('notification-channels.destroy', [
'notificationChannel' => $channel->id,

View File

@ -2,11 +2,14 @@
namespace Tests\Feature;
use App\Enums\ServerProvider;
use App\Models\ServerProvider;
use App\ServerProviders\DigitalOcean;
use App\ServerProviders\Hetzner;
use App\ServerProviders\Linode;
use App\ServerProviders\Vultr;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Inertia\Testing\AssertableInertia;
use JsonException;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;
@ -16,8 +19,6 @@ class ServerProvidersTest extends TestCase
/**
* @param array<string, mixed> $input
*
* @throws JsonException
*/
#[DataProvider('data')]
public function test_connect_provider(string $provider, array $input): void
@ -34,7 +35,7 @@ public function test_connect_provider(string $provider, array $input): void
$input
);
$this->post(route('server-providers.store'), $data)
->assertSessionHasNoErrors();
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('server_providers', [
'provider' => $provider,
@ -75,7 +76,7 @@ public function test_see_providers_list(): void
{
$this->actingAs($this->user);
\App\Models\ServerProvider::factory()->create([
ServerProvider::factory()->create([
'user_id' => $this->user->id,
]);
@ -84,21 +85,18 @@ public function test_see_providers_list(): void
->assertInertia(fn (AssertableInertia $page) => $page->component('server-providers/index'));
}
/**
* @throws JsonException
*/
#[DataProvider('data')]
public function test_delete_provider(string $provider): void
{
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
$this->delete(route('server-providers.destroy', $provider))
->assertSessionHasNoErrors()
->assertSessionDoesntHaveErrors()
->assertRedirect(route('server-providers'));
$this->assertDatabaseMissing('server_providers', [
@ -111,7 +109,7 @@ public function test_cannot_delete_provider(string $provider): void
{
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => $provider,
]);
@ -144,32 +142,32 @@ public static function data(): array
// ],
// ],
[
ServerProvider::LINODE,
Linode::id(),
[
'token' => 'token',
],
],
[
ServerProvider::LINODE,
Linode::id(),
[
'token' => 'token',
'global' => 1,
],
],
[
ServerProvider::DIGITALOCEAN,
DigitalOcean::id(),
[
'token' => 'token',
],
],
[
ServerProvider::VULTR,
Vultr::id(),
[
'token' => 'token',
],
],
[
ServerProvider::HETZNER,
Hetzner::id(),
[
'token' => 'token',
],

View File

@ -2,38 +2,37 @@
namespace Tests\Feature;
use App\Enums\Database;
use App\Enums\OperatingSystem;
use App\Enums\ServerProvider;
use App\Enums\ServerStatus;
use App\Enums\ServiceStatus;
use App\Enums\Webserver;
use App\Facades\SSH;
use App\Models\ServerProvider;
use App\NotificationChannels\Email\NotificationMail;
use App\ServerProviders\Custom;
use App\ServerProviders\Hetzner;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class ServerTest extends TestCase
{
use RefreshDatabase;
public function test_create_regular_server(): void
public function test_create_server(): void
{
$this->actingAs($this->user);
Storage::fake();
SSH::fake('Active: active'); // fake output for service installations
$this->post(route('servers.store', [
'provider' => ServerProvider::CUSTOM,
'provider' => Custom::id(),
'name' => 'test',
'ip' => '1.1.1.1',
'port' => '22',
'os' => OperatingSystem::UBUNTU22,
'webserver' => Webserver::NGINX,
'database' => Database::MYSQL80,
'php' => '8.2',
]))
->assertSessionDoesntHaveErrors();
@ -45,85 +44,6 @@ public function test_create_regular_server(): void
$this->assertDatabaseHas('services', [
'server_id' => 1,
'type' => 'php',
'version' => '8.2',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 1,
'type' => 'webserver',
'name' => 'nginx',
'version' => 'latest',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 1,
'type' => 'database',
'name' => 'mysql',
'version' => '8.0',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 1,
'type' => 'firewall',
'name' => 'ufw',
'version' => 'latest',
'status' => ServiceStatus::READY,
]);
}
public function test_create_regular_server_with_caddy(): void
{
$this->actingAs($this->user);
SSH::fake('Active: active'); // fake output for service installations
$this->post(route('servers.store', [
'provider' => ServerProvider::CUSTOM,
'name' => 'caddy-test',
'ip' => '2.2.2.2',
'port' => '22',
'os' => OperatingSystem::UBUNTU22,
'webserver' => Webserver::CADDY,
'database' => Database::MYSQL80,
'php' => '8.2',
]))
->assertSessionDoesntHaveErrors();
$this->assertDatabaseHas('servers', [
'name' => 'caddy-test',
'ip' => '2.2.2.2',
'status' => ServerStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 2,
'type' => 'php',
'version' => '8.2',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 2,
'type' => 'webserver',
'name' => 'caddy',
'version' => 'latest',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 2,
'type' => 'database',
'name' => 'mysql',
'version' => '8.0',
'status' => ServiceStatus::READY,
]);
$this->assertDatabaseHas('services', [
'server_id' => 2,
'type' => 'firewall',
'name' => 'ufw',
'version' => 'latest',
@ -156,16 +76,16 @@ public function test_cannot_delete_on_provider(): void
$this->actingAs($this->user);
$provider = \App\Models\ServerProvider::factory()->create([
$provider = ServerProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => ServerProvider::HETZNER,
'provider' => Hetzner::id(),
'credentials' => [
'token' => 'token',
],
]);
$this->server->update([
'provider' => ServerProvider::HETZNER,
'provider' => Hetzner::id(),
'provider_id' => $provider->id,
'provider_data' => [
'hetzner_id' => 1,

View File

@ -4,10 +4,15 @@
use App\Enums\LoadBalancerMethod;
use App\Enums\SiteStatus;
use App\Enums\SiteType;
use App\Enums\SourceControl;
use App\Facades\SSH;
use App\Models\Site;
use App\Models\SourceControl;
use App\SiteTypes\Laravel;
use App\SiteTypes\LoadBalancer;
use App\SiteTypes\PHPBlank;
use App\SiteTypes\PHPMyAdmin;
use App\SiteTypes\Wordpress;
use App\SourceControlProviders\Github;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Inertia\Testing\AssertableInertia;
@ -33,9 +38,9 @@ public function test_create_site(array $inputs): void
$this->actingAs($this->user);
/** @var \App\Models\SourceControl $sourceControl */
$sourceControl = \App\Models\SourceControl::factory()->create([
'provider' => SourceControl::GITHUB,
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => Github::id(),
]);
$inputs['source_control'] = $sourceControl->id;
@ -70,7 +75,7 @@ public function test_isolated_user_failure(array $inputs): void
public function test_create_site_failed_due_to_source_control(int $status): void
{
$inputs = [
'type' => SiteType::LARAVEL,
'type' => Laravel::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -89,9 +94,9 @@ public function test_create_site_failed_due_to_source_control(int $status): void
$this->actingAs($this->user);
/** @var \App\Models\SourceControl $sourceControl */
$sourceControl = \App\Models\SourceControl::factory()->create([
'provider' => SourceControl::GITHUB,
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => Github::id(),
]);
$inputs['source_control'] = $sourceControl->id;
@ -177,9 +182,9 @@ public function test_update_source_control(): void
], 201),
]);
/** @var \App\Models\SourceControl $sourceControl */
$sourceControl = \App\Models\SourceControl::factory()->create([
'provider' => SourceControl::GITHUB,
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => Github::id(),
]);
$this->patch(route('site-settings.update-source-control', [
@ -206,9 +211,9 @@ public function test_failed_to_update_source_control(): void
], 404),
]);
/** @var \App\Models\SourceControl $sourceControl */
$sourceControl = \App\Models\SourceControl::factory()->create([
'provider' => SourceControl::GITHUB,
/** @var SourceControl $sourceControl */
$sourceControl = SourceControl::factory()->create([
'provider' => Github::id(),
]);
$this->patch(route('site-settings.update-source-control', [
@ -279,7 +284,7 @@ public static function failure_create_data(): array
return [
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -289,7 +294,7 @@ public static function failure_create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -299,7 +304,7 @@ public static function failure_create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -309,7 +314,7 @@ public static function failure_create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -319,7 +324,7 @@ public static function failure_create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -338,7 +343,7 @@ public static function create_data(): array
return [
[
[
'type' => SiteType::LARAVEL,
'type' => Laravel::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com', 'www2.example.com'],
'php_version' => '8.2',
@ -350,7 +355,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::LARAVEL,
'type' => Laravel::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com', 'www2.example.com'],
'php_version' => '8.2',
@ -363,7 +368,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::WORDPRESS,
'type' => Wordpress::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -380,7 +385,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::WORDPRESS,
'type' => Wordpress::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -398,7 +403,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -407,7 +412,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -417,7 +422,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::PHPMYADMIN,
'type' => PHPMyAdmin::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -426,7 +431,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::PHPMYADMIN,
'type' => PHPMyAdmin::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'php_version' => '8.2',
@ -436,7 +441,7 @@ public static function create_data(): array
],
[
[
'type' => SiteType::LOAD_BALANCER,
'type' => LoadBalancer::id(),
'domain' => 'example.com',
'aliases' => ['www.example.com'],
'user' => 'example',

View File

@ -3,6 +3,9 @@
namespace Tests\Feature;
use App\Models\SourceControl;
use App\SourceControlProviders\Bitbucket;
use App\SourceControlProviders\Github;
use App\SourceControlProviders\Gitlab;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use PHPUnit\Framework\Attributes\DataProvider;
@ -38,7 +41,7 @@ public function test_connect_provider(string $provider, ?string $customUrl, arra
'url' => $customUrl,
]);
if (isset($input['global'])) {
if (isset($input['global']) && $input['global']) {
$this->assertDatabaseHas('source_controls', [
'provider' => $provider,
'url' => $customUrl,
@ -132,11 +135,11 @@ public function test_edit_source_control(string $provider, ?string $url, array $
public static function data(): array
{
return [
['github', null, ['token' => 'test']],
['github', null, ['token' => 'test', 'global' => '1']],
['gitlab', null, ['token' => 'test']],
['gitlab', 'https://git.example.com/', ['token' => 'test']],
['bitbucket', null, ['username' => 'test', 'password' => 'test']],
[Github::id(), null, ['token' => 'test']],
[Github::id(), null, ['token' => 'test', 'global' => true]],
[Gitlab::id(), null, ['token' => 'test']],
[Gitlab::id(), 'https://git.example.com/', ['token' => 'test']],
[Bitbucket::id(), null, ['username' => 'test', 'password' => 'test']],
];
}
}

View File

@ -2,11 +2,12 @@
namespace Tests\Feature;
use App\Enums\StorageProvider;
use App\Facades\FTP;
use App\Models\Backup;
use App\Models\Database;
use App\Models\StorageProvider as StorageProviderModel;
use App\StorageProviders\Dropbox;
use App\StorageProviders\Local;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Inertia\Testing\AssertableInertia;
@ -25,17 +26,17 @@ public function test_create(array $input): void
{
$this->actingAs($this->user);
if ($input['provider'] === StorageProvider::DROPBOX) {
if ($input['provider'] === Dropbox::id()) {
Http::fake();
}
if ($input['provider'] === StorageProvider::FTP) {
if ($input['provider'] === \App\StorageProviders\FTP::id()) {
FTP::fake();
}
$this->post(route('storage-providers.store'), $input);
if ($input['provider'] === StorageProvider::FTP) {
if ($input['provider'] === \App\StorageProviders\FTP::id()) {
FTP::assertConnected($input['host']);
}
@ -52,7 +53,7 @@ public function test_see_providers_list(): void
StorageProviderModel::factory()->create([
'user_id' => $this->user->id,
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$this->get(route('storage-providers'))
@ -111,14 +112,14 @@ public static function createData(): array
return [
[
[
'provider' => StorageProvider::LOCAL,
'provider' => Local::id(),
'name' => 'local-test',
'path' => '/home/vito/backups',
],
],
[
[
'provider' => StorageProvider::LOCAL,
'provider' => Local::id(),
'name' => 'local-test',
'path' => '/home/vito/backups',
'global' => 1,
@ -126,7 +127,7 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::FTP,
'provider' => \App\StorageProviders\FTP::id(),
'name' => 'ftp-test',
'host' => '1.2.3.4',
'port' => '22',
@ -139,7 +140,7 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::FTP,
'provider' => \App\StorageProviders\FTP::id(),
'name' => 'ftp-test',
'host' => '1.2.3.4',
'port' => '22',
@ -153,14 +154,14 @@ public static function createData(): array
],
[
[
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
'name' => 'dropbox-test',
'token' => 'token',
],
],
[
[
'provider' => StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
'name' => 'dropbox-test',
'token' => 'token',
'global' => 1,

View File

@ -62,6 +62,7 @@ public function test_create_worker(): void
$this->post(route('workers.store', [
'server' => $this->server,
]), [
'name' => 'Test Worker',
'command' => 'php artisan worker:work',
'user' => 'vito',
'auto_start' => 1,
@ -72,6 +73,7 @@ public function test_create_worker(): void
$this->assertDatabaseHas('workers', [
'server_id' => $this->server->id,
'name' => 'Test Worker',
'command' => 'php artisan worker:work',
'user' => 'vito',
'auto_start' => 1,
@ -94,6 +96,7 @@ public function test_create_worker_as_isolated_user(): void
'server' => $this->server,
'site' => $this->site,
]), [
'name' => 'Test Worker',
'command' => 'php artisan worker:work',
'user' => 'example',
'auto_start' => 1,
@ -124,6 +127,7 @@ public function test_cannot_create_worker_as_invalid_user(): void
'server' => $this->server,
'site' => $this->site,
]), [
'name' => 'Test Worker',
'command' => 'php artisan worker:work',
'user' => 'example',
'auto_start' => 1,
@ -154,6 +158,7 @@ public function test_cannot_create_worker_on_another_sites_user(): void
'server' => $this->server,
'site' => $this->site,
]), [
'name' => 'Test Worker',
'command' => 'php artisan worker:work',
'user' => 'example',
'auto_start' => 1,

View File

@ -2,16 +2,21 @@
namespace Tests;
use App\Enums\Database;
use App\Enums\ServiceStatus;
use App\Enums\UserRole;
use App\Enums\Webserver;
use App\Models\NotificationChannel;
use App\Models\Redirect;
use App\Models\Server;
use App\Models\Site;
use App\Models\SourceControl;
use App\Models\User;
use App\NotificationChannels\Email;
use App\Services\Database\Mysql;
use App\Services\Firewall\Ufw;
use App\Services\PHP\PHP;
use App\Services\ProcessManager\Supervisor;
use App\Services\Redis\Redis;
use App\Services\Webserver\Nginx;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\File;
@ -46,7 +51,7 @@ protected function setUp(): void
$this->user->createDefaultProject();
$this->notificationChannel = NotificationChannel::factory()->create([
'provider' => \App\Enums\NotificationChannel::EMAIL,
'provider' => Email::id(),
'connected' => true,
'data' => [
'email' => 'user@example.com',
@ -81,10 +86,35 @@ private function setupServer(): void
$this->server->provider()->generateKeyPair();
}
$this->server->type()->createServices([
'webserver' => Webserver::NGINX,
'database' => Database::MYSQL80,
'php' => '8.2',
$this->server->services()->create([
'type' => Nginx::type(),
'name' => Nginx::id(),
'version' => 'latest',
]);
$this->server->services()->create([
'type' => Mysql::type(),
'name' => Mysql::id(),
'version' => '8.0',
]);
$this->server->services()->create([
'type' => PHP::type(),
'name' => PHP::id(),
'version' => '8.2',
]);
$this->server->services()->create([
'type' => Ufw::type(),
'name' => Ufw::id(),
'version' => 'latest',
]);
$this->server->services()->create([
'type' => Supervisor::type(),
'name' => Supervisor::id(),
'version' => 'latest',
]);
$this->server->services()->create([
'type' => Redis::type(),
'name' => Redis::id(),
'version' => 'latest',
]);
$this->server->services()->update([

View File

@ -2,20 +2,18 @@
namespace Tests\Traits;
use App\Enums\Database;
use App\Enums\LoadBalancerMethod;
use App\Enums\PHP;
use App\Enums\ServiceStatus;
use App\Enums\SiteType;
use App\Enums\Webserver;
use App\Models\Server;
use App\Models\Site;
use App\SiteTypes\LoadBalancer;
use App\SiteTypes\PHPBlank;
trait PrepareLoadBalancer
{
private function prepare(): void
{
$this->site->type = SiteType::LOAD_BALANCER;
$this->site->type = LoadBalancer::id();
$this->site->type_data = [
'method' => LoadBalancerMethod::ROUND_ROBIN,
];
@ -26,11 +24,6 @@ private function prepare(): void
'project_id' => $this->user->current_project_id,
]);
foreach ($servers as $server) {
$server->type()->createServices([
'webserver' => Webserver::NGINX,
'database' => Database::NONE,
'php' => PHP::NONE,
]);
$server->services()->update([
'status' => ServiceStatus::READY,
]);
@ -38,7 +31,7 @@ private function prepare(): void
'domain' => 'vito.test',
'aliases' => ['www.vito.test'],
'server_id' => $server->id,
'type' => SiteType::PHP_BLANK,
'type' => PHPBlank::id(),
'path' => '/home/vito/vito.test',
'web_directory' => '',
]);

View File

@ -21,7 +21,7 @@ public function test_install_vito_agent(): void
'https://api.github.com/repos/vitodeploy/agent/tags' => Http::response([['name' => '0.1.0']]),
]);
$this->server->monitoring()->delete();
$this->server->monitoring()?->delete();
app(Install::class)->install($this->server, [
'type' => 'monitoring',
@ -40,7 +40,7 @@ public function test_install_vito_agent(): void
public function test_install_vito_agent_failed(): void
{
$this->server->monitoring()->delete();
$this->server->monitoring()?->delete();
$this->expectExceptionMessage('Failed to fetch tags');
SSH::fake('Active: inactive');
Http::fake([

View File

@ -20,7 +20,7 @@ public function test_uninstall_vito_agent(): void
{
SSH::fake();
$this->server->monitoring()->delete();
$this->server->monitoring()?->delete();
$service = Service::factory()->create([
'server_id' => $this->server->id,

View File

@ -6,6 +6,7 @@
use App\Models\Backup;
use App\Models\Database;
use App\Models\StorageProvider;
use App\StorageProviders\Dropbox;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@ -29,7 +30,7 @@ public function test_run_backups(): void
$storage = StorageProvider::factory()->create([
'user_id' => $this->user->id,
'provider' => \App\Enums\StorageProvider::DROPBOX,
'provider' => Dropbox::id(),
]);
$backup = Backup::factory()->create([

View File

@ -3,7 +3,7 @@
namespace Tests\Unit\SSH\Services\Database;
use App\Facades\SSH;
use App\SSH\Services\Database\Database;
use App\Services\Database\Database;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;

View File

@ -3,7 +3,7 @@
namespace Tests\Unit\SSH\Services\Database;
use App\Facades\SSH;
use App\SSH\Services\Database\Database;
use App\Services\Database\Database;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;

View File

@ -3,7 +3,7 @@
namespace Tests\Unit\SSH\Services\Database;
use App\Facades\SSH;
use App\SSH\Services\Database\Database;
use App\Services\Database\Database;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;

View File

@ -2,7 +2,6 @@
namespace Tests\Unit\StorageProviders;
use App\Enums\StorageProvider;
use App\Models\StorageProvider as StorageProviderModel;
use App\StorageProviders\S3;
use Aws\Command;
@ -18,7 +17,7 @@ class S3Test extends TestCase
public function test_s3_connect_successful(): void
{
$storageProvider = StorageProviderModel::factory()->create([
'provider' => StorageProvider::S3,
'provider' => S3::id(),
'credentials' => [
'api_url' => 'https://fake-bucket.s3.us-east-1.s3-compatible.com',
'key' => 'fake-key',
@ -62,7 +61,7 @@ public function test_s3_connect_successful(): void
public function test_s3_connect_failure(): void
{
$storageProvider = StorageProviderModel::factory()->create([
'provider' => StorageProvider::S3,
'provider' => S3::id(),
'credentials' => [
'key' => 'fake-key',
'secret' => 'fake-secret',