Skip to main content

DebugElementHarness

A utility class that provides a convenient, type-safe API for interacting with elements in tests using test IDs.

This class simplifies querying for elements and performing common actions like clicking, focusing, reading text, and setting form values. It works with elements that have a test ID attribute (by default data-test-id, set by TestIdDirective).

TestIdDirective​

Description​

An Angular attribute directive that adds a data-test-id attribute to DOM elements for testing purposes.

Usage​

<button testboxTestId="submit-button">Submit</button>

Renders as:

<button data-test-id="submit-button">Submit</button>

idsToMap​

Converts an array of test IDs into a type-safe map:

const testIds = ['submitButton', 'cancelButton'] as const;
const testIdMap = TestIdDirective.idsToMap(testIds);
// testIdMap = { submitButton: 'submitButton', cancelButton: 'cancelButton' }

Use it in templates with property binding:

<button [testboxTestId]="testIdMap.submitButton">Submit</button>

DebugElementHarness​

Constructor​

new DebugElementHarness<
TestIds extends readonly string[]
>(
debugElement: DebugElement,
testIds: TestIds,
testIdAttribute?: string // default: 'data-test-id'
)

Property: elements​

A record keyed by each test ID, where each key exposes the element API:

harness.elements.submitButton.click();
harness.elements.title.getTextContent();

Element API​

Each test ID exposes the following methods:

query(parentDebugElement?: DebugElement): DebugElement | null​

Queries for a single element with the test ID.

Returns the first matched DebugElement, or null if not found.

const button = harness.elements.submitButton.query();
expect(button).not.toBeNull();

queryAll(parentDebugElement?: DebugElement): DebugElement[]​

Queries for all elements with the test ID.

Returns an array of matched DebugElement instances (empty array if none found).

const items = harness.elements.todoItem.queryAll();
expect(items.length).toBe(3);

click(parentDebugElement?: DebugElement): void​

Clicks the element. Throws NoElementByTestIdFoundError if not found.

harness.elements.submitButton.click();

focus(parentDebugElement?: DebugElement): void​

Focuses the element. Throws NoElementByTestIdFoundError if not found.

harness.elements.searchInput.focus();

getTextContent(parentDebugElement?: DebugElement): string​

Returns the textContent of the element. Throws NoElementByTestIdFoundError if not found.

const title = harness.elements.pageTitle.getTextContent();
expect(title).toContain('Welcome');

changeValue(value: string, parentDebugElement?: DebugElement): void​

Sets the value of a form element and dispatches a change event. Throws NoElementByTestIdFoundError if not found.

harness.elements.countrySelect.changeValue('DE');

inputValue(value: string, parentDebugElement?: DebugElement): void​

Sets the value of a form element and dispatches an input event. Throws NoElementByTestIdFoundError if not found.

harness.elements.searchBox.inputValue('query text');

Scoping queries​

All methods accept an optional parentDebugElement to search within a specific subtree:

const listItem = harness.elements.todoItem.queryAll()[15];
const deleteButton = harness.elements.deleteButton.query(listItem);

Custom test attribute​

If you use a custom directive instead of TestIdDirective, pass your attribute name as the third constructor argument:

const harness = new DebugElementHarness(
fixture.debugElement,
testIds,
'data-testid' // custom attribute
);

Extending the harness​

You can create a component-specific harness by extending DebugElementHarness:

import {DebugElementHarness} from 'ngx-testbox/testing';
import {testIds} from './test-ids';

export class TodoHarness extends DebugElementHarness<typeof testIds> {
constructor(debugElement: DebugElement) {
super(debugElement, testIds);
}

setTodoInput(value: string): void {
const input = this.elements.todoInput.query().nativeElement;
input.value = value;
input.dispatchEvent(new Event('input'));
}
}