@@ -2,6 +2,26 @@ const { expect } = require("@playwright/test");
2
2
const config = require ( "../config" ) ;
3
3
const { getCreditCardExpiry } = require ( "../scripts/utils.js" )
4
4
5
+ /**
6
+ * Give an answer to the consent tracking form.
7
+ *
8
+ * Note: the consent tracking form hovers over some elements in the app. This can cause a test to fail.
9
+ * Run this function after a page.goto to release the form from view.
10
+ *
11
+ * @param {Object } page - Object that represents a tab/window in the browser provided by playwright
12
+ * @param {Boolean } dnt - Do Not Track value to answer the form. False to enable tracking, True to disable tracking.
13
+ */
14
+ export const answerConsentTrackingForm = async ( page , dnt = false ) => {
15
+ if ( await page . locator ( 'text=Tracking Consent' ) . count ( ) > 0 ) {
16
+ var text = 'Accept'
17
+ if ( dnt )
18
+ text = 'Decline'
19
+ const answerButton = page . locator ( 'button:visible' , { hasText : text } ) ;
20
+ await expect ( answerButton ) . toBeVisible ( ) ;
21
+ await answerButton . click ( ) ;
22
+ }
23
+ }
24
+
5
25
/**
6
26
* Navigates to the `Cotton Turtleneck Sweater` PDP (Product Detail Page) on mobile
7
27
* with the black variant selected
@@ -11,6 +31,7 @@ const { getCreditCardExpiry } = require("../scripts/utils.js")
11
31
export const navigateToPDPMobile = async ( { page} ) => {
12
32
// Home page
13
33
await page . goto ( config . RETAIL_APP_HOME ) ;
34
+ await answerConsentTrackingForm ( page )
14
35
15
36
await page . getByLabel ( "Menu" , { exact : true } ) . click ( ) ;
16
37
@@ -64,6 +85,7 @@ export const navigateToPDPMobile = async ({page}) => {
64
85
*/
65
86
export const navigateToPDPDesktop = async ( { page} ) => {
66
87
await page . goto ( config . RETAIL_APP_HOME ) ;
88
+ await answerConsentTrackingForm ( page )
67
89
68
90
await page . getByRole ( "link" , { name : "Womens" } ) . hover ( ) ;
69
91
const topsNav = await page . getByRole ( "link" , { name : "Tops" , exact : true } ) ;
@@ -144,6 +166,7 @@ export const addProductToCart = async ({page, isMobile = false}) => {
144
166
export const registerShopper = async ( { page, userCredentials, isMobile = false } ) => {
145
167
// Create Account and Sign In
146
168
await page . goto ( config . RETAIL_APP_HOME + "/registration" ) ;
169
+ await answerConsentTrackingForm ( page )
147
170
148
171
await page . waitForLoadState ( ) ;
149
172
@@ -160,10 +183,13 @@ export const registerShopper = async ({page, userCredentials, isMobile = false})
160
183
await page
161
184
. locator ( "input#password" )
162
185
. fill ( userCredentials . password ) ;
163
-
186
+
187
+ // Best Practice: await the network call and assert on the network response rather than waiting for pageLoadState()
188
+ // to avoid race conditions from lock in pageLoadState being released before network call resolves
189
+ const tokenResponsePromise = page . waitForResponse ( '**/shopper/auth/v1/organizations/**/oauth2/token' )
164
190
await page . getByRole ( "button" , { name : / C r e a t e A c c o u n t / i } ) . click ( ) ;
165
-
166
- await page . waitForLoadState ( ) ;
191
+ await tokenResponsePromise ;
192
+ expect ( ( await tokenResponsePromise ) . status ( ) ) . toBe ( 200 ) ;
167
193
168
194
await expect (
169
195
page . getByRole ( "heading" , { name : / A c c o u n t D e t a i l s / i } )
@@ -186,6 +212,8 @@ export const registerShopper = async ({page, userCredentials, isMobile = false})
186
212
*/
187
213
export const validateOrderHistory = async ( { page} ) => {
188
214
await page . goto ( config . RETAIL_APP_HOME + "/account/orders" ) ;
215
+ await answerConsentTrackingForm ( page )
216
+
189
217
await expect (
190
218
page . getByRole ( "heading" , { name : / O r d e r H i s t o r y / i } )
191
219
) . toBeVisible ( ) ;
@@ -209,6 +237,7 @@ export const validateOrderHistory = async ({page}) => {
209
237
*/
210
238
export const validateWishlist = async ( { page} ) => {
211
239
await page . goto ( config . RETAIL_APP_HOME + "/account/wishlist" ) ;
240
+ await answerConsentTrackingForm ( page )
212
241
213
242
await expect (
214
243
page . getByRole ( "heading" , { name : / W i s h l i s t / i } )
@@ -236,19 +265,17 @@ export const validateWishlist = async ({page}) => {
236
265
export const loginShopper = async ( { page, userCredentials} ) => {
237
266
try {
238
267
await page . goto ( config . RETAIL_APP_HOME + "/login" ) ;
268
+ await answerConsentTrackingForm ( page )
269
+
239
270
await page . locator ( "input#email" ) . fill ( userCredentials . email ) ;
240
271
await page
241
272
. locator ( "input#password" )
242
273
. fill ( userCredentials . password ) ;
274
+
275
+ const tokenResponsePromise = page . waitForResponse ( '**/shopper/auth/v1/organizations/**/oauth2/token' )
243
276
await page . getByRole ( "button" , { name : / S i g n I n / i } ) . click ( ) ;
244
-
245
- await page . waitForLoadState ( ) ;
246
-
247
- // redirected to Account Details page after logging in
248
- await expect (
249
- page . getByRole ( "heading" , { name : / A c c o u n t D e t a i l s / i } )
250
- ) . toBeVisible ( { timeout : 2000 } ) ;
251
- return true ;
277
+ await tokenResponsePromise ;
278
+ return await tokenResponsePromise . status ( ) === 200 ;
252
279
} catch {
253
280
return false ;
254
281
}
@@ -263,7 +290,7 @@ export const loginShopper = async ({page, userCredentials}) => {
263
290
*/
264
291
export const searchProduct = async ( { page, query, isMobile = false } ) => {
265
292
await page . goto ( config . RETAIL_APP_HOME ) ;
266
-
293
+ await answerConsentTrackingForm ( page )
267
294
// For accessibility reasons, we have two search bars
268
295
// one for desktop and one for mobile depending on your device type
269
296
const searchInputs = page . locator ( 'input[aria-label="Search for products..."]' ) ;
0 commit comments