Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/hdorgeval/playwright-fluent

Fluent API around playwright
https://github.com/hdorgeval/playwright-fluent

e2e e2e-testing fluent-api playwright playwright-api playwright-fluent test-automation test-framework test-runner testing testing-library

Last synced: 30 days ago
JSON representation

Fluent API around playwright

Awesome Lists containing this project

README

        

# playwright-fluent

Fluent API around [Playwright](https://github.com/microsoft/playwright)

[![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)
[![Build status](https://ci.appveyor.com/api/projects/status/5gtetagv1onhhn7l?svg=true)](https://ci.appveyor.com/project/hdorgeval/playwright-fluent)
[![npm version](https://img.shields.io/npm/v/playwright-fluent.svg)](https://www.npmjs.com/package/playwright-fluent)
[![Mentioned in Awesome](https://awesome.re/mentioned-badge.svg)](https://awesome.re)

###### [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)

## Installation

```sh
npm i --save playwright-fluent
```

If not already installed, the `playwright` package should also be installed with a version >= 1.12.0

## Usage

```js
import { PlaywrightFluent, userDownloadsDirectory } from 'playwright-fluent';

const p = new PlaywrightFluent();

await p
.withBrowser('chromium')
.withOptions({ headless: false })
.withCursor()
.withDialogs()
.recordPageErrors()
.recordFailedRequests()
.recordDownloadsTo(userDownloadsDirectory)
.emulateDevice('iPhone 6 landscape')
.navigateTo('https://reactstrap.github.io/components/form/')
.click('#exampleEmail')
.typeText('[email protected]')
.pressKey('Tab')
.expectThatSelector('#examplePassword')
.hasFocus()
.typeText("don't tell!")
.pressKey('Tab')
.expectThatSelector('#examplePassword')
.hasClass('is-valid')
.hover('#exampleCustomSelect')
.select('Value 3')
.in('#exampleCustomSelect')
.close();
```

This 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:

```js
const selector = p
.selector('[role="row"]') // will get all dom elements, within the current page, with the attribute role="row"
.withText('foobar') // will filter only those that contain the text 'foobar'
.find('td') // from previous result(s), find all embedded elements
.nth(2); // take only the second cell

await p.expectThat(selector).hasText('foobar-2');
```

## Usage with Iframes

This fluent API enables to seamlessly navigate inside an iframe and switch back to the page:

```js
const p = new PlaywrightFluent();
const selector = 'iframe';
const inputInIframe = '#input-inside-iframe';
const inputInMainPage = '#input-in-main-page';
await p
.withBrowser('chromium')
.withOptions({ headless: false })
.withCursor()
.navigateTo(url)
.hover(selector)
.switchToIframe(selector)
.click(inputInIframe)
.typeText('hey I am in the iframe')
.switchBackToPage()
.click(inputInMainPage)
.typeText('hey I am back in the page!');
```

## Usage with Dialogs

This fluent API enables to handle `alert`, `prompt` and `confirm` dialogs:

```js
const p = new PlaywrightFluent();

await p
.withBrowser(browser)
.withOptions({ headless: true })
.WithDialogs()
.navigateTo(url)
// do some stuff that will open a dialog
.waitForDialog()
.expectThatDialog()
.isOfType('prompt')
.expectThatDialog()
.hasMessage('Please say yes or no')
.expectThatDialog()
.hasValue('yes')
.typeTextInDialogAndSubmit('foobar');
```

## Usage with the tracing API

This fluent API enables to handle the `playwright` tracing API in the following way:

```js
const p = new PlaywrightFluent();

await p
.withBrowser(browser)
.withOptions({ headless: true })
.withTracing()
.withCursor()
.startTracing({ title: 'my first trace' })
.navigateTo(url)
// do some stuff on the opened page
.stopTracingAndSaveTrace({ path: path.join(__dirname, 'trace1.zip') })
// do other stuff
.startTracing({ title: 'my second trace' })
// do other stuff
.stopTracingAndSaveTrace({ path: path.join(__dirname, 'trace2.zip') });
```

## Usage with collection of elements

This fluent API enables to perform actions and assertions on a collection of DOM elements with a `forEach()` operator.

See it below in action on `ag-grid` where all athletes with `Julia` in their name must be selected:

![demo-for-each](images/demo-for-each.gif)

```js
const p = new PlaywrightFluent();

const url = `https://www.ag-grid.com/javascript-data-grid/keyboard-navigation/`;
const cookiesConsentButton = p
.selector('#onetrust-button-group')
.find('button')
.withText('Accept All Cookies');

const gridContainer = 'div#myGrid';
const rowsContainer = 'div.ag-body-viewport div.ag-center-cols-container';
const rows = p.selector(gridContainer).find(rowsContainer).find('div[role="row"]');
const filter = p.selector(gridContainer).find('input[aria-label="Athlete Filter Input"]').parent();

await p
.withBrowser('chromium')
.withOptions({ headless: false })
.withCursor()
.navigateTo(url)
.click(cookiesConsentButton)
.switchToIframe('iframe[title="grid-keyboard-navigation"]')
.hover(gridContainer)
.click(filter)
.typeText('Julia')
.pressKey('Enter')
.expectThat(rows.nth(1))
.hasText('Julia');

await rows.forEach(async (row) => {
const checkbox = row
.find('input')
.withAriaLabel('Press Space to toggle row selection (unchecked)')
.parent();
await p.click(checkbox);
});
```

## Usage with Stories

This package provides a way to write tests as functional components called `Story`:

`stories.ts`

```js
import { Story, StoryWithProps } from 'playwright-fluent';

export interface StartAppProps {
browser: BrowserName;
isHeadless: boolean;
url: string;
}

// first story: start the App
export const startApp: StoryWithProps = async (p, props) => {
await p
.withBrowser(props.browser)
.withOptions({ headless: props.isHeadless })
.withCursor()
.navigateTo(props.url);
}

// second story: fill in the form
export const fillForm: Story = async (p) => {
await p
.click(selector)
.select(option)
.in(customSelect)
...;
};

// threrd story: submit form
export const submitForm: Story = async (p) => {
await p
.click(selector);
};

// fourth story: assert
export const elementIsVisible: Story = async (p) => {
await p
.expectThatSelector(selector)
.isVisible();
};
```

`test.ts`

```js
import { startApp, fillForm } from 'stories';
import { PlaywrightFluent } from 'playwright-fluent';
const p = new PlaywrightFluent();

await p
.runStory(startApp, { browser: 'chrome', isHeadless: false, url: 'http://example.com' })
.runStory(fillForm)
.close();

// Also methods synonyms are available to achieve better readability
const user = new PlaywrightFluent();
await user
.do(startApp, { browser: 'chrome', isHeadless: false, url: 'http://example.com' })
.and(fillForm)
.attemptsTo(submitForm)
.verifyIf(elementIsVisible)
.close();
```

## Usage with mocks

This fluent API provides a generic and simple infrastructure for massive request interception and response mocking.

This 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.

[Read more about the Fluent Mock API](./docs/mock.api.md)

This API is still a draft and is in early development, but stay tuned!

## Contributing

Check out our [contributing guide](./CONTRIBUTING.md).

## Resources

- [Playwright Fluent API documentation](/docs/playwright-fluent.api.md)
- [Selector API documentation](/docs/selector.api.md)
- [Assertion API documentation](/docs/assertion.api.md)
- [Mock API documentation](/docs/mock.api.md)

## FAQ

### Q: How does playwright-fluent relate to [Playwright](https://github.com/microsoft/playwright)?

`playwright-fluent` is just a wrapper around the Playwright API.
It leverages the power of Playwright by giving a Fluent API, that enables to consume the Playwright API with chainable actions and assertions.
The purpose of `playwright-fluent` is to be able to write e2e tests in a way that makes tests more readable, reusable and maintainable.

### Q: Can I start using playwright-fluent in my existing code base?

Yes you can.

```js
import { PlaywrightFluent } from 'playwright-fluent';

// just create a new instance with playwright's browser and page instances
const p = new PlaywrightFluent(browser, page);

// you can also create a new instance with playwright's browser and frame instances
const p = new PlaywrightFluent(browser, frame);

// now you can use the fluent API
```

### Q: Can I use Playwright together with the playwright-fluent?

Yes you can. To use the Playwright API, call the `currentBrowser()` and/or `currentPage()` methods exposed by the fluent API:

```js
const browser = 'chromium';
const p = new PlaywrightFluent();
await p
.withBrowser(browser)
.emulateDevice('iPhone 6 landscape')
.withCursor()
.navigateTo('https://reactstrap.github.io/components/form/')
...;

// now if you want to use the playwright API from this point:
const browser = p.currentBrowser();
const page = p.currentPage();

// the browser and page objects are standard playwright objects
// so now you are ready to go by using the playwright API
```

### Q: What can I do with the currently published npm package playwright-fluent?

The documentations:

- [Playwright Fluent API documentation](/docs/playwright-fluent.api.md)
- [Selector API documentation](/docs/selector.api.md)
- [Assertion API documentation](/docs/assertion.api.md)
- [Mock API documentation](/docs/mock.api.md)

reflect the current status of the development and are inline with the published package.

### Q: Do you have some samples on how to use this library?

Yes, 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).