137 lines
4.8 KiB
TypeScript
137 lines
4.8 KiB
TypeScript
import { Component } from '@angular/core';
|
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { MainCarouselComponent } from './main-carousel.component';
|
|
|
|
@Component({
|
|
imports: [MainCarouselComponent],
|
|
template: `
|
|
<app-main-carousel
|
|
[images]="images"
|
|
[imageAlts]="['Primera promoción', 'Segunda promoción', 'Tercera promoción']"
|
|
[autoSlideInterval]="1000"
|
|
/>
|
|
`,
|
|
})
|
|
class TestHostComponent {
|
|
readonly images = ['/images/one.webp', '/images/two.webp', '/images/three.webp'];
|
|
}
|
|
|
|
@Component({
|
|
imports: [MainCarouselComponent],
|
|
template: `<app-main-carousel [images]="images" />`,
|
|
})
|
|
class ResponsiveTestHostComponent {
|
|
readonly images = [{ desktop: '/images/desktop.webp', mobile: '/images/mobile.webp' }];
|
|
}
|
|
|
|
describe('MainCarouselComponent', () => {
|
|
let fixture: ComponentFixture<TestHostComponent>;
|
|
|
|
beforeEach(async () => {
|
|
await TestBed.configureTestingModule({
|
|
imports: [TestHostComponent, ResponsiveTestHostComponent],
|
|
}).compileComponents();
|
|
|
|
fixture = TestBed.createComponent(TestHostComponent);
|
|
fixture.detectChanges();
|
|
});
|
|
|
|
it('renderiza solamente las imágenes y sus indicadores', () => {
|
|
const element = fixture.nativeElement as HTMLElement;
|
|
const images = element.querySelectorAll('.main-carousel__image');
|
|
const indicators = element.querySelectorAll('.main-carousel__indicator');
|
|
|
|
expect(images).toHaveLength(3);
|
|
expect(indicators).toHaveLength(3);
|
|
expect(images[0].getAttribute('alt')).toBe('Primera promoción');
|
|
expect(images[0].classList).toContain('main-carousel__image--active');
|
|
});
|
|
|
|
it('usa la variante móvil del crop cuando está disponible', () => {
|
|
const responsiveFixture = TestBed.createComponent(ResponsiveTestHostComponent);
|
|
responsiveFixture.detectChanges();
|
|
|
|
const picture = responsiveFixture.nativeElement.querySelector('picture') as HTMLPictureElement;
|
|
const source = picture.querySelector('source') as HTMLSourceElement;
|
|
const image = picture.querySelector('img') as HTMLImageElement;
|
|
|
|
expect(source.getAttribute('media')).toBe('(max-width: 576px)');
|
|
expect(source.getAttribute('srcset')).toBe('/images/mobile.webp');
|
|
expect(image.getAttribute('src')).toBe('/images/desktop.webp');
|
|
});
|
|
|
|
it('carga las imágenes secuencialmente y prioriza la imagen visible', () => {
|
|
const images = fixture.nativeElement.querySelectorAll(
|
|
'.main-carousel__image',
|
|
) as NodeListOf<HTMLImageElement>;
|
|
|
|
expect(images[0].getAttribute('src')).toBe('/images/one.webp');
|
|
expect(images[0].getAttribute('fetchpriority')).toBe('high');
|
|
expect(images[1].getAttribute('src')).toBeNull();
|
|
expect(images[2].getAttribute('src')).toBeNull();
|
|
|
|
images[0].dispatchEvent(new Event('load'));
|
|
fixture.detectChanges();
|
|
|
|
expect(images[1].getAttribute('src')).toBe('/images/two.webp');
|
|
expect(images[1].getAttribute('fetchpriority')).toBe('low');
|
|
expect(images[2].getAttribute('src')).toBeNull();
|
|
|
|
images[1].dispatchEvent(new Event('load'));
|
|
fixture.detectChanges();
|
|
|
|
expect(images[2].getAttribute('src')).toBe('/images/three.webp');
|
|
});
|
|
|
|
it('avanza automáticamente entre las imágenes', () => {
|
|
fixture.destroy();
|
|
vi.useFakeTimers();
|
|
|
|
try {
|
|
fixture = TestBed.createComponent(TestHostComponent);
|
|
fixture.detectChanges();
|
|
const images = fixture.nativeElement.querySelectorAll(
|
|
'.main-carousel__image',
|
|
) as NodeListOf<HTMLImageElement>;
|
|
|
|
images[0].dispatchEvent(new Event('load'));
|
|
fixture.detectChanges();
|
|
images[1].dispatchEvent(new Event('load'));
|
|
fixture.detectChanges();
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
fixture.detectChanges();
|
|
|
|
expect(images[1].classList).toContain('main-carousel__image--active');
|
|
} finally {
|
|
fixture.destroy();
|
|
vi.useRealTimers();
|
|
}
|
|
});
|
|
|
|
it('permite seleccionar una imagen desde los indicadores', () => {
|
|
const indicators = fixture.nativeElement.querySelectorAll(
|
|
'.main-carousel__indicator',
|
|
) as NodeListOf<HTMLButtonElement>;
|
|
|
|
indicators[2].click();
|
|
fixture.detectChanges();
|
|
|
|
const images = fixture.nativeElement.querySelectorAll('.main-carousel__image');
|
|
expect(images[2].classList).toContain('main-carousel__image--active');
|
|
expect(indicators[2].getAttribute('aria-current')).toBe('true');
|
|
});
|
|
|
|
it('permite navegar con las flechas del teclado', () => {
|
|
const carousel = fixture.nativeElement.querySelector('.main-carousel') as HTMLElement;
|
|
|
|
carousel.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
|
|
fixture.detectChanges();
|
|
|
|
const images = fixture.nativeElement.querySelectorAll('.main-carousel__image');
|
|
expect(images[2].classList).toContain('main-carousel__image--active');
|
|
});
|
|
});
|