import { TestBed } from '@angular/core/testing'; import { DEFAULT_STATUSES, StatusesStore } from './statuses.store'; const STORAGE_KEY = 'bonsai_statuses'; describe('StatusesStore', () => { let store: StatusesStore; beforeEach(() => { localStorage.removeItem(STORAGE_KEY); TestBed.configureTestingModule({}); store = TestBed.inject(StatusesStore); }); afterEach(() => { localStorage.removeItem(STORAGE_KEY); }); describe('statuses', () => { it('returns default statuses when localStorage is empty', () => { expect(store.statuses()).toEqual(DEFAULT_STATUSES); }); it('restores statuses saved in localStorage', () => { const saved = [ { id: 'done', label: 'TERMINÉ', bg: '#dcfce7', color: '#166534', order: 0 }, { id: 'draft', label: 'BROUILLON', bg: '#e2e8f0', color: '#475569', order: 1 }, ]; localStorage.setItem(STORAGE_KEY, JSON.stringify(saved)); TestBed.resetTestingModule(); TestBed.configureTestingModule({}); const freshStore = TestBed.inject(StatusesStore); expect(freshStore.statuses()).toEqual(saved); }); it('falls back to default when localStorage contains invalid JSON', () => { localStorage.setItem(STORAGE_KEY, 'not-json'); TestBed.resetTestingModule(); TestBed.configureTestingModule({}); const freshStore = TestBed.inject(StatusesStore); expect(freshStore.statuses()).toEqual(DEFAULT_STATUSES); }); it('sorts statuses by order on load', () => { const unsorted = [DEFAULT_STATUSES[2], DEFAULT_STATUSES[0], DEFAULT_STATUSES[1], DEFAULT_STATUSES[3]]; localStorage.setItem(STORAGE_KEY, JSON.stringify(unsorted)); TestBed.resetTestingModule(); TestBed.configureTestingModule({}); const freshStore = TestBed.inject(StatusesStore); expect(freshStore.statuses().map((s) => s.id)).toEqual(['draft', 'todo', 'in-progress', 'done']); }); }); describe('setOrder', () => { it('reassigns order values based on position', () => { const reordered = [DEFAULT_STATUSES[3], DEFAULT_STATUSES[2], DEFAULT_STATUSES[1], DEFAULT_STATUSES[0]]; store.setOrder(reordered); expect(store.statuses()[0].id).toBe('done'); expect(store.statuses()[0].order).toBe(0); expect(store.statuses()[3].id).toBe('draft'); expect(store.statuses()[3].order).toBe(3); }); it('persists the new order to localStorage', () => { const reordered = [DEFAULT_STATUSES[1], DEFAULT_STATUSES[0], DEFAULT_STATUSES[2], DEFAULT_STATUSES[3]]; store.setOrder(reordered); const stored = JSON.parse(localStorage.getItem(STORAGE_KEY)!); expect(stored[0].id).toBe('todo'); expect(stored[1].id).toBe('draft'); }); }); describe('getById', () => { it('returns the matching status entity', () => { expect(store.getById('draft')?.label).toBe('BROUILLON'); }); it('returns undefined for unknown id', () => { expect(store.getById('unknown')).toBeUndefined(); }); }); describe('isCompleted', () => { it('returns true for done status', () => { expect(store.isCompleted('done')).toBe(true); }); it('returns false for non-completed statuses', () => { expect(store.isCompleted('draft')).toBe(false); expect(store.isCompleted('todo')).toBe(false); expect(store.isCompleted('in-progress')).toBe(false); }); it('returns false for unknown status', () => { expect(store.isCompleted('unknown')).toBe(false); }); it('returns true for a custom status with countsAsCompleted true', () => { store.create({ id: 'abandoned', label: 'ABANDONNÉE', bg: '#f1f5f9', color: '#64748b', countsAsCompleted: true }); expect(store.isCompleted('abandoned')).toBe(true); }); }); describe('create', () => { it('adds a new status with the next order value', () => { store.create({ id: 'blocked', label: 'BLOQUÉ', bg: '#fee2e2', color: '#991b1b', countsAsCompleted: false }); const added = store.getById('blocked'); expect(added?.label).toBe('BLOQUÉ'); expect(added?.order).toBe(DEFAULT_STATUSES.length); }); it('persists the new status to localStorage', () => { store.create({ id: 'custom', label: 'CUSTOM', bg: '#fff', color: '#000', countsAsCompleted: false }); const stored = JSON.parse(localStorage.getItem(STORAGE_KEY)!); expect(stored.some((s: { id: string }) => s.id === 'custom')).toBe(true); }); }); describe('update', () => { it('updates label, bg and color of an existing status', () => { store.update('draft', { label: 'NOUVEAU', bg: '#fff', color: '#000', countsAsCompleted: false }); const updated = store.getById('draft'); expect(updated?.label).toBe('NOUVEAU'); expect(updated?.bg).toBe('#fff'); }); it('does not change unrelated statuses', () => { store.update('draft', { label: 'NOUVEAU' }); expect(store.getById('todo')?.label).toBe('À FAIRE'); }); }); });