https://github.com/FrancescoBorzi/ngx-page-object-model
Angular Component Tests made easy
https://github.com/FrancescoBorzi/ngx-page-object-model
angular angular-testing testing-library
Last synced: 3 months ago
JSON representation
Angular Component Tests made easy
- Host: GitHub
- URL: https://github.com/FrancescoBorzi/ngx-page-object-model
- Owner: FrancescoBorzi
- License: mit
- Created: 2024-12-18T19:43:18.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2025-08-22T22:53:38.000Z (4 months ago)
- Last Synced: 2025-08-23T00:46:59.002Z (4 months ago)
- Topics: angular, angular-testing, testing-library
- Language: TypeScript
- Homepage: https://francescoborzi.github.io/ngx-page-object-model/
- Size: 9.8 MB
- Stars: 34
- Watchers: 1
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
- awesome-angular - ngx-page-object-model - This library simplifies Angular UI component testing using the Page Object Model (POM), separating test logic from DOM manipulation for better abstraction. (Testing / Helpers)
- fucking-awesome-angular - ngx-page-object-model - This library simplifies Angular UI component testing using the Page Object Model (POM), separating test logic from DOM manipulation for better abstraction. (Testing / Helpers)
README
# ngx-page-object-model
[](https://www.codefactor.io/repository/github/FrancescoBorzi/ngx-page-object-model)
[](https://github.com/FrancescoBorzi/ngx-page-object-model/actions)

ngx-page-object-model is a lightweight library designed to simplify writing [unit tests for Angular UI Components](https://javascript.plainenglish.io/component-dom-testing-in-angular-0d2256414c06) by leveraging the [Page Object Model (POM) design pattern](https://martinfowler.com/bliki/PageObject.html).
By using the Page Object Model design pattern, you can create a new abstraction level and keep your test logic separated from the logic to read and manipulate the DOM.
This library is fully Angular-based and completely testing-framework-agnostic, making it compatible with [Jasmine](https://jasmine.github.io/), [Jest](https://jestjs.io/), [Vitest](https://vitest.dev/), or any other unit testing framework.
It can be used alongside tools like [Spectator](https://ngneat.github.io/spectator/) or as a standalone solution.
## Setup
```
npm install -D ngx-page-object-model
```
- Check the [Documentation](https://francescoborzi.github.io/ngx-page-object-model) for more details
## Basic examples
### Example of tests without Page Object Model
In this minimalistic example, direct interaction with the DOM happens within the test itself, leading to repetition and more complex code:
```typescript
beforeEach(async () => {
// ...
fixture = TestBed.createComponent(CounterComponent);
});
it('should increase the counter when clicking on the increase button', () => {
fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();
expect(fixture.debugElement.query(By.css(`[data-testid="count"]`)).nativeElement.innerHTML).toEqual('1');
});
it('should decrease the counter if the current value is greater than 0 when clicking on the decrease button', () => {
fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();
fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();
fixture.debugElement.query(By.css(`#decrease-btn`)).nativeElement.click();
expect(fixture.debugElement.query(By.css(`[data-testid="count"]`)).nativeElement.innerHTML).toEqual('1');
});
```
### Example of tests using the Page Object Model
With the Page Object Model pattern, the logic to interact with the DOM is encapsulated within a dedicated page object.
This approach makes tests more readable, ensures accurate typing for HTML elements, and reduces code duplication. The page object is simply a class extending `PageObjectModel`:
```typescript
import { DebugHtmlElement, PageObjectModel } from 'ngx-page-object-model';
class CounterPage extends PageObjectModel {
getIncreaseButton(): DebugHtmlElement {
return this.getDebugElementByCss('#increase-btn');
}
getDecreaseButton(): DebugHtmlElement {
return this.getDebugElementByCss('#decrease-btn');
}
getCount(): DebugHtmlElement {
return this.getDebugElementByTestId('count');
}
clickIncreaseButton(): void {
this.getIncreaseButton().nativeElement.click();
}
clickDecreaseButton(): void {
this.getDecreaseButton().nativeElement.click();
}
}
```
The test code is now cleaner, more focused, and avoids repetitive DOM manipulation:
```typescript
beforeEach(async () => {
// ...
fixture = TestBed.createComponent(CounterComponent);
page = new CounterPage(fixture);
});
it('should increase the counter when clicking on the increase button', () => {
page.clickIncreaseButton();
expect(page.getCount().nativeElement.innerHTML).toEqual('1');
});
it('should decrease the counter if the current value is greater than 0 when clicking on the decrease button', () => {
page.clickIncreaseButton();
page.clickIncreaseButton();
page.clickDecreaseButton();
expect(page.getCount().nativeElement.innerHTML).toEqual('0');
});
```
## More developer-friendly errors
When using Angular default methods, running into a typo in a selector usually gives you an error like this:
> TypeError: Cannot read properties of null (reading 'nativeElement')
The methods provided by `ngx-page-object-model`, such as `getDebugElementByCss()` and `getDebugElementByTestId()`, are instead designed to produce clearer and more descriptive error messages:
> Element with selector "#some-selector" was not found.
This makes debugging a lot smoother, helping you quickly spot and fix broken CSS selectors or incorrect `data-testid` values.
### Expect an element to not be there
If you want to explicitly check that an element is not present in the DOM, you can pass `false` to disable the default assertion error:
```typescript
// Assert that the count element is not present in the DOM
expect(page.getCount(false)).not.toBeDefined();
```
## Documentation
- Check the [Documentation](https://francescoborzi.github.io/ngx-page-object-model) for more code examples, features and techniques.