feat(ticketing): resolve validity in tenant timezone
This commit is contained in:
90
tests/Unit/Ticket/TenantTimezoneValidityTest.php
Normal file
90
tests/Unit/Ticket/TenantTimezoneValidityTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Ticket;
|
||||
|
||||
use App\Domains\Commerce\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Commerce\Catalog\Models\Variant;
|
||||
use App\Domains\Core\Tenant\Models\Tenant;
|
||||
use App\Domains\Ticketing\Event\Models\EventDate;
|
||||
use App\Domains\Ticketing\Ticket\Enums\ValidityTimeType;
|
||||
use App\Domains\Ticketing\Ticket\Models\ValidityTime;
|
||||
use App\Domains\Ticketing\Ticket\Resources\ValidityTimeResource;
|
||||
use App\Domains\Ticketing\Ticket\Services\ResolvedValidityGroup;
|
||||
use App\Domains\Ticketing\Ticket\Services\TicketValidityResolver;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TenantTimezoneValidityTest extends TestCase
|
||||
{
|
||||
public function test_recurring_windows_use_local_day_and_exclusive_end(): void
|
||||
{
|
||||
$window = new ValidityTime(['type' => ValidityTimeType::TimeWindow, 'start_time' => '22:00', 'end_time' => '02:00']);
|
||||
$group = new ResolvedValidityGroup(collect([$window]), 'America/Argentina/Buenos_Aires');
|
||||
foreach (['2026-09-22 01:00' => true, '2026-09-22 04:59' => true, '2026-09-22 05:00' => false, '2026-09-22 18:00' => false] as $time => $expected) {
|
||||
$at = CarbonImmutable::parse($time, 'UTC');
|
||||
$this->assertSame($expected, $group->isValid($at), $time);
|
||||
$this->assertSame($expected, $window->isValid($at, 'America/Argentina/Buenos_Aires'), $time);
|
||||
}
|
||||
$this->assertFalse((new ResolvedValidityGroup(collect([$window]), 'Asia/Tokyo'))->isValid(CarbonImmutable::parse('2026-09-22 01:00', 'UTC')));
|
||||
}
|
||||
|
||||
public function test_event_anchor_uses_local_date_when_utc_date_is_next_day(): void
|
||||
{
|
||||
$fixed = new ValidityTime(['type' => ValidityTimeType::FixedWindow,
|
||||
'fixed_starts_at' => '2026-09-22 01:00', 'fixed_expires_at' => '2026-09-22 06:00']);
|
||||
$window = new ValidityTime(['type' => ValidityTimeType::TimeWindow, 'start_time' => '22:00', 'end_time' => '02:00']);
|
||||
$group = new ResolvedValidityGroup(collect([$fixed, $window]), 'America/Argentina/Buenos_Aires');
|
||||
$this->assertTrue($group->isValid(CarbonImmutable::parse('2026-09-22 04:00', 'UTC')));
|
||||
$this->assertFalse($group->isValid(CarbonImmutable::parse('2026-09-23 04:00', 'UTC')));
|
||||
$this->assertSame('2026-09-22 01:00', $group->effectiveStartsAt()->utc()->format('Y-m-d H:i'));
|
||||
$this->assertSame('2026-09-22 05:00', $group->effectiveExpiresAt()->utc()->format('Y-m-d H:i'));
|
||||
}
|
||||
|
||||
public function test_local_window_compares_with_utc_now_in_resource(): void
|
||||
{
|
||||
$this->travelTo(CarbonImmutable::parse('2026-09-21 22:00', 'UTC'));
|
||||
$window = new ValidityTime(['type' => ValidityTimeType::TimeWindow, 'start_time' => '18:00', 'end_time' => '20:00']);
|
||||
$resource = ValidityTimeResource::make($window, 'America/Argentina/Buenos_Aires');
|
||||
$this->assertTrue($resource->resolve()['is_valid']);
|
||||
$this->assertFalse($window->isValid(now(), 'Asia/Tokyo'));
|
||||
$this->travelBack();
|
||||
}
|
||||
|
||||
public function test_daylight_saving_uses_date_specific_offset(): void
|
||||
{
|
||||
$window = new ValidityTime(['type' => ValidityTimeType::TimeWindow, 'start_time' => '18:00', 'end_time' => '20:00']);
|
||||
$this->assertSame('2026-01-21 23:00', $window->startsAt(CarbonImmutable::parse('2026-01-21 12:00', 'UTC'), 'America/New_York')->utc()->format('Y-m-d H:i'));
|
||||
$this->assertSame('2026-07-21 22:00', $window->startsAt(CarbonImmutable::parse('2026-07-21 12:00', 'UTC'), 'America/New_York')->utc()->format('Y-m-d H:i'));
|
||||
}
|
||||
|
||||
public function test_resolver_passes_tenant_timezone_to_groups(): void
|
||||
{
|
||||
$tenant = new Tenant(['timezone' => 'Asia/Tokyo']);
|
||||
$item = new CatalogItem;
|
||||
$item->setRelation('tenant', $tenant);
|
||||
$date = new EventDate;
|
||||
$date->setRelation('validityTime', new ValidityTime([
|
||||
'type' => ValidityTimeType::FixedWindow,
|
||||
'fixed_starts_at' => '2026-09-21 13:00',
|
||||
'fixed_expires_at' => '2026-09-21 17:00',
|
||||
]));
|
||||
$variant = new Variant;
|
||||
$variant->setRelation('catalogItem', $item);
|
||||
$variant->setRelation('eventDates', new Collection([$date]));
|
||||
$variant->setRelation('eventDate', null);
|
||||
$variant->setRelation('definitions', new Collection);
|
||||
$resolved = (new TicketValidityResolver)->resolveVariant($variant);
|
||||
$this->assertSame('Asia/Tokyo', $resolved->groups->first()->timezone);
|
||||
}
|
||||
|
||||
public function test_event_hours_are_local_and_end_can_be_next_day(): void
|
||||
{
|
||||
$date = new EventDate(['date' => '2026-09-21', 'time_start' => '22:00', 'time_end' => '02:00']);
|
||||
$date->setRelation('tenant', new Tenant(['timezone' => 'America/Argentina/Buenos_Aires']));
|
||||
$this->assertSame('2026-09-22 01:00', $date->startsAt()->utc()->format('Y-m-d H:i'));
|
||||
$this->assertSame('2026-09-22 05:00', $date->endsAt()->utc()->format('Y-m-d H:i'));
|
||||
$date->setRelation('tenant', new Tenant(['timezone' => 'Asia/Tokyo']));
|
||||
$this->assertSame('2026-09-21 13:00', $date->startsAt()->utc()->format('Y-m-d H:i'));
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ use App\Domains\Commerce\Catalog\Models\ItemAttribute;
|
||||
use App\Domains\Commerce\Catalog\Models\Variant;
|
||||
use App\Domains\Commerce\Catalog\Models\VariantDefinition;
|
||||
use App\Domains\Ticketing\Event\Models\EventDate;
|
||||
use App\Shared\Enums\FieldType;
|
||||
use App\Domains\Ticketing\Ticket\Enums\ValidityTimeType;
|
||||
use App\Domains\Ticketing\Ticket\Models\ValidityTime;
|
||||
use App\Domains\Ticketing\Ticket\Services\TicketValidityResolver;
|
||||
use App\Shared\Enums\FieldType;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Tests\TestCase;
|
||||
@@ -200,6 +200,7 @@ class TicketValidityResolverTest extends TestCase
|
||||
private function variant(EloquentCollection $eventDates, EloquentCollection $definitions): Variant
|
||||
{
|
||||
$variant = new Variant;
|
||||
$variant->setRelation('catalogItem', null);
|
||||
$variant->setRelation('eventDates', $eventDates);
|
||||
$variant->setRelation('eventDate', null);
|
||||
$variant->setRelation('definitions', $definitions);
|
||||
|
||||
Reference in New Issue
Block a user