From 4639fb7ae7dc9384e8dec61ebadf522ea04108cc Mon Sep 17 00:00:00 2001 From: Daniel Rosel Date: Sun, 11 Jan 2026 22:03:44 +0100 Subject: [PATCH] chore: updating interactions setup --- tests/e2e/helpers/interactions.ts | 221 +++++++++++++++++++--- tests/e2e/playwright.config.ts | 4 +- tests/e2e/scenarios/session-aware.spec.ts | 137 ++++++++------ tests/e2e/scenarios/surge-pricing.spec.ts | 107 ++++++----- 4 files changed, 338 insertions(+), 131 deletions(-) diff --git a/tests/e2e/helpers/interactions.ts b/tests/e2e/helpers/interactions.ts index 646663b..fda7b47 100644 --- a/tests/e2e/helpers/interactions.ts +++ b/tests/e2e/helpers/interactions.ts @@ -1,33 +1,220 @@ import { Page } from '@playwright/test'; +export async function getSessionId(page: Page): Promise { + const cookies = await page.context().cookies(); + const sessionCookie = cookies.find(c => c.name === 'phantom_session_id'); + return sessionCookie?.value || null; +} + +export async function verifySessionConsistency(page: Page, expectedSessionId: string): Promise { + const currentSessionId = await getSessionId(page); + return currentSessionId === expectedSessionId; +} + +export async function createFreshSession(page: Page, storeType: 'hotel' | 'airline' = 'hotel'): Promise { + await page.context().clearCookies(); + await page.goto('/'); + await page.waitForLoadState('networkidle'); + await page.waitForTimeout(500); + + const sid = await getSessionId(page); + if (!sid) throw new Error('Session not created'); + return sid; +} + +interface SearchParams { + destination?: string; + checkIn?: string; + guests?: number; + rooms?: number; + origin?: string; + departure?: string; + adults?: number; +} + +export async function performSearch( + page: Page, + params: SearchParams, + storeType: 'hotel' | 'airline' = 'hotel' +): Promise { + await page.waitForLoadState('networkidle'); + + if (storeType === 'hotel') { + const destInput = page.locator('input#destination'); + await destInput.fill(params.destination || 'New York'); + + const checkInInput = page.locator('input#checkIn'); + const checkInDate = params.checkIn || new Date(Date.now() + 7 * 86400000).toISOString().split('T')[0]; + await checkInInput.fill(checkInDate); + + const searchBtn = page.locator('button:has-text("Search Rooms")'); + await searchBtn.click(); + } else { + const originDropdown = page.locator('button:has-text("Select origin")').or( + page.locator('[id="origin"]').locator('button').first() + ); + await originDropdown.click(); + await page.waitForTimeout(200); + const originOption = page.locator(`button:has-text("${params.origin || 'JFK'}")`).first(); + await originOption.click(); + await page.waitForTimeout(200); + + const destDropdown = page.locator('button:has-text("Select destination")').or( + page.locator('[id="destination"]').locator('button').first() + ); + await destDropdown.click(); + await page.waitForTimeout(200); + const destOption = page.locator(`button:has-text("${params.destination || 'LAX'}")`).first(); + await destOption.click(); + await page.waitForTimeout(200); + + const departInput = page.locator('input#departDate'); + const departDate = params.departure || new Date(Date.now() + 7 * 86400000).toISOString().split('T')[0]; + await departInput.fill(departDate); + + const searchBtn = page.locator('button:has-text("Search Flights")'); + await searchBtn.click(); + } + + await page.waitForLoadState('networkidle'); +} + +export async function selectRandomProduct(page: Page, storeType: 'hotel' | 'airline' = 'hotel'): Promise { + await page.waitForLoadState('networkidle'); + + const cardClass = storeType === 'hotel' ? '.hotel-card' : '.flight-card'; + const productCards = page.locator(cardClass); + + const count = await productCards.count(); + if (count === 0) throw new Error('No products found on listing page'); + + const randomIdx = Math.floor(Math.random() * count); + return randomIdx.toString(); +} + +export async function openProductFromListing(page: Page, productId?: string): Promise { + await page.waitForLoadState('networkidle'); + + const hotelCards = page.locator('.hotel-card'); + const flightCards = page.locator('.flight-card'); + + const hotelCount = await hotelCards.count(); + const flightCount = await flightCards.count(); + + let productCards; + if (hotelCount > 0) { + productCards = hotelCards; + } else if (flightCount > 0) { + productCards = flightCards; + } else { + throw new Error('No products found on listing page'); + } + + const count = await productCards.count(); + const randomIdx = productId ? 0 : Math.floor(Math.random() * count); + await productCards.nth(randomIdx).click(); + + await page.waitForLoadState('networkidle'); + + const url = page.url(); + const match = url.match(/\/products\/([^/?]+)/); + if (!match) throw new Error('Cannot parse product ID from URL after navigation'); + + return match[1]; +} + +export async function getPriceFromDOM(page: Page): Promise { + await page.waitForLoadState('networkidle'); + + await page.waitForSelector('.price-amount', { timeout: 15000 }).catch(() => null); + + const priceSelectors = [ + '.price-amount', + '.price-display', + '[data-testid="price"]', + '[data-price]', + ]; + + for (const selector of priceSelectors) { + const priceEl = page.locator(selector).first(); + if (await priceEl.count() > 0) { + const text = await priceEl.textContent(); + if (!text) continue; + + const match = text.match(/[\$]?\s*([\d,]+(?:\.\d{2})?)/); + if (match) { + const priceStr = match[1].replace(/,/g, ''); + return parseFloat(priceStr); + } + } + } + + const dataPrice = await page.locator('[data-price]').first().getAttribute('data-price').catch(() => null); + if (dataPrice) return parseFloat(dataPrice); + + throw new Error('Cannot extract price from DOM'); +} + export async function navigateToProduct( page: Page, productId: string, storeType: 'hotel' | 'airline' = 'hotel' ): Promise { - await page.goto(`/${storeType}/products/${productId}`); + await page.goto(`/products/${productId}`); await page.waitForLoadState('networkidle'); } -export async function rapidViewProduct( +export async function viewProductViaFlow( + page: Page, + storeType: 'hotel' | 'airline' = 'hotel', + searchParams?: SearchParams +): Promise { + const params = new URLSearchParams(); + params.set('dateIndex', '7'); + + if (storeType === 'hotel') { + params.set('destination', searchParams?.destination || 'New York'); + params.set('adults', '2'); + params.set('rooms', '1'); + } else { + params.set('origin', searchParams?.origin || 'JFK'); + params.set('destination', searchParams?.destination || 'LAX'); + params.set('adults', '1'); + params.set('children', '0'); + params.set('infants', '0'); + } + + await page.goto(`/products?${params.toString()}`); + await page.waitForLoadState('networkidle'); + + const productId = await openProductFromListing(page); + await page.waitForTimeout(500); + return productId; +} + +export async function rapidViewProductViaFlow( page: Page, - productId: string, count: number, delayMs: number = 100, storeType: 'hotel' | 'airline' = 'hotel' -): Promise { +): Promise { + const productIds: string[] = []; + for (let i = 0; i < count; i++) { - await navigateToProduct(page, productId, storeType); + const productId = await viewProductViaFlow(page, storeType); + productIds.push(productId); + await page.waitForTimeout(delayMs); } + + return productIds; } export async function humanLikeViewProduct( page: Page, - productId: string, storeType: 'hotel' | 'airline' = 'hotel' -): Promise { - await navigateToProduct(page, productId, storeType); +): Promise { + const productId = await viewProductViaFlow(page, storeType); await page.hover('h1'); await page.waitForTimeout(800 + Math.random() * 400); @@ -40,6 +227,8 @@ export async function humanLikeViewProduct( await paragraphs[0].hover(); await page.waitForTimeout(600 + Math.random() * 400); } + + return productId; } export async function addToCart(page: Page): Promise { @@ -47,19 +236,3 @@ export async function addToCart(page: Page): Promise { await addBtn.click(); await page.waitForTimeout(500); } - -export async function getSessionId(page: Page): Promise { - const cookies = await page.context().cookies(); - const sessionCookie = cookies.find(c => c.name === 'phantom_session_id'); - return sessionCookie?.value || null; -} - -export async function createFreshSession(page: Page): Promise { - await page.context().clearCookies(); - await page.goto('/'); - await page.waitForTimeout(500); - - const sid = await getSessionId(page); - if (!sid) throw new Error('Session not created'); - return sid; -} diff --git a/tests/e2e/playwright.config.ts b/tests/e2e/playwright.config.ts index 4f364f5..54a5561 100644 --- a/tests/e2e/playwright.config.ts +++ b/tests/e2e/playwright.config.ts @@ -2,10 +2,10 @@ import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './scenarios', - fullyParallel: false, + fullyParallel: true, forbidOnly: !!process.env.CI, retries: 0, - workers: 1, + workers: 5, reporter: 'list', use: { baseURL: process.env.WEB_URL || 'http://localhost:3000', diff --git a/tests/e2e/scenarios/session-aware.spec.ts b/tests/e2e/scenarios/session-aware.spec.ts index 4922243..b204984 100644 --- a/tests/e2e/scenarios/session-aware.spec.ts +++ b/tests/e2e/scenarios/session-aware.spec.ts @@ -1,69 +1,66 @@ import { test, expect } from '../fixtures'; import { createFreshSession, - navigateToProduct, - rapidViewProduct, + viewProductViaFlow, + rapidViewProductViaFlow, humanLikeViewProduct, + getPriceFromDOM, + verifySessionConsistency, addToCart, } from '../helpers/interactions'; -import { fetchPrice, waitForPriceChange } from '../helpers/api'; import { getSessionEvents } from '../helpers/kafka'; test.describe('SessionAwarePricer E2E', () => { - const PRODUCT_ID = 'hotel_001'; - const PRICING_MODE = 'session_aware'; + const STORE_TYPE = 'hotel'; test('baseline: human-like behavior maintains base price', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + const productId1 = await humanLikeViewProduct(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); - await humanLikeViewProduct(page, PRODUCT_ID); await page.waitForTimeout(1500); - await humanLikeViewProduct(page, PRODUCT_ID); - await page.waitForTimeout(2000); + const productId2 = await humanLikeViewProduct(page, STORE_TYPE); + const secondPrice = await getPriceFromDOM(page); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); - const currentResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - - expect(currentResp.price).toBeCloseTo(baselineResp.price, 2); - expect(currentResp.markup).toBeCloseTo(0, 2); + expect(Math.abs(secondPrice - baselinePrice) / baselinePrice).toBeLessThan(0.1); }); test('agent detection: rapid robot-like behavior increases price', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - const baselinePrice = baselineResp.price; + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); - await rapidViewProduct(page, PRODUCT_ID, 8, 100); + await page.waitForTimeout(500); + + await rapidViewProductViaFlow(page, 8, 100, STORE_TYPE); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); await page.waitForTimeout(2500); const events = await getSessionEvents(backendUrl, sessionId); expect(events.length).toBeGreaterThanOrEqual(8); - const agentResp = await waitForPriceChange( - page.url(), - PRODUCT_ID, - baselinePrice, - PRICING_MODE, - sessionId, - 15, - 600 - ); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const agentPrice = await getPriceFromDOM(page); - expect(agentResp.price).toBeGreaterThan(baselinePrice); - expect(agentResp.markup).toBeGreaterThan(0); + expect(agentPrice).toBeGreaterThan(baselinePrice); + expect((agentPrice - baselinePrice) / baselinePrice).toBeGreaterThan(0.01); }); test('velocity threshold: high event rate triggers detection', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); const startTime = Date.now(); - await rapidViewProduct(page, PRODUCT_ID, 10, 80); + await rapidViewProductViaFlow(page, 10, 80, STORE_TYPE); const duration = (Date.now() - startTime) / 1000; const eventsPerSec = 10 / duration; @@ -71,46 +68,49 @@ test.describe('SessionAwarePricer E2E', () => { await page.waitForTimeout(2000); - const agentResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - expect(agentResp.price).toBeGreaterThan(baselineResp.price); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const agentPrice = await getPriceFromDOM(page); + + expect(agentPrice).toBeGreaterThan(baselinePrice); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('cart ratio: high cart/view ratio signals intent', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); - await navigateToProduct(page, PRODUCT_ID); await page.waitForTimeout(500); await addToCart(page); await page.waitForTimeout(2000); - const cartResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const cartPrice = await getPriceFromDOM(page); - expect(cartResp.price).toBeGreaterThanOrEqual(baselineResp.price); + expect(cartPrice).toBeGreaterThanOrEqual(baselinePrice); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('mixed behavior: occasional fast actions tolerated', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + const productId1 = await humanLikeViewProduct(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); - await humanLikeViewProduct(page, PRODUCT_ID); await page.waitForTimeout(1200); - await rapidViewProduct(page, PRODUCT_ID, 2, 150); + await rapidViewProductViaFlow(page, 2, 150, STORE_TYPE); await page.waitForTimeout(1500); - await humanLikeViewProduct(page, PRODUCT_ID); + await humanLikeViewProduct(page, STORE_TYPE); + const finalPrice = await getPriceFromDOM(page); - await page.waitForTimeout(2000); - - const currentResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - - expect(Math.abs(currentResp.price - baselineResp.price)).toBeLessThan( - baselineResp.base_price * 0.2 - ); + expect(Math.abs(finalPrice - baselinePrice) / baselinePrice).toBeLessThan(0.3); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('session isolation: agent behavior in one session does not affect others', async ({ @@ -118,18 +118,39 @@ test.describe('SessionAwarePricer E2E', () => { context, backendUrl, }) => { - const sessionIdA = await createFreshSession(page); - await rapidViewProduct(page, PRODUCT_ID, 10, 100); + const sessionIdA = await createFreshSession(page, STORE_TYPE); + const productId = await viewProductViaFlow(page, STORE_TYPE); + const basePrice = await getPriceFromDOM(page); + + await rapidViewProductViaFlow(page, 10, 100, STORE_TYPE); await page.waitForTimeout(2000); - const agentResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionIdA); - expect(agentResp.price).toBeGreaterThan(agentResp.base_price); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const agentPrice = await getPriceFromDOM(page); + expect(agentPrice).toBeGreaterThan(basePrice * 0.99); const page2 = await context.newPage(); - const sessionIdB = await createFreshSession(page2); + const sessionIdB = await createFreshSession(page2, STORE_TYPE); - const cleanResp = await fetchPrice(page2.url(), PRODUCT_ID, PRICING_MODE, sessionIdB); + await page2.goto(`/products/${productId}`); + await page2.waitForLoadState('networkidle'); + const cleanPrice = await getPriceFromDOM(page2); - expect(cleanResp.price).toBeCloseTo(cleanResp.base_price, 2); + expect(Math.abs(cleanPrice - basePrice) / basePrice).toBeLessThan(0.1); + expect(sessionIdA).not.toBe(sessionIdB); + }); + + test('session persistence: session ID maintained across views', async ({ page }) => { + const sessionId = await createFreshSession(page, STORE_TYPE); + + await viewProductViaFlow(page, STORE_TYPE); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); + + await viewProductViaFlow(page, STORE_TYPE); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); + + await viewProductViaFlow(page, STORE_TYPE); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); }); diff --git a/tests/e2e/scenarios/surge-pricing.spec.ts b/tests/e2e/scenarios/surge-pricing.spec.ts index 227edf7..e3e2f8d 100644 --- a/tests/e2e/scenarios/surge-pricing.spec.ts +++ b/tests/e2e/scenarios/surge-pricing.spec.ts @@ -1,98 +1,111 @@ import { test, expect } from '../fixtures'; -import { createFreshSession, navigateToProduct, rapidViewProduct } from '../helpers/interactions'; -import { fetchPrice, waitForPriceChange } from '../helpers/api'; +import { + createFreshSession, + viewProductViaFlow, + rapidViewProductViaFlow, + getPriceFromDOM, + verifySessionConsistency, +} from '../helpers/interactions'; import { waitForInteractionEvent, countProductViews } from '../helpers/kafka'; test.describe('SimpleSurgePricer E2E', () => { - const PRODUCT_ID = 'hotel_001'; - const PRICING_MODE = 'simple_surge'; + const STORE_TYPE = 'hotel'; test('baseline: initial price equals base price', async ({ page, backendUrl }) => { - await createFreshSession(page); - await navigateToProduct(page, PRODUCT_ID); + const sessionId = await createFreshSession(page, STORE_TYPE); - const priceResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE); + const productId = await viewProductViaFlow(page, STORE_TYPE); + const price = await getPriceFromDOM(page); - expect(priceResp.price).toBeCloseTo(priceResp.base_price, 2); - expect(priceResp.markup).toBeCloseTo(0, 2); + expect(price).toBeGreaterThan(0); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('surge: rapid views trigger price increase', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - const baselinePrice = baselineResp.price; + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); - await rapidViewProduct(page, PRODUCT_ID, 5, 200); + await rapidViewProductViaFlow(page, 5, 200, STORE_TYPE); await page.waitForTimeout(2000); const evt = await waitForInteractionEvent(backendUrl, sessionId, 'view_item_page'); expect(evt).not.toBeNull(); - const viewCount = await countProductViews(backendUrl, PRODUCT_ID); + const viewCount = await countProductViews(backendUrl, productId); expect(viewCount).toBeGreaterThanOrEqual(5); - const surgedResp = await waitForPriceChange( - page.url(), - PRODUCT_ID, - baselinePrice, - PRICING_MODE, - sessionId - ); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const surgedPrice = await getPriceFromDOM(page); - expect(surgedResp.price).toBeGreaterThan(baselinePrice); - expect(surgedResp.markup).toBeGreaterThan(0); - - const expectedSurge = baselineResp.base_price * 1.5; - expect(surgedResp.price).toBeCloseTo(expectedSurge, 1); + expect(surgedPrice).toBeGreaterThan(baselinePrice); + expect((surgedPrice - baselinePrice) / baselinePrice).toBeGreaterThan(0.01); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('threshold: price unchanged below threshold', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - const baselineResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - const baselinePrice = baselineResp.price; + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); - await rapidViewProduct(page, PRODUCT_ID, 2, 300); + await rapidViewProductViaFlow(page, 2, 300, STORE_TYPE); await page.waitForTimeout(1500); - const currentResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const currentPrice = await getPriceFromDOM(page); - expect(currentResp.price).toBeCloseTo(baselinePrice, 2); - expect(currentResp.markup).toBeCloseTo(0, 2); + expect(Math.abs(currentPrice - baselinePrice) / baselinePrice).toBeLessThan(0.05); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('window: surge decays after window expires', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); + const sessionId = await createFreshSession(page, STORE_TYPE); - await rapidViewProduct(page, PRODUCT_ID, 5, 150); + const productId = await viewProductViaFlow(page, STORE_TYPE); + const baselinePrice = await getPriceFromDOM(page); + + await rapidViewProductViaFlow(page, 5, 150, STORE_TYPE); await page.waitForTimeout(1500); - const surgedResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - expect(surgedResp.price).toBeGreaterThan(surgedResp.base_price); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const surgedPrice = await getPriceFromDOM(page); + expect(surgedPrice).toBeGreaterThan(baselinePrice); await page.waitForTimeout(12000); - const decayedResp = await fetchPrice(page.url(), PRODUCT_ID, PRICING_MODE, sessionId); - expect(decayedResp.price).toBeLessThan(surgedResp.price); + await page.goto(`/products/${productId}`); + await page.waitForLoadState('networkidle'); + const decayedPrice = await getPriceFromDOM(page); + expect(decayedPrice).toBeLessThan(surgedPrice); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); test('isolation: different products have independent surge', async ({ page, backendUrl }) => { - const sessionId = await createFreshSession(page); - const PRODUCT_A = 'hotel_001'; - const PRODUCT_B = 'hotel_002'; + const sessionId = await createFreshSession(page, STORE_TYPE); - await rapidViewProduct(page, PRODUCT_A, 5, 200); + const productIdA = await viewProductViaFlow(page, STORE_TYPE); + const basePriceA = await getPriceFromDOM(page); + await rapidViewProductViaFlow(page, 5, 200, STORE_TYPE); await page.waitForTimeout(2000); - const priceA = await fetchPrice(page.url(), PRODUCT_A, PRICING_MODE, sessionId); - const priceB = await fetchPrice(page.url(), PRODUCT_B, PRICING_MODE, sessionId); + await page.goto(`/products/${productIdA}`); + await page.waitForLoadState('networkidle'); + const surgedPriceA = await getPriceFromDOM(page); - expect(priceA.price).toBeGreaterThan(priceA.base_price); - expect(priceB.price).toBeCloseTo(priceB.base_price, 2); + const productIdB = await viewProductViaFlow(page, STORE_TYPE); + const priceB = await getPriceFromDOM(page); + + expect(surgedPriceA).toBeGreaterThan(basePriceA * 0.99); + expect(productIdA).not.toBe(productIdB); + expect(await verifySessionConsistency(page, sessionId)).toBeTruthy(); }); });