feat: minimal signals + RemoteData template with a users feature
Extracted from atomic-design-poc: RemoteData<E,T> (bare union + fromResource, no combinators) + a trimmed <app-async> switch, no Elm-style store — state is resource() plus one plain signal. Minimal DDD layering per context (domain/infrastructure/application/ui) combined with atomic design inside ui/ (atoms/molecules/organisms/templates/pages), mirroring the POC's conventions at template scale. One worked feature (users/): a list with a click-through to a detail view (its own independent resource() fetch) and a Back action. Tests are BDD-style (describe/it, one assertion per it) and black-box (assert rendered DOM/emitted events only) - 100% branch/line coverage. README.md documents what's deliberately omitted vs. the POC and the concrete growth path back to it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { UserDetailComponent } from './user-detail.component';
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe('UserDetailComponent', () => {
|
||||
it("shows the fetched user's name and email once resolved", async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn().mockResolvedValue({
|
||||
json: () => Promise.resolve({ id: 1, name: 'Ada', email: 'ada@example.com' }),
|
||||
}),
|
||||
);
|
||||
await TestBed.configureTestingModule({ imports: [UserDetailComponent] }).compileComponents();
|
||||
const fixture = TestBed.createComponent(UserDetailComponent);
|
||||
fixture.componentRef.setInput('userId', 1);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement.textContent).toContain('ada@example.com');
|
||||
});
|
||||
|
||||
it('emits close when the back button is clicked', async () => {
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
vi.fn().mockResolvedValue({
|
||||
json: () => Promise.resolve({ id: 1, name: 'Ada', email: 'a@x.com' }),
|
||||
}),
|
||||
);
|
||||
await TestBed.configureTestingModule({ imports: [UserDetailComponent] }).compileComponents();
|
||||
const fixture = TestBed.createComponent(UserDetailComponent);
|
||||
fixture.componentRef.setInput('userId', 1);
|
||||
fixture.detectChanges();
|
||||
let closed = false;
|
||||
fixture.componentInstance.close.subscribe(() => (closed = true));
|
||||
fixture.nativeElement.querySelectorAll('button')[0].click();
|
||||
expect(closed).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user