Skip to content

Commit fc8676c

Browse files
authored
Merge pull request #303 from QAComet/qacomet/cart-tests
Cart tests
2 parents 2be5564 + 32409d8 commit fc8676c

File tree

13 files changed

+367
-39
lines changed

13 files changed

+367
-39
lines changed

e2e/fixtures/base/cart-dropdown.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,33 @@ export class CartDropdown {
1919
await this.navCartLink.hover()
2020
}
2121

22-
async getCartItem(name: string) {
23-
const cartItem = this.cartDropdown.getByTestId("cart-item").filter({
24-
hasText: name,
25-
})
26-
const quantity = cartItem
27-
.getByTestId("cart-item-quantity")
28-
.getAttribute("data-value")
29-
const variant = cartItem
30-
.getByTestId("cart-item-variant")
31-
.getAttribute("data-value")
22+
async close() {
23+
if (await this.cartDropdown.isVisible()) {
24+
const box = await this.cartDropdown.boundingBox()
25+
if (!box) {
26+
return
27+
}
28+
await this.page.mouse.move(box.x + box.width / 4, box.y + box.height / 4)
29+
await this.page.mouse.move(5, 10)
30+
}
31+
}
32+
33+
async getCartItem(name: string, variant: string) {
34+
const cartItem = this.cartDropdown
35+
.getByTestId("cart-item")
36+
.filter({
37+
hasText: name,
38+
})
39+
.filter({
40+
hasText: `Variant: ${variant}`,
41+
})
3242
return {
3343
locator: cartItem,
3444
productLink: cartItem.getByTestId("product-link"),
3545
removeButton: cartItem.getByTestId("cart-item-remove-button"),
3646
name,
37-
quantity,
38-
variant,
47+
quantity: cartItem.getByTestId("cart-item-quantity"),
48+
variant: cartItem.getByTestId("cart-item-variant"),
3949
}
4050
}
4151
}

e2e/fixtures/cart-page.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export class CartPage extends BasePage {
2323
cartGiftCardAmount: Locator
2424
cartShipping: Locator
2525
cartTaxes: Locator
26+
cartTotal: Locator
2627
checkoutButton: Locator
2728

2829
constructor(page: Page) {
@@ -61,22 +62,23 @@ export class CartPage extends BasePage {
6162
)
6263
this.cartShipping = this.container.getByTestId("cart-shipping")
6364
this.cartTaxes = this.container.getByTestId("cart-taxes")
65+
this.cartTotal = this.container.getByTestId("cart-total")
6466
}
6567

6668
async getProduct(title: string, variant: string) {
6769
const productRow = this.productRow
6870
.filter({
69-
has: this.productTitle.filter({ hasText: title }),
71+
hasText: title,
7072
})
7173
.filter({
72-
has: this.productVariant.filter({ hasText: variant }),
74+
hasText: `Variant: ${variant}`,
7375
})
7476
return {
7577
productRow,
7678
title: productRow.getByTestId("product-title"),
7779
variant: productRow.getByTestId("product-variant"),
7880
deleteButton: productRow.getByTestId("delete-button"),
79-
quantitySelect: productRow.getByTestId("quantity-select"),
81+
quantitySelect: productRow.getByTestId("product-select-button"),
8082
price: productRow.getByTestId("product-unit-price"),
8183
total: productRow.getByTestId("product-price"),
8284
}

e2e/fixtures/product-page.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class ProductPage extends BasePage {
99
productTitle: Locator
1010
productDescription: Locator
1111
productOptions: Locator
12+
productPrice: Locator
1213
addProductButton: Locator
1314
mobileActionsContainer: Locator
1415
mobileTitle: Locator
@@ -24,6 +25,7 @@ export class ProductPage extends BasePage {
2425
this.productTitle = this.container.getByTestId("product-title")
2526
this.productDescription = this.container.getByTestId("product-description")
2627
this.productOptions = this.container.getByTestId("product-options")
28+
this.productPrice = this.container.getByTestId("product-price")
2729
this.addProductButton = this.container.getByTestId("add-product-button")
2830
this.mobileActionsContainer = page.getByTestId("mobile-actions")
2931
this.mobileTitle = this.mobileActionsContainer.getByTestId("mobile-title")
@@ -35,10 +37,16 @@ export class ProductPage extends BasePage {
3537
)
3638
}
3739

40+
async clickAddProduct() {
41+
await this.addProductButton.click()
42+
await this.cartDropdown.cartDropdown.waitFor({ state: "visible" })
43+
}
44+
3845
async selectOption(option: string) {
46+
await this.page.mouse.move(0, 0) // hides the checkout container
3947
const optionButton = this.productOptions
4048
.getByTestId("option-button")
4149
.filter({ hasText: option })
42-
await optionButton.click()
50+
await optionButton.click({ clickCount: 2 })
4351
}
4452
}

e2e/tests/public/cart.spec.ts

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/*
2+
Test List
3+
- login from the sign in page redirects you page to the cart
4+
*/
5+
import { test, expect } from "../../index"
6+
import { compareFloats, getFloatValue } from "../../utils"
7+
8+
test.describe("Cart tests", async () => {
9+
test("Ensure adding multiple items from a product page adjusts the cart accordingly", async ({
10+
page,
11+
cartPage,
12+
productPage,
13+
storePage,
14+
}) => {
15+
// Assuming we have access to our page objects here
16+
const cartDropdown = cartPage.cartDropdown
17+
18+
await test.step("Navigate to the product page", async () => {
19+
await storePage.goto()
20+
const product = await storePage.getProduct("Sweatshirt")
21+
await product.locator.click()
22+
await productPage.container.waitFor({ state: "visible" })
23+
})
24+
25+
await test.step("Add the small size to the cart and verify the data", async () => {
26+
await productPage.selectOption("S")
27+
await productPage.addProductButton.click()
28+
await expect(cartDropdown.navCartLink).toContainText("(1)")
29+
const cartItem = await cartDropdown.getCartItem("Sweatshirt", "S")
30+
await expect(cartItem.locator).toBeVisible()
31+
await expect(cartItem.variant).toContainText("S")
32+
await expect(cartItem.quantity).toContainText("1")
33+
await cartDropdown.goToCartButton.click()
34+
await cartDropdown.close()
35+
await cartPage.container.waitFor({ state: "visible" })
36+
const productInCart = await cartPage.getProduct("Sweatshirt", "S")
37+
await expect(productInCart.productRow).toBeVisible()
38+
await expect(productInCart.quantitySelect).toHaveValue("1")
39+
await page.goBack()
40+
await productPage.container.waitFor({ state: "visible" })
41+
})
42+
43+
await test.step("Add the small size to the cart again and verify the data", async () => {
44+
await productPage.selectOption("S")
45+
await productPage.addProductButton.click()
46+
await expect(cartDropdown.navCartLink).toContainText("(2)")
47+
const cartItem = await cartDropdown.getCartItem("Sweatshirt", "S")
48+
await expect(cartItem.locator).toBeVisible()
49+
await expect(cartItem.variant).toContainText("S")
50+
await expect(cartItem.quantity).toContainText("2")
51+
await cartDropdown.goToCartButton.click()
52+
await cartDropdown.close()
53+
await cartPage.container.waitFor({ state: "visible" })
54+
const productInCart = await cartPage.getProduct("Sweatshirt", "S")
55+
await expect(productInCart.productRow).toBeVisible()
56+
await expect(productInCart.quantitySelect).toHaveValue("2")
57+
await page.goBack()
58+
await productPage.container.waitFor({ state: "visible" })
59+
})
60+
61+
await test.step("Add the medium size to the cart and verify the data", async () => {
62+
await productPage.selectOption("M")
63+
await productPage.addProductButton.click()
64+
await expect(cartDropdown.navCartLink).toContainText("(3)")
65+
const mediumCartItem = await cartDropdown.getCartItem("Sweatshirt", "M")
66+
await expect(mediumCartItem.locator).toBeVisible()
67+
await expect(mediumCartItem.variant).toContainText("M")
68+
await expect(mediumCartItem.quantity).toContainText("1")
69+
await cartDropdown.goToCartButton.click()
70+
await cartDropdown.close()
71+
await cartPage.container.waitFor({ state: "visible" })
72+
const mediumProductInCart = await cartPage.getProduct("Sweatshirt", "M")
73+
await expect(mediumProductInCart.productRow).toBeVisible()
74+
await expect(mediumProductInCart.quantitySelect).toHaveValue("1")
75+
const smallProductInCart = await cartPage.getProduct("Sweatshirt", "S")
76+
await expect(smallProductInCart.productRow).toBeVisible()
77+
await expect(smallProductInCart.quantitySelect).toHaveValue("2")
78+
})
79+
})
80+
81+
test("Ensure adding two products into the cart and verify the quantities", async ({
82+
cartPage,
83+
productPage,
84+
storePage,
85+
}) => {
86+
const cartDropdown = cartPage.cartDropdown
87+
88+
await test.step("Navigate to the product page - go to the store page and click on the Sweatshirt product", async () => {
89+
await storePage.goto()
90+
const product = await storePage.getProduct("Sweatshirt")
91+
await product.locator.click()
92+
await productPage.container.waitFor({ state: "visible" })
93+
})
94+
95+
await test.step("Add the small sweatshirt to the cart", async () => {
96+
await productPage.selectOption("S")
97+
await productPage.addProductButton.click()
98+
await expect(cartDropdown.navCartLink).toContainText("(1)")
99+
const sweatshirtItem = await cartDropdown.getCartItem("Sweatshirt", "S")
100+
await expect(sweatshirtItem.locator).toBeVisible()
101+
await expect(sweatshirtItem.variant).toHaveText("Variant: S")
102+
await expect(sweatshirtItem.quantity).toContainText("1")
103+
await cartDropdown.close()
104+
})
105+
106+
await test.step("Navigate to another product - Sweatpants", async () => {
107+
await storePage.goto()
108+
const product = await storePage.getProduct("Sweatpants")
109+
await product.locator.click()
110+
await productPage.container.waitFor({ state: "visible" })
111+
})
112+
113+
await test.step("Add the small sweatpants to the cart", async () => {
114+
await productPage.selectOption("S")
115+
await productPage.addProductButton.click()
116+
await expect(cartDropdown.navCartLink).toContainText("(2)")
117+
const sweatpantsItem = await cartDropdown.getCartItem("Sweatpants", "S")
118+
await expect(sweatpantsItem.locator).toBeVisible()
119+
await expect(sweatpantsItem.variant).toHaveText("Variant: S")
120+
await expect(sweatpantsItem.quantity).toContainText("1")
121+
const sweatshirtItem = await cartDropdown.getCartItem("Sweatshirt", "S")
122+
await expect(sweatshirtItem.locator).toBeVisible()
123+
await expect(sweatshirtItem.quantity).toContainText("1")
124+
await cartDropdown.goToCartButton.click()
125+
await cartDropdown.close()
126+
await cartPage.container.waitFor({ state: "visible" })
127+
})
128+
129+
await test.step("Verify the quantities in the cart", async () => {
130+
const sweatpantsProduct = await cartPage.getProduct("Sweatpants", "S")
131+
await expect(sweatpantsProduct.productRow).toBeVisible()
132+
await expect(sweatpantsProduct.quantitySelect).toHaveValue("1")
133+
const sweatshirtProduct = await cartPage.getProduct("Sweatshirt", "S")
134+
await expect(sweatshirtProduct.productRow).toBeVisible()
135+
await expect(sweatshirtProduct.quantitySelect).toHaveValue("1")
136+
})
137+
})
138+
139+
test("Verify the prices carries over to checkout", async ({
140+
cartPage,
141+
productPage,
142+
storePage,
143+
}) => {
144+
await test.step("Navigate to the product page - go to the store page and click on the Hoodie product", async () => {
145+
await storePage.goto()
146+
const product = await storePage.getProduct("Hoodie")
147+
await product.locator.click()
148+
await productPage.container.waitFor({ state: "visible" })
149+
})
150+
151+
let hoodieSmallPrice = 0
152+
let hoodieMediumPrice = 0
153+
await test.step("Add the hoodie to the cart", async () => {
154+
await productPage.selectOption("S")
155+
hoodieSmallPrice = getFloatValue(
156+
(await productPage.productPrice.getAttribute("data-value")) || "0"
157+
)
158+
await productPage.clickAddProduct()
159+
await productPage.cartDropdown.close()
160+
await productPage.selectOption("M")
161+
hoodieMediumPrice = getFloatValue(
162+
(await productPage.productPrice.getAttribute("data-value")) || "0"
163+
)
164+
await productPage.clickAddProduct()
165+
166+
await productPage.cartDropdown.close()
167+
})
168+
169+
await test.step("Navigate to another product - Longsleeve", async () => {
170+
await storePage.goto()
171+
const product = await storePage.getProduct("Longsleeve")
172+
await product.locator.click()
173+
await productPage.container.waitFor({ state: "visible" })
174+
})
175+
176+
let longsleeveSmallPrice = 0
177+
await test.step("Add the small longsleeve to the cart", async () => {
178+
await productPage.selectOption("S")
179+
longsleeveSmallPrice = getFloatValue(
180+
(await productPage.productPrice.getAttribute("data-value")) || "0"
181+
)
182+
await productPage.clickAddProduct()
183+
await productPage.cartDropdown.close()
184+
await productPage.selectOption("S")
185+
await productPage.clickAddProduct()
186+
await productPage.selectOption("S")
187+
await productPage.clickAddProduct()
188+
await productPage.cartDropdown.goToCartButton.click()
189+
await productPage.cartDropdown.close()
190+
await cartPage.container.waitFor({ state: "visible" })
191+
})
192+
193+
await test.step("Verify the price in the cart is the expected value", async () => {
194+
const total = getFloatValue(
195+
(await cartPage.cartSubtotal.getAttribute("data-value")) || "0"
196+
)
197+
const calculatedTotal =
198+
3 * longsleeveSmallPrice + hoodieSmallPrice + hoodieMediumPrice
199+
expect(compareFloats(total, calculatedTotal)).toBe(0)
200+
})
201+
})
202+
})

e2e/utils/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function getFloatValue(s: string) {
2+
return parseFloat(parseFloat(s).toFixed(2))
3+
}
4+
5+
export function compareFloats(f1: number, f2: number) {
6+
const diff = f1 - f2
7+
if (Math.abs(diff) < 0.01) {
8+
return 0
9+
} else if (diff < 0) {
10+
return -1
11+
} else {
12+
return 1
13+
}
14+
}

src/lib/util/get-product-price.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ export function getProductPrice({
3636
})
3737

3838
return {
39+
calculated_price_number: cheapestVariant.calculated_price,
3940
calculated_price: formatAmount({
4041
amount: cheapestVariant.calculated_price,
4142
region,
4243
includeTaxes: false,
4344
}),
45+
original_price_number: cheapestVariant.original_price,
4446
original_price: formatAmount({
4547
amount: cheapestVariant.original_price,
4648
region,
@@ -68,11 +70,13 @@ export function getProductPrice({
6870
}
6971

7072
return {
73+
calculated_price_number: variant.calculated_price,
7174
calculated_price: formatAmount({
7275
amount: variant.calculated_price,
7376
region,
7477
includeTaxes: false,
7578
}),
79+
original_price_number: variant.original_price,
7680
original_price: formatAmount({
7781
amount: variant.original_price,
7882
region,

0 commit comments

Comments
 (0)