{"id":15211078,"url":"https://github.com/lariat-js/playwright","last_synced_at":"2025-12-25T15:46:18.106Z","repository":{"id":39675702,"uuid":"388898647","full_name":"lariat-js/playwright","owner":"lariat-js","description":"🪢 Page object framework for Playwright.","archived":false,"fork":false,"pushed_at":"2024-02-17T02:54:29.000Z","size":4071,"stargazers_count":35,"open_issues_count":0,"forks_count":2,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-09-18T16:04:37.634Z","etag":null,"topics":["end-to-end-testing","page-object-model","playwright","playwright-test","testing"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lariat-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-23T18:55:02.000Z","updated_at":"2025-05-26T16:21:06.000Z","dependencies_parsed_at":"2023-12-02T02:28:54.136Z","dependency_job_id":"eb5495ca-a057-4fed-8f87-847334688325","html_url":"https://github.com/lariat-js/playwright","commit_stats":null,"previous_names":["lariat-js/playwright","widen/lariat"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/lariat-js/playwright","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lariat-js%2Fplaywright","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lariat-js%2Fplaywright/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lariat-js%2Fplaywright/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lariat-js%2Fplaywright/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lariat-js","download_url":"https://codeload.github.com/lariat-js/playwright/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lariat-js%2Fplaywright/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281654331,"owners_count":26538643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-29T02:00:06.901Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["end-to-end-testing","page-object-model","playwright","playwright-test","testing"],"created_at":"2024-09-28T08:03:22.323Z","updated_at":"2025-10-29T16:31:08.608Z","avatar_url":"https://github.com/lariat-js.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lariat for Playwright\n\n[![Build](https://github.com/lariat-js/playwright/actions/workflows/build.yml/badge.svg)](https://github.com/lariat-js/playwright/actions/workflows/build.yml)\n[![npm](https://img.shields.io/npm/v/@lariat/playwright)](https://www.npmjs.com/package/@lariat/playwright)\n\nPage object framework for [Playwright](https://playwright.dev).\n\n## Installation\n\nnpm\n\n```sh\nnpm install @lariat/playwright\n```\n\nYarn\n\n```sh\nyarn add @lariat/playwright\n```\n\npnpm\n\n```sh\npnpm add @lariat/playwright\n```\n\nBun\n\n```sh\nbun add @lariat/playwright\n```\n\n## Basic Usage\n\nAt the core of Lariat is the `Collection` class. This class is used to represent\na collection of elements in a page or section of a page and can include\nassociated utility methods for interacting with those elements.\n\nTo create your own collections, simply create a class which extends the\n`Collection` class. You can then define elements using the `Collection.el()`\nmethod which we will explore more in a moment.\n\n```ts\nimport Collection from '@lariat/playwright'\n\nclass TodoPage extends Collection\u003cPage\u003e {\n  input = this.el('#todo-input')\n}\n```\n\nWith your collection defined, you can instantiate it in your test to access the\nelements.\n\n```ts\ntest('create a todo', async ({ page }) =\u003e {\n  const todoPage = new TodoPage(page)\n  await todoPage.input.fill('Finish the website')\n})\n```\n\n## Elements\n\nElements are defined in collections using the `Collection.el()` method.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  saveButton = this.el('#save-button')\n}\n```\n\nElements are represented using Playwright\n[locators](https://playwright.dev/docs/api/class-locator) .\n\n```ts\nconst todoPage = new TodoPage(page)\nawait todoPage.saveButton.click()\n```\n\n### `has` and `hasText`\n\nThe `has` and `hasText` locator options can be passed to `Collection.el()` to\nmatch elements that contain a given locator or text.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  buttonWithIcon = this.el('button', { has: this.el('svg') })\n  saveButton = this.el('button', { hasText: 'Save' })\n}\n```\n\n### Dynamic selectors\n\nBecause collections in Lariat are plain JavaScript classes, you can easily\ncreate elements with dynamic selectors. Consider a todo list where we find an\nitem based on it's name. Our collection might look something like this:\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  item = (name: string) =\u003e this.el(`#todo-item[data-name=\"${name}\"]`)\n}\n\nconst todoPage = new TodoPage(page)\nconst item = todoPage.item('Finish the website')\nawait item.click()\n```\n\n### Portals\n\nSometimes, the DOM structure of a page might not match the visual structure\nexactly. For example, if you use React's `createPortal` function you can render\nan element outside the main React tree. To support these use cases, Lariat\nallows you to pass a `portal` option to `Collection.el()` to indicate that the\nelement should not be based off the `root` element.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  modal = this.el('#modal', { portal: true })\n}\n```\n\n## Utility methods\n\nBecause collections are plain JavaScript classes, you can easily add utility\nmethods to your collections.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  input = this.el('#todo-input')\n  saveButton = this.el('#save-button')\n\n  async create(name: string) {\n    await this.input.fill(name)\n    await this.input.click()\n  }\n}\n\nconst todoPage = new TodoPage(page)\nawait todoPage.create('Finish the website')\n```\n\n## Nested collections\n\nSo far, we've shown examples of simple collections, but Lariat also gives you\nthe ability to nest collections inside each other. With this approach, you can\ncreate a page object structure that more closely resembles your page layout.\n\nTo nest a collection, use the `Collection.nest()` method and pass the nested\ncollection class and the root of the nested collection.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  field = this.nest(TextField, '#todo-field')\n}\n\nconst todoPage = new TodoPage(page)\nawait todoPage.field.input.fill('Finish the website')\n```\n\nIf your nested collection is used merely to group a set of related elements\ntogether, you can use the parent's `root` property as the root of the child\ncollection.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  field = this.nest(TextField, this.root)\n}\n```\n\nIf your nested collection exists outside the DOM structure of the parent\ncollection, you can use the parent's `frame` property as the root of the child\ncollection. This behaves very similarly to the `portal` option for\n`Collection.el()`.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  modal = this.nest(Modal, this.frame)\n}\n```\n\n### `first`, `last`, and `nth`\n\nIn some cases, you may have a nested collection where multiple instances exist\non the page. For example, a todo list may contain multiple todo items each of\nwhich are represented as a collection. To make these scenarios easier, Lariat\nprovides `first`, `last`, and `nth` methods which will return a new instance of\nthe nested collection scoped to that specific item.\n\n```ts\nclass TodoPage extends Collection\u003cPage\u003e {\n  item = this.nest(TodoItem, '.todo-item')\n}\n\nconst todoPage = new TodoPage(page)\nconst firstItem = todoPage.item.first()\nconst secondItem = todoPage.item.nth(1)\nconst lastItem = todoPage.item.last()\n```\n\n## Frames\n\nLariat has utilities for working with frames thanks to Playwright's\n[`FrameLocator`](https://playwright.dev/docs/api/class-framelocator).\n\nThe simplest way to access an element in a frame is by using the `frame` option\nof `Collection.el`. Simply pass a string as a selector for the frame and Lariat\nwill take care of the rest.\n\n```ts\nclass FramePage extends Collection\u003cPage\u003e {\n  frameHeader = this.el('h1', { frame: '#my-frame' })\n}\n```\n\nHowever, if you need to access multiple elements in a frame, you can use\n`Collection.nest` with a `FrameLocator`.\n\n```ts\nclass MyFrame extends Collection\u003cFrameLocator\u003e {\n  header = this.el('h1')\n  content = this.el('main')\n}\n\nclass FramePage extends Collection\u003cPage\u003e {\n  myFrame = this.nest(MyFrame, this.page.frameLocator('#my-frame'))\n}\n```\n\nYou can use a similar method to instantiate collections with a `FrameLocator` as\nthe root.\n\n```ts\nclass MyFrame extends Collection\u003cFrameLocator\u003e {\n  header = this.el('h1')\n  content = this.el('main')\n}\n\nnew MyFrame(page.frameLocator('#my-frame'))\n```\n\n## Accessing the page or frame\n\nLariat makes it easy to access the page or frame that a collection is associated\nwith.\n\n```ts\nclass TodoPage extends Collection {\n  input = this.el('#todo-input')\n}\n\nconst todoPage = new TodoPage(page.locator('#my-page'))\nawait todoPage.frame.goto('https://google.com')\nawait todoPage.page.mouse.down()\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flariat-js%2Fplaywright","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flariat-js%2Fplaywright","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flariat-js%2Fplaywright/lists"}