-
Notifications
You must be signed in to change notification settings - Fork 82
tests(e2e): vendor Elgentos Playwright E2E test suite #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
digitalrisedorset
wants to merge
6
commits into
mage-os:main
Choose a base branch
from
digitalrisedorset:ci/tests-e2e-playwright-elgentos-hyva
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
b868259
tests(e2e): vendor Elgentos Playwright E2E test suite
0651fff
Removed failing tests to deliver a codebase with 100% passing tests
993b1d6
Merge branch 'mage-os:main' into ci/tests-e2e-playwright-elgentos-hyva
digitalrisedorset 0ec6073
fix: skip .env generation when running in CI
544a67d
fix(e2e): synchronize package-lock.json with dependencies
5741d44
feat(e2e): add GitHub and HTML Playwright reporters
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,19 @@ | ||
| PLAYWRIGHT_BASE_URL=https://hyva-demo.elgentos.io/ | ||
| PLAYWRIGHT_PRODUCTION_URL=https://hyva-demo.elgentos.io/ | ||
| PLAYWRIGHT_REVIEW_URL=https://hyva-demo.elgentos.io/ | ||
|
|
||
| MAGENTO_ADMIN_SLUG= | ||
| MAGENTO_ADMIN_USERNAME= | ||
| MAGENTO_ADMIN_PASSWORD= | ||
|
|
||
| MAGENTO_THEME_LOCALE= | ||
| MAGENTO_NEW_ACCOUNT_PASSWORD= | ||
| MAGENTO_EXISTING_ACCOUNT_EMAIL_CHROMIUM= | ||
| MAGENTO_EXISTING_ACCOUNT_EMAIL_FIREFOX= | ||
| MAGENTO_EXISTING_ACCOUNT_EMAIL_WEBKIT= | ||
| MAGENTO_EXISTING_ACCOUNT_PASSWORD= | ||
| MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD= | ||
|
|
||
| MAGENTO_COUPON_CODE_CHROMIUM= | ||
| MAGENTO_COUPON_CODE_FIREFOX= | ||
| MAGENTO_COUPON_CODE_WEBKIT= | ||
This file contains hidden or 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,4 @@ | ||
| { | ||
| "cookies": [], | ||
| "origins": [] | ||
| } |
This file contains hidden or 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,4 @@ | ||
| { | ||
| "cookies": [], | ||
| "origins": [] | ||
| } |
This file contains hidden or 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,4 @@ | ||
| { | ||
| "cookies": [], | ||
| "origins": [] | ||
| } |
This file contains hidden or 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,273 @@ | ||
| // @ts-check | ||
|
|
||
| /** | ||
| * Copyright Elgentos. All rights reserved. | ||
| * https://elgentos.nl/ | ||
| * | ||
| * @fileoverview Various tests to check account functionality. | ||
| */ | ||
|
|
||
| // Import test and expect from utils to ensure authenticated state. | ||
| import { test, expect } from '@utils/fixtures.utils'; | ||
| import { faker } from '@faker-js/faker'; | ||
|
|
||
| import AccountPage from '@poms/frontend/account.page'; | ||
| import LoginPage from '@poms/frontend/login.page'; | ||
| import NewsletterSubscriptionPage from '@poms/frontend/newsletter.page'; | ||
|
|
||
| import { requireEnv } from '@utils/env.utils'; | ||
| import ApiClient from '@utils/apiClient.utils'; | ||
| import { UIReference, outcomeMarker, slugs, inputValues} from '@config'; | ||
|
|
||
| /** | ||
| * Test group: User credentials tests | ||
| */ | ||
| test.describe('User credentials tests (API-provisioned)', { annotation: | ||
| {type: 'Account Dashboard', description: 'Test for changing credentials using API-provisioned account'}, }, () => { | ||
|
|
||
| let apiClient: ApiClient; | ||
|
|
||
| // Ensure we don't use an authenticated state. | ||
| test.use({ storageState: { cookies: [], origins: [] } }); | ||
|
|
||
| test.beforeAll(async () => { | ||
| apiClient = await new ApiClient().create(); | ||
| }); | ||
|
|
||
| test.afterAll(async () => { | ||
| await apiClient.dispose(); | ||
| }); | ||
|
|
||
| /** | ||
| * Test: User changes their password | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| * @param request - APIRequestContext instance used to create accounts with the API. | ||
| */ | ||
| test('Change_password', { tag: ['@account-credentials', '@hot'] }, async ({ page, request }) => { | ||
| const accountPage = new AccountPage(page); | ||
| const loginPage = new LoginPage(page); | ||
|
|
||
| const parallelIndex = test.info().parallelIndex; | ||
| const email = `playwright_pwtest_${parallelIndex}@elgentos.nl`; | ||
| const password = requireEnv('MAGENTO_EXISTING_ACCOUNT_PASSWORD'); | ||
| const changedPassword = requireEnv('MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD'); | ||
|
|
||
| // Ensure a fresh account exists with the original password | ||
| const searchResponse = await apiClient.get( | ||
| `/rest/V1/customers/search` + | ||
| `?searchCriteria[filterGroups][0][filters][0][field]=email` + | ||
| `&searchCriteria[filterGroups][0][filters][0][value]=${email}` + | ||
| `&searchCriteria[filterGroups][0][filters][0][conditionType]=eq` | ||
| ); | ||
|
|
||
| if (searchResponse.items?.length > 0) { | ||
| await apiClient.delete(`/rest/V1/customers/${searchResponse.items[0].id}`); | ||
| } | ||
|
|
||
| await apiClient.post('/rest/V1/customers', { | ||
| customer: { | ||
| email, | ||
| firstname: inputValues.account.firstName, | ||
| lastname: inputValues.account.lastName, | ||
| }, | ||
| password, | ||
| }); | ||
|
|
||
| // Login and change password via UI | ||
| await loginPage.login(email, password); | ||
| await page.goto(slugs.account.changePasswordSlug, { waitUntil: 'load' }); | ||
| await expect(page.getByRole('textbox', { name: UIReference.credentials.currentPasswordFieldLabel })).toBeVisible(); | ||
| await accountPage.updatePassword(password, changedPassword); | ||
|
|
||
| // Verify the new password works via API | ||
| const tokenResponse = await request.post('/rest/V1/integration/customer/token', { | ||
| data: { username: email, password: changedPassword }, | ||
| }); | ||
| expect(tokenResponse.ok(), 'Customer token API should accept the new password').toBeTruthy(); | ||
| }); | ||
|
|
||
| /** | ||
| * Test: User changes their e-mailaddress | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| * @param request - APIRequestContext instance used to create accounts with the API. | ||
| */ | ||
| test('Update_email_address', { tag: ['@account-credentials', '@hot'] }, async ({ page, request }) => { | ||
| const accountPage = new AccountPage(page); | ||
| const loginPage = new LoginPage(page); | ||
|
|
||
| const parallelIndex = test.info().parallelIndex; | ||
| const originalEmail = `playwright_emailtest_${parallelIndex}@elgentos.nl`; | ||
| const updatedEmail = `playwright_emailtest_updated_${parallelIndex}@elgentos.nl`; | ||
| const password = requireEnv('MAGENTO_EXISTING_ACCOUNT_PASSWORD'); | ||
|
|
||
| // Ensure a fresh account exists with the original email | ||
| const searchResponse = await apiClient.get( | ||
| `/rest/V1/customers/search` + | ||
| `?searchCriteria[filterGroups][0][filters][0][field]=email` + | ||
| `&searchCriteria[filterGroups][0][filters][0][value]=${originalEmail}` + | ||
| `&searchCriteria[filterGroups][0][filters][0][conditionType]=eq` | ||
| ); | ||
|
|
||
| if (searchResponse.items?.length > 0) { | ||
| await apiClient.delete(`/rest/V1/customers/${searchResponse.items[0].id}`); | ||
| } | ||
|
|
||
| // Also clean up any leftover updated email account from a previous run | ||
| const updatedSearchResponse = await apiClient.get( | ||
| `/rest/V1/customers/search` + | ||
| `?searchCriteria[filterGroups][0][filters][0][field]=email` + | ||
| `&searchCriteria[filterGroups][0][filters][0][value]=${updatedEmail}` + | ||
| `&searchCriteria[filterGroups][0][filters][0][conditionType]=eq` | ||
| ); | ||
|
|
||
| if (updatedSearchResponse.items?.length > 0) { | ||
| await apiClient.delete(`/rest/V1/customers/${updatedSearchResponse.items[0].id}`); | ||
| } | ||
|
|
||
| await apiClient.post('/rest/V1/customers', { | ||
| customer: { | ||
| email: originalEmail, | ||
| firstname: inputValues.account.firstName, | ||
| lastname: inputValues.account.lastName, | ||
| }, | ||
| password, | ||
| }); | ||
|
|
||
| // Login and update email via UI | ||
| await loginPage.login(originalEmail, password); | ||
| await page.goto(slugs.account.accountEditSlug, { waitUntil: 'load' }); | ||
| await expect(page.locator('#form-validate'). | ||
| getByText(UIReference.accountDashboard.accountDashboardTitleLabel), | ||
| `Heading "${UIReference.accountDashboard.accountDashboardTitleLabel}" is visible`).toBeVisible(); | ||
| await accountPage.updateEmail(password, updatedEmail); | ||
|
|
||
| // Verify the updated email works via API | ||
| const tokenResponse = await request.post('/rest/V1/integration/customer/token', { | ||
| data: { username: updatedEmail, password: password }, | ||
| }); | ||
| expect(tokenResponse.ok(), 'Customer token API should accept the updated email').toBeTruthy(); | ||
| }); | ||
| }); | ||
|
|
||
| /** | ||
| * Test Group: Account address book actions | ||
| */ | ||
| test.describe.serial('Account address book actions', { annotation: {type: 'Account Dashboard', description: 'Tests for the Address Book'},}, () => { | ||
|
|
||
| test.beforeEach(async ({page}) => { | ||
| await page.goto(slugs.account.addressIndexSlug, {waitUntil: "load"}); | ||
|
|
||
| // if page navigated to new address, no address had been added yet. | ||
| if(page.url().includes('new')){ | ||
| await expect(async () => { | ||
| await expect(page.getByText(UIReference.newAddress.addNewAddressTitle), | ||
| `Heading "${UIReference.newAddress.addNewAddressTitle}" is visible`).toBeVisible(); | ||
| }).toPass(); | ||
| } else { | ||
| await expect(async () => { | ||
| await expect(page.getByRole('heading', | ||
| { name: UIReference.address.addressBookTitle }), | ||
| `Heading "${UIReference.address.addressBookTitle}" is visible`).toBeVisible(); | ||
| }).toPass(); | ||
| } | ||
| }); | ||
|
|
||
| /** | ||
| * Test: The user adds an address to their account | ||
| * @assume the user is already logged in. | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| */ | ||
| test('Add_an_address',{ tag: ['@address-actions', '@hot'] }, async ({page}) => { | ||
| await page.goto(slugs.account.addressNewSlug); | ||
| const accountPage = new AccountPage(page); | ||
|
|
||
| const address = `${faker.location.streetAddress()} ${Math.floor(Math.random() * 100 + 1)}`; | ||
| const company = faker.company.name(); | ||
|
|
||
| await accountPage.addNewAddress({ company: company, street: address}); | ||
|
|
||
| await expect(page.getByText(address).first(), `Expect new address to be listed`).toBeVisible(); | ||
| await expect(page.getByText(company).first(), `Expect new company name to be listed`).toBeVisible(); | ||
| }); | ||
|
|
||
| /** | ||
| * Test: The user edits an existing address to their account | ||
| * @assume the user is already logged in. | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| */ | ||
| test('Edit_existing_address',{ tag: ['@address-actions', '@hot'] }, async ({page}) => { | ||
| const accountPage = new AccountPage(page); | ||
| await page.goto(slugs.account.addressBookSlug); | ||
| let editAddressButton = page.getByRole('link', {name: UIReference.accountDashboard.editAddressIconButton}).first(); | ||
| let isDefaultAddress = false; | ||
|
|
||
| if(await editAddressButton.isHidden()){ | ||
| // The edit address button was not found, add another address first. | ||
| if(await page.getByRole('link', { name: 'Change Shipping Address arrow' }).isVisible()) { | ||
| isDefaultAddress = true; | ||
| } else { | ||
| expect (page.url(), `Edit address button not found, check URL is to the new address page`).toBe(slugs.account.addressNewSlug); | ||
| await accountPage.addNewAddress(); | ||
| } | ||
| } | ||
|
|
||
| // const companyName = faker.company.name(); | ||
| const address = `${faker.location.streetAddress()} ${Math.floor(Math.random() * 100 + 1)}`; | ||
| await accountPage.editExistingAddress({street:address}, isDefaultAddress); | ||
|
|
||
| // await expect(page.getByText(companyName)).toBeVisible(); | ||
| await expect(page.getByText(address).first()).toBeVisible(); | ||
| }); | ||
|
|
||
| /** | ||
| * Test: The user can't add an address if they don't fill in all the required fields | ||
| * @assume the user is already logged in. | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| */ | ||
| test('Missing_required_field_prevents_creation',{ tag: ['@address-actions'] }, async ({page}) => { | ||
| await page.goto(slugs.account.addressNewSlug); | ||
| const accountPage = new AccountPage(page); | ||
|
|
||
| await accountPage.phoneNumberField.fill(inputValues.firstAddress.firstPhoneNumberValue); | ||
| await accountPage.saveAddressButton.click(); | ||
|
|
||
| const errorMessage = page.getByText(UIReference.general.errorMessageStreetAddressRequiredFieldText).first(); | ||
| await errorMessage.waitFor(); | ||
| await expect(errorMessage, `Error message "${UIReference.general.errorMessageStreetAddressRequiredFieldText}" is visible`).toBeVisible(); | ||
| }); | ||
| }); | ||
|
|
||
| /** | ||
| * Test Group: Newsletter tests | ||
| */ | ||
| test.describe('Newsletter actions', { annotation: {type: 'Account Dashboard', description: 'Newsletter tests'},}, () => { | ||
|
|
||
| /** | ||
| * Test: The user (un)subscribes from the newsletter | ||
| * @assume the user is already logged in. | ||
| * @param page - Playwright page instance used to interact with the website. | ||
| */ | ||
| test('Update_newsletter_subscription',{ tag: ['@newsletter-actions', '@cold'] }, async ({page}) => { | ||
| // Navigate to a page. | ||
| await page.goto(slugs.account.accountOverviewSlug); | ||
| await page.waitForLoadState(); | ||
|
|
||
| const newsletterPage = new NewsletterSubscriptionPage(page); | ||
| let newsletterLink = page.getByRole('link', { name: UIReference.accountDashboard.links.newsletterLink }); | ||
| const newsletterCheckElement = page.getByLabel(UIReference.newsletterSubscriptions.generalSubscriptionCheckLabel); | ||
|
|
||
| await newsletterLink.click(); | ||
| await expect(page.getByText(outcomeMarker.account.newsletterSubscriptionTitle, { exact: true })).toBeVisible(); | ||
|
|
||
| let updateSubscription = await newsletterPage.updateNewsletterSubscription(); | ||
|
|
||
| await newsletterLink.click(); | ||
|
|
||
| if(updateSubscription) { | ||
| await expect(newsletterCheckElement).toBeChecked(); | ||
| } | ||
| else { | ||
| await expect(newsletterCheckElement).not.toBeChecked(); | ||
| } | ||
| }); | ||
| }); |
This file contains hidden or 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,31 @@ | ||
| // @ts-check | ||
|
|
||
| import { test as setup, expect } from '@playwright/test'; | ||
| import path from 'path'; | ||
| import { UIReference, slugs } from '@config'; | ||
| import { requireEnv } from '@utils/env.utils'; | ||
|
|
||
| const authFile = path.join(__dirname, '../playwright/.auth/user.json'); | ||
|
|
||
| setup('authenticate', async ({ page, browserName }) => { | ||
| const browserEngine = browserName?.toUpperCase() || "UNKNOWN"; | ||
| const emailInputValue = requireEnv(`MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine}`); | ||
| const passwordInputValue = requireEnv('MAGENTO_EXISTING_ACCOUNT_PASSWORD'); | ||
|
|
||
| // Perform authentication steps. Replace these actions with your own. | ||
| await page.goto(slugs.account.loginSlug); | ||
| await page.getByLabel(UIReference.credentials.emailFieldLabel, {exact: true}).fill(emailInputValue); | ||
| await page.getByLabel(UIReference.credentials.passwordFieldLabel, {exact: true}).fill(passwordInputValue); | ||
| await page.getByRole('button', { name: UIReference.credentials.loginButtonLabel }).click(); | ||
| // Wait until the page receives the cookies. | ||
| // | ||
| // Sometimes login flow sets cookies in the process of several redirects. | ||
| // Wait for the final URL to ensure that the cookies are actually set. | ||
| // await page.waitForURL(''); | ||
| // Alternatively, you can wait until the page reaches a state where all cookies are set. | ||
| await expect(page.getByRole('link', { name: UIReference.mainMenu.myAccountLogoutItem })).toBeVisible(); | ||
|
|
||
| // End of authentication steps. | ||
|
|
||
| await page.context().storageState({ path: authFile }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this file (renamed to .env) is required to run the e2e test suite: the data should point to the test Magento url. I do not know what this url is?
Assuming the demo url may be https://mageos.demo.co.uk/, the below is a possible content:
PLAYWRIGHT_BASE_URL=https://mageos.demo.co.uk/
PLAYWRIGHT_PRODUCTION_URL=https://mageos.demo.co.uk/
PLAYWRIGHT_REVIEW_URL=
MAGENTO_ADMIN_SLUG=admin
MAGENTO_ADMIN_USERNAME=admin
MAGENTO_ADMIN_PASSWORD=P1ssw0rd
MAGENTO_THEME_LOCALE=en_US
MAGENTO_NEW_ACCOUNT_PASSWORD=NewTest1234!
MAGENTO_EXISTING_ACCOUNT_EMAIL_CHROMIUM=test-user@magsite.co.uk
MAGENTO_EXISTING_ACCOUNT_EMAIL_FIREFOX=test-user@magsite.co.uk
MAGENTO_EXISTING_ACCOUNT_EMAIL_WEBKIT=test-user@magsite.co.uk
MAGENTO_EXISTING_ACCOUNT_PASSWORD=TestPassword123!
MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD=Test2Password123!
MAGENTO_COUPON_CODE_CHROMIUM=H20
MAGENTO_COUPON_CODE_FIREFOX=H20
MAGENTO_COUPON_CODE_WEBKIT=H20
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll need something to integrate it with the github-action at https://github.com/mage-os/github-actions/pull/313/changes -- the action should provide the access URL to the instance or test runner. CC @michielgerritsen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to pair on this @michielgerritsen if helpful.