generated from Kentico/repo-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
E2E tests with associated ci.yml changes
- Loading branch information
1 parent
74fe7d5
commit ac6a483
Showing
9 changed files
with
592 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules/ | ||
/test-results/ | ||
/playwright-report/ | ||
/blob-report/ | ||
/playwright/.cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Playwright E2E tests | ||
|
||
## Description | ||
|
||
E2E tests are implemented using Playwright - an open-source, NodeJS-based framework for web testing and automation. | ||
|
||
To prevent false-positives, tests are configured to run maximum of 2 times based on the result of the 1st test. Following combinations apply. | ||
|
||
- test PASSES the 1st run -> Test **PASSED** | ||
- test FAILS the 1st run, retries and PASSES the 2nd run -> Test **PASSED** with **FLAKY** signature | ||
- test FAILS the 1st, retries and FAILS the 2nd run -> Test **FAILED** | ||
|
||
## Install dependencies | ||
|
||
`npm i` | ||
|
||
`npx playwright install --with-deps` | ||
|
||
## Run tests | ||
|
||
Following env variables are expected to be set | ||
|
||
- ASPNETCORE_URLS = Base url of the app | ||
- CMSSHOPIFYCONFIG\_\_ADMINAPIKEY = Shopify API access token | ||
- CMSSHOPIFYCONFIG\_\_SHOPIFYURL = Shopify store URL | ||
- CMSSHOPIFYCONFIG\_\_STOREPASSWORD = Shopify store password | ||
|
||
Run the tests with command | ||
|
||
`npx playwright test` | ||
|
||
## Test results | ||
|
||
Test results are generated whether the tests pass or fail. | ||
|
||
#### HTML | ||
|
||
HTML test result can be opened using | ||
|
||
`npx playwright show-report` | ||
|
||
#### JUnit | ||
|
||
Test results are generated also in JUnit format, for possible integration with other reporting systems. XML file can be found in `test-results/e2e-junit-results.xml` | ||
|
||
#### Artifacts | ||
|
||
In case of a test failure, following artifacts are created | ||
|
||
- Screenshot of the last application state (point of failure) - generates on every fail | ||
- Video of full test run - generates on every fail | ||
- Trace - generates on first retry | ||
|
||
Trace contains enhanced information to ease debugging failures. It can be opened with Trace Viewer (GUI tool) locally or using hosted variant by Playwright where it is possible to upload trace files using drag and drop. | ||
|
||
To open local Trace Viewer use | ||
|
||
`npx playwright show-trace path/to/trace.zip` | ||
|
||
Hosted variant by Playwright can be found at | ||
|
||
[trace.playwright.dev](https://trace.playwright.dev/) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "playwright", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"scripts": {}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"description": "", | ||
"devDependencies": { | ||
"@playwright/test": "^1.48.2", | ||
"@types/node": "^22.9.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { type Locator, type Page } from "@playwright/test"; | ||
|
||
export class BasePage { | ||
readonly page: Page; | ||
|
||
constructor(page: Page) { | ||
this.page = page; | ||
} | ||
|
||
async goto(url: string) { | ||
await this.page.goto(url); | ||
await this.fullyLoadPage(); | ||
} | ||
async fullyLoadPage() { | ||
await this.page.evaluate(() => | ||
document.querySelectorAll("img[loading=lazy]").forEach((img) => img.setAttribute("loading", "eager")) | ||
); | ||
|
||
await this.page.evaluate(async () => { | ||
await new Promise((resolve) => { | ||
let totalHeight = 0; | ||
const distance = 200; | ||
const timer = setInterval(() => { | ||
var scrollHeight = document.body.scrollHeight; | ||
window.scrollBy(0, distance); | ||
totalHeight += distance; | ||
if (totalHeight >= scrollHeight - window.innerHeight) { | ||
clearInterval(timer); | ||
resolve(void 0); | ||
} | ||
}, 70); | ||
}); | ||
window.scrollTo(0, 0); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { type Locator, type Page } from "@playwright/test"; | ||
import { BasePage } from "./BasePage"; | ||
|
||
export class CheckoutPage extends BasePage { | ||
readonly $firstName: Locator; | ||
readonly $lastName: Locator; | ||
readonly $email: Locator; | ||
readonly $address: Locator; | ||
readonly $city: Locator; | ||
readonly $psc: Locator; | ||
readonly $country: Locator; | ||
readonly $shippingMethods: Locator; | ||
readonly $cardNumber: Locator; | ||
readonly $cardExpirationDate: Locator; | ||
readonly $cardSecurityCode: Locator; | ||
readonly $payBtn: Locator; | ||
|
||
constructor(page: Page) { | ||
super(page); | ||
|
||
this.$firstName = page.locator('#TextField0[name="firstName"]'); | ||
this.$lastName = page.locator('#TextField1[name="lastName"]'); | ||
this.$email = page.locator('input[name="email"]'); | ||
this.$address = page.locator('#TextField2[name="address1"]'); | ||
this.$city = page.locator('#TextField5[name="city"]'); | ||
this.$psc = page.locator('#TextField4[name="postalCode"]'); | ||
this.$country = page.locator('select[name="countryCode"]'); | ||
this.$shippingMethods = page.locator("#shipping_methods"); | ||
this.$cardNumber = page | ||
.frameLocator('iframe[title="Field container for: Card number"]') | ||
.getByPlaceholder("Card number"); | ||
this.$cardExpirationDate = page | ||
.frameLocator('iframe[title="Field container for: Expiration date (MM / YY)"]') | ||
.getByPlaceholder("Expiration date (MM / YY)"); | ||
this.$cardSecurityCode = page | ||
.frameLocator('iframe[title="Field container for: Security code"]') | ||
.getByPlaceholder("Security code"); | ||
this.$payBtn = page.locator("#checkout-pay-button"); | ||
} | ||
|
||
async fillCustomerDetails(details) { | ||
await this.$firstName.fill(details.firstName); | ||
await this.$lastName.fill(details.lastName); | ||
await this.$email.fill(details.email); | ||
await this.$address.fill(details.address); | ||
await this.$psc.fill(details.psc); | ||
await this.$city.fill(details.city); | ||
await this.$country.selectOption({ label: details.country }); | ||
} | ||
async selectShipping(shipping) { | ||
await this.$shippingMethods.locator("label", { hasText: shipping }).click(); | ||
} | ||
async fillPayment(payment) { | ||
await this.$cardNumber.fill(payment.cardNumber); | ||
await this.$cardExpirationDate.fill(payment.cardExpirationDate); | ||
await this.$cardSecurityCode.fill(payment.cardSecurityCode); | ||
} | ||
async confirmOrder() { | ||
await this.$payBtn.click(); | ||
} | ||
} |
Oops, something went wrong.