import { signal } from '@angular/core'; import { TestBed, getTestBed } from '@angular/core/testing'; import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; import { of } from 'rxjs'; import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; import { ModalService } from '../../../../core/services/modal.service'; import { Tenant } from '../../../../core/services/tenant.interface'; import { TenantService } from '../../../../core/services/tenant.service'; import { ToastService } from '../../../../core/services/toast.service'; import { ReutilizablesTestPageComponent } from './reutilizables-test-page.component'; const tenant: Tenant = { id: 1, codigo: 'test', nombre: 'Test Tenant', dominio: 'localhost', primary_color: '#6376F3', secondary_color: '#A0A0A0', danger_color: '#FF8888', success_color: '#198754', header_bg_color: '#313131', footer_bg_color: '#313131', header_logo: 'https://example.com/header.png', footer_logo: 'https://example.com/footer.png', categories: [], }; function createTenantServiceStub(currentTenant: Tenant | null) { const tenantState = signal(currentTenant); const statusState = signal<'ready' | 'not-found'>('ready'); return { tenant: tenantState.asReadonly(), status: statusState.asReadonly(), getTenant: () => tenantState(), bootstrap: vi.fn().mockResolvedValue(undefined), }; } function createToastServiceStub() { return { success: vi.fn(), danger: vi.fn(), info: vi.fn(), }; } function createModalServiceStub() { return { open: vi.fn(), openConfirm: vi.fn().mockReturnValue(of(true)), openConfirmDelete: vi.fn().mockReturnValue(of(false)), }; } describe('ReutilizablesTestPageComponent', () => { beforeAll(() => { try { getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting()); } catch { // Test environment may already be initialized by another setup entrypoint. } }); afterEach(() => { TestBed.resetTestingModule(); }); it('renders the tenant configuration section with logo sources and swatch colors', async () => { const modalServiceStub = createModalServiceStub(); await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: modalServiceStub, }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; const sectionTitle = element.querySelector('.configuracion-tennant h2'); expect(sectionTitle?.textContent).toContain('Configuracion Tenant'); const headerImg = element.querySelector( '.tenant-logo-card img[alt="Header Logo"]', ) as HTMLImageElement; expect(headerImg?.src).toBe(tenant.header_logo); const footerImg = element.querySelector( '.tenant-logo-card img[alt="Footer Logo"]', ) as HTMLImageElement; expect(footerImg?.src).toBe(tenant.footer_logo); expect(element.textContent).toContain(tenant.primary_color); expect(element.textContent).toContain(tenant.secondary_color); expect(element.textContent).toContain(tenant.danger_color); expect(element.textContent).toContain(tenant.success_color); }); it('renders the paginator demo with the initial page status', async () => { const modalServiceStub = createModalServiceStub(); await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: modalServiceStub, }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; expect(element.querySelector('app-paginator')).not.toBeNull(); expect(element.querySelector('[data-testid="paginator-status"]')?.textContent?.trim()).toBe( '1/8', ); }); it('renders the reusable map demo with all configured locations', async () => { await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: createModalServiceStub(), }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const mapDemo = fixture.nativeElement.querySelector( '[data-testid="location-map-demo"]', ) as HTMLElement; const accessibleLocations = mapDemo.querySelectorAll('app-location-map .visually-hidden li'); expect(mapDemo.querySelector('app-location-map')).not.toBeNull(); expect(accessibleLocations).toHaveLength(3); expect(mapDemo.textContent).toContain('Gigante de Arroyito'); fixture.destroy(); }); it('renders the carousel demo with mocked product images', async () => { await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: createModalServiceStub(), }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; const carouselDemo = element.querySelector('[data-testid="products-carousel"]'); const carouselItems = carouselDemo?.querySelectorAll('[data-carousel-index]'); const productImages = carouselDemo?.querySelectorAll('app-product-column-with-image img'); expect(carouselDemo?.querySelector('app-carousel')).not.toBeNull(); expect(carouselItems).toHaveLength(6); expect(productImages).toHaveLength(6); expect(productImages?.[0].getAttribute('src')).toContain('/images/carousel-mochila-roja.webp'); expect(productImages?.[1].getAttribute('src')).toContain( '/images/carousel-auriculares-amarillos.webp', ); expect( new Set(Array.from(productImages ?? [], (image) => image.getAttribute('src'))).size, ).toBe(6); }); it('renders the main carousel demo with remote images', async () => { await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: createModalServiceStub(), }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; const carouselDemo = element.querySelector('[data-testid="main-carousel"]'); const images = carouselDemo?.querySelectorAll('.main-carousel__image'); const indicators = carouselDemo?.querySelectorAll('.main-carousel__indicator'); expect(carouselDemo?.querySelector('app-main-carousel')).not.toBeNull(); expect(images).toHaveLength(3); expect(indicators).toHaveLength(3); expect(images?.[0].getAttribute('src')).toContain('images.unsplash.com'); fixture.destroy(); }); it('renders the modal showcase and opens the confirm demos from the buttons', async () => { const modalServiceStub = createModalServiceStub(); await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: modalServiceStub, }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; const buttons = Array.from(element.querySelectorAll('.button-group app-button button')); const confirmButton = buttons.find((button) => button.textContent?.includes('Abrir confirm modal'), ) as HTMLButtonElement; const deleteButton = buttons.find((button) => button.textContent?.includes('Abrir confirm delete'), ) as HTMLButtonElement; expect(element.querySelector('[data-testid="modal-last-result"]')?.textContent).toContain( 'Todavia no se abrio ningun modal.', ); confirmButton.click(); fixture.detectChanges(); deleteButton.click(); fixture.detectChanges(); expect(modalServiceStub.openConfirm).toHaveBeenCalledWith({ title: 'Confirmar accion', content: 'Caso base para verificar apertura, cierre y devolucion de resultado.', confirmLabel: 'Confirmar', }); expect(modalServiceStub.openConfirmDelete).toHaveBeenCalledWith({ title: 'Eliminar producto', content: 'Esta accion eliminara el producto del catalogo. Podras volver a crearlo manualmente.', confirmLabel: 'Eliminar', }); expect(element.querySelector('[data-testid="modal-last-result"]')?.textContent).toContain( 'Resultado: false', ); }); it('updates the visible result when the confirm modal resolves to true', async () => { const modalServiceStub = createModalServiceStub(); await TestBed.configureTestingModule({ imports: [ReutilizablesTestPageComponent], providers: [ { provide: TenantService, useValue: createTenantServiceStub(tenant), }, { provide: ToastService, useValue: createToastServiceStub(), }, { provide: ModalService, useValue: modalServiceStub, }, ], }).compileComponents(); const fixture = TestBed.createComponent(ReutilizablesTestPageComponent); fixture.detectChanges(); const element = fixture.nativeElement as HTMLElement; const confirmButton = Array.from( element.querySelectorAll('.button-group app-button button'), ).find((button) => button.textContent?.includes('Abrir confirm modal')) as HTMLButtonElement; confirmButton.click(); fixture.detectChanges(); expect(element.querySelector('[data-testid="modal-last-result"]')?.textContent).toContain( 'Resultado: true', ); }); });