Files
shopit-front/src/app/shared/components/stepper/stepper.component.spec.ts

129 lines
4.4 KiB
TypeScript

import { Component, signal, ViewChild } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { StepperComponent } from './stepper.component';
import { StepComponent } from './step.component';
@Component({
imports: [StepperComponent, StepComponent],
template: `
<app-stepper #stepper>
<app-step label="Step 1" [isValid]="step1Valid()">
<div id="content-1">Content 1</div>
</app-step>
<app-step label="Step 2" [isValid]="step2Valid()">
<div id="content-2">Content 2</div>
</app-step>
</app-stepper>
`
})
class TestHostComponent {
@ViewChild('stepper') stepper!: StepperComponent;
step1Valid = signal(true);
step2Valid = signal(true);
}
describe('StepperComponent & StepComponent', () => {
async function setup() {
await TestBed.configureTestingModule({
imports: [TestHostComponent, StepperComponent, StepComponent]
}).compileComponents();
const fixture = TestBed.createComponent(TestHostComponent);
fixture.detectChanges();
return { fixture, component: fixture.componentInstance };
}
it('renders step labels in the indicator bar', async () => {
const { fixture } = await setup();
const labels = fixture.nativeElement.querySelectorAll('.stepper-header__label');
expect(labels.length).toBe(2);
expect(labels[0].textContent.trim()).toBe('Step 1');
expect(labels[1].textContent.trim()).toBe('Step 2');
});
it('activates the first step by default and shows its content', async () => {
const { fixture } = await setup();
const content1 = fixture.nativeElement.querySelector('#content-1');
const content2 = fixture.nativeElement.querySelector('#content-2');
expect(content1).not.toBeNull();
expect(content2).toBeNull();
});
it('advances to step 2 when next() is called and current step is valid', async () => {
const { fixture, component } = await setup();
component.stepper.next();
fixture.detectChanges();
const content1 = fixture.nativeElement.querySelector('#content-1');
const content2 = fixture.nativeElement.querySelector('#content-2');
expect(content1).toBeNull();
expect(content2).not.toBeNull();
expect(component.stepper.currentStepIndex()).toBe(1);
});
it('does not advance to step 2 when next() is called if current step is invalid', async () => {
const { fixture, component } = await setup();
component.step1Valid.set(false);
fixture.detectChanges();
component.stepper.next();
fixture.detectChanges();
const content1 = fixture.nativeElement.querySelector('#content-1');
const content2 = fixture.nativeElement.querySelector('#content-2');
expect(content1).not.toBeNull();
expect(content2).toBeNull();
expect(component.stepper.currentStepIndex()).toBe(0);
});
it('goes back to step 1 when previous() is called', async () => {
const { fixture, component } = await setup();
component.stepper.next();
fixture.detectChanges();
expect(component.stepper.currentStepIndex()).toBe(1);
component.stepper.previous();
fixture.detectChanges();
expect(component.stepper.currentStepIndex()).toBe(0);
expect(fixture.nativeElement.querySelector('#content-1')).not.toBeNull();
});
it('marks the first circle as active by default', async () => {
const { fixture } = await setup();
const items = fixture.nativeElement.querySelectorAll('.stepper-header__item');
expect(items[0].classList.contains('is-active')).toBe(true);
expect(items[1].classList.contains('is-active')).toBe(false);
});
it('marks step 1 as completed and step 2 as active after advancing', async () => {
const { fixture, component } = await setup();
component.stepper.next();
fixture.detectChanges();
const items = fixture.nativeElement.querySelectorAll('.stepper-header__item');
expect(items[0].classList.contains('is-completed')).toBe(true);
expect(items[1].classList.contains('is-active')).toBe(true);
});
it('allows navigating back to a completed step via goToStep()', async () => {
const { fixture, component } = await setup();
component.stepper.next();
fixture.detectChanges();
expect(component.stepper.currentStepIndex()).toBe(1);
component.stepper.goToStep(0);
fixture.detectChanges();
expect(component.stepper.currentStepIndex()).toBe(0);
expect(fixture.nativeElement.querySelector('#content-1')).not.toBeNull();
});
});