{"id":13651221,"url":"https://github.com/hdorgeval/playwright-fluent","last_synced_at":"2025-04-06T09:10:54.887Z","repository":{"id":39981035,"uuid":"237519718","full_name":"hdorgeval/playwright-fluent","owner":"hdorgeval","description":"Fluent API around playwright","archived":false,"fork":false,"pushed_at":"2023-08-14T19:53:25.000Z","size":7763,"stargazers_count":159,"open_issues_count":2,"forks_count":11,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-18T14:12:31.068Z","etag":null,"topics":["e2e","e2e-testing","fluent-api","playwright","playwright-api","playwright-fluent","test-automation","test-framework","test-runner","testing","testing-library"],"latest_commit_sha":null,"homepage":"","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/hdorgeval.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-01-31T21:32:50.000Z","updated_at":"2024-04-11T13:14:46.000Z","dependencies_parsed_at":"2024-01-03T05:48:19.219Z","dependency_job_id":null,"html_url":"https://github.com/hdorgeval/playwright-fluent","commit_stats":{"total_commits":1155,"total_committers":4,"mean_commits":288.75,"dds":"0.024242424242424288","last_synced_commit":"292b782bc53f87babd04ac23cd21856e322af0a6"},"previous_names":["hdorgeval/playwright-controller"],"tags_count":119,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hdorgeval%2Fplaywright-fluent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hdorgeval%2Fplaywright-fluent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hdorgeval%2Fplaywright-fluent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hdorgeval%2Fplaywright-fluent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hdorgeval","download_url":"https://codeload.github.com/hdorgeval/playwright-fluent/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457803,"owners_count":20941906,"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","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":["e2e","e2e-testing","fluent-api","playwright","playwright-api","playwright-fluent","test-automation","test-framework","test-runner","testing","testing-library"],"created_at":"2024-08-02T02:00:46.695Z","updated_at":"2025-04-06T09:10:54.865Z","avatar_url":"https://github.com/hdorgeval.png","language":"TypeScript","funding_links":[],"categories":["Utils","testing"],"sub_categories":[],"readme":"# playwright-fluent\r\n\r\nFluent API around [Playwright](https://github.com/microsoft/playwright)\r\n\r\n[![TestsPipeline](https://github.com/hdorgeval/playwright-fluent/actions/workflows/tests_pipeline.yml/badge.svg)](https://github.com/hdorgeval/playwright-fluent/actions/workflows/tests_pipeline.yml)\r\n[![Build status](https://ci.appveyor.com/api/projects/status/5gtetagv1onhhn7l?svg=true)](https://ci.appveyor.com/project/hdorgeval/playwright-fluent)\r\n[![npm version](https://img.shields.io/npm/v/playwright-fluent.svg)](https://www.npmjs.com/package/playwright-fluent)\r\n[![Mentioned in Awesome](https://awesome.re/mentioned-badge.svg)](https://awesome.re)\r\n\r\n###### [Fluent API](/docs/playwright-fluent.api.md) | [Selector API](/docs/selector.api.md) | [Assertion API](/docs/assertion.api.md) | [Mock API](/docs/mock.api.md) | [FAQ](#faq) | [with jest](https://github.com/hdorgeval/playwright-fluent-ts-jest-starter#playwright-fluent-ts-jest-starter) | [with cucumber-js v6](https://github.com/hdorgeval/playwright-fluent-ts-cucumber6-starter) | [with cucumber-js v7](https://github.com/hdorgeval/playwright-fluent-ts-cucumber7-starter)\r\n\r\n## Installation\r\n\r\n```sh\r\nnpm i --save playwright-fluent\r\n```\r\n\r\nIf not already installed, the `playwright` package should also be installed with a version \u003e= 1.12.0\r\n\r\n## Usage\r\n\r\n```js\r\nimport { PlaywrightFluent, userDownloadsDirectory } from 'playwright-fluent';\r\n\r\nconst p = new PlaywrightFluent();\r\n\r\nawait p\r\n  .withBrowser('chromium')\r\n  .withOptions({ headless: false })\r\n  .withCursor()\r\n  .withDialogs()\r\n  .recordPageErrors()\r\n  .recordFailedRequests()\r\n  .recordDownloadsTo(userDownloadsDirectory)\r\n  .emulateDevice('iPhone 6 landscape')\r\n  .navigateTo('https://reactstrap.github.io/components/form/')\r\n  .click('#exampleEmail')\r\n  .typeText('foo.bar@baz.com')\r\n  .pressKey('Tab')\r\n  .expectThatSelector('#examplePassword')\r\n  .hasFocus()\r\n  .typeText(\"don't tell!\")\r\n  .pressKey('Tab')\r\n  .expectThatSelector('#examplePassword')\r\n  .hasClass('is-valid')\r\n  .hover('#exampleCustomSelect')\r\n  .select('Value 3')\r\n  .in('#exampleCustomSelect')\r\n  .close();\r\n```\r\n\r\nThis package provides also a Selector API that enables to find and target a DOM element or a collection of DOM elements embedded in complex DOM Hierarchy:\r\n\r\n```js\r\nconst selector = p\r\n  .selector('[role=\"row\"]') // will get all dom elements, within the current page, with the attribute role=\"row\"\r\n  .withText('foobar') // will filter only those that contain the text 'foobar'\r\n  .find('td') // from previous result(s), find all embedded \u003ctd\u003e elements\r\n  .nth(2); // take only the second cell\r\n\r\nawait p.expectThat(selector).hasText('foobar-2');\r\n```\r\n\r\n## Usage with Iframes\r\n\r\nThis fluent API enables to seamlessly navigate inside an iframe and switch back to the page:\r\n\r\n```js\r\nconst p = new PlaywrightFluent();\r\nconst selector = 'iframe';\r\nconst inputInIframe = '#input-inside-iframe';\r\nconst inputInMainPage = '#input-in-main-page';\r\nawait p\r\n  .withBrowser('chromium')\r\n  .withOptions({ headless: false })\r\n  .withCursor()\r\n  .navigateTo(url)\r\n  .hover(selector)\r\n  .switchToIframe(selector)\r\n  .click(inputInIframe)\r\n  .typeText('hey I am in the iframe')\r\n  .switchBackToPage()\r\n  .click(inputInMainPage)\r\n  .typeText('hey I am back in the page!');\r\n```\r\n\r\n## Usage with Dialogs\r\n\r\nThis fluent API enables to handle `alert`, `prompt` and `confirm` dialogs:\r\n\r\n```js\r\nconst p = new PlaywrightFluent();\r\n\r\nawait p\r\n  .withBrowser(browser)\r\n  .withOptions({ headless: true })\r\n  .WithDialogs()\r\n  .navigateTo(url)\r\n  // do some stuff that will open a dialog\r\n  .waitForDialog()\r\n  .expectThatDialog()\r\n  .isOfType('prompt')\r\n  .expectThatDialog()\r\n  .hasMessage('Please say yes or no')\r\n  .expectThatDialog()\r\n  .hasValue('yes')\r\n  .typeTextInDialogAndSubmit('foobar');\r\n```\r\n\r\n## Usage with the tracing API\r\n\r\nThis fluent API enables to handle the `playwright` tracing API in the following way:\r\n\r\n```js\r\nconst p = new PlaywrightFluent();\r\n\r\nawait p\r\n  .withBrowser(browser)\r\n  .withOptions({ headless: true })\r\n  .withTracing()\r\n  .withCursor()\r\n  .startTracing({ title: 'my first trace' })\r\n  .navigateTo(url)\r\n  // do some stuff on the opened page\r\n  .stopTracingAndSaveTrace({ path: path.join(__dirname, 'trace1.zip') })\r\n  // do other stuff\r\n  .startTracing({ title: 'my second trace' })\r\n  // do other stuff\r\n  .stopTracingAndSaveTrace({ path: path.join(__dirname, 'trace2.zip') });\r\n```\r\n\r\n## Usage with collection of elements\r\n\r\nThis fluent API enables to perform actions and assertions on a collection of DOM elements with a `forEach()` operator.\r\n\r\nSee it below in action on `ag-grid` where all athletes with `Julia` in their name must be selected:\r\n\r\n![demo-for-each](images/demo-for-each.gif)\r\n\r\n```js\r\nconst p = new PlaywrightFluent();\r\n\r\nconst url = `https://www.ag-grid.com/javascript-data-grid/keyboard-navigation/`;\r\nconst cookiesConsentButton = p\r\n  .selector('#onetrust-button-group')\r\n  .find('button')\r\n  .withText('Accept All Cookies');\r\n\r\nconst gridContainer = 'div#myGrid';\r\nconst rowsContainer = 'div.ag-body-viewport div.ag-center-cols-container';\r\nconst rows = p.selector(gridContainer).find(rowsContainer).find('div[role=\"row\"]');\r\nconst filter = p.selector(gridContainer).find('input[aria-label=\"Athlete Filter Input\"]').parent();\r\n\r\nawait p\r\n  .withBrowser('chromium')\r\n  .withOptions({ headless: false })\r\n  .withCursor()\r\n  .navigateTo(url)\r\n  .click(cookiesConsentButton)\r\n  .switchToIframe('iframe[title=\"grid-keyboard-navigation\"]')\r\n  .hover(gridContainer)\r\n  .click(filter)\r\n  .typeText('Julia')\r\n  .pressKey('Enter')\r\n  .expectThat(rows.nth(1))\r\n  .hasText('Julia');\r\n\r\nawait rows.forEach(async (row) =\u003e {\r\n  const checkbox = row\r\n    .find('input')\r\n    .withAriaLabel('Press Space to toggle row selection (unchecked)')\r\n    .parent();\r\n  await p.click(checkbox);\r\n});\r\n```\r\n\r\n## Usage with Stories\r\n\r\nThis package provides a way to write tests as functional components called `Story`:\r\n\r\n`stories.ts`\r\n\r\n```js\r\nimport { Story, StoryWithProps } from 'playwright-fluent';\r\n\r\nexport interface StartAppProps {\r\n  browser: BrowserName;\r\n  isHeadless: boolean;\r\n  url: string;\r\n}\r\n\r\n// first story: start the App\r\nexport const startApp: StoryWithProps\u003cStartAppProps\u003e = async (p, props) =\u003e {\r\n  await p\r\n    .withBrowser(props.browser)\r\n    .withOptions({ headless: props.isHeadless })\r\n    .withCursor()\r\n    .navigateTo(props.url);\r\n}\r\n\r\n// second story: fill in the form\r\nexport const fillForm: Story = async (p) =\u003e {\r\n  await p\r\n    .click(selector)\r\n    .select(option)\r\n    .in(customSelect)\r\n    ...;\r\n};\r\n\r\n// threrd story: submit form\r\nexport const submitForm: Story = async (p) =\u003e {\r\n  await p\r\n    .click(selector);\r\n};\r\n\r\n// fourth story: assert\r\nexport const elementIsVisible: Story = async (p) =\u003e {\r\n  await p\r\n    .expectThatSelector(selector)\r\n    .isVisible();\r\n};\r\n```\r\n\r\n`test.ts`\r\n\r\n```js\r\nimport { startApp, fillForm } from 'stories';\r\nimport { PlaywrightFluent } from 'playwright-fluent';\r\nconst p = new PlaywrightFluent();\r\n\r\nawait p\r\n  .runStory(startApp, { browser: 'chrome', isHeadless: false, url: 'http://example.com' })\r\n  .runStory(fillForm)\r\n  .close();\r\n\r\n// Also methods synonyms are available to achieve better readability\r\nconst user = new PlaywrightFluent();\r\nawait user\r\n  .do(startApp, { browser: 'chrome', isHeadless: false, url: 'http://example.com' })\r\n  .and(fillForm)\r\n  .attemptsTo(submitForm)\r\n  .verifyIf(elementIsVisible)\r\n  .close();\r\n```\r\n\r\n## Usage with mocks\r\n\r\nThis fluent API provides a generic and simple infrastructure for massive request interception and response mocking.\r\n\r\nThis Mock API leverages the `Playwright` request interception infrastructure and will enable you to mock all HTTP requests in order to test the front in complete isolation from the backend.\r\n\r\n[Read more about the Fluent Mock API](./docs/mock.api.md)\r\n\r\nThis API is still a draft and is in early development, but stay tuned!\r\n\r\n## Contributing\r\n\r\nCheck out our [contributing guide](./CONTRIBUTING.md).\r\n\r\n## Resources\r\n\r\n- [Playwright Fluent API documentation](/docs/playwright-fluent.api.md)\r\n- [Selector API documentation](/docs/selector.api.md)\r\n- [Assertion API documentation](/docs/assertion.api.md)\r\n- [Mock API documentation](/docs/mock.api.md)\r\n\r\n## FAQ\r\n\r\n### Q: How does playwright-fluent relate to [Playwright](https://github.com/microsoft/playwright)?\r\n\r\n`playwright-fluent` is just a wrapper around the Playwright API.\r\nIt leverages the power of Playwright by giving a Fluent API, that enables to consume the Playwright API with chainable actions and assertions.\r\nThe purpose of `playwright-fluent` is to be able to write e2e tests in a way that makes tests more readable, reusable and maintainable.\r\n\r\n### Q: Can I start using playwright-fluent in my existing code base?\r\n\r\nYes you can.\r\n\r\n```js\r\nimport { PlaywrightFluent } from 'playwright-fluent';\r\n\r\n// just create a new instance with playwright's browser and page instances\r\nconst p = new PlaywrightFluent(browser, page);\r\n\r\n// you can also create a new instance with playwright's browser and frame instances\r\nconst p = new PlaywrightFluent(browser, frame);\r\n\r\n// now you can use the fluent API\r\n```\r\n\r\n### Q: Can I use Playwright together with the playwright-fluent?\r\n\r\nYes you can. To use the Playwright API, call the `currentBrowser()` and/or `currentPage()` methods exposed by the fluent API:\r\n\r\n```js\r\nconst browser = 'chromium';\r\nconst p = new PlaywrightFluent();\r\nawait p\r\n  .withBrowser(browser)\r\n  .emulateDevice('iPhone 6 landscape')\r\n  .withCursor()\r\n  .navigateTo('https://reactstrap.github.io/components/form/')\r\n  ...;\r\n\r\n// now if you want to use the playwright API from this point:\r\nconst browser = p.currentBrowser();\r\nconst page = p.currentPage();\r\n\r\n// the browser and page objects are standard playwright objects\r\n// so now you are ready to go by using the playwright API\r\n```\r\n\r\n### Q: What can I do with the currently published npm package playwright-fluent?\r\n\r\nThe documentations:\r\n\r\n- [Playwright Fluent API documentation](/docs/playwright-fluent.api.md)\r\n- [Selector API documentation](/docs/selector.api.md)\r\n- [Assertion API documentation](/docs/assertion.api.md)\r\n- [Mock API documentation](/docs/mock.api.md)\r\n\r\nreflect the current status of the development and are inline with the published package.\r\n\r\n### Q: Do you have some samples on how to use this library?\r\n\r\nYes, have a look to this [demo project with jest](https://github.com/hdorgeval/playwright-fluent-ts-jest-starter#playwright-fluent-ts-jest-starter), this [demo project with cucumber-js v6](https://github.com/hdorgeval/playwright-fluent-ts-cucumber6-starter) or this [demo project with cucumber-js v7](https://github.com/hdorgeval/playwright-fluent-ts-cucumber7-starter).\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhdorgeval%2Fplaywright-fluent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhdorgeval%2Fplaywright-fluent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhdorgeval%2Fplaywright-fluent/lists"}