Add tests for ticket validity and event date formatting

- Create TicketValiditySchemaTest to verify database schema for ticket validity.
- Update CatalogModelsTest to include tests for event date attributes and selection options.
- Introduce EventDateTextFormatterTest for formatting event dates in Spanish.
- Refactor EventModelsTest to include validity time relationships.
- Add SaleDetailResourceTest to ensure correct serialization of purchase items.
- Enhance TicketTest with validity time checks and status management.
- Implement ValidityTimeResourceTest to validate resource output for different validity types.
- Add ValidityTimeTest to verify casting and validity checks for validity time types.
This commit is contained in:
2026-08-11 12:41:35 -03:00
parent b294e5c46e
commit 02cf3f3773
166 changed files with 10203 additions and 1849 deletions

View File

@@ -4,8 +4,6 @@ namespace Tests\Feature\Seeders;
use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Enums\CatalogItemType;
use App\Domains\Catalog\Enums\EventProductType;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\ProductLayout;
@@ -13,10 +11,8 @@ use App\Domains\Catalog\Models\Attribute;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Catalog\Models\FeaturedGroup;
use App\Domains\Catalog\Models\Inventory;
use App\Domains\Event\Models\Event;
use App\Domains\Event\Models\EventDate;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Enums\TicketGenerationPolicy;
use Database\Seeders\AttributeSeeder;
use Database\Seeders\FiestaFutbolInfantilProductSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
@@ -26,21 +22,10 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
{
use RefreshDatabase;
public function test_it_seeds_event_items_for_the_new_catalog(): void
public function test_it_seeds_the_configurable_catalog_with_its_categories(): void
{
$headerLogo = Attachment::query()->create([
'path' => 'tests/header.png',
'filename' => 'header.png',
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
]);
$footerLogo = Attachment::query()->create([
'path' => 'tests/footer.png',
'filename' => 'footer.png',
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
]);
$headerLogo = $this->attachment('header');
$footerLogo = $this->attachment('footer');
$tenant = Tenant::query()->create([
'codigo' => 'fiesta_futbol_infantil',
'nombre' => 'Fiesta Fútbol Infantil',
@@ -55,127 +40,17 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
'footer_logo_id' => $footerLogo->id,
]);
$this->seed([
AttributeSeeder::class,
FiestaFutbolInfantilProductSeeder::class,
]);
$this->seed([
AttributeSeeder::class,
FiestaFutbolInfantilProductSeeder::class,
]);
$this->seed([AttributeSeeder::class, FiestaFutbolInfantilProductSeeder::class]);
$this->seed([AttributeSeeder::class, FiestaFutbolInfantilProductSeeder::class]);
$this->assertFalse(Attribute::query()
->where('tenant_codigo', $tenant->codigo)
->exists());
$this->assertSame('9, 10, 11 y 12 de Octubre 2026', $tenant->fresh()->event_date_text);
$event = Event::query()
->where('tenant_code', $tenant->codigo)
->with('dates')
->sole();
$this->assertSame($event->id, $tenant->fresh()->active_event_id);
$this->assertCount(4, $event->dates);
$this->assertSame(1, Event::query()->where('tenant_code', $tenant->codigo)->count());
$this->assertSame(4, EventDate::query()->where('event_id', $event->id)->count());
$generalAdmission = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('slug', 'entrada-general')
->with('variants.eventDate', 'itemAttributes')
->sole();
$this->assertNull($generalAdmission->inventory_id);
$this->assertTrue($generalAdmission->event->is($event));
$this->assertSame(EventProductType::Entry, $generalAdmission->event_product_type);
$this->assertCount(0, $generalAdmission->itemAttributes);
$this->assertCount(4, $generalAdmission->variants);
$this->assertEqualsCanonicalizing(
['2026-10-09', '2026-10-10', '2026-10-11', '2026-10-12'],
$generalAdmission->variants
->map(fn ($variant) => $variant->eventDate->date->format('Y-m-d'))
->all()
$this->assertSame(
['color', 'event_date', 'horario', 'servicio', 'talle', 'tipo_alojamiento'],
Attribute::query()->where('tenant_codigo', $tenant->codigo)->orderBy('codigo')->pluck('codigo')->all(),
);
$this->assertSame(
[
['2026-10-09 00:00:00', '2026-10-09 23:59:59'],
['2026-10-10 00:00:00', '2026-10-10 23:59:59'],
['2026-10-11 00:00:00', '2026-10-11 23:59:59'],
['2026-10-12 00:00:00', '2026-10-12 23:59:59'],
],
$generalAdmission->variants
->sortBy(fn ($variant) => $variant->eventDate->date)
->map(fn ($variant): array => [
$variant->getMinimumUseDate()->format('Y-m-d H:i:s'),
$variant->getMaximumUseDate()->format('Y-m-d H:i:s'),
])
->values()
->all()
);
$standardItems = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('type', CatalogItemType::Standard->value)
->get();
$this->assertCount(7, $standardItems);
foreach ($standardItems as $standardItem) {
$this->assertSame($event->id, $standardItem->event_id);
$this->assertSame(
'2026-10-09 00:00:00',
$standardItem->minimum_use_date->format('Y-m-d H:i:s'),
);
$this->assertSame(
'2026-10-12 23:59:59',
$standardItem->maximum_use_date->format('Y-m-d H:i:s'),
);
}
$allDaysItem = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('nombre', 'Entrada General - Todos los días')
->with('bundleComponents.variant.eventDate')
->sole();
$this->assertSame(CatalogItemType::Bundle, $allDaysItem->type);
$this->assertSame('40000.00', $allDaysItem->precio);
$this->assertNull($allDaysItem->inventory_id);
$this->assertFalse($allDaysItem->has_tickets);
$this->assertSame($event->id, $allDaysItem->event_id);
$this->assertSame(EventProductType::Entry, $allDaysItem->event_product_type);
$this->assertCount(4, $allDaysItem->bundleComponents);
$this->assertEqualsCanonicalizing(
['2026-10-09', '2026-10-10', '2026-10-11', '2026-10-12'],
$allDaysItem->bundleComponents
->map(fn ($component) => $component->variant->eventDate->date->format('Y-m-d'))
->all()
);
$foodCombo = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('nombre', 'Combo 2 Panchos + 2 Hamburguesas')
->with('bundleComponents.catalogItem')
->sole();
$this->assertSame(CatalogItemType::Bundle, $foodCombo->type);
$this->assertSame('24000.00', $foodCombo->precio);
$this->assertNull($foodCombo->inventory_id);
$this->assertSame(EventProductType::Product, $foodCombo->event_product_type);
$this->assertSame(
[
'hamburguesa-papa-frita' => 2,
'pancho' => 2,
],
$foodCombo->bundleComponents
->mapWithKeys(fn ($component): array => [
$component->catalogItem->slug => $component->quantity,
])
->sortKeys()
->all()
);
$this->assertSame(9, CatalogItem::query()->where('tenant_code', $tenant->codigo)->count());
$this->assertSame(10, Inventory::query()->count());
$this->assertSame(
['Bebidas', 'Comidas', 'Entradas', 'Estacionamiento', 'Gastronomía'],
['Alojamientos', 'Comidas', 'Entradas', 'Merchandising'],
Category::query()
->where('tenant_code', $tenant->codigo)
->orderBy('nombre')
@@ -183,53 +58,100 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
->all(),
);
$this->assertSame(
'Estacionamiento',
['abono', 'alojamiento', 'camiseta', 'comida'],
CatalogItem::query()->where('tenant_code', $tenant->codigo)->orderBy('slug')->pluck('slug')->all(),
);
$this->assertTrue(
CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('slug', 'estacionamiento-auto')
->with('category')
->sole()
->category
->nombre,
->get()
->every(fn (CatalogItem $item): bool => $item->has_tickets),
);
$this->assertTrue(
CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->get()
->every(fn (CatalogItem $item): bool => $item->ticket_generation_policy === TicketGenerationPolicy::OnePerUnit),
);
$featuredGroups = FeaturedGroup::query()
$expectedVariantCounts = [
'camiseta' => 12,
'alojamiento' => 2,
'comida' => 24,
'abono' => 1,
];
foreach ($expectedVariantCounts as $slug => $count) {
$item = CatalogItem::query()->where('tenant_code', $tenant->codigo)->where('slug', $slug)->sole();
$this->assertCount($count, $item->variants);
}
$variantStocks = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->with('category.catalogItems')
->orderBy('group_order')
->get();
->with('variants.inventory')
->get()
->flatMap(fn (CatalogItem $item) => $item->variants)
->map(fn ($variant): int => $variant->inventory->real_stock);
$this->assertGreaterThan($variantStocks->count() / 2, $variantStocks->filter(fn (int $stock): bool => $stock > 5)->count());
$this->assertNotEmpty($variantStocks->filter(fn (int $stock): bool => $stock === 0));
$this->assertNotEmpty($variantStocks->filter(fn (int $stock): bool => $stock >= 1 && $stock <= 5));
$this->assertSame(
[
'Entradas' => ['entrada-general', 'entrada-general-todos-los-dias'],
'Estacionamiento' => ['estacionamiento-auto', 'estacionamiento-moto'],
'Comidas' => ['hamburguesa-papa-frita', 'pancho', 'combo-2-panchos-2-hamburguesas'],
'Bebidas' => ['coca-cola-500ml', 'agua-mineral-1l'],
'abono' => 'Entradas',
'alojamiento' => 'Alojamientos',
'camiseta' => 'Merchandising',
'comida' => 'Comidas',
],
$featuredGroups
->mapWithKeys(fn (FeaturedGroup $group): array => [
$group->group_name => $group->category->catalogItems->pluck('slug')->all(),
])
->all()
CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->with('category')
->orderBy('slug')
->get()
->mapWithKeys(fn (CatalogItem $item): array => [$item->slug => $item->category?->nombre])
->all(),
);
$this->assertSame(
[
['Entradas', FeaturedGroupSource::Category, 'Entradas', ProductLayout::Row, GroupLayout::SimpleVertical, 0],
['Estacionamiento', FeaturedGroupSource::Category, 'Estacionamiento', ProductLayout::ColumnWithCart, GroupLayout::Simple, 1],
['Comidas', FeaturedGroupSource::Category, 'Comidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 2],
['Bebidas', FeaturedGroupSource::Category, 'Bebidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 3],
],
$featuredGroups
->map(fn (FeaturedGroup $group): array => [
$group->group_name,
$group->source_type,
$group->category->nombre,
$group->product_layout,
$group->group_layout,
$group->group_order,
])
->all()
$abono = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('slug', 'abono')
->with('itemAttributes.attribute', 'variants.eventDates')
->sole();
$dateAttribute = $abono->itemAttributes->firstWhere('attribute.codigo', 'event_date');
$this->assertTrue($dateAttribute->allow_multi_select);
$this->assertEqualsCanonicalizing(
[4],
$abono->variants->map(fn ($variant): int => $variant->eventDates->count())->all(),
);
$food = CatalogItem::query()
->where('tenant_code', $tenant->codigo)
->where('slug', 'comida')
->with('variants')
->sole();
$this->assertSame('4000.00', $food->precio);
$this->assertCount(24, $food->variants->pluck('descripcion')->unique());
$this->assertEqualsCanonicalizing(
['4000.00', '8000.00', '10000.00'],
$food->variants->pluck('precio')->unique()->values()->all(),
);
$this->assertTrue($food->variants->every(
fn ($variant): bool => $variant->descripcion !== null && $variant->precio !== null
));
$featuredGroup = FeaturedGroup::query()->where('tenant_code', $tenant->codigo)->sole();
$this->assertSame(FeaturedGroupSource::All, $featuredGroup->source_type);
$this->assertSame(ProductLayout::Row, $featuredGroup->product_layout);
$this->assertSame(GroupLayout::SimpleVertical, $featuredGroup->group_layout);
$this->assertNull($featuredGroup->category_id);
}
private function attachment(string $name): Attachment
{
return Attachment::query()->create([
'path' => "tests/{$name}.png",
'filename' => "{$name}.png",
'type' => AttachmentType::Image,
'mime_type' => 'image/png',
]);
}
}

View File

@@ -20,10 +20,12 @@ class MenuSeederTest extends TestCase
public function test_it_seeds_the_admin_menus(): void
{
$tenant = $this->createTenant('admin_tenant');
$fiestaTenant = $this->createTenant('fiesta_futbol_infantil');
$this->seed(MenuSeeder::class);
$expectedMenus = [
'adminapp.inicio' => ['Inicio', '/admin/inicio'],
'adminapp.catalog' => ['Catálogo', '/admin/catalog'],
'adminapp.categories' => ['Categorías', '/admin/categories'],
'adminapp.combos' => ['Combos', '/admin/combos'],
@@ -31,6 +33,12 @@ class MenuSeederTest extends TestCase
'adminapp.staff' => ['Staff', '/admin/staff'],
'adminapp.ventas' => ['Ventas', '/admin/ventas'],
];
$fiestaCategoryMenus = [
'adminapp.fiesta-futbol-infantil.entradas' => ['Entradas', '/admin/entradas'],
'adminapp.fiesta-futbol-infantil.alojamientos' => ['Alojamientos', '/admin/alojamientos'],
'adminapp.fiesta-futbol-infantil.merchandising' => ['Merchandising', '/admin/merchandising'],
'adminapp.fiesta-futbol-infantil.comida' => ['Comida', '/admin/comidas'],
];
$adminApp = Menu::query()
->with('children')
@@ -41,7 +49,7 @@ class MenuSeederTest extends TestCase
$this->assertSame(Menu::CONTENT_TYPE_DYNAMIC, $adminApp->content_type);
$this->assertSame('/', $adminApp->route);
$this->assertSame(
array_keys($expectedMenus),
array_keys([...$expectedMenus, ...$fiestaCategoryMenus]),
$adminApp->children->pluck('code')->sort()->values()->all()
);
$this->assertTrue(
@@ -64,6 +72,27 @@ class MenuSeederTest extends TestCase
);
}
foreach ($fiestaCategoryMenus as $code => [$label, $route]) {
$menu = Menu::query()->where('code', $code)->firstOrFail();
$this->assertSame($label, $menu->label);
$this->assertSame($route, $menu->route);
$this->assertSame('main.adminapp', $menu->parent_menu_code);
$this->assertFalse($tenant->menues()->where('menues.code', $code)->exists());
$this->assertTrue($fiestaTenant->menues()->where('menues.code', $code)->exists());
}
foreach ([
'adminapp.inicio',
'adminapp.catalog',
'adminapp.categories',
'adminapp.combos',
] as $code) {
$this->assertFalse(
$fiestaTenant->menues()->where('menues.code', $code)->exists()
);
}
$this->assertFalse(
Menu::query()->whereIn('code', [
'admin.event',