Files
ladill-events/tests/Feature/CustomDomainTest.php
T
isaaccladandClaude Opus 4.8 75bb72abb3
Deploy Ladill Events / deploy (push) Successful in 39s
Fix custom-domain test fixtures (public_id, bypass platform.session)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 17:06:27 +00:00

109 lines
3.7 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\CustomDomain;
use App\Models\QrCode;
use App\Models\User;
use App\Services\CustomDomain\CustomDomainService;
use App\Services\CustomDomain\DnsResolver;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
class CustomDomainTest extends TestCase
{
use RefreshDatabase;
private string $serverIp = '161.97.138.149';
protected function setUp(): void
{
parent::setUp();
config([
'customdomain.enabled' => true,
'customdomain.server_ip' => $this->serverIp,
'customdomain.ssl_api_url' => 'https://domains.ladill.com/api',
'customdomain.ssl_api_key' => 'events-ssl-key',
'customdomain.callback_secret' => 'shared-secret',
]);
}
private function event(?User $owner = null): QrCode
{
$owner ??= User::factory()->create(['public_id' => 'usr_'.uniqid()]);
return QrCode::create([
'user_id' => $owner->id,
'short_code' => 'sc'.uniqid(),
'type' => QrCode::TYPE_CHURCH,
'label' => 'My Event',
'is_active' => true,
]);
}
private function fakeDns(array $ips): void
{
$this->app->bind(DnsResolver::class, fn () => new class($ips) extends DnsResolver {
public function __construct(private array $ips) {}
public function aRecords(string $host): array { return $this->ips; }
});
}
public function test_verify_requests_certificate_when_dns_points_to_app(): void
{
Http::fake(['*/ssl/certificates' => Http::response(['status' => 'pending'], 202)]);
$this->fakeDns([$this->serverIp]);
$service = app(CustomDomainService::class);
$domain = $service->attach($this->event(), 'myevent.com', true);
[$ok] = $service->verifyAndProvision($domain->fresh());
$this->assertTrue($ok);
$this->assertNotNull($domain->fresh()->dns_verified_at);
Http::assertSent(fn ($r) => str_contains($r->url(), '/ssl/certificates') && $r['host'] === 'myevent.com');
}
public function test_verify_fails_when_dns_not_pointing(): void
{
$this->fakeDns(['1.2.3.4']);
$service = app(CustomDomainService::class);
$domain = $service->attach($this->event(), 'myevent.com', true);
[$ok, $msg] = $service->verifyAndProvision($domain->fresh());
$this->assertFalse($ok);
$this->assertStringContainsString('DNS', $msg);
}
public function test_signed_callback_marks_domain_live_and_resolves(): void
{
$event = $this->event();
app(CustomDomainService::class)->attach($event, 'myevent.com', true);
$payload = json_encode(['event' => 'ssl.active', 'data' => [
'host' => 'myevent.com', 'status' => 'active', 'expires_at' => now()->addDays(89)->toIso8601String(),
]], JSON_UNESCAPED_SLASHES);
$sig = hash_hmac('sha256', $payload, 'shared-secret');
$this->call('POST', '/api/ssl-callback', [], [], [], [
'HTTP_X-Ladill-Signature' => $sig, 'CONTENT_TYPE' => 'application/json',
], $payload)->assertOk();
$resolved = app(CustomDomainService::class)->resolveStorefront('www.myevent.com');
$this->assertSame($event->id, $resolved?->id);
}
public function test_store_requires_event_ownership(): void
{
$event = $this->event();
$intruder = User::factory()->create(['public_id' => 'usr_'.uniqid()]);
$this->withoutMiddleware(\App\Http\Middleware\EnsurePlatformSession::class);
$this->actingAs($intruder)
->post(route('events.custom-domain.store', $event), ['host' => 'myevent.com'])
->assertForbidden();
}
}