diff --git a/e2e/fixtures/account/orders-page.ts b/e2e/fixtures/account/orders-page.ts index 3fcd161fe..3b3f9a9f4 100644 --- a/e2e/fixtures/account/orders-page.ts +++ b/e2e/fixtures/account/orders-page.ts @@ -2,6 +2,7 @@ import { Locator, Page } from "@playwright/test" import { AccountPage } from "./account-page" export class OrdersPage extends AccountPage { + ordersWrapper: Locator noOrdersContainer: Locator continueShoppingButton: Locator orderCard: Locator @@ -9,6 +10,7 @@ export class OrdersPage extends AccountPage { constructor(page: Page) { super(page) + this.ordersWrapper = page.getByTestId("orders-page-wrapper") this.noOrdersContainer = page.getByTestId("no-orders-container") this.continueShoppingButton = page.getByTestId("continue-shopping-button") this.orderCard = page.getByTestId("order-card") @@ -38,4 +40,10 @@ export class OrdersPage extends AccountPage { items, } } + + async goto() { + await super.goto() + await this.ordersLink.click() + await this.ordersWrapper.waitFor({ state: "visible" }) + } } diff --git a/e2e/fixtures/base/cart-dropdown.ts b/e2e/fixtures/base/cart-dropdown.ts index bdd734bb0..40a1440bb 100644 --- a/e2e/fixtures/base/cart-dropdown.ts +++ b/e2e/fixtures/base/cart-dropdown.ts @@ -19,23 +19,33 @@ export class CartDropdown { await this.navCartLink.hover() } - async getCartItem(name: string) { - const cartItem = this.cartDropdown.getByTestId("cart-item").filter({ - hasText: name, - }) - const quantity = cartItem - .getByTestId("cart-item-quantity") - .getAttribute("data-value") - const variant = cartItem - .getByTestId("cart-item-variant") - .getAttribute("data-value") + async close() { + if (await this.cartDropdown.isVisible()) { + const box = await this.cartDropdown.boundingBox() + if (!box) { + return + } + await this.page.mouse.move(box.x + box.width / 4, box.y + box.height / 4) + await this.page.mouse.move(5, 10) + } + } + + async getCartItem(name: string, variant: string) { + const cartItem = this.cartDropdown + .getByTestId("cart-item") + .filter({ + hasText: name, + }) + .filter({ + hasText: `Variant: ${variant}`, + }) return { locator: cartItem, productLink: cartItem.getByTestId("product-link"), removeButton: cartItem.getByTestId("cart-item-remove-button"), name, - quantity, - variant, + quantity: cartItem.getByTestId("cart-item-quantity"), + variant: cartItem.getByTestId("cart-item-variant"), } } } diff --git a/e2e/fixtures/cart-page.ts b/e2e/fixtures/cart-page.ts index 6655cbad7..138305040 100644 --- a/e2e/fixtures/cart-page.ts +++ b/e2e/fixtures/cart-page.ts @@ -23,6 +23,7 @@ export class CartPage extends BasePage { cartGiftCardAmount: Locator cartShipping: Locator cartTaxes: Locator + cartTotal: Locator checkoutButton: Locator constructor(page: Page) { @@ -61,22 +62,23 @@ export class CartPage extends BasePage { ) this.cartShipping = this.container.getByTestId("cart-shipping") this.cartTaxes = this.container.getByTestId("cart-taxes") + this.cartTotal = this.container.getByTestId("cart-total") } async getProduct(title: string, variant: string) { const productRow = this.productRow .filter({ - has: this.productTitle.filter({ hasText: title }), + hasText: title, }) .filter({ - has: this.productVariant.filter({ hasText: variant }), + hasText: `Variant: ${variant}`, }) return { productRow, title: productRow.getByTestId("product-title"), variant: productRow.getByTestId("product-variant"), deleteButton: productRow.getByTestId("delete-button"), - quantitySelect: productRow.getByTestId("quantity-select"), + quantitySelect: productRow.getByTestId("product-select-button"), price: productRow.getByTestId("product-unit-price"), total: productRow.getByTestId("product-price"), } diff --git a/e2e/fixtures/checkout-page.ts b/e2e/fixtures/checkout-page.ts index 1f670d122..1bf52434f 100644 --- a/e2e/fixtures/checkout-page.ts +++ b/e2e/fixtures/checkout-page.ts @@ -13,6 +13,7 @@ export class CheckoutPage extends BasePage { shippingAddressOptions: Locator shippingAddressOption: Locator + billingAddressCheckbox: Locator billingAddressInput: Locator billingCityInput: Locator billingCompanyInput: Locator @@ -24,6 +25,7 @@ export class CheckoutPage extends BasePage { shippingAddressInput: Locator shippingCityInput: Locator shippingCompanyInput: Locator + shippingEmailInput: Locator shippingFirstNameInput: Locator shippingLastNameInput: Locator shippingPhoneInput: Locator @@ -67,6 +69,7 @@ export class CheckoutPage extends BasePage { cartGiftCardAmount: Locator cartShipping: Locator cartTaxes: Locator + cartTotal: Locator itemsTable: Locator itemRow: Locator itemTitle: Locator @@ -96,6 +99,9 @@ export class CheckoutPage extends BasePage { this.shippingAddressOption = this.container.getByTestId( "shipping-address-option" ) + this.billingAddressCheckbox = this.container.getByTestId( + "billing-address-checkbox" + ) this.billingAddressInput = this.container.getByTestId( "billing-address-input" ) @@ -118,7 +124,10 @@ export class CheckoutPage extends BasePage { "shipping-address-input" ) this.shippingCityInput = this.container.getByTestId("shipping-city-input") - this.shippingCompanyInput = this.container.getByTestId("shipping-company-input") + this.shippingCompanyInput = this.container.getByTestId( + "shipping-company-input" + ) + this.shippingEmailInput = this.container.getByTestId("shipping-email-input") this.shippingFirstNameInput = this.container.getByTestId( "shipping-first-name-input" ) @@ -158,7 +167,7 @@ export class CheckoutPage extends BasePage { ) this.deliveryOptionRadio = this.container.getByTestId( - "deliver-option-radio" + "delivery-option-radio" ) this.deliveryOptionErrorMessage = this.container.getByTestId( "delivery-option-error-message" @@ -214,6 +223,7 @@ export class CheckoutPage extends BasePage { ) this.cartShipping = this.container.getByTestId("cart-shipping") this.cartTaxes = this.container.getByTestId("cart-taxes") + this.cartTotal = this.container.getByTestId("cart-total") this.itemsTable = this.container.getByTestId("items-table") this.itemRow = this.container.getByTestId("item-row") this.itemTitle = this.container.getByTestId("item-title") @@ -241,7 +251,7 @@ export class CheckoutPage extends BasePage { (opts) => { const select = opts[0] const choice = opts[1] - return (select.textContent||"").includes(choice) + return (select.textContent || "").includes(choice) }, [selectHandle, address] as [ElementHandle, string] ) diff --git a/e2e/fixtures/order-page.ts b/e2e/fixtures/order-page.ts index 6f1e07e6b..a8840e686 100644 --- a/e2e/fixtures/order-page.ts +++ b/e2e/fixtures/order-page.ts @@ -61,17 +61,16 @@ export class OrderPage extends BasePage { async getProduct(title: string, variant: string) { const productRow = this.productRow .filter({ - has: this.productTitle.filter({ hasText: title }), + hasText: title, }) .filter({ - has: this.productVariant.filter({ hasText: variant }), + hasText: `Variant: ${variant}`, }) return { productRow, - title: productRow.getByTestId("product-title"), + name: productRow.getByTestId("product-name"), variant: productRow.getByTestId("product-variant"), - deleteButton: productRow.getByTestId("delete-button"), - quantitySelect: productRow.getByTestId("quantity-select"), + quantity: productRow.getByTestId("product-quantity"), price: productRow.getByTestId("product-unit-price"), total: productRow.getByTestId("product-price"), } diff --git a/e2e/fixtures/product-page.ts b/e2e/fixtures/product-page.ts index c3c7bb45b..66b79ba9e 100644 --- a/e2e/fixtures/product-page.ts +++ b/e2e/fixtures/product-page.ts @@ -9,6 +9,7 @@ export class ProductPage extends BasePage { productTitle: Locator productDescription: Locator productOptions: Locator + productPrice: Locator addProductButton: Locator mobileActionsContainer: Locator mobileTitle: Locator @@ -24,6 +25,7 @@ export class ProductPage extends BasePage { this.productTitle = this.container.getByTestId("product-title") this.productDescription = this.container.getByTestId("product-description") this.productOptions = this.container.getByTestId("product-options") + this.productPrice = this.container.getByTestId("product-price") this.addProductButton = this.container.getByTestId("add-product-button") this.mobileActionsContainer = page.getByTestId("mobile-actions") this.mobileTitle = this.mobileActionsContainer.getByTestId("mobile-title") @@ -35,10 +37,16 @@ export class ProductPage extends BasePage { ) } + async clickAddProduct() { + await this.addProductButton.click() + await this.cartDropdown.cartDropdown.waitFor({ state: "visible" }) + } + async selectOption(option: string) { + await this.page.mouse.move(0, 0) // hides the checkout container const optionButton = this.productOptions .getByTestId("option-button") .filter({ hasText: option }) - await optionButton.click() + await optionButton.click({ clickCount: 2 }) } } diff --git a/e2e/tests/public/cart.spec.ts b/e2e/tests/public/cart.spec.ts new file mode 100644 index 000000000..edaaaf666 --- /dev/null +++ b/e2e/tests/public/cart.spec.ts @@ -0,0 +1,202 @@ +/* +Test List +- login from the sign in page redirects you page to the cart +*/ +import { test, expect } from "../../index" +import { compareFloats, getFloatValue } from "../../utils" + +test.describe("Cart tests", async () => { + test("Ensure adding multiple items from a product page adjusts the cart accordingly", async ({ + page, + cartPage, + productPage, + storePage, + }) => { + // Assuming we have access to our page objects here + const cartDropdown = cartPage.cartDropdown + + await test.step("Navigate to the product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the small size to the cart and verify the data", async () => { + await productPage.selectOption("S") + await productPage.addProductButton.click() + await expect(cartDropdown.navCartLink).toContainText("(1)") + const cartItem = await cartDropdown.getCartItem("Sweatshirt", "S") + await expect(cartItem.locator).toBeVisible() + await expect(cartItem.variant).toContainText("S") + await expect(cartItem.quantity).toContainText("1") + await cartDropdown.goToCartButton.click() + await cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + const productInCart = await cartPage.getProduct("Sweatshirt", "S") + await expect(productInCart.productRow).toBeVisible() + await expect(productInCart.quantitySelect).toHaveValue("1") + await page.goBack() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the small size to the cart again and verify the data", async () => { + await productPage.selectOption("S") + await productPage.addProductButton.click() + await expect(cartDropdown.navCartLink).toContainText("(2)") + const cartItem = await cartDropdown.getCartItem("Sweatshirt", "S") + await expect(cartItem.locator).toBeVisible() + await expect(cartItem.variant).toContainText("S") + await expect(cartItem.quantity).toContainText("2") + await cartDropdown.goToCartButton.click() + await cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + const productInCart = await cartPage.getProduct("Sweatshirt", "S") + await expect(productInCart.productRow).toBeVisible() + await expect(productInCart.quantitySelect).toHaveValue("2") + await page.goBack() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the medium size to the cart and verify the data", async () => { + await productPage.selectOption("M") + await productPage.addProductButton.click() + await expect(cartDropdown.navCartLink).toContainText("(3)") + const mediumCartItem = await cartDropdown.getCartItem("Sweatshirt", "M") + await expect(mediumCartItem.locator).toBeVisible() + await expect(mediumCartItem.variant).toContainText("M") + await expect(mediumCartItem.quantity).toContainText("1") + await cartDropdown.goToCartButton.click() + await cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + const mediumProductInCart = await cartPage.getProduct("Sweatshirt", "M") + await expect(mediumProductInCart.productRow).toBeVisible() + await expect(mediumProductInCart.quantitySelect).toHaveValue("1") + const smallProductInCart = await cartPage.getProduct("Sweatshirt", "S") + await expect(smallProductInCart.productRow).toBeVisible() + await expect(smallProductInCart.quantitySelect).toHaveValue("2") + }) + }) + + test("Ensure adding two products into the cart and verify the quantities", async ({ + cartPage, + productPage, + storePage, + }) => { + const cartDropdown = cartPage.cartDropdown + + await test.step("Navigate to the product page - go to the store page and click on the Sweatshirt product", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the small sweatshirt to the cart", async () => { + await productPage.selectOption("S") + await productPage.addProductButton.click() + await expect(cartDropdown.navCartLink).toContainText("(1)") + const sweatshirtItem = await cartDropdown.getCartItem("Sweatshirt", "S") + await expect(sweatshirtItem.locator).toBeVisible() + await expect(sweatshirtItem.variant).toHaveText("Variant: S") + await expect(sweatshirtItem.quantity).toContainText("1") + await cartDropdown.close() + }) + + await test.step("Navigate to another product - Sweatpants", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatpants") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the small sweatpants to the cart", async () => { + await productPage.selectOption("S") + await productPage.addProductButton.click() + await expect(cartDropdown.navCartLink).toContainText("(2)") + const sweatpantsItem = await cartDropdown.getCartItem("Sweatpants", "S") + await expect(sweatpantsItem.locator).toBeVisible() + await expect(sweatpantsItem.variant).toHaveText("Variant: S") + await expect(sweatpantsItem.quantity).toContainText("1") + const sweatshirtItem = await cartDropdown.getCartItem("Sweatshirt", "S") + await expect(sweatshirtItem.locator).toBeVisible() + await expect(sweatshirtItem.quantity).toContainText("1") + await cartDropdown.goToCartButton.click() + await cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Verify the quantities in the cart", async () => { + const sweatpantsProduct = await cartPage.getProduct("Sweatpants", "S") + await expect(sweatpantsProduct.productRow).toBeVisible() + await expect(sweatpantsProduct.quantitySelect).toHaveValue("1") + const sweatshirtProduct = await cartPage.getProduct("Sweatshirt", "S") + await expect(sweatshirtProduct.productRow).toBeVisible() + await expect(sweatshirtProduct.quantitySelect).toHaveValue("1") + }) + }) + + test("Verify the prices carries over to checkout", async ({ + cartPage, + productPage, + storePage, + }) => { + await test.step("Navigate to the product page - go to the store page and click on the Hoodie product", async () => { + await storePage.goto() + const product = await storePage.getProduct("Hoodie") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + let hoodieSmallPrice = 0 + let hoodieMediumPrice = 0 + await test.step("Add the hoodie to the cart", async () => { + await productPage.selectOption("S") + hoodieSmallPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + await productPage.cartDropdown.close() + await productPage.selectOption("M") + hoodieMediumPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + + await productPage.cartDropdown.close() + }) + + await test.step("Navigate to another product - Longsleeve", async () => { + await storePage.goto() + const product = await storePage.getProduct("Longsleeve") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + let longsleeveSmallPrice = 0 + await test.step("Add the small longsleeve to the cart", async () => { + await productPage.selectOption("S") + longsleeveSmallPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + await productPage.cartDropdown.close() + await productPage.selectOption("S") + await productPage.clickAddProduct() + await productPage.selectOption("S") + await productPage.clickAddProduct() + await productPage.cartDropdown.goToCartButton.click() + await productPage.cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Verify the price in the cart is the expected value", async () => { + const total = getFloatValue( + (await cartPage.cartSubtotal.getAttribute("data-value")) || "0" + ) + const calculatedTotal = + 3 * longsleeveSmallPrice + hoodieSmallPrice + hoodieMediumPrice + expect(compareFloats(total, calculatedTotal)).toBe(0) + }) + }) +}) diff --git a/e2e/tests/public/checkout.spec.ts b/e2e/tests/public/checkout.spec.ts new file mode 100644 index 000000000..7211ec0a7 --- /dev/null +++ b/e2e/tests/public/checkout.spec.ts @@ -0,0 +1,582 @@ +import { test, expect } from "../../index" +import { compareFloats, getFloatValue } from "../../utils" + +test.describe("Checkout flow tests", async () => { + test("Default checkout flow", async ({ + cartPage, + checkoutPage, + orderPage, + productPage, + storePage, + }) => { + await test.step("Navigate to a product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.highlight() + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the product to the cart and goto checkout", async () => { + await productPage.selectOption("M") + await productPage.clickAddProduct() + await productPage.cartDropdown.navCartLink.click() + await productPage.cartDropdown.goToCartButton.click() + await cartPage.container.waitFor({ state: "visible" }) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Enter in the first step of the checkout process", async () => { + await test.step("Enter in the shipping address info", async () => { + await checkoutPage.shippingFirstNameInput.fill("First") + await checkoutPage.shippingLastNameInput.fill("Last") + await checkoutPage.shippingCompanyInput.fill("MyCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake street") + await checkoutPage.shippingPostalCodeInput.fill("80010") + await checkoutPage.shippingCityInput.fill("Denver") + await checkoutPage.shippingProvinceInput.fill("Colorado") + await checkoutPage.shippingCountrySelect.selectOption("United States") + }) + + await test.step("Enter in the contact info and open the billing info form", async () => { + await checkoutPage.shippingEmailInput.fill("test@example.com") + await checkoutPage.shippingPhoneInput.fill("3031112222") + await checkoutPage.billingAddressCheckbox.uncheck() + }) + + await test.step("Enter in the billing address info", async () => { + await checkoutPage.billingFirstNameInput.fill("First") + await checkoutPage.billingLastNameInput.fill("Last") + await checkoutPage.billingCompanyInput.fill("MyCorp") + await checkoutPage.billingAddressInput.fill("123 Fake street") + await checkoutPage.billingPostalInput.fill("80010") + await checkoutPage.billingCityInput.fill("Denver") + await checkoutPage.billingProvinceInput.fill("Colorado") + await checkoutPage.billingCountrySelect.selectOption("United States") + await checkoutPage.submitAddressButton.click() + }) + }) + + await test.step("Complete the rest of the payment process", async () => { + await checkoutPage.selectDeliveryOption("FakeEx Standard") + await checkoutPage.submitDeliveryOptionButton.click() + await checkoutPage.submitPaymentButton.click() + await checkoutPage.submitOrderButton.click() + await orderPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Verify the products ordered are correct", async () => { + const product = await orderPage.getProduct("Sweatshirt", "M") + await expect(product.name).toContainText("Sweatshirt") + await expect(product.variant).toContainText("M") + await expect(product.quantity).toContainText("1") + }) + + await test.step("Verify the shipping info is correct", async () => { + const address = orderPage.shippingAddressSummary + await expect(address).toContainText("First") + await expect(address).toContainText("Last") + await expect(address).toContainText("123 Fake street") + await expect(address).toContainText("80010") + await expect(address).toContainText("Denver") + await expect(address).toContainText("US") + + const contact = orderPage.shippingContactSummary + await expect(contact).toContainText("test@example.com") + await expect(contact).toContainText("3031112222") + + const method = orderPage.shippingMethodSummary + await expect(method).toContainText("FakeEx Standard") + }) + }) + + test("Editing checkout steps works as expected", async ({ + cartPage, + checkoutPage, + productPage, + storePage, + }) => { + await test.step("Navigate to a product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.highlight() + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the product to the cart and goto checkout", async () => { + await productPage.selectOption("M") + await productPage.clickAddProduct() + await productPage.cartDropdown.navCartLink.click() + await productPage.cartDropdown.goToCartButton.click() + await cartPage.container.waitFor({ state: "visible" }) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Enter in the first step of the checkout process", async () => { + await test.step("Enter in the shipping address info", async () => { + await checkoutPage.shippingFirstNameInput.fill("First") + await checkoutPage.shippingLastNameInput.fill("Last") + await checkoutPage.shippingCompanyInput.fill("MyCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake street") + await checkoutPage.shippingPostalCodeInput.fill("80010") + await checkoutPage.shippingCityInput.fill("Denver") + await checkoutPage.shippingProvinceInput.fill("Colorado") + await checkoutPage.shippingCountrySelect.selectOption("United States") + }) + + await test.step("Enter in the contact info and open the billing info form", async () => { + await checkoutPage.shippingEmailInput.fill("test@example.com") + await checkoutPage.shippingPhoneInput.fill("3031112222") + await checkoutPage.billingAddressCheckbox.uncheck() + }) + + await test.step("Enter in the billing address info", async () => { + await checkoutPage.billingFirstNameInput.fill("First") + await checkoutPage.billingLastNameInput.fill("Last") + await checkoutPage.billingCompanyInput.fill("MyCorp") + await checkoutPage.billingAddressInput.fill("123 Fake street") + await checkoutPage.billingPostalInput.fill("80010") + await checkoutPage.billingCityInput.fill("Denver") + await checkoutPage.billingProvinceInput.fill("Colorado") + await checkoutPage.billingCountrySelect.selectOption("United States") + await checkoutPage.submitAddressButton.click() + }) + }) + + await test.step("Submit the delivery and payment options", async () => { + await checkoutPage.selectDeliveryOption("FakeEx Standard") + await checkoutPage.submitDeliveryOptionButton.click() + await checkoutPage.submitPaymentButton.click() + }) + + await test.step("Edit the shipping info", async () => { + await checkoutPage.editAddressButton.click() + await test.step("Edit the shipping address", async () => { + await checkoutPage.shippingFirstNameInput.fill("First1") + await checkoutPage.shippingLastNameInput.fill("Last1") + await checkoutPage.shippingCompanyInput.fill("MeCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake Road") + await checkoutPage.shippingPostalCodeInput.fill("80011") + await checkoutPage.shippingCityInput.fill("Donver") + await checkoutPage.shippingProvinceInput.fill("CO") + await checkoutPage.shippingCountrySelect.selectOption("Canada") + }) + + await test.step("Edit the shipping contact info", async () => { + await checkoutPage.shippingEmailInput.fill("tester@example.com") + await checkoutPage.shippingPhoneInput.fill("3231112222") + }) + + await test.step("Edit the billing info", async () => { + await checkoutPage.billingFirstNameInput.fill("Farst") + await checkoutPage.billingLastNameInput.fill("List") + await checkoutPage.billingCompanyInput.fill("MistCorp") + await checkoutPage.billingAddressInput.fill("321 Fake street") + await checkoutPage.billingPostalInput.fill("80110") + await checkoutPage.billingCityInput.fill("Denvur") + await checkoutPage.billingProvinceInput.fill("AB") + await checkoutPage.billingCountrySelect.selectOption("Canada") + }) + await checkoutPage.submitAddressButton.click() + }) + + await test.step("Make sure the edits are reflected in the container", async () => { + await test.step("Check shipping address summary", async () => { + const shippingColumn = checkoutPage.shippingAddressSummary + await expect(shippingColumn).toContainText("First1") + await expect(shippingColumn).toContainText("Last1") + await expect(shippingColumn).toContainText("123 Fake Road") + await expect(shippingColumn).toContainText("80011") + await expect(shippingColumn).toContainText("Donver") + await expect(shippingColumn).toContainText("CA") + }) + + await test.step("Check shipping contact summary", async () => { + const contactColumn = checkoutPage.shippingContactSummary + await expect(contactColumn).toContainText("tester@example.com") + await expect(contactColumn).toContainText("3231112222") + }) + + await test.step("Check billing summary", async () => { + const billingColumn = checkoutPage.billingAddressSummary + await expect(billingColumn).toContainText("Farst") + await expect(billingColumn).toContainText("List") + await expect(billingColumn).toContainText("321 Fake street") + await expect(billingColumn).toContainText("Denvur") + await expect(billingColumn).toContainText("CA") + }) + }) + }) + + test("Shipping info saved is filled back into the forms after clicking edit", async ({ + cartPage, + checkoutPage, + productPage, + storePage, + }) => { + await test.step("Navigate to a product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.highlight() + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the product to the cart and goto checkout", async () => { + await productPage.selectOption("M") + await productPage.clickAddProduct() + await productPage.cartDropdown.navCartLink.click() + await productPage.cartDropdown.goToCartButton.click() + await cartPage.container.waitFor({ state: "visible" }) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Enter in the first step of the checkout process", async () => { + await test.step("Enter in the shipping address info", async () => { + await checkoutPage.shippingFirstNameInput.fill("First") + await checkoutPage.shippingLastNameInput.fill("Last") + await checkoutPage.shippingCompanyInput.fill("MyCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake street") + await checkoutPage.shippingPostalCodeInput.fill("80010") + await checkoutPage.shippingCityInput.fill("Denver") + await checkoutPage.shippingProvinceInput.fill("Colorado") + await checkoutPage.shippingCountrySelect.selectOption("United States") + }) + + await test.step("Enter in the contact info and open the billing info form", async () => { + await checkoutPage.shippingEmailInput.fill("test@example.com") + await checkoutPage.shippingPhoneInput.fill("3031112222") + await checkoutPage.billingAddressCheckbox.uncheck() + }) + + await test.step("Enter in the billing address info", async () => { + await checkoutPage.billingFirstNameInput.fill("First") + await checkoutPage.billingLastNameInput.fill("Last") + await checkoutPage.billingCompanyInput.fill("MyCorp") + await checkoutPage.billingAddressInput.fill("123 Fake street") + await checkoutPage.billingPostalInput.fill("80010") + await checkoutPage.billingCityInput.fill("Denver") + await checkoutPage.billingProvinceInput.fill("Colorado") + await checkoutPage.billingCountrySelect.selectOption("United States") + await checkoutPage.submitAddressButton.click() + }) + }) + + await test.step("Click the edit address form and ensure the fields are filled correctly", async () => { + await checkoutPage.editAddressButton.click() + await test.step("Check the shipping address", async () => { + await expect(checkoutPage.shippingFirstNameInput).toHaveValue("First") + await expect(checkoutPage.shippingLastNameInput).toHaveValue("Last") + await expect(checkoutPage.shippingCompanyInput).toHaveValue("MyCorp") + await expect(checkoutPage.shippingAddressInput).toHaveValue( + "123 Fake street" + ) + await expect(checkoutPage.shippingPostalCodeInput).toHaveValue("80010") + await expect(checkoutPage.shippingCityInput).toHaveValue("Denver") + await expect(checkoutPage.shippingProvinceInput).toHaveValue("Colorado") + await expect(checkoutPage.shippingCountrySelect).toHaveValue("us") + }) + + await test.step("Check the shipping contact", async () => { + await expect(checkoutPage.shippingEmailInput).toHaveValue( + "test@example.com" + ) + await expect(checkoutPage.shippingPhoneInput).toHaveValue("3031112222") + }) + + await test.step("Check the billing address", async () => { + await expect(checkoutPage.billingFirstNameInput).toHaveValue("First") + await expect(checkoutPage.billingLastNameInput).toHaveValue("Last") + await expect(checkoutPage.billingCompanyInput).toHaveValue("MyCorp") + await expect(checkoutPage.billingAddressInput).toHaveValue( + "123 Fake street" + ) + await expect(checkoutPage.billingPostalInput).toHaveValue("80010") + await expect(checkoutPage.billingCityInput).toHaveValue("Denver") + await expect(checkoutPage.billingProvinceInput).toHaveValue("Colorado") + await expect(checkoutPage.billingCountrySelect).toHaveValue("us") + }) + }) + + await test.step("Set the billing info to the same as checked and perform checks", async () => { + await checkoutPage.billingAddressCheckbox.check() + await checkoutPage.submitAddressButton.click() + await checkoutPage.editAddressButton.click() + await expect(checkoutPage.billingAddressCheckbox).toBeChecked() + }) + }) + + test("Shipping info in the checkout page is correctly reflected in the summary", async ({ + cartPage, + checkoutPage, + productPage, + storePage, + }) => { + await test.step("Navigate to a product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.highlight() + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the product to the cart and goto checkout", async () => { + await productPage.selectOption("M") + await productPage.clickAddProduct() + await productPage.cartDropdown.navCartLink.click() + await productPage.cartDropdown.goToCartButton.click() + await cartPage.container.waitFor({ state: "visible" }) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Enter in the first step of the checkout process", async () => { + await test.step("Enter in the shipping address info", async () => { + await checkoutPage.shippingFirstNameInput.fill("First") + await checkoutPage.shippingLastNameInput.fill("Last") + await checkoutPage.shippingCompanyInput.fill("MyCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake street") + await checkoutPage.shippingPostalCodeInput.fill("80010") + await checkoutPage.shippingCityInput.fill("Denver") + await checkoutPage.shippingProvinceInput.fill("Colorado") + await checkoutPage.shippingCountrySelect.selectOption("United States") + }) + + await test.step("Enter in the contact info and open the billing info form", async () => { + await checkoutPage.shippingEmailInput.fill("test@example.com") + await checkoutPage.shippingPhoneInput.fill("3031112222") + await checkoutPage.billingAddressCheckbox.uncheck() + }) + + await test.step("Enter in the billing address info", async () => { + await checkoutPage.billingFirstNameInput.fill("First") + await checkoutPage.billingLastNameInput.fill("Last") + await checkoutPage.billingCompanyInput.fill("MyCorp") + await checkoutPage.billingAddressInput.fill("123 Fake street") + await checkoutPage.billingPostalInput.fill("80010") + await checkoutPage.billingCityInput.fill("Denver") + await checkoutPage.billingProvinceInput.fill("Colorado") + await checkoutPage.billingCountrySelect.selectOption("United States") + await checkoutPage.submitAddressButton.click() + }) + }) + + await test.step("Ensure the shipping column reflects the entered data", async () => { + const shippingColumn = checkoutPage.shippingAddressSummary + await expect(shippingColumn).toContainText("First") + await expect(shippingColumn).toContainText("Last") + await expect(shippingColumn).toContainText("123 Fake street") + await expect(shippingColumn).toContainText("80010") + await expect(shippingColumn).toContainText("Denver") + await expect(shippingColumn).toContainText("US") + }) + + await test.step("Ensure the contact column reflects the entered data", async () => { + const contactColumn = checkoutPage.shippingContactSummary + await expect(contactColumn).toContainText("test@example.com") + await expect(contactColumn).toContainText("3031112222") + }) + + await test.step("Ensure the billing column reflects the entered data", async () => { + const billingColumn = checkoutPage.billingAddressSummary + await expect(billingColumn).toContainText("First") + await expect(billingColumn).toContainText("Last") + await expect(billingColumn).toContainText("123 Fake street") + await expect(billingColumn).toContainText("Denver") + await expect(billingColumn).toContainText("US") + }) + + await test.step("Edit the billing info so it is the same as the billing address", async () => { + await checkoutPage.editAddressButton.click() + await checkoutPage.billingAddressCheckbox.check() + await checkoutPage.submitAddressButton.click() + const billingColumn = checkoutPage.billingAddressSummary + await expect(billingColumn).toContainText("are the same.") + }) + }) + + test("Entering checkout, leaving, then returning takes you back to the correct checkout spot", async ({ + cartPage, + checkoutPage, + productPage, + storePage, + }) => { + await test.step("Navigate to a product page", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.highlight() + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Add the product to the cart and goto checkout", async () => { + await productPage.selectOption("M") + await productPage.clickAddProduct() + await productPage.cartDropdown.navCartLink.click() + await productPage.cartDropdown.goToCartButton.click() + await cartPage.container.waitFor({ state: "visible" }) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Navigate away and back to the checkout page", async () => { + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitAddressButton).toBeVisible() + }) + + await test.step("Enter in the first step of the checkout process", async () => { + await test.step("Enter in the shipping address info", async () => { + await checkoutPage.shippingFirstNameInput.fill("First") + await checkoutPage.shippingLastNameInput.fill("Last") + await checkoutPage.shippingCompanyInput.fill("MyCorp") + await checkoutPage.shippingAddressInput.fill("123 Fake street") + await checkoutPage.shippingPostalCodeInput.fill("80010") + await checkoutPage.shippingCityInput.fill("Denver") + await checkoutPage.shippingProvinceInput.fill("Colorado") + await checkoutPage.shippingCountrySelect.selectOption("United States") + }) + + await test.step("Enter in the contact info and open the billing info form", async () => { + await checkoutPage.shippingEmailInput.fill("test@example.com") + await checkoutPage.shippingPhoneInput.fill("3031112222") + await checkoutPage.billingAddressCheckbox.uncheck() + }) + + await test.step("Enter in the billing address info", async () => { + await checkoutPage.billingFirstNameInput.fill("First") + await checkoutPage.billingLastNameInput.fill("Last") + await checkoutPage.billingCompanyInput.fill("MyCorp") + await checkoutPage.billingAddressInput.fill("123 Fake street") + await checkoutPage.billingPostalInput.fill("80010") + await checkoutPage.billingCityInput.fill("Denver") + await checkoutPage.billingProvinceInput.fill("Colorado") + await checkoutPage.billingCountrySelect.selectOption("United States") + }) + await checkoutPage.submitAddressButton.click() + await checkoutPage.deliveryOptionRadio + .first() + .waitFor({ state: "visible" }) + }) + + await test.step("Navigate away and back to the checkout page", async () => { + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitDeliveryOptionButton).toBeVisible() + }) + + await test.step("Submit the delivery choice and navigate back and forth", async () => { + await checkoutPage.selectDeliveryOption("FakeEx Standard") + await checkoutPage.submitDeliveryOptionButton.click() + await checkoutPage.submitPaymentButton.waitFor({ state: "visible" }) + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitPaymentButton).toBeVisible() + }) + + await test.step("Submit the payment info and navigate back and forth", async () => { + await checkoutPage.submitPaymentButton.click() + await checkoutPage.submitOrderButton.waitFor({ state: "visible" }) + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitPaymentButton).toBeVisible() + }) + + await test.step("Click edit on the shipping info and navigate back and forth", async () => { + await checkoutPage.editAddressButton.click() + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitPaymentButton).toBeVisible() + }) + + await test.step("Click edit on the shipping choice and navigate back and forth", async () => { + await checkoutPage.editDeliveryButton.click() + await checkoutPage.backToCartLink.click() + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + await expect(checkoutPage.submitPaymentButton).toBeVisible() + }) + }) + + test("Verify the prices carries over to checkout", async ({ + cartPage, + checkoutPage, + productPage, + storePage, + }) => { + await test.step("Navigate to the product page - go to the store page and click on the Sweatshirt product", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatshirt") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + let sweatshirtSmallPrice = 0 + let sweatshirtMediumPrice = 0 + await test.step("Add the sweatshirts to the cart", async () => { + await productPage.selectOption("S") + sweatshirtSmallPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + await productPage.cartDropdown.close() + await productPage.selectOption("M") + sweatshirtMediumPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + await productPage.cartDropdown.close() + }) + + await test.step("Navigate to another product - Sweatpants", async () => { + await storePage.goto() + const product = await storePage.getProduct("Sweatpants") + await product.locator.click() + await productPage.container.waitFor({ state: "visible" }) + }) + + let sweatpantsSmallPrice = 0 + await test.step("Add the small sweatpants to the cart", async () => { + await productPage.selectOption("S") + sweatpantsSmallPrice = getFloatValue( + (await productPage.productPrice.getAttribute("data-value")) || "0" + ) + await productPage.clickAddProduct() + await productPage.cartDropdown.close() + await productPage.selectOption("S") + await productPage.clickAddProduct() + await productPage.cartDropdown.goToCartButton.click() + await productPage.cartDropdown.close() + await cartPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Verify the price in the cart is the expected value", async () => { + const total = getFloatValue( + (await cartPage.cartSubtotal.getAttribute("data-value")) || "0" + ) + const calculatedTotal = + 2 * sweatpantsSmallPrice + sweatshirtSmallPrice + sweatshirtMediumPrice + expect(compareFloats(total, calculatedTotal)).toBe(0) + await cartPage.checkoutButton.click() + await checkoutPage.container.waitFor({ state: "visible" }) + }) + + await test.step("Go to checkout and verify the price in the checkout is the expected value", async () => { + const total = getFloatValue( + (await checkoutPage.cartSubtotal.getAttribute("data-value")) || "0" + ) + const calculatedTotal = + 2 * sweatpantsSmallPrice + sweatshirtSmallPrice + sweatpantsSmallPrice + expect(compareFloats(total, calculatedTotal)).toBe(0) + }) + }) +}) diff --git a/e2e/utils/index.ts b/e2e/utils/index.ts new file mode 100644 index 000000000..b7f9f4b12 --- /dev/null +++ b/e2e/utils/index.ts @@ -0,0 +1,14 @@ +export function getFloatValue(s: string) { + return parseFloat(parseFloat(s).toFixed(2)) +} + +export function compareFloats(f1: number, f2: number) { + const diff = f1 - f2 + if (Math.abs(diff) < 0.01) { + return 0 + } else if (diff < 0) { + return -1 + } else { + return 1 + } +} diff --git a/src/app/[countryCode]/(main)/account/@dashboard/orders/page.tsx b/src/app/[countryCode]/(main)/account/@dashboard/orders/page.tsx index 63e18ebc7..7e5c082bb 100644 --- a/src/app/[countryCode]/(main)/account/@dashboard/orders/page.tsx +++ b/src/app/[countryCode]/(main)/account/@dashboard/orders/page.tsx @@ -17,7 +17,7 @@ export default async function Orders() { } return ( -
diff --git a/src/lib/util/get-product-price.ts b/src/lib/util/get-product-price.ts
index d15f6ea0c..0dcce4dbc 100644
--- a/src/lib/util/get-product-price.ts
+++ b/src/lib/util/get-product-price.ts
@@ -36,11 +36,13 @@ export function getProductPrice({
})
return {
+ calculated_price_number: cheapestVariant.calculated_price,
calculated_price: formatAmount({
amount: cheapestVariant.calculated_price,
region,
includeTaxes: false,
}),
+ original_price_number: cheapestVariant.original_price,
original_price: formatAmount({
amount: cheapestVariant.original_price,
region,
@@ -68,11 +70,13 @@ export function getProductPrice({
}
return {
+ calculated_price_number: variant.calculated_price,
calculated_price: formatAmount({
amount: variant.calculated_price,
region,
includeTaxes: false,
}),
+ original_price_number: variant.original_price,
original_price: formatAmount({
amount: variant.original_price,
region,
diff --git a/src/modules/checkout/components/shipping-address/index.tsx b/src/modules/checkout/components/shipping-address/index.tsx
index 63d966b39..12bbd5f31 100644
--- a/src/modules/checkout/components/shipping-address/index.tsx
+++ b/src/modules/checkout/components/shipping-address/index.tsx
@@ -175,7 +175,7 @@ const ShippingAddress = ({
value={formData.email}
onChange={handleChange}
required
- dat-testid="shipping-email-input"
+ data-testid="shipping-email-input"
/>
= ({ data }) => {
Original: - {selectedPrice.original_price} + + {selectedPrice.original_price} +
-{selectedPrice.percentage_diff}% diff --git a/src/modules/products/templates/index.tsx b/src/modules/products/templates/index.tsx index cf3e7f727..6af20bbb9 100644 --- a/src/modules/products/templates/index.tsx +++ b/src/modules/products/templates/index.tsx @@ -29,7 +29,10 @@ const ProductTemplate: React.FC