import { describe, it, expect } from 'vitest'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { TaskDetailSidebar } from '@app/features/tasks/ui/task-detail-sidebar/task-detail-sidebar'; import { TaskBuilder } from '@tests/builders/task.builder'; describe('TaskDetailSidebar', () => { let component: TaskDetailSidebar; let fixture: ComponentFixture; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [TaskDetailSidebar], }).compileComponents(); fixture = TestBed.createComponent(TaskDetailSidebar); component = fixture.componentInstance; fixture.componentRef.setInput('task', new TaskBuilder().build()); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should render task title', () => { fixture.componentRef.setInput('task', new TaskBuilder().withTitle('My Task').build()); fixture.detectChanges(); const title = fixture.nativeElement.querySelector('.task-sidebar__title'); expect(title?.textContent).toContain('My Task'); }); it('should render description', () => { fixture.componentRef.setInput('task', new TaskBuilder().withDescription('My Description').build()); fixture.detectChanges(); const desc = fixture.nativeElement.querySelector('.task-sidebar__text'); expect(desc?.textContent).toContain('My Description'); }); it('should show fallback when no description', () => { fixture.componentRef.setInput('task', new TaskBuilder().withDescription('').build()); fixture.detectChanges(); const desc = fixture.nativeElement.querySelector('.task-sidebar__text'); expect(desc?.textContent).toContain('No description provided'); }); it('should render due date', () => { fixture.componentRef.setInput('task', new TaskBuilder().withDueDate('2026-12-25').build()); fixture.detectChanges(); const meta = fixture.nativeElement.querySelector('.task-sidebar__meta'); expect(meta?.textContent).toContain('2026-12-25'); }); it('should return current state from history', () => { fixture.componentRef.setInput('task', new TaskBuilder().withState('active').build()); expect(component.currentState()).toBe('active'); }); it('should return new when history is empty', () => { fixture.componentRef.setInput('task', new TaskBuilder().withStateHistory([]).build()); expect(component.currentState()).toBe('new'); }); it('should return 0 progress for new state', () => { fixture.componentRef.setInput('task', new TaskBuilder().withState('new').build()); expect(component.getStateProgress()).toBe(0); }); it('should return 50 progress for active state', () => { fixture.componentRef.setInput('task', new TaskBuilder().withState('active').build()); expect(component.getStateProgress()).toBe(50); }); it('should return 100 progress for resolved state', () => { fixture.componentRef.setInput('task', new TaskBuilder().withState('resolved').build()); expect(component.getStateProgress()).toBe(100); }); it('should emit close event', () => { const spy = vi.fn(); component.close.subscribe(spy); component.onClose(); expect(spy).toHaveBeenCalledOnce(); }); it('should emit changeState event', () => { const spy = vi.fn(); component.changeState.subscribe(spy); component.onChangeState('active'); expect(spy).toHaveBeenCalledWith('active'); }); it('should emit deleteTask event', () => { const spy = vi.fn(); component.deleteTask.subscribe(spy); component.onDeleteTask(); expect(spy).toHaveBeenCalledOnce(); }); it('should emit addNote event', () => { const spy = vi.fn(); component.addNote.subscribe(spy); component.onAddNote('New note'); expect(spy).toHaveBeenCalledWith('New note'); }); it('should emit deleteNote event', () => { const spy = vi.fn(); component.deleteNote.subscribe(spy); component.onDeleteNote(0); expect(spy).toHaveBeenCalledWith(0); }); });