mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 15:39:59 +00:00
- Delete Blade components, component classes, Livewire components and views that nothing uses after the redesign. - Delete tests that only compare Blade/CSS source text; keep the source checks for authorization gates, stable wire:key values and escaping. - Update stale tests to the current UI and behaviour. - Update DESIGN.md to the current navigation and layout. - Add a lesson: test behaviour, not source markup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
204 lines
8.5 KiB
PHP
204 lines
8.5 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('loading-indicator shrink-0 animate-spin', 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'],
|
|
]);
|