Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9af5caf
Fix usage for Object.hasOwn
shethj Sep 3, 2025
5142a48
Fix linting
shethj Sep 3, 2025
5b38bcf
update the mcp tool name and readme
wei-liu-sf Sep 3, 2025
2a4cc6a
Fix: Don't pass `code_challenge` if its undefined in `getPasswordRese…
joeluong-sfcc Sep 3, 2025
6ca9fe8
Merge branch 'develop' into W-19507083-renaming-mcp-tools_wliu
wei-liu-sf Sep 3, 2025
9a4dfb3
resize the images
wei-liu-sf Sep 3, 2025
db89f40
Merge branch 'W-19507083-renaming-mcp-tools_wliu' of https://github.c…
wei-liu-sf Sep 3, 2025
5c046bb
update CHANGELOG.md
wei-liu-sf Sep 3, 2025
0683a5a
@W-19364221 - Handle Removal of Last Address for Registered (#3231)
shauryemahajanSF Sep 3, 2025
199bd68
Merge branch 'develop' into W-19507083-renaming-mcp-tools_wliu
wei-liu-sf Sep 3, 2025
475d330
@W-19507083 -- Normalize the mcp tool name and Update README
wei-liu-sf Sep 3, 2025
8a0b696
@W-19327219: Update in isolation tests in MRT reference app (#3172)
rahulkumawat1 Sep 3, 2025
0b15688
Cleanup of tool
snilakandan13 Sep 3, 2025
5bf8d87
Merge conflicts
snilakandan13 Sep 3, 2025
26da5af
Added tests
snilakandan13 Sep 3, 2025
540c8fb
updated tool
snilakandan13 Sep 3, 2025
679097e
Gracefully handle when some config.app.* properties are missing (@W-1…
vmarta Sep 3, 2025
68d1dfb
@W-19364130 feat: fix shipping costs summary mode pricing (#3240)
sf-henry-semaganda Sep 3, 2025
2f3c013
Handle OS specific filepaths in tests
shethj Sep 3, 2025
2611018
Merge branch 'develop' into hotfix/validate-project-type-err
shethj Sep 3, 2025
bd3f171
Merge branch 'develop' into t/commerce/W-19406761/cleanupOfGitVersion…
snilakandan13 Sep 4, 2025
2c5ba77
Merge pull request #3241 from SalesforceCommerceCloud/t/commerce/W-19…
snilakandan13 Sep 4, 2025
7771f69
Enable OTEL test
shethj Sep 4, 2025
c0f4de8
Merge branch 'develop' into hotfix/validate-project-type-err
shethj Sep 4, 2025
af4a01c
Merge pull request #3237 from SalesforceCommerceCloud/hotfix/validate…
shethj Sep 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ jobs:
- name: Create .env with environment variables to be set on the MRT target
run: |-
echo "PWA_KIT_SLAS_CLIENT_SECRET=${{ secrets.ZZRF_002_SLAS_PRIVATE_CLIENT_SECRET }}" > ${{ vars.MRT_ENV_VARS_E2E_BASE_FILENAME }}
echo "OTEL_TRACING_ENABLED=true" >> ${{ vars.MRT_ENV_VARS_E2E_BASE_FILENAME }}

# Call the e2e/scripts/update-mrt-target.js script to update the MRT target config and environment variables.
# This script is a Node.js script that makes a PATCH request to the MRT API to update the MRT target config and environment variables.
Expand Down
19 changes: 14 additions & 5 deletions e2e/scripts/validate-generated-project.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ const validateExtensibilityConfig = async (project, templateVersion) => {
const pkg = require(pkgPath)
return new Promise((resolve, reject) => {
if (
!pkg.hasOwn('ccExtensibility') ||
!pkg['ccExtensibility'].hasOwn('extends') ||
!pkg['ccExtensibility'].hasOwn('overridesDir') ||
!Object.hasOwn(pkg, 'ccExtensibility') ||
!Object.hasOwn(pkg['ccExtensibility'], 'extends') ||
!Object.hasOwn(pkg['ccExtensibility'], 'overridesDir') ||
pkg['ccExtensibility'].extends !== '@salesforce/retail-react-app' ||
pkg['ccExtensibility'].overridesDir !== 'overrides'
) {
Expand Down Expand Up @@ -94,6 +94,15 @@ program
)
.option('--templateVersion <templateVersion>', 'Template version used to generate the project')

program.parse(process.argv)
// Export functions for testing
module.exports = {
validateGeneratedArtifacts,
validateExtensibilityConfig,
main
}

main(program)
// Only run CLI when file is executed directly
if (require.main === module) {
program.parse(process.argv)
main(program)
}
153 changes: 153 additions & 0 deletions e2e/scripts/validate-generated-project.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright (c) 2025, 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 fs = require('fs')
const path = require('path')

// Mock the dependencies
jest.mock('fs')

// Mocking the config.js file to allow testing with smaller arrays of expected artifacts
jest.mock('../config.js', () => ({
GENERATED_PROJECTS_DIR: '../generated-projects',
EXPECTED_GENERATED_ARTIFACTS: {
'retail-app-demo': ['package.json', 'node_modules', 'config'],
'retail-app-ext': ['package.json', 'node_modules', 'overrides']
}
}))
jest.mock('./utils.js', () => ({
diffArrays: jest.fn()
}))

// Import the functions to test
const {diffArrays} = require('./utils.js')
const {validateGeneratedArtifacts} = require('./validate-generated-project.js')

describe('validateGeneratedArtifacts', () => {
beforeEach(() => {
jest.clearAllMocks()
})

test('resolves when all expected artifacts are present', async () => {
const project = 'retail-app-demo'
const expectedArtifacts = ['package.json', 'node_modules', 'config']
const actualArtifacts = ['package.json', 'node_modules', 'config', 'extra-file']

fs.readdirSync.mockReturnValue(actualArtifacts)
diffArrays.mockReturnValue([])

const result = await validateGeneratedArtifacts(project)

expect(fs.readdirSync).toHaveBeenCalledWith(
// path.sep is used to handle the platform-specific path separator. (Windows uses \ and other platforms use /)
expect.stringContaining(`generated-projects${path.sep}${project}`)
)
expect(diffArrays).toHaveBeenCalledWith(expectedArtifacts, actualArtifacts)
expect(result).toBe(`Successfully validated generated artifacts for: ${project} `)
})

test('rejects when artifacts are missing', async () => {
const project = 'retail-app-demo'
const actualArtifacts = ['package.json', 'node_modules']
const missingArtifacts = ['config']

fs.readdirSync.mockReturnValue(actualArtifacts)
diffArrays.mockReturnValue(missingArtifacts)

await expect(validateGeneratedArtifacts(project)).rejects.toBe(
`Generated project (${project}) is missing one or more artifacts: ${missingArtifacts}`
)
})

test('rejects when project directory does not exist', async () => {
const project = 'non-existent-project'
const error = new Error('ENOENT: no such file or directory')

fs.readdirSync.mockImplementation(() => {
throw error
})

await expect(validateGeneratedArtifacts(project)).rejects.toBe(
`Generated project (${project}) is missing one or more artifacts: ${error}`
)
})

test('handles project with no expected artifacts', async () => {
const project = 'unknown-project'
const actualArtifacts = ['some-file']

fs.readdirSync.mockReturnValue(actualArtifacts)
diffArrays.mockReturnValue([])

const result = await validateGeneratedArtifacts(project)

expect(diffArrays).toHaveBeenCalledWith([], actualArtifacts)
expect(result).toBe(`Successfully validated generated artifacts for: ${project} `)
})
})

// Since it requires files at runtime, we'll test the key validation logic
describe('validateExtensibilityConfig validation logic', () => {
test('validates Object.hasOwn usage for extensibility config', () => {
// Test the core validation logic that was fixed
const validConfig = {
ccExtensibility: {
extends: '@salesforce/retail-react-app',
overridesDir: 'overrides'
}
}

const invalidConfigMissingProperty = {
ccExtensibility: {
extends: '@salesforce/retail-react-app'
// missing overridesDir
}
}

const invalidConfigWrongExtends = {
ccExtensibility: {
extends: '@wrong/package',
overridesDir: 'overrides'
}
}

expect(Object.hasOwn(validConfig, 'ccExtensibility')).toBe(true)
expect(Object.hasOwn(validConfig.ccExtensibility, 'extends')).toBe(true)
expect(Object.hasOwn(validConfig.ccExtensibility, 'overridesDir')).toBe(true)

expect(Object.hasOwn(invalidConfigMissingProperty.ccExtensibility, 'overridesDir')).toBe(
false
)

const isValidConfig = (pkg) => {
return (
Object.hasOwn(pkg, 'ccExtensibility') &&
Object.hasOwn(pkg.ccExtensibility, 'extends') &&
Object.hasOwn(pkg.ccExtensibility, 'overridesDir') &&
pkg.ccExtensibility.extends === '@salesforce/retail-react-app' &&
pkg.ccExtensibility.overridesDir === 'overrides'
)
}

expect(isValidConfig(validConfig)).toBe(true)
expect(isValidConfig(invalidConfigMissingProperty)).toBe(false)
expect(isValidConfig(invalidConfigWrongExtends)).toBe(false)
})

test('validates template version matching logic', () => {
const pkg = {version: '1.0.0'}

const validateVersion = (pkg, templateVersion) => {
return !templateVersion || pkg.version === templateVersion
}

expect(validateVersion(pkg, undefined)).toBe(true)
expect(validateVersion(pkg, null)).toBe(true)
expect(validateVersion(pkg, '1.0.0')).toBe(true)
expect(validateVersion(pkg, '2.0.0')).toBe(false)
})
})
2 changes: 1 addition & 1 deletion e2e/tests/opentelemetry-b3-tracing.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test.beforeEach(async ({page}) => {
})
})

test.skip('should inject B3 headers when __server_timing param is passed', async ({page}) => {
test('should inject B3 headers when __server_timing param is passed', async ({page}) => {
const url = `${config.RETAIL_APP_HOME}?__server_timing=true`

const responseHeaders = []
Expand Down
8 changes: 4 additions & 4 deletions packages/commerce-sdk-react/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1326,8 +1326,8 @@ class Auth {
callback_uri: parameters.callback_uri,
hint: parameters.hint || 'cross_device',
locale: parameters.locale,
code_challenge: parameters.code_challenge,
idp_name: parameters.idp_name
idp_name: parameters.idp_name,
...(parameters.code_challenge && {code_challenge: parameters.code_challenge})
}
}

Expand Down Expand Up @@ -1357,8 +1357,8 @@ class Auth {
channel_id: parameters.channel_id || slasClient.clientConfig.parameters.siteId,
client_id: parameters.client_id || slasClient.clientConfig.parameters.clientId,
new_password: parameters.new_password,
code_verifier: parameters.code_verifier,
hint: parameters.hint
hint: parameters.hint,
code_verifier: parameters.code_verifier
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
/* eslint-disable @typescript-eslint/no-var-requires */
const sites = require('./sites.js')
const {parseCommerceAgentSettings} = require('./utils.js')
const {parseSettings} = require('./utils.js')

module.exports = {
app: {
Expand All @@ -23,9 +23,17 @@ module.exports = {
// Commerce shopping agent configuration for embedded messaging service
// This enables an agentic shopping experience in the application
// This property accepts either a JSON string or a plain JavaScript object.
// The value is set from the COMMERCE_AGENT_SETTINGS environment variable.
// If the COMMERCE_AGENT_SETTINGS environment variable is not set, the feature is disabled.
commerceAgent: parseCommerceAgentSettings(process.env.COMMERCE_AGENT_SETTINGS),
commerceAgent: parseSettings(process.env.COMMERCE_AGENT_SETTINGS) || {
enabled: 'false',
askAgentOnSearch: 'false',
embeddedServiceName: '',
embeddedServiceEndpoint: '',
scriptSourceUrl: '',
scrt2Url: '',
salesforceOrgId: '',
commerceOrgId: '',
siteId: ''
},
// Customize how your 'site' and 'locale' are displayed in the url.
url: {
{{#if answers.project.demo.enableDemoSettings}}
Expand Down
35 changes: 35 additions & 0 deletions packages/pwa-kit-create-app/assets/bootstrap/js/config/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2021, salesforce.com, 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
*/

/**
* Safely parses settings from either a JSON string or object
* @param {string|object} settings - The settings
* @returns {object} Parsed settings object
*/
function parseSettings(settings) {
// If settings is already an object, return it
if (typeof settings === 'object' && settings !== null) {
return settings
}

// If settings is a string, try to parse it
if (typeof settings === 'string') {
try {
return JSON.parse(settings)
} catch (error) {
console.warn('Invalid json format:', error.message)
return
}
}

console.warn('Cannot parse settings from:', settings)
return
}

module.exports = {
parseSettings
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
/* eslint-disable @typescript-eslint/no-var-requires */
const sites = require('./sites.js')
const {parseCommerceAgentSettings} = require('./utils.js')
const {parseSettings} = require('./utils.js')

module.exports = {
app: {
Expand All @@ -23,9 +23,17 @@ module.exports = {
// Commerce shopping agent configuration for embedded messaging service
// This enables an agentic shopping experience in the application
// This property accepts either a JSON string or a plain JavaScript object.
// The value is set from the COMMERCE_AGENT_SETTINGS environment variable.
// If the COMMERCE_AGENT_SETTINGS environment variable is not set, the feature is disabled.
commerceAgent: parseCommerceAgentSettings(process.env.COMMERCE_AGENT_SETTINGS),
commerceAgent: parseSettings(process.env.COMMERCE_AGENT_SETTINGS) || {
enabled: 'false',
askAgentOnSearch: 'false',
embeddedServiceName: '',
embeddedServiceEndpoint: '',
scriptSourceUrl: '',
scrt2Url: '',
salesforceOrgId: '',
commerceOrgId: '',
siteId: ''
},
// Customize settings for your url
url: {
{{#if answers.project.demo.enableDemoSettings}}
Expand Down
Loading
Loading