mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
- Runtime logs: add a compact text view, move display options and log level filters into a View menu, move copy and download into an Export menu, and remove the extra top margin. - Replace spinner loading cards with skeletons on the logs, dynamic configurations, proxy, TLS certificates, Docker images, environment variables, preview deployments, rollback, subscription, cloud provider, and new resource pages.
204 lines
8.4 KiB
PHP
204 lines
8.4 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Server\CreatePage;
|
|
use App\Livewire\Server\New\ByDigitalOcean;
|
|
use App\Livewire\Server\New\ByHetzner;
|
|
use App\Livewire\Server\New\ByVultr;
|
|
use App\Models\CloudProviderToken;
|
|
use App\Models\InstanceSettings;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
InstanceSettings::unguarded(fn () => InstanceSettings::updateOrCreate(['id' => 0], ['id' => 0]));
|
|
|
|
$this->team = Team::factory()->create();
|
|
$this->admin = User::factory()->create();
|
|
$this->admin->teams()->attach($this->team, ['role' => 'admin']);
|
|
|
|
$this->actingAs($this->admin);
|
|
session(['currentTeam' => $this->team]);
|
|
});
|
|
|
|
test('provider token selection redirects to a token specific server creation url', function (string $component, string $provider, string $type) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
]);
|
|
|
|
Livewire::test($component)
|
|
->call('selectToken', $token->id)
|
|
->assertRedirect(route('server.create.token', [
|
|
'type' => $type,
|
|
'token_uuid' => $token->uuid,
|
|
]));
|
|
})->with([
|
|
'hetzner' => [ByHetzner::class, 'hetzner', 'hetzner'],
|
|
'vultr' => [ByVultr::class, 'vultr', 'vultr'],
|
|
'digital-ocean' => [ByDigitalOcean::class, 'digitalocean', 'digital-ocean'],
|
|
]);
|
|
|
|
test('provider token selection is rendered as clickable token boxes', function (string $component, string $provider, string $type, string $tokenName) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
'name' => $tokenName,
|
|
]);
|
|
|
|
Livewire::test($component)
|
|
->assertSee($tokenName)
|
|
->assertSee(route('server.create.token', ['type' => $type, 'token_uuid' => $token->uuid]))
|
|
->assertDontSee('loadingProviderTokenId', false)
|
|
->assertDontSee('coolbox-loading', false)
|
|
->assertSee('href="'.route('server.create.token', ['type' => $type, 'token_uuid' => $token->uuid]).'"', false)
|
|
->assertSee('wire:key="'.$provider.'-token-'.$token->id.'"', false)
|
|
->assertDontSee('wire:click="selectToken(', false)
|
|
->assertDontSee('loading-spinner', false)
|
|
->assertDontSee('Loading Hetzner details...')
|
|
->assertDontSee('Loading Vultr details...')
|
|
->assertDontSee('Loading DigitalOcean details...')
|
|
->assertDontSee('Select a saved token')
|
|
->assertDontSee('You need a saved')
|
|
->assertDontSee('Continue');
|
|
})->with([
|
|
'hetzner' => [ByHetzner::class, 'hetzner', 'hetzner', 'Production Hetzner'],
|
|
'vultr' => [ByVultr::class, 'vultr', 'vultr', 'Production Vultr'],
|
|
'digital-ocean' => [ByDigitalOcean::class, 'digitalocean', 'digital-ocean', 'Production DigitalOcean'],
|
|
]);
|
|
|
|
test('provider token selection shows an add token box when no tokens exist', function (string $component, string $provider, string $title) {
|
|
Livewire::test($component)
|
|
->assertSee($title)
|
|
->assertSee('Add an API token to continue provisioning.')
|
|
->assertSee('Add token')
|
|
->assertDontSee('wire:key="'.$provider.'-token-', false)
|
|
->assertDontSee('wire:click="selectToken(', false);
|
|
})->with([
|
|
'hetzner' => [ByHetzner::class, 'hetzner', 'No Hetzner tokens'],
|
|
'vultr' => [ByVultr::class, 'vultr', 'No Vultr tokens'],
|
|
'digital-ocean' => [ByDigitalOcean::class, 'digitalocean', 'No DigitalOcean tokens'],
|
|
]);
|
|
|
|
test('provider token urls pass the token uuid into the server creation page', function () {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => 'hetzner',
|
|
]);
|
|
|
|
expect(route('server.create.token', [
|
|
'type' => 'hetzner',
|
|
'token_uuid' => $token->uuid,
|
|
]))->toEndWith('/servers/new/hetzner/'.$token->uuid);
|
|
|
|
Livewire::test(CreatePage::class, [
|
|
'type' => 'hetzner',
|
|
'token_uuid' => $token->uuid,
|
|
])
|
|
->assertSet('type', 'hetzner')
|
|
->assertSet('token_uuid', $token->uuid)
|
|
->assertSet('title', 'Hetzner');
|
|
});
|
|
|
|
test('provider token pages defer provider api data loading until wire init', function (string $component, string $provider, string $type, string $loadingText, string $wireInitCall) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
]);
|
|
|
|
Http::fake([
|
|
'*' => Http::response([], 200),
|
|
]);
|
|
|
|
Livewire::test($component, ['selectedTokenUuid' => $token->uuid])
|
|
->assertSet('current_step', 2)
|
|
->assertSet('loading_data', true)
|
|
->assertSee($loadingText)
|
|
->assertSee($wireInitCall, false)
|
|
->assertSee('role="status"', false)
|
|
->assertDontSee('border-b-2 border-primary', false);
|
|
|
|
Http::assertNothingSent();
|
|
})->with([
|
|
'hetzner' => [ByHetzner::class, 'hetzner', 'hetzner', 'Loading Hetzner data', 'wire:init="loadHetznerData"'],
|
|
'vultr' => [ByVultr::class, 'vultr', 'vultr', 'Loading Vultr data', 'wire:init="loadVultrData"'],
|
|
'digital-ocean' => [ByDigitalOcean::class, 'digitalocean', 'digital-ocean', 'Loading DigitalOcean data', 'wire:init="loadDigitalOceanData"'],
|
|
]);
|
|
|
|
test('provider token pages render api error details when a selected token is invalid', function (string $component, string $provider, string $type, string $loadMethod, string $providerName, string $apiMessage, array $responseBody) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
'name' => $providerName.' Token',
|
|
]);
|
|
|
|
Http::fake([
|
|
'*' => Http::response($responseBody, 401),
|
|
]);
|
|
|
|
Livewire::test($component, ['selectedTokenUuid' => $token->uuid])
|
|
->call($loadMethod)
|
|
->assertSet('loading_data', false)
|
|
->assertSet('provider_data_error', "{$providerName} API error: {$apiMessage}")
|
|
->assertDispatched('error')
|
|
->assertSee("Unable to load {$providerName}")
|
|
->assertSee($apiMessage)
|
|
->assertSee('Select another token')
|
|
->assertSee('href="'.route('server.create.type', ['type' => $type]).'"', false)
|
|
->assertSee('wire:navigate', false)
|
|
->assertDontSee('wire:click="previousStep"', false);
|
|
})->with([
|
|
'hetzner' => [ByHetzner::class, 'hetzner', 'hetzner', 'loadHetznerData', 'Hetzner', 'the token you have provided is invalid', ['error' => ['code' => 'unauthorized', 'message' => 'the token you have provided is invalid']]],
|
|
'vultr' => [ByVultr::class, 'vultr', 'vultr', 'loadVultrData', 'Vultr', 'Invalid API key', ['error' => 'Invalid API key', 'status' => 401]],
|
|
'digital-ocean' => [ByDigitalOcean::class, 'digitalocean', 'digital-ocean', 'loadDigitalOceanData', 'DigitalOcean', 'Unable to authenticate you', ['id' => 'Unauthorized', 'message' => 'Unable to authenticate you']],
|
|
]);
|
|
|
|
test('change method button on token specific provider creation pages returns to server type selection', function (string $provider, string $type) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
]);
|
|
|
|
Livewire::test(CreatePage::class, [
|
|
'type' => $type,
|
|
'token_uuid' => $token->uuid,
|
|
])
|
|
->assertSee('Change method')
|
|
->assertSee('href="'.route('server.create').'"', false)
|
|
->assertDontSee('>Back<', false);
|
|
})->with([
|
|
'hetzner' => ['hetzner', 'hetzner'],
|
|
'vultr' => ['vultr', 'vultr'],
|
|
'digital-ocean' => ['digitalocean', 'digital-ocean'],
|
|
]);
|
|
|
|
test('provider token picker is hidden on token specific provider creation pages', function (string $provider, string $type) {
|
|
$token = CloudProviderToken::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'provider' => $provider,
|
|
]);
|
|
$tokenUrl = route('server.create.token', ['type' => $type, 'token_uuid' => $token->uuid]);
|
|
|
|
Livewire::test(CreatePage::class, [
|
|
'type' => $type,
|
|
])
|
|
->assertSee('href="'.$tokenUrl.'"', false)
|
|
->assertDontSee('+ New Token');
|
|
|
|
Livewire::test(CreatePage::class, [
|
|
'type' => $type,
|
|
'token_uuid' => $token->uuid,
|
|
])
|
|
->assertDontSee('href="'.$tokenUrl.'"', false)
|
|
->assertDontSee('Add token')
|
|
->assertDontSee('+ New Token');
|
|
})->with([
|
|
'hetzner' => ['hetzner', 'hetzner'],
|
|
'vultr' => ['vultr', 'vultr'],
|
|
'digital-ocean' => ['digitalocean', 'digital-ocean'],
|
|
]);
|