{"id":24796183,"url":"https://github.com/francescoborzi/ngx-page-object-model","last_synced_at":"2026-04-06T15:01:06.840Z","repository":{"id":268776127,"uuid":"905421089","full_name":"FrancescoBorzi/ngx-page-object-model","owner":"FrancescoBorzi","description":"Angular Component Tests made easy","archived":false,"fork":false,"pushed_at":"2026-04-03T00:48:06.000Z","size":11256,"stargazers_count":36,"open_issues_count":9,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-03T00:49:25.335Z","etag":null,"topics":["angular","angular-testing","testing-library"],"latest_commit_sha":null,"homepage":"https://francescoborzi.github.io/ngx-page-object-model/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FrancescoBorzi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":"www.paypal.me/francesco92dev"}},"created_at":"2024-12-18T19:43:18.000Z","updated_at":"2026-04-03T00:46:32.000Z","dependencies_parsed_at":"2024-12-18T21:29:43.552Z","dependency_job_id":"7b2e79a6-7591-43c7-9d2e-e84134b32815","html_url":"https://github.com/FrancescoBorzi/ngx-page-object-model","commit_stats":null,"previous_names":["francescoborzi/ngx-page-object-model"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/FrancescoBorzi/ngx-page-object-model","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FrancescoBorzi%2Fngx-page-object-model","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FrancescoBorzi%2Fngx-page-object-model/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FrancescoBorzi%2Fngx-page-object-model/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FrancescoBorzi%2Fngx-page-object-model/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FrancescoBorzi","download_url":"https://codeload.github.com/FrancescoBorzi/ngx-page-object-model/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FrancescoBorzi%2Fngx-page-object-model/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31477013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T14:34:32.243Z","status":"ssl_error","status_checked_at":"2026-04-06T14:34:31.723Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-testing","testing-library"],"created_at":"2025-01-30T00:31:39.526Z","updated_at":"2026-04-06T15:01:06.822Z","avatar_url":"https://github.com/FrancescoBorzi.png","language":"TypeScript","funding_links":["www.paypal.me/francesco92dev","https://www.paypal.me/francesco92dev"],"categories":[],"sub_categories":[],"readme":"# ngx-page-object-model\n\n[![CodeFactor](https://www.codefactor.io/repository/github/FrancescoBorzi/ngx-page-object-model/badge)](https://www.codefactor.io/repository/github/FrancescoBorzi/ngx-page-object-model)\n[![Actions Status](https://github.com/FrancescoBorzi/ngx-page-object-model/workflows/CI/badge.svg)](https://github.com/FrancescoBorzi/ngx-page-object-model/actions)\n\u003ca href=\"https://www.paypal.me/francesco92dev\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/badge/Donate-PayPal-ff3f59.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/ngx-page-object-model\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/npm/dw/ngx-page-object-model\"\u003e\u003c/a\u003e\n\nngx-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).\n\nBy 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.\n\nThis 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.\nIt can be used alongside tools like [Spectator](https://ngneat.github.io/spectator/) or as a standalone solution.\n\n## Setup\n\n```\nnpm install -D ngx-page-object-model\n```\n\n- Check the [Documentation](https://francescoborzi.github.io/ngx-page-object-model) for more details\n\n## Basic examples\n\n### Example of tests without Page Object Model\n\nIn this minimalistic example, direct interaction with the DOM happens within the test itself, leading to repetition and more complex code:\n\n```typescript\nbeforeEach(async () =\u003e {\n  // ...\n  fixture = TestBed.createComponent(CounterComponent);\n});\n\nit('should increase the counter when clicking on the increase button', () =\u003e {\n  fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();\n\n  expect(fixture.debugElement.query(By.css(`[data-testid=\"count\"]`)).nativeElement.innerHTML).toEqual('1');\n});\n\nit('should decrease the counter if the current value is greater than 0 when clicking on the decrease button', () =\u003e {\n  fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();\n  fixture.debugElement.query(By.css(`#increase-btn`)).nativeElement.click();\n\n  fixture.debugElement.query(By.css(`#decrease-btn`)).nativeElement.click();\n\n  expect(fixture.debugElement.query(By.css(`[data-testid=\"count\"]`)).nativeElement.innerHTML).toEqual('1');\n});\n```\n\n### Example of tests using the Page Object Model\n\nWith the Page Object Model pattern, the logic to interact with the DOM is encapsulated within a dedicated page object.\nThis approach makes tests more readable, ensures accurate typing for HTML elements, and reduces code duplication. The page object is simply a class extending `PageObjectModel`:\n\n```typescript\nimport { DebugHtmlElement, PageObjectModel } from 'ngx-page-object-model';\n\nclass CounterPage extends PageObjectModel\u003cCounterComponent\u003e {\n  getIncreaseButton(): DebugHtmlElement\u003cHTMLButtonElement\u003e {\n    return this.getDebugElementByCss('#increase-btn');\n  }\n  getDecreaseButton(): DebugHtmlElement\u003cHTMLButtonElement\u003e {\n    return this.getDebugElementByCss('#decrease-btn');\n  }\n  getCount(): DebugHtmlElement\u003cHTMLSpanElement\u003e {\n    return this.getDebugElementByTestId('count');\n  }\n\n  clickIncreaseButton(): void {\n    this.getIncreaseButton().nativeElement.click();\n  }\n  clickDecreaseButton(): void {\n    this.getDecreaseButton().nativeElement.click();\n  }\n}\n```\n\nThe test code is now cleaner, more focused, and avoids repetitive DOM manipulation:\n\n```typescript\nbeforeEach(async () =\u003e {\n  // ...\n  fixture = TestBed.createComponent(CounterComponent);\n  page = new CounterPage(fixture);\n});\n\nit('should increase the counter when clicking on the increase button', () =\u003e {\n  page.clickIncreaseButton();\n\n  expect(page.getCount().nativeElement.innerHTML).toEqual('1');\n});\n\nit('should decrease the counter if the current value is greater than 0 when clicking on the decrease button', () =\u003e {\n  page.clickIncreaseButton();\n  page.clickIncreaseButton();\n\n  page.clickDecreaseButton();\n\n  expect(page.getCount().nativeElement.innerHTML).toEqual('0');\n});\n```\n\n## More developer-friendly errors\n\nWhen using Angular default methods, running into a typo in a selector usually gives you an error like this:\n\n\u003e TypeError: Cannot read properties of null (reading 'nativeElement')\n\nThe methods provided by `ngx-page-object-model`, such as `getDebugElementByCss()` and `getDebugElementByTestId()`, are instead designed to produce clearer and more descriptive error messages:\n\n\u003e Element with selector \"#some-selector\" was not found.\n\nThis makes debugging a lot smoother, helping you quickly spot and fix broken CSS selectors or incorrect `data-testid` values.\n\n### Expect an element to not be there\n\nIf you want to explicitly check that an element is not present in the DOM, you can pass `false` to disable the default assertion error:\n\n```typescript\n// Assert that the count element is not present in the DOM\nexpect(page.getCount(false)).not.toBeDefined();\n```\n\n## Documentation\n\n- Check the [Documentation](https://francescoborzi.github.io/ngx-page-object-model) for more code examples, features and techniques.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrancescoborzi%2Fngx-page-object-model","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrancescoborzi%2Fngx-page-object-model","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrancescoborzi%2Fngx-page-object-model/lists"}