diff --git a/package.json b/package.json index 97e8b1f..dd66ffa 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "license": "ISC", "description": "", "devDependencies": { + "@faker-js/faker": "^9.4.0", "@playwright/test": "^1.47.2", "@types/node": "^22.7.4" }, diff --git a/tests/base/account.spec.ts b/tests/base/account.spec.ts index e130aab..76474aa 100644 --- a/tests/base/account.spec.ts +++ b/tests/base/account.spec.ts @@ -108,21 +108,15 @@ 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}); + if(await addNewAddressTitle.isHidden()) { await accountPage.deleteAllAddresses(); testInfo.annotations.push({ type: 'Notification: deleted addresses', description: `All addresses are deleted to recreate the first address flow.` }); await page.goto(slugs.account.addressNewSlug); } - let phoneNumberValue = inputvalues.firstAddress.firstPhoneNumberValue; - let addressValue = inputvalues.firstAddress.firstStreetAddressValue; - let zipCodeValue = inputvalues.firstAddress.firstZipCodeValue; - let cityNameValue = inputvalues.firstAddress.firstCityValue; - let stateValue = inputvalues.firstAddress.firstProvinceValue; - - await accountPage.addNewAddress(phoneNumberValue, addressValue, zipCodeValue, cityNameValue, stateValue); + await accountPage.addNewAddress(); }); /** @@ -136,16 +130,9 @@ test.describe.serial('Account address book actions', { annotation: {type: 'Accou */ test('I can add another address',{ tag: '@address-actions', }, async ({page}) => { await page.goto(slugs.account.addressNewSlug); - const accountPage = new AccountPage(page); - - let phoneNumberValue = inputvalues.secondAddress.secondPhoneNumberValue; - let addressValue = inputvalues.secondAddress.secondStreetAddressValue; - let zipCodeValue = inputvalues.secondAddress.secondZipCodeValue; - let cityNameValue = inputvalues.secondAddress.secondCityValue; - let stateValue = inputvalues.secondAddress.secondProvinceValue; - - await accountPage.addNewAddress(phoneNumberValue, addressValue, zipCodeValue, cityNameValue, stateValue); + + await accountPage.addNewAddress(); }); /** @@ -160,22 +147,18 @@ test.describe.serial('Account address book actions', { annotation: {type: 'Accou * @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}, testInfo) => { + test('I can edit an existing address',{ tag: '@address-actions', }, async ({page}) => { const accountPage = new AccountPage(page); - let newFirstName = inputvalues.editedAddress.editfirstNameValue; - let newLastName = inputvalues.editedAddress.editLastNameValue; - let newStreet = inputvalues.editedAddress.editStreetAddressValue; - let newZipCode = inputvalues.editedAddress.editZipCodeValue; - let newCity = inputvalues.editedAddress.editCityValue; - let newState = inputvalues.editedAddress.editStateValue; - + await page.goto(slugs.account.addressNewSlug); let editAddressButton = page.getByRole('link', {name: selectors.accountDashboard.editAddressIconButton}).first(); - if(await editAddressButton.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); + + if(await editAddressButton.isHidden()){ + // The edit address button was not found, add another address first. + await accountPage.addNewAddress(); } - await accountPage.editExistingAddress(newFirstName, newLastName, newStreet, newZipCode, newCity, newState); + await page.goto(slugs.account.addressBookSlug); + await accountPage.editExistingAddress(); }); /** diff --git a/tests/base/checkout.spec.ts b/tests/base/checkout.spec.ts index 0819eae..e42045a 100644 --- a/tests/base/checkout.spec.ts +++ b/tests/base/checkout.spec.ts @@ -42,6 +42,7 @@ test.describe('Checkout (login required)', () => { const loginPage = new LoginPage(page); await loginPage.login(emailInputValue, passwordInputValue); + await page.goto(slugs.checkoutSlug); }); /** @@ -68,18 +69,16 @@ test.describe('Checkout (login required)', () => { if(!addressAlreadyAdded){ // Address field is visible and addressalreadyAdded is not true, so we need to add an address to the account. const accountPage = new AccountPage(page); - - let phoneNumberValue = inputvalues.firstAddress.firstPhoneNumberValue; - let addressValue = inputvalues.firstAddress.firstStreetAddressValue; - let zipCodeValue = inputvalues.firstAddress.firstZipCodeValue; - let cityNameValue = inputvalues.firstAddress.firstCityValue; - let stateValue = inputvalues.firstAddress.firstProvinceValue; - - await accountPage.addNewAddress(phoneNumberValue, addressValue, zipCodeValue, cityNameValue, stateValue); + await accountPage.addNewAddress(); } else { throw new Error(`Address field is visible even though an address has been added to the account.`); } } + + // expect to see radio button to select existing address + let shippingRadioButton = page.locator(selectors.checkout.shippingAddressRadioLocator).first(); + await expect(shippingRadioButton, 'Radio button to select address should be visible').toBeVisible(); + }); @@ -94,11 +93,11 @@ test.describe('Checkout (login required)', () => { * @then I should see a confirmation that my order has been placed * @and a order number should be created and show to me */ - test('Place order for simple product',{ tag: '@simple-product-order',}, async ({page}) => { + test('Place order for simple product',{ tag: '@simple-product-order',}, async ({page}, testInfo) => { const checkoutPage = new CheckoutPage(page); - await checkoutPage.placeOrder(); + let orderNumber = await checkoutPage.placeOrder(); + testInfo.annotations.push({ type: 'Order number', description: `${orderNumber}` }); }); - }); test.describe('Checkout (guest)', () => { diff --git a/tests/base/config/expected/expected.json b/tests/base/config/expected/expected.json index 7dc1301..970321c 100644 --- a/tests/base/config/expected/expected.json +++ b/tests/base/config/expected/expected.json @@ -37,7 +37,9 @@ "couponAppliedNotification": "Your coupon was successfully applied", "couponRemovedNotification": "Your coupon was successfully removed", "checkoutPriceReducedSymbol": "-$", - "incorrectDiscountNotification": "The coupon code isn't valid. Verify the code and try again." + "incorrectDiscountNotification": "The coupon code isn't valid. Verify the code and try again.", + "orderPlacedNotification": "Thank you for your purchase!", + "orderPlacedNumberText": "Your order number is:" }, "contactPage": { "messageSentConfirmationText": "Thanks for contacting us with" diff --git a/tests/base/config/selectors/selectors.json b/tests/base/config/selectors/selectors.json index b3a684e..e16f475 100644 --- a/tests/base/config/selectors/selectors.json +++ b/tests/base/config/selectors/selectors.json @@ -89,7 +89,8 @@ "openCartButtonLabel": "Cart", "openCartButtonLabelCont": "item", "openCartButtonLabelContMultiple": "items", - "cartDetailsLocator": "#checkout-cart-details div" + "cartDetailsLocator": "#checkout-cart-details div", + "shippingAddressRadioLocator": "#shipping-details input[type='radio']" }, "miniCart": { "checkOutButtonLabel": "Checkout", diff --git a/tests/base/contact.spec.ts b/tests/base/contact.spec.ts index 224ad6c..cc77ea5 100644 --- a/tests/base/contact.spec.ts +++ b/tests/base/contact.spec.ts @@ -1,9 +1,6 @@ import {test, expect} from '@playwright/test'; import { ContactPage } from './fixtures/contact.page'; -import slugs from './config/slugs.json'; -import inputvalues from './config/input-values/input-values.json'; - /** * @feature Magento 2 Contact Form * @scenario User fills in the contact form and sends a message @@ -16,10 +13,5 @@ import inputvalues from './config/input-values/input-values.json'; */ test('I can send a message through the contact form',{ tag: '@contact-form',}, async ({page}) => { const contactPage = new ContactPage(page); - let formName = inputvalues.accountCreation.firstNameValue; - let formEmail = inputvalues.contact.contactFormEmailValue; - let message = inputvalues.contact.contactFormMessage; - - await page.goto(slugs.contact); - await contactPage.fillOutForm(formName,formEmail,message); + await contactPage.fillOutForm(); }); \ No newline at end of file diff --git a/tests/base/fixtures/account.page.ts b/tests/base/fixtures/account.page.ts index 946f89a..5bf8280 100644 --- a/tests/base/fixtures/account.page.ts +++ b/tests/base/fixtures/account.page.ts @@ -1,4 +1,5 @@ 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'; @@ -66,28 +67,31 @@ export class AccountPage { this.editAddressButton = page.getByRole('link', {name: selectors.accountDashboard.editAddressIconButton}).first(); } - async addNewAddress(phonenumber: string,streetName: string, zipCode: string, cityName: string, state: string){ + async addNewAddress(){ let addressAddedNotification = verify.address.newAddressAddedNotifcation; + let streetName = faker.location.streetAddress(); // Name should be filled in automatically. await expect(this.firstNameField).not.toBeEmpty(); await expect(this.lastNameField).not.toBeEmpty(); - await this.phoneNumberField.fill(phonenumber); + await this.phoneNumberField.fill(faker.phone.number()); await this.streetAddressField.fill(streetName); - await this.zipCodeField.fill(zipCode); - await this.cityField.fill(cityName); - await this.stateSelectorField.selectOption(state); + await this.zipCodeField.fill(faker.location.zipCode()); + await this.cityField.fill(faker.location.city()); + await this.stateSelectorField.selectOption(faker.location.state()); await this.saveAddressButton.click(); await this.page.waitForLoadState(); - await expect(this.page.getByText(addressAddedNotification)).toBeVisible(); + await expect.soft(this.page.getByText(addressAddedNotification)).toBeVisible(); await expect(this.page.getByText(streetName).last()).toBeVisible(); } + - async editExistingAddress(firstName: string, lastName: string, streetName: string, zipCode: string, cityName: string, state: string){ + async editExistingAddress(){ // the notification for a modified address is the same as the notification for a new address. let addressModifiedNotification = verify.address.newAddressAddedNotifcation; + let streetName = faker.location.streetAddress(); await this.editAddressButton.click(); @@ -95,17 +99,17 @@ export class AccountPage { await expect(this.firstNameField).not.toBeEmpty(); await expect(this.lastNameField).not.toBeEmpty(); - await this.firstNameField.fill(firstName); - await this.lastNameField.fill(lastName); + await this.firstNameField.fill(faker.person.firstName()); + await this.lastNameField.fill(faker.person.lastName()); await this.streetAddressField.fill(streetName); - await this.zipCodeField.fill(zipCode); - await this.cityField.fill(cityName); - await this.stateSelectorField.selectOption(state); + await this.zipCodeField.fill(faker.location.zipCode()); + await this.cityField.fill(faker.location.city()); + await this.stateSelectorField.selectOption(faker.location.state()); await this.saveAddressButton.click(); await this.page.waitForLoadState(); - await expect(this.page.getByText(addressModifiedNotification)).toBeVisible(); + await expect.soft(this.page.getByText(addressModifiedNotification)).toBeVisible(); await expect(this.page.getByText(streetName).last()).toBeVisible(); } diff --git a/tests/base/fixtures/checkout.page.ts b/tests/base/fixtures/checkout.page.ts index bafebb8..9605bae 100644 --- a/tests/base/fixtures/checkout.page.ts +++ b/tests/base/fixtures/checkout.page.ts @@ -23,7 +23,7 @@ export class CheckoutPage { } async placeOrder(){ - let orderPlacedNotification = "Thank you for your purchase!"; + let orderPlacedNotification = verify.checkout.orderPlacedNotification; await this.page.goto(slugs.checkoutSlug); await this.shippingMethodOptionFixed.check(); @@ -49,10 +49,12 @@ export class CheckoutPage { }); await expect(this.page.getByText(orderPlacedNotification)).toBeVisible(); - let orderNumber = await this.page.locator('p').filter({ hasText: 'Your order number is:' }).getByRole('link').innerText(); + let orderNumber = await this.page.locator('p').filter({ hasText: verify.checkout.orderPlacedNumberText }).getByRole('link').innerText(); console.log(`Your ordernumer is: ${orderNumber}`); - await expect(this.continueShoppingButton, `Your order number is: ${orderNumber}`).toBeVisible(); + // 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(); return orderNumber; } diff --git a/tests/base/fixtures/contact.page.ts b/tests/base/fixtures/contact.page.ts index 01cd963..7ab8b07 100644 --- a/tests/base/fixtures/contact.page.ts +++ b/tests/base/fixtures/contact.page.ts @@ -1,6 +1,9 @@ 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 slugs from '../config/slugs.json'; export class ContactPage { readonly page: Page; @@ -17,11 +20,12 @@ export class ContactPage { this.sendFormButton = this.page.getByRole('button', { name: selectors.general.genericSubmitButtonLabel }); } - async fillOutForm(name: string, email: string, message: string){ + async fillOutForm(){ + await this.page.goto(slugs.contact); let messageSentConfirmationText = verify.contactPage.messageSentConfirmationText; - await this.nameField.fill(name); - await this.emailField.fill(email); - await this.messageField.fill(message); + await this.nameField.fill(faker.person.firstName()); + await this.emailField.fill(faker.internet.email()); + await this.messageField.fill(faker.lorem.paragraph()); await this.sendFormButton.click(); await expect(this.page.getByText(messageSentConfirmationText)).toBeVisible(); diff --git a/tests/base/register.spec.ts b/tests/base/register.spec.ts index 9b643b5..a7f9d85 100644 --- a/tests/base/register.spec.ts +++ b/tests/base/register.spec.ts @@ -37,7 +37,5 @@ test('User can register an account', { tag: '@setup', }, async ({page, browserNa } // end of browserNameEmailSection - - // password is retrieved from .env file in createNewAccount() function await registerPage.createNewAccount(firstName, lastName, accountEmail, existingAccountPassword); });