mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Co-authored-by: Aditya Tripathi <aditya@climactic.co>
199 lines
6.8 KiB
PHP
199 lines
6.8 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Dashboard;
|
|
use App\Livewire\Dashboard\TrafficAnalytics;
|
|
use App\Models\Application;
|
|
use App\Models\Environment;
|
|
use App\Models\InstanceSettings;
|
|
use App\Models\PrivateKey;
|
|
use App\Models\Project;
|
|
use App\Models\Server;
|
|
use App\Models\StandaloneDocker;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use App\Services\SentinelTrafficClient;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
class FakeDashboardTrafficClient extends SentinelTrafficClient
|
|
{
|
|
public array $responses = [];
|
|
|
|
protected function raw(string $url): string
|
|
{
|
|
foreach ($this->responses as $needle => $response) {
|
|
if (str_contains($url, $needle)) {
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
return '{}';
|
|
}
|
|
}
|
|
|
|
class FailingDashboardTrafficClient extends SentinelTrafficClient
|
|
{
|
|
protected function raw(string $url): string
|
|
{
|
|
throw new RuntimeException('Server unreachable');
|
|
}
|
|
}
|
|
|
|
function fakeDashboardTrafficResponses(int $requests = 1000): array
|
|
{
|
|
return [
|
|
'/traffic/apps' => json_encode([]),
|
|
'/traffic/overview' => json_encode([
|
|
'requests' => $requests,
|
|
'bytes_in' => 5000,
|
|
'bytes_out' => 25000,
|
|
'status' => ['s2xx' => 900, 's3xx' => 50, 's4xx' => 40, 's5xx' => 10],
|
|
'latency' => ['p50' => 12.5, 'p95' => 45.2, 'p99' => 90.1],
|
|
'unique_visitors' => 320,
|
|
]),
|
|
'/traffic/breakdown/country' => json_encode([
|
|
['value' => 'US', 'requests' => 600, 'bytes_out' => 15000],
|
|
]),
|
|
];
|
|
}
|
|
|
|
beforeEach(function () {
|
|
InstanceSettings::forceCreate(['id' => 0]);
|
|
$this->team = Team::factory()->create();
|
|
$this->user = User::factory()->create();
|
|
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
|
$this->actingAs($this->user);
|
|
session(['currentTeam' => $this->team]);
|
|
|
|
$this->privateKey = PrivateKey::factory()->create(['team_id' => $this->team->id]);
|
|
});
|
|
|
|
it('hides traffic analytics from the dashboard when no server has it enabled', function () {
|
|
$server = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$server->settings->is_traffic_analytics_enabled = false;
|
|
$server->settings->save();
|
|
|
|
Livewire::test(Dashboard::class)
|
|
->assertOk()
|
|
->assertDontSee('Traffic analytics');
|
|
});
|
|
|
|
it('renders the team traffic summary aggregated across servers with an approximate badge', function () {
|
|
$serverOne = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$serverOne->settings->is_traffic_analytics_enabled = true;
|
|
$serverOne->settings->save();
|
|
|
|
$serverTwo = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$serverTwo->settings->is_traffic_analytics_enabled = true;
|
|
$serverTwo->settings->save();
|
|
|
|
$fakeOne = new FakeDashboardTrafficClient($serverOne);
|
|
$fakeOne->responses = fakeDashboardTrafficResponses(1000);
|
|
|
|
$fakeTwo = new FakeDashboardTrafficClient($serverTwo);
|
|
$fakeTwo->responses = fakeDashboardTrafficResponses(500);
|
|
|
|
app()->bind(SentinelTrafficClient::class, function ($app, $params) use ($serverOne, $fakeOne, $fakeTwo) {
|
|
$server = $params['server'] ?? null;
|
|
|
|
return $server && $server->is($serverOne) ? $fakeOne : $fakeTwo;
|
|
});
|
|
|
|
loadLazy(Livewire::test(TrafficAnalytics::class))
|
|
->assertOk()
|
|
->assertSee('Requests')
|
|
->assertSee('1,500')
|
|
->assertSee('Unique visitors')
|
|
->assertSee('approximate');
|
|
});
|
|
|
|
it('shows only sparkline KPI cards that link through to the full analytics page', function () {
|
|
$server = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$server->settings->is_traffic_analytics_enabled = true;
|
|
$server->settings->save();
|
|
|
|
$otherTeam = Team::factory()->create();
|
|
$otherProject = Project::factory()->create(['team_id' => $otherTeam->id]);
|
|
$otherEnvironment = Environment::factory()->create(['project_id' => $otherProject->id]);
|
|
$otherServer = Server::factory()->create(['team_id' => $otherTeam->id]);
|
|
$otherDestination = StandaloneDocker::factory()->create(['server_id' => $otherServer->id, 'network' => 'other-team-test']);
|
|
|
|
$otherTeamApplication = Application::factory()->create([
|
|
'name' => 'Secret Other Team App',
|
|
'environment_id' => $otherEnvironment->id,
|
|
'destination_id' => $otherDestination->id,
|
|
'destination_type' => StandaloneDocker::class,
|
|
]);
|
|
|
|
$fake = new FakeDashboardTrafficClient($server);
|
|
$fake->responses = fakeDashboardTrafficResponses(1000);
|
|
$fake->responses['/traffic/apps'] = json_encode([$otherTeamApplication->uuid]);
|
|
|
|
app()->bind(SentinelTrafficClient::class, fn () => $fake);
|
|
|
|
loadLazy(Livewire::test(TrafficAnalytics::class))
|
|
->assertOk()
|
|
// The slimmed dashboard shows only KPI cards + a link to /analytics — no per-app rows.
|
|
->assertSee('Open analytics')
|
|
->assertSee(route('analytics'), false)
|
|
->assertDontSee('Top applications')
|
|
->assertDontSee('Secret Other Team App')
|
|
->assertDontSee($otherTeamApplication->uuid);
|
|
});
|
|
|
|
it('hides dashboard analytics when every server fetch fails', function () {
|
|
$serverOne = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$serverOne->settings->is_traffic_analytics_enabled = true;
|
|
$serverOne->settings->save();
|
|
|
|
$serverTwo = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
$serverTwo->settings->is_traffic_analytics_enabled = true;
|
|
$serverTwo->settings->save();
|
|
|
|
app()->bind(SentinelTrafficClient::class, function ($app, $params) {
|
|
return new FailingDashboardTrafficClient($params['server']);
|
|
});
|
|
|
|
loadLazy(Livewire::test(TrafficAnalytics::class))
|
|
->assertOk()
|
|
->assertDontSee('Traffic analytics')
|
|
->assertDontSee('No analytics data yet')
|
|
->assertDontSee('Unique visitors')
|
|
->assertDontSee('Error rate');
|
|
});
|
|
|
|
it('renders nothing when no server in the team has traffic analytics enabled', function () {
|
|
$server = Server::factory()->create([
|
|
'team_id' => $this->team->id,
|
|
'private_key_id' => $this->privateKey->id,
|
|
]);
|
|
// New servers default analytics on; this scenario is the all-disabled team.
|
|
$server->settings->is_traffic_analytics_enabled = false;
|
|
$server->settings->save();
|
|
|
|
loadLazy(Livewire::test(TrafficAnalytics::class))
|
|
->assertOk()
|
|
->assertDontSee('Unique visitors')
|
|
->assertDontSee('Traffic analytics');
|
|
});
|