0]); $this->user = User::factory()->create(); $this->team = $this->user->teams()->first(); $this->actingAs($this->user); session(['currentTeam' => $this->team]); }); it('toggles traffic analytics via the sentinel settings component', function () { ConfigureTrafficAnalytics::partialMock()->shouldReceive('handle')->once()->andReturnUsing(function ($server, $enable) { $server->settings->is_traffic_analytics_enabled = $enable; $server->settings->save(); return true; }); $server = Server::factory()->create(['team_id' => $this->team->id]); $server->proxy->set('type', 'TRAEFIK'); $server->save(); // New servers default analytics on; start from the disabled state to exercise enabling. $server->settings->is_traffic_analytics_enabled = false; $server->settings->save(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); 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->proxy->set('type', 'TRAEFIK'); $server->save(); $server->settings->is_traffic_analytics_enabled = false; $server->settings->save(); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->assertSee('Enable traffic analytics?') ->assertSeeHtml('wire:target="toggleTrafficAnalytics"') ->assertSee('Enabling traffic analytics will restart Sentinel and the proxy. Your applications will experience a brief interruption.'); }); it('does not enable traffic analytics on a swarm server', function () { ConfigureTrafficAnalytics::partialMock()->shouldReceive('handle')->never(); $server = Server::factory()->create(['team_id' => $this->team->id]); $server->proxy->set('type', 'TRAEFIK'); $server->save(); $server->settings->is_swarm_manager = true; $server->settings->is_traffic_analytics_enabled = false; $server->settings->save(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->call('toggleTrafficAnalytics') ->assertDispatched('error', 'Traffic analytics is not supported on Swarm/Build servers.') ->assertHasNoErrors(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); }); it('saves traffic analytics settings from the sentinel form', function () { Queue::fake(); $server = Server::factory()->create(['team_id' => $this->team->id]); $server->settings->is_traffic_analytics_enabled = true; $server->settings->save(); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->set('trafficTopn', 100) ->set('trafficSampleThreshold', 500) ->set('trafficRetention1hDays', 14) ->set('trafficRetention1dDays', 180) ->set('isGeoipEnabled', false) ->set('geoipRefreshDays', 7) ->call('saveTrafficAnalyticsSettings') ->assertHasNoErrors(); $settings = $server->settings->fresh(); expect($settings->traffic_topn)->toBe(100) ->and($settings->traffic_sample_threshold)->toBe(500) ->and($settings->traffic_retention_1h_days)->toBe(14) ->and($settings->traffic_retention_1d_days)->toBe(180) ->and($settings->is_geoip_enabled)->toBeFalse() ->and($settings->geoip_refresh_days)->toBe(7); }); it('saves the client IP mode from the sentinel form', function () { Queue::fake(); $server = Server::factory()->create(['team_id' => $this->team->id]); $server->settings->is_traffic_analytics_enabled = true; $server->settings->save(); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->assertSet('trafficIpMode', 'full') ->assertSee('Client IP addresses') ->set('trafficIpMode', 'anonymized') ->call('saveTrafficAnalyticsSettings') ->assertHasNoErrors(); expect($server->settings->fresh()->traffic_ip_mode)->toBe(TrafficIpMode::Anonymized); }); it('rejects an unknown client IP mode', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->set('trafficIpMode', 'partial') ->call('saveTrafficAnalyticsSettings') ->assertHasErrors(['trafficIpMode']); expect($server->settings->fresh()->traffic_ip_mode)->toBe(TrafficIpMode::Full); }); it('does not let a team member change the client IP mode', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); $server->settings->is_traffic_analytics_enabled = true; $server->settings->save(); $component = Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]); $member = User::factory()->create(); $this->team->members()->attach($member->id, ['role' => 'member']); $this->actingAs($member); $component->set('trafficIpMode', 'off') ->call('saveTrafficAnalyticsSettings'); expect($server->settings->fresh()->traffic_ip_mode)->toBe(TrafficIpMode::Full); }); it('rejects a zero top-n cap', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->set('trafficTopn', 0) ->call('saveTrafficAnalyticsSettings') ->assertHasErrors(['trafficTopn']); }); it('does not enable traffic analytics on a build server', function () { ConfigureTrafficAnalytics::partialMock()->shouldReceive('handle')->never(); $server = Server::factory()->create(['team_id' => $this->team->id]); $server->proxy->set('type', 'TRAEFIK'); $server->save(); $server->settings->server_role = ServerRole::BUILD; $server->settings->is_traffic_analytics_enabled = false; $server->settings->save(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->call('toggleTrafficAnalytics') ->assertDispatched('error', 'Traffic analytics is not supported on Swarm/Build servers.') ->assertHasNoErrors(); expect($server->fresh()->isTrafficAnalyticsEnabled())->toBeFalse(); }); it('disables the analytics toggle and explains why when the server has no traefik or caddy proxy', function () { $server = Server::factory()->create(['team_id' => $this->team->id]); $server->proxy->set('type', 'NONE'); $server->save(); $server->settings->is_traffic_analytics_enabled = false; $server->settings->save(); $html = Livewire::test(TrafficAnalyticsSettings::class, ['server' => $server]) ->assertSee('Traffic analytics needs the Traefik or Caddy proxy.') ->assertDontSee('Enable traffic analytics?') ->assertDontSeeHtml('submitAction') ->html(); expect($html)->toMatch('/