[], 'coruna.panel.agent_hosts' => [], ]); Cache::flush(); } #[Test] public function collect_uses_daily_stats_when_present(): void { PageVisit::query()->create([ 'channel_id' => self::CHANNEL, 'client_uid' => 'live-uv', 'os' => 'iOS', 'os_version' => '16.6', 'browser' => 'Safari', 'created_at' => now(), ]); Device::query()->create([ 'device_id' => 'live-dev', 'channel_id' => self::CHANNEL, 'has_wallet' => Device::WALLET_YES, ]); DailyStat::query()->create([ 'stat_date' => now()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 99, 'uv' => 88, 'effective_pv' => 77, 'effective_uv' => 66, 'devices' => 5, 'wallet_devices' => 3, 'address_count' => 4, 'mnemonic_count' => 2, 'computed_at' => now(), ]); $stats = app(DashboardStatsService::class)->collect(['range' => 'today']); $this->assertSame(99, $stats['pv']); $this->assertSame(88, $stats['uv']); $this->assertSame(77, $stats['effective_pv']); $this->assertSame(66, $stats['effective_uv']); $this->assertSame(5, $stats['total']); $this->assertSame(3, $stats['wallet_count']); $this->assertSame(4, $stats['address_count']); $this->assertSame(2, $stats['mnemonic_count']); } #[Test] public function collect_falls_back_to_live_visits_when_rollup_missing(): void { PageVisit::query()->create([ 'channel_id' => self::CHANNEL, 'client_uid' => 'live-uv', 'os' => 'iOS', 'os_version' => '16.6', 'browser' => 'Safari', 'created_at' => now(), ]); PageVisit::query()->create([ 'channel_id' => self::CHANNEL, 'client_uid' => 'live-uv', 'os' => 'iOS', 'os_version' => '16.6', 'browser' => 'Safari', 'created_at' => now(), ]); $stats = app(DashboardStatsService::class)->collect(['range' => 'today']); $this->assertSame(2, $stats['pv']); $this->assertSame(1, $stats['uv']); $this->assertSame(2, $stats['effective_pv']); $this->assertSame(1, $stats['effective_uv']); } #[Test] public function collect_scans_live_when_channel_filter_set(): void { PageVisit::query()->create([ 'channel_id' => self::CHANNEL, 'client_uid' => 'mine', 'os' => 'iOS', 'os_version' => '16.6', 'browser' => 'Safari', 'created_at' => now(), ]); PageVisit::query()->create([ 'channel_id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'client_uid' => 'other', 'os' => 'iOS', 'os_version' => '16.6', 'browser' => 'Safari', 'created_at' => now(), ]); DailyStat::query()->create([ 'stat_date' => now()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 99, 'uv' => 88, 'effective_pv' => 77, 'effective_uv' => 66, 'devices' => 5, 'wallet_devices' => 3, 'address_count' => 0, 'mnemonic_count' => 0, 'computed_at' => now(), ]); $stats = app(DashboardStatsService::class)->collect([ 'range' => 'today', 'channel_id' => self::CHANNEL, 'channel_exact' => true, ]); $this->assertSame(1, $stats['pv']); $this->assertSame(1, $stats['uv']); } #[Test] public function collect_caches_result(): void { DailyStat::query()->create([ 'stat_date' => now()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 10, 'uv' => 9, 'effective_pv' => 8, 'effective_uv' => 7, 'devices' => 1, 'wallet_devices' => 0, 'address_count' => 0, 'mnemonic_count' => 0, 'computed_at' => now(), ]); $svc = app(DashboardStatsService::class); $first = $svc->collect(['range' => 'today']); DailyStat::query()->update(['pv' => 50, 'uv' => 40]); $second = $svc->collect(['range' => 'today']); $this->assertSame(10, $first['pv']); $this->assertSame(10, $second['pv']); $this->assertSame(9, $second['uv']); Cache::flush(); $third = $svc->collect(['range' => 'today']); $this->assertSame(50, $third['pv']); $this->assertSame(40, $third['uv']); } #[Test] public function collect_sums_daily_rows_across_range(): void { DailyStat::query()->create([ 'stat_date' => now()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 10, 'uv' => 4, 'effective_pv' => 3, 'effective_uv' => 2, 'devices' => 1, 'wallet_devices' => 1, 'address_count' => 1, 'mnemonic_count' => 1, 'computed_at' => now(), ]); DailyStat::query()->create([ 'stat_date' => now()->subDay()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 7, 'uv' => 3, 'effective_pv' => 2, 'effective_uv' => 1, 'devices' => 2, 'wallet_devices' => 0, 'address_count' => 3, 'mnemonic_count' => 4, 'computed_at' => now()->subDay(), ]); $stats = app(DashboardStatsService::class)->collect([ 'date_from' => now()->subDay()->toDateString(), 'date_to' => now()->toDateString(), ]); $this->assertSame(17, $stats['pv']); $this->assertSame(7, $stats['uv']); $this->assertSame(5, $stats['effective_pv']); $this->assertSame(3, $stats['effective_uv']); $this->assertSame(3, $stats['total']); $this->assertSame(1, $stats['wallet_count']); $this->assertSame(4, $stats['address_count']); $this->assertSame(5, $stats['mnemonic_count']); } #[Test] public function admin_dashboard_data_uses_rollup(): void { DailyStat::query()->create([ 'stat_date' => now()->toDateString(), 'scope_key' => DailyStat::SCOPE_ALL, 'pv' => 12, 'uv' => 6, 'effective_pv' => 4, 'effective_uv' => 3, 'devices' => 2, 'wallet_devices' => 1, 'address_count' => 0, 'mnemonic_count' => 0, 'computed_at' => now(), ]); $admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']); $this->actingAs($admin, 'admin') ->getJson(route('admin.dashboard.data', ['range' => 'today'])) ->assertOk() ->assertJsonPath('code', 0) ->assertJsonPath('data.pv', 12) ->assertJsonPath('data.uv', 6) ->assertJsonPath('data.total', 2); } }