From 5cd650cd9fdf3137cb0405f13d67cfe9227518b5 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Mon, 27 Jan 2025 19:55:53 -0800 Subject: [PATCH 01/19] some updates --- e2e/scripts/pageHelpers.js | 22 ++++++++++++++++++- e2e/tests/desktop/registered-shopper.spec.js | 2 +- e2e/tests/dnt.spec.js | 4 +++- e2e/tests/homepage.spec.js | 2 ++ packages/commerce-sdk-react/src/auth/index.ts | 3 +++ 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index b67b4a6e6c..2f236f1b9c 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -2,6 +2,17 @@ const { expect } = require("@playwright/test"); const config = require("../config"); const { getCreditCardExpiry } = require("../scripts/utils.js") +export const answerConsentTrackingForm = async (page, dnt = true) => { + if (await page.locator('text=Tracking Consent').count() > 0) { + var text = 'Accept' + if (dnt) + text = 'Decline' + const answerButton = page.locator('button:visible', { hasText: text }); + await expect(answerButton).toBeVisible(); + await answerButton.click(); + } +} + /** * Navigates to the `Cotton Turtleneck Sweater` PDP (Product Detail Page) on mobile * with the black variant selected @@ -11,6 +22,7 @@ const { getCreditCardExpiry } = require("../scripts/utils.js") export const navigateToPDPMobile = async ({page}) => { // Home page await page.goto(config.RETAIL_APP_HOME); + await answerConsentTrackingForm(page) await page.getByLabel("Menu", { exact: true }).click(); @@ -64,6 +76,7 @@ export const navigateToPDPMobile = async ({page}) => { */ export const navigateToPDPDesktop = async ({page}) => { await page.goto(config.RETAIL_APP_HOME); + await answerConsentTrackingForm(page) await page.getByRole("link", { name: "Womens" }).hover(); const topsNav = await page.getByRole("link", { name: "Tops", exact: true }); @@ -144,6 +157,7 @@ export const addProductToCart = async ({page, isMobile = false}) => { export const registerShopper = async ({page, userCredentials, isMobile = false}) => { // Create Account and Sign In await page.goto(config.RETAIL_APP_HOME + "/registration"); + await answerConsentTrackingForm(page) await page.waitForLoadState(); @@ -186,6 +200,8 @@ export const registerShopper = async ({page, userCredentials, isMobile = false}) */ export const validateOrderHistory = async ({page}) => { await page.goto(config.RETAIL_APP_HOME + "/account/orders"); + await answerConsentTrackingForm(page) + await expect( page.getByRole("heading", { name: /Order History/i }) ).toBeVisible(); @@ -209,6 +225,7 @@ export const validateOrderHistory = async ({page}) => { */ export const validateWishlist = async ({page}) => { await page.goto(config.RETAIL_APP_HOME + "/account/wishlist"); + await answerConsentTrackingForm(page) await expect( page.getByRole("heading", { name: /Wishlist/i }) @@ -236,6 +253,9 @@ export const validateWishlist = async ({page}) => { export const loginShopper = async ({page, userCredentials}) => { try { await page.goto(config.RETAIL_APP_HOME + "/login"); + await answerConsentTrackingForm(page) + + // await answerConsentTrackingForm(page) await page.locator("input#email").fill(userCredentials.email); await page .locator("input#password") @@ -263,7 +283,7 @@ export const loginShopper = async ({page, userCredentials}) => { */ export const searchProduct = async ({page, query, isMobile = false}) => { await page.goto(config.RETAIL_APP_HOME); - + await answerConsentTrackingForm(page) // For accessibility reasons, we have two search bars // one for desktop and one for mobile depending on your device type const searchInputs = page.locator('input[aria-label="Search for products..."]'); diff --git a/e2e/tests/desktop/registered-shopper.spec.js b/e2e/tests/desktop/registered-shopper.spec.js index c1c34afa17..9905b45175 100644 --- a/e2e/tests/desktop/registered-shopper.spec.js +++ b/e2e/tests/desktop/registered-shopper.spec.js @@ -146,7 +146,7 @@ test("Registered shopper can add item to wishlist", async ({ page }) => { page, userCredentials: REGISTERED_USER_CREDENTIALS }) - + // console.log("(JEREMY) isLoggedIn: ", isLoggedIn) if(!isLoggedIn) { await registerShopper({page, userCredentials: REGISTERED_USER_CREDENTIALS}) } diff --git a/e2e/tests/dnt.spec.js b/e2e/tests/dnt.spec.js index 9565205a21..f724298087 100644 --- a/e2e/tests/dnt.spec.js +++ b/e2e/tests/dnt.spec.js @@ -51,7 +51,7 @@ const checkDntCookie = async (page, expectedValue) => { test("Shopper can use the consent tracking form", async ({ page }) => { - await page.context().clearCookies(); + // await page.context().clearCookies(); await page.goto(config.RETAIL_APP_HOME); const modalSelector = '[aria-label="Close consent tracking form"]' @@ -77,6 +77,8 @@ test("Shopper can use the consent tracking form", async ({ page }) => { await page.click('text=Womens'); // Reloading the page after setting DNT makes the form not appear again await page.reload() + checkDntCookie(page, '1') + console.log("(JEREMY) dnt cookie is 1") await expect(page.getByText(/Tracking Consent/i)).toBeHidden(); // Registering after setting DNT persists the preference diff --git a/e2e/tests/homepage.spec.js b/e2e/tests/homepage.spec.js index a8f57c06f3..fe0687f9cd 100644 --- a/e2e/tests/homepage.spec.js +++ b/e2e/tests/homepage.spec.js @@ -7,10 +7,12 @@ const { test, expect } = require("@playwright/test"); const config = require("../config"); +const {answerConsentTrackingForm} = require("../scripts/pageHelpers.js") test.describe("Retail app home page loads", () => { test.beforeEach(async ({ page }) => { await page.goto(config.RETAIL_APP_HOME); + await answerConsentTrackingForm(page); }); test("has title", async ({ page }) => { diff --git a/packages/commerce-sdk-react/src/auth/index.ts b/packages/commerce-sdk-react/src/auth/index.ts index 6dc8fed1de..76f95c771d 100644 --- a/packages/commerce-sdk-react/src/auth/index.ts +++ b/packages/commerce-sdk-react/src/auth/index.ts @@ -336,8 +336,11 @@ class Auth { if (accessToken) { const {dnt} = this.parseSlasJWT(accessToken) isInSync = dnt === dntCookieVal + console.log("(JEREMY) dnt from token: ", dnt) + console.log("(JEREMY) dnt from cookie: ", dntCookieVal) } if ((dntCookieVal !== '1' && dntCookieVal !== '0') || !isInSync) { + console.log("(JEREMY) is not in sync. deleting cookie") this.delete(DNT_COOKIE_NAME) } else { dntCookieStatus = Boolean(Number(dntCookieVal)) From b3e512037aad592d9b0d4b1f9d69eb95c7efd3af Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Mon, 27 Jan 2025 20:01:01 -0800 Subject: [PATCH 02/19] port change just for dev --- packages/test-commerce-sdk-react/app/ssr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/test-commerce-sdk-react/app/ssr.js b/packages/test-commerce-sdk-react/app/ssr.js index e681f6ae5a..3de25b8860 100644 --- a/packages/test-commerce-sdk-react/app/ssr.js +++ b/packages/test-commerce-sdk-react/app/ssr.js @@ -17,7 +17,7 @@ const options = { defaultCacheTimeSeconds: 600, // The port that the local dev server listens on - port: 3000, + port: 4000, // The protocol on which the development Express app listens. // Note that http://localhost is treated as a secure context for development, From 3b0726c8840f5e2e90e93a065d042fb97159e250 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 00:51:23 -0800 Subject: [PATCH 03/19] DNT test suite fix --- e2e/tests/{ => desktop}/dnt.spec.js | 48 +++------- e2e/tests/mobile/dnt.spec.js | 93 +++++++++++++++++++ packages/commerce-sdk-react/src/auth/index.ts | 3 - 3 files changed, 104 insertions(+), 40 deletions(-) rename e2e/tests/{ => desktop}/dnt.spec.js (65%) create mode 100644 e2e/tests/mobile/dnt.spec.js diff --git a/e2e/tests/dnt.spec.js b/e2e/tests/desktop/dnt.spec.js similarity index 65% rename from e2e/tests/dnt.spec.js rename to e2e/tests/desktop/dnt.spec.js index f724298087..e49c2bcf0a 100644 --- a/e2e/tests/dnt.spec.js +++ b/e2e/tests/desktop/dnt.spec.js @@ -6,41 +6,16 @@ */ const { test, expect } = require("@playwright/test"); -const config = require("../config"); +const config = require("../../config.js"); const { generateUserCredentials -} = require("../scripts/utils.js"); +} = require("../../scripts/utils.js"); +const { + registerShopper +} = require("../../scripts/pageHelpers.js") const REGISTERED_USER_CREDENTIALS = generateUserCredentials(); -const registerUser = async (page) => { - await page.goto(config.RETAIL_APP_HOME + "/registration"); - - const registrationFormHeading = page.getByText(/Let's get started!/i); - await registrationFormHeading.waitFor(); - - await page - .locator("input#firstName") - .fill(REGISTERED_USER_CREDENTIALS.firstName); - await page - .locator("input#lastName") - .fill(REGISTERED_USER_CREDENTIALS.lastName); - await page.locator("input#email").fill(REGISTERED_USER_CREDENTIALS.email); - await page - .locator("input#password") - .fill(REGISTERED_USER_CREDENTIALS.password); - - await page.getByRole("button", { name: /Create Account/i }).click(); - - await expect( - page.getByRole("heading", { name: /Account Details/i }) - ).toBeVisible(); - - await expect( - page.getByRole("heading", { name: /My Account/i }) - ).toBeVisible(); -} - const checkDntCookie = async (page, expectedValue) => { var cookies = await page.context().cookies(); var cookieName = 'dw_dnt'; @@ -49,9 +24,9 @@ const checkDntCookie = async (page, expectedValue) => { expect(cookie.value).toBe(expectedValue); } +test("Shopper can use the consent tracking form", async ({page}) => { + await page.context().clearCookies(); -test("Shopper can use the consent tracking form", async ({ page }) => { - // await page.context().clearCookies(); await page.goto(config.RETAIL_APP_HOME); const modalSelector = '[aria-label="Close consent tracking form"]' @@ -62,6 +37,7 @@ test("Shopper can use the consent tracking form", async ({ page }) => { const declineButton = page.locator('button:visible', { hasText: 'Decline' }); await expect(declineButton).toBeVisible(); await declineButton.click(); + await page.waitForTimeout(5000); // Intercept einstein request let apiCallsMade = false; @@ -71,19 +47,17 @@ test("Shopper can use the consent tracking form", async ({ page }) => { }); // The value of 1 comes from defaultDnt prop in _app-config/index.jsx - checkDntCookie(page, '1') + await checkDntCookie(page, '1') // Trigger einstein events await page.click('text=Womens'); // Reloading the page after setting DNT makes the form not appear again await page.reload() - checkDntCookie(page, '1') - console.log("(JEREMY) dnt cookie is 1") await expect(page.getByText(/Tracking Consent/i)).toBeHidden(); // Registering after setting DNT persists the preference - await registerUser(page) - checkDntCookie(page, '1') + await registerShopper({page, userCredentials: REGISTERED_USER_CREDENTIALS}); + await checkDntCookie(page, '1') // Logging out clears the preference const buttons = await page.getByText(/Log Out/i).elementHandles(); diff --git a/e2e/tests/mobile/dnt.spec.js b/e2e/tests/mobile/dnt.spec.js new file mode 100644 index 0000000000..8fd9ba8269 --- /dev/null +++ b/e2e/tests/mobile/dnt.spec.js @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023, Salesforce, Inc. + * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +const { test, expect } = require("@playwright/test"); +const config = require("../../config.js"); +const { + generateUserCredentials +} = require("../../scripts/utils.js"); +const { + registerShopper +} = require("../../scripts/pageHelpers.js") + +const REGISTERED_USER_CREDENTIALS = generateUserCredentials(); + +const checkDntCookie = async (page, expectedValue) => { + var cookies = await page.context().cookies(); + var cookieName = 'dw_dnt'; + var cookie = cookies.find(cookie => cookie.name === cookieName); + expect(cookie).toBeTruthy(); + expect(cookie.value).toBe(expectedValue); +} + +test("Shopper can use the consent tracking form", async ({page}) => { + await page.context().clearCookies(); + + await page.goto(config.RETAIL_APP_HOME); + + const modalSelector = '[aria-label="Close consent tracking form"]' + page.locator(modalSelector).waitFor() + await expect(page.getByText(/Tracking Consent/i)).toBeVisible({timeout: 10000}); + + // Decline Tracking + const declineButton = page.locator('button:visible', { hasText: 'Decline' }); + await expect(declineButton).toBeVisible(); + await declineButton.click(); + await page.waitForTimeout(5000); + + // Intercept einstein request + let apiCallsMade = false; + await page.route('https://api.cquotient.com/v3/activities/aaij-MobileFirst/viewCategory', (route) => { + apiCallsMade = true; + route.continue(); + }); + + // The value of 1 comes from defaultDnt prop in _app-config/index.jsx + await checkDntCookie(page, '1') + + // Trigger einstein events + await page.getByLabel("Menu", { exact: true }).click(); + + // SSR nav loads top level categories as direct links so we wait till all sub-categories load in the accordion + const categoryAccordion = page.locator( + "#category-nav .chakra-accordion__button svg+:text('Womens')" + ); + await categoryAccordion.waitFor(); + + await page.getByRole("button", { name: "Womens" }).click(); + + const clothingNav = page.getByRole("button", { name: "Clothing" }); + + await clothingNav.waitFor(); + + await clothingNav.click(); + // Reloading the page after setting DNT makes the form not appear again + await page.reload() + await expect(page.getByText(/Tracking Consent/i)).toBeHidden(); + + // Registering after setting DNT persists the preference + await registerShopper({page, userCredentials: REGISTERED_USER_CREDENTIALS}); + await checkDntCookie(page, '1') + + // Logging out clears the preference + await page.getByRole("heading", { name: /My Account/i }).click() + const buttons = await page.getByText(/Log Out/i).elementHandles(); + for (const button of buttons) { + if (await button.isVisible()) { + await button.click(); + break; + } + } + + var cookies = await page.context().cookies(); + if (cookies.some(item => item.name === "dw_dnt")) { + throw new Error('dw_dnt still exists in the cookies'); + } + await page.reload(); + await expect(page.getByText(/Tracking Consent/i)).toBeVisible({timeout: 10000}); + expect(apiCallsMade).toBe(false); +}); diff --git a/packages/commerce-sdk-react/src/auth/index.ts b/packages/commerce-sdk-react/src/auth/index.ts index 76f95c771d..6dc8fed1de 100644 --- a/packages/commerce-sdk-react/src/auth/index.ts +++ b/packages/commerce-sdk-react/src/auth/index.ts @@ -336,11 +336,8 @@ class Auth { if (accessToken) { const {dnt} = this.parseSlasJWT(accessToken) isInSync = dnt === dntCookieVal - console.log("(JEREMY) dnt from token: ", dnt) - console.log("(JEREMY) dnt from cookie: ", dntCookieVal) } if ((dntCookieVal !== '1' && dntCookieVal !== '0') || !isInSync) { - console.log("(JEREMY) is not in sync. deleting cookie") this.delete(DNT_COOKIE_NAME) } else { dntCookieStatus = Boolean(Number(dntCookieVal)) From db482741de18d6dfccf2f045b832c4864d9b72db Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 00:53:09 -0800 Subject: [PATCH 04/19] Put back port --- packages/template-retail-react-app/app/ssr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/template-retail-react-app/app/ssr.js b/packages/template-retail-react-app/app/ssr.js index 566af3e496..e48fe38bdb 100644 --- a/packages/template-retail-react-app/app/ssr.js +++ b/packages/template-retail-react-app/app/ssr.js @@ -33,7 +33,7 @@ const options = { mobify: getConfig(), // The port that the local dev server listens on - port: 3000, + port: 4000, // The protocol on which the development Express app listens. // Note that http://localhost is treated as a secure context for development, From ae34972314a934553a473d9b4a79dc9b8366862e Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 00:54:19 -0800 Subject: [PATCH 05/19] revert port --- packages/template-retail-react-app/app/ssr.js | 2 +- packages/test-commerce-sdk-react/app/ssr.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/template-retail-react-app/app/ssr.js b/packages/template-retail-react-app/app/ssr.js index e48fe38bdb..566af3e496 100644 --- a/packages/template-retail-react-app/app/ssr.js +++ b/packages/template-retail-react-app/app/ssr.js @@ -33,7 +33,7 @@ const options = { mobify: getConfig(), // The port that the local dev server listens on - port: 4000, + port: 3000, // The protocol on which the development Express app listens. // Note that http://localhost is treated as a secure context for development, diff --git a/packages/test-commerce-sdk-react/app/ssr.js b/packages/test-commerce-sdk-react/app/ssr.js index 3de25b8860..e681f6ae5a 100644 --- a/packages/test-commerce-sdk-react/app/ssr.js +++ b/packages/test-commerce-sdk-react/app/ssr.js @@ -17,7 +17,7 @@ const options = { defaultCacheTimeSeconds: 600, // The port that the local dev server listens on - port: 4000, + port: 3000, // The protocol on which the development Express app listens. // Note that http://localhost is treated as a secure context for development, From 096e2e28f0999f24eda88bbf8033f1d7ba0daf70 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 01:00:20 -0800 Subject: [PATCH 06/19] cleanup --- e2e/scripts/pageHelpers.js | 1 - e2e/tests/mobile/dnt.spec.js | 1 - 2 files changed, 2 deletions(-) diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index 2f236f1b9c..26f1e38075 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -255,7 +255,6 @@ export const loginShopper = async ({page, userCredentials}) => { await page.goto(config.RETAIL_APP_HOME + "/login"); await answerConsentTrackingForm(page) - // await answerConsentTrackingForm(page) await page.locator("input#email").fill(userCredentials.email); await page .locator("input#password") diff --git a/e2e/tests/mobile/dnt.spec.js b/e2e/tests/mobile/dnt.spec.js index 8fd9ba8269..0a37bb4652 100644 --- a/e2e/tests/mobile/dnt.spec.js +++ b/e2e/tests/mobile/dnt.spec.js @@ -37,7 +37,6 @@ test("Shopper can use the consent tracking form", async ({page}) => { const declineButton = page.locator('button:visible', { hasText: 'Decline' }); await expect(declineButton).toBeVisible(); await declineButton.click(); - await page.waitForTimeout(5000); // Intercept einstein request let apiCallsMade = false; From 381add643e80b8b2a751454c8bcd56d881a3a719 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 09:32:04 -0800 Subject: [PATCH 07/19] comments --- e2e/scripts/pageHelpers.js | 11 ++++++++++- e2e/tests/desktop/registered-shopper.spec.js | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index 26f1e38075..72eb795055 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -2,7 +2,16 @@ const { expect } = require("@playwright/test"); const config = require("../config"); const { getCreditCardExpiry } = require("../scripts/utils.js") -export const answerConsentTrackingForm = async (page, dnt = true) => { +/** + * Give an answer to the consent tracking form. + * + * Note: the consent tracking form hovers over some elements in the app. This can cause a test to fail. + * Run this function after a page.goto to release the form from view. + * + * @param {Object} page - Object that represents a tab/window in the browser provided by playwright + * @param {Boolean} dnt - Do Not Track value to answer the form. False to enable tracking, True to disable tracking. + */ +export const answerConsentTrackingForm = async (page, dnt = false) => { if (await page.locator('text=Tracking Consent').count() > 0) { var text = 'Accept' if (dnt) diff --git a/e2e/tests/desktop/registered-shopper.spec.js b/e2e/tests/desktop/registered-shopper.spec.js index 9905b45175..c1c34afa17 100644 --- a/e2e/tests/desktop/registered-shopper.spec.js +++ b/e2e/tests/desktop/registered-shopper.spec.js @@ -146,7 +146,7 @@ test("Registered shopper can add item to wishlist", async ({ page }) => { page, userCredentials: REGISTERED_USER_CREDENTIALS }) - // console.log("(JEREMY) isLoggedIn: ", isLoggedIn) + if(!isLoggedIn) { await registerShopper({page, userCredentials: REGISTERED_USER_CREDENTIALS}) } From e810f5871eacb23128aa798784788f4ad825b56d Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 09:43:15 -0800 Subject: [PATCH 08/19] clean up --- e2e/tests/desktop/dnt.spec.js | 5 ++--- e2e/tests/mobile/dnt.spec.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/e2e/tests/desktop/dnt.spec.js b/e2e/tests/desktop/dnt.spec.js index e49c2bcf0a..538b0115c6 100644 --- a/e2e/tests/desktop/dnt.spec.js +++ b/e2e/tests/desktop/dnt.spec.js @@ -24,7 +24,7 @@ const checkDntCookie = async (page, expectedValue) => { expect(cookie.value).toBe(expectedValue); } -test("Shopper can use the consent tracking form", async ({page}) => { +test("Shopper can use the consent tracking form", async ({ page }) => { await page.context().clearCookies(); await page.goto(config.RETAIL_APP_HOME); @@ -45,8 +45,7 @@ test("Shopper can use the consent tracking form", async ({page}) => { apiCallsMade = true; route.continue(); }); - - // The value of 1 comes from defaultDnt prop in _app-config/index.jsx + await checkDntCookie(page, '1') // Trigger einstein events diff --git a/e2e/tests/mobile/dnt.spec.js b/e2e/tests/mobile/dnt.spec.js index 0a37bb4652..66f72e7748 100644 --- a/e2e/tests/mobile/dnt.spec.js +++ b/e2e/tests/mobile/dnt.spec.js @@ -24,7 +24,7 @@ const checkDntCookie = async (page, expectedValue) => { expect(cookie.value).toBe(expectedValue); } -test("Shopper can use the consent tracking form", async ({page}) => { +test("Shopper can use the consent tracking form", async ({ page }) => { await page.context().clearCookies(); await page.goto(config.RETAIL_APP_HOME); @@ -45,7 +45,6 @@ test("Shopper can use the consent tracking form", async ({page}) => { route.continue(); }); - // The value of 1 comes from defaultDnt prop in _app-config/index.jsx await checkDntCookie(page, '1') // Trigger einstein events From 4f7b9d870bcc50135e55ae3e2020920bf13f4472 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Tue, 28 Jan 2025 11:30:39 -0800 Subject: [PATCH 09/19] some logging for dev --- .../template-retail-react-app/app/pages/product-list/index.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/template-retail-react-app/app/pages/product-list/index.jsx b/packages/template-retail-react-app/app/pages/product-list/index.jsx index d96422c7c7..3ba2c95c0f 100644 --- a/packages/template-retail-react-app/app/pages/product-list/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-list/index.jsx @@ -105,6 +105,7 @@ const REFINEMENT_DISALLOW_LIST = ['c_isNew'] * allowable filters and sort refinements. */ const ProductList = (props) => { + console.log("(JEREMY) in ProductList") // Using destructuring to omit properties; we must rename `isLoading` because we use a different // `isLoading` later in this function. // eslint-disable-next-line react/prop-types, @typescript-eslint/no-unused-vars @@ -399,6 +400,8 @@ const ProductList = (props) => { } }, [productSearchResult]) + console.log("(JEREMY) productSearchResult: ", productSearchResult) + return ( Date: Tue, 28 Jan 2025 12:21:30 -0800 Subject: [PATCH 10/19] Revert "some logging for dev" This reverts commit 4f7b9d870bcc50135e55ae3e2020920bf13f4472. --- .../template-retail-react-app/app/pages/product-list/index.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/template-retail-react-app/app/pages/product-list/index.jsx b/packages/template-retail-react-app/app/pages/product-list/index.jsx index 3ba2c95c0f..d96422c7c7 100644 --- a/packages/template-retail-react-app/app/pages/product-list/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-list/index.jsx @@ -105,7 +105,6 @@ const REFINEMENT_DISALLOW_LIST = ['c_isNew'] * allowable filters and sort refinements. */ const ProductList = (props) => { - console.log("(JEREMY) in ProductList") // Using destructuring to omit properties; we must rename `isLoading` because we use a different // `isLoading` later in this function. // eslint-disable-next-line react/prop-types, @typescript-eslint/no-unused-vars @@ -400,8 +399,6 @@ const ProductList = (props) => { } }, [productSearchResult]) - console.log("(JEREMY) productSearchResult: ", productSearchResult) - return ( Date: Tue, 28 Jan 2025 16:11:02 -0800 Subject: [PATCH 11/19] Fix wishlist tests --- e2e/config.js | 2 +- e2e/scripts/pageHelpers.js | 17 +++++++--------- e2e/tests/desktop/registered-shopper.spec.js | 2 +- e2e/tests/mobile/registered-shopper.spec.js | 2 +- .../config/default.js | 20 +++++++++---------- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/e2e/config.js b/e2e/config.js index 363012cf3a..9a9b82d8b3 100644 --- a/e2e/config.js +++ b/e2e/config.js @@ -7,7 +7,7 @@ module.exports = { RETAIL_APP_HOME: - process.env.RETAIL_APP_HOME || + process.env.RETAIL_APP_HOME || "localhost:3000" || "https://scaffold-pwa-e2e-tests-pwa-kit.mobify-storefront.com", GENERATED_PROJECTS_DIR: "../generated-projects", GENERATE_PROJECTS: ["retail-app-demo", "retail-app-ext", "retail-app-no-ext"], diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index 72eb795055..8bb76d389b 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -184,9 +184,10 @@ export const registerShopper = async ({page, userCredentials, isMobile = false}) .locator("input#password") .fill(userCredentials.password); + const tokenResponsePromise=page.waitForResponse('**/shopper/auth/v1/organizations/**/oauth2/token') await page.getByRole("button", { name: /Create Account/i }).click(); - - await page.waitForLoadState(); + await tokenResponsePromise; + expect((await tokenResponsePromise).status()).toBe(200); await expect( page.getByRole("heading", { name: /Account Details/i }) @@ -268,15 +269,11 @@ export const loginShopper = async ({page, userCredentials}) => { await page .locator("input#password") .fill(userCredentials.password); + + const tokenResponsePromise=page.waitForResponse('**/shopper/auth/v1/organizations/**/oauth2/token') await page.getByRole("button", { name: /Sign In/i }).click(); - - await page.waitForLoadState(); - - // redirected to Account Details page after logging in - await expect( - page.getByRole("heading", { name: /Account Details/i }) - ).toBeVisible({ timeout: 2000 }); - return true; + await tokenResponsePromise; + return await tokenResponsePromise.status() === 200; } catch { return false; } diff --git a/e2e/tests/desktop/registered-shopper.spec.js b/e2e/tests/desktop/registered-shopper.spec.js index c1c34afa17..a0433aebce 100644 --- a/e2e/tests/desktop/registered-shopper.spec.js +++ b/e2e/tests/desktop/registered-shopper.spec.js @@ -148,7 +148,7 @@ test("Registered shopper can add item to wishlist", async ({ page }) => { }) if(!isLoggedIn) { - await registerShopper({page, userCredentials: REGISTERED_USER_CREDENTIALS}) + await registerShopper({page, userCredentials: generateUserCredentials()}) } // Navigate to PDP diff --git a/e2e/tests/mobile/registered-shopper.spec.js b/e2e/tests/mobile/registered-shopper.spec.js index e751a85ea7..19c134a60f 100644 --- a/e2e/tests/mobile/registered-shopper.spec.js +++ b/e2e/tests/mobile/registered-shopper.spec.js @@ -153,7 +153,7 @@ test("Registered shopper can add item to wishlist", async ({ page }) => { if(!isLoggedIn) { await registerShopper({ page, - userCredentials: REGISTERED_USER_CREDENTIALS, + userCredentials: generateUserCredentials(), isMobile: true }) } diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index 8fb5673dd2..e6d4d94a14 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -15,19 +15,19 @@ module.exports = { showDefaults: true, interpretPlusSignAsSpace: false }, - defaultSite: 'RefArchGlobal', - siteAliases: { - RefArch: 'us', - RefArchGlobal: 'global' - }, + defaultSite: 'RefArch', + // siteAliases: { + // RefArch: 'us', + // RefArchGlobal: 'global' + // }, sites, commerceAPI: { proxyPath: `/mobify/proxy/api`, parameters: { - clientId: 'c9c45bfd-0ed3-4aa2-9971-40f88962b836', - organizationId: 'f_ecom_zzrf_001', - shortCode: '8o7m175y', - siteId: 'RefArchGlobal' + clientId: '987fc116-d30c-4537-93cb-c2bd433c3b5a', + organizationId: 'f_ecom_zzrf_002', + shortCode: 'kv7kzm78', + siteId: 'RefArch' } }, einsteinAPI: { @@ -57,7 +57,7 @@ module.exports = { path: 'api' }, { - host: 'zzrf-001.dx.commercecloud.salesforce.com', + host: 'zzrf-002.dx.commercecloud.salesforce.com', path: 'ocapi' } ] From 4ccfbc946846de620fdcae94378d31bdc4759b27 Mon Sep 17 00:00:00 2001 From: Jainam Tushar Sheth Date: Tue, 28 Jan 2025 16:13:18 -0800 Subject: [PATCH 12/19] Remove localhost from config --- e2e/config.js | 2 +- e2e/tests/desktop/registered-shopper.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/config.js b/e2e/config.js index 9a9b82d8b3..363012cf3a 100644 --- a/e2e/config.js +++ b/e2e/config.js @@ -7,7 +7,7 @@ module.exports = { RETAIL_APP_HOME: - process.env.RETAIL_APP_HOME || "localhost:3000" || + process.env.RETAIL_APP_HOME || "https://scaffold-pwa-e2e-tests-pwa-kit.mobify-storefront.com", GENERATED_PROJECTS_DIR: "../generated-projects", GENERATE_PROJECTS: ["retail-app-demo", "retail-app-ext", "retail-app-no-ext"], diff --git a/e2e/tests/desktop/registered-shopper.spec.js b/e2e/tests/desktop/registered-shopper.spec.js index a0433aebce..bc6aa7fada 100644 --- a/e2e/tests/desktop/registered-shopper.spec.js +++ b/e2e/tests/desktop/registered-shopper.spec.js @@ -148,7 +148,7 @@ test("Registered shopper can add item to wishlist", async ({ page }) => { }) if(!isLoggedIn) { - await registerShopper({page, userCredentials: generateUserCredentials()}) + await registerShopper({page, userCredentials: generateUserCredentials() }) } // Navigate to PDP From 65b70db6affc5627d761698fabea4e441ddfa21d Mon Sep 17 00:00:00 2001 From: Jainam Tushar Sheth Date: Wed, 29 Jan 2025 10:15:07 -0800 Subject: [PATCH 13/19] Revert PWA Kit config --- .../config/default.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index e6d4d94a14..502ba42e62 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -15,19 +15,19 @@ module.exports = { showDefaults: true, interpretPlusSignAsSpace: false }, - defaultSite: 'RefArch', - // siteAliases: { - // RefArch: 'us', - // RefArchGlobal: 'global' - // }, + defaultSite: 'RefArchGlobal', + siteAliases: { + RefArch: 'us', + RefArchGlobal: 'global' + }, sites, commerceAPI: { proxyPath: `/mobify/proxy/api`, parameters: { - clientId: '987fc116-d30c-4537-93cb-c2bd433c3b5a', - organizationId: 'f_ecom_zzrf_002', - shortCode: 'kv7kzm78', - siteId: 'RefArch' + clientId: 'c9c45bfd-0ed3-4aa2-9971-40f88962b836', + organizationId: 'f_ecom_zzrf_001', + shortCode: '8o7m175y', + siteId: 'RefArchGlobal' } }, einsteinAPI: { @@ -53,11 +53,11 @@ module.exports = { ssrFunctionNodeVersion: '20.x', proxyConfigs: [ { - host: 'kv7kzm78.api.commercecloud.salesforce.com', + host: '8o7m175y.api.commercecloud.salesforce.com', path: 'api' }, { - host: 'zzrf-002.dx.commercecloud.salesforce.com', + host: 'zzrf-001.dx.commercecloud.salesforce.com', path: 'ocapi' } ] From 736303febf65652ec8193000a1b386cb804c2f10 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Wed, 29 Jan 2025 10:44:42 -0800 Subject: [PATCH 14/19] try different shortcode --- packages/template-retail-react-app/config/default.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index 502ba42e62..1677fe5929 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -26,7 +26,7 @@ module.exports = { parameters: { clientId: 'c9c45bfd-0ed3-4aa2-9971-40f88962b836', organizationId: 'f_ecom_zzrf_001', - shortCode: '8o7m175y', + shortCode: 'kv7kzm78', siteId: 'RefArchGlobal' } }, @@ -53,7 +53,7 @@ module.exports = { ssrFunctionNodeVersion: '20.x', proxyConfigs: [ { - host: '8o7m175y.api.commercecloud.salesforce.com', + host: 'kv7kzm78.api.commercecloud.salesforce.com', path: 'api' }, { From 359d1d3fcdb5fc868d7ded4761bb20603452fbad Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Thu, 30 Jan 2025 09:54:19 -0800 Subject: [PATCH 15/19] Revert "try different shortcode" This reverts commit 736303febf65652ec8193000a1b386cb804c2f10. --- packages/template-retail-react-app/config/default.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index 1677fe5929..502ba42e62 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -26,7 +26,7 @@ module.exports = { parameters: { clientId: 'c9c45bfd-0ed3-4aa2-9971-40f88962b836', organizationId: 'f_ecom_zzrf_001', - shortCode: 'kv7kzm78', + shortCode: '8o7m175y', siteId: 'RefArchGlobal' } }, @@ -53,7 +53,7 @@ module.exports = { ssrFunctionNodeVersion: '20.x', proxyConfigs: [ { - host: 'kv7kzm78.api.commercecloud.salesforce.com', + host: '8o7m175y.api.commercecloud.salesforce.com', path: 'api' }, { From 953d25f6480ba7854b5ccdfdc05ef2543411627a Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Thu, 30 Jan 2025 09:54:48 -0800 Subject: [PATCH 16/19] restore shortcode in proxy config --- packages/template-retail-react-app/config/default.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index 502ba42e62..8fb5673dd2 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -53,7 +53,7 @@ module.exports = { ssrFunctionNodeVersion: '20.x', proxyConfigs: [ { - host: '8o7m175y.api.commercecloud.salesforce.com', + host: 'kv7kzm78.api.commercecloud.salesforce.com', path: 'api' }, { From c006b9e7f970e0981b3c9735b7dd34ac90c49206 Mon Sep 17 00:00:00 2001 From: Jang ho Jung Date: Thu, 30 Jan 2025 11:13:42 -0800 Subject: [PATCH 17/19] A comment --- e2e/scripts/pageHelpers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/e2e/scripts/pageHelpers.js b/e2e/scripts/pageHelpers.js index 8bb76d389b..ba6e01c92b 100644 --- a/e2e/scripts/pageHelpers.js +++ b/e2e/scripts/pageHelpers.js @@ -183,7 +183,9 @@ export const registerShopper = async ({page, userCredentials, isMobile = false}) await page .locator("input#password") .fill(userCredentials.password); - + + // Best Practice: await the network call and assert on the network response rather than waiting for pageLoadState() + // to avoid race conditions from lock in pageLoadState being released before network call resolves const tokenResponsePromise=page.waitForResponse('**/shopper/auth/v1/organizations/**/oauth2/token') await page.getByRole("button", { name: /Create Account/i }).click(); await tokenResponsePromise; From 07784388d4daabef081601840f1a20d4ff69e808 Mon Sep 17 00:00:00 2001 From: Joel Uong <88680517+joeluong-sfcc@users.noreply.github.com> Date: Thu, 30 Jan 2025 17:55:01 -0500 Subject: [PATCH 18/19] Support Node 22 (@W-17518271@) (#2218) * bump node/npm version * update e2e workflow and CHANGELOG * exclude node 18 npm 11 from ci * update ssrFunctionNodeVersion * update MRT node in CI * update package-lock and babel config * upgrade upload-artifact from v3 to v4 * add name to upload artifact * revert back to v4 * add dynamic naming for upload-artifact workflow * revert removal of node 16 in package.json * update e2e ci * update test.yml * update package-lock.json * exclude 16/11 --------- Signed-off-by: Joel Uong <88680517+joeluong-sfcc@users.noreply.github.com> --- .github/workflows/e2e.yml | 48 ++++++++++++------- .github/workflows/test.yml | 35 ++++++++------ package-lock.json | 4 +- package.json | 4 +- packages/commerce-sdk-react/CHANGELOG.md | 1 + packages/commerce-sdk-react/package-lock.json | 4 +- packages/commerce-sdk-react/package.json | 4 +- .../configs/babel.config.js | 2 +- packages/internal-lib-build/package-lock.json | 4 +- packages/internal-lib-build/package.json | 4 +- packages/pwa-kit-create-app/CHANGELOG.md | 1 + .../assets/bootstrap/js/config/default.js.hbs | 2 +- .../assets/bootstrap/js/package.json.hbs | 4 +- .../retail-react-app/config/default.js.hbs | 2 +- packages/pwa-kit-create-app/package-lock.json | 4 +- packages/pwa-kit-create-app/package.json | 4 +- packages/pwa-kit-dev/CHANGELOG.md | 1 + packages/pwa-kit-dev/package-lock.json | 4 +- packages/pwa-kit-dev/package.json | 4 +- .../src/configs/babel/babel-config.js | 2 +- .../src/configs/webpack/test/package.json | 4 +- packages/pwa-kit-react-sdk/CHANGELOG.md | 1 + packages/pwa-kit-react-sdk/package-lock.json | 4 +- packages/pwa-kit-react-sdk/package.json | 4 +- packages/pwa-kit-react-sdk/setup-jest.js | 2 +- packages/pwa-kit-runtime/CHANGELOG.md | 1 + packages/pwa-kit-runtime/package-lock.json | 6 +-- packages/pwa-kit-runtime/package.json | 4 +- .../template-express-minimal/package.json | 2 +- .../package-lock.json | 4 +- .../template-mrt-reference-app/package.json | 6 +-- .../template-retail-react-app/CHANGELOG.md | 2 + .../config/default.js | 2 +- .../config/mocks/default.js | 2 +- .../package-lock.json | 8 ++-- .../template-retail-react-app/package.json | 4 +- .../package-lock.json | 4 +- .../template-typescript-minimal/package.json | 6 +-- .../test-commerce-sdk-react/package-lock.json | 4 +- packages/test-commerce-sdk-react/package.json | 6 +-- 40 files changed, 122 insertions(+), 92 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 00f8b4a43c..4d33ace8de 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -11,18 +11,22 @@ jobs: fail-fast: false matrix: # Run all matrix env at once because we will not deploy demo app to MRT. - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: ubuntu-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} steps: - name: Checkout uses: actions/checkout@v4 @@ -58,18 +62,22 @@ jobs: # Run one matrix env at a time because we need to deploy each app to MRT and run e2e tests there max-parallel: 1 matrix: - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: ubuntu-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} steps: - name: Checkout uses: actions/checkout@v4 @@ -155,18 +163,22 @@ jobs: # Run one matrix env at a time because we need to deploy each app to MRT and run e2e tests there max-parallel: 1 matrix: - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: ubuntu-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} steps: - name: Checkout uses: actions/checkout@v4 @@ -251,18 +263,22 @@ jobs: max-parallel: 1 matrix: # Run all matrix env at once because we will not deploy demo app to MRT. - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: ubuntu-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a0424345d3..568e6ad3f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,21 +44,24 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: ubuntu-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) - # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} # The current recommended version for Managed Runtime: # https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/upgrade-node-version.html - IS_MRT_NODE: ${{ matrix.node == 20 && matrix.npm == 10 }} + IS_MRT_NODE: ${{ matrix.node == 22 && matrix.npm == 10 }} steps: - name: Checkout uses: actions/checkout@v3 @@ -141,21 +144,25 @@ jobs: strategy: fail-fast: false matrix: - node: [16, 18, 20] - npm: [8, 9, 10] - exclude: # node 16 is not compatible with npm 10 + node: [16, 18, 20, 22] + npm: [8, 9, 10, 11] + exclude: # node 16 with npm 10/11 and node 18 with npm 11 are not compatible - node: 16 npm: 10 + - node: 16 + npm: 11 + - node: 18 + npm: 11 runs-on: windows-latest env: # The "default" npm is the one that ships with a given version of node. # For more: https://nodejs.org/en/download/releases/ # (We also use this env var for making sure a step runs once for the current node version) # Note: For node 18, the default was npm 9 until v18.19.0, when it became npm 10 - IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) }} + IS_DEFAULT_NPM: ${{ (matrix.node == 16 && matrix.npm == 8) || (matrix.node == 18 && matrix.npm == 10) || (matrix.node == 20 && matrix.npm == 10) || (matrix.node == 22 && matrix.npm == 10) }} # The current recommended version for Managed Runtime: # https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/upgrade-node-version.html - IS_MRT_NODE: ${{ matrix.node == 20 && matrix.npm == 10 }} + IS_MRT_NODE: ${{ matrix.node == 22 && matrix.npm == 10 }} steps: - name: Checkout uses: actions/checkout@v3 @@ -196,7 +203,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 - name: Setup Ubuntu Machine uses: "./.github/actions/setup_ubuntu" @@ -295,7 +302,7 @@ jobs: - name: Setup Node uses: actions/setup-node@v3 with: - node-version: 20 + node-version: 22 - name: Setup Windows Machine uses: "./.github/actions/setup_windows" @@ -339,7 +346,7 @@ jobs: strategy: fail-fast: false matrix: - node: [20] # Should match node version supported by MRT. + node: [22] # Should match node version supported by MRT. runs-on: ubuntu-latest steps: - name: Checkout diff --git a/package-lock.json b/package-lock.json index 4a3c2a6109..a3a7b097f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,8 @@ "syncpack": "^10.1.0" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@babel/code-frame": { diff --git a/package.json b/package.json index 27b5eb4be3..5b7213f8a6 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "syncpack": "^10.1.0" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "dependencies": { "node-fetch": "^2.6.9" diff --git a/packages/commerce-sdk-react/CHANGELOG.md b/packages/commerce-sdk-react/CHANGELOG.md index e510bd32f8..042ffc0356 100644 --- a/packages/commerce-sdk-react/CHANGELOG.md +++ b/packages/commerce-sdk-react/CHANGELOG.md @@ -6,6 +6,7 @@ - Update CacheUpdateMatrix for mergeBasket mutation [#2138](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2092) - Clear auth state if session has been invalidated by a password change [#2092](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2092) - DNT interface improvement [#2203](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2203) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) ## v3.1.0 (Oct 28, 2024) diff --git a/packages/commerce-sdk-react/package-lock.json b/packages/commerce-sdk-react/package-lock.json index 87f68f39ae..85abe50081 100644 --- a/packages/commerce-sdk-react/package-lock.json +++ b/packages/commerce-sdk-react/package-lock.json @@ -42,8 +42,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "optionalDependencies": { "prop-types": "^15.8.1" diff --git a/packages/commerce-sdk-react/package.json b/packages/commerce-sdk-react/package.json index 670b7c9bb6..0da559b631 100644 --- a/packages/commerce-sdk-react/package.json +++ b/packages/commerce-sdk-react/package.json @@ -84,8 +84,8 @@ "react-router-dom": "^5.3.4" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "publishConfig": { "directory": "dist" diff --git a/packages/internal-lib-build/configs/babel.config.js b/packages/internal-lib-build/configs/babel.config.js index b3d0c99dc9..113d180a04 100644 --- a/packages/internal-lib-build/configs/babel.config.js +++ b/packages/internal-lib-build/configs/babel.config.js @@ -10,7 +10,7 @@ const config = { require('@babel/preset-env'), { targets: { - node: 18 + node: 22 } } ], diff --git a/packages/internal-lib-build/package-lock.json b/packages/internal-lib-build/package-lock.json index 76e1cd43b8..2a08c6e0c1 100644 --- a/packages/internal-lib-build/package-lock.json +++ b/packages/internal-lib-build/package-lock.json @@ -50,8 +50,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "peerDependencies": { "typescript": "4.9.5" diff --git a/packages/internal-lib-build/package.json b/packages/internal-lib-build/package.json index 2af7e4f35c..66f26c33df 100644 --- a/packages/internal-lib-build/package.json +++ b/packages/internal-lib-build/package.json @@ -73,7 +73,7 @@ } }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } } diff --git a/packages/pwa-kit-create-app/CHANGELOG.md b/packages/pwa-kit-create-app/CHANGELOG.md index c975e71058..adc2b10977 100644 --- a/packages/pwa-kit-create-app/CHANGELOG.md +++ b/packages/pwa-kit-create-app/CHANGELOG.md @@ -1,4 +1,5 @@ ## v3.9.0-dev (Oct 29, 2024) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) ## v3.8.0 (Oct 28, 2024) diff --git a/packages/pwa-kit-create-app/assets/bootstrap/js/config/default.js.hbs b/packages/pwa-kit-create-app/assets/bootstrap/js/config/default.js.hbs index 2d2ed1bb25..74d2eaf3bb 100644 --- a/packages/pwa-kit-create-app/assets/bootstrap/js/config/default.js.hbs +++ b/packages/pwa-kit-create-app/assets/bootstrap/js/config/default.js.hbs @@ -66,7 +66,7 @@ module.exports = { ], // Additional parameters that configure Express app behavior. ssrParameters: { - ssrFunctionNodeVersion: '20.x', + ssrFunctionNodeVersion: '22.x', proxyConfigs: [ { host: '{{answers.project.commerce.shortCode}}.api.commercecloud.salesforce.com', diff --git a/packages/pwa-kit-create-app/assets/bootstrap/js/package.json.hbs b/packages/pwa-kit-create-app/assets/bootstrap/js/package.json.hbs index 016ac33bb4..796d3b65a8 100644 --- a/packages/pwa-kit-create-app/assets/bootstrap/js/package.json.hbs +++ b/packages/pwa-kit-create-app/assets/bootstrap/js/package.json.hbs @@ -3,8 +3,8 @@ "version": "0.0.1", "license": "See license in LICENSE", "engines": { - "node": "^18.0.0 || ^20.0.0", - "npm": "^9.0.0 || ^10.0.0" + "node": "^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^9.0.0 || ^10.0.0 || ^11.0.0" }, "ccExtensibility": { "extends": "{{preset.templateSource.id}}", diff --git a/packages/pwa-kit-create-app/assets/templates/@salesforce/retail-react-app/config/default.js.hbs b/packages/pwa-kit-create-app/assets/templates/@salesforce/retail-react-app/config/default.js.hbs index 0825bb91b5..ab7d0971a5 100644 --- a/packages/pwa-kit-create-app/assets/templates/@salesforce/retail-react-app/config/default.js.hbs +++ b/packages/pwa-kit-create-app/assets/templates/@salesforce/retail-react-app/config/default.js.hbs @@ -68,7 +68,7 @@ module.exports = { ], // Additional parameters that configure Express app behavior. ssrParameters: { - ssrFunctionNodeVersion: '20.x', + ssrFunctionNodeVersion: '22.x', proxyConfigs: [ { host: '{{answers.project.commerce.shortCode}}.api.commercecloud.salesforce.com', diff --git a/packages/pwa-kit-create-app/package-lock.json b/packages/pwa-kit-create-app/package-lock.json index cba5041081..1197d8146c 100644 --- a/packages/pwa-kit-create-app/package-lock.json +++ b/packages/pwa-kit-create-app/package-lock.json @@ -25,8 +25,8 @@ "verdaccio": "^5.22.1" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@babel/runtime": { diff --git a/packages/pwa-kit-create-app/package.json b/packages/pwa-kit-create-app/package.json index 738d10c2a0..7d566081b1 100644 --- a/packages/pwa-kit-create-app/package.json +++ b/packages/pwa-kit-create-app/package.json @@ -43,7 +43,7 @@ "verdaccio": "^5.22.1" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } } diff --git a/packages/pwa-kit-dev/CHANGELOG.md b/packages/pwa-kit-dev/CHANGELOG.md index 1503e9c384..71ba4a7766 100644 --- a/packages/pwa-kit-dev/CHANGELOG.md +++ b/packages/pwa-kit-dev/CHANGELOG.md @@ -1,4 +1,5 @@ ## v3.9.0-dev (Oct 29, 2024) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) ## v3.8.0 (Oct 28, 2024) diff --git a/packages/pwa-kit-dev/package-lock.json b/packages/pwa-kit-dev/package-lock.json index 487ca5ec03..dccfc09047 100644 --- a/packages/pwa-kit-dev/package-lock.json +++ b/packages/pwa-kit-dev/package-lock.json @@ -103,8 +103,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "peerDependencies": { "@loadable/component": "^5.15.3", diff --git a/packages/pwa-kit-dev/package.json b/packages/pwa-kit-dev/package.json index 9c78fa9cc4..215d1490a9 100644 --- a/packages/pwa-kit-dev/package.json +++ b/packages/pwa-kit-dev/package.json @@ -141,8 +141,8 @@ } }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "publishConfig": { "directory": "dist" diff --git a/packages/pwa-kit-dev/src/configs/babel/babel-config.js b/packages/pwa-kit-dev/src/configs/babel/babel-config.js index 3ffbc8efbf..05439dbeab 100644 --- a/packages/pwa-kit-dev/src/configs/babel/babel-config.js +++ b/packages/pwa-kit-dev/src/configs/babel/babel-config.js @@ -11,7 +11,7 @@ const config = { require('@babel/preset-env'), { targets: { - node: 18 + node: 22 } } ], diff --git a/packages/pwa-kit-dev/src/configs/webpack/test/package.json b/packages/pwa-kit-dev/src/configs/webpack/test/package.json index fa9b8c1041..a7ca9da5b3 100644 --- a/packages/pwa-kit-dev/src/configs/webpack/test/package.json +++ b/packages/pwa-kit-dev/src/configs/webpack/test/package.json @@ -3,8 +3,8 @@ "version": "2.8.0-dev", "license": "See license in LICENSE", "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "ccExtensibility": { "extends": "retail-react-app", diff --git a/packages/pwa-kit-react-sdk/CHANGELOG.md b/packages/pwa-kit-react-sdk/CHANGELOG.md index edd353a41d..8b0f042014 100644 --- a/packages/pwa-kit-react-sdk/CHANGELOG.md +++ b/packages/pwa-kit-react-sdk/CHANGELOG.md @@ -1,6 +1,7 @@ ## v3.9.0-dev (Oct 29, 2024) - Fix the performance logging util to not round duration. [#2199](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2199) - Add RedirectWithStatus component, allowing finer grained control of rediriects and their status code [#2173](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2173) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) ## v3.8.0 (Oct 28, 2024) - [Server Affinity] - Attach dwsid to SCAPI request headers [#2090](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2090) diff --git a/packages/pwa-kit-react-sdk/package-lock.json b/packages/pwa-kit-react-sdk/package-lock.json index b772c3b140..f3632addd2 100644 --- a/packages/pwa-kit-react-sdk/package-lock.json +++ b/packages/pwa-kit-react-sdk/package-lock.json @@ -38,8 +38,8 @@ "supertest": "^4.0.2" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "peerDependencies": { "@loadable/component": "^5.15.3", diff --git a/packages/pwa-kit-react-sdk/package.json b/packages/pwa-kit-react-sdk/package.json index ce0331117c..d3f8d96cfd 100644 --- a/packages/pwa-kit-react-sdk/package.json +++ b/packages/pwa-kit-react-sdk/package.json @@ -73,8 +73,8 @@ "react-router-dom": "^5.3.4" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "publishConfig": { "directory": "dist" diff --git a/packages/pwa-kit-react-sdk/setup-jest.js b/packages/pwa-kit-react-sdk/setup-jest.js index 325513050b..2d94d3e2b1 100644 --- a/packages/pwa-kit-react-sdk/setup-jest.js +++ b/packages/pwa-kit-react-sdk/setup-jest.js @@ -25,7 +25,7 @@ jest.mock('@salesforce/pwa-kit-runtime/utils/ssr-config', () => { '**/*.json' ], ssrParameters: { - ssrFunctionNodeVersion: '20.x', + ssrFunctionNodeVersion: '22.x', proxyConfigs: [ { host: 'kv7kzm78.api.commercecloud.salesforce.com', diff --git a/packages/pwa-kit-runtime/CHANGELOG.md b/packages/pwa-kit-runtime/CHANGELOG.md index c80ae51b7f..c1add78088 100644 --- a/packages/pwa-kit-runtime/CHANGELOG.md +++ b/packages/pwa-kit-runtime/CHANGELOG.md @@ -1,5 +1,6 @@ ## v3.9.0-dev (Oct 29, 2024) - Fix stale service worker file that could cause requests to still use old Content-Security-Policy [#2191](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2191) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) ## v3.8.0 (Oct 28, 2024) - Add proxy handling for trusted agent on behalf of (TAOB) requests [#2077](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2077) diff --git a/packages/pwa-kit-runtime/package-lock.json b/packages/pwa-kit-runtime/package-lock.json index 345abc747e..6acf4261d1 100644 --- a/packages/pwa-kit-runtime/package-lock.json +++ b/packages/pwa-kit-runtime/package-lock.json @@ -35,11 +35,11 @@ "supertest": "^4.0.2" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "peerDependencies": { - "@salesforce/pwa-kit-dev": "3.7.0" + "@salesforce/pwa-kit-dev": "3.9.0-dev" }, "peerDependenciesMeta": { "@salesforce/pwa-kit-dev": { diff --git a/packages/pwa-kit-runtime/package.json b/packages/pwa-kit-runtime/package.json index 3428731935..d4e6134bf5 100644 --- a/packages/pwa-kit-runtime/package.json +++ b/packages/pwa-kit-runtime/package.json @@ -66,8 +66,8 @@ } }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "publishConfig": { "directory": "dist" diff --git a/packages/template-express-minimal/package.json b/packages/template-express-minimal/package.json index faeb38f810..0e48647012 100644 --- a/packages/template-express-minimal/package.json +++ b/packages/template-express-minimal/package.json @@ -22,7 +22,7 @@ "mobify": { "ssrEnabled": true, "ssrParameters": { - "ssrFunctionNodeVersion": "20.x" + "ssrFunctionNodeVersion": "22.x" }, "ssrOnly": [ "ssr.js", diff --git a/packages/template-mrt-reference-app/package-lock.json b/packages/template-mrt-reference-app/package-lock.json index b35e69fa75..149e6a4d8e 100644 --- a/packages/template-mrt-reference-app/package-lock.json +++ b/packages/template-mrt-reference-app/package-lock.json @@ -22,8 +22,8 @@ "supertest": "^4.0.2" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@aws-crypto/crc32": { diff --git a/packages/template-mrt-reference-app/package.json b/packages/template-mrt-reference-app/package.json index 489c6f7955..f2121266c1 100644 --- a/packages/template-mrt-reference-app/package.json +++ b/packages/template-mrt-reference-app/package.json @@ -25,13 +25,13 @@ "supertest": "^4.0.2" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "mobify": { "ssrEnabled": true, "ssrParameters": { - "ssrFunctionNodeVersion": "20.x", + "ssrFunctionNodeVersion": "22.x", "proxyConfigs": [ { "host": "httpbin.org", diff --git a/packages/template-retail-react-app/CHANGELOG.md b/packages/template-retail-react-app/CHANGELOG.md index d923697c7f..08c55dc7fc 100644 --- a/packages/template-retail-react-app/CHANGELOG.md +++ b/packages/template-retail-react-app/CHANGELOG.md @@ -10,6 +10,8 @@ - [BUG] Fixed "getCheckboxProps is not a function" when rendering checkout page in generated app.[#2140](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2140) - Replace transfer basket call with merge basket on checkout [#2138](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2138) - [BUG] Fix images being fetced multiple times on Safari [#2223](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2223) +- Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) + ### Accessibility Improvements - [a11y] Fix LinkList component to follow a11y practise [#2098])(https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2098) diff --git a/packages/template-retail-react-app/config/default.js b/packages/template-retail-react-app/config/default.js index 8fb5673dd2..e39c9e2a19 100644 --- a/packages/template-retail-react-app/config/default.js +++ b/packages/template-retail-react-app/config/default.js @@ -50,7 +50,7 @@ module.exports = { '**/*.json' ], ssrParameters: { - ssrFunctionNodeVersion: '20.x', + ssrFunctionNodeVersion: '22.x', proxyConfigs: [ { host: 'kv7kzm78.api.commercecloud.salesforce.com', diff --git a/packages/template-retail-react-app/config/mocks/default.js b/packages/template-retail-react-app/config/mocks/default.js index e204d2f10a..032d1c4d99 100644 --- a/packages/template-retail-react-app/config/mocks/default.js +++ b/packages/template-retail-react-app/config/mocks/default.js @@ -107,7 +107,7 @@ module.exports = { ], // Additional parameters that configure Express app behavior. ssrParameters: { - ssrFunctionNodeVersion: '20.x', + ssrFunctionNodeVersion: '22.x', proxyConfigs: [ { host: 'localhost:8888', diff --git a/packages/template-retail-react-app/package-lock.json b/packages/template-retail-react-app/package-lock.json index c540ff55b0..7bca58f546 100644 --- a/packages/template-retail-react-app/package-lock.json +++ b/packages/template-retail-react-app/package-lock.json @@ -1,12 +1,12 @@ { "name": "@salesforce/retail-react-app", - "version": "5.1.0-dev", + "version": "6.0.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@salesforce/retail-react-app", - "version": "5.1.0-dev", + "version": "6.0.0-dev", "license": "See license in LICENSE", "dependencies": { "@chakra-ui/icons": "^2.0.19", @@ -53,8 +53,8 @@ "react-router-dom": "^5.3.4" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@adobe/css-tools": { diff --git a/packages/template-retail-react-app/package.json b/packages/template-retail-react-app/package.json index cdebcc0a98..fb76848fc1 100644 --- a/packages/template-retail-react-app/package.json +++ b/packages/template-retail-react-app/package.json @@ -86,8 +86,8 @@ "cross-env": "^5.2.1" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "bundlesize": [ { diff --git a/packages/template-typescript-minimal/package-lock.json b/packages/template-typescript-minimal/package-lock.json index 6ed08729a1..57bf8c3354 100644 --- a/packages/template-typescript-minimal/package-lock.json +++ b/packages/template-typescript-minimal/package-lock.json @@ -20,8 +20,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@babel/runtime": { diff --git a/packages/template-typescript-minimal/package.json b/packages/template-typescript-minimal/package.json index 8be41feef4..d4e104180f 100644 --- a/packages/template-typescript-minimal/package.json +++ b/packages/template-typescript-minimal/package.json @@ -32,8 +32,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "mobify": { "ssrEnabled": true, @@ -50,7 +50,7 @@ "**/*.json" ], "ssrParameters": { - "ssrFunctionNodeVersion": "20.x", + "ssrFunctionNodeVersion": "22.x", "proxyConfigs": [ { "host": "kv7kzm78.api.commercecloud.salesforce.com", diff --git a/packages/test-commerce-sdk-react/package-lock.json b/packages/test-commerce-sdk-react/package-lock.json index 7cdeca30f1..979fcde646 100644 --- a/packages/test-commerce-sdk-react/package-lock.json +++ b/packages/test-commerce-sdk-react/package-lock.json @@ -22,8 +22,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@babel/runtime": { diff --git a/packages/test-commerce-sdk-react/package.json b/packages/test-commerce-sdk-react/package.json index ef33b8ac0c..4c1ae099a7 100644 --- a/packages/test-commerce-sdk-react/package.json +++ b/packages/test-commerce-sdk-react/package.json @@ -36,8 +36,8 @@ "typescript": "4.9.5" }, "engines": { - "node": "^16.11.0 || ^18.0.0 || ^20.0.0", - "npm": "^8.0.0 || ^9.0.0 || ^10.0.0" + "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0", + "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" }, "mobify": { "ssrEnabled": true, @@ -54,7 +54,7 @@ "**/*.json" ], "ssrParameters": { - "ssrFunctionNodeVersion": "20.x", + "ssrFunctionNodeVersion": "22.x", "proxyConfigs": [ { "host": "kv7kzm78.api.commercecloud.salesforce.com", From 44672686aa9fe3d0382f1f9dd5e118d18559c3bf Mon Sep 17 00:00:00 2001 From: vcua-mobify <47404250+vcua-mobify@users.noreply.github.com> Date: Tue, 4 Feb 2025 12:38:32 -0800 Subject: [PATCH 19/19] @W-17643479@ Add page meta data to search results and product pages (#2232) * Add page meta data to search results and product pages * Changelog * Apply suggestions --------- Signed-off-by: vcua-mobify <47404250+vcua-mobify@users.noreply.github.com> --- packages/template-retail-react-app/CHANGELOG.md | 3 ++- .../app/pages/product-detail/index.jsx | 13 +++++++++++-- .../app/pages/product-list/index.jsx | 12 +++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/template-retail-react-app/CHANGELOG.md b/packages/template-retail-react-app/CHANGELOG.md index 08c55dc7fc..5b0c45c5e7 100644 --- a/packages/template-retail-react-app/CHANGELOG.md +++ b/packages/template-retail-react-app/CHANGELOG.md @@ -11,7 +11,8 @@ - Replace transfer basket call with merge basket on checkout [#2138](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2138) - [BUG] Fix images being fetced multiple times on Safari [#2223](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2223) - Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218) - +tags +- PDP / PLP: Add page meta data tags that have been defined in BM [#2232](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2232) ### Accessibility Improvements - [a11y] Fix LinkList component to follow a11y practise [#2098])(https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2098) diff --git a/packages/template-retail-react-app/app/pages/product-detail/index.jsx b/packages/template-retail-react-app/app/pages/product-detail/index.jsx index ea7c8be085..51533402dc 100644 --- a/packages/template-retail-react-app/app/pages/product-detail/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-detail/index.jsx @@ -99,7 +99,8 @@ const ProductDetail = () => { 'prices', 'variations', 'set_products', - 'bundled_products' + 'bundled_products', + 'page_meta_tags' ], allImages: true } @@ -455,7 +456,15 @@ const ProductDetail = () => { > {product?.pageTitle} - + {product?.pageMetaTags?.length > 0 && + product.pageMetaTags.map(({id, value}) => ( + + ))} + {/* Fallback for description if not included in pageMetaTags */} + {!product?.pageMetaTags?.some((tag) => tag.id === 'description') && + product?.pageDescription && ( + + )} diff --git a/packages/template-retail-react-app/app/pages/product-list/index.jsx b/packages/template-retail-react-app/app/pages/product-list/index.jsx index d96422c7c7..52640fcb96 100644 --- a/packages/template-retail-react-app/app/pages/product-list/index.jsx +++ b/packages/template-retail-react-app/app/pages/product-list/index.jsx @@ -159,7 +159,14 @@ const ProductList = (props) => { perPricebook: true, allVariationProperties: true, allImages: true, - expand: ['promotions', 'variations', 'prices', 'images', 'custom_properties'], + expand: [ + 'promotions', + 'variations', + 'prices', + 'images', + 'page_meta_tags', + 'custom_properties' + ], refine: _refine } }, @@ -411,6 +418,9 @@ const ProductList = (props) => { {category?.pageTitle ?? searchQuery} + {productSearchResult?.pageMetaTags?.map(({id, value}) => { + return + })} {showNoResults ? (