Fix guest demo UX and enforce guest limits
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-21 21:35:40 +01:00
parent 50cc4e76df
commit 2f9a700e00
28 changed files with 812 additions and 118 deletions

View File

@@ -4,6 +4,7 @@ namespace Tests\Feature;
use App\Enums\PhotoLiveStatus;
use App\Models\Event;
use App\Models\EventJoinTokenEvent;
use App\Models\EventPackage;
use App\Models\GuestPolicySetting;
use App\Models\MediaStorageTarget;
@@ -223,6 +224,44 @@ class GuestJoinTokenFlowTest extends TestCase
->assertJsonPath('demo_read_only', true);
}
public function test_guest_limit_counts_unique_devices(): void
{
$event = $this->createPublishedEvent();
$package = Package::factory()->endcustomer()->create([
'max_guests' => 2,
]);
$eventPackage = EventPackage::create([
'event_id' => $event->id,
'package_id' => $package->id,
'purchased_price' => $package->price,
'purchased_at' => now(),
'used_photos' => 0,
'used_guests' => 0,
'gallery_expires_at' => now()->addDays(7),
]);
$token = $this->tokenService->createToken($event);
$this->withHeader('X-Device-Id', 'device-guest')
->getJson("/api/v1/events/{$token->token}")
->assertOk();
$this->assertSame(1, $eventPackage->refresh()->used_guests);
$this->withHeader('X-Device-Id', 'device-guest')
->getJson("/api/v1/events/{$token->token}")
->assertOk();
$this->assertSame(1, $eventPackage->refresh()->used_guests);
$this->withHeader('X-Device-Id', 'device-guest-2')
->getJson("/api/v1/events/{$token->token}")
->assertOk();
$this->assertSame(2, $eventPackage->refresh()->used_guests);
}
public function test_guest_event_response_includes_live_show_settings(): void
{
$event = $this->createPublishedEvent();
@@ -241,6 +280,44 @@ class GuestJoinTokenFlowTest extends TestCase
->assertJsonPath('live_show.moderation_mode', 'manual');
}
public function test_guest_join_blocks_new_devices_after_grace_limit(): void
{
$event = $this->createPublishedEvent();
$package = Package::factory()->endcustomer()->create([
'max_guests' => 1,
]);
EventPackage::create([
'event_id' => $event->id,
'package_id' => $package->id,
'purchased_price' => $package->price,
'purchased_at' => now(),
'used_photos' => 0,
'used_guests' => 11,
'gallery_expires_at' => now()->addDays(7),
]);
$token = $this->tokenService->createToken($event);
$this->withHeader('X-Device-Id', 'new-device')
->getJson("/api/v1/events/{$token->token}")
->assertStatus(402)
->assertJsonPath('error.code', 'guest_limit_exceeded');
EventJoinTokenEvent::create([
'event_join_token_id' => $token->id,
'event_id' => $event->id,
'tenant_id' => $event->tenant_id,
'event_type' => 'access_granted',
'device_id' => 'known-device',
'occurred_at' => now(),
]);
$this->withHeader('X-Device-Id', 'known-device')
->getJson("/api/v1/events/{$token->token}")
->assertOk();
}
public function test_guest_cannot_upload_photo_with_demo_token(): void
{
Storage::fake('public');

View File

@@ -161,6 +161,36 @@ class PackageLimitEvaluatorTest extends TestCase
$this->assertTrue($summary['can_add_guests']);
}
public function test_guest_limits_apply_grace_buffer_before_blocking(): void
{
Config::set('package-limits.guest_grace', 10);
$package = Package::factory()->endcustomer()->create([
'max_guests' => 5,
]);
$tenant = Tenant::factory()->create();
$event = Event::factory()->for($tenant)->create();
$eventPackage = EventPackage::create([
'event_id' => $event->id,
'package_id' => $package->id,
'purchased_price' => $package->price,
'purchased_at' => now(),
'used_photos' => 0,
'used_guests' => 5,
'gallery_expires_at' => now()->addDays(7),
])->fresh(['package']);
$summary = $this->evaluator->summarizeEventPackage($eventPackage);
$this->assertSame('warning', $summary['guests']['state']);
$eventPackage->update(['used_guests' => 15]);
$summary = $this->evaluator->summarizeEventPackage($eventPackage->fresh(['package']));
$this->assertSame('limit_reached', $summary['guests']['state']);
}
public function test_assess_photo_upload_respects_extra_limits(): void
{
$package = Package::factory()->endcustomer()->create([

View File

@@ -134,14 +134,14 @@ class PackageUsageTrackerTest extends TestCase
'purchased_price' => $package->price,
'purchased_at' => now(),
'used_photos' => 0,
'used_guests' => 2,
'used_guests' => 12,
'gallery_expires_at' => now()->addDays(7),
])->fresh(['package']);
/** @var PackageUsageTracker $tracker */
$tracker = app(PackageUsageTracker::class);
$tracker->recordGuestUsage($eventPackage, 1, 1);
$tracker->recordGuestUsage($eventPackage, 11, 1);
EventFacade::assertDispatched(EventPackageGuestLimitReached::class);
}