import { provideHttpClient } from '@angular/common/http'; import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; import { ProjectEntity, ProjectsStore } from './projects.store'; const API = '/api'; const makeProject = (overrides: Partial = {}): ProjectEntity => ({ id: 1, name: 'Mon Projet', owner: 'Alice', status: 'Actif', progress: 50, ...overrides, }); describe('ProjectsStore', () => { let store: ProjectsStore; let httpMock: HttpTestingController; const loadWith = async (projects: ProjectEntity[]) => { const p = store.load(); httpMock.expectOne(`${API}/projects`).flush(projects); await p; }; beforeEach(() => { TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()], }); store = TestBed.inject(ProjectsStore); httpMock = TestBed.inject(HttpTestingController); }); afterEach(() => httpMock.verify()); it('should be created', () => { expect(store).toBeTruthy(); }); describe('load', () => { it('populates projects from the API', async () => { await loadWith([makeProject({ id: 1 }), makeProject({ id: 2 })]); expect(store.projects().length).toBe(2); }); it('sets loading to true during load and false after', async () => { const p = store.load(); expect(store.loading()).toBe(true); httpMock.expectOne(`${API}/projects`).flush([]); await p; expect(store.loading()).toBe(false); expect(store.loaded()).toBe(true); }); it('does not reload if already loaded', async () => { await loadWith([]); await store.load(); httpMock.expectNone(`${API}/projects`); }); it('falls back to stub projects when the API returns an error', async () => { const p = store.load(); httpMock.expectOne(`${API}/projects`).error(new ProgressEvent('error')); await p; expect(store.projects().length).toBeGreaterThan(0); expect(store.loaded()).toBe(true); }); }); describe('getById', () => { beforeEach(async () => { await loadWith([makeProject({ id: 1 }), makeProject({ id: 2 })]); }); it('returns the project with the given id', () => { expect(store.getById(1)?.id).toBe(1); }); it('returns undefined for an unknown id', () => { expect(store.getById(9999)).toBeUndefined(); }); }); describe('createLocal', () => { beforeEach(async () => { await loadWith([makeProject({ id: 1 }), makeProject({ id: 3 })]); }); it('adds a new project with id = max existing id + 1', () => { const created = store.createLocal('Nouveau', 'Alice'); expect(created.id).toBe(4); expect(created.name).toBe('Nouveau'); expect(created.owner).toBe('Alice'); expect(created.status).toBe('Nouveau'); }); it('appends the new project to the list', () => { const before = store.projects().length; store.createLocal('Test', 'Bob'); expect(store.projects().length).toBe(before + 1); }); it('trims name and owner', () => { const created = store.createLocal(' Nom ', ' Alice '); expect(created.name).toBe('Nom'); expect(created.owner).toBe('Alice'); }); }); describe('upsert', () => { beforeEach(async () => { await loadWith([makeProject({ id: 1, name: 'Existing' }), makeProject({ id: 2 })]); }); it('creates a new project via POST when id is 0', async () => { const before = store.projects().length; const p = store.upsert(makeProject({ id: 0, name: 'New Project' })); httpMock.expectOne({ method: 'POST', url: `${API}/projects` }).flush(makeProject({ id: 99, name: 'New Project' })); await p; expect(store.projects().length).toBe(before + 1); expect(store.getById(99)?.name).toBe('New Project'); }); it('updates an existing project via PUT', async () => { const p = store.upsert(makeProject({ id: 1, name: 'Updated' })); httpMock.expectOne({ method: 'PUT', url: `${API}/projects/1` }).flush(makeProject({ id: 1, name: 'Updated' })); await p; expect(store.getById(1)?.name).toBe('Updated'); }); }); describe('deleteById', () => { beforeEach(async () => { await loadWith([makeProject({ id: 1 }), makeProject({ id: 2 })]); }); it('removes the project from the store', async () => { const p = store.deleteById(1); httpMock.expectOne({ method: 'DELETE', url: `${API}/projects/1` }).flush(null); await p; expect(store.getById(1)).toBeUndefined(); expect(store.projects().length).toBe(1); }); }); });