Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

To add Angular component harness support for a testing environment beyond TestBed or WebDriver, implement two bindings: a TestElement that performs interactions with the environment’s elements, and a concrete HarnessEnvironment that locates those elements and connects harnesses to Angular’s stability behavior. Then expose a loader so tests can obtain harness instances.

When to create a custom harness environment

Component harnesses provide a supported, user-oriented API for interacting with components in tests. By insulating tests from private implementation details such as DOM structure, they can make tests easier to read and maintain, and let a harness be reused across testing environments. They are especially useful for shared interactive widgets whose implementation may change independently of their consumers. Angular’s harness overview describes these benefits and the role of harnesses.

The Angular CDK documents two built-in environments: TestbedHarnessEnvironment for unit tests using Angular TestBed, and SeleniumWebDriverHarnessEnvironment for WebDriver end-to-end tests. Use the supplied loader when your tests run in one of those environments. For another runner or browser automation setup, provide the environment-specific element interactions and implement the environment bindings yourself. Install the CDK if it is not already in the project with ng add @angular/cdk. Angular’s harness usage guide covers the built-in environments and loader options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Implement the environment-specific TestElement

TestElement is the abstraction that allows the same harness API to work across environments. Each environment must provide an implementation for its raw element type. Its operations return promises, which accommodates environments where DOM operations are asynchronous, including WebDriver. Common operations include blur(), click(), and getAttribute().

Pay particular attention to keyboard input: the target environment’s key codes may differ from the CDK’s TestKey values. Map CDK keys to the codes expected by the target rather than assuming they match. Angular’s guide says, “Every test environment must define a TestElement implementation.” It points to the CDK’s unit-test and Selenium WebDriver element implementations as examples. Read Angular’s guide to adding support for additional testing environments.

Subclass HarnessEnvironment

In HarnessEnvironment<E>, E is the raw element type used by the target environment. The concrete subclass must implement these six responsibilities:

Method What it must do
getDocumentRoot(): E Return the environment’s root element, such as document.body.
createTestElement(element: E): TestElement Wrap a raw element in the environment-specific TestElement.
createEnvironment(element: E): HarnessEnvironment Create a nested environment rooted at the supplied element.
getAllRawElements(selector: string): Promise<E[]> Find all matching raw elements beneath the environment root.
forceStabilize(): Promise<void> Resolve when NgZone is stable and, where applicable, cause stabilization. Angular gives flush() in a fakeAsync test as an example.
waitForTasksOutsideAngular(): Promise<void> Resolve when the parent zone of NgZone is stable.

Give the subclass a protected constructor and a static loader method that returns a HarnessLoader. The loader is the entry point test authors use to find harnesses. A custom environment can also offer additional entry points or accept arguments required by its runner. Angular’s guide recommends studying the TestbedHarnessEnvironment and Selenium WebDriver implementations in the CDK as examples.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Connect automatic change detection

If the environment should support manualChangeDetection and parallel, connect it to auto change detection status. Call handleAutoChangeDetectionStatus(handler) with a handler that receives the status object, including isDisabled and onDetectChangesNow(). When the environment should no longer handle status changes, call stopHandlingAutoChangeDetectionStatus(). These hooks let the harness APIs coordinate change detection with the custom environment.

Expose the right loader scope

Choose a root that matches how tests need to locate components. The TestBed loader is rooted at a ComponentFixture by default. When a popup or overlay places its DOM outside the fixture—for example, under document.body—the TestBed environment’s documentRootLoader() can search from the document root instead. Its harnessForFixture() method can return a harness for the fixture root itself. The WebDriver loader is rooted at the current document and takes a WebDriver client. Angular’s usage guide documents these built-in entry points.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Account for interaction and stability differences

Harness methods are mostly asynchronous, so use await to make operation order clear. Angular also provides parallel for simultaneous operations and to optimize change-detection checks. These APIs do not guarantee identical behavior across environments: simulated unit-test events and real user interactions can differ, and the CDK aims to normalize behavior rather than erase every difference.

Before treating a custom environment as equivalent to an existing one, verify how it handles:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Whether DOM operations are synchronous or asynchronous.
  • How it generates keyboard and other events, including any mapping from TestKey values.
  • Which root and scoped-element access patterns it provides.
  • How it models Angular change detection, zone stability, and tasks outside Angular.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.