Files
ladill-link/tests/Feature/LinkRedirectTest.php
T
isaacclad d45f4b5c58
Deploy Ladill Link / deploy (push) Successful in 1m55s
Make Ladill Link short URLs fully dynamic at click time.
Forward query strings and path suffixes to the live destination, resolve public hosts from config/custom domains instead of hardcoding ladl.link, and keep proxy Location rewrites on the visitor host.
2026-07-16 20:05:43 +00:00

332 lines
12 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\ShortLink;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Tests\TestCase;
class LinkRedirectTest 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_direct_redirect_links_go_to_destination_url(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'direct1',
'source_app' => 'link',
'source_kind' => 'redirect',
'is_managed_here' => true,
'destination_url' => 'https://example.com/target',
'is_active' => true,
]);
$this->get('https://ladl.link/direct1')
->assertRedirect('https://example.com/target');
}
public function test_direct_redirect_forwards_query_string_dynamically(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'promo',
'source_app' => 'link',
'source_kind' => 'redirect',
'is_managed_here' => true,
'destination_url' => 'https://example.com/landing?ref=home',
'is_active' => true,
]);
$this->get('https://ladl.link/promo?utm_source=ig&ref=campaign')
->assertRedirect('https://example.com/landing?ref=campaign&utm_source=ig');
}
public function test_direct_redirect_appends_path_suffix_dynamically(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'docs',
'source_app' => 'link',
'source_kind' => 'redirect',
'is_managed_here' => true,
'destination_url' => 'https://example.com/help',
'is_active' => true,
]);
$this->get('https://ladl.link/docs/getting-started?src=nav')
->assertRedirect('https://example.com/help/getting-started?src=nav');
}
public function test_public_url_uses_config_domain_dynamically(): void
{
config(['link.public_domain' => 'go.example.test']);
$user = $this->user();
$link = ShortLink::create([
'user_id' => $user->id,
'slug' => 'branded',
'source_app' => 'link',
'source_kind' => 'redirect',
'is_managed_here' => true,
'destination_url' => 'https://example.com',
'is_active' => true,
]);
$this->assertSame('https://go.example.test/branded', $link->publicUrl());
$this->assertSame('go.example.test', ShortLink::publicHost());
}
public function test_catalog_qr_links_proxy_to_platform_instead_of_bad_destination(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'qrpage',
'source_app' => 'qrplus',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/qrpage · Link list page',
'is_active' => true,
]);
Http::fake([
'https://ladill.com/q/qrpage' => Http::response('<html>QR page</html>', 200),
]);
$this->get('https://ladl.link/qrpage')
->assertOk()
->assertSee('QR page');
Http::assertSent(function ($request) {
return $request->url() === 'https://ladill.com/q/qrpage'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
}
public function test_transfer_qr_proxies_to_transfer_app_without_redirect_loop(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'mo4o0v1t',
'source_app' => 'transfer',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/mo4o0v1t',
'is_active' => true,
]);
Http::fake([
'https://ladill.com/q/mo4o0v1t' => Http::response('', 302, [
'Location' => 'https://ladl.link/mo4o0v1t/transfer',
]),
'https://transfer.ladill.com/q/mo4o0v1t/transfer' => Http::response('<html>Transfer files</html>', 200),
]);
$this->get('https://ladl.link/mo4o0v1t')
->assertOk()
->assertSee('Transfer files');
Http::assertSent(function ($request) {
return $request->url() === 'https://transfer.ladill.com/q/mo4o0v1t/transfer'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
}
public function test_event_qr_falls_back_to_events_app_when_platform_returns_404(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'sales-webinar',
'source_app' => 'events',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/sales-webinar',
'is_active' => true,
]);
Http::fake([
'https://ladill.com/q/sales-webinar' => Http::response('Not found', 404),
'https://events.ladill.com/q/sales-webinar' => Http::response('<html>Event page</html>', 200),
]);
$this->get('https://ladl.link/sales-webinar')
->assertOk()
->assertSee('Event page');
Http::assertSent(function ($request) {
return $request->url() === 'https://events.ladill.com/q/sales-webinar'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
}
public function test_event_registration_confirmation_proxies_directly_to_events_app(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'sales-webinar',
'source_app' => 'events',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/sales-webinar',
'is_active' => true,
]);
Http::fake([
'https://events.ladill.com/q/sales-webinar/registered/QRE-TESTREF123456' => Http::response('<html>Registration confirmed</html>', 200),
]);
$this->get('https://ladl.link/sales-webinar/registered/QRE-TESTREF123456')
->assertOk()
->assertSee('Registration confirmed');
Http::assertSent(function ($request) {
return $request->url() === 'https://events.ladill.com/q/sales-webinar/registered/QRE-TESTREF123456'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
Http::assertNotSent(function ($request) {
return str_starts_with($request->url(), 'https://ladill.com/q/sales-webinar/registered/');
});
}
public function test_event_registration_post_forwards_json_body_to_events(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'sales-webinar',
'source_app' => 'events',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/sales-webinar',
'is_active' => true,
]);
Http::fake([
'https://events.ladill.com/q/sales-webinar/register' => function ($request) {
$payload = json_decode($request->body(), true);
return Http::response(json_encode([
'paid' => false,
'success_url' => 'https://ladl.link/sales-webinar/registered/QRE-TESTREF123456',
'badge_code' => 'BADGE123',
]), 200, ['Content-Type' => 'application/json']);
},
]);
$this->postJson('https://ladl.link/sales-webinar/register', [
'tier' => 'General Admission',
'attendee_name' => 'Jane Doe',
'attendee_email' => 'jane@example.com',
'attendee_phone' => '+233200000000',
])
->assertOk()
->assertJsonPath('success_url', 'https://ladl.link/sales-webinar/registered/QRE-TESTREF123456');
Http::assertSent(function ($request) {
if ($request->url() !== 'https://events.ladill.com/q/sales-webinar/register') {
return false;
}
$payload = json_decode($request->body(), true);
return is_array($payload)
&& ($payload['attendee_email'] ?? '') === 'jane@example.com'
&& ($payload['tier'] ?? '') === 'General Admission'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
}
public function test_event_registration_post_does_not_require_link_app_csrf_token(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'sales-webinar',
'source_app' => 'events',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/sales-webinar',
'is_active' => true,
]);
Http::fake([
'https://events.ladill.com/q/sales-webinar/register' => Http::response(json_encode([
'paid' => false,
'success_url' => 'https://ladl.link/sales-webinar/registered/QRE-TESTREF123456',
'badge_code' => 'BADGE123',
]), 200, ['Content-Type' => 'application/json']),
]);
$this->postJson('https://ladl.link/sales-webinar/register', [
'tier' => 'General Admission',
'attendee_name' => 'Jane Doe',
'attendee_email' => 'jane@example.com',
'attendee_phone' => '+233200000000',
])
->assertOk()
->assertJsonPath('badge_code', 'BADGE123');
}
public function test_mini_pay_post_does_not_require_link_app_csrf_token(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'shop-pay',
'source_app' => 'mini',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/shop-pay',
'is_active' => true,
]);
Http::fake([
'https://ladill.com/q/shop-pay/pay' => Http::response(json_encode([
'checkout_url' => 'https://ladill.com/pay/momo/REF123',
'provider' => 'mtn_momo',
]), 200, ['Content-Type' => 'application/json']),
]);
$this->postJson('https://ladl.link/shop-pay/pay', [
'amount' => 12.5,
'customer_phone' => '0241234567',
])
->assertOk()
->assertJsonPath('provider', 'mtn_momo')
->assertJsonPath('checkout_url', 'https://ladill.com/pay/momo/REF123');
Http::assertSent(function ($request) {
if ($request->url() !== 'https://ladill.com/q/shop-pay/pay') {
return false;
}
$payload = json_decode($request->body(), true);
return is_array($payload)
&& (float) ($payload['amount'] ?? 0) === 12.5
&& ($payload['customer_phone'] ?? '') === '0241234567'
&& $request->hasHeader('X-Ladill-Internal', '1');
});
}
}