skills/angular-awesome-testing/SKILL.md
Write and maintain tests for Angular Awesome wrapper directives, components, and services. Use when creating spec files for wa-* components, testing form control integration, testing event emission, testing toast/service behavior, running headless or BrowserStack tests, or debugging test failures in Angular Awesome.
npx skillsauth add gedmarc/angular-awesome angular-awesome-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Write reliable, maintainable tests for Angular Awesome wrappers.
npm run test:headless or npx ng test --no-watch --browsers=ChromeHeadlessnpx ng test --no-watch --browsers=ChromeHeadless --include="**/<name>*.spec.ts"npm run test:bs@Component({
selector: 'test-host', standalone: true,
imports: [WaButtonDirective],
template: `<wa-button [variant]="v" [disabled]="d" (wa-click)="clicked($event)">Go</wa-button>`
})
class TestHostComponent {
v = 'brand'; d = false;
events: Event[] = [];
clicked(e: Event) { this.events.push(e); }
}
describe('WaButtonDirective', () => {
let fixture: ComponentFixture<TestHostComponent>;
let host: TestHostComponent;
beforeEach(async () => {
await TestBed.configureTestingModule({ imports: [TestHostComponent] }).compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
host = fixture.componentInstance;
});
it('creates element', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('wa-button')).toBeTruthy();
});
it('binds variant', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('wa-button').getAttribute('variant')).toBe('brand');
});
it('updates on change', () => {
fixture.detectChanges();
host.v = 'danger';
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('wa-button').getAttribute('variant')).toBe('danger');
});
it('projects content', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('wa-button').textContent).toContain('Go');
});
});
describe('WaToastService', () => {
let service: WaToastService;
function getToasts() {
let v: Toast[] = [];
service.toasts$.subscribe(t => v = t).unsubscribe();
return v;
}
beforeEach(() => {
TestBed.configureTestingModule({
providers: [WaToastService, { provide: WA_TOAST_CONFIG, useValue: { placement: 'top-end', max: 2, duration: 100 } }]
});
service = TestBed.inject(WaToastService);
});
it('show returns id', () => expect(typeof service.show('Hi')).toBe('string'));
it('emits visible list', () => { service.show('A'); expect(getToasts().length).toBe(1); });
it('queues beyond max', () => { service.show('A'); service.show('B'); service.show('C'); expect(getToasts().length).toBe(2); });
it('auto-dismiss', fakeAsync(() => { service.setConfig({ duration: 5 }); service.show('X'); tick(6); expect(getToasts().length).toBe(0); }));
it('sticky', fakeAsync(() => { service.show('S', { duration: 0 }); tick(9999); expect(getToasts().length).toBe(1); }));
});
describe('WaToastContainerComponent', () => {
let fixture: ComponentFixture<WaToastContainerComponent>;
let service: WaToastService;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [WaToastContainerComponent],
providers: [{ provide: WA_TOAST_CONFIG, useValue: { placement: 'top-end', max: 3, duration: 0 } }]
}).compileComponents();
fixture = TestBed.createComponent(WaToastContainerComponent);
service = TestBed.inject(WaToastService);
});
it('renders wa-toast', () => {
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('wa-toast')).toBeTruthy();
});
it('renders toast items', () => {
fixture.detectChanges();
service.show('Hi');
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('wa-toast-item').length).toBe(1);
});
});
Every spec must test:
detectChanges()@Input reflects as the correct attributefakeAsync/tickquerySelector/querySelectorAll — web components are unknown elements in test DOM.getAttribute() — not property access — to verify attribute reflection.fixture.detectChanges() after every mutation.fakeAsync + tick for any setTimeout/auto-dismiss behavior.--include glob for .md files — only *.spec.ts.development
Use Angular Awesome wrapper directives for Web Awesome web components in Angular 20+ projects. Trigger when tasks mention wa-* components (wa-button, wa-input, wa-dialog, wa-toast, wa-select, wa-checkbox, etc.), Angular Awesome directives, Web Awesome Angular integration, component variants/appearance/size tokens, slot projection, form control binding, or angular-awesome imports. Covers component usage, layout utilities, services (toast), theming, and accessibility.
development
Theme and style Angular Awesome components using Web Awesome design tokens, CSS custom properties, CSS parts, variant/appearance/size tokens, and layout utilities. Use when customizing component appearance, applying brand colors, overriding default styles, using CSS shadow parts, or configuring layout directives (cluster, stack, grid, gap, align, flank, frame, split).
development
Create a new Angular Awesome wrapper directive or component for a Web Awesome web component. Use when adding a new wa-* component wrapper, scaffolding a directive with its spec/rules/example files, wiring it into public-api.ts, updating the changelog, and regenerating docs. Covers the full end-to-end flow from llms.txt API extraction through to build verification.
development
Migrate Angular Awesome component wrappers when the upstream Web Awesome API changes. Use when replacing custom implementations with official web components, updating property names or types, removing deprecated fields, aligning placement/position values, updating tests for new APIs, and updating docs/changelog for breaking changes.