Deploy Ladill Link / deploy (push) Successful in 32s
Record parsed user-agent and geo data on clicks, then surface breakdowns and richer recent-click context on per-link and account analytics views. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.0 KiB
PHP
97 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\LinkClick;
|
|
use App\Models\ShortLink;
|
|
use App\Models\User;
|
|
use App\Services\Link\LinkAnalyticsService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Str;
|
|
use Tests\TestCase;
|
|
|
|
class LinkAnalyticsTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private function user(): User
|
|
{
|
|
return User::create([
|
|
'public_id' => (string) Str::uuid(),
|
|
'name' => 'Test',
|
|
'email' => 'test+'.uniqid().'@example.com',
|
|
]);
|
|
}
|
|
|
|
public function test_redirect_records_device_browser_os_and_country(): void
|
|
{
|
|
$user = $this->user();
|
|
ShortLink::create([
|
|
'user_id' => $user->id,
|
|
'slug' => 'tracked',
|
|
'source_app' => 'link',
|
|
'source_kind' => 'redirect',
|
|
'is_managed_here' => true,
|
|
'destination_url' => 'https://example.com/target',
|
|
'is_active' => true,
|
|
]);
|
|
|
|
$this->withHeaders([
|
|
'User-Agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
|
|
'CF-IPCountry' => 'GH',
|
|
])->get('https://ladl.link/tracked')
|
|
->assertRedirect('https://example.com/target');
|
|
|
|
$click = LinkClick::first();
|
|
$this->assertNotNull($click);
|
|
$this->assertSame('mobile', $click->device_type);
|
|
$this->assertSame('Safari', $click->browser);
|
|
$this->assertSame('iOS', $click->os);
|
|
$this->assertSame('GH', $click->country);
|
|
}
|
|
|
|
public function test_breakdown_for_link_groups_clicks_by_device(): void
|
|
{
|
|
$user = $this->user();
|
|
$link = ShortLink::create([
|
|
'user_id' => $user->id,
|
|
'slug' => 'breakdown',
|
|
'source_app' => 'link',
|
|
'source_kind' => 'redirect',
|
|
'is_managed_here' => true,
|
|
'destination_url' => 'https://example.com',
|
|
'is_active' => true,
|
|
'clicks_total' => 2,
|
|
'unique_clicks_total' => 2,
|
|
]);
|
|
|
|
LinkClick::create([
|
|
'short_link_id' => $link->id,
|
|
'ip_hash' => 'a',
|
|
'device_type' => 'mobile',
|
|
'browser' => 'Chrome',
|
|
'os' => 'Android',
|
|
'country' => 'GH',
|
|
'is_unique' => true,
|
|
'clicked_at' => now(),
|
|
]);
|
|
LinkClick::create([
|
|
'short_link_id' => $link->id,
|
|
'ip_hash' => 'b',
|
|
'device_type' => 'desktop',
|
|
'browser' => 'Chrome',
|
|
'os' => 'Windows',
|
|
'country' => 'US',
|
|
'is_unique' => true,
|
|
'clicked_at' => now(),
|
|
]);
|
|
|
|
$devices = app(LinkAnalyticsService::class)->breakdownForLink($link, 'device_type');
|
|
|
|
$this->assertCount(2, $devices);
|
|
$labels = array_column($devices, 'label');
|
|
$this->assertContains('Mobile', $labels);
|
|
$this->assertContains('Desktop', $labels);
|
|
}
|
|
}
|