Adds a curated, Pi-native, skills+prompts-only profile at pi/core/ for downstream packagers that mirror GitHub Releases. - manifests/pi-core.json: explicit include lists, per-item exclusion reasons, curation rules, safety allowlists; every root skill and command must be classified. - scripts/build-pi-core.js regenerates pi/core deterministically (package.json from VERSION, LICENSE, README.md, CURATION.md, skills/, commands/); --check fails CI on drift. council is renamed ecc-council inside pi/core only. - Safety checks: no callable endpoints outside the allowlist, no npx/curl|sh/pip install, no secrets, no absolute home paths, no symlinks, valid frontmatter, no duplicate names. - CI: build + drift check and an offline Pi CLI load test of pi/core. - Release: VERSION, package.json and pi/core/package.json at 2.2.2, CHANGELOG, tag-triggered release verification, and a two-week cadence in CONTRIBUTING.md. pi/core: 123 of 293 skills and 24 of 94 commands; 35,006 characters of skill description text.
2.8 KiB
Testing with Component Harnesses
Component harnesses are the standard, preferred way to interact with components in tests. They provide a robust, user-centric API that makes tests less brittle and easier to read by insulating them from changes to a component's internal DOM structure.
Why Use Harnesses?
- Robustness: Tests don't break when you refactor a component's internal HTML or CSS classes.
- Readability: Tests describe interactions from a user's perspective (e.g.,
button.click(),slider.getValue()) instead of through DOM queries (fixture.nativeElement.querySelector(...)). - Reusability: The same harness can be used in both unit tests and E2E tests.
Angular Material provides a test harness for every component in its library.
Using a Harness in a Unit Test
The TestbedHarnessEnvironment is the entry point for using harnesses in unit tests.
Example: Testing with a MatButtonHarness
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
import {MatButtonHarness} from '@angular/material/button/testing';
import {MyButtonContainerComponent} from './my-button-container.component';
describe('MyButtonContainerComponent', () => {
let fixture: ComponentFixture<MyButtonContainerComponent>;
let loader: HarnessLoader;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyButtonContainerComponent, MatButtonModule],
}).compileComponents();
fixture = TestBed.createComponent(MyButtonContainerComponent);
// Create a harness loader for the component's fixture
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should find a button with specific text', async () => {
// Load the harness for a MatButton with the text "Submit"
const submitButton = await loader.getHarness(MatButtonHarness.with({text: 'Submit'}));
// Use the harness API to interact with the component
expect(await submitButton.isDisabled()).toBe(false);
await submitButton.click();
// ... assertions
});
});
Key Concepts
-
HarnessLoader: An object used to find and create harness instances. Get a loader for your component's fixture usingTestbedHarnessEnvironment.loader(fixture). -
loader.getHarness(HarnessClass): Asynchronously finds and returns a harness instance for the first matching component. -
HarnessClass.with({ ... }): Many harnesses provide a staticwithmethod that returns aHarnessPredicate. This allows you to filter and find components based on their properties, like text, selector, or disabled state. Always use this to precisely target the component you want to test. -
Harness API: Once you have a harness instance, use its methods (e.g.,
.click(),.getText(),.getValue()) to interact with the component. These methods automatically handle waiting for async operations and change detection.