diff --git a/tests/base/account.spec.ts b/tests/base/account.spec.ts index 76474aa..fcc9949 100644 --- a/tests/base/account.spec.ts +++ b/tests/base/account.spec.ts @@ -7,8 +7,8 @@ import {NewsletterSubscriptionPage} from './fixtures/newsletter.page'; import slugs from './config/slugs.json'; import inputvalues from './config/input-values/input-values.json'; -import selectors from './config/selectors/selectors.json'; -import verify from './config/expected/expected.json'; +import UIReference from './config/element-identifiers/element-identifiers.json'; +import outcomeMarker from './config/outcome-markers/outcome-markers.json'; // Before each test, log in test.beforeEach(async ({ page, browserName }) => { @@ -43,7 +43,7 @@ test.describe('Account information actions', {annotation: {type: 'Account Dashbo * @then I should see a notification that my password has been updated * @and I should be able to login with my new credentials. */ - test('I can change my password',{ tag: '@account-credentials', }, async ({page, browserName}) => { + test('I can change my password',{ tag: '@account-credentials', }, async ({page, browserName}, testInfo) => { // Create instances and set variables const mainMenu = new MainMenuPage(page); @@ -58,7 +58,7 @@ test.describe('Account information actions', {annotation: {type: 'Account Dashbo let changedPasswordValue = process.env.MAGENTO_EXISTING_ACCOUNT_CHANGED_PASSWORD; // Log out of current account - if(await page.getByRole('link', { name: selectors.mainMenu.myAccountLogoutItem }).isVisible()){ + if(await page.getByRole('link', { name: UIReference.mainMenu.myAccountLogoutItem }).isVisible()){ await mainMenu.logout(); } @@ -108,7 +108,7 @@ test.describe.serial('Account address book actions', { annotation: {type: 'Accou test('I can add my first address',{ tag: '@address-actions', }, async ({page}, testInfo) => { const accountPage = new AccountPage(page); - let addNewAddressTitle = page.getByRole('heading', {level: 1, name: selectors.newAddress.addNewAddressTitle}); + let addNewAddressTitle = page.getByRole('heading', {level: 1, name: UIReference.newAddress.addNewAddressTitle}); if(await addNewAddressTitle.isHidden()) { await accountPage.deleteAllAddresses(); @@ -150,7 +150,7 @@ test.describe.serial('Account address book actions', { annotation: {type: 'Accou test('I can edit an existing address',{ tag: '@address-actions', }, async ({page}) => { const accountPage = new AccountPage(page); await page.goto(slugs.account.addressNewSlug); - let editAddressButton = page.getByRole('link', {name: selectors.accountDashboard.editAddressIconButton}).first(); + let editAddressButton = page.getByRole('link', {name: UIReference.accountDashboard.editAddressIconButton}).first(); if(await editAddressButton.isHidden()){ // The edit address button was not found, add another address first. @@ -175,11 +175,11 @@ test.describe.serial('Account address book actions', { annotation: {type: 'Accou test('I can delete an address',{ tag: '@address-actions', }, async ({page}, testInfo) => { const accountPage = new AccountPage(page); - let deleteAddressButton = page.getByRole('link', {name: selectors.accountDashboard.addressDeleteIconButton}).first(); + let deleteAddressButton = page.getByRole('link', {name: UIReference.accountDashboard.addressDeleteIconButton}).first(); if(await deleteAddressButton.isHidden()) { await page.goto(slugs.account.addressNewSlug); - await accountPage.addNewAddress(inputvalues.firstAddress.firstPhoneNumberValue, inputvalues.firstAddress.firstStreetAddressValue, inputvalues.firstAddress.firstZipCodeValue, inputvalues.firstAddress.firstCityValue, inputvalues.firstAddress.firstProvinceValue); + await accountPage.addNewAddress(); } await accountPage.deleteFirstAddressFromAddressBook(); }); @@ -204,11 +204,11 @@ test.describe('Newsletter actions', { annotation: {type: 'Account Dashboard', de test('I can update my newsletter subscription',{ tag: '@newsletter-actions', }, async ({page, browserName}) => { test.skip(browserName === 'webkit', '.click() does not work, still searching for a workaround'); const newsletterPage = new NewsletterSubscriptionPage(page); - let newsletterLink = page.getByRole('link', { name: selectors.accountDashboard.links.newsletterLink }); - const newsletterCheckElement = page.getByLabel(selectors.newsletterSubscriptions.generalSubscriptionCheckLabel); + let newsletterLink = page.getByRole('link', { name: UIReference.accountDashboard.links.newsletterLink }); + const newsletterCheckElement = page.getByLabel(UIReference.newsletterSubscriptions.generalSubscriptionCheckLabel); await newsletterLink.click(); - await expect(page.getByText(verify.account.newsletterSubscriptionTitle, { exact: true })).toBeVisible(); + await expect(page.getByText(outcomeMarker.account.newsletterSubscriptionTitle, { exact: true })).toBeVisible(); let updateSubscription = await newsletterPage.updateNewsletterSubscription(); diff --git a/tests/base/cart.spec.ts b/tests/base/cart.spec.ts index 84f5163..19fefd8 100644 --- a/tests/base/cart.spec.ts +++ b/tests/base/cart.spec.ts @@ -5,8 +5,8 @@ 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'; +import UIReference from './config/element-identifiers/element-identifiers.json'; +import outcomeMarker from './config/outcome-markers/outcome-markers.json'; test.describe('Cart functionalities (guest)', () => { /** @@ -25,14 +25,14 @@ test.describe('Cart functionalities (guest)', () => { const productPage = new ProductPage(page); await page.goto(slugs.productpage.simpleProductSlug); - await productPage.addSimpleProductToCart(selectors.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); + await productPage.addSimpleProductToCart(UIReference.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); await mainMenu.openMiniCart(); - await expect(page.getByText(verify.miniCart.simpleProductInCartTitle)).toBeVisible(); + await expect(page.getByText(outcomeMarker.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(); + await expect(page.getByRole('strong').getByRole('link', {name: UIReference.productPage.simpleProductTitle}), `Product is visible in cart`).toBeVisible(); }); /** @@ -46,7 +46,7 @@ test.describe('Cart functionalities (guest)', () => { 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 productpage.addSimpleProductToCart(UIReference.productPage.secondSimpleProducTitle, slugs.productpage.secondSimpleProductSlug); }); await test.step('Log in with account', async () =>{ @@ -63,8 +63,8 @@ test.describe('Cart functionalities (guest)', () => { }); 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(); + await expect(page.getByRole('strong').getByRole('link', { name: UIReference.productPage.simpleProductTitle }),`${UIReference.productPage.simpleProductTitle} should still be in cart`).toBeVisible(); + await expect(page.getByRole('strong').getByRole('link', { name: UIReference.productPage.secondSimpleProducTitle }),`${UIReference.productPage.secondSimpleProducTitle} should still be in cart`).toBeVisible(); }); /** @feature Remove product from cart @@ -77,7 +77,7 @@ test.describe('Cart functionalities (guest)', () => { */ test('Remove product from cart',{ tag: '@cart',}, async ({page}) => { const cart = new CartPage(page); - await cart.removeProduct(selectors.productPage.simpleProductTitle); + await cart.removeProduct(UIReference.productPage.simpleProductTitle); }); /** @@ -172,11 +172,11 @@ test.describe('Price checking tests', () => { const productPage = new ProductPage(page); await page.goto(slugs.productpage.simpleProductSlug); // set quantity to 2 so we can see that the math works - await page.getByLabel(selectors.productPage.quantityFieldLabel).fill('2'); + await page.getByLabel(UIReference.productPage.quantityFieldLabel).fill('2'); - productPagePrice = await page.locator(selectors.productPage.simpleProductPrice).innerText(); - productPageAmount = await page.getByLabel(selectors.productPage.quantityFieldLabel).inputValue(); - await productPage.addSimpleProductToCart(selectors.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug, '2'); + productPagePrice = await page.locator(UIReference.productPage.simpleProductPrice).innerText(); + productPageAmount = await page.getByLabel(UIReference.productPage.quantityFieldLabel).inputValue(); + await productPage.addSimpleProductToCart(UIReference.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug, '2'); }); @@ -185,7 +185,7 @@ test.describe('Price checking tests', () => { await page.waitForLoadState(); // returns productPriceInCheckout and productQuantityInCheckout - checkoutProductDetails = await cart.getCheckoutValues(selectors.productPage.simpleProductTitle, productPagePrice, productPageAmount); + checkoutProductDetails = await cart.getCheckoutValues(UIReference.productPage.simpleProductTitle, productPagePrice, productPageAmount); }); await test.step('Step: Calculate and check expectations', async () =>{ @@ -216,8 +216,8 @@ test.describe('Price checking tests', () => { // set quantity to 2 so we can see that the math works await page.getByLabel('Quantity').fill('2'); - productPagePrice = await page.locator(selectors.productPage.simpleProductPrice).innerText(); - productPageAmount = await page.getByLabel(selectors.productPage.quantityFieldLabel).inputValue(); + productPagePrice = await page.locator(UIReference.productPage.simpleProductPrice).innerText(); + productPageAmount = await page.getByLabel(UIReference.productPage.quantityFieldLabel).inputValue(); await productPage.addConfigurableProductToCart(); }); @@ -227,7 +227,7 @@ test.describe('Price checking tests', () => { await page.waitForLoadState(); // returns productPriceInCheckout and productQuantityInCheckout - checkoutProductDetails = await cart.getCheckoutValues(selectors.productPage.configurableProductTitle, productPagePrice, productPageAmount); + checkoutProductDetails = await cart.getCheckoutValues(UIReference.productPage.configurableProductTitle, productPagePrice, productPageAmount); }); await test.step('Step: Calculate and check expectations', async () =>{ diff --git a/tests/base/checkout.spec.ts b/tests/base/checkout.spec.ts index e42045a..0cb876d 100644 --- a/tests/base/checkout.spec.ts +++ b/tests/base/checkout.spec.ts @@ -5,8 +5,7 @@ import {AccountPage} from './fixtures/account.page'; import { CheckoutPage } from './fixtures/checkout.page'; import slugs from './config/slugs.json'; -import inputvalues from './config/input-values/input-values.json'; -import selectors from './config/selectors/selectors.json'; +import UIReference from './config/element-identifiers/element-identifiers.json'; /** @@ -24,7 +23,7 @@ test.beforeEach(async ({ page }) => { const productPage = new ProductPage(page); await page.goto(slugs.productpage.simpleProductSlug); - await productPage.addSimpleProductToCart(selectors.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); + await productPage.addSimpleProductToCart(UIReference.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); await page.goto(slugs.checkoutSlug); }); @@ -54,8 +53,8 @@ test.describe('Checkout (login required)', () => { * @then My name and address should already be filled in */ test('My address should be already filled in at the checkout',{ tag: '@checkout',}, async ({page}) => { - let signInLink = page.getByRole('link', { name: selectors.credentials.loginButtonLabel }); - let addressField = page.getByLabel(selectors.newAddress.streetAddressLabel); + let signInLink = page.getByRole('link', { name: UIReference.credentials.loginButtonLabel }); + let addressField = page.getByLabel(UIReference.newAddress.streetAddressLabel); let addressAlreadyAdded = false; if(await signInLink.isVisible()) { @@ -63,7 +62,7 @@ test.describe('Checkout (login required)', () => { } // name field should NOT be on the page - await expect(page.getByLabel(selectors.personalInformation.firstNameLabel)).toBeHidden(); + await expect(page.getByLabel(UIReference.personalInformation.firstNameLabel)).toBeHidden(); if(await addressField.isVisible()) { if(!addressAlreadyAdded){ @@ -76,7 +75,7 @@ test.describe('Checkout (login required)', () => { } // expect to see radio button to select existing address - let shippingRadioButton = page.locator(selectors.checkout.shippingAddressRadioLocator).first(); + let shippingRadioButton = page.locator(UIReference.checkout.shippingAddressRadioLocator).first(); await expect(shippingRadioButton, 'Radio button to select address should be visible').toBeVisible(); }); diff --git a/tests/base/config/selectors/selectors.json b/tests/base/config/element-identifiers/element-identifiers.json similarity index 100% rename from tests/base/config/selectors/selectors.json rename to tests/base/config/element-identifiers/element-identifiers.json diff --git a/tests/base/config/expected/expected.json b/tests/base/config/outcome-markers/outcome-markers.json similarity index 100% rename from tests/base/config/expected/expected.json rename to tests/base/config/outcome-markers/outcome-markers.json diff --git a/tests/base/contact.spec.ts b/tests/base/contact.spec.ts index cc77ea5..a369e00 100644 --- a/tests/base/contact.spec.ts +++ b/tests/base/contact.spec.ts @@ -1,4 +1,4 @@ -import {test, expect} from '@playwright/test'; +import {test} from '@playwright/test'; import { ContactPage } from './fixtures/contact.page'; /** diff --git a/tests/base/fixtures/account.page.ts b/tests/base/fixtures/account.page.ts index 5bf8280..e0d3e68 100644 --- a/tests/base/fixtures/account.page.ts +++ b/tests/base/fixtures/account.page.ts @@ -1,8 +1,8 @@ import {expect, type Locator, type Page} from '@playwright/test'; import {faker} from '@faker-js/faker'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; import slugs from '../config/slugs.json'; export class AccountPage { @@ -35,40 +35,40 @@ export class AccountPage { constructor(page: Page){ this.page = page; - this.accountDashboardTitle = page.getByRole('heading', { name: selectors.accountDashboard.accountDashboardTitleLabel }); - this.firstNameField = page.getByLabel(selectors.personalInformation.firstNameLabel); - this.lastNameField = page.getByLabel(selectors.personalInformation.lastNameLabel); - this.phoneNumberField = page.getByLabel(selectors.newAddress.phoneNumberLabel); - this.streetAddressField = page.getByLabel(selectors.newAddress.streetAddressLabel, {exact:true}); - this.zipCodeField = page.getByLabel(selectors.newAddress.zipCodeLabel); - this.cityField = page.getByLabel(selectors.newAddress.cityNameLabel); - this.countrySelectorField = page.getByLabel(selectors.newAddress.countryLabel); - this.stateSelectorField = page.getByLabel(selectors.newAddress.provinceSelectLabel).filter({hasText: selectors.newAddress.provinceSelectFilterLabel}); - this.saveAddressButton = page.getByRole('button',{name: selectors.newAddress.saveAdressButton}); + this.accountDashboardTitle = page.getByRole('heading', { name: UIReference.accountDashboard.accountDashboardTitleLabel }); + this.firstNameField = page.getByLabel(UIReference.personalInformation.firstNameLabel); + this.lastNameField = page.getByLabel(UIReference.personalInformation.lastNameLabel); + this.phoneNumberField = page.getByLabel(UIReference.newAddress.phoneNumberLabel); + this.streetAddressField = page.getByLabel(UIReference.newAddress.streetAddressLabel, {exact:true}); + this.zipCodeField = page.getByLabel(UIReference.newAddress.zipCodeLabel); + this.cityField = page.getByLabel(UIReference.newAddress.cityNameLabel); + this.countrySelectorField = page.getByLabel(UIReference.newAddress.countryLabel); + this.stateSelectorField = page.getByLabel(UIReference.newAddress.provinceSelectLabel).filter({hasText: UIReference.newAddress.provinceSelectFilterLabel}); + this.saveAddressButton = page.getByRole('button',{name: UIReference.newAddress.saveAdressButton}); // Account Information elements - this.changePasswordCheck = page.getByRole('checkbox', {name: selectors.personalInformation.changePasswordCheckLabel}); - this.currentPasswordField = page.getByLabel(selectors.credentials.currentPasswordFieldLabel); - this.newPasswordField = page.getByLabel(selectors.credentials.newPasswordFieldLabel, {exact:true}); - this.confirmNewPasswordField = page.getByLabel(selectors.credentials.newPasswordConfirmFieldLabel); - this.genericSaveButton = page.getByRole('button', { name: selectors.general.genericSaveButtonLabel }); + this.changePasswordCheck = page.getByRole('checkbox', {name: UIReference.personalInformation.changePasswordCheckLabel}); + this.currentPasswordField = page.getByLabel(UIReference.credentials.currentPasswordFieldLabel); + this.newPasswordField = page.getByLabel(UIReference.credentials.newPasswordFieldLabel, {exact:true}); + this.confirmNewPasswordField = page.getByLabel(UIReference.credentials.newPasswordConfirmFieldLabel); + this.genericSaveButton = page.getByRole('button', { name: UIReference.general.genericSaveButtonLabel }); // Account Creation elements - this.accountCreationFirstNameField = page.getByLabel(selectors.personalInformation.firstNameLabel); - this.accountCreationLastNameField = page.getByLabel(selectors.personalInformation.lastNameLabel); - this.accountCreationEmailField = page.getByLabel(selectors.credentials.emailFieldLabel, { exact: true}); - this.accountCreationPasswordField = page.getByLabel(selectors.credentials.passwordFieldLabel, { exact: true }); - this.accountCreationPasswordRepeatField = page.getByLabel(selectors.credentials.passwordConfirmFieldLabel); - this.accountCreationConfirmButton = page.getByRole('button', {name: selectors.accountCreation.createAccountButtonLabel}); + this.accountCreationFirstNameField = page.getByLabel(UIReference.personalInformation.firstNameLabel); + this.accountCreationLastNameField = page.getByLabel(UIReference.personalInformation.lastNameLabel); + this.accountCreationEmailField = page.getByLabel(UIReference.credentials.emailFieldLabel, { exact: true}); + this.accountCreationPasswordField = page.getByLabel(UIReference.credentials.passwordFieldLabel, { exact: true }); + this.accountCreationPasswordRepeatField = page.getByLabel(UIReference.credentials.passwordConfirmFieldLabel); + this.accountCreationConfirmButton = page.getByRole('button', {name: UIReference.accountCreation.createAccountButtonLabel}); // Address Book elements - this.addNewAddressButton = page.getByRole('button',{name: selectors.accountDashboard.addAddressButtonLabel}); - this.deleteAddressButton = page.getByRole('link', {name: selectors.accountDashboard.addressDeleteIconButton}).first(); - this.editAddressButton = page.getByRole('link', {name: selectors.accountDashboard.editAddressIconButton}).first(); + this.addNewAddressButton = page.getByRole('button',{name: UIReference.accountDashboard.addAddressButtonLabel}); + this.deleteAddressButton = page.getByRole('link', {name: UIReference.accountDashboard.addressDeleteIconButton}).first(); + this.editAddressButton = page.getByRole('link', {name: UIReference.accountDashboard.editAddressIconButton}).first(); } async addNewAddress(){ - let addressAddedNotification = verify.address.newAddressAddedNotifcation; + let addressAddedNotification = outcomeMarker.address.newAddressAddedNotifcation; let streetName = faker.location.streetAddress(); // Name should be filled in automatically. @@ -90,7 +90,7 @@ export class AccountPage { async editExistingAddress(){ // the notification for a modified address is the same as the notification for a new address. - let addressModifiedNotification = verify.address.newAddressAddedNotifcation; + let addressModifiedNotification = outcomeMarker.address.newAddressAddedNotifcation; let streetName = faker.location.streetAddress(); await this.editAddressButton.click(); @@ -115,7 +115,7 @@ export class AccountPage { async deleteFirstAddressFromAddressBook(){ - let addressDeletedNotification = verify.address.addressDeletedNotification; + let addressDeletedNotification = outcomeMarker.address.addressDeletedNotification; // Dialog function to click confirm this.page.on('dialog', async (dialog) => { if (dialog.type() === 'confirm') { @@ -129,7 +129,7 @@ export class AccountPage { } async updatePassword(currentPassword:string, newPassword: string){ - let passwordUpdatedNotification = verify.account.changedPasswordNotificationText; + let passwordUpdatedNotification = outcomeMarker.account.changedPasswordNotificationText; await this.changePasswordCheck.check(); await this.currentPasswordField.fill(currentPassword); @@ -140,7 +140,6 @@ export class AccountPage { await this.page.waitForLoadState(); await expect(this.page.getByText(passwordUpdatedNotification)).toBeVisible(); - console.log(`Password has been changed! Please update your .env file password with "${newPassword}"`); } async create(firstName: string, lastName: string, email: string, password: string){ @@ -156,7 +155,7 @@ export class AccountPage { } async deleteAllAddresses() { - let addressDeletedNotification = verify.address.addressDeletedNotification; + let addressDeletedNotification = outcomeMarker.address.addressDeletedNotification; this.page.on('dialog', async (dialog) => { if (dialog.type() === 'confirm') { diff --git a/tests/base/fixtures/cart.page.ts b/tests/base/fixtures/cart.page.ts index cc10268..bd2794d 100644 --- a/tests/base/fixtures/cart.page.ts +++ b/tests/base/fixtures/cart.page.ts @@ -1,7 +1,7 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; export class CartPage { readonly page: Page; @@ -14,60 +14,60 @@ export class CartPage { constructor(page: Page) { this.page = page; - this.showDiscountButton = this.page.getByRole('button', { name: selectors.cart.showDiscountFormButtonLabel }); + this.showDiscountButton = this.page.getByRole('button', { name: UIReference.cart.showDiscountFormButtonLabel }); } async applyDiscountCode(code: string){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountButton.click(); } - let applyDiscoundButton = this.page.getByRole('button', {name: selectors.cart.applyDiscountButtonLabel, exact:true}); - let discountField = this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel); + let applyDiscoundButton = this.page.getByRole('button', {name: UIReference.cart.applyDiscountButtonLabel, exact:true}); + let discountField = this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel); await discountField.fill(code); await applyDiscoundButton.click(); await this.page.waitForLoadState(); - await expect(this.page.getByText(`${verify.cart.discountAppliedNotification} "${code}"`),`Notification that discount code ${code} has been applied`).toBeVisible(); - await expect(this.page.getByText(verify.cart.priceReducedSymbols),`'- $' should be visible on the page`).toBeVisible(); + await expect(this.page.getByText(`${outcomeMarker.cart.discountAppliedNotification} "${code}"`),`Notification that discount code ${code} has been applied`).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.cart.priceReducedSymbols),`'- $' should be visible on the page`).toBeVisible(); //Close message to prevent difficulties with other tests. - await this.page.getByLabel(selectors.general.closeMessageLabel).click(); + await this.page.getByLabel(UIReference.general.closeMessageLabel).click(); } async enterWrongCouponCode(code: string){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountButton.click(); } - let applyDiscoundButton = this.page.getByRole('button', {name: selectors.cart.applyDiscountButtonLabel, exact:true}); - let discountField = this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel); + let applyDiscoundButton = this.page.getByRole('button', {name: UIReference.cart.applyDiscountButtonLabel, exact:true}); + let discountField = this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel); await discountField.fill(code); await applyDiscoundButton.click(); await this.page.waitForLoadState(); - let incorrectNotification = `${verify.cart.incorrectCouponCodeNotificationOne} "${code}" ${verify.cart.incorrectCouponCodeNotificationTwo}`; + let incorrectNotification = `${outcomeMarker.cart.incorrectCouponCodeNotificationOne} "${code}" ${outcomeMarker.cart.incorrectCouponCodeNotificationTwo}`; await expect(this.page.getByText(incorrectNotification), `Code should not work`).toBeVisible(); } async removeDiscountCode(){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountButton.click(); } - let cancelCouponButton = this.page.getByRole('button', {name: selectors.cart.cancelCouponButtonLabel}); + let cancelCouponButton = this.page.getByRole('button', {name: UIReference.cart.cancelCouponButtonLabel}); await cancelCouponButton.click(); await this.page.waitForLoadState(); - await expect(this.page.getByText(verify.cart.discountRemovedNotification),`Notification should be visible`).toBeVisible(); - await expect(this.page.getByText(verify.cart.priceReducedSymbols),`'- $' should not be on the page`).toBeHidden(); + await expect(this.page.getByText(outcomeMarker.cart.discountRemovedNotification),`Notification should be visible`).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.cart.priceReducedSymbols),`'- $' should not be on the page`).toBeHidden(); } async removeProduct(name: string){ - //let removeButton = this.page.getByLabel(`${selectors.cart.cancelCouponButtonLabel} ${name}`); + //let removeButton = this.page.getByLabel(`${UIReference.cart.cancelCouponButtonLabel} ${name}`); let removeButton = this.page.getByLabel(`Remove ${name}`); await removeButton.click(); await this.page.waitForLoadState(); @@ -76,18 +76,18 @@ export class CartPage { async getCheckoutValues(productName:string, pricePDP:string, amountPDP:string){ // Open minicart based on amount of products in cart - let cartItemAmount = await this.page.locator(selectors.miniCart.minicartAmountBubbleLocator).count(); + let cartItemAmount = await this.page.locator(UIReference.miniCart.minicartAmountBubbleLocator).count(); if(cartItemAmount == 1) { - await this.page.getByLabel(`${selectors.checkout.openCartButtonLabel} ${cartItemAmount} ${selectors.checkout.openCartButtonLabelCont}`).click(); + await this.page.getByLabel(`${UIReference.checkout.openCartButtonLabel} ${cartItemAmount} ${UIReference.checkout.openCartButtonLabelCont}`).click(); } else { - await this.page.getByLabel(`${selectors.checkout.openCartButtonLabel} ${cartItemAmount} ${selectors.checkout.openCartButtonLabelContMultiple}`).click(); + await this.page.getByLabel(`${UIReference.checkout.openCartButtonLabel} ${cartItemAmount} ${UIReference.checkout.openCartButtonLabelContMultiple}`).click(); } // Get values from checkout page - let productInCheckout = this.page.locator(selectors.checkout.cartDetailsLocator).filter({ hasText: productName }).nth(1); - this.productPriceInCheckout = await productInCheckout.getByText(selectors.general.genericPriceSymbol).innerText(); + let productInCheckout = this.page.locator(UIReference.checkout.cartDetailsLocator).filter({ hasText: productName }).nth(1); + this.productPriceInCheckout = await productInCheckout.getByText(UIReference.general.genericPriceSymbol).innerText(); this.productPriceInCheckout = this.productPriceInCheckout.trim(); - let productImage = this.page.locator(selectors.checkout.cartDetailsLocator) + let productImage = this.page.locator(UIReference.checkout.cartDetailsLocator) .filter({ has: this.page.getByRole('img', { name: productName })}); this.productQuantityInCheckout = await productImage.locator('> span').innerText(); @@ -96,10 +96,10 @@ export class CartPage { async calculateProductPricesAndCompare(pricePDP: string, amountPDP:string, priceCheckout:string, amountCheckout:string){ // perform magic to calculate price * amount and mold it into the correct form again - pricePDP = pricePDP.replace(selectors.general.genericPriceSymbol,''); + pricePDP = pricePDP.replace(UIReference.general.genericPriceSymbol,''); let pricePDPInt = Number(pricePDP); let quantityPDPInt = +amountPDP; - let calculatedPricePDP = `${selectors.general.genericPriceSymbol}` + (pricePDPInt * quantityPDPInt).toFixed(2); + let calculatedPricePDP = `${UIReference.general.genericPriceSymbol}` + (pricePDPInt * quantityPDPInt).toFixed(2); expect(amountPDP,`Amount on PDP (${amountPDP}) equals amount in checkout (${amountCheckout})`).toEqual(amountPDP); expect(calculatedPricePDP, `Price * qty on PDP (${calculatedPricePDP}) equals price * qty in checkout (${priceCheckout})`).toEqual(priceCheckout); diff --git a/tests/base/fixtures/checkout.page.ts b/tests/base/fixtures/checkout.page.ts index 9605bae..78bd70a 100644 --- a/tests/base/fixtures/checkout.page.ts +++ b/tests/base/fixtures/checkout.page.ts @@ -1,7 +1,7 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; import slugs from '../config/slugs.json'; export class CheckoutPage { @@ -15,15 +15,15 @@ export class CheckoutPage { constructor(page: Page){ this.page = page; - this.shippingMethodOptionFixed = this.page.getByLabel(selectors.checkout.shippingMethodFixedLabel); - this.paymentMethodOptionCheck = this.page.getByLabel(selectors.checkout.paymentOptionCheckLabel); - this.showDiscountFormButton = this.page.getByRole('button', {name: selectors.checkout.openDiscountFormLabel}); - this.placeOrderButton = this.page.getByRole('button', { name: selectors.checkout.placeOrderButtonLabel }); - this.continueShoppingButton = this.page.getByRole('link', { name: selectors.checkout.continueShoppingLabel }); + this.shippingMethodOptionFixed = this.page.getByLabel(UIReference.checkout.shippingMethodFixedLabel); + this.paymentMethodOptionCheck = this.page.getByLabel(UIReference.checkout.paymentOptionCheckLabel); + this.showDiscountFormButton = this.page.getByRole('button', {name: UIReference.checkout.openDiscountFormLabel}); + this.placeOrderButton = this.page.getByRole('button', { name: UIReference.checkout.placeOrderButtonLabel }); + this.continueShoppingButton = this.page.getByRole('link', { name: UIReference.checkout.continueShoppingLabel }); } async placeOrder(){ - let orderPlacedNotification = verify.checkout.orderPlacedNotification; + let orderPlacedNotification = outcomeMarker.checkout.orderPlacedNotification; await this.page.goto(slugs.checkoutSlug); await this.shippingMethodOptionFixed.check(); @@ -49,61 +49,61 @@ export class CheckoutPage { }); await expect(this.page.getByText(orderPlacedNotification)).toBeVisible(); - let orderNumber = await this.page.locator('p').filter({ hasText: verify.checkout.orderPlacedNumberText }).getByRole('link').innerText(); - console.log(`Your ordernumer is: ${orderNumber}`); + let orderNumber = await this.page.locator('p').filter({ hasText: outcomeMarker.checkout.orderPlacedNumberText }).getByRole('link').innerText(); + // console.log(`Your ordernumer is: ${orderNumber}`); // This await only exists to report order number to the HTML reporter. // TODO: replace this with a proper way to write something to the HTML reporter. - await expect(this.continueShoppingButton, `${verify.checkout.orderPlacedNumberText} ${orderNumber}`).toBeVisible(); + await expect(this.continueShoppingButton, `${outcomeMarker.checkout.orderPlacedNumberText} ${orderNumber}`).toBeVisible(); return orderNumber; } async applyDiscountCodeCheckout(code: string){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountFormButton.click(); } - if(await this.page.getByText(verify.cart.priceReducedSymbols).isVisible()){ + if(await this.page.getByText(outcomeMarker.cart.priceReducedSymbols).isVisible()){ // discount is already active. - let cancelCouponButton = this.page.getByRole('button', { name: selectors.checkout.cancelDiscountButtonLabel }); + let cancelCouponButton = this.page.getByRole('button', { name: UIReference.checkout.cancelDiscountButtonLabel }); await cancelCouponButton.click(); } - let applyCouponCheckoutButton = this.page.getByRole('button', { name: selectors.checkout.applyDiscountButtonLabel }); - let checkoutDiscountField = this.page.getByPlaceholder(selectors.checkout.discountInputFieldLabel); + let applyCouponCheckoutButton = this.page.getByRole('button', { name: UIReference.checkout.applyDiscountButtonLabel }); + let checkoutDiscountField = this.page.getByPlaceholder(UIReference.checkout.discountInputFieldLabel); await checkoutDiscountField.fill(code); await applyCouponCheckoutButton.click(); - await expect(this.page.getByText(`${verify.checkout.couponAppliedNotification}`),`Notification that discount code ${code} has been applied`).toBeVisible({timeout: 30000}); - await expect(this.page.getByText(verify.checkout.checkoutPriceReducedSymbol),`'-$' should be visible on the page`).toBeVisible(); + await expect(this.page.getByText(`${outcomeMarker.checkout.couponAppliedNotification}`),`Notification that discount code ${code} has been applied`).toBeVisible({timeout: 30000}); + await expect(this.page.getByText(outcomeMarker.checkout.checkoutPriceReducedSymbol),`'-$' should be visible on the page`).toBeVisible(); } async enterWrongCouponCode(code: string){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountFormButton.click(); } - let applyCouponCheckoutButton = this.page.getByRole('button', { name: selectors.checkout.applyDiscountButtonLabel }); - let checkoutDiscountField = this.page.getByPlaceholder(selectors.checkout.discountInputFieldLabel); + let applyCouponCheckoutButton = this.page.getByRole('button', { name: UIReference.checkout.applyDiscountButtonLabel }); + let checkoutDiscountField = this.page.getByPlaceholder(UIReference.checkout.discountInputFieldLabel); await checkoutDiscountField.fill(code); await applyCouponCheckoutButton.click(); - await expect(this.page.getByText(verify.checkout.incorrectDiscountNotification), `Code should not work`).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.checkout.incorrectDiscountNotification), `Code should not work`).toBeVisible(); } async removeDiscountCode(){ - if(await this.page.getByPlaceholder(selectors.cart.discountInputFieldLabel).isHidden()){ + if(await this.page.getByPlaceholder(UIReference.cart.discountInputFieldLabel).isHidden()){ // discount field is not open. await this.showDiscountFormButton.click(); } - let cancelCouponButton = this.page.getByRole('button', {name: selectors.cart.cancelCouponButtonLabel}); + let cancelCouponButton = this.page.getByRole('button', {name: UIReference.cart.cancelCouponButtonLabel}); await cancelCouponButton.click(); - await expect(this.page.getByText(verify.checkout.couponRemovedNotification),`Notification should be visible`).toBeVisible(); - await expect(this.page.getByText(verify.checkout.checkoutPriceReducedSymbol),`'-$' should not be on the page`).toBeHidden(); + await expect(this.page.getByText(outcomeMarker.checkout.couponRemovedNotification),`Notification should be visible`).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.checkout.checkoutPriceReducedSymbol),`'-$' should not be on the page`).toBeHidden(); } } \ No newline at end of file diff --git a/tests/base/fixtures/contact.page.ts b/tests/base/fixtures/contact.page.ts index 7ab8b07..ec734ba 100644 --- a/tests/base/fixtures/contact.page.ts +++ b/tests/base/fixtures/contact.page.ts @@ -1,8 +1,8 @@ import {expect, type Locator, type Page} from '@playwright/test'; import {faker} from '@faker-js/faker'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; import slugs from '../config/slugs.json'; export class ContactPage { @@ -14,15 +14,15 @@ export class ContactPage { constructor(page: Page){ this.page = page; - this.nameField = this.page.getByLabel(selectors.credentials.nameFieldLabel); - this.emailField = this.page.getByLabel(selectors.credentials.emailFieldLabel, {exact: true}); - this.messageField = this.page.getByLabel(selectors.contactPage.messageFieldLabel); - this.sendFormButton = this.page.getByRole('button', { name: selectors.general.genericSubmitButtonLabel }); + this.nameField = this.page.getByLabel(UIReference.credentials.nameFieldLabel); + this.emailField = this.page.getByLabel(UIReference.credentials.emailFieldLabel, {exact: true}); + this.messageField = this.page.getByLabel(UIReference.contactPage.messageFieldLabel); + this.sendFormButton = this.page.getByRole('button', { name: UIReference.general.genericSubmitButtonLabel }); } async fillOutForm(){ await this.page.goto(slugs.contact); - let messageSentConfirmationText = verify.contactPage.messageSentConfirmationText; + let messageSentConfirmationText = outcomeMarker.contactPage.messageSentConfirmationText; await this.nameField.fill(faker.person.firstName()); await this.emailField.fill(faker.internet.email()); await this.messageField.fill(faker.lorem.paragraph()); diff --git a/tests/base/fixtures/home.page.ts b/tests/base/fixtures/home.page.ts index 2122a6e..cd753ee 100644 --- a/tests/base/fixtures/home.page.ts +++ b/tests/base/fixtures/home.page.ts @@ -1,6 +1,6 @@ import {type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; export class HomePage { @@ -12,7 +12,7 @@ export class HomePage { } async addHomepageProductToCart(){ - let buyProductButton = this.page.getByRole('button').filter({hasText: selectors.general.addToCartLabel}).first(); + let buyProductButton = this.page.getByRole('button').filter({hasText: UIReference.general.addToCartLabel}).first(); if(await buyProductButton.isVisible()) { await buyProductButton.click(); diff --git a/tests/base/fixtures/login.page.ts b/tests/base/fixtures/login.page.ts index 0f0ffe2..06d0d7c 100644 --- a/tests/base/fixtures/login.page.ts +++ b/tests/base/fixtures/login.page.ts @@ -1,8 +1,7 @@ import {expect, type Locator, type Page} from '@playwright/test'; import slugs from '../config/slugs.json'; -import selectors from '../config/selectors/selectors.json'; -import expected from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; export class LoginPage { readonly page: Page; @@ -12,9 +11,9 @@ export class LoginPage { constructor(page: Page) { this.page = page; - this.loginEmailField = page.getByLabel(selectors.credentials.emailFieldLabel, {exact: true}); - this.loginPasswordField = page.getByLabel(selectors.credentials.passwordFieldLabel, {exact: true}); - this.loginButton = page.getByRole('button', { name: selectors.credentials.loginButtonLabel }); + this.loginEmailField = page.getByLabel(UIReference.credentials.emailFieldLabel, {exact: true}); + this.loginPasswordField = page.getByLabel(UIReference.credentials.passwordFieldLabel, {exact: true}); + this.loginButton = page.getByRole('button', { name: UIReference.credentials.loginButtonLabel }); } async login(email: string, password: string){ @@ -24,6 +23,6 @@ export class LoginPage { // usage of .press("Enter") to prevent webkit issues with button.click(); await this.loginButton.press("Enter"); - await expect(this.page.getByRole('link', { name: selectors.mainMenu.myAccountLogoutItem })).toBeVisible(); + await expect(this.page.getByRole('link', { name: UIReference.mainMenu.myAccountLogoutItem })).toBeVisible(); } } \ No newline at end of file diff --git a/tests/base/fixtures/magentoAdmin.page.ts b/tests/base/fixtures/magentoAdmin.page.ts index 7a04cd3..be763a6 100644 --- a/tests/base/fixtures/magentoAdmin.page.ts +++ b/tests/base/fixtures/magentoAdmin.page.ts @@ -1,6 +1,6 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; import values from '../config/input-values/input-values.json'; export class MagentoAdminPage { @@ -11,9 +11,9 @@ export class MagentoAdminPage { constructor(page: Page) { this.page = page; - this.adminLoginEmailField = page.getByLabel(selectors.magentoAdminPage.usernameFieldLabel); - this.adminLoginPasswordField = page.getByLabel(selectors.magentoAdminPage.passwordFieldLabel); - this.adminLoginButton = page.getByRole('button', {name: selectors.magentoAdminPage.loginButtonLabel}); + this.adminLoginEmailField = page.getByLabel(UIReference.magentoAdminPage.usernameFieldLabel); + this.adminLoginPasswordField = page.getByLabel(UIReference.magentoAdminPage.passwordFieldLabel); + this.adminLoginButton = page.getByRole('button', {name: UIReference.magentoAdminPage.loginButtonLabel}); } async login(username: string, password: string){ @@ -34,16 +34,16 @@ export class MagentoAdminPage { throw new Error("MAGENTO_COUPON_CODE_CHROMIUM, MAGENTO_COUPON_CODE_FIREFOX or MAGENTO_COUPON_CODE_WEBKIT is not defined in your .env file."); } - await this.page.getByRole('link', {name: selectors.magentoAdminPage.navigation.marketingButtonLabel}).click(); + await this.page.getByRole('link', {name: UIReference.magentoAdminPage.navigation.marketingButtonLabel}).click(); await this.page.waitForLoadState('networkidle'); - //await this.page.getByRole('link', {name: selectors.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel}).waitFor(); - await expect(this.page.getByRole('link', {name: selectors.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel})).toBeVisible(); - await this.page.getByRole('link', {name: selectors.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel}).click(); + //await this.page.getByRole('link', {name: UIReference.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel}).waitFor(); + await expect(this.page.getByRole('link', {name: UIReference.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel})).toBeVisible(); + await this.page.getByRole('link', {name: UIReference.magentoAdminPage.subNavigation.cartPriceRulesButtonLabel}).click(); await this.page.waitForLoadState('networkidle'); - await this.page.getByRole('button', {name: selectors.cartPriceRulesPage.addCartPriceRuleButtonLabel}).click(); - await this.page.getByLabel(selectors.cartPriceRulesPage.ruleNameFieldLabel).fill(values.coupon.couponCodeRuleName); + await this.page.getByRole('button', {name: UIReference.cartPriceRulesPage.addCartPriceRuleButtonLabel}).click(); + await this.page.getByLabel(UIReference.cartPriceRulesPage.ruleNameFieldLabel).fill(values.coupon.couponCodeRuleName); - const websiteSelector = this.page.getByLabel(selectors.cartPriceRulesPage.websitesSelectLabel); + const websiteSelector = this.page.getByLabel(UIReference.cartPriceRulesPage.websitesSelectLabel); await websiteSelector.evaluate(select => { for (const option of select.options) { option.selected = true; @@ -51,7 +51,7 @@ export class MagentoAdminPage { select.dispatchEvent(new Event('change')); }); - const customerGroupsSelector = this.page.getByLabel(selectors.cartPriceRulesPage.customerGroupsSelectLabel, { exact: true }); + const customerGroupsSelector = this.page.getByLabel(UIReference.cartPriceRulesPage.customerGroupsSelectLabel, { exact: true }); await customerGroupsSelector.evaluate(select => { for (const option of select.options) { option.selected = true; @@ -59,48 +59,48 @@ export class MagentoAdminPage { select.dispatchEvent(new Event('change')); }); - await this.page.locator(selectors.cartPriceRulesPage.couponTypeSelectField).selectOption({ label: values.coupon.couponType }); - await this.page.getByLabel(selectors.cartPriceRulesPage.couponCodeFieldLabel).fill(magentoCouponCode); + await this.page.locator(UIReference.cartPriceRulesPage.couponTypeSelectField).selectOption({ label: values.coupon.couponType }); + await this.page.getByLabel(UIReference.cartPriceRulesPage.couponCodeFieldLabel).fill(magentoCouponCode); - await this.page.getByText(selectors.cartPriceRulesPage.actionsSubtitleLabel, { exact: true }).click(); - await this.page.getByLabel(selectors.cartPriceRulesPage.discountAmountFieldLabel).fill('10'); + await this.page.getByText(UIReference.cartPriceRulesPage.actionsSubtitleLabel, { exact: true }).click(); + await this.page.getByLabel(UIReference.cartPriceRulesPage.discountAmountFieldLabel).fill('10'); await this.page.getByRole('button', { name: 'Save', exact: true }).click(); } async enableMultipleAdminLogins() { await this.page.waitForLoadState('networkidle'); - await this.page.getByRole('link', { name: selectors.magentoAdminPage.navigation.storesButtonLabel }).click(); - await this.page.getByRole('link', { name: selectors.magentoAdminPage.subNavigation.configurationButtonLabel }).click(); - await this.page.getByRole('tab', { name: selectors.configurationPage.advancedTabLabel }).click(); - await this.page.getByRole('link', { name: selectors.configurationPage.advancedAdministrationTabLabel, exact: true }).click(); + await this.page.getByRole('link', { name: UIReference.magentoAdminPage.navigation.storesButtonLabel }).click(); + await this.page.getByRole('link', { name: UIReference.magentoAdminPage.subNavigation.configurationButtonLabel }).click(); + await this.page.getByRole('tab', { name: UIReference.configurationPage.advancedTabLabel }).click(); + await this.page.getByRole('link', { name: UIReference.configurationPage.advancedAdministrationTabLabel, exact: true }).click(); - if (!await this.page.locator(selectors.configurationPage.allowMultipleLoginsSystemCheckbox).isVisible()) { - await this.page.getByRole('link', { name: selectors.configurationPage.securitySectionLabel }).click(); + if (!await this.page.locator(UIReference.configurationPage.allowMultipleLoginsSystemCheckbox).isVisible()) { + await this.page.getByRole('link', { name: UIReference.configurationPage.securitySectionLabel }).click(); } - await this.page.locator(selectors.configurationPage.allowMultipleLoginsSystemCheckbox).uncheck(); - await this.page.locator(selectors.configurationPage.allowMultipleLoginsSelectField).selectOption({ label: values.adminLogins.allowMultipleLogins }); - await this.page.getByRole('button', { name: selectors.configurationPage.saveConfigButtonLabel }).click(); + await this.page.locator(UIReference.configurationPage.allowMultipleLoginsSystemCheckbox).uncheck(); + await this.page.locator(UIReference.configurationPage.allowMultipleLoginsSelectField).selectOption({ label: values.adminLogins.allowMultipleLogins }); + await this.page.getByRole('button', { name: UIReference.configurationPage.saveConfigButtonLabel }).click(); } async disableLoginCaptcha() { await this.page.waitForLoadState('networkidle'); - await this.page.getByRole('link', { name: selectors.magentoAdminPage.navigation.storesButtonLabel }).click(); - await this.page.getByRole('link', { name: selectors.magentoAdminPage.subNavigation.configurationButtonLabel }).click(); + await this.page.getByRole('link', { name: UIReference.magentoAdminPage.navigation.storesButtonLabel }).click(); + await this.page.getByRole('link', { name: UIReference.magentoAdminPage.subNavigation.configurationButtonLabel }).click(); await this.page.waitForLoadState('networkidle'); - await this.page.getByRole('tab', { name: selectors.configurationPage.customersTabLabel }).click(); - await this.page.getByRole('link', { name: selectors.configurationPage.customerConfigurationTabLabel }).click(); + await this.page.getByRole('tab', { name: UIReference.configurationPage.customersTabLabel }).click(); + await this.page.getByRole('link', { name: UIReference.configurationPage.customerConfigurationTabLabel }).click(); await this.page.waitForLoadState('networkidle'); - if (!await this.page.locator(selectors.configurationPage.captchaSettingSystemCheckbox).isVisible()) { - // await this.page.getByRole('link', { name: new RegExp(selectors.configurationPage.captchaSectionLabel) }).click(); - await this.page.getByRole('link', { name: selectors.configurationPage.captchaSectionLabel }).click(); + if (!await this.page.locator(UIReference.configurationPage.captchaSettingSystemCheckbox).isVisible()) { + // await this.page.getByRole('link', { name: new RegExp(UIReference.configurationPage.captchaSectionLabel) }).click(); + await this.page.getByRole('link', { name: UIReference.configurationPage.captchaSectionLabel }).click(); } - await this.page.locator(selectors.configurationPage.captchaSettingSystemCheckbox).uncheck(); - await this.page.locator(selectors.configurationPage.captchaSettingSelectField).selectOption({ label: values.captcha.captchaDisabled }); - await this.page.getByRole('button', { name: selectors.configurationPage.saveConfigButtonLabel }).click(); + await this.page.locator(UIReference.configurationPage.captchaSettingSystemCheckbox).uncheck(); + await this.page.locator(UIReference.configurationPage.captchaSettingSelectField).selectOption({ label: values.captcha.captchaDisabled }); + await this.page.getByRole('button', { name: UIReference.configurationPage.saveConfigButtonLabel }).click(); await this.page.waitForLoadState('networkidle'); } } diff --git a/tests/base/fixtures/mainmenu.page.ts b/tests/base/fixtures/mainmenu.page.ts index 475e005..b49da71 100644 --- a/tests/base/fixtures/mainmenu.page.ts +++ b/tests/base/fixtures/mainmenu.page.ts @@ -1,8 +1,8 @@ import {expect, type Locator, type Page} from '@playwright/test'; import slugs from '../config/slugs.json'; -import selectors from '../config/selectors/selectors.json'; -import expected from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; export class MainMenuPage { @@ -14,10 +14,10 @@ export class MainMenuPage { constructor(page: Page) { this.page = page; - this.mainMenuAccountButton = page.getByLabel(selectors.mainMenu.myAccountButtonLabel); - this.mainMenuMiniCartButton = page.getByLabel(selectors.mainMenu.miniCartLabel); - this.mainMenuLogoutItem = page.getByTitle(selectors.mainMenu.myAccountLogoutItem); - this.mainMenuMyAccountItem = page.getByTitle(selectors.mainMenu.myAccountButtonLabel); + this.mainMenuAccountButton = page.getByLabel(UIReference.mainMenu.myAccountButtonLabel); + this.mainMenuMiniCartButton = page.getByLabel(UIReference.mainMenu.miniCartLabel); + this.mainMenuLogoutItem = page.getByTitle(UIReference.mainMenu.myAccountLogoutItem); + this.mainMenuMyAccountItem = page.getByTitle(UIReference.mainMenu.myAccountButtonLabel); } async gotoMyAccount(){ @@ -25,7 +25,7 @@ export class MainMenuPage { await this.mainMenuAccountButton.click(); await this.mainMenuMyAccountItem.click(); - await expect(this.page.getByRole('heading', { name: selectors.accountDashboard.accountDashboardTitleLabel })).toBeVisible(); + await expect(this.page.getByRole('heading', { name: UIReference.accountDashboard.accountDashboardTitleLabel })).toBeVisible(); } async gotoAddressBook() { @@ -39,20 +39,20 @@ export class MainMenuPage { if(miniCartItemCount == "1") { //await this.page.getByLabel("Toggle minicart, 1 item").click(); - await this.page.getByLabel(`${selectors.miniCart.miniCartToggleLabelPrefix} ${selectors.miniCart.miniCartToggleLabelOneItem}`).click(); + await this.page.getByLabel(`${UIReference.miniCart.miniCartToggleLabelPrefix} ${UIReference.miniCart.miniCartToggleLabelOneItem}`).click(); } else { - await this.page.getByLabel(`${selectors.miniCart.miniCartToggleLabelPrefix} ${miniCartItemCount} ${selectors.miniCart.miniCartToggleLabelMultiItem}`).click(); + await this.page.getByLabel(`${UIReference.miniCart.miniCartToggleLabelPrefix} ${miniCartItemCount} ${UIReference.miniCart.miniCartToggleLabelMultiItem}`).click(); } } else { // there are no items in the cart - await this.page.getByLabel(`${selectors.miniCart.miniCartToggleLabelPrefix} ${selectors.miniCart.miniCartToggleLabelEmpty}`).click(); + await this.page.getByLabel(`${UIReference.miniCart.miniCartToggleLabelPrefix} ${UIReference.miniCart.miniCartToggleLabelEmpty}`).click(); } */ // await this.page.locator('#menu-cart-icon > span').innerText(); //if(miniCartItemCount = "0") await this.mainMenuMiniCartButton.click(); - await expect(this.page.getByText(expected.miniCart.miniCartTitle)).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.miniCart.miniCartTitle)).toBeVisible(); } async logout(){ @@ -60,6 +60,6 @@ export class MainMenuPage { await this.mainMenuAccountButton.click(); await this.mainMenuLogoutItem.click(); - await expect(this.page.getByText(expected.logout.logoutConfirmationText, { exact: true })).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.logout.logoutConfirmationText, { exact: true })).toBeVisible(); } } \ No newline at end of file diff --git a/tests/base/fixtures/minicart.page.ts b/tests/base/fixtures/minicart.page.ts index 46f2862..181ea50 100644 --- a/tests/base/fixtures/minicart.page.ts +++ b/tests/base/fixtures/minicart.page.ts @@ -1,7 +1,7 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; import slugs from '../config/slugs.json'; export class MiniCartPage { @@ -18,14 +18,14 @@ export class MiniCartPage { constructor(page: Page) { this.page = page; - this.toCheckoutButton = page.getByRole('link', { name: selectors.miniCart.checkOutButtonLabel }); - this.toCartButton = page.getByRole('link', { name: selectors.miniCart.toCartLinkLabel }); - this.editProductButton = page.getByLabel(selectors.miniCart.editProductIconLabel); - this.productQuantityField = page.getByLabel(selectors.miniCart.productQuantityFieldLabel); - this.updateItemButton = page.getByRole('button', { name: selectors.cart.updateItemButtonLabel }); - this.removeProductMiniCartButton = page.getByLabel(selectors.miniCart.removeProductIconLabel).first(); - this.priceOnPDP = page.getByLabel(selectors.general.genericPriceLabel).getByText(selectors.general.genericPriceSymbol); - this.priceInMinicart = page.getByText(selectors.general.genericPriceSymbol).first(); + this.toCheckoutButton = page.getByRole('link', { name: UIReference.miniCart.checkOutButtonLabel }); + this.toCartButton = page.getByRole('link', { name: UIReference.miniCart.toCartLinkLabel }); + this.editProductButton = page.getByLabel(UIReference.miniCart.editProductIconLabel); + this.productQuantityField = page.getByLabel(UIReference.miniCart.productQuantityFieldLabel); + this.updateItemButton = page.getByRole('button', { name: UIReference.cart.updateItemButtonLabel }); + this.removeProductMiniCartButton = page.getByLabel(UIReference.miniCart.removeProductIconLabel).first(); + this.priceOnPDP = page.getByLabel(UIReference.general.genericPriceLabel).getByText(UIReference.general.genericPriceSymbol); + this.priceInMinicart = page.getByText(UIReference.general.genericPriceSymbol).first(); } async goToCheckout(){ @@ -39,13 +39,13 @@ export class MiniCartPage { } async removeProductFromMinicart() { - let productRemovedNotification = verify.miniCart.productRemovedConfirmation; + let productRemovedNotification = outcomeMarker.miniCart.productRemovedConfirmation; await this.removeProductMiniCartButton.click(); await expect(this.page.getByText(productRemovedNotification)).toBeVisible(); } async updateProduct(amount: string){ - let productQuantityChangedNotification = verify.miniCart.productQuantityChangedConfirmation; + let productQuantityChangedNotification = outcomeMarker.miniCart.productQuantityChangedConfirmation; await this.editProductButton.click(); await expect(this.page).toHaveURL(new RegExp(`${slugs.cartProductChangeSlug}.*`)); @@ -53,16 +53,16 @@ export class MiniCartPage { await this.updateItemButton.click(); await expect(this.page.getByText(productQuantityChangedNotification)).toBeVisible(); - let productQuantityInCart = await this.page.getByLabel(selectors.cart.cartQuantityLabel).first().inputValue(); - console.log(productQuantityInCart); + let productQuantityInCart = await this.page.getByLabel(UIReference.cart.cartQuantityLabel).first().inputValue(); + // console.log(productQuantityInCart); expect(productQuantityInCart).toBe(amount); } async checkPriceWithProductPage() { - const priceOnPage = await this.page.locator(selectors.productPage.simpleProductPrice).first().innerText(); + const priceOnPage = await this.page.locator(UIReference.productPage.simpleProductPrice).first().innerText(); const productTitle = await this.page.getByRole('heading', { level : 1}).innerText(); const productListing = this.page.locator('div').filter({hasText: productTitle}); - const priceInMinicart = await productListing.locator(selectors.miniCart.minicartPriceFieldClass).first().textContent(); + const priceInMinicart = await productListing.locator(UIReference.miniCart.minicartPriceFieldClass).first().textContent(); //expect(priceOnPage).toBe(priceInMinicart); expect(priceOnPage, `Expect these prices to be the same: priceOnpage: ${priceOnPage} and priceInMinicart: ${priceInMinicart}`).toBe(priceInMinicart); } diff --git a/tests/base/fixtures/newsletter.page.ts b/tests/base/fixtures/newsletter.page.ts index 55d310b..b557c1d 100644 --- a/tests/base/fixtures/newsletter.page.ts +++ b/tests/base/fixtures/newsletter.page.ts @@ -1,6 +1,6 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; export class NewsletterSubscriptionPage { readonly page: Page; @@ -9,15 +9,15 @@ export class NewsletterSubscriptionPage { constructor(page: Page) { this.page = page; - this.newsletterCheckElement = page.getByLabel(selectors.newsletterSubscriptions.generalSubscriptionCheckLabel); - this.saveSubscriptionsButton = page.getByRole('button', {name:selectors.newsletterSubscriptions.saveSubscriptionsButton}); + this.newsletterCheckElement = page.getByLabel(UIReference.newsletterSubscriptions.generalSubscriptionCheckLabel); + this.saveSubscriptionsButton = page.getByRole('button', {name:UIReference.newsletterSubscriptions.saveSubscriptionsButton}); } async updateNewsletterSubscription(){ if(await this.newsletterCheckElement.isChecked()) { // user is already subscribed, test runs unsubscribe - var subscriptionUpdatedNotification = verify.account.newsletterRemovedNotification; + var subscriptionUpdatedNotification = outcomeMarker.account.newsletterRemovedNotification; await this.newsletterCheckElement.uncheck(); await this.saveSubscriptionsButton.click(); @@ -26,7 +26,7 @@ export class NewsletterSubscriptionPage { } else { // user is not yet subscribed, test runs subscribe - subscriptionUpdatedNotification = verify.account.newsletterSavedNotification; + subscriptionUpdatedNotification = outcomeMarker.account.newsletterSavedNotification; await this.newsletterCheckElement.check(); await this.saveSubscriptionsButton.click(); diff --git a/tests/base/fixtures/product.page.ts b/tests/base/fixtures/product.page.ts index bf16337..a6e5cbb 100644 --- a/tests/base/fixtures/product.page.ts +++ b/tests/base/fixtures/product.page.ts @@ -1,7 +1,7 @@ import {expect, type Locator, type Page} from '@playwright/test'; -import selectors from '../config/selectors/selectors.json'; -import verify from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; export class ProductPage { readonly page: Page; @@ -16,7 +16,7 @@ export class ProductPage { async addSimpleProductToCart(product: string, url: string, quantity?: string) { await this.page.goto(url); this.simpleProductTitle = this.page.getByRole('heading', {name: product, exact:true}); - let productAddedNotification = `${verify.productPage.simpleProductAddedNotification} ${product}`; + let productAddedNotification = `${outcomeMarker.productPage.simpleProductAddedNotification} ${product}`; await this.page.goto(url); this.simpleProductTitle = this.page.getByRole('heading', {name: product, exact:true}); @@ -25,7 +25,7 @@ export class ProductPage { if(quantity){ // set quantity - await this.page.getByLabel(selectors.productPage.quantityFieldLabel).fill('2'); + await this.page.getByLabel(UIReference.productPage.quantityFieldLabel).fill('2'); } await this.simpleProductAddToCartButon.click(); @@ -33,11 +33,11 @@ export class ProductPage { } async addConfigurableProductToCart(){ - const productOptions = this.page.locator(selectors.productPage.configurableProductOptionForm); + const productOptions = this.page.locator(UIReference.productPage.configurableProductOptionForm); // loop through each radiogroup (product option) within the form for (const option of await productOptions.getByRole('radiogroup').all()) { - await option.locator(selectors.productPage.configurableProductOptionValue).first().check(); + await option.locator(UIReference.productPage.configurableProductOptionValue).first().check(); } await this.simpleProductAddToCartButon.click(); diff --git a/tests/base/fixtures/register.page.ts b/tests/base/fixtures/register.page.ts index 5bbbdd9..1358a86 100644 --- a/tests/base/fixtures/register.page.ts +++ b/tests/base/fixtures/register.page.ts @@ -1,9 +1,8 @@ import {expect, type Locator, type Page} from '@playwright/test'; import slugs from '../config/slugs.json'; -import selectors from '../config/selectors/selectors.json'; -import inputvalues from '../config/input-values/input-values.json'; -import expected from '../config/expected/expected.json'; +import UIReference from '../config/element-identifiers/element-identifiers.json'; +import outcomeMarker from '../config/outcome-markers/outcome-markers.json'; export class RegisterPage { readonly page: Page; @@ -16,12 +15,12 @@ export class RegisterPage { constructor(page: Page){ this.page = page; - this.accountCreationFirstNameField = page.getByLabel(selectors.personalInformation.firstNameLabel); - this.accountCreationLastNameField = page.getByLabel(selectors.personalInformation.lastNameLabel); - this.accountCreationEmailField = page.getByLabel(selectors.credentials.emailFieldLabel, { exact: true}); - this.accountCreationPasswordField = page.getByLabel(selectors.credentials.passwordFieldLabel, { exact: true }); - this.accountCreationPasswordRepeatField = page.getByLabel(selectors.credentials.passwordConfirmFieldLabel); - this.accountCreationConfirmButton = page.getByRole('button', {name: selectors.accountCreation.createAccountButtonLabel}); + this.accountCreationFirstNameField = page.getByLabel(UIReference.personalInformation.firstNameLabel); + this.accountCreationLastNameField = page.getByLabel(UIReference.personalInformation.lastNameLabel); + this.accountCreationEmailField = page.getByLabel(UIReference.credentials.emailFieldLabel, { exact: true}); + this.accountCreationPasswordField = page.getByLabel(UIReference.credentials.passwordFieldLabel, { exact: true }); + this.accountCreationPasswordRepeatField = page.getByLabel(UIReference.credentials.passwordConfirmFieldLabel); + this.accountCreationConfirmButton = page.getByRole('button', {name: UIReference.accountCreation.createAccountButtonLabel}); } @@ -35,8 +34,8 @@ export class RegisterPage { await this.accountCreationPasswordRepeatField.fill(password); await this.accountCreationConfirmButton.click(); - await expect(this.page.getByText(expected.account.accountCreatedNotificationText)).toBeVisible(); + await expect(this.page.getByText(outcomeMarker.account.accountCreatedNotificationText)).toBeVisible(); // log credentials to console to add to .env file - console.log(`Account created with credentials: email address "${email}" and password "${password}"`); + //console.log(`Account created with credentials: email address "${email}" and password "${password}"`); } } \ No newline at end of file diff --git a/tests/base/home.spec.ts b/tests/base/home.spec.ts index a256146..8c987af 100644 --- a/tests/base/home.spec.ts +++ b/tests/base/home.spec.ts @@ -2,7 +2,7 @@ import {test, expect} from '@playwright/test'; import {MainMenuPage} from './fixtures/mainmenu.page'; import {HomePage} from './fixtures/home.page'; -import verify from './config/expected/expected.json'; +import outcomeMarker from './config/outcome-markers/outcome-markers.json'; test('Add product on homepage to cart',{ tag: '@homepage',}, async ({page}) => { const homepage = new HomePage(page); @@ -11,5 +11,5 @@ test('Add product on homepage to cart',{ tag: '@homepage',}, async ({page}) => { await page.goto(''); await homepage.addHomepageProductToCart(); await mainmenu.openMiniCart(); - await expect(page.getByText('x ' + verify.homePage.firstProductName), 'product should be visible in cart').toBeVisible(); + await expect(page.getByText('x ' + outcomeMarker.homePage.firstProductName), 'product should be visible in cart').toBeVisible(); }); \ No newline at end of file diff --git a/tests/base/minicart.spec.ts b/tests/base/minicart.spec.ts index 8309d45..072915c 100644 --- a/tests/base/minicart.spec.ts +++ b/tests/base/minicart.spec.ts @@ -4,9 +4,8 @@ import {ProductPage} from './fixtures/product.page'; import { MiniCartPage } from './fixtures/minicart.page'; import slugs from './config/slugs.json'; -import inputvalues from './config/input-values/input-values.json'; -import selectors from './config/selectors/selectors.json'; -import verify from './config/expected/expected.json'; +import UIReference from './config/element-identifiers/element-identifiers.json'; +import outcomeMarker from './config/outcome-markers/outcome-markers.json'; test.describe('Minicart Actions', {annotation: {type: 'Minicart', description: 'Minicart simple product tests'},}, () => { @@ -26,9 +25,9 @@ test.describe('Minicart Actions', {annotation: {type: 'Minicart', description: ' const productPage = new ProductPage(page); await page.goto(slugs.productpage.simpleProductSlug); - await productPage.addSimpleProductToCart(selectors.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); + await productPage.addSimpleProductToCart(UIReference.productPage.simpleProductTitle, slugs.productpage.simpleProductSlug); await mainMenu.openMiniCart(); - await expect(page.getByText(verify.miniCart.simpleProductInCartTitle)).toBeVisible(); + await expect(page.getByText(outcomeMarker.miniCart.simpleProductInCartTitle)).toBeVisible(); }); /** @@ -117,7 +116,7 @@ test.describe('Minicart Actions', {annotation: {type: 'Minicart', description: ' await page.goto(slugs.productpage.configurableProductSlug); await productPage.addConfigurableProductToCart(); await mainMenu.openMiniCart(); - await expect(page.getByText(verify.miniCart.configurableProductMinicartTitle)).toBeVisible(); + await expect(page.getByText(outcomeMarker.miniCart.configurableProductMinicartTitle)).toBeVisible(); }); /** diff --git a/tests/base/register.spec.ts b/tests/base/register.spec.ts index a7f9d85..670e26f 100644 --- a/tests/base/register.spec.ts +++ b/tests/base/register.spec.ts @@ -15,7 +15,7 @@ test.use({ storageState: { cookies: [], origins: [] } }); * @then I click the 'Create account' button * @then I should see a messsage confirming my account was created */ -test('User can register an account', { tag: '@setup', }, async ({page, browserName}) => { +test('User can register an account', { tag: '@setup', }, async ({page, browserName}, testInfo) => { const registerPage = new RegisterPage(page); // Retrieve desired password from .env file @@ -38,4 +38,5 @@ test('User can register an account', { tag: '@setup', }, async ({page, browserNa // end of browserNameEmailSection await registerPage.createNewAccount(firstName, lastName, accountEmail, existingAccountPassword); + testInfo.annotations.push({ type: 'Notification: account created!', description: `Credentials used: ${accountEmail}, password: ${existingAccountPassword}` }); });