From 85f7b1d78d801f81b58e8a9215d7c47ca5c81ca6 Mon Sep 17 00:00:00 2001 From: KeerthiSap Date: Mon, 11 Aug 2025 11:00:54 +0000 Subject: [PATCH 1/8] Update latest configurations for environment --- .env-cmdrc | 61 ++++++++++++------- .../root/config/default-checkout-config.ts | 2 +- projects/storefrontapp/src/app/app.module.ts | 12 +++- .../features/cdc/cdc-feature.module.ts | 9 ++- 4 files changed, 58 insertions(+), 26 deletions(-) diff --git a/.env-cmdrc b/.env-cmdrc index 393896d4bba..1aacb2df1c6 100644 --- a/.env-cmdrc +++ b/.env-cmdrc @@ -1,60 +1,77 @@ { "dev": { - "CX_BASE_URL": "https://api.c432wmya2v-teamspart3-s4-public.model-t.myhybris.cloud" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "s1": { - "CX_BASE_URL": "https://api.c432wmya2v-teamspart3-s1-public.model-t.myhybris.cloud" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "local": { - "CX_BASE_URL": "https://localhost:9002" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "local-http": { "CX_BASE_URL": "http://localhost:9002" }, "ci": { - "CX_BASE_URL": "https://api.c432wmya2v-teamspart3-s4-public.model-t.myhybris.cloud" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "ccv2": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-p1-public.model-t.myhybris.cloud" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "cds": { "CX_CDS": "true" }, "lighthouse": { - "CX_BASE_URL": "https://api.spartacus.rocks" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "cdc": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s1-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_CDC": "true" }, "digital-payments": { - "CX_BASE_URL": "https://backoffice.cp96avkh5f-sapcxteam1-d5-public.model-t.cc.commerce.ondemand.com", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_DIGITAL_PAYMENTS": "true" }, "epd-visualization": { "CX_EPD_VISUALIZATION": "true", - "CX_BASE_URL": "https://api.cp96avkh5f-integrati1-d1-public.model-t.cc.commerce.ondemand.com" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "opf": { "CX_OPF": "true", - "CX_BASE_URL": "https://api.cp96avkh5f-integrati2-d1-public.model-t.cc.commerce.ondemand.com" + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud" }, "cpq": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s1-public.model-t.myhybris.cloud/", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_B2B": "true", "CX_CPQ": "true" }, "segment-refs": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-p7-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_SEGMENT_REFS": "true" }, "b2c": { "CX_B2B": "false", - "CX_CDS": "false" - }, + "CX_CDS": "false", + "CX_DIGITAL_PAYMENTS": "true", + "CX_MY_ACCOUNT_V2": "true", + "CX_CDC": "true", + "CX_PDF_INVOICES": "true", + "CX_OPPS": "true", + "CX_CDP": "true", + "CX_ESTIMATED_DELIVERY_DATE": "true", + "CX_OMF": "true" + }, "b2b": { - "CX_B2B": "true" - }, + "CX_B2B": "true", + "CX_S4OM": "true", + "CX_REQUESTED_DELIVERY_DATE": "true", + "CX_MY_ACCOUNT_V2": "false", + "CX_CDC": "true", + "CX_PDF_INVOICES": "true", + "CX_OPPS": "true", + "CX_CDP": "true", + "CX_ESTIMATED_DELIVERY_DATE": "true", + "CX_S4_SERVICE": "true" + }, "s4om": { "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_B2B": "true", @@ -63,7 +80,7 @@ "CX_PDF_INVOICES": "true" }, "omf": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s9-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_OMF": "true" }, "requested-delivery-date": { @@ -71,26 +88,26 @@ "CX_REQUESTED_DELIVERY_DATE": "true" }, "estimated-delivery-date": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s5-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_ESTIMATED_DELIVERY_DATE": "true" }, "pdf-invoices": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s5-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_PDF_INVOICES": "true" }, "my-account-v2": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s5-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_PDF_INVOICES": "true", "CX_MY_ACCOUNT_V2": "true" }, "cdp": { "CX_CDP": "true", - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s5-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_PDF_INVOICES": "true", "CX_MY_ACCOUNT_V2": "true" }, "opps": { - "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s5-public.model-t.myhybris.cloud", + "CX_BASE_URL": "https://api.cg79x9wuu9-eccommerc1-s8-public.model-t.myhybris.cloud", "CX_OPPS": "true" }, "s4-service": { diff --git a/feature-libs/checkout/base/root/config/default-checkout-config.ts b/feature-libs/checkout/base/root/config/default-checkout-config.ts index d6357349f40..d94d5c25b0f 100644 --- a/feature-libs/checkout/base/root/config/default-checkout-config.ts +++ b/feature-libs/checkout/base/root/config/default-checkout-config.ts @@ -37,6 +37,6 @@ export const defaultCheckoutConfig: CheckoutConfig = { ], express: false, defaultDeliveryMode: [DeliveryModePreferences.FREE], - guest: false, + guest: true, }, }; diff --git a/projects/storefrontapp/src/app/app.module.ts b/projects/storefrontapp/src/app/app.module.ts index 4b4577429ef..44eee6e7162 100644 --- a/projects/storefrontapp/src/app/app.module.ts +++ b/projects/storefrontapp/src/app/app.module.ts @@ -30,7 +30,8 @@ import { translationsJa, translationsZh, } from '@spartacus/assets'; -import { +import { + CmsConfig, I18nConfig, OccConfig, RoutingConfig, @@ -107,6 +108,15 @@ if (!environment.production) { // without a key, for development or demo purposes. googleMaps: { apiKey: GOOGLE_MAPS_DEVELOPMENT_KEY_CONFIG }, }), + provideConfig({ + cmsComponents: { + ProductAddToCartComponent: { + data: { + inventoryDisplay: true, + }, + }, + }, + }), ], bootstrap: [StorefrontComponent], }) diff --git a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts index 5406be42430..7a68cbfdaf5 100644 --- a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts +++ b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts @@ -21,12 +21,17 @@ import { cdc: [ { baseSite: 'electronics-spa', - javascriptUrl: 'JS_SDK_URL_PLACEHOLDER', + javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', + sessionExpiration: 3600, + }, + { + baseSite: 'apparel-uk-spa', + javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', sessionExpiration: 3600, }, { baseSite: 'powertools-spa', - javascriptUrl: 'JS_SDK_URL_PLACEHOLDER', + javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3__pAj9UsaNXJAaDi-d8xvhzNBvGXDYx0GlTg1R9YQWVgTIQbdBZzR98_y-nFZWUNl', sessionExpiration: 3600, }, ], From dcd46121f5c00d3b132327d15d58f6bfd57ffaf5 Mon Sep 17 00:00:00 2001 From: Raja Singh Date: Mon, 11 Aug 2025 19:43:58 +0530 Subject: [PATCH 2/8] CXSPA-10739: redirecting fix and automobile ext --- package.json | 34 +++++++++---------- .../features/cdc/cdc-feature.module.ts | 5 +++ .../spartacus-b2c-configuration.module.ts | 2 ++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index b52a3e81026..7319beb6e3b 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "scripts": { "postinstall": "ts-node scripts/npm-postinstall/patch-@angular-build-19.0.4.ts", "build:analyze": "npm run build -- --stats-json && npx esbuild-visualizer --metadata ./dist/storefrontapp/stats.json", - "build": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build", + "build": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build", "watch": "npm run build -- --watch --configuration development", "build:core": "nx build core --configuration production", "build:storefrontlib": "nx build storefrontlib --configuration production", @@ -55,11 +55,11 @@ "build:schematics": "npm --prefix projects/schematics run build", "build:setup": "nx build setup --configuration production", "build:storefinder": "npm --prefix feature-libs/storefinder run build:schematics && nx build storefinder --configuration production", - "build:csr": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build-csr", - "build:ssr": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build:production", - "build:ssr:opf": "env-cmd --no-override -e opf,b2c,$SPA_ENV nx run storefrontapp:build:production", - "build:ssr:ci": "env-cmd -e ci,b2c,$SPA_ENV nx run storefrontapp:build:production", - "build:ssr:local-http-backend": "env-cmd -e local-http,b2c,$SPA_ENV nx run storefrontapp:build:production", + "build:csr": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build-csr", + "build:ssr": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build:production", + "build:ssr:opf": "env-cmd --no-override -e opf,b2c,b2b nx run storefrontapp:build:production", + "build:ssr:ci": "env-cmd -e ci,b2c,b2b nx run storefrontapp:build:production", + "build:ssr:local-http-backend": "env-cmd -e local-http,b2c,b2b nx run storefrontapp:build:production", "build:smartedit": "npm --prefix feature-libs/smartedit run build:schematics && nx build smartedit --configuration production", "build:tracking": "npm --prefix feature-libs/tracking run build:schematics && nx build tracking --configuration production", "build:quote": "npm --prefix feature-libs/quote run build:schematics && nx build quote --configuration production", @@ -132,16 +132,16 @@ "lint:styles": "stylelint \"{projects,feature-libs,integration-libs}/**/*.scss\"", "prettier": "prettier --config ./.prettierrc --list-different \"{projects,feature-libs,core-libs,integration-libs}/**/*{.ts,.js,.json,.scss,.html}\"", "prettier:fix": "prettier --config ./.prettierrc --list-different \"{projects,feature-libs,core-libs,integration-libs}/**/*{.ts,.js,.json,.scss,.html}\" --write", - "start": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:b2b": "env-cmd --no-override -e dev,b2b,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:ci": "env-cmd --no-override -e ci,b2c,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:ci:b2b": "env-cmd --no-override -e ci,b2b,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:opf": "env-cmd --no-override -e opf,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:opf:ssl": "env-cmd --no-override -e opf,$SPA_ENV nx serve storefrontapp --configuration=development --ssl", - "start:opf:b2b": "env-cmd --no-override -e b2b,opf,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:opf:b2b:ssl": "env-cmd --no-override -e b2b,opf,$SPA_ENV nx serve storefrontapp --configuration=development --ssl", - "start:punchout": "env-cmd --no-override -e punchout,$SPA_ENV nx serve storefrontapp --configuration=development", - "start:prod": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx serve storefrontapp --configuration=production", + "start": "env-cmd --no-override -e dev,b2c,b2b nx serve storefrontapp --configuration=development", + "start:b2b": "env-cmd --no-override -e dev,b2b,b2b nx serve storefrontapp --configuration=development", + "start:ci": "env-cmd --no-override -e ci,b2c,b2b nx serve storefrontapp --configuration=development", + "start:ci:b2b": "env-cmd --no-override -e ci,b2b,b2b nx serve storefrontapp --configuration=development", + "start:opf": "env-cmd --no-override -e opf,b2b nx serve storefrontapp --configuration=development", + "start:opf:ssl": "env-cmd --no-override -e opf,b2b nx serve storefrontapp --configuration=development --ssl", + "start:opf:b2b": "env-cmd --no-override -e b2b,opf,b2b nx serve storefrontapp --configuration=development", + "start:opf:b2b:ssl": "env-cmd --no-override -e b2b,opf,b2b nx serve storefrontapp --configuration=development --ssl", + "start:punchout": "env-cmd --no-override -e punchout,b2b nx serve storefrontapp --configuration=development", + "start:prod": "env-cmd --no-override -e dev,b2c,b2b nx serve storefrontapp --configuration=production", "start:pwa": " cd ./dist/storefrontapp/browser && http-server -p 4200 --silent --proxy http://localhost:4200?", "test": "nx test", "test:all-schematics": "set -e; npm --prefix ./projects/schematics test -- -u; for dir in feature-libs/* integration-libs/*; do (cd $dir && npm run test:schematics -- -u); done", @@ -156,7 +156,7 @@ "serve:ssr:dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 SSR_TIMEOUT=30000 node dist/storefrontapp/server/server.mjs", "test:ssr": "env-cmd -e dev nx test ssr-tests", "test:ssr:ci": "env-cmd -e ci nx test ssr-tests", - "prerender": "env-cmd --no-override -e dev,$SPA_ENV cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 nx run storefrontapp:prerender", + "prerender": "env-cmd --no-override -e dev,b2b cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 nx run storefrontapp:prerender", "publish:docs": "npx --yes gh-pages@^2.2.0 -d documentation -m \"Compodocs updates\"", "test:cds:lib": "nx test cds --code-coverage", "build:cds:ssr": "env-cmd --no-override -e dev,b2c,cds nx run storefrontapp:build:production" diff --git a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts index 7a68cbfdaf5..19e29acdb86 100644 --- a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts +++ b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts @@ -29,6 +29,11 @@ import { javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', sessionExpiration: 3600, }, + { + baseSite: 'automobile-spa', + javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', + sessionExpiration: 3600, + }, { baseSite: 'powertools-spa', javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3__pAj9UsaNXJAaDi-d8xvhzNBvGXDYx0GlTg1R9YQWVgTIQbdBZzR98_y-nFZWUNl', diff --git a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts index d6e9061a6ca..851e1d826e0 100644 --- a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts +++ b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts @@ -28,6 +28,8 @@ const defaultBaseSite = [ 'apparel-uk', 'apparel-uk-spa', 'apparel-uk-standalone', + 'automobile-spa', + 'automobile' ]; const baseSite = environment.epdVisualization ? ['electronics-epdvisualization-spa'].concat(defaultBaseSite) From 1c03cf47e1868db435fb500800056148e61323c5 Mon Sep 17 00:00:00 2001 From: KeerthiSap <81921271+KeerthiSap@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:10:08 +0200 Subject: [PATCH 3/8] Epic/jdk21auth (#20602) Co-authored-by: Melody-zhou-512 <140146828+Melody-zhou-512@users.noreply.github.com> Co-authored-by: Saptarshi Bose Co-authored-by: Hak Woo Kim Co-authored-by: Hakwoo Kim Co-authored-by: LarisaStar <61147963+Larisa-Staroverova@users.noreply.github.com> Co-authored-by: Sergiej Drozd Co-authored-by: Florent Letendre Co-authored-by: sdrozdsap <163305268+sdrozdsap@users.noreply.github.com> --- .../checkout-delivery-mode.component.html | 15 +- .../checkout-delivery-mode.component.spec.ts | 6 +- ...checkout-review-shipping.component.spec.ts | 2 +- .../checkout-review-shipping.component.ts | 9 +- .../quote-summary-actions.component.html | 2 +- .../quote-summary-actions.component.spec.ts | 16 ++ .../quote-summary-actions.component.ts | 13 +- feature-libs/quote/root/model/quote.model.ts | 1 + .../cds/src/profiletag/profile-tag.module.ts | 2 + .../cds/src/profiletag/providers/index.ts | 7 + .../providers/login-events.provider.spec.ts | 96 +++++++++++ .../providers/login-events.provider.ts | 48 ++++++ .../profile-tag-lifecycle.service.spec.ts | 157 ++++++++++++++++-- .../services/profile-tag-lifecycle.service.ts | 26 ++- .../cds/src/profiletag/tokens/index.ts | 7 + .../profiletag/tokens/login-events.token.ts | 22 +++ ...vice-checkout-delivery-mode.component.html | 28 +--- .../user-auth/facade/auth.service.spec.ts | 37 +++++ .../src/auth/user-auth/facade/auth.service.ts | 17 +- .../feature-toggles/config/feature-toggles.ts | 19 ++- .../checkout/checkout-as-guest.e2e.cy.ts | 58 ++++--- .../navigation-login-a11y.e2e.cy.ts | 7 +- .../cypress/helpers/checkout-as-guest.ts | 30 +++- .../cypress/helpers/checkout-variants.ts | 115 +++++++------ .../cypress/helpers/order-history.ts | 3 + .../cypress/support/utils/order-placed.ts | 6 +- .../spartacus/spartacus-features.module.ts | 2 +- run-spartacus-product-configurator-e2es.sh | 10 +- 28 files changed, 589 insertions(+), 172 deletions(-) create mode 100644 integration-libs/cds/src/profiletag/providers/index.ts create mode 100644 integration-libs/cds/src/profiletag/providers/login-events.provider.spec.ts create mode 100644 integration-libs/cds/src/profiletag/providers/login-events.provider.ts create mode 100644 integration-libs/cds/src/profiletag/tokens/index.ts create mode 100644 integration-libs/cds/src/profiletag/tokens/login-events.token.ts diff --git a/feature-libs/checkout/base/components/checkout-delivery-mode/checkout-delivery-mode.component.html b/feature-libs/checkout/base/components/checkout-delivery-mode/checkout-delivery-mode.component.html index 5bd9f5af1e6..c9d182c9758 100644 --- a/feature-libs/checkout/base/components/checkout-delivery-mode/checkout-delivery-mode.component.html +++ b/feature-libs/checkout/base/components/checkout-delivery-mode/checkout-delivery-mode.component.html @@ -1,17 +1,8 @@
- - - {{ 'checkoutMode.deliveryMethod' | cxTranslate }} - - - - - - {{ 'checkoutMode.deliveryOptions' | cxTranslate }} - - - + + {{ 'checkoutMode.deliveryOptions' | cxTranslate }} + { expect(component.areButtonsRendered([])).toBe(false); }); + it('should return false if allowed actions contains only DOWNLOAD_ACTION', () => { + const quoteWithDownloadACtion: Quote = { + ...mockQuote, + allowedActions: [ + { + type: QuoteActionType.DOWNLOAD_QUOTE_PROPOSAL_DOCUMENT, + isPrimary: false, + }, + ], + }; + mockQuoteDetails$.next(quoteWithDownloadACtion); + expect( + component.areButtonsRendered(quoteWithDownloadACtion.allowedActions) + ).toBe(false); + }); + it("should return 'true' if allowed actions is not empty", () => { expect(component.areButtonsRendered(mockQuote.allowedActions)).toBe(true); }); diff --git a/feature-libs/quote/components/summary/actions/quote-summary-actions.component.ts b/feature-libs/quote/components/summary/actions/quote-summary-actions.component.ts index 65fd9da7927..dfc958657ed 100644 --- a/feature-libs/quote/components/summary/actions/quote-summary-actions.component.ts +++ b/feature-libs/quote/components/summary/actions/quote-summary-actions.component.ts @@ -304,7 +304,7 @@ export class QuoteSummaryActionsComponent * @returns - if there are any action buttons, returns 'true', otherwise 'false'. */ areButtonsRendered(allowedActions: QuoteAction[]): boolean { - return allowedActions.length > 0; + return this.getFilteredActions(allowedActions).length > 0; } /** @@ -318,7 +318,10 @@ export class QuoteSummaryActionsComponent if (action.isPrimary) { return 'btn-primary'; } - if (allowedActions.length <= this.AMOUNT_OF_ACTION_BUTTONS) { + if ( + this.getFilteredActions(allowedActions).length <= + this.AMOUNT_OF_ACTION_BUTTONS + ) { return 'btn-secondary'; } return action.type === QuoteActionType.CANCEL @@ -401,4 +404,10 @@ export class QuoteSummaryActionsComponent }); return foundRole; } + + getFilteredActions(allowedActions: QuoteAction[]): QuoteAction[] { + return allowedActions.filter( + (action) => action.type !== 'DOWNLOAD_QUOTE_PROPOSAL_DOCUMENT' + ); + } } diff --git a/feature-libs/quote/root/model/quote.model.ts b/feature-libs/quote/root/model/quote.model.ts index 1f1496f110c..60cbd603310 100644 --- a/feature-libs/quote/root/model/quote.model.ts +++ b/feature-libs/quote/root/model/quote.model.ts @@ -67,6 +67,7 @@ export enum QuoteActionType { REJECT = 'REJECT', EXPIRED = 'EXPIRED', REQUOTE = 'REQUOTE', + DOWNLOAD_QUOTE_PROPOSAL_DOCUMENT = 'DOWNLOAD_QUOTE_PROPOSAL_DOCUMENT', } export enum QuoteState { diff --git a/integration-libs/cds/src/profiletag/profile-tag.module.ts b/integration-libs/cds/src/profiletag/profile-tag.module.ts index 6a667904879..836d4519354 100644 --- a/integration-libs/cds/src/profiletag/profile-tag.module.ts +++ b/integration-libs/cds/src/profiletag/profile-tag.module.ts @@ -11,6 +11,7 @@ import { OccBackendNotification } from './adapters/occ-backend-notification-adap import { ProfileTagCmsModule } from './cms-components/profile-tag-cms.module'; import { ConsentReferenceInterceptor } from './http-interceptors/consent-reference-interceptor'; import { DebugInterceptor } from './http-interceptors/debug-interceptor'; +import { provideLoginEventsTracking } from './providers'; @NgModule({ imports: [ProfileTagCmsModule], @@ -25,6 +26,7 @@ import { DebugInterceptor } from './http-interceptors/debug-interceptor'; provide: CdsBackendNotificationAdapter, useClass: OccBackendNotification, }, + ...provideLoginEventsTracking(), ], }) export class ProfileTagModule {} diff --git a/integration-libs/cds/src/profiletag/providers/index.ts b/integration-libs/cds/src/profiletag/providers/index.ts new file mode 100644 index 00000000000..440b614da8b --- /dev/null +++ b/integration-libs/cds/src/profiletag/providers/index.ts @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2025 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './login-events.provider'; diff --git a/integration-libs/cds/src/profiletag/providers/login-events.provider.spec.ts b/integration-libs/cds/src/profiletag/providers/login-events.provider.spec.ts new file mode 100644 index 00000000000..8bf41f269ff --- /dev/null +++ b/integration-libs/cds/src/profiletag/providers/login-events.provider.spec.ts @@ -0,0 +1,96 @@ +import { TestBed } from '@angular/core/testing'; +import { APP_INITIALIZER } from '@angular/core'; +import { ActionsSubject } from '@ngrx/store'; +import { AuthActions } from '@spartacus/core'; +import { provideLoginEventsTracking } from './login-events.provider'; +import { LOGIN_EVENTS, LoginEventEnvelope } from '../tokens/login-events.token'; +import { Observable, Subscription } from 'rxjs'; +import { take } from 'rxjs/operators'; + +describe('provideLoginEventsTracking', () => { + let actions$: ActionsSubject; + let loginEvents$: Observable; + let subscription: Subscription; + let mockTimestamp: number; + + beforeEach(() => { + mockTimestamp = 1234567890; + spyOn(Date, 'now').and.returnValue(mockTimestamp); + + TestBed.configureTestingModule({ + providers: [ + ...provideLoginEventsTracking(), + { provide: ActionsSubject, useFactory: () => new ActionsSubject() }, + ], + }); + + const initializers = TestBed.inject(APP_INITIALIZER); + if (initializers && Array.isArray(initializers)) { + TestBed.runInInjectionContext(() => { + initializers.forEach((fn) => fn()); + }); + } + + actions$ = TestBed.inject(ActionsSubject); + loginEvents$ = TestBed.inject(LOGIN_EVENTS); + subscription = new Subscription(); + }); + + afterEach(() => { + subscription.unsubscribe(); + TestBed.resetTestingModule(); + }); + + it('provides LOGIN_EVENTS observable', () => { + expect(loginEvents$).toBeTruthy(); + }); + + it('emits envelope on AuthActions.LOGIN with action and timestamp', (done) => { + const s = loginEvents$.pipe(take(1)).subscribe((env) => { + expect(env.action.type).toBe(AuthActions.LOGIN); + expect(env.timestamp).toBe(mockTimestamp); + expect(Date.now).toHaveBeenCalled(); + done(); + }); + subscription.add(s); + actions$.next({ type: AuthActions.LOGIN }); + }); + + it('replays the last login event to late subscribers', (done) => { + actions$.next({ type: AuthActions.LOGIN }); + + const s = loginEvents$.pipe(take(1)).subscribe((env) => { + expect(env.action.type).toBe(AuthActions.LOGIN); + expect(env.timestamp).toBe(mockTimestamp); + done(); + }); + subscription.add(s); + }); + + it('ignores non-login actions', (done) => { + const received: LoginEventEnvelope[] = []; + const s = loginEvents$.subscribe((e) => received.push(e)); + subscription.add(s); + + actions$.next({ type: 'OTHER' }); + expect(received.length).toBe(0); + done(); + }); + + it('updates replay with the newest login event', (done) => { + const firstTimestamp = 1111111111; + const secondTimestamp = 2222222222; + + (Date.now as jasmine.Spy).and.returnValue(firstTimestamp); + actions$.next({ type: AuthActions.LOGIN }); + (Date.now as jasmine.Spy).and.returnValue(secondTimestamp); + actions$.next({ type: AuthActions.LOGIN }); + + const s = loginEvents$.pipe(take(1)).subscribe((env) => { + expect(env.action.type).toBe(AuthActions.LOGIN); + expect(env.timestamp).toBe(secondTimestamp); + done(); + }); + subscription.add(s); + }); +}); diff --git a/integration-libs/cds/src/profiletag/providers/login-events.provider.ts b/integration-libs/cds/src/profiletag/providers/login-events.provider.ts new file mode 100644 index 00000000000..47b4520f1e4 --- /dev/null +++ b/integration-libs/cds/src/profiletag/providers/login-events.provider.ts @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2025 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { inject, provideAppInitializer } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { ActionsSubject } from '@ngrx/store'; +import { AuthActions } from '@spartacus/core'; +import { ReplaySubject } from 'rxjs'; +import { filter, tap } from 'rxjs/operators'; +import { LOGIN_EVENTS, LoginEventEnvelope } from '../tokens/login-events.token'; + +/** + * Provides login events tracking that starts immediately on app initialization. + * Uses ReplaySubject to ensure no login events are missed. + * Provides timestamp to deduplicate login events. + */ +export function provideLoginEventsTracking() { + const loginEvents$ = new ReplaySubject(1); + + return [ + { + provide: LOGIN_EVENTS, + useValue: loginEvents$.asObservable(), + }, + provideAppInitializer(() => { + const actionsSubject = inject(ActionsSubject); + actionsSubject + .pipe( + filter( + (action): action is AuthActions.Login => + action.type === AuthActions.LOGIN + ), + tap((action) => { + const envelope: LoginEventEnvelope = { + action, + timestamp: Date.now(), + }; + loginEvents$.next(envelope); + }), + takeUntilDestroyed() + ) + .subscribe(); + }), + ]; +} diff --git a/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.spec.ts b/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.spec.ts index 277621edaa8..f298b05cec2 100644 --- a/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.spec.ts +++ b/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.spec.ts @@ -1,30 +1,46 @@ import { TestBed } from '@angular/core/testing'; import { ActionsSubject, StoreModule } from '@ngrx/store'; -import { ConsentService } from '@spartacus/core'; -import { of } from 'rxjs'; +import { + AuthActions, + ConsentService, + FeatureConfigService, +} from '@spartacus/core'; +import { of, Subject } from 'rxjs'; import { CdsConfig } from '../../config/cds-config'; import { ConsentChangedPushEvent } from '../model/profile-tag.model'; import { ProfileTagLifecycleService } from './profile-tag-lifecycle.service'; import { fakeAsync, tick, flush } from '@angular/core/testing'; +import { LOGIN_EVENTS, LoginEventEnvelope } from '../tokens/login-events.token'; describe('ProfileTagLifecycleService', () => { let service: ProfileTagLifecycleService; let consentService: jasmine.SpyObj; + let featureConfigService: jasmine.SpyObj; let actionsSubject: ActionsSubject; + let loginEventsSubject: Subject; beforeEach(() => { const consentServiceSpy = jasmine.createSpyObj('ConsentService', [ 'getConsent', 'isConsentGiven', ]); + const featureConfigServiceSpy = jasmine.createSpyObj( + 'FeatureConfigService', + ['isEnabled'] + ); + + loginEventsSubject = new Subject(); + TestBed.configureTestingModule({ imports: [StoreModule.forRoot({})], providers: [ { provide: ConsentService, useValue: consentServiceSpy }, + { provide: FeatureConfigService, useValue: featureConfigServiceSpy }, { provide: CdsConfig, useValue: { cds: { consentTemplateId: 'templateId' } }, }, + { provide: LOGIN_EVENTS, useValue: loginEventsSubject.asObservable() }, ActionsSubject, ProfileTagLifecycleService, ], @@ -33,6 +49,9 @@ describe('ProfileTagLifecycleService', () => { consentService = TestBed.inject( ConsentService ) as jasmine.SpyObj; + featureConfigService = TestBed.inject( + FeatureConfigService + ) as jasmine.SpyObj; actionsSubject = TestBed.inject(ActionsSubject); }); @@ -74,15 +93,133 @@ describe('ProfileTagLifecycleService', () => { }); }); - it('should return login successful event', fakeAsync(() => { - const mockAction = { type: 'LOGIN' }; - actionsSubject.next(mockAction); - tick(); + describe('loginSuccessful()', () => { + describe('when cdsLoginEventsToken feature flag is disabled', () => { + beforeEach(() => { + featureConfigService.isEnabled.and.returnValue(false); + }); + + it('should return login successful event from ActionsSubject', fakeAsync(() => { + const mockAction = { type: AuthActions.LOGIN }; + + let result: boolean | undefined; + service.loginSuccessful().subscribe((value: boolean) => { + result = value; + }); + + actionsSubject.next(mockAction); + tick(); + + expect(result).toBe(true); + expect(featureConfigService.isEnabled).toHaveBeenCalledWith( + 'cdsLoginEventsToken' + ); + + flush(); + })); - service.loginSuccessful().subscribe((result: boolean) => { - expect(result).toBe(true); + it('should not emit for non-LOGIN actions', fakeAsync(() => { + const mockAction = { type: AuthActions.LOGOUT }; + + let result: boolean | undefined; + service.loginSuccessful().subscribe((value: boolean) => { + result = value; + }); + + actionsSubject.next(mockAction); + tick(); + + expect(result).toBeUndefined(); + + flush(); + })); }); - flush(); - })); + describe('when cdsLoginEventsToken feature flag is enabled', () => { + beforeEach(() => { + featureConfigService.isEnabled.and.returnValue(true); + }); + + it('should return login successful event from LOGIN_EVENTS token', fakeAsync(() => { + let result: boolean | undefined; + service.loginSuccessful().subscribe((value: boolean) => { + result = value; + }); + + const mockLoginEvent: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: Date.now(), + }; + + loginEventsSubject.next(mockLoginEvent); + tick(); + + expect(result).toBe(true); + expect(featureConfigService.isEnabled).toHaveBeenCalledWith( + 'cdsLoginEventsToken' + ); + + flush(); + })); + + it('should deduplicate login events by timestamp', fakeAsync(() => { + const results: boolean[] = []; + service.loginSuccessful().subscribe((value: boolean) => { + results.push(value); + }); + + const timestamp = Date.now(); + const mockLoginEvent1: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: timestamp, + }; + const mockLoginEvent2: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: timestamp, // Same timestamp - should be filtered out + }; + const mockLoginEvent3: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: timestamp + 1000, // Different timestamp - should pass through + }; + + loginEventsSubject.next(mockLoginEvent1); + loginEventsSubject.next(mockLoginEvent2); + loginEventsSubject.next(mockLoginEvent3); + tick(); + + expect(results).toEqual([true, true]); // Only 2 events should pass through + + flush(); + })); + + it('should allow events with different timestamps', fakeAsync(() => { + const results: boolean[] = []; + service.loginSuccessful().subscribe((value: boolean) => { + results.push(value); + }); + + const mockLoginEvent1: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: 1000, + }; + const mockLoginEvent2: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: 2000, + }; + const mockLoginEvent3: LoginEventEnvelope = { + action: { type: AuthActions.LOGIN }, + timestamp: 3000, + }; + + loginEventsSubject.next(mockLoginEvent1); + loginEventsSubject.next(mockLoginEvent2); + loginEventsSubject.next(mockLoginEvent3); + tick(); + + expect(results).toEqual([true, true, true]); // All events should pass through + + flush(); + })); + }); + }); }); diff --git a/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.ts b/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.ts index 48c48385099..c17252cc124 100644 --- a/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.ts +++ b/integration-libs/cds/src/profiletag/services/profile-tag-lifecycle.service.ts @@ -4,18 +4,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { ActionsSubject } from '@ngrx/store'; -import { AuthActions, ConsentService } from '@spartacus/core'; +import { + AuthActions, + ConsentService, + FeatureConfigService, +} from '@spartacus/core'; import { Observable } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; +import { distinctUntilChanged, filter, map } from 'rxjs/operators'; import { CdsConfig } from '../../config/cds-config'; import { ConsentChangedPushEvent } from '../model/profile-tag.model'; +import { LOGIN_EVENTS } from '../tokens/login-events.token'; @Injectable({ providedIn: 'root', }) export class ProfileTagLifecycleService { + private readonly loginEnvelopes$ = inject(LOGIN_EVENTS); + private readonly featureConfigService = inject(FeatureConfigService); + constructor( protected consentService: ConsentService, protected config: CdsConfig, @@ -39,7 +47,19 @@ export class ProfileTagLifecycleService { ); } + /** + * Emits true only for unique login envelopes (deduped by timestamp across the app lifetime). + */ loginSuccessful(): Observable { + const cdsLoginEventsToken = this.featureConfigService.isEnabled( + 'cdsLoginEventsToken' + ); + if (cdsLoginEventsToken) { + return this.loginEnvelopes$.pipe( + distinctUntilChanged((a, b) => a.timestamp === b.timestamp), + map(() => true) + ); + } return this.actionsSubject.pipe( filter((action) => action.type === AuthActions.LOGIN), map(() => true) diff --git a/integration-libs/cds/src/profiletag/tokens/index.ts b/integration-libs/cds/src/profiletag/tokens/index.ts new file mode 100644 index 00000000000..af8f8dff711 --- /dev/null +++ b/integration-libs/cds/src/profiletag/tokens/index.ts @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2025 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export * from './login-events.token'; diff --git a/integration-libs/cds/src/profiletag/tokens/login-events.token.ts b/integration-libs/cds/src/profiletag/tokens/login-events.token.ts new file mode 100644 index 00000000000..ad9a7537e89 --- /dev/null +++ b/integration-libs/cds/src/profiletag/tokens/login-events.token.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2025 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { InjectionToken } from '@angular/core'; +import { AuthActions } from '@spartacus/core'; +import { Observable } from 'rxjs'; + +export interface LoginEventEnvelope { + action: AuthActions.Login; + timestamp: number; +} + +/** + * Injection token for login events observable. + * Provides access to login events that are captured from app initialization. + */ +export const LOGIN_EVENTS = new InjectionToken>( + 'LOGIN_EVENTS' +); diff --git a/integration-libs/s4-service/checkout/components/checkout-delivery-mode/service-checkout-delivery-mode.component.html b/integration-libs/s4-service/checkout/components/checkout-delivery-mode/service-checkout-delivery-mode.component.html index a27e5afcaff..d05dcf9f417 100644 --- a/integration-libs/s4-service/checkout/components/checkout-delivery-mode/service-checkout-delivery-mode.component.html +++ b/integration-libs/s4-service/checkout/components/checkout-delivery-mode/service-checkout-delivery-mode.component.html @@ -1,17 +1,8 @@
- - - {{ 'serviceOrderCheckout.productDeliveryMethods' | cxTranslate }} - - - - - - {{ 'serviceOrderCheckout.productDeliveryOptions' | cxTranslate }} - - - + + {{ 'serviceOrderCheckout.productDeliveryOptions' | cxTranslate }} + - - - {{ 'serviceOrderCheckout.serviceDeliveryMethod' | cxTranslate }} - - - - - {{ 'serviceOrderCheckout.serviceDeliveryOption' | cxTranslate }} - - + + {{ 'serviceOrderCheckout.serviceDeliveryOption' | cxTranslate }} +
{ } clearUserId() {} setUserId() {} + isEmulated(): Observable { + return of(); + } } const oauthLibEvents = new BehaviorSubject({ @@ -157,6 +160,7 @@ describe('AuthService', () => { spyOn(userIdService, 'setUserId').and.callThrough(); spyOn(store, 'dispatch').and.callThrough(); spyOn(authStorageService, 'getItem').and.returnValue('token'); + spyOn(userIdService, 'isEmulated').and.returnValue(of(false)); await service.checkOAuthParamsInUrl(); @@ -167,9 +171,23 @@ describe('AuthService', () => { expect(store.dispatch).toHaveBeenCalledWith(new AuthActions.Login()); }); + it('when customer emulated in asm page', async () => { + spyOn(authStorageService, 'getItem').and.returnValue('token'); + spyOn(userIdService, 'setUserId').and.callThrough(); + + spyOn(userIdService, 'isEmulated').and.returnValue(of(true)); + + await service.checkOAuthParamsInUrl(); + + expect(userIdService.setUserId).not.toHaveBeenCalledWith( + OCC_USER_ID_CURRENT + ); + }); + describe('when the token is received', () => { it('should redirect', async () => { spyOn(authRedirectService, 'redirect').and.callThrough(); + spyOn(userIdService, 'isEmulated').and.returnValue(of(false)); await service.checkOAuthParamsInUrl(); @@ -178,6 +196,7 @@ describe('AuthService', () => { it('should dispatch login action', async () => { spyOn(store, 'dispatch').and.callThrough(); + spyOn(userIdService, 'isEmulated').and.returnValue(of(false)); await service.checkOAuthParamsInUrl(); @@ -190,6 +209,7 @@ describe('AuthService', () => { spyOn(oAuthLibWrapperService, 'tryLogin').and.returnValue( Promise.resolve({ result: true, tokenReceived: false }) ); + spyOn(userIdService, 'isEmulated').and.returnValue(of(false)); }); it('should NOT redirect', async () => { @@ -215,7 +235,24 @@ describe('AuthService', () => { (featureConfigService.isEnabled as jasmine.Spy).and.returnValue(true); }); + it('when customer emulated in asm page', async () => { + spyOn(authStorageService, 'getItem').and.returnValue('token'); + spyOn(userIdService, 'setUserId').and.callThrough(); + + spyOn(userIdService, 'isEmulated').and.returnValue(of(true)); + + await service.checkOAuthParamsInUrl(); + + expect(userIdService.setUserId).not.toHaveBeenCalledWith( + OCC_USER_ID_CURRENT + ); + }); + describe('when the token is received', () => { + beforeEach(() => { + spyOn(userIdService, 'isEmulated').and.returnValue(of(false)); + }); + it('should login user and dispatch login action', async () => { spyOn(oAuthLibWrapperService, 'tryLogin').and.callThrough(); spyOn(userIdService, 'setUserId').and.callThrough(); diff --git a/projects/core/src/auth/user-auth/facade/auth.service.ts b/projects/core/src/auth/user-auth/facade/auth.service.ts index b5c63a6f053..0a562500649 100644 --- a/projects/core/src/auth/user-auth/facade/auth.service.ts +++ b/projects/core/src/auth/user-auth/facade/auth.service.ts @@ -6,11 +6,18 @@ import { inject, Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; -import { BehaviorSubject, lastValueFrom, Observable } from 'rxjs'; +import { + BehaviorSubject, + firstValueFrom, + lastValueFrom, + Observable, +} from 'rxjs'; import { distinctUntilChanged, map, shareReplay, tap } from 'rxjs/operators'; -import { FeatureConfigService } from '../../../features-config/services/feature-config.service'; +import { FeatureConfigService } from '../../../features-config'; +import { LoggerService } from '../../../logger'; import { OCC_USER_ID_CURRENT } from '../../../occ/utils/occ-constants'; import { RoutingService } from '../../../routing/facade/routing.service'; +import { CrossSiteRequestForgeryService } from '../../client-auth'; import { StateWithClientAuth } from '../../client-auth/store/client-auth-state'; import { OAuthTryLoginResult } from '../models/oauth-try-login-response'; import { AuthMultisiteIsolationService } from '../services/auth-multisite-isolation.service'; @@ -19,8 +26,6 @@ import { AuthStorageService } from '../services/auth-storage.service'; import { OAuthLibWrapperService } from '../services/oauth-lib-wrapper.service'; import { AuthActions } from '../store/actions/index'; import { UserIdService } from './user-id.service'; -import { CrossSiteRequestForgeryService } from '../../client-auth'; -import { LoggerService } from '../../../logger'; /** * Auth service for normal user authentication. @@ -66,10 +71,12 @@ export class AuthService { const token = this.authStorageService.getItem('access_token'); + const isEmulated = await firstValueFrom(this.userIdService.isEmulated()); + // We get the value `true` of `result` in the _code flow_ even if we did not log in successfully // (see source code https://github.com/manfredsteyer/angular-oauth2-oidc/blob/d95d7da788e2c1390346c66de62dc31f10d2b852/projects/lib/src/oauth-service.ts#L1711), // that why we also need to check if we have access_token - if (loginResult.result && token) { + if (loginResult.result && token && !isEmulated) { this.userIdService.setUserId(OCC_USER_ID_CURRENT); if ( diff --git a/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts b/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts index b93ecc23d9b..ac03f09ac47 100644 --- a/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts +++ b/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts @@ -9,12 +9,6 @@ // We want this interface to be STRICT and cause a compilation error when a removed property is used. // Thanks to that, customers using a property that was recently removed, will know they have to adapt their code. export interface FeatureTogglesInterface { - /** - * In 'CheckoutDeliveryModeComponent' and 'CheckReviewShippingComponent', it displays - * the new delivery options translation - */ - showDeliveryOptionsTranslation?: boolean; - /** * New REDESIGNED search-box component */ @@ -746,6 +740,17 @@ export interface FeatureTogglesInterface { */ productCarouselScrolling?: boolean; + /** + * Feature flag to enable using the new LOGIN_EVENTS token instead of the ActionsSubject LOGIN stream for tracking. + * + * When enabled, the new LOGIN_EVENTS token will be used instead of the ActionsSubject LOGIN stream. + * This is needed to support code flow authentication. If we are using the ActionsSubject LOGIN stream, + * the login event won't be captured once we are redirected back from the auth server. + * + * Used in `ProfileTagLifecycleService` + */ + cdsLoginEventsToken?: boolean; + /** * Feature flag to enable using in the index.html. * @@ -858,7 +863,6 @@ export interface FeatureTogglesInterface { } export const defaultFeatureToggles: Required = { - showDeliveryOptionsTranslation: true, searchBoxV2: true, trendingSearches: true, useProductCarouselBatchApi: true, @@ -964,6 +968,7 @@ export const defaultFeatureToggles: Required = { topProgressBarUseTransformAnimation: false, disableCxPageSlotMarginAnimation: false, productCarouselScrolling: false, + cdsLoginEventsToken: false, createMediaPreconnectLink: false, unifiedDefaultHeaderSlotsAcrossBreakpoints: false, reserveSpaceForImagesOnPdpAndPlp: false, diff --git a/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/checkout/checkout-as-guest.e2e.cy.ts b/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/checkout/checkout-as-guest.e2e.cy.ts index da9e06f98d5..5fa421d83f1 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/checkout/checkout-as-guest.e2e.cy.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/checkout/checkout-as-guest.e2e.cy.ts @@ -29,43 +29,49 @@ context('Checkout as guest', { testIsolation: false }, () => { guestCheckout.testCheckoutAsGuest(); // Test depends on on core test for guest account creation. + // JDK21: identified bug CXSPA-10758, skip test until fix gets applied it('should keep products in guest cart and restart checkout', () => { - checkout.goToCheapProductDetailsPage(); - checkout.addCheapProductToCartAndProceedToCheckout(); + cy.whenJDK21(() => { + cy.log('skip for JDK21, will be fix by CXSPA-10758'); + }); + cy.whenJDK17(() => { + checkout.goToCheapProductDetailsPage(); + checkout.addCheapProductToCartAndProceedToCheckout(); - guestCheckout.loginAsGuest(guestCheckout.guestUser); + guestCheckout.loginAsGuest(guestCheckout.guestUser); - checkout.fillAddressFormWithCheapProduct(); + checkout.fillAddressFormWithCheapProduct(); - const deliveryAddressPage = waitForPage( - '/checkout/delivery-address', - 'getDeliveryPage' - ); + const deliveryAddressPage = waitForPage( + '/checkout/delivery-address', + 'getDeliveryPage' + ); - checkout.clickHamburger(); + checkout.clickHamburger(); - cy.getLoginRegisterLink({ clickAndWait: true }); + cy.getLoginRegisterLink({ clickAndWait: true }); - login(guestCheckout.guestUser.email, guestCheckout.guestUser.password); - cy.wait(`@${deliveryAddressPage}`) - .its('response.statusCode') - .should('eq', 200); + login(guestCheckout.guestUser.email, guestCheckout.guestUser.password); + cy.wait(`@${deliveryAddressPage}`) + .its('response.statusCode') + .should('eq', 200); - cy.get('cx-login div.cx-login-greet').should('exist'); - cy.get('.cx-checkout-title').should('contain', 'Shipping Address'); + cy.get('cx-login div.cx-login-greet').should('exist'); + cy.get('.cx-checkout-title').should('contain', 'Shipping Address'); - cy.get('cx-mini-cart .count').contains('1'); + cy.get('cx-mini-cart .count').contains('1'); - const cartPage = waitForPage('/cart', 'getCartPage'); - cy.get('cx-mini-cart').click(); - cy.wait(`@${cartPage}`).its('response.statusCode').should('eq', 200); + const cartPage = waitForPage('/cart', 'getCartPage'); + cy.get('cx-mini-cart').click(); + cy.wait(`@${cartPage}`).its('response.statusCode').should('eq', 200); - cy.get('cx-cart-item-list') - .contains('tr[cx-cart-item-list-row]', cheapProduct.code) - .within(() => { - cy.get('cx-item-counter input').should('have.value', '1'); - }); - loginHelper.signOutUser(); + cy.get('cx-cart-item-list') + .contains('tr[cx-cart-item-list-row]', cheapProduct.code) + .within(() => { + cy.get('cx-item-counter input').should('have.value', '1'); + }); + loginHelper.signOutUser(); + }); }); }); }); diff --git a/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/user_access/navigation-login-a11y.e2e.cy.ts b/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/user_access/navigation-login-a11y.e2e.cy.ts index 3811eff4c3d..1d27792e91b 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/user_access/navigation-login-a11y.e2e.cy.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/e2e/regression/user_access/navigation-login-a11y.e2e.cy.ts @@ -18,8 +18,8 @@ function assertNavigationButtonsAttributes(buttonsSelector: string) { } describe('Navigation Login', () => { - let user; - before(() => { + it('should login and logout successfully and have correct Navigation Menu buttons values', () => { + let user; cy.whenJDK17(() => { visitLoginPage(); }); @@ -27,9 +27,6 @@ describe('Navigation Login', () => { cy.visit('/login/register'); }); user = login.registerUserFromLoginPage(); - }); - - it('should login and logout successfully and have correct Navigation Menu buttons values', () => { login.loginUser(); const tokenRevocationRequestAlias = login.listenForTokenRevocationRequest(); diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-as-guest.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-as-guest.ts index cdfe7a07d06..735522cbb05 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-as-guest.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-as-guest.ts @@ -7,6 +7,7 @@ import { getSampleUser, SampleUser, user } from '../sample-data/checkout-flow'; import { assertAddressForm } from './address-book'; import * as checkout from './checkout-flow'; +import { AddressData } from './checkout-forms'; import { waitForPage } from './navigation'; import { validateUpdateProfileForm } from './update-profile'; @@ -67,7 +68,7 @@ export function testCheckoutAsGuest() { lastName: guestUser.lastName, phone: '', address: guestUser.address, - }, + } as AddressData, 'US-CA' ); @@ -88,14 +89,33 @@ export function testCheckoutAsGuest() { }); } -export function createAccountFromGuest(password: string) { - const homePage = waitForPage('homepage', 'getHomePage'); +function fillGuestRegistrationForm(password: string) { cy.get('cx-guest-register-form').within(() => { cy.get('[formcontrolname="password"]').clear().type(password); cy.get('[formcontrolname="passwordconf"]').clear().type(password); cy.get('button[type=submit]').click(); }); +} + +export function createAccountFromGuest(password: string, email?: string) { + cy.whenJDK17(() => { + const homePage = waitForPage('homepage', 'getHomePage'); + fillGuestRegistrationForm(password); + cy.wait(`@${homePage}`); + cy.get('cx-page-slot.Section1 cx-banner'); + }); - cy.wait(`@${homePage}`); - cy.get('cx-page-slot.Section1 cx-banner'); + cy.whenJDK21(() => { + const loginPage = waitForPage('/login', 'getLoginPage'); + fillGuestRegistrationForm(password); + cy.wait(`@${loginPage}`); + cy.location('pathname').should('include', '/login'); + cy.get('cx-login-form').within(() => { + cy.get('input[name="username"]') + .clear() + .type(guestUser?.email ?? email); + cy.get('input[name="password"]').clear().type(password); + cy.get('button[type="submit"]').click(); + }); + }); } diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-variants.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-variants.ts index 38c492f1b79..ffb6733ca8a 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-variants.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/checkout-variants.ts @@ -14,6 +14,7 @@ import { assertAddressForm } from './address-book'; import { login } from './auth-forms'; import * as guestCheckout from './checkout-as-guest'; import * as checkout from './checkout-flow'; +import { AddressData } from './checkout-forms'; import { waitForPage } from './navigation'; import { validateUpdateProfileForm } from './update-profile'; import { @@ -60,7 +61,10 @@ export function testCheckoutVariantAsGuest() { variantProduct, true ); - guestCheckout.createAccountFromGuest(variantUser.password); + guestCheckout.createAccountFromGuest( + variantUser.password, + variantUser.email + ); cy.selectUserMenuOption({ option: 'Personal Details', @@ -76,7 +80,7 @@ export function testCheckoutVariantAsGuest() { lastName: variantUser.lastName, phone: '', address: variantUser.address, - }, + } as AddressData, 'GB' ); @@ -102,75 +106,84 @@ export function testCheckoutVariantAsGuest() { } export function testCheckoutVariantAsGuestAndVerifyCart() { + // JDK21: identified bug CXSPA-10758, skip test until fix gets applied it('should perform checkout as guest, create an account and verify guest data, and verify cart persists after registering', () => { - checkout.goToCheapProductDetailsPage(products[0]); - addVariantOfSameProductToCart(); + cy.whenJDK21(() => { + cy.log('skip for JDK21, will be fix by CXSPA-10758'); + }); + cy.whenJDK17(() => { + checkout.goToCheapProductDetailsPage(products[0]); + addVariantOfSameProductToCart(); - visitProductWithoutVariantPage(); - addMutipleProductWithoutVariantToCart(); + visitProductWithoutVariantPage(); + addMutipleProductWithoutVariantToCart(); - checkout.goToCheapProductDetailsPage(products[0]); - checkout.addCheapProductToCartAndProceedToCheckout(variantProduct); + checkout.goToCheapProductDetailsPage(products[0]); + checkout.addCheapProductToCartAndProceedToCheckout(variantProduct); - guestCheckout.loginAsGuest(variantUser); + guestCheckout.loginAsGuest(variantUser); - checkout.checkSummaryAmount(cartWithTotalVariantProduct); + checkout.checkSummaryAmount(cartWithTotalVariantProduct); - checkout.fillAddressFormWithCheapProduct(variantUser); + checkout.fillAddressFormWithCheapProduct(variantUser); - checkout.verifyDeliveryOptions(); + checkout.verifyDeliveryOptions(); - checkout.fillPaymentFormWithCheapProduct(variantUser, undefined); + checkout.fillPaymentFormWithCheapProduct(variantUser, undefined); - checkout.placeOrderWithCheapProduct( - variantUser, - cartWithTotalVariantProduct, - APPAREL_CURRENCY - ); + checkout.placeOrderWithCheapProduct( + variantUser, + cartWithTotalVariantProduct, + APPAREL_CURRENCY + ); - checkout.verifyOrderConfirmationPageWithCheapProduct( - variantUser, - variantProduct, - true - ); - guestCheckout.createAccountFromGuest(variantUser.password); + checkout.verifyOrderConfirmationPageWithCheapProduct( + variantUser, + variantProduct, + true + ); + guestCheckout.createAccountFromGuest( + variantUser.password, + variantUser.email + ); - const deliveryAddressPage = waitForPage( - '/checkout/delivery-address', - 'getDeliveryAddressPage' - ); + const deliveryAddressPage = waitForPage( + '/checkout/delivery-address', + 'getDeliveryAddressPage' + ); - checkout.goToCheapProductDetailsPage(products[0]); - checkout.addCheapProductToCartAndBeginCheckoutForSignedInCustomer( - variantProduct - ); + checkout.goToCheapProductDetailsPage(products[0]); + checkout.addCheapProductToCartAndBeginCheckoutForSignedInCustomer( + variantProduct + ); - cy.wait(`@${deliveryAddressPage}`) - .its('response.statusCode') - .should('eq', 200); + cy.wait(`@${deliveryAddressPage}`) + .its('response.statusCode') + .should('eq', 200); - cy.get('.cx-checkout-title').should('contain', 'Shipping Address'); - cy.get('cx-mini-cart .count').contains('1'); + cy.get('.cx-checkout-title').should('contain', 'Shipping Address'); + cy.get('cx-mini-cart .count').contains('1'); - checkout.signOut(); + checkout.signOut(); - cy.getLoginRegisterLink({ clickAndWait: true }); + cy.getLoginRegisterLink({ clickAndWait: true }); - login(variantUser.email, variantUser.password); + login(variantUser.email, variantUser.password); - cy.get('cx-login div.cx-login-greet').should('exist'); - cy.get('cx-mini-cart .count').contains('1'); + cy.get('cx-login div.cx-login-greet').should('exist'); + cy.get('cx-mini-cart .count').contains('1'); - const cartPage = waitForPage('/cart', 'getCartPage'); - cy.get('cx-mini-cart').click(); - cy.wait(`@${cartPage}`).its('response.statusCode').should('eq', 200); + const cartPage = waitForPage('/cart', 'getCartPage'); + cy.get('cx-mini-cart').click(); + cy.wait(`@${cartPage}`).its('response.statusCode').should('eq', 200); - cy.get('cx-cart-item-list') - .contains('tr[cx-cart-item-list-row]', variantProduct.code) - .within(() => { - cy.get('cx-item-counter input').should('have.value', '1'); - }); - checkout.signOut(); + cy.get('cx-cart-item-list') + .contains('tr[cx-cart-item-list-row]', variantProduct.code) + .within(() => { + cy.get('cx-item-counter input').should('have.value', '1'); + }); + checkout.signOut(); + }); }); } diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/order-history.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/order-history.ts index a6b644cea7c..d32f080da85 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/order-history.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/order-history.ts @@ -109,6 +109,9 @@ export const orderHistoryTest = { url: string = orderHistoryLink ) { it('should go to Order History once user has logged in', () => { + cy.visit(url); + cy.url().should('contain', '/login'); + cy.getLoginRegisterLink().should('contain', 'Sign In / Register'); login(sampleUser.email, sampleUser.password); cy.url().should('contain', url); if (url === replenishmentOrderHistoryUrl) { diff --git a/projects/storefrontapp-e2e-cypress/cypress/support/utils/order-placed.ts b/projects/storefrontapp-e2e-cypress/cypress/support/utils/order-placed.ts index 132a9bd9e7d..c424df10de1 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/support/utils/order-placed.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/support/utils/order-placed.ts @@ -6,9 +6,9 @@ const delay = 3000; -// 1 min in milliseconds -const timerTimeout = 180000; -const consignmentTimerTimeout = 180000; +// 4 min in milliseconds +const timerTimeout = 240000; +const consignmentTimerTimeout = 240000; // start time let startTime = 0; diff --git a/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts b/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts index 28d5cf88e31..711de41bedd 100644 --- a/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts +++ b/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts @@ -292,7 +292,6 @@ if (environment.cpq) { }, provideFeatureTogglesFactory(() => { const appFeatureToggles: Required = { - showDeliveryOptionsTranslation: true, searchBoxV2: true, trendingSearches: true, useProductCarouselBatchApi: true, @@ -404,6 +403,7 @@ if (environment.cpq) { topProgressBarUseTransformAnimation: true, disableCxPageSlotMarginAnimation: true, productCarouselScrolling: true, + cdsLoginEventsToken: true, createMediaPreconnectLink: true, unifiedDefaultHeaderSlotsAcrossBreakpoints: true, reserveSpaceForImagesOnPdpAndPlp: true, diff --git a/run-spartacus-product-configurator-e2es.sh b/run-spartacus-product-configurator-e2es.sh index ea1d1f37641..3272290bd66 100755 --- a/run-spartacus-product-configurator-e2es.sh +++ b/run-spartacus-product-configurator-e2es.sh @@ -1,6 +1,6 @@ #!/bin/bash # This script is invoked from https://github.tools.sap/cx-commerce/wonderful-testing-framework/blob/main/resources/wtf/config.yaml -# By default, the e2es for b2c product-configurator will be executed without parameters. +# By default, the e2es for b2c product-configurator will be executed without parameters. # Supported options include "cpq", "b2c" and "b2c_flaky" param=${1:-"b2c"} # Default to "b2c" if no parameter provided @@ -9,16 +9,16 @@ param=${1:-"b2c"} # Default to "b2c" if no parameter provided case "$param" in "cpq") export E2E_BASE_SITE="powertools-spa" - export ENDPOINT_URL_PUBLIC_SPARTACUS=$ENDPOINT_URL_PUBLIC_SPA_POWERTOOLS + export ENDPOINT_URL_PUBLIC_SPARTACUS=$ENDPOINT_URL_PUBLIC_SPA_POWERTOOLS export E2ES_TO_RUN="'cypress/e2e/**/cpq-configuration.ccv2-e2e.cy.ts'" ;; "b2c") export E2E_BASE_SITE="electronics-spa" - export E2ES_TO_RUN="'cypress/e2e/**/product_configurator/*-configurator*e2e.cy.ts'" + export E2ES_TO_RUN="'cypress/e2e/regression/product_configurator/*-configurator*e2e.cy.ts'" ;; "b2c_flaky") export E2E_BASE_SITE="electronics-spa" - export E2ES_TO_RUN="'cypress/e2e/**/*-configurator*e2e*flaky.cy.ts'" + export E2ES_TO_RUN="'cypress/e2e/regression/*-configurator*e2e*flaky.cy.ts'" ;; *) echo "Invalid parameter. Please provide a valid parameter." @@ -31,4 +31,4 @@ esac (cd projects/storefrontapp-e2e-cypress && npm install) # run spartacus ccv2 e2es for product-configurator -npm run e2e:run:ci:ccv2-product-configurator \ No newline at end of file +npm run e2e:run:ci:ccv2-product-configurator From 23e0aee471ea7bfd101284edc62b6040492b0c98 Mon Sep 17 00:00:00 2001 From: Raja Singh Date: Tue, 12 Aug 2025 17:18:51 +0530 Subject: [PATCH 4/8] Revert "CXSPA-10739: redirecting fix and automobile ext" This reverts commit dcd46121f5c00d3b132327d15d58f6bfd57ffaf5. --- package.json | 34 +++++++++---------- .../features/cdc/cdc-feature.module.ts | 5 --- .../spartacus-b2c-configuration.module.ts | 2 -- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 7319beb6e3b..b52a3e81026 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "scripts": { "postinstall": "ts-node scripts/npm-postinstall/patch-@angular-build-19.0.4.ts", "build:analyze": "npm run build -- --stats-json && npx esbuild-visualizer --metadata ./dist/storefrontapp/stats.json", - "build": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build", + "build": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build", "watch": "npm run build -- --watch --configuration development", "build:core": "nx build core --configuration production", "build:storefrontlib": "nx build storefrontlib --configuration production", @@ -55,11 +55,11 @@ "build:schematics": "npm --prefix projects/schematics run build", "build:setup": "nx build setup --configuration production", "build:storefinder": "npm --prefix feature-libs/storefinder run build:schematics && nx build storefinder --configuration production", - "build:csr": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build-csr", - "build:ssr": "env-cmd --no-override -e dev,b2c,b2b nx run storefrontapp:build:production", - "build:ssr:opf": "env-cmd --no-override -e opf,b2c,b2b nx run storefrontapp:build:production", - "build:ssr:ci": "env-cmd -e ci,b2c,b2b nx run storefrontapp:build:production", - "build:ssr:local-http-backend": "env-cmd -e local-http,b2c,b2b nx run storefrontapp:build:production", + "build:csr": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build-csr", + "build:ssr": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:build:production", + "build:ssr:opf": "env-cmd --no-override -e opf,b2c,$SPA_ENV nx run storefrontapp:build:production", + "build:ssr:ci": "env-cmd -e ci,b2c,$SPA_ENV nx run storefrontapp:build:production", + "build:ssr:local-http-backend": "env-cmd -e local-http,b2c,$SPA_ENV nx run storefrontapp:build:production", "build:smartedit": "npm --prefix feature-libs/smartedit run build:schematics && nx build smartedit --configuration production", "build:tracking": "npm --prefix feature-libs/tracking run build:schematics && nx build tracking --configuration production", "build:quote": "npm --prefix feature-libs/quote run build:schematics && nx build quote --configuration production", @@ -132,16 +132,16 @@ "lint:styles": "stylelint \"{projects,feature-libs,integration-libs}/**/*.scss\"", "prettier": "prettier --config ./.prettierrc --list-different \"{projects,feature-libs,core-libs,integration-libs}/**/*{.ts,.js,.json,.scss,.html}\"", "prettier:fix": "prettier --config ./.prettierrc --list-different \"{projects,feature-libs,core-libs,integration-libs}/**/*{.ts,.js,.json,.scss,.html}\" --write", - "start": "env-cmd --no-override -e dev,b2c,b2b nx serve storefrontapp --configuration=development", - "start:b2b": "env-cmd --no-override -e dev,b2b,b2b nx serve storefrontapp --configuration=development", - "start:ci": "env-cmd --no-override -e ci,b2c,b2b nx serve storefrontapp --configuration=development", - "start:ci:b2b": "env-cmd --no-override -e ci,b2b,b2b nx serve storefrontapp --configuration=development", - "start:opf": "env-cmd --no-override -e opf,b2b nx serve storefrontapp --configuration=development", - "start:opf:ssl": "env-cmd --no-override -e opf,b2b nx serve storefrontapp --configuration=development --ssl", - "start:opf:b2b": "env-cmd --no-override -e b2b,opf,b2b nx serve storefrontapp --configuration=development", - "start:opf:b2b:ssl": "env-cmd --no-override -e b2b,opf,b2b nx serve storefrontapp --configuration=development --ssl", - "start:punchout": "env-cmd --no-override -e punchout,b2b nx serve storefrontapp --configuration=development", - "start:prod": "env-cmd --no-override -e dev,b2c,b2b nx serve storefrontapp --configuration=production", + "start": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:b2b": "env-cmd --no-override -e dev,b2b,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:ci": "env-cmd --no-override -e ci,b2c,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:ci:b2b": "env-cmd --no-override -e ci,b2b,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:opf": "env-cmd --no-override -e opf,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:opf:ssl": "env-cmd --no-override -e opf,$SPA_ENV nx serve storefrontapp --configuration=development --ssl", + "start:opf:b2b": "env-cmd --no-override -e b2b,opf,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:opf:b2b:ssl": "env-cmd --no-override -e b2b,opf,$SPA_ENV nx serve storefrontapp --configuration=development --ssl", + "start:punchout": "env-cmd --no-override -e punchout,$SPA_ENV nx serve storefrontapp --configuration=development", + "start:prod": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx serve storefrontapp --configuration=production", "start:pwa": " cd ./dist/storefrontapp/browser && http-server -p 4200 --silent --proxy http://localhost:4200?", "test": "nx test", "test:all-schematics": "set -e; npm --prefix ./projects/schematics test -- -u; for dir in feature-libs/* integration-libs/*; do (cd $dir && npm run test:schematics -- -u); done", @@ -156,7 +156,7 @@ "serve:ssr:dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 SSR_TIMEOUT=30000 node dist/storefrontapp/server/server.mjs", "test:ssr": "env-cmd -e dev nx test ssr-tests", "test:ssr:ci": "env-cmd -e ci nx test ssr-tests", - "prerender": "env-cmd --no-override -e dev,b2b cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 nx run storefrontapp:prerender", + "prerender": "env-cmd --no-override -e dev,$SPA_ENV cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 nx run storefrontapp:prerender", "publish:docs": "npx --yes gh-pages@^2.2.0 -d documentation -m \"Compodocs updates\"", "test:cds:lib": "nx test cds --code-coverage", "build:cds:ssr": "env-cmd --no-override -e dev,b2c,cds nx run storefrontapp:build:production" diff --git a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts index 19e29acdb86..7a68cbfdaf5 100644 --- a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts +++ b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts @@ -29,11 +29,6 @@ import { javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', sessionExpiration: 3600, }, - { - baseSite: 'automobile-spa', - javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', - sessionExpiration: 3600, - }, { baseSite: 'powertools-spa', javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3__pAj9UsaNXJAaDi-d8xvhzNBvGXDYx0GlTg1R9YQWVgTIQbdBZzR98_y-nFZWUNl', diff --git a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts index 851e1d826e0..d6e9061a6ca 100644 --- a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts +++ b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts @@ -28,8 +28,6 @@ const defaultBaseSite = [ 'apparel-uk', 'apparel-uk-spa', 'apparel-uk-standalone', - 'automobile-spa', - 'automobile' ]; const baseSite = environment.epdVisualization ? ['electronics-epdvisualization-spa'].concat(defaultBaseSite) From 1b964317028a6e60e3d26b1c1da97fe3ee69b53d Mon Sep 17 00:00:00 2001 From: Raja Singh Date: Tue, 12 Aug 2025 17:24:15 +0530 Subject: [PATCH 5/8] CXSPA-10739: redirecting fix revert and automobile ext --- .../src/app/spartacus/spartacus-b2c-configuration.module.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts index d6e9061a6ca..851e1d826e0 100644 --- a/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts +++ b/projects/storefrontapp/src/app/spartacus/spartacus-b2c-configuration.module.ts @@ -28,6 +28,8 @@ const defaultBaseSite = [ 'apparel-uk', 'apparel-uk-spa', 'apparel-uk-standalone', + 'automobile-spa', + 'automobile' ]; const baseSite = environment.epdVisualization ? ['electronics-epdvisualization-spa'].concat(defaultBaseSite) From 831b2dd8c6a776dff202d6f466a1dd9cd3ecfde3 Mon Sep 17 00:00:00 2001 From: Raja Singh <59006156+rjsinghraj@users.noreply.github.com> Date: Tue, 12 Aug 2025 17:29:25 +0530 Subject: [PATCH 6/8] Update cdc-feature.module.ts --- .../src/app/spartacus/features/cdc/cdc-feature.module.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts index 7a68cbfdaf5..4827f92c364 100644 --- a/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts +++ b/projects/storefrontapp/src/app/spartacus/features/cdc/cdc-feature.module.ts @@ -28,6 +28,11 @@ import { baseSite: 'apparel-uk-spa', javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', sessionExpiration: 3600, + }, + { + baseSite: 'automobile-spa', + javascriptUrl: 'https://cdns.eu1.gigya.com/JS/gigya.js?apikey=3_k_wG-sllOhu2rjDEWHjG9-ncnnGAMHfkIcUKzl94weJU1Y18hITRgnTDp1LP8QdC', + sessionExpiration: 3600, }, { baseSite: 'powertools-spa', From dc7a82c295b1c61de829f99ce03939949c03ced3 Mon Sep 17 00:00:00 2001 From: Raja Singh Date: Wed, 13 Aug 2025 12:11:16 +0530 Subject: [PATCH 7/8] CXIEP-8670: disbaled showRealTimeStockInPDP --- .../features-config/feature-toggles/config/feature-toggles.ts | 2 +- .../src/app/spartacus/spartacus-features.module.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts b/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts index ac03f09ac47..745a0873443 100644 --- a/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts +++ b/projects/core/src/features-config/feature-toggles/config/feature-toggles.ts @@ -947,7 +947,7 @@ export const defaultFeatureToggles: Required = { a11yPdpGridArrangement: true, a11yHamburgerMenuTrapFocus: true, useExtendedMediaComponentConfiguration: true, - showRealTimeStockInPDP: true, + showRealTimeStockInPDP: false, a11yScrollToTopPositioning: true, a11yWideScreenImprovements: false, a11yOptimizedMenuSpacing: false, diff --git a/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts b/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts index 711de41bedd..02ba88fcee5 100644 --- a/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts +++ b/projects/storefrontapp/src/app/spartacus/spartacus-features.module.ts @@ -381,7 +381,7 @@ if (environment.cpq) { a11yPdpGridArrangement: true, a11yHamburgerMenuTrapFocus: true, useExtendedMediaComponentConfiguration: true, - showRealTimeStockInPDP: true, + showRealTimeStockInPDP: false, a11yScrollToTopPositioning: true, a11yWideScreenImprovements: true, a11yWrapReviewOrderInSection: true, From d1f200082b1d9f41b78b1bd0256e494ad8486480 Mon Sep 17 00:00:00 2001 From: Anjana BL Date: Mon, 18 Aug 2025 16:47:50 +0530 Subject: [PATCH 8/8] Adding log for checking CXSPA-10782 --- .../core/src/auth/user-auth/services/auth-config.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/projects/core/src/auth/user-auth/services/auth-config.service.ts b/projects/core/src/auth/user-auth/services/auth-config.service.ts index 4c9878b6076..21a601d6418 100644 --- a/projects/core/src/auth/user-auth/services/auth-config.service.ts +++ b/projects/core/src/auth/user-auth/services/auth-config.service.ts @@ -27,7 +27,9 @@ export class AuthConfigService { * Utility to make access to authentication config easier. */ private get config(): AuthConfig['authentication'] { - return this.authConfig?.authentication ?? {}; + let x = this.authConfig?.authentication ?? {}; + console.log(x); //temporarily adding log for checking CXSPA-10782 + return x; } /**