Skip to content

Commit

Permalink
Merge pull request #163 from pactflow/add_playwright
Browse files Browse the repository at this point in the history
feat: add details of playwright adapter demo
  • Loading branch information
YOU54F authored Oct 28, 2022
2 parents dd0fbcf + 60adb46 commit 40acf0e
Show file tree
Hide file tree
Showing 24 changed files with 7,451 additions and 7,692 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/sync-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ on:
- pactflow-example-bi-directional-consumer-cypress-updated
- pactflow-example-bi-directional-consumer-mountebank-updated
- pactflow-example-bi-directional-consumer-msw-js-updated
- pactflow-example-bi-directional-consumer-playwright-js-updated
- pactflow-example-bi-directional-consumer-dotnet-updated
- pactflow-example-bi-directional-provider-dredd-updated
- pactflow-example-bi-directional-provider-postman-updated
Expand Down Expand Up @@ -171,6 +172,10 @@ jobs:
run: bundle exec scripts/sync/example_consumer_bidirectional_nock.rb && echo 'COMMIT_MESSAGE="synced example_consumer_bidirectional_nock docs"' >> $GITHUB_ENV
if: github.event.action == 'pactflow-example-bi-directional-consumer-nock-updated'

- name: Sync example_consumer_bidirectional_playwright_js docs
run: bundle exec scripts/sync/example_consumer_bidirectional_playwright_js.rb && echo 'COMMIT_MESSAGE="synced example_consumer_bidirectional_playwright_js docs"' >> $GITHUB_ENV
if: github.event.action == 'pactflow-example-bi-directional-consumer-playwright-js-updated'

- name: Commit and push changes
uses: EndBug/add-and-commit@v4
with:
Expand Down
28 changes: 28 additions & 0 deletions scripts/sync/example_consumer_bidirectional_playwright_js.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env ruby

require 'octokit'
require 'base64'
require 'fileutils'
require 'pathname'
require_relative 'support'

SOURCE_REPO = 'pactflow/example-bi-directional-consumer-playwright-js'.freeze
DESTINATION_DIR = relative_path_to('website/docs/docs/examples/bi-directional/consumer/playwright_js')
TRANSFORM_PATH = ->(path) { File.join(DESTINATION_DIR, path.downcase) }
INCLUDE = [
->(path) { %w[README.md].include?(path) }
].freeze
IGNORE = [].freeze

CUSTOM_ACTIONS = [
[:all, lambda { |md_file_contents|
md_file_contents.enable_headers
md_file_contents.extract_title
md_file_contents.fields[:sidebar_label] = md_file_contents.fields[:title]
md_file_contents.add_lines_at_start("## Source Code\n\nhttps://github.com/#{SOURCE_REPO}\n")
}]
].freeze

FileUtils.mkdir_p DESTINATION_DIR

sync(SOURCE_REPO, INCLUDE, IGNORE, TRANSFORM_PATH, CUSTOM_ACTIONS, 'main')
1 change: 1 addition & 0 deletions website/docs/docs/bi-directional-contract-testing/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The following are adapters for common tools that provide a mocking capability th
| Mock Service Worker (MSW) | Convert MSW HTTP mocks into consumer contracts | [link](./tools/msw) |
| Wiremock (Java) | Convert Wiremock Java mocks into consumer contracts) | [link](./tools/wiremock) |
| Wiremock (.NET) | Convert Wiremock .NET mocks into consumer contracts | [link](./tools/wiremock-net) |
| Playwright | Convert Playwright routes into consumer contracts - beta, example shown | [link](/docs/examples/bi-directional/consumer/playwright_js/) |

## Can't find what you're looking for?

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
custom_edit_url: https://github.com/pactflow/example-bi-directional-consumer-playwright-js/edit/main/README.md
title: Example NodeJS/React Consumer - playwright (BYO Adapter)
sidebar_label: Example NodeJS/React Consumer - playwright (BYO Adapter)
---

<!-- This file has been synced from the pactflow/example-bi-directional-consumer-playwright-js repository. Please do not edit it directly. The URL of the source file can be found in the custom_edit_url value above -->

## Source Code

https://github.com/pactflow/example-bi-directional-consumer-playwright-js


[![Build](https://github.com/pactflow/example-bi-directional-consumer-playwright-js/actions/workflows/build.yml/badge.svg)](https://github.com/pactflow/example-bi-directional-consumer-playwright-js/actions/workflows/build.yml)

[![Can I deploy Status](https://testdemo.pactflow.io/pacticipants/pactflow-example-bi-directional-consumer-playwright-js/branches/main/latest-version/can-i-deploy/to-environment/production/badge)](https://testdemo.pactflow.io/pacticipants/pactflow-example-bi-directional-consumer-playwright-js/branches/main/latest-version/can-i-deploy/to-environment/production/badge)

- [Example NodeJS/React Consumer - playwright (BYO Adapter)](#example-nodejsreact-consumer---playwright-byo-adapter)
- [Overview of Example](#overview-of-example)
- [Key points with playwright](#key-points-with-playwright)
- [Overview of Part of Bi-Directional Contract Testing Flow](#overview-of-part-of-bi-directional-contract-testing-flow)
- [Compatibile with Providers](#compatibile-with-providers)
- [Pre-requisites](#pre-requisites)
- [Environment variables](#environment-variables)
- [Usage](#usage)
- [Steps](#steps)
- [OS/Platform specific considerations](#osplatform-specific-considerations)
- [Caveats](#caveats)
- [Related topics / posts / discussions](#related-topics--posts--discussions)
- [Other examples of how to do this form of testing](#other-examples-of-how-to-do-this-form-of-testing)
- [Found an issue?](#found-an-issue)

## Overview of Example

<!-- Consumer Overview -->

This is an example of a React "Product" API consumer that uses playwright & [Pactflow](https://pactflow.io) and GitHub Actions to generate and publish Pact consumer contracts.

It performs pre-deployment cross-compatibility checks to ensure that it is compatible with specified providers using the Bi-Directional contract capability of Pactflow.

<!-- General -->

See the full [Pactflow Bi-Directional Workshop](https://docs.pactflow.io/docs/workshops/bi-directional-contract-testing) for which this can be substituted in as the "consumer".

### Key points with playwright

It:

- It a React app implementing a "Product" website created with Create React App
- It utilises playwright to functionally test the website
- It utilises a small helper file to cover playwright routes into pact interactions

## Overview of Part of Bi-Directional Contract Testing Flow

<!-- Consumer Overview -->

In the following diagram, You can see how the consumer testing process works - it's the same as the current Pact process.

When we call "can-i-deploy" the cross-contract validation process kicks off on Pactflow, to ensure any consumer consumes a valid subset of the OAS for the provider.

![Consumer Test](https://raw.githubusercontent.com/pactflow/example-bi-directional-consumer-playwright-js/main/docs/consumer-scope.png)

The project uses a Makefile to simulate a very simple build pipeline with two stages - test and deploy.

When you run the CI pipeline (see below for doing this), the pipeline should perform the following activities (simplified):

- Test
- Run tests (including the pact tests that generate the contract)
- Publish pacts, tagging the consumer version with the name of the current branch
- Check if we are safe to deploy to Production with `can-i-deploy` (ie. has the cross-contract validation has been successfully performed)
- Deploy (only from <main|master>)
- Deploy app to Production
- Record the Production deployment in the Pact Broker

![Consumer Pipeline](https://raw.githubusercontent.com/pactflow/example-bi-directional-consumer-playwright-js/main/docs./../docs/consumer-pipeline.png)

## Compatibile with Providers

<!-- Provider Compatability -->

This project is currently compatible with the following provider(s):

- [pactflow-example-bi-directional-provider-dredd](https://github.com/pactflow/example-bi-directional-provider-dredd)
- [pactflow-example-bi-directional-provider-restassured](https://github.com/pactflow/example-provider-restassured)
- [pactflow-example-bi-directional-provider-postman](https://github.com/pactflow/example-bi-directional-provider-postman)
<!-- * [pactflow-example-bi-directional-provider-dotnet](https://github.com/pactflow/example-bi-directional-provider-dotnet) -->

See [Environment variables](#environment-variables) on how to set these up.

## Pre-requisites

**Software**:

- Tools listed at: https://docs.pactflow.io/docs/workshops/ci-cd/set-up-ci/prerequisites/
- A pactflow.io account with an valid [API token](https://docs.pactflow.io/docs/getting-started/#configuring-your-api-token)

### Environment variables

To be able to run some of the commands locally, you will need to export the following environment variables into your shell:

- `PACT_BROKER_TOKEN`: a valid [API token](https://docs.pactflow.io/docs/getting-started/#configuring-your-api-token) for Pactflow
- `PACT_BROKER_BASE_URL`: a fully qualified domain name with protocol to your pact broker e.g. https://testdemo.pactflow.io

<!-- CONSUMER env vars -->

Set `PACT_PROVIDER` to one of the following

- `PACT_PROVIDER=pactflow-example-bi-directional-provider-dredd`: Dredd - (https://github.com/pactflow/example-bi-directional-provider-dredd)
- `PACT_PROVIDER=pactflow-example-bi-directional-provider-postman`: Postman - (https://github.com/pactflow/example-bi-directional-provider-postman)
- `PACT_PROVIDER=pactflow-example-bi-directional-provider-restassured`: Rest Assured - (https://github.com/pactflow/example-bi-directional-provider-restassured)

## Usage

### Steps

NOTE: playwright tests are located in `./playwright/integration`. See below for how to start playwright test, generate consumer contract and publish contract to pactflow.

- `make install` - install project dependencies

Run each step separately

- `make test_and_publish` - tests the provider and publishes provider contracts to Pactflow
- This will perform the following 2 calls
- `make test`
- `make publish_provider_contract`
- `make can_i_deploy` - runs can-i-deploy to check if its safe to deploy the provider
- `make deploy` - deploys the app and records deployment

or run the whole lot in one go

- `make ci` - run the CI process, but locally (uses Docker by default)

Installing alternate pact CLI tools.

If you don't have docker, you can use one of the ruby tools. The standalone, doesn't require that you install Ruby on your host machine.

- `make install-pact-ruby-cli` - installs the pact ruby CLI tool
- `make install-pact-ruby-standalone` - installs the pact standalone CLI depending on your platform
- `make uninstall-pact-ruby-standalone` - uninstalls the pact standalone CLI

Using alternate pact CLI tools.

- `PACT_TOOL=docker make ci` - run the CI process, using the pact Docker CLI tool
- `PACT_TOOL=ruby_standalone make ci` - run the CI process, using the pact standalone CLI tool
- `PACT_TOOL=ruby_cli make ci` - run the CI process, using the pact ruby CLI tool

\_How to use Playwright

- Spin up the ui project by running `npm run start`
- Run your playwright tests with `npm run test`

Look at one of the tests `test/productByQuery.spec.js`

1. Import `transformPlaywrightMatchToPact` from `test/playwrightSerialiser.js`
2. add `transformPlaywrightMatchToPact` function call into your playwright [route](https://playwright.dev/docs/api/class-page#page-route)

```js
const { transformPlaywrightMatchToPact } = require('./playwrightSerialiser')

await page.route(productApiPath + '/products?id=2', async (route) => {
const response = {
status: 200,
body: JSON.stringify(testData),
headers: {
'Content-Type': 'application/json'
}
}
route.fulfill(response)
const pacticipant = 'pactflow-example-bi-directional-consumer-playwright-js'
const provider = process.env.PACT_PROVIDER || 'pactflow-example-bi-directional-provider-dredd'
await transformPlaywrightMatchToPact(route, { pacticipant, provider })
return
})
```

## OS/Platform specific considerations

The makefile has been configured to run on Unix/Windows and MacOS based systems, and tested against Github Actions

They can be run locally on Unix/Windows and MacOS, or on Windows via [WSL2](https://docs.microsoft.com/en-us/windows/wsl/install) or a shell with bash.

## Caveats

- [OAS considerations](https://docs.pactflow.io/docs/bi-directional-contract-testing/contracts/oas#considerations)

## Related topics / posts / discussions

- [Consumer Side Bi-Directional Contract Testing Guide](https://docs.pactflow.io/docs/bi-directional-contract-testing/consumer)
- [Provider Side Bi-Directional Contract Testing Guide](https://docs.pactflow.io/docs/bi-directional-contract-testing/provider)

## Other examples of how to do this form of testing

- TBC

## Found an issue?

Reach out via a GitHub Issue, or reach us over in the [Pact foundation Slack](https://slack.pact.io)
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-table": "^7.7.0",
"redocusaurus": "^1.0.2"
"redocusaurus": "^1.4.0"
},
"devDependencies": {
"improved-yarn-audit": "^2.3.2"
Expand Down
1 change: 1 addition & 0 deletions website/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ module.exports = {
'docs/examples/bi-directional/consumer/cypress/readme',
'docs/examples/bi-directional/consumer/mountebank/readme',
'docs/examples/bi-directional/consumer/msw/readme',
'docs/examples/bi-directional/consumer/playwright_js/readme',
'docs/examples/bi-directional/consumer/dotnet/readme',
'docs/examples/bi-directional/provider/readyapi/readme',
'docs/examples/bi-directional/provider/soapui/readme',
Expand Down
6 changes: 2 additions & 4 deletions website/src/components/tabGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,9 @@ function generateLanguageTab({ data, withLabel, withLink, useCaseFilter }) {
)
.map((tr) => {
return (
<>
<li>
<a href={tr.linkUrl}>{tr.linkTitle}</a>
<li key={tr.linkTitle + "language_link" + Math.random()}>
<a href={tr.linkUrl}>{tr.linkTitle}</a>
</li>
</>
);
})}
</div>
Expand Down
29 changes: 28 additions & 1 deletion website/src/data/examples.table.js
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,33 @@ export const tableData = [
}
]
},
{
linkTitle:
'React JavaScript Website using Playwright routes and custom pact adapter to generate Pact contracts',
linkUrl: '/docs/examples/bi-directional/consumer/playwright_js',
badges: [],
language: 'JavaScript',
useCase: 'OpenAPI',
side: 'Consumer',
compatible_clients: [
{
name: 'Example Bi-Directional Provider Dredd',
link: '/docs/examples/bi-directional/provider/dredd/'
},
{
name: 'Example Bi-Directional Provider Postman',
link: '/docs/examples/bi-directional/provider/postman/'
},
{
name: 'Example Bi-Directional Provider RestAssured',
link: '/docs/examples/bi-directional/provider/restassured/'
},
{
name: 'Example Provider',
link: '/docs/examples/js/provider'
}
]
},
{
linkTitle:
'React JavaScript Website using Cypress fixtures and pact-cypress-adapter to generate Pact contracts',
Expand Down Expand Up @@ -645,7 +672,7 @@ export const columns = [
const compatible_clients = original.compatible_clients;
if (!compatible_clients) return '';
return compatible_clients.map((w) => (
<li>
<li key={w.link + original.linkTitle + Math.random()}>
<a href={w.link}>{w.name}</a>
</li>
));
Expand Down
18 changes: 16 additions & 2 deletions website/src/data/icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const label_with_link_mountebank = generateIconWithLabel(
);
const label_with_link_pact = generateIconWithLabel(meta.testing_tools['pact']);
const label_with_link_msw = generateIconWithLabel(meta.testing_tools['msw']);
const label_with_link_playwright_js = generateIconWithLabel(meta.testing_tools['playwright_js']);
const label_postman = generateIconWithLabel({
...meta.testing_tools['postman'],
iconLink: undefined
Expand Down Expand Up @@ -82,6 +83,10 @@ const label_msw = generateIconWithLabel({
...meta.testing_tools['msw'],
iconLink: undefined
});
const label_playwright_js = generateIconWithLabel({
...meta.testing_tools['playwright_js'],
iconLink: undefined
});
const icon_with_link_postman = generateIcon(meta.testing_tools['postman']);
const icon_with_link_restassured = generateIcon(
meta.testing_tools['restassured']
Expand All @@ -100,6 +105,7 @@ const icon_with_link_mountebank = generateIcon(
);
const icon_with_link_pact = generateIcon(meta.testing_tools['pact']);
const icon_with_link_msw = generateIcon(meta.testing_tools['msw']);
const icon_with_link_playwright_js = generateIcon(meta.testing_tools['playwright_js']);
const icon_postman = generateIcon({
...meta.testing_tools['postman'],
iconLink: undefined
Expand Down Expand Up @@ -148,6 +154,10 @@ const icon_msw = generateIcon({
...meta.testing_tools['msw'],
iconLink: undefined
});
const icon_playwright_js = generateIcon({
...meta.testing_tools['playwright_js'],
iconLink: undefined
});

const label_with_link_javascript = generateIconWithLabel(meta.languages['js']);
const label_with_link_java = generateIconWithLabel(meta.languages['java']);
Expand Down Expand Up @@ -355,6 +365,7 @@ const testingToolIconsWithLabels = {
label_with_link_mountebank,
label_with_link_pact,
label_with_link_msw,
label_with_link_playwright_js,
label_postman,
label_restassured,
label_readyapi,
Expand All @@ -366,7 +377,8 @@ const testingToolIconsWithLabels = {
label_nock,
label_mountebank,
label_pact,
label_msw
label_msw,
label_playwright_js
};
const testingToolIcons = {
icon_with_link_postman,
Expand All @@ -381,6 +393,7 @@ const testingToolIcons = {
icon_with_link_mountebank,
icon_with_link_pact,
icon_with_link_msw,
icon_with_link_playwright_js,
icon_postman,
icon_restassured,
icon_readyapi,
Expand All @@ -392,5 +405,6 @@ const testingToolIcons = {
icon_nock,
icon_mountebank,
icon_pact,
icon_msw
icon_msw,
icon_playwright_js
};
Loading

0 comments on commit 40acf0e

Please sign in to comment.