Skip to content

Commit

Permalink
Merge branch 'main' into gitlab-25
Browse files Browse the repository at this point in the history
  • Loading branch information
shayfaber authored Jan 13, 2025
2 parents 1eb9b96 + 7ad8c22 commit 4680eec
Show file tree
Hide file tree
Showing 19 changed files with 718 additions and 89 deletions.
11 changes: 8 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ MAGENTO_ADMIN_USERNAME=
MAGENTO_ADMIN_PASSWORD=

MAGENTO_NEW_ACCOUNT_PASSWORD=
MAGENTO_EXISTING_ACCOUNT_EMAIL=
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=
CAPTCHA_BYPASS=false
MAGENTO_COUPON_CODE_CHROMIUM=
MAGENTO_COUPON_CODE_FIREFOX=
MAGENTO_COUPON_CODE_WEBKIT=

CAPTCHA_BYPASS=
69 changes: 69 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Magento 2 BDD E2E Testing Suite Self Test

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

env:
BASE_URL: https://hyva-demo.elgentos.io/
PRODUCTION_URL: https://hyva-demo.elgentos.io/
STAGING_URL: https://hyva-demo.elgentos.io/

MAGENTO_ADMIN_SLUG: ${{ secrets.MAGENTO_ADMIN_SLUG }}
MAGENTO_ADMIN_USERNAME: ${{ secrets.MAGENTO_ADMIN_USERNAME }}
MAGENTO_ADMIN_PASSWORD: ${{ secrets.MAGENTO_ADMIN_PASSWORD }}

MAGENTO_NEW_ACCOUNT_PASSWORD: ${{ secrets.MAGENTO_NEW_ACCOUNT_PASSWORD }}
MAGENTO_EXISTING_ACCOUNT_EMAIL_CHROMIUM: ${{ secrets.MAGENTO_EXISTING_ACCOUNT_EMAIL_CHROMIUM }}
MAGENTO_EXISTING_ACCOUNT_EMAIL_FIREFOX: ${{ secrets.MAGENTO_EXISTING_ACCOUNT_EMAIL_FIREFOX }}
MAGENTO_EXISTING_ACCOUNT_EMAIL_WEBKIT: ${{ secrets.MAGENTO_EXISTING_ACCOUNT_EMAIL_WEBKIT }}
MAGENTO_EXISTING_ACCOUNT_PASSWORD: ${{ secrets.MAGENTO_EXISTING_ACCOUNT_PASSWORD }}
MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD: ${{ secrets.MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD }}

MAGENTO_COUPON_CODE_CHROMIUM: ${{ secrets.MAGENTO_COUPON_CODE_CHROMIUM }}
MAGENTO_COUPON_CODE_FIREFOX: ${{ secrets.MAGENTO_COUPON_CODE_FIREFOX }}
MAGENTO_COUPON_CODE_WEBKIT: ${{ secrets.MAGENTO_COUPON_CODE_WEBKIT }}

CAPTCHA_BYPASS: true

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 16

- name: Install dependencies
run: npm install

- name: Install Playwright browsers
run: npx playwright install

- name: Install Playwright dependencies
run: npx playwright install-deps


- name: Copy config files
run: |
cp playwright.config.example.ts playwright.config.ts
cp bypass-captcha.config.example.ts bypass-captcha.config.ts
- name: Run Playwright setup test
run: npx playwright test --reporter=line --workers=4 tests/base/setup.spec.ts
env:
CI: true

- name: Run Playwright tests
run: npx playwright test --reporter=line --workers=4 --exclude=tests/base/setup.spec.ts
env:
CI: true
19 changes: 10 additions & 9 deletions tests/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { test as setup, expect } from '@playwright/test';
import path from 'path';
import slugs from './refactor/config/slugs.json';
import selectors from './refactor/config/selectors/selectors.json';
import slugs from './base/config/slugs.json';
import selectors from './base/config/selectors/selectors.json';

const authFile = path.join(__dirname, '../playwright/.auth/user.json');

setup('authenticate', async ({ page }) => {
let emailInputValue = process.env.MAGENTO_EXISTING_ACCOUNT_EMAIL;
setup('authenticate', async ({ page, browserName }) => {
const browserEngine = browserName?.toUpperCase() || "UNKNOWN";
let emailInputValue = process.env[`MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine}`];
let passwordInputValue = process.env.MAGENTO_EXISTING_ACCOUNT_PASSWORD;

if(!emailInputValue || !passwordInputValue) {
throw new Error("Your password variable and/or your email variable have not defined in the .env file, or the account hasn't been created yet.");
throw new Error("MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine} and/or MAGENTO_EXISTING_ACCOUNT_PASSWORD have not defined in the .env file, or the account hasn't been created yet.");
}

// Perform authentication steps. Replace these actions with your own.
await page.goto(slugs.account.loginSlug);
await page.getByLabel(selectors.login.emailFieldLabel, {exact: true}).fill(emailInputValue);
await page.getByLabel(selectors.login.PasswordFieldLabel, {exact: true}).fill(passwordInputValue);
await page.getByRole('button', { name: selectors.login.loginButtonLabel }).click();
await page.getByLabel(selectors.credentials.emailFieldLabel, {exact: true}).fill(emailInputValue);
await page.getByLabel(selectors.credentials.passwordFieldLabel, {exact: true}).fill(passwordInputValue);
await page.getByRole('button', { name: selectors.credentials.loginButtonLabel }).click();
// Wait until the page receives the cookies.
//
// Sometimes login flow sets cookies in the process of several redirects.
Expand All @@ -29,4 +30,4 @@ setup('authenticate', async ({ page }) => {
// End of authentication steps.

await page.context().storageState({ path: authFile });
});
});
25 changes: 13 additions & 12 deletions tests/base/account.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@ import verify from './config/expected/expected.json';


// Before each test, log in
test.beforeEach(async ({ page }) => {
let emailInputValue = process.env.MAGENTO_EXISTING_ACCOUNT_EMAIL;
test.beforeEach(async ({ page, browserName }) => {
const browserEngine = browserName?.toUpperCase() || "UNKNOWN";
let emailInputValue = process.env[`MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine}`];
let passwordInputValue = process.env.MAGENTO_EXISTING_ACCOUNT_PASSWORD;

if(!emailInputValue || !passwordInputValue) {
throw new Error("Your password variable and/or your email variable have not defined in the .env file, or the account hasn't been created yet.");
throw new Error("MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine} and/or MAGENTO_EXISTING_ACCOUNT_PASSWORD have not defined in the .env file, or the account hasn't been created yet.");
}

const loginPage = new LoginPage(page);
await loginPage.login(emailInputValue, passwordInputValue);
});

test.describe('Account information actions', {annotation: {type: 'Account Dashboard', description: 'Test for Account Information'},}, () => {

test.beforeEach(async ({page}) => {
await page.goto(slugs.account.accountOverviewSlug);
});
Expand Down Expand Up @@ -85,7 +86,7 @@ test.describe('Account address book actions', { annotation: {type: 'Account Dash
* @and I haven't added an address yet
* @when I fill in the required information
* @and I click the save button
* @then I should see a notification my address has been updated.
* @then I should see a notification my address has been updated.
* @and The new address should be selected as default and shipping address
*/

Expand All @@ -111,7 +112,7 @@ test.describe('Account address book actions', { annotation: {type: 'Account Dash
* @when I go to the page where I can add another address
* @when I fill in the required information
* @and I click the save button
* @then I should see a notification my address has been updated.
* @then I should see a notification my address has been updated.
* @and The new address should be listed
*/
test('I can add another address',{ tag: '@address-actions', }, async ({page}) => {
Expand All @@ -138,7 +139,7 @@ test.describe('Account address book actions', { annotation: {type: 'Account Dash
* @when I click on the button to edit the address
* @and I fill in the required information correctly
* @then I click the save button
* @then I should see a notification my address has been updated.
* @then I should see a notification my address has been updated.
* @and The updated address should be visible in the addres book page.
*/
test('I can edit an existing address',{ tag: '@address-actions', }, async ({page}) => {
Expand All @@ -149,7 +150,7 @@ test.describe('Account address book actions', { annotation: {type: 'Account Dash
let newZipCode = inputvalues.editedAddress.editZipCodeValue;
let newCity = inputvalues.editedAddress.editCityValue;
let newState = inputvalues.editedAddress.editStateValue;

await page.goto(slugs.account.addressBookSlug);
await accountPage.editExistingAddress(newFirstName, newLastName, newStreet, newZipCode, newCity, newState);

Expand All @@ -163,7 +164,7 @@ test.describe('Account address book actions', { annotation: {type: 'Account Dash
* @when I go to the page where I can see my address(es)
* @when I click the trash button for the address I want to delete
* @and I click the confirmation button
* @then I should see a notification my address has been deleted.
* @then I should see a notification my address has been deleted.
* @and The address should be removed from the overview.
*/
test('I can delete an address',{ tag: '@address-actions', }, async ({page}) => {
Expand All @@ -178,7 +179,7 @@ test.describe('Newsletter actions', { annotation: {type: 'Account Dashboard', de
// go to the Dashboard page
await page.goto(slugs.account.accountOverviewSlug);
});

// TODO: What if website offers multiple subscriptions?

/**
Expand All @@ -205,9 +206,9 @@ test.describe('Newsletter actions', { annotation: {type: 'Account Dashboard', de
await newsletterLink.click();

if(updateSubscription){
await expect(newsletterCheckElement).toBeChecked();
await expect(newsletterCheckElement).toBeChecked();
} else {
await expect(newsletterCheckElement).not.toBeChecked();
await expect(newsletterCheckElement).not.toBeChecked();
}
});

Expand Down
107 changes: 101 additions & 6 deletions tests/base/cart.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { test, expect } from '@playwright/test';
import { ProductPage } from './fixtures/product.page';
import { MainMenuPage } from './fixtures/mainmenu.page';
import {LoginPage} from './fixtures/login.page';
import { CartPage } from './fixtures/cart.page';

import slugs from './config/slugs.json';
import selectors from './config/selectors/selectors.json';
import verify from './config/expected/expected.json';

test.describe('Cart functionalities', () => {
test.describe('Cart functionalities (guest)', () => {
/**
* @feature BeforeEach runs before each test in this group.
* @scenario Add a product to the cart and confirm it's there.
Expand All @@ -25,19 +26,49 @@ test.describe('Cart functionalities', () => {

//TODO: Use a storagestate or API call to add product to the cart so shorten test time
await page.goto(slugs.productpage.simpleProductSlug);
await productPage.addSimpleProductToCart();
await productPage.addSimpleProductToCart(selectors.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug);
await mainMenu.openMiniCart();
await expect(page.getByText(verify.miniCart.simpleProductInCartTitle)).toBeVisible();
await page.goto(slugs.cartSlug);
});


test('Product can be added to cart',{ tag: '@cart',}, async ({page}) => {
await expect(page.getByRole('strong').getByRole('link', {name: selectors.productPage.simpleProductTitle}), `Product is visible in cart`).toBeVisible();
});

/**
* @feature Remove product from cart
* @feature Product permanence after login
* @scenario A product added to the cart should still be there after user has logged in
* @given I have a product in my cart
* @when I log in
* @then I should still have that product in my cart
*/
test('Product should remain in cart after logging in',{ tag: ['@cart', '@account']}, async ({page, browserName}) => {
await test.step('Add another product to cart', async () =>{
const productpage = new ProductPage(page);
await page.goto(slugs.productpage.secondSimpleProductSlug);
await productpage.addSimpleProductToCart(selectors.productPage.secondSimpleProducTitle, slugs.productpage.secondSimpleProductSlug);
});

await test.step('Log in with account', async () =>{
const browserEngine = browserName?.toUpperCase() || "UNKNOWN";
const loginPage = new LoginPage(page);
let emailInputValue = process.env[`MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine}`];
let passwordInputValue = process.env.MAGENTO_EXISTING_ACCOUNT_PASSWORD;

if(!emailInputValue || !passwordInputValue) {
throw new Error("MAGENTO_EXISTING_ACCOUNT_EMAIL_${browserEngine} and/or MAGENTO_EXISTING_ACCOUNT_PASSWORD have not defined in the .env file, or the account hasn't been created yet.");
}

await loginPage.login(emailInputValue, passwordInputValue);
});

await page.goto(slugs.cartSlug);
await expect(page.getByRole('strong').getByRole('link', { name: selectors.productPage.simpleProductTitle }),`${selectors.productPage.simpleProductTitle} should still be in cart`).toBeVisible();
await expect(page.getByRole('strong').getByRole('link', { name: selectors.productPage.secondSimpleProducTitle }),`${selectors.productPage.secondSimpleProducTitle} should still be in cart`).toBeVisible();
});

/** @feature Remove product from cart
* @scenario User has added a product and wants to remove it from the cart page
* @given I have added a product to my cart
* @and I am on the cart page
Expand All @@ -50,7 +81,71 @@ test.describe('Cart functionalities', () => {
await cart.removeProduct(selectors.productPage.simpleProductTitle);
});

});
/**
* @feature Discount Code
* @scenario User adds a discount code to their cart
* @given I have a product in my cart
* @and I am on my cart page
* @when I click on the 'add discount code' button
* @then I fill in a code
* @and I click on 'apply code'
* @then I should see a confirmation that my code has been added
* @and the code should be visible in the cart
* @and a discount should be applied to the product
*/
test('Add coupon code in cart',{ tag: ['@cart', '@coupon-code']}, async ({page, browserName}) => {
const browserEngine = browserName?.toUpperCase() || "UNKNOWN";
const cart = new CartPage(page);
let discountCode = process.env[`MAGENTO_COUPON_CODE_${browserEngine}`];

if(!discountCode) {
throw new Error(`MAGENTO_COUPON_CODE_${browserEngine} appears to not be set in .env file. Value reported: ${discountCode}`);
}

await cart.applyDiscountCode(discountCode);
});

/**
* @feature Remove discount code from cart
* @scenario User has added a discount code, then removes it
* @given I have a product in my cart
* @and I am on my cart page
* @when I add a discount code
* @then I should see a notification
* @and the code should be visible in the cart
* @and a discount should be applied to a product
* @when I click the 'cancel coupon' button
* @then I should see a notification the discount has been removed
* @and the discount should no longer be visible.
*/
test('Remove coupon code from cart',{ tag: ['@cart', '@coupon-code'] }, async ({page, browserName}) => {
const browserEngine = browserName?.toUpperCase() || "UNKNOWN";
const cart = new CartPage(page);
let discountCode = process.env[`MAGENTO_COUPON_CODE_${browserEngine}`];

if(!discountCode) {
throw new Error(`MAGENTO_COUPON_CODE_${browserEngine} appears to not be set in .env file. Value reported: ${discountCode}`);
}

// TODO: create API call to quickly add discount code rather than run a test again.
await cart.applyDiscountCode(discountCode);
await cart.removeDiscountCode();
});

/**
* @feature Incorrect discount code check
* @scenario The user provides an incorrect discount code, the system should reflect that
* @given I have a product in my cart
* @and I am on the cart page
* @when I enter a wrong discount code
* @then I should get a notification that the code did not work.
*/

test('Using an invalid coupon code should give an error',{ tag: ['@cart', '@coupon-code'] }, async ({page}) => {
const cart = new CartPage(page);
await cart.enterWrongCouponCode("Incorrect Couon Code");
});
})

test.describe('Price checking tests', () => {

Expand Down
Loading

0 comments on commit 4680eec

Please sign in to comment.