Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
dc6d400
test: centralise locators and refactor tests
KrupaPammi Apr 29, 2026
e9062b1
test: add test that's been removed
KrupaPammi Apr 29, 2026
6a524f7
test: write first test in cucumber
KrupaPammi Apr 30, 2026
5bb625d
test: convert submit dir tests into Gherkin and add step definitions
KrupaPammi May 1, 2026
4004a8a
test: convert /update tests into Gherkin and add step-definitions
KrupaPammi May 5, 2026
d2b564d
test: Add comments in cucumber config
KrupaPammi May 5, 2026
6c97779
test: disable local playwright reports and test-results that generate…
KrupaPammi May 7, 2026
fd17063
test: move shard redirect step into comon step-definitions
KrupaPammi May 8, 2026
f195111
test: setup and convert playwright-local tests into cucumber
KrupaPammi May 12, 2026
ae0d8a7
ci: Add retry and parallel options in the config
KrupaPammi May 12, 2026
69e5750
ci: update playwright run with cucumber script
KrupaPammi May 12, 2026
65a24df
test: Add mobile safari config and parallel scripts
KrupaPammi May 12, 2026
9c22095
test: fix marketing prefs step by adding scrollingintoview
KrupaPammi May 12, 2026
3edd445
test: few tweaks
KrupaPammi May 12, 2026
dd18155
test: fix failing staging tests locally
KrupaPammi May 13, 2026
a7e3b1b
test: resolve ambiguous steps
KrupaPammi May 14, 2026
f0a2b5c
test: fix campaign code from RND26 to SR26
KrupaPammi May 14, 2026
4769a96
test: remove nightly-sanity tag
KrupaPammi May 14, 2026
bbb00de
use consistent kebab casing
KrupaPammi May 14, 2026
06a398a
config: add playwright equivalent timeouts in cucumber config
KrupaPammi May 14, 2026
051336b
move browserstack capabilities into cucumber config
KrupaPammi May 14, 2026
b3125f6
keep the test script as before
KrupaPammi May 14, 2026
1968a49
test: add default navigation timeout
KrupaPammi May 19, 2026
7637a84
downgrade cucumber version to 8.9.1 to support node 16
KrupaPammi May 19, 2026
01353cc
test: move resuable steps into giftaid common
KrupaPammi May 19, 2026
db2969f
test: delete giftaid submission steps file as it's moved to common
KrupaPammi May 19, 2026
b545fc7
test: update transsource value to SR26_GiftAid
KrupaPammi May 19, 2026
65b48d4
test: fix missing update validation step definition; populateUpdateFo…
KrupaPammi May 19, 2026
9dafdd1
add comments in playwright-local config
KrupaPammi May 19, 2026
78bc781
test: move selectors to locators file
KrupaPammi May 20, 2026
fbf2563
test: remove playwright.config files
KrupaPammi May 20, 2026
a173f53
remove local playwright.config file; fix casing
KrupaPammi May 20, 2026
4c6c051
Merge remote-tracking branch 'origin/master' into test/eng-5100-playw…
KrupaPammi May 20, 2026
6e86b81
remove playwright scripts
KrupaPammi May 20, 2026
24c2b21
remove FORCE_COLOR from the local cucumber scripts
KrupaPammi May 20, 2026
f5be6b8
use only 2 parallel workers in playwright-local tests
KrupaPammi May 20, 2026
ec1b5c8
test: move local Playwright selectors into centralized locators file
KrupaPammi May 22, 2026
323c3c2
test: refactor methods to use shared this.page instance
KrupaPammi May 22, 2026
cf006f4
test: remove duplicate local thank you submission step
KrupaPammi May 22, 2026
a1a481b
ci: remove duplicated scripts; remove sanity tags and name from the s…
KrupaPammi May 22, 2026
90c9445
docs: update README with new local Cucumber and staging test steps
KrupaPammi May 22, 2026
5ac4344
test: reorder and group Given, When, thens in step def files
KrupaPammi May 27, 2026
55722f2
test: add cucumber config typing for IntelliSense purpose
KrupaPammi May 27, 2026
8e14b6d
test: fix local MP helper method to select Text/SMS option
KrupaPammi May 27, 2026
605803d
test: use fill instead of type
KrupaPammi May 27, 2026
636ea8b
test: add missing letter T in the file name
KrupaPammi May 27, 2026
0a7a4ab
test: increase timeout for the thank you message to appear
KrupaPammi Jun 4, 2026
547c5db
test: test: enable Playwright video recording in CI for Cucumber tests
KrupaPammi Jun 4, 2026
4269040
test: add Playwright video and trace artifacts for failed Cucumber sc…
KrupaPammi Jun 4, 2026
ae391bd
test: update playwright artifacts comment
KrupaPammi Jun 5, 2026
e40fbc0
ci: change artifacts path from directory paths
KrupaPammi Jun 5, 2026
68b3831
ci: save failed videos after browser context closes
KrupaPammi Jun 5, 2026
5c6b7c6
ci: save chromuim failed videos after browser context closes
KrupaPammi Jun 5, 2026
29c040b
ci: debug Playwright artifact upload step
KrupaPammi Jun 5, 2026
fc2f684
ci: move the debug steop
KrupaPammi Jun 5, 2026
dab8db0
clean up debug steps for artifacts
KrupaPammi Jun 5, 2026
a8f81f6
test: remove unspported delay option from fill()
KrupaPammi Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,27 @@ jobs:
- name: Install playwright browsers
run: yarn playwright install chromium

- name: Run Playwright Chrome Tests
run: yarn test:playwright-local:ci:chromium
- name: Run Cucumber Giftaid Sanity Tests
run: yarn test:ci:chromium
continue-on-error: false
env:
NODE_ENV: development
REACT_APP_ENDPOINT_URL: ${{ secrets.REACT_APP_ENDPOINT_URL }}
FORCE_COLOR: 1

# Test run video was always captured, so this action uses "always()" condition
- name: Upload videos
- name: List Playwright artifacts
if: failure()
run: find playwright-local/test-results -type f || true

# Upload Playwright video and trace artifacts for failed scenarios only
- name: playwright-chromium-artifacts
if: failure()
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
name: playwright-failure-artifacts-chromium
path: |
playwright-local/test-results/failed-videos/**/*.webm
playwright-local/test-results/traces/**/*.zip
retention-days: 3

playwright-mobile:
Expand Down Expand Up @@ -85,21 +91,27 @@ jobs:
- name: Install playwright browsers (WebKit)
run: yarn playwright install webkit

- name: Run Mobile WebKit Tests
run: yarn test:playwright-local:ci:mobile
- name: Run Mobile Cucumber Tests
run: yarn test:ci:mobile
continue-on-error: false
env:
NODE_ENV: development
REACT_APP_ENDPOINT_URL: ${{ secrets.REACT_APP_ENDPOINT_URL }}
FORCE_COLOR: 1

# Test run video was always captured, so this action uses "always()" condition
- name: Upload videos
- name: List Playwright artifacts
if: failure()
run: find playwright-local/test-results -type f || true

# Upload Playwright video and trace artifacts for failed scenarios only
- name: playwright-mobile-artifacts
if: failure()
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
name: playwright-failure-artifacts-mobile
path: |
playwright-local/test-results/failed-videos/**/*.webm
playwright-local/test-results/traces/**/*.zip
retention-days: 3

lint:
Expand Down
104 changes: 87 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,36 +67,106 @@ The domains for giftaid are as follows

## Testing

### Playwright-Local Tests
### Playwright-Local Cucumber Tests

To run PR Playwright Tests locally (after running `yarn playwright install` if you haven't previously), you need to first export `REACT_APP_ENDPOINT_URL=https://giftaid-sandbox.sls.comicrelief.com/` in your terminal for the form to get submitted and then run the script `test:playwright-local:local` found in package.json; this script starts the http://localhost:3000 server in the background, config for this is found in `playwright-local/playwright-local.config.js` file and runs the tests in headless mode.
Local end-to-end tests use:
- Cucumber
- Playwright
- Chromium and Mobile Safari
- A locally running React app on `http://localhost:3000`

To view a test in a _headed_ mode locally, use the according command; `test:playwright-local--h`.
### Start the local server

To run a single test, add `only` annotation
Before running the tests locally, start the React app:

eg: test.only('Valid giftaid submission', async ({ page }) => {
});

### Staging Playwright Tests
```bash
yarn start
```
This starts the application on: http://localhost:3000

### Running Local Tests

Run all local tests:

```bash
yarn test:local
```

Run Chromium tests:

```bash
yarn test:local:chromium
```

Run Mobile Safari tests:

```bash
yarn test:local:mobile
```

### Run Tests in Headed Mode

Run Chromium in headed mode:

```bash
yarn test:local:chromium:headed
```

Run Mobile Safari in headed mode:

```bash
yarn test:local:mobile:headed
```

### Run Specific Tests by Tag

Example:

```bash
yarn test:local --tags "@valid-giftaid-submission"
```

Run address validation tests:

```bash
yarn test:local --tags "@address-validation"
```

### Local Test Structure

```text
playwright-local/
├── tests/features
├── tests/step-definitions
├── tests/support
└── tests/utils
```

- Feature files contain readable Gherkin scenarios using the `.feature` extension
- Step definitions contain the Playwright automation implementation
- Hooks create a fresh browser context and page for every scenario
- Shared selectors are stored in `utils/locators.js`
- Shared reusable helper methods are stored in `utils/commands.js`

### Staging BrowserStack Tests

Staging tests run against BrowserStack and require the following environment variables:

In order to run Playwright end-to-end tests locally you need to change directory to playwright folder `cd playwright` and export the following environment variables to your terminal:`BASE_URL, BROWSERSTACK_ACCESS_KEY, BROWSERSTACK_USERNAME`
Browserstack credentials can be found in https://github.com/comicrelief/serverless-giftaid/blob/master/concourse/private.yml
```bash
export BASE_URL='https://giftaid-staging.comicrelief.com/'
export BROWSERSTACK_USERNAME='<INSERT_USERNAME>'
export BROWSERSTACK_ACCESS_KEY='<INSERT_ACCESS_KEY>'
```
### Running tests

To run spa-feature-test or nightly-test-sanity, check the commands in playwright/package.json eg: `yarn test:sanity`
BrowserStack credentials can be found in:

```text
serverless-giftaid/concourse/private.yml
```

To run a single test, add `only` annotation
### Running Staging Tests

eg: test.only('submit form with valid inputs', async ({ page }) => {
});

Check serverless-giftaid in order to get the right values and then you can run the test executing:
Run staging tests:

```bash
yarn test:sanity
Expand Down
17 changes: 8 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,13 @@
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"lint": "eslint --color src",
"test:playwright-local:local": "playwright test --config=./playwright-local/playwright-local.config.js",
"test:playwright-local:local:chromium": "playwright test --config=./playwright-local/playwright-local.config.js --project=chromium",
"test:playwright-local:local:chromium--h": "playwright test --config=./playwright-local/playwright-local.config.js --project=chromium --headed",
"test:playwright-local:local:mobile": "playwright test --config=./playwright-local/playwright-local.config.js --project=mobile-safari",
"test:playwright-local:local:mobile--h": "playwright test --config=./playwright-local/playwright-local.config.js --project=mobile-safari --headed",
"test:playwright-local:ci": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:playwright-local",
"test:playwright-local:ci:chromium": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:playwright-local:local:chromium",
"test:playwright-local:ci:mobile": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:playwright-local:local:mobile",
"test:playwright-local:local:chrome:mobile": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:playwright-local:local",
"test:local": "cd playwright-local && BASE_URL=http://localhost:3000 cucumber-js --config config/cucumber.js",
"test:local:chromium": "cd playwright-local && BROWSER=chromium BASE_URL=http://localhost:3000 cucumber-js --config config/cucumber.js",
"test:local:chromium:headed": "cd playwright-local && BROWSER=chromium HEADED=true BASE_URL=http://localhost:3000 cucumber-js --config config/cucumber.js",
"test:local:mobile": "cd playwright-local && BROWSER=mobile-safari BASE_URL=http://localhost:3000 cucumber-js --config config/cucumber.js",
"test:local:mobile:headed": "cd playwright-local && BROWSER=mobile-safari HEADED=true BASE_URL=http://localhost:3000 cucumber-js --config config/cucumber.js",
"test:ci:chromium": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:local:chromium",
"test:ci:mobile": "export NODE_ENV=development; start-server-and-test start http://localhost:3000 test:local:mobile",
"snyk-protect": "snyk-protect",
"prepublish": "yarn snyk-protect"
},
Expand All @@ -59,6 +57,7 @@
"@babel/runtime": "^7.11.2",
"@comicrelief/data-models": "^1.15.4",
"@comicrelief/test-utils": "^1.5.13",
"@cucumber/cucumber": "8.9.1",
"@playwright/test": "1.38.1",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
Expand Down
16 changes: 16 additions & 0 deletions playwright-local/config/cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/** @type {Partial<import('@cucumber/cucumber').IConfiguration>} */
module.exports = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cucumber provides a type for its configuration. I suggest we make use of it for IntelliSense purposes:

/** @type {Partial<import('@cucumber/cucumber').IConfiguration>} */
module.exports = { ... }

default: {
paths: ['tests/features/**/*.feature'],
require: [
'tests/support/**/*.js',
'tests/step-definitions/**/*.js',
],
// Use 'pretty' locally for readable step-by-step output.
// On CI keep the output minimal to avoid noisy logs.
format: ['progress', 'summary'],
retry: 2, // Retry failed scenarios twice
parallel: 2, // Run scenarios in parallel workers
publishQuiet: true, // Hide the default Cucumber report publishing link (we check on Github actions)
},
};
60 changes: 0 additions & 60 deletions playwright-local/playwright-local.config.js

This file was deleted.

43 changes: 43 additions & 0 deletions playwright-local/tests/features/submit/addressValidation.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
@address-validation
Feature: Address validation

Background:
Given I am on the local Giftaid page
And I select the local Giftaid option
And I enter the local supporter details

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that stands out to me, having each of these test scenarios now written in a natural language style, is the importance of making sure that the language chosen is clear and unambiguous. From a technical side, I'm guessing each step name can be pretty much any string, so long as it's unique, as in any other test runner.

So two questions really on that point:

  • Every step in this feature file contains the word "local". I started off looking at the postcode test, and thought "okay, local postcode, that's the postcode of the area where the supporter lives". Then I realised everything was "local", even in some places where this doesn't make sense in natural language, e.g. what does "local supporter details" mean? Presumably this is a convention you've followed within the playwright-local directory, but my question is, is there a technical reason for it, e.g. conflicts between names in these tests and the staging tests?

    If not, I'd recommend omitting "local", as it reduces clarity. Or, if there is a technical need for it, perhaps rename each step to "locally I do something".

  • More generally, do you know of any guidance or standard on how to give our steps good names?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point @seb-cr,

On the first point:

I did try removing local, but because we have both playwright-local and playwright-staging suites with similar scenarios, PhpStorm shows multiple matching step definitions when navigating from the feature file. The reason I added local was mainly to make the steps unique and avoid accidentally updating the staging step definitions instead of the local ones. I agree it reads a bit less naturally, but I thought it would help avoid confusion while both suites exist. What would you suggest here?

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the second point: I mostly followed what the Cucumber docs mention around step organisation here: https://cucumber.io/docs/gherkin/step-organization/

So far, I’ve removed duplicate/ambiguous step definitions and moved common ones into shared files. I’ve also only kept steps that are actually used in feature files and added reusable scenario outlines for repeated validation cases. As Giftaid is a fairly small app, I haven't run into many issues yet, apart from the local/staging overlap mentioned above. But, as and when I work on react-payments, I may find more areas where we need clearer conventions.


Scenario: Empty postcode should show an error message
When I clear the local postcode field
And I submit the local Giftaid form
Then I should see the local postcode error message "Please enter your postcode"

Scenario Outline: Invalid postcodes should show error messages
When I enter the local postcode "<postcode>"
Then I should see the local postcode error message "<message>"

Examples:
| postcode | message |
| 12SE17TP | Please enter a valid UK postcode, using a space. For non-UK addresses, please use manual entry below. |
| comic relief | Please enter a valid UK postcode, using a space. For non-UK addresses, please use manual entry below. |
| cro 7tp | Please enter a valid UK postcode, using a space. For non-UK addresses, please use manual entry below. |

Scenario: Entering a postcode without selecting an address should show an error message
When I enter the local postcode "E1 8QS"
And I search for the local postcode
Then I should see the local address dropdown
When I submit the local Giftaid form
Then I should see the local address select error message "Please select your address"

Scenario: Clicking the manual address link should show the address fields
When I enter the local postcode "E1 8QS"
Then I should see the local manual address link
When I click the local manual address link
Then I should see the local manual address fields

Scenario: Invalid address fields should show error messages
When I enter the local postcode "E1 8QS"
And I click the local manual address link
And I enter the local invalid address line 1
Then I should see the local address line 1 error message
When I enter the local invalid town
Then I should see the local town error message
Loading
Loading