155 lines
5.5 KiB
PHP
155 lines
5.5 KiB
PHP
<?php
|
|
|
|
use App\Enums\OperationKind;
|
|
use App\Enums\OperationStatus;
|
|
use App\Models\Application;
|
|
use App\Models\Environment;
|
|
use App\Models\Operation;
|
|
use App\Models\Organisation;
|
|
use App\Models\Service;
|
|
use App\Models\User;
|
|
use Inertia\Testing\AssertableInertia;
|
|
|
|
it('lists organisation operations with filters and target context', function () {
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$application = Application::factory()->for($organisation)->create();
|
|
$environment = Environment::factory()->for($application)->create();
|
|
|
|
Operation::factory()->create([
|
|
'kind' => OperationKind::ENVIRONMENT_DEPLOY,
|
|
'target_type' => $environment->getMorphClass(),
|
|
'target_id' => $environment->id,
|
|
'status' => OperationStatus::IN_PROGRESS,
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->get(route('operations.index', [
|
|
'organisation' => $organisation->id,
|
|
'kind' => OperationKind::ENVIRONMENT_DEPLOY->value,
|
|
]));
|
|
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
|
->component('operations/Index', false)
|
|
->where('operations.data.0.kind', OperationKind::ENVIRONMENT_DEPLOY->value)
|
|
->where('filters.kind', OperationKind::ENVIRONMENT_DEPLOY->value));
|
|
});
|
|
|
|
it('shows an operation with steps and children', function () {
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$service = Service::factory()->for($organisation)->create();
|
|
$operation = Operation::factory()->create([
|
|
'target_type' => $service->getMorphClass(),
|
|
'target_id' => $service->id,
|
|
]);
|
|
$operation->steps()->create([
|
|
'name' => 'Deploy container',
|
|
'order' => 1,
|
|
'status' => OperationStatus::COMPLETED,
|
|
'script' => 'docker ps',
|
|
'logs' => 'ok',
|
|
]);
|
|
|
|
Operation::factory()->create([
|
|
'parent_id' => $operation->id,
|
|
'target_type' => $service->getMorphClass(),
|
|
'target_id' => $service->id,
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->get(route('operations.show', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
|
->component('operations/Show', false)
|
|
->where('operation.hash', $operation->hash)
|
|
->has('operation.steps', 1)
|
|
->has('operation.children', 1));
|
|
});
|
|
|
|
it('does not show operations from another organisation', function () {
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$otherOrganisation = Organisation::factory()->create();
|
|
$service = Service::factory()->for($otherOrganisation)->create();
|
|
$operation = Operation::factory()->create([
|
|
'target_type' => $service->getMorphClass(),
|
|
'target_id' => $service->id,
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->get(route('operations.show', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
$response->assertNotFound();
|
|
});
|
|
|
|
it('retries failed operations owned by the organisation', function () {
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$service = Service::factory()->for($organisation)->create();
|
|
$operation = Operation::factory()->create([
|
|
'target_type' => $service->getMorphClass(),
|
|
'target_id' => $service->id,
|
|
'status' => OperationStatus::FAILED,
|
|
'started_at' => now(),
|
|
'finished_at' => now(),
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->post(route('operations.retry', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
$response->assertRedirect(route('operations.show', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
expect($operation->refresh()->status)->toBe(OperationStatus::PENDING)
|
|
->and($operation->started_at)->toBeNull()
|
|
->and($operation->finished_at)->toBeNull();
|
|
});
|
|
|
|
it('cancels operations and downloads logs', function () {
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$service = Service::factory()->for($organisation)->create();
|
|
$operation = Operation::factory()->create([
|
|
'target_type' => $service->getMorphClass(),
|
|
'target_id' => $service->id,
|
|
'status' => OperationStatus::IN_PROGRESS,
|
|
]);
|
|
$operation->steps()->create([
|
|
'name' => 'Deploy container',
|
|
'order' => 1,
|
|
'status' => OperationStatus::IN_PROGRESS,
|
|
'script' => 'docker ps',
|
|
'logs' => 'hello',
|
|
'error_logs' => 'error',
|
|
]);
|
|
|
|
$this->actingAs($user)->post(route('operations.cancel', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]))->assertRedirect(route('operations.show', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
expect($operation->refresh()->status)->toBe(OperationStatus::CANCELLED)
|
|
->and($operation->finished_at)->not->toBeNull();
|
|
|
|
$response = $this->actingAs($user)->get(route('operations.logs', [
|
|
'organisation' => $organisation->id,
|
|
'operation' => $operation->id,
|
|
]));
|
|
|
|
$response->assertOk();
|
|
$response->assertHeader('content-type', 'text/plain; charset=UTF-8');
|
|
});
|