name: stack-angular description: Angular frontend conventions, patterns, and test infrastructure. Use when working with Angular components, services, modules, RxJS, Angular CLI, ng commands, Jasmine tests, Component Harnesses, HttpTestingController, Angular routing, Angular forms, Angular pipes, or Angular dependency injection. user-invocable: false
Integration Tests
// Use Component Harnesses + HttpTestingController
describe('OrderListComponent', () => {
it('should display orders after loading', async () => {
const harness = await TestbedHarnessEnvironment.harnessForFixture(
fixture, OrderListComponentHarness
);
await harness.clickRefresh();
const items = await harness.getOrderItems();
expect(items.length).toBeGreaterThan(0);
});
});
Frameworks
- Jasmine for tests
- Component Harnesses for component testing
- HttpTestingController for service integration
Build & Test Commands
ng build
ng test --watch=false
Test Patterns by Component Classification
Presentational Components
Skip standalone tests — covered by parent component integration tests.
Exception: if the component has 3+ conditional branches (e.g., *ngIf / @if chains), write a focused component test.
Smart/Container Components
// Component Harness + HttpTestingController for smart components
describe('DashboardComponent', () => {
it('should load and display stats from service', async () => {
const harness = await TestbedHarnessEnvironment.harnessForFixture(
fixture, DashboardComponentHarness
);
const req = httpTestingController.expectOne('/api/stats');
req.flush(mockStats);
const cards = await harness.getStatCards();
expect(cards.length).toBe(mockStats.length);
});
});
Form-heavy Components
// Integration test for reactive form submission
describe('ProfileFormComponent', () => {
it('should submit valid form data', async () => {
const harness = await TestbedHarnessEnvironment.harnessForFixture(
fixture, ProfileFormComponentHarness
);
await harness.fillName('Jane Doe');
await harness.fillEmail('jane@example.com');
await harness.clickSubmit();
const req = httpTestingController.expectOne('/api/profile');
expect(req.request.body.name).toBe('Jane Doe');
});
it('should show validation error for invalid email', async () => {
const harness = await TestbedHarnessEnvironment.harnessForFixture(
fixture, ProfileFormComponentHarness
);
await harness.fillEmail('not-an-email');
await harness.clickSubmit();
const error = await harness.getEmailError();
expect(error).toBeTruthy();
});
});
Unit test custom validators separately only when they have complex rules:
describe('passwordStrengthValidator', () => {
it('should reject passwords without special characters', () => {
const control = new FormControl('weakpassword');
const result = passwordStrengthValidator(control);
expect(result?.['passwordStrength']).toBeTruthy();
});
});
Critical User Journey (E2E)
// Playwright Test — E2E for auth flow (runs in CI)
import { test, expect } from '@playwright/test';
test('login flow', async ({ page }) => {
await page.goto('/login');
await page.fill('[data-testid="email"]', 'user@example.com');
await page.fill('[data-testid="password"]', 'securepassword');
await page.click('[data-testid="login-button"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('[data-testid="welcome-message"]')).toBeVisible();
});
Visual/Layout Components
Write Playwright visual regression tests — these run in CI and catch regressions automatically:
// Playwright visual regression test (runs in CI)
test('sidebar matches visual baseline', async ({ page }) => {
await page.goto('/dashboard');
await expect(page.locator('[data-testid="sidebar"]')).toHaveScreenshot('sidebar.png');
});
For interactive spot-checks during development, use Playwright CLI (playwright-cli snapshot, playwright-cli screenshot). Neither replaces Playwright Test — see the testing skill's "Browser Testing Tools" section.
Data Display Components
// Integration test for data table with transformation
describe('OrderTableComponent', () => {
it('should display formatted order data', async () => {
const harness = await TestbedHarnessEnvironment.harnessForFixture(
fixture, OrderTableComponentHarness
);
const req = httpTestingController.expectOne('/api/orders');
req.flush([{ amount: 1500, date: '2024-01-15' }]);
const rows = await harness.getRows();
expect(rows.length).toBe(1);
const amount = await rows[0].getAmount();
expect(amount).toContain('$15.00');
});
});
Security
- Trust Angular's built-in XSS protection — do not bypass with
bypassSecurityTrust*unless absolutely necessary and reviewed - Use
HttpClientwhich includes XSRF protection by default - Sanitize user input displayed via
[innerHTML]usingDomSanitizer
Read the project's applicable agent guidance (AGENTS.md for Codex, CLAUDE.md for
Claude Code) and relevant docs/<topic>.md files for project-specific Angular
conventions when they exist.
Expert Next.js App Router
Developpement
Un skill qui transforme Claude en expert Next.js App Router.
Générateur de README
Developpement
Crée des README.md professionnels et complets pour vos projets.
Rédacteur de Documentation API
Developpement
Génère de la documentation API complète au format OpenAPI/Swagger.