import { Component, signal } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { ShippingModeService } from '@africanies/africanies-core';
import type { ShippingMode } from '@africanies/africanies-models';
import { ToggleComponent } from './toggle.component';
@Component({
standalone: true,
imports: [ToggleComponent, ReactiveFormsModule],
template: `
`,
})
class ToggleHostComponent {
readonly value = signal(false);
readonly loading = signal(false);
readonly disabled = signal(false);
readonly control = new FormControl(false, { nonNullable: true });
readonly emitted: boolean[] = [];
onValueChange(next: boolean): void {
this.emitted.push(next);
}
}
describe('ToggleComponent', () => {
let fixture: ComponentFixture;
let host: ToggleHostComponent;
let mode: ReturnType>;
beforeEach(async () => {
mode = signal('sfn');
await TestBed.configureTestingModule({
imports: [ToggleHostComponent],
providers: [
{
provide: ShippingModeService,
useValue: {
mode: mode.asReadonly(),
setMode: (next: ShippingMode) => mode.set(next),
},
},
],
}).compileComponents();
fixture = TestBed.createComponent(ToggleHostComponent);
host = fixture.componentInstance;
fixture.detectChanges();
});
function switches(): HTMLButtonElement[] {
return Array.from(
fixture.nativeElement.querySelectorAll('button[role="switch"]'),
);
}
it('emits the next value without flipping until the parent commits', () => {
const [toggle] = switches();
expect(toggle.getAttribute('aria-checked')).toBe('false');
toggle.click();
fixture.detectChanges();
expect(host.emitted).toEqual([true]);
expect(toggle.getAttribute('aria-checked')).toBe('false');
host.value.set(true);
fixture.detectChanges();
expect(toggle.getAttribute('aria-checked')).toBe('true');
});
it('shows a spinner and blocks clicks while loading', () => {
const [toggle] = switches();
host.loading.set(true);
fixture.detectChanges();
expect(toggle.getAttribute('aria-busy')).toBe('true');
expect(toggle.disabled).toBe(true);
expect(toggle.querySelector('.animate-spin')).not.toBeNull();
toggle.click();
fixture.detectChanges();
expect(host.emitted).toEqual([]);
});
it('propagates clicks through ControlValueAccessor', () => {
const [, formToggle] = switches();
formToggle.click();
fixture.detectChanges();
expect(host.control.value).toBe(true);
expect(formToggle.getAttribute('aria-checked')).toBe('true');
});
});