update test

This commit is contained in:
2026-05-24 11:09:12 +02:00
parent c9f2863815
commit 264d9f1402
9 changed files with 575 additions and 138 deletions
@@ -1,3 +1,4 @@
import { signal } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ActivatedRoute, convertToParamMap, Router } from '@angular/router';
import { provideRouter } from '@angular/router';
@@ -23,6 +24,63 @@ const makeIssue = (overrides: Partial<IssueEntity> = {}): IssueEntity => ({
...overrides,
});
class FakeIssuesStore {
private _data = signal<IssueEntity[]>([
makeIssue({ id: 1, name: 'Issue 1' }),
makeIssue({ id: 2, name: 'Issue 2' }),
makeIssue({ id: 3, name: 'Issue 3' }),
]);
readonly issues = this._data.asReadonly();
readonly loading = signal(false);
readonly loaded = signal(true);
getById(id: number): IssueEntity | undefined {
return this._data().find((i) => i.id === id);
}
getNextId(): number {
const ids = this._data().map((i) => i.id);
return ids.length === 0 ? 1 : Math.max(...ids) + 1;
}
load(): Promise<void> {
return Promise.resolve();
}
upsert(issue: any): Promise<IssueEntity> {
const { comments: c, estimatedTime: et, dependsOnIds: deps, dependsOnId: legacy, ...rest } = issue;
const normalized: IssueEntity = {
...makeIssue(),
...rest,
dependsOnIds: Array.isArray(deps)
? deps.filter((v: unknown) => typeof v === 'number')
: typeof legacy === 'number'
? [legacy]
: [],
comments: Array.isArray(c) ? c : [],
estimatedTime: et ?? null,
};
this._data.update((issues) => {
const idx = issues.findIndex((i) => i.id === normalized.id);
if (idx === -1) return [...issues, normalized];
const copy = [...issues];
copy[idx] = normalized;
return copy;
});
return Promise.resolve(normalized);
}
deleteById(id: number): Promise<void> {
this._data.update((issues) =>
issues
.filter((i) => i.id !== id)
.map((i) => ({ ...i, dependsOnIds: i.dependsOnIds.filter((d) => d !== id) })),
);
return Promise.resolve();
}
}
function makeRoute(id = '1', path = 'issues/:id') {
return {
snapshot: {
@@ -37,30 +95,26 @@ function makeRoute(id = '1', path = 'issues/:id') {
describe('IssueDetail — existing issue', () => {
let component: IssueDetail;
let fixture: ComponentFixture<IssueDetail>;
let store: IssuesStore;
let store: FakeIssuesStore;
let router: Router;
beforeEach(async () => {
localStorage.clear();
store = new FakeIssuesStore();
await TestBed.configureTestingModule({
imports: [IssueDetail],
providers: [
provideRouter([]),
{ provide: ActivatedRoute, useValue: makeRoute('1') },
{ provide: IssuesStore, useValue: store },
],
}).compileComponents();
store = TestBed.inject(IssuesStore);
router = TestBed.inject(Router);
fixture = TestBed.createComponent(IssueDetail);
component = fixture.componentInstance;
await fixture.whenStable();
});
afterEach(() => {
localStorage.clear();
});
it('should create', () => {
expect(component).toBeTruthy();
});
@@ -115,7 +169,7 @@ describe('IssueDetail — existing issue', () => {
describe('deleteIssue', () => {
it('removes the issue and navigates to /issues', async () => {
const spy = vi.spyOn(router, 'navigate').mockResolvedValue(true);
(component as any).deleteIssue();
await (component as any).deleteIssue();
expect(store.getById(1)).toBeUndefined();
expect(spy).toHaveBeenCalledWith(['/issues']);
});
@@ -169,9 +223,9 @@ describe('IssueDetail — existing issue', () => {
expect((component as any).selectedCandidateId).toBeNull();
});
it('confirmAddDependency adds the selected id and saves', () => {
it('confirmAddDependency adds the selected id and saves', async () => {
(component as any).selectedCandidateId = 2;
(component as any).confirmAddDependency();
await (component as any).confirmAddDependency();
expect((component as any).issue.dependsOnIds).toContain(2);
expect(store.getById(1)?.dependsOnIds).toContain(2);
expect((component as any).showAddDependency).toBe(false);
@@ -370,9 +424,9 @@ describe('IssueDetail — existing issue', () => {
expect(created?.type).toBe('Story');
});
it('confirmCreateInEpic resets the form', () => {
it('confirmCreateInEpic resets the form', async () => {
(component as any).newIssueName = 'Child Issue';
(component as any).confirmCreateInEpic();
await (component as any).confirmCreateInEpic();
expect((component as any).showCreateInEpic).toBe(false);
expect((component as any).newIssueName).toBe('');
});
@@ -405,9 +459,9 @@ describe('IssueDetail — existing issue', () => {
expect((component as any).selectedEpicCandidateId).toBeNull();
});
it('confirmAddToEpic assigns the epic name to the selected issue', () => {
it('confirmAddToEpic assigns the epic name to the selected issue', async () => {
(component as any).selectedEpicCandidateId = 2;
(component as any).confirmAddToEpic();
await (component as any).confirmAddToEpic();
expect(store.getById(2)?.epic).toBe('My Epic');
expect((component as any).showAddToEpic).toBe(false);
});
@@ -436,11 +490,11 @@ describe('IssueDetail — existing issue', () => {
describe('IssueDetail — new issue route', () => {
let component: IssueDetail;
let fixture: ComponentFixture<IssueDetail>;
let store: IssuesStore;
let store: FakeIssuesStore;
let router: Router;
beforeEach(async () => {
localStorage.clear();
store = new FakeIssuesStore();
await TestBed.configureTestingModule({
imports: [IssueDetail],
providers: [
@@ -456,20 +510,16 @@ describe('IssueDetail — new issue route', () => {
paramMap: of(convertToParamMap({})),
},
},
{ provide: IssuesStore, useValue: store },
],
}).compileComponents();
store = TestBed.inject(IssuesStore);
router = TestBed.inject(Router);
fixture = TestBed.createComponent(IssueDetail);
component = fixture.componentInstance;
await fixture.whenStable();
});
afterEach(() => {
localStorage.clear();
});
it('should create', () => {
expect(component).toBeTruthy();
});
@@ -486,14 +536,14 @@ describe('IssueDetail — new issue route', () => {
it('saveIssue without explicit flag does nothing for new route', () => {
(component as any).issue.name = 'Draft Name';
const countBefore = store.issues().length;
(component as any).saveIssue(); // explicit = false
(component as any).saveIssue();
expect(store.issues().length).toBe(countBefore);
});
it('saveIssue with explicit=true creates the issue and navigates', async () => {
const spy = vi.spyOn(router, 'navigate').mockResolvedValue(true);
(component as any).issue.name = 'Brand New Issue';
(component as any).saveIssue(true);
await (component as any).saveIssue(true);
expect(store.issues().some((i) => i.name === 'Brand New Issue')).toBe(true);
expect(spy).toHaveBeenCalledWith(['/issues', 10]);
});