Skip to content

Commit ae9c4ca

Browse files
committed
Resolve merge conflicts
2 parents d05405e + 4955d78 commit ae9c4ca

File tree

9 files changed

+593
-1
lines changed

9 files changed

+593
-1
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
CMSSHOPIFYCONFIG__SHOPIFYURL: ${{ secrets.SHOPIFY_URL }}
4747
CMSSHOPIFYCONFIG__STOREFRONTAPIKEY: ${{ secrets.STOREFRONT_API_KEY }}
4848
CMSSHOPIFYCONFIG__STOREFRONTAPIVERSION: ${{ secrets.STOREFRONT_API_VERSION }}
49+
CMSSHOPIFYCONFIG__STOREPASSWORD: ${{ secrets.SHOPIFY_STORE_PASSWORD }}
4950
XPERIENCE_BY_KENTICO_LICENSE: eyJEYXRhIjoie1x1MDAyMnRpZXJcdTAwMjI6XHUwMDIyQWR2YW5jZWRcdTAwMjIsXHUwMDIybGljZW5zZVx1MDAyMjpudWxsLFx1MDAyMmxpbWl0YXRpb25zXHUwMDIyOntcdTAwMjJjaGFubmVsc1x1MDAyMjo1LFx1MDAyMm1pY3JvQ2hhbm5lbHNcdTAwMjI6NX0sXHUwMDIya2V5XHUwMDIyOntcdTAwMjJpZFx1MDAyMjpcdTAwMjJlZjdmZTczZC1mNzI4LTQzOTYtOTQ3MS0yZGFhOTlkM2NlOWZcdTAwMjIsXHUwMDIydmVyc2lvblx1MDAyMjpcdTAwMjIxXHUwMDIyLFx1MDAyMmlzc3VlZERhdGVVdGNcdTAwMjI6XHUwMDIyMjAyNC0xMC0yMVQxMjoxMzo1My42NDA3NDczWlx1MDAyMixcdTAwMjJleHBpcmF0aW9uRGF0ZVV0Y1x1MDAyMjpcdTAwMjIyMDI1LTEwLTIwVDEyOjExOjAwWlx1MDAyMixcdTAwMjJ0eXBlXHUwMDIyOlx1MDAyMkRldmVsb3BtZW50XHUwMDIyLFx1MDAyMm5hbWVcdTAwMjI6XHUwMDIyS0VOVElDT19HSF9hY3Rpb25zXHUwMDIyLFx1MDAyMnN5bmNocm9uaXphdGlvblx1MDAyMjp0cnVlfX0iLCJTaWduYXR1cmUiOiJKRlhieTEwSjlTeDR6ZWFjZzR1YldSS3BSMldsOWlJXHUwMDJCWVZ2ZXNnN1BSeEE0ZGhIbXk3XHUwMDJCaXVtbk1JRXpKZmpQWGU1bC9cdTAwMkJMbjFOcXZTcVBDY0NaWjdaM1M1OFVKd3ZoWVdqVzI4ckRFL3FNaVNIM1M4V2lPYXd4anVUZ1Y2UmlaZDNNemloTEFFMFkxR1JUbDRodFlLOUFUZEpmQXk4NXFcdTAwMkJnVmJZaGpzc3dSaWttNzcwVm1jVWEvLzZSOFlYQ3hRMVJBTkZ4OU1sZlQxeVpQckl3UkhcdTAwMkJNaEFsUGN2b1RiTHNpNTRURW5LcTVSOTlIVGNTRkJcdTAwMkJ3VnBkNGF0bFRoVjZVM1hLQXV4Z2g4YjRcdTAwMkJiRnZ0L1o3UnFUZUY1bVx1MDAyQkJPdnFocWZyd1J4VnBER1dYaVQ4aXNTdjRpbTVXbjBHWXFmR3JHSXdcdTAwMkJOU3k5aW92NEw4VlVPOWM3cFE9PSJ9
5051

5152
steps:
@@ -58,6 +59,18 @@ jobs:
5859
with:
5960
global-json-file: global.json
6061

62+
- name: Setup Node
63+
uses: actions/setup-node@v4
64+
with:
65+
node-version: lts/*
66+
67+
- name: Install NPM
68+
run: |
69+
cd test/Playwright
70+
npm ci
71+
npx playwright install --with-deps
72+
cd ../..
73+
6174
- name: Install dependencies
6275
run: |
6376
dotnet restore `
@@ -166,9 +179,22 @@ jobs:
166179
exit 1
167180
}
168181
169-
# TODO: Run the E2E tests
182+
# Sleep for finishing initialization
183+
Start-Sleep -Seconds 10
184+
185+
# Run the E2E tests
186+
cd test/Playwright
187+
npx playwright test
188+
cd ../..
170189
171190
# Stop the background ASP.NET Core application
172191
Receive-Job -Name ${{ env.PROJECT_NAME }}
173192
Stop-Job -Name ${{ env.PROJECT_NAME }}
174193
Remove-Job -Name ${{ env.PROJECT_NAME }}
194+
195+
- uses: actions/upload-artifact@v4
196+
if: ${{ !cancelled() }}
197+
with:
198+
name: playwright-report
199+
path: ./test/Playwright/playwright-report/
200+
retention-days: 30

test/Playwright/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
/test-results/
3+
/playwright-report/
4+
/blob-report/
5+
/playwright/.cache/

test/Playwright/README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Playwright E2E tests
2+
3+
## Description
4+
5+
E2E tests are implemented using Playwright - an open-source, NodeJS-based framework for web testing and automation.
6+
7+
To prevent false-positives, tests are configured to run maximum of 2 times based on the result of the 1st test. Following combinations apply.
8+
9+
- test PASSES the 1st run -> Test **PASSED**
10+
- test FAILS the 1st run, retries and PASSES the 2nd run -> Test **PASSED** with **FLAKY** signature
11+
- test FAILS the 1st, retries and FAILS the 2nd run -> Test **FAILED**
12+
13+
## Install dependencies
14+
15+
`npm i`
16+
17+
`npx playwright install --with-deps`
18+
19+
## Run tests
20+
21+
Following env variables are expected to be set
22+
23+
- ASPNETCORE_URLS = Base url of the app
24+
- CMSSHOPIFYCONFIG\_\_ADMINAPIKEY = Shopify API access token
25+
- CMSSHOPIFYCONFIG\_\_SHOPIFYURL = Shopify store URL
26+
- CMSSHOPIFYCONFIG\_\_STOREPASSWORD = Shopify store password
27+
28+
Run the tests with command
29+
30+
`npx playwright test`
31+
32+
## Test results
33+
34+
Test results are generated whether the tests pass or fail.
35+
36+
#### HTML
37+
38+
HTML test result can be opened using
39+
40+
`npx playwright show-report`
41+
42+
#### JUnit
43+
44+
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`
45+
46+
#### Artifacts
47+
48+
In case of a test failure, following artifacts are created
49+
50+
- Screenshot of the last application state (point of failure) - generates on every fail
51+
- Video of full test run - generates on every fail
52+
- Trace - generates on first retry
53+
54+
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.
55+
56+
To open local Trace Viewer use
57+
58+
`npx playwright show-trace path/to/trace.zip`
59+
60+
Hosted variant by Playwright can be found at
61+
62+
[trace.playwright.dev](https://trace.playwright.dev/)

test/Playwright/package-lock.json

Lines changed: 97 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/Playwright/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "playwright",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {},
6+
"keywords": [],
7+
"author": "",
8+
"license": "ISC",
9+
"description": "",
10+
"devDependencies": {
11+
"@playwright/test": "^1.48.2",
12+
"@types/node": "^22.9.0"
13+
}
14+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { type Locator, type Page } from "@playwright/test";
2+
3+
export class BasePage {
4+
readonly page: Page;
5+
6+
constructor(page: Page) {
7+
this.page = page;
8+
}
9+
10+
async goto(url: string) {
11+
await this.page.goto(url);
12+
await this.fullyLoadPage();
13+
}
14+
async fullyLoadPage() {
15+
await this.page.evaluate(() =>
16+
document.querySelectorAll("img[loading=lazy]").forEach((img) => img.setAttribute("loading", "eager"))
17+
);
18+
19+
await this.page.evaluate(async () => {
20+
await new Promise((resolve) => {
21+
let totalHeight = 0;
22+
const distance = 200;
23+
const timer = setInterval(() => {
24+
var scrollHeight = document.body.scrollHeight;
25+
window.scrollBy(0, distance);
26+
totalHeight += distance;
27+
if (totalHeight >= scrollHeight - window.innerHeight) {
28+
clearInterval(timer);
29+
resolve(void 0);
30+
}
31+
}, 70);
32+
});
33+
window.scrollTo(0, 0);
34+
});
35+
}
36+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { type Locator, type Page } from "@playwright/test";
2+
import { BasePage } from "./BasePage";
3+
4+
export class CheckoutPage extends BasePage {
5+
readonly $firstName: Locator;
6+
readonly $lastName: Locator;
7+
readonly $email: Locator;
8+
readonly $address: Locator;
9+
readonly $city: Locator;
10+
readonly $psc: Locator;
11+
readonly $country: Locator;
12+
readonly $shippingMethods: Locator;
13+
readonly $cardNumber: Locator;
14+
readonly $cardExpirationDate: Locator;
15+
readonly $cardSecurityCode: Locator;
16+
readonly $payBtn: Locator;
17+
18+
constructor(page: Page) {
19+
super(page);
20+
21+
this.$firstName = page.locator('#TextField0[name="firstName"]');
22+
this.$lastName = page.locator('#TextField1[name="lastName"]');
23+
this.$email = page.locator('input[name="email"]');
24+
this.$address = page.locator('#TextField2[name="address1"]');
25+
this.$city = page.locator('#TextField5[name="city"]');
26+
this.$psc = page.locator('#TextField4[name="postalCode"]');
27+
this.$country = page.locator('select[name="countryCode"]');
28+
this.$shippingMethods = page.locator("#shipping_methods");
29+
this.$cardNumber = page
30+
.frameLocator('iframe[title="Field container for: Card number"]')
31+
.getByPlaceholder("Card number");
32+
this.$cardExpirationDate = page
33+
.frameLocator('iframe[title="Field container for: Expiration date (MM / YY)"]')
34+
.getByPlaceholder("Expiration date (MM / YY)");
35+
this.$cardSecurityCode = page
36+
.frameLocator('iframe[title="Field container for: Security code"]')
37+
.getByPlaceholder("Security code");
38+
this.$payBtn = page.locator("#checkout-pay-button");
39+
}
40+
41+
async fillCustomerDetails(details) {
42+
await this.$firstName.fill(details.firstName);
43+
await this.$lastName.fill(details.lastName);
44+
await this.$email.fill(details.email);
45+
await this.$address.fill(details.address);
46+
await this.$psc.fill(details.psc);
47+
await this.$city.fill(details.city);
48+
await this.$country.selectOption({ label: details.country });
49+
}
50+
async selectShipping(shipping) {
51+
await this.$shippingMethods.locator("label", { hasText: shipping }).click();
52+
}
53+
async fillPayment(payment) {
54+
await this.$cardNumber.fill(payment.cardNumber);
55+
await this.$cardExpirationDate.fill(payment.cardExpirationDate);
56+
await this.$cardSecurityCode.fill(payment.cardSecurityCode);
57+
}
58+
async confirmOrder() {
59+
await this.$payBtn.click();
60+
}
61+
}

0 commit comments

Comments
 (0)