From 936a2566c686577eaac0e8b1410cd4877de1fc60 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 9 Sep 2026 14:28:15 +0200 Subject: [PATCH] fix(analytics): hide traffic UI when disabled and skip default-on (#11700) --- app/Livewire/Analytics.php | 30 +++++++++- .../Project/Application/Analytics.php | 11 +++- app/Livewire/Server/Proxy.php | 1 - .../Server/TrafficAnalyticsSettings.php | 2 + app/Models/ServerSetting.php | 9 --- .../livewire/analytics-placeholder.blade.php | 2 + resources/views/livewire/analytics.blade.php | 12 ++-- resources/views/livewire/dashboard.blade.php | 5 +- .../traffic-analytics-placeholder.blade.php | 20 +------ .../dashboard/traffic-analytics.blade.php | 26 +++------ .../project/application/analytics.blade.php | 2 +- .../application/configuration.blade.php | 3 +- .../project/application/general.blade.php | 3 - .../livewire/project/shared/metrics.blade.php | 6 +- .../livewire/server/analytics/show.blade.php | 3 +- .../views/livewire/server/proxy.blade.php | 6 ++ .../traffic-analytics-settings.blade.php | 39 +++++++++++-- .../Feature/ApplicationGeneralLayoutTest.php | 6 ++ .../Feature/MetricsDisabledEmptyStateTest.php | 11 ++++ .../ProxyConfigurationLoadingStateTest.php | 18 ++++++ .../ApplicationAnalyticsTest.php | 43 +++++++++++++- .../DashboardTrafficAnalyticsTest.php | 40 +++++++++++-- .../ServerAnalyticsPageTest.php | 58 +++++++++++++++++++ .../ServerSettingTrafficTest.php | 16 ++--- .../ToggleTrafficAnalyticsTest.php | 24 ++++++++ 25 files changed, 309 insertions(+), 87 deletions(-) create mode 100644 tests/Feature/MetricsDisabledEmptyStateTest.php diff --git a/app/Livewire/Analytics.php b/app/Livewire/Analytics.php index 24ba69d2d4..abf9d88cfd 100644 --- a/app/Livewire/Analytics.php +++ b/app/Livewire/Analytics.php @@ -11,6 +11,7 @@ use Illuminate\Contracts\View\View; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Livewire\Attributes\Lazy; +use Livewire\Attributes\On; use Livewire\Attributes\Url; use Livewire\Component; @@ -178,6 +179,23 @@ class Analytics extends Component $this->live = ! $this->live; } + #[On('trafficAnalyticsStateChanged')] + public function refreshTrafficAnalyticsState(): void + { + if ($this->scopedServerUuid === null) { + return; + } + + $server = Server::ownedByCurrentTeam()->whereUuid($this->scopedServerUuid)->firstOrFail(); + $this->overview = null; + $this->servers = $server->isTrafficAnalyticsEnabled() ? collect([$server]) : collect(); + + if ($this->servers->isNotEmpty()) { + $this->refreshAppOptions(); + $this->loadData(); + } + } + public function isLivePollable(): bool { return $this->live && $this->range === '24h'; @@ -564,10 +582,18 @@ class Analytics extends Component return [$from->toIso8601ZuluString(), $to->toIso8601ZuluString()]; } - public function placeholder(): View + public function placeholder(array $params = []): View { + $scopedServerUuid = $params['scopedServerUuid'] ?? null; + $hideSkeleton = false; + + if (is_string($scopedServerUuid)) { + $server = Server::ownedByCurrentTeamCached()->firstWhere('uuid', $scopedServerUuid); + $hideSkeleton = $server !== null && ! $server->isTrafficAnalyticsEnabled(); + } + // Rendered instantly; the Sentinel round-trips run in the deferred lazy-load request. - return view('livewire.analytics-placeholder'); + return view('livewire.analytics-placeholder', compact('hideSkeleton')); } public function render() diff --git a/app/Livewire/Project/Application/Analytics.php b/app/Livewire/Project/Application/Analytics.php index 3db21ab400..0c5e30b737 100644 --- a/app/Livewire/Project/Application/Analytics.php +++ b/app/Livewire/Project/Application/Analytics.php @@ -221,8 +221,17 @@ class Analytics extends Component return [$from->toIso8601ZuluString(), $to->toIso8601ZuluString()]; } - public function placeholder(): View + public function placeholder(array $params = []): View { + $application = $params['application'] ?? null; + + if ($application instanceof Application && ! $application->destination?->server?->isTrafficAnalyticsEnabled()) { + $this->application = $application; + $this->enabled = false; + + return view('livewire.project.application.analytics'); + } + // Rendered instantly; the Sentinel round-trip runs in the deferred lazy-load request. return view('livewire.project.application.analytics-placeholder'); } diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index 296fd4da5d..0454d97049 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -56,7 +56,6 @@ class Proxy extends Component $this->redirectEnabled = data_get($this->server, 'proxy.redirect_enabled', true); $this->redirectUrl = data_get($this->server, 'proxy.redirect_url'); $this->syncData(false); - $this->loadProxyConfiguration(); $this->clearAppliedTraefikBranchWarning(); } diff --git a/app/Livewire/Server/TrafficAnalyticsSettings.php b/app/Livewire/Server/TrafficAnalyticsSettings.php index 48022d9aed..c6d96df488 100644 --- a/app/Livewire/Server/TrafficAnalyticsSettings.php +++ b/app/Livewire/Server/TrafficAnalyticsSettings.php @@ -3,6 +3,7 @@ namespace App\Livewire\Server; use App\Actions\Server\ConfigureTrafficAnalytics; +use App\Livewire\Analytics; use App\Models\Server; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\View\View; @@ -83,6 +84,7 @@ class TrafficAnalyticsSettings extends Component ConfigureTrafficAnalytics::run($this->server, $enable); $this->server->refresh(); $this->isTrafficAnalyticsEnabled = $this->server->isTrafficAnalyticsEnabled(); + $this->dispatch('trafficAnalyticsStateChanged')->to(Analytics::class); $this->dispatch('success', $enable ? 'Traffic analytics enabled. Restarting proxy and Sentinel.' : 'Traffic analytics disabled. Restarting proxy and Sentinel.'); diff --git a/app/Models/ServerSetting.php b/app/Models/ServerSetting.php index 58f28ba32d..512247b771 100644 --- a/app/Models/ServerSetting.php +++ b/app/Models/ServerSetting.php @@ -170,15 +170,6 @@ class ServerSetting extends Model { static::creating(function ($setting) { try { - // Enable traffic analytics by default for eligible servers, unless the - // caller explicitly set a value. Swarm and build servers are ineligible, - // mirroring the toggle guard so the flag never contradicts capability. - // Runs before sentinel generation, which may throw and be swallowed below. - if (! $setting->isDirty('is_traffic_analytics_enabled')) { - $isSwarm = $setting->is_swarm_manager || $setting->is_swarm_worker; - $isBuild = (bool) $setting->is_build_server; - $setting->is_traffic_analytics_enabled = ! $isSwarm && ! $isBuild; - } if (str($setting->sentinel_token)->isEmpty()) { $setting->generateSentinelToken(save: false, ignoreEvent: true); } diff --git a/resources/views/livewire/analytics-placeholder.blade.php b/resources/views/livewire/analytics-placeholder.blade.php index cb6007b95b..767f0f46ac 100644 --- a/resources/views/livewire/analytics-placeholder.blade.php +++ b/resources/views/livewire/analytics-placeholder.blade.php @@ -1,4 +1,5 @@
+ @if (! ($hideSkeleton ?? false)) {{-- Header (real chrome; only the data below is a skeleton) --}}
@if (empty($scopedServerUuid ?? null)) @@ -54,4 +55,5 @@ + @endif
diff --git a/resources/views/livewire/analytics.blade.php b/resources/views/livewire/analytics.blade.php index e816d1c2a0..9b6fd3643b 100644 --- a/resources/views/livewire/analytics.blade.php +++ b/resources/views/livewire/analytics.blade.php @@ -123,17 +123,17 @@ $appListboxOptions = array_merge( @endif @if ($servers->isEmpty()) - - @if ($scopedServerUuid === null) + @if ($scopedServerUuid === null) + View servers - @endif - + + @endif @elseif (! $overview) sortBy('name', SORT_NATURAL)->take($dashboardItemLimit); $dashboardServers = $servers->sortBy('name', SORT_NATURAL)->take($dashboardItemLimit); + $hasTrafficAnalytics = $servers->contains(fn ($server) => $server->isTrafficAnalyticsEnabled()); @endphp
- + @if ($hasTrafficAnalytics) + + @endif
- {{-- Real section header; only the KPI grid below is a skeleton. --}} -
-
-

- Traffic analytics -

-

- Team-wide request volume across servers with traffic analytics enabled -

-
-
- - -
-
- - -
+
diff --git a/resources/views/livewire/dashboard/traffic-analytics.blade.php b/resources/views/livewire/dashboard/traffic-analytics.blade.php index e707689ffc..3cf7ec4b5c 100644 --- a/resources/views/livewire/dashboard/traffic-analytics.blade.php +++ b/resources/views/livewire/dashboard/traffic-analytics.blade.php @@ -7,6 +7,8 @@ $approxBadge = fn (string $tooltip) => ' +@if ($servers->isNotEmpty() && $overview)
- @if ($servers->isEmpty()) - - - - View servers - - - - @elseif (! $overview) - - @else - {{-- Sparkline KPI cards. Each links through to the full analytics page. --}} + {{-- Sparkline KPI cards. Each links through to the full analytics page. --}}
- @endif +@endif + diff --git a/resources/views/livewire/project/application/analytics.blade.php b/resources/views/livewire/project/application/analytics.blade.php index 1255343c8e..5a0fa32a87 100644 --- a/resources/views/livewire/project/application/analytics.blade.php +++ b/resources/views/livewire/project/application/analytics.blade.php @@ -18,7 +18,7 @@ $analyticsServerUuid = $application->destination?->server?->uuid; - Server settings + Server analytics diff --git a/resources/views/livewire/project/application/configuration.blade.php b/resources/views/livewire/project/application/configuration.blade.php index 3d6add96b5..cc3bcd8027 100644 --- a/resources/views/livewire/project/application/configuration.blade.php +++ b/resources/views/livewire/project/application/configuration.blade.php @@ -46,7 +46,8 @@ @elseif ($currentRoute === 'project.application.metrics') @elseif ($currentRoute === 'project.application.analytics') - + @elseif ($currentRoute === 'project.application.tags') @elseif ($currentRoute === 'project.application.danger') diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index e882c518d5..1150b8d998 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -25,9 +25,6 @@ - -
$buildPack !== 'dockercompose', diff --git a/resources/views/livewire/project/shared/metrics.blade.php b/resources/views/livewire/project/shared/metrics.blade.php index 62417d42cc..f166334236 100644 --- a/resources/views/livewire/project/shared/metrics.blade.php +++ b/resources/views/livewire/project/shared/metrics.blade.php @@ -24,9 +24,9 @@ - - Enable Sentinel and metrics for this server before collecting application usage data. - + @elseif (!str($resource->status)->contains('running')) @endcan - + diff --git a/resources/views/livewire/server/proxy.blade.php b/resources/views/livewire/server/proxy.blade.php index e561f412fe..1d4033ea1a 100644 --- a/resources/views/livewire/server/proxy.blade.php +++ b/resources/views/livewire/server/proxy.blade.php @@ -90,6 +90,7 @@ @if ($server->proxyType() === ProxyTypes::TRAEFIK->value || $server->proxyType() === 'CADDY') @can('update', $server) @@ -128,6 +129,11 @@ @endif @endif +
+ +
+ @if ($proxySettings)
diff --git a/resources/views/livewire/server/traffic-analytics-settings.blade.php b/resources/views/livewire/server/traffic-analytics-settings.blade.php index 49cbca4495..8031654046 100644 --- a/resources/views/livewire/server/traffic-analytics-settings.blade.php +++ b/resources/views/livewire/server/traffic-analytics-settings.blade.php @@ -8,10 +8,22 @@ - - {{ $isTrafficAnalyticsEnabled ? 'Disable' : 'Enable' }} traffic analytics - + @if ($isTrafficAnalyticsEnabled) +
+ + +
+ @endif
@if ($isTrafficAnalyticsEnabled) @@ -45,7 +57,24 @@ @else + icon-name="dashboard"> + +
+ + +
+
+
@endif
diff --git a/tests/Feature/ApplicationGeneralLayoutTest.php b/tests/Feature/ApplicationGeneralLayoutTest.php index 41f62022af..ceff52b3e7 100644 --- a/tests/Feature/ApplicationGeneralLayoutTest.php +++ b/tests/Feature/ApplicationGeneralLayoutTest.php @@ -21,6 +21,12 @@ test('compose file loading waits for the user to confirm the file location', fun ->not->toContain('x-init="$wire.dispatch(\'loadCompose\', true)"'); }); +test('traffic analytics is only shown on the dedicated analytics page', function () { + $view = file_get_contents(resource_path('views/livewire/project/application/general.blade.php')); + + expect($view)->not->toContain('toContain('toContain('description="Enable Sentinel and metrics for this server before collecting application usage data."') + ->toContain('icon-name="dashboard"') + ->not->toContain(''); +}); diff --git a/tests/Feature/ProxyConfigurationLoadingStateTest.php b/tests/Feature/ProxyConfigurationLoadingStateTest.php index 112f68d8cc..f5779e0ac5 100644 --- a/tests/Feature/ProxyConfigurationLoadingStateTest.php +++ b/tests/Feature/ProxyConfigurationLoadingStateTest.php @@ -10,3 +10,21 @@ it('disables proxy configuration controls and covers the editor while saving', f ->toContain('Updating proxy configuration') ->toContain('aria-live="polite"'); }); + +it('loads only the compose file from the frontend and shows the shared loading indicator', function () { + $page = file_get_contents(resource_path('views/livewire/server/proxy/show.blade.php')); + $proxy = file_get_contents(resource_path('views/livewire/server/proxy.blade.php')); + $component = file_get_contents(app_path('Livewire/Server/Proxy.php')); + + expect($page) + ->toContain('') + ->not->toContain(''); + + expect($proxy) + ->toContain('x-init="$wire.loadProxyConfiguration()"') + ->toContain('wire:loading.flex wire:target="loadProxyConfiguration"') + ->toContain(''); + + expect($component) + ->not->toContain('$this->loadProxyConfiguration();'); +}); diff --git a/tests/Feature/TrafficAnalytics/ApplicationAnalyticsTest.php b/tests/Feature/TrafficAnalytics/ApplicationAnalyticsTest.php index ec7f9b2037..1c551c8b21 100644 --- a/tests/Feature/TrafficAnalytics/ApplicationAnalyticsTest.php +++ b/tests/Feature/TrafficAnalytics/ApplicationAnalyticsTest.php @@ -3,6 +3,7 @@ use App\Livewire\Project\Application\Analytics; use App\Models\Application; use App\Models\Environment; +use App\Models\InstanceSettings; use App\Models\PrivateKey; use App\Models\Project; use App\Models\Server; @@ -82,6 +83,7 @@ beforeEach(function () { // Server (from a prior enabled test) can leak into a later test and be treated as // analytics-enabled, mounting the component against an unreachable server. Server::flushIdentityMap(); + InstanceSettings::forceCreate(['id' => 0]); $this->team = Team::factory()->create(); $this->user = User::factory()->create(); @@ -114,6 +116,35 @@ function makeAnalyticsApplication(Team $team, PrivateKey $privateKey, Environmen ]); } +it('only lazy loads application analytics when traffic analytics is enabled', function () { + $configuration = file_get_contents(resource_path('views/livewire/project/application/configuration.blade.php')); + + expect($configuration) + ->toContain(':lazy="$application->destination?->server?->isTrafficAnalyticsEnabled()"'); +}); + +it('renders the disabled state in the initial application analytics page response', function () { + $application = makeAnalyticsApplication($this->team, $this->privateKey, $this->environment, false); + + $this->get(route('project.application.analytics', [ + 'project_uuid' => $this->project->uuid, + 'environment_uuid' => $this->environment->uuid, + 'application_uuid' => $application->uuid, + ])) + ->assertOk() + ->assertSee('Traffic analytics is not enabled') + ->assertDontSee('__lazyLoad', escape: false) + ->assertDontSee('analytics-range-section'); +}); + +it('guards the lazy placeholder when traffic analytics is disabled', function () { + $application = makeAnalyticsApplication($this->team, $this->privateKey, $this->environment, false); + + Livewire::test(Analytics::class, ['application' => $application, 'lazy' => true]) + ->assertSee('Traffic analytics is not enabled') + ->assertDontSee('analytics-range-section'); +}); + it('renders KPIs from a mocked traffic client when analytics is enabled', function () { $application = makeAnalyticsApplication($this->team, $this->privateKey, $this->environment, true); @@ -189,9 +220,13 @@ it('falls back to the donut for the per-app chart when the series endpoint is ab it('shows an empty state when traffic analytics is disabled for the server', function () { $application = makeAnalyticsApplication($this->team, $this->privateKey, $this->environment, false); - loadLazy(Livewire::test(Analytics::class, ['application' => $application])) + Livewire::test(Analytics::class, ['application' => $application, 'lazy' => false]) ->assertOk() ->assertSee('Analytics') + ->assertSee('Traffic analytics is not enabled') + ->assertSee('Server analytics') + ->assertSeeHtml(route('server.analytics', ['server_uuid' => $application->destination->server->uuid])) + ->assertDontSee('__lazyLoad', escape: false) ->assertDontSee('Unique visitors'); }); @@ -204,8 +239,10 @@ it('renders the disabled empty-state without crashing when the application has n expect($application->destination)->toBeNull(); - loadLazy(Livewire::test(Analytics::class, ['application' => $application])) + Livewire::test(Analytics::class, ['application' => $application, 'lazy' => false]) ->assertOk() ->assertSee('Analytics') - ->assertDontSee('Server settings'); + ->assertSee('Traffic analytics is not enabled') + ->assertDontSee('__lazyLoad', escape: false) + ->assertDontSee('Server analytics'); }); diff --git a/tests/Feature/TrafficAnalytics/DashboardTrafficAnalyticsTest.php b/tests/Feature/TrafficAnalytics/DashboardTrafficAnalyticsTest.php index 58a701f6dc..76a3c5b7ed 100644 --- a/tests/Feature/TrafficAnalytics/DashboardTrafficAnalyticsTest.php +++ b/tests/Feature/TrafficAnalytics/DashboardTrafficAnalyticsTest.php @@ -1,5 +1,6 @@ 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, @@ -150,6 +164,14 @@ it('shows loading states while the dashboard range refreshes', function () { ->toContain('aria-label="Loading analytics"'); }); +it('styles the open analytics link as a dashboard action button', function () { + $view = file_get_contents(resource_path('views/livewire/dashboard/traffic-analytics.blade.php')); + + expect($view) + ->toContain('class="group inline-flex h-7 shrink-0 items-center gap-1.5 rounded-md border border-neutral-200 bg-white px-2.5') + ->toContain('group-hover:translate-x-0.5'); +}); + it('uses the dashboard surface treatment for the analytics KPI group', function () { $view = file_get_contents(resource_path('views/livewire/dashboard/traffic-analytics.blade.php')); @@ -162,7 +184,7 @@ it('uses the dashboard surface treatment for the analytics KPI group', function ->not->toContain('dark:bg-base dark:hover:bg-white/[0.03]'); }); -it('shows a failure empty-state instead of an all-zero KPI panel when every server fetch fails', function () { +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, @@ -183,12 +205,14 @@ it('shows a failure empty-state instead of an all-zero KPI panel when every serv loadLazy(Livewire::test(TrafficAnalytics::class)) ->assertOk() - ->assertSee('No analytics data yet') + ->assertSeeHtml('class="contents"') + ->assertDontSee('Traffic analytics') + ->assertDontSee('No analytics data yet') ->assertDontSee('Unique visitors') ->assertDontSee('Error rate'); }); -it('shows an empty state when no server in the team has traffic analytics enabled', function () { +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, @@ -200,5 +224,13 @@ it('shows an empty state when no server in the team has traffic analytics enable loadLazy(Livewire::test(TrafficAnalytics::class)) ->assertOk() ->assertDontSee('Unique visitors') - ->assertSee('not enabled'); + ->assertDontSee('Traffic analytics'); +}); + +it('uses an empty lazy placeholder so analytics only appears after data loads', function () { + $view = file_get_contents(resource_path('views/livewire/dashboard/traffic-analytics-placeholder.blade.php')); + + expect($view) + ->toContain('class="contents"') + ->not->toContain('Traffic analytics'); }); diff --git a/tests/Feature/TrafficAnalytics/ServerAnalyticsPageTest.php b/tests/Feature/TrafficAnalytics/ServerAnalyticsPageTest.php index 1f74a6e59a..cdf0eb4ab4 100644 --- a/tests/Feature/TrafficAnalytics/ServerAnalyticsPageTest.php +++ b/tests/Feature/TrafficAnalytics/ServerAnalyticsPageTest.php @@ -3,6 +3,7 @@ use App\Livewire\Analytics; use App\Livewire\Server\Analytics\Show; use App\Livewire\Server\TrafficAnalyticsSettings; +use App\Models\InstanceSettings; use App\Models\Server; use App\Models\User; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -13,6 +14,7 @@ use Livewire\Livewire; uses(RefreshDatabase::class); beforeEach(function () { + InstanceSettings::forceCreate(['id' => 0]); $this->user = User::factory()->create(); $this->team = $this->user->teams()->first(); $this->actingAs($this->user); @@ -60,6 +62,20 @@ it('moves traffic analytics configuration out of sentinel and onto analytics', f ->not->toContain('id="trafficTopn"'); }); +it('matches the server metrics empty state when traffic analytics is disabled', function () { + $view = file_get_contents(resource_path('views/livewire/server/traffic-analytics-settings.blade.php')); + $disabledState = str($view) + ->after('@else') + ->before('@endif') + ->toString(); + + expect($disabledState) + ->toContain('title="Traffic analytics is disabled"') + ->toContain('') + ->toContain('isHighlightedButton') + ->toContain('buttonTitle="Enable traffic analytics"'); +}); + it('renders traffic analytics settings above the server analytics dashboard', function () { $view = file_get_contents(resource_path('views/livewire/server/analytics/show.blade.php')); @@ -67,6 +83,13 @@ it('renders traffic analytics settings above the server analytics dashboard', fu ->toBeLessThan(strpos($view, 'toContain(':lazy="$server->isTrafficAnalyticsEnabled()"'); +}); + it('matches other server pages without a visible page title', function () { $view = file_get_contents(resource_path('views/livewire/server/analytics/show.blade.php')); @@ -88,6 +111,41 @@ it('scopes the server analytics page to its route server', function () { ->assertDontSee($otherServer->name); }); +it('does not duplicate the disabled state on a scoped server analytics dashboard', function () { + $server = Server::factory()->create(['team_id' => $this->team->id]); + $server->settings->is_traffic_analytics_enabled = false; + $server->settings->save(); + + Livewire::test(Analytics::class, ['scopedServerUuid' => $server->uuid]) + ->assertDontSee('Traffic analytics is not enabled'); +}); + +it('removes stale analytics content when traffic analytics is disabled', function () { + $server = Server::factory()->create(['team_id' => $this->team->id]); + $server->settings->is_traffic_analytics_enabled = true; + $server->settings->save(); + + $component = Livewire::test(Analytics::class, ['scopedServerUuid' => $server->uuid]); + + $server->settings->is_traffic_analytics_enabled = false; + $server->settings->save(); + + $component + ->dispatch('trafficAnalyticsStateChanged') + ->assertSet('servers', fn ($servers) => $servers->isEmpty()) + ->assertDontSee('No analytics data yet'); +}); + +it('does not render a skeleton placeholder for a disabled scoped server', function () { + $server = Server::factory()->create(['team_id' => $this->team->id]); + $server->settings->is_traffic_analytics_enabled = false; + $server->settings->save(); + + Livewire::test(Analytics::class, ['scopedServerUuid' => $server->uuid, 'lazy' => true]) + ->assertDontSee('analytics-overview-section') + ->assertDontSee('analytics-requests-section'); +}); + it('saves traffic analytics settings from the server analytics page', function () { Queue::fake(); diff --git a/tests/Feature/TrafficAnalytics/ServerSettingTrafficTest.php b/tests/Feature/TrafficAnalytics/ServerSettingTrafficTest.php index 98710c688f..3f7d7d0b7a 100644 --- a/tests/Feature/TrafficAnalytics/ServerSettingTrafficTest.php +++ b/tests/Feature/TrafficAnalytics/ServerSettingTrafficTest.php @@ -14,14 +14,14 @@ beforeEach(function () { $this->team = $user->teams()->first(); }); -it('defaults traffic analytics to enabled for a normal server and exposes a server helper', function () { +it('defaults traffic analytics to disabled for a normal server and exposes a server helper', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); - expect($server->settings->is_traffic_analytics_enabled)->toBeTrue(); - expect($server->isTrafficAnalyticsEnabled())->toBeTrue(); + expect($server->settings->is_traffic_analytics_enabled)->toBeFalse(); + expect($server->isTrafficAnalyticsEnabled())->toBeFalse(); - $server->settings->is_traffic_analytics_enabled = false; + $server->settings->is_traffic_analytics_enabled = true; $server->settings->save(); - expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); + expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeTrue(); }); it('defaults traffic analytics to disabled for a swarm server', function () { @@ -44,14 +44,14 @@ it('defaults traffic analytics to disabled for a build server', function () { expect($setting->is_traffic_analytics_enabled)->toBeFalse(); }); -it('respects an explicit traffic analytics value on creation', function () { +it('respects an explicit enabled traffic analytics value on creation', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); $setting = ServerSetting::create([ 'server_id' => $server->id, - 'is_traffic_analytics_enabled' => false, + 'is_traffic_analytics_enabled' => true, ]); - expect($setting->is_traffic_analytics_enabled)->toBeFalse(); + expect($setting->is_traffic_analytics_enabled)->toBeTrue(); }); it('defaults traffic collection and geoip settings to sentinel values', function () { diff --git a/tests/Feature/TrafficAnalytics/ToggleTrafficAnalyticsTest.php b/tests/Feature/TrafficAnalytics/ToggleTrafficAnalyticsTest.php index d1a75ba0ff..63864aada1 100644 --- a/tests/Feature/TrafficAnalytics/ToggleTrafficAnalyticsTest.php +++ b/tests/Feature/TrafficAnalytics/ToggleTrafficAnalyticsTest.php @@ -1,7 +1,9 @@ 0]); $this->user = User::factory()->create(); $this->team = $this->user->teams()->first(); $this->actingAs($this->user); @@ -32,11 +35,32 @@ it('toggles traffic analytics via the sentinel settings component', function () Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->call('toggleTrafficAnalytics') + ->assertDispatchedTo(Analytics::class, 'trafficAnalyticsStateChanged') ->assertHasNoErrors(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeTrue(); }); +it('warns about the application interruption before enabling traffic analytics', function () { + $server = Server::factory()->create(['team_id' => $this->team->id]); + $server->settings->is_traffic_analytics_enabled = false; + $server->settings->save(); + + Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) + ->assertSee('Enable traffic analytics?') + ->assertDontSeeHtml('wire:confirm') + ->assertSeeHtml('wire:loading.flex') + ->assertSeeHtml('wire:target="toggleTrafficAnalytics"') + ->assertSee('Restarting Sentinel and proxy...') + ->assertSee('Enabling traffic analytics will restart Sentinel and the proxy. Your applications will experience a brief interruption.'); +}); + +it('allows the analytics toggle modal to update after the state changes', function () { + $view = file_get_contents(resource_path('views/livewire/server/traffic-analytics-settings.blade.php')); + + expect($view)->toContain(':ignoreWire="false"'); +}); + it('does not enable traffic analytics on a swarm server', function () { ConfigureTrafficAnalytics::partialMock()->shouldReceive('handle')->never();