createTenant('admin_tenant'); $this->seed(MenuSeeder::class); $expectedMenus = [ 'admin.catalog' => ['Catálogo', '/admin/catalog'], 'admin.categories' => ['Categorías', '/admin/categories'], 'admin.combos' => ['Combos', '/admin/combos'], 'admin.event' => ['Eventos', '/admin/event'], 'admin.staff' => ['Staff', '/admin/staff'], 'admin.ventas' => ['Ventas', '/admin/ventas'], ]; $adminMenus = Menu::query() ->whereIn('code', array_keys($expectedMenus)) ->get() ->keyBy('code'); $this->assertCount(count($expectedMenus), $adminMenus); foreach ($expectedMenus as $code => [$label, $route]) { $this->assertSame($label, $adminMenus->get($code)?->label); $this->assertSame($route, $adminMenus->get($code)?->route); $this->assertTrue( $tenant->menues()->where('menues.code', $code)->exists() ); } } public function test_it_assigns_menus_to_the_expected_roles(): void { $this->seed(AuthorizationSeeder::class); $this->seed(MenuSeeder::class); $allMenuCodes = Menu::query() ->orderBy('code') ->pluck('code') ->all(); $userMenuCodes = Menu::query() ->where('code', 'not like', 'admin.%') ->orderBy('code') ->pluck('code') ->all(); foreach ([RoleCode::Admin->value, RoleCode::AdminApp->value] as $roleCode) { $roleMenuCodes = Role::query() ->where('codigo', $roleCode) ->firstOrFail() ->menus() ->orderBy('menues.code') ->pluck('menues.code') ->all(); $this->assertSame($allMenuCodes, $roleMenuCodes); } $userRoleMenuCodes = Role::query() ->where('codigo', RoleCode::User->value) ->firstOrFail() ->menus() ->orderBy('menues.code') ->pluck('menues.code') ->all(); $this->assertSame($userMenuCodes, $userRoleMenuCodes); $this->assertDatabaseCount( 'roles_menues', (count($allMenuCodes) * 2) + count($userMenuCodes) ); } public function test_it_seeds_the_account_menu_hierarchy(): void { $tenant = $this->createTenant('account_tenant'); $this->seed(MenuSeeder::class); $account = Menu::query() ->with('children') ->where('code', 'account') ->firstOrFail(); $this->assertSame(Menu::CONTENT_TYPE_DYNAMIC, $account->content_type); $this->assertSame('Mi cuenta', $account->label); $this->assertSame('/mi-cuenta', $account->route); $this->assertSame([ 'account.profile', 'account.purchases', 'account.tickets', ], $account->children->pluck('code')->sort()->values()->all()); $this->assertSame([ 'account.profile' => '/mi-cuenta/datos-personales', 'account.purchases' => '/mi-cuenta/compras', 'account.tickets' => '/mi-cuenta/tickets', ], $account->children->pluck('route', 'code')->sortKeys()->all()); $this->assertTrue( $tenant->menues()->where('menues.code', 'account')->exists() ); $this->assertFalse( Menu::query()->whereIn('code', ['profile', 'purchases', 'tickets'])->exists() ); } public function test_it_seeds_the_help_menu_hierarchy_and_content_schemas(): void { $this->seed(MenuSeeder::class); $help = Menu::query() ->with('children') ->where('code', 'help') ->firstOrFail(); $this->assertSame(Menu::CONTENT_TYPE_DYNAMIC, $help->content_type); $this->assertSame('Ayuda', $help->label); $this->assertSame([ 'help.contact', 'help.faq', 'help.payment-methods', 'help.shipping', 'help.terms-and-conditions', ], $help->children->pluck('code')->sort()->values()->all()); $faq = Menu::query()->where('code', 'help.faq')->firstOrFail(); $this->assertSame(Menu::CONTENT_TYPE_STATIC, $faq->content_type); $this->assertEquals([ '*.pregunta' => 'required|string', '*.respuesta' => 'required|string', '*.is_active' => 'sometimes|boolean', ], $faq->static_content_schema); $contact = Menu::query()->where('code', 'help.contact')->firstOrFail(); $this->assertSame(Menu::CONTENT_TYPE_STATIC, $contact->content_type); $this->assertSame('required|url', $contact->static_content_schema['whatsapp.whatsapp_url']); $this->assertSame('required|string', $contact->static_content_schema['phone']); $this->assertSame( 'required|array|min:1', $contact->static_content_schema['locations.*.addresses'] ); $this->assertSame( 'required|array|size:2', $contact->static_content_schema['locations.*.addresses.*.coordinates'] ); $this->assertSame( 'required|string', $contact->static_content_schema['locations.*.addresses.*.address'] ); $this->assertSame( 'required|numeric|between:-90,90', $contact->static_content_schema['locations.*.addresses.*.coordinates.0'] ); $this->assertSame('prohibited', $contact->static_content_schema['map_locations']); } public function test_it_assigns_help_to_the_supported_tenants_with_faq_content(): void { $sonder = $this->createTenant('sonder'); $fiesta = $this->createTenant('fiesta_futbol_infantil'); $otherTenant = $this->createTenant('other'); $this->seed(MenuSeeder::class); $expectedQuestions = [ [ 'pregunta' => '¿Hay algún límite de compra?', 'respuesta' => 'No hay un límite general de compra. La cantidad disponible depende del stock de cada producto.', 'is_active' => true, ], [ 'pregunta' => '¿Cuáles son los medios de pago disponibles?', 'respuesta' => 'Podés consultar y seleccionar los medios de pago habilitados al momento de finalizar tu compra.', 'is_active' => false, ], [ 'pregunta' => 'Necesito asesoramiento antes de comprar el producto, ¿cómo puedo hacer?', 'respuesta' => 'Nuestro equipo comercial está preparado para asesorarte, no dudes en escribirnos por WhatsApp al (0341) 6658247 de lunes a viernes de 8.30 a 20 horas. Los sábados, domingos y feriados te contestaremos lo más rápido posible.', 'is_active' => false, ], ]; $expectedContact = [ 'whatsapp' => [ 'whatsapp_url' => 'https://wa.me/543412602222', 'whatsapp_label' => 'Chatea con nosotros', ], 'phone' => '+54 9 (0341) 6658247', 'locations' => [ 'rosario' => [ 'label' => 'Rosario', 'addresses' => [ [ 'label' => 'Gigante de Arroyito', 'address' => 'Av. Génova 640, Rosario', 'coordinates' => [-32.913997, -60.674567], ], [ 'label' => 'Telepagos', 'address' => 'Rioja 1150, piso 12, dpto. 3, Rosario', 'coordinates' => [-32.946820, -60.639320], ], ], ], ], ]; foreach ([$sonder, $fiesta] as $tenant) { $helpMenus = $tenant->menues() ->where(fn ($query) => $query ->where('menues.code', 'help') ->orWhere('menues.parent_menu_code', 'help')) ->get(); $this->assertCount(6, $helpMenus); $this->assertEquals( $expectedQuestions, $helpMenus->firstWhere('code', 'help.faq')->pivot->static_content ); $this->assertEquals( $expectedContact, $helpMenus->firstWhere('code', 'help.contact')->pivot->static_content ); } $this->assertFalse( $otherTenant->menues()->where('menues.code', 'help')->exists() ); } private function createTenant(string $code): Tenant { $headerLogo = $this->createAttachment("{$code}-header.png"); $footerLogo = $this->createAttachment("{$code}-footer.png"); return Tenant::query()->create([ 'codigo' => $code, 'nombre' => $code, 'dominio' => "{$code}.example.com", 'primary_color' => '#111111', 'secondary_color' => '#222222', 'danger_color' => '#333333', 'success_color' => '#444444', 'header_bg_color' => '#ffffff', 'footer_bg_color' => '#ffffff', 'header_logo_id' => $headerLogo->id, 'footer_logo_id' => $footerLogo->id, ]); } private function createAttachment(string $filename): Attachment { return Attachment::query()->create([ 'path' => "test/{$filename}", 'filename' => $filename, 'type' => AttachmentType::Image, 'mime_type' => 'image/png', ]); } }