mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-29 01:54:37 +08:00
Add a /dashboard/canvas page that renders every team server with its resources and their running or queued deployments, backed by a new ServerCanvasController::dashboard endpoint and a per-server usage endpoint for zone headers. The dashboard remembers the list/canvas choice and each section (projects, servers) its own table/grid view. - Show Deploying/Queued pills on canvas cards and a foldable recent deployments panel; add shared CanvasControls component - Allow backup downloads from the server host via the S3 download storage (PrepareFileDownloadJob accepts a null container) - Extract backup toggle/run actions into ManagesDatabaseBackup and surface them in backup execution headers; merge S3 and retention sections into the general backup settings - Move deployments indicator to the top bar and add a main nav resource menu with submenus; simplify breadcrumbs and settings layouts - Add shared variables overview canvas and scheduled task modals - Add feature tests for dashboard canvas, view modes, navbar submenus, backup S3 downloads and scheduled task modals
103 lines
3.8 KiB
PHP
103 lines
3.8 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Project\Shared\ScheduledTask\All;
|
|
use App\Livewire\Project\Shared\ScheduledTask\Show;
|
|
use App\Models\Application;
|
|
use App\Models\Environment;
|
|
use App\Models\InstanceSettings;
|
|
use App\Models\Project;
|
|
use App\Models\ScheduledTask;
|
|
use App\Models\Server;
|
|
use App\Models\StandaloneDocker;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
$this->withoutVite();
|
|
Server::flushIdentityMap();
|
|
InstanceSettings::forceCreate(['id' => 0]);
|
|
|
|
$this->user = User::factory()->create();
|
|
$this->team = Team::factory()->create();
|
|
$this->user->teams()->attach($this->team, ['role' => 'owner']);
|
|
|
|
$server = Server::factory()->create(['team_id' => $this->team->id]);
|
|
$destination = StandaloneDocker::where('server_id', $server->id)->first();
|
|
$project = Project::factory()->create(['team_id' => $this->team->id]);
|
|
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
|
$this->application = Application::factory()->create([
|
|
'environment_id' => $environment->id,
|
|
'destination_id' => $destination->id,
|
|
'destination_type' => $destination->getMorphClass(),
|
|
]);
|
|
$this->task = ScheduledTask::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'application_id' => $this->application->id,
|
|
'name' => 'modal-task',
|
|
'command' => 'echo hello',
|
|
]);
|
|
|
|
$this->actingAs($this->user);
|
|
session(['currentTeam' => $this->team]);
|
|
});
|
|
|
|
test('opening a task shows the editor modal', function () {
|
|
Livewire::test(All::class, ['resource' => $this->application])
|
|
->call('openTask', $this->task->uuid)
|
|
->assertSet('taskModalOpen', true)
|
|
->assertSet('taskUuid', $this->task->uuid)
|
|
->assertSeeLivewire(Show::class);
|
|
});
|
|
|
|
test('task uuid in the url opens the modal on load', function () {
|
|
Livewire::withQueryParams(['task_uuid' => $this->task->uuid])
|
|
->test(All::class, ['resource' => $this->application])
|
|
->assertSet('taskModalOpen', true)
|
|
->assertSeeLivewire(Show::class);
|
|
});
|
|
|
|
test('a task of another resource cannot be opened', function () {
|
|
$otherTask = ScheduledTask::factory()->create(['team_id' => Team::factory()->create()->id]);
|
|
|
|
expect(fn () => Livewire::test(All::class, ['resource' => $this->application])
|
|
->call('openTask', $otherTask->uuid))
|
|
->toThrow(ModelNotFoundException::class);
|
|
});
|
|
|
|
test('deleting a task from the modal closes it', function () {
|
|
$list = Livewire::test(All::class, ['resource' => $this->application])
|
|
->call('openTask', $this->task->uuid);
|
|
|
|
Livewire::test(Show::class, ['resource' => $this->application, 'task' => $this->task])
|
|
->call('delete')
|
|
->assertDispatched('scheduledTaskDeleted');
|
|
|
|
expect(ScheduledTask::find($this->task->id))->toBeNull();
|
|
|
|
$list->dispatch('scheduledTaskDeleted')
|
|
->assertSet('taskModalOpen', false)
|
|
->assertSet('taskUuid', '')
|
|
->assertDontSee('modal-task');
|
|
});
|
|
|
|
test('old task page url redirects to the list with the modal open', function () {
|
|
$application = $this->application->load('environment.project');
|
|
|
|
$this->get(route('project.application.scheduled-tasks', [
|
|
'project_uuid' => $application->environment->project->uuid,
|
|
'environment_uuid' => $application->environment->uuid,
|
|
'application_uuid' => $application->uuid,
|
|
'task_uuid' => $this->task->uuid,
|
|
]))->assertRedirect(route('project.application.scheduled-tasks.show', [
|
|
'project_uuid' => $application->environment->project->uuid,
|
|
'environment_uuid' => $application->environment->uuid,
|
|
'application_uuid' => $application->uuid,
|
|
'task_uuid' => $this->task->uuid,
|
|
]));
|
|
});
|