From 0abfcd1efda16bea54b5cdda008c8d536d568204 Mon Sep 17 00:00:00 2001 From: kzheng Date: Fri, 27 Jun 2025 15:26:22 -0700 Subject: [PATCH 1/4] @W-18670301 - added prettier and tuned tests --- package-lock.json | 17 ++- package.json | 3 +- .../scripts/trim-extensions.js | 3 + .../scripts/trim-extensions.test.js | 101 +++++++++++++++++- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index a78878f949..43d835ea65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,8 @@ "dependencies": { "@babel/parser": "^7.27.5", "@babel/traverse": "^7.27.4", - "node-fetch": "^2.6.9" + "node-fetch": "^2.6.9", + "prettier": "^3.6.2" }, "devDependencies": { "@playwright/test": "^1.49.0", @@ -7936,6 +7937,20 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", diff --git a/package.json b/package.json index 0d4094dafb..07a3573732 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "dependencies": { "@babel/parser": "^7.27.5", "@babel/traverse": "^7.27.4", - "node-fetch": "^2.6.9" + "node-fetch": "^2.6.9", + "prettier": "^3.6.2" } } diff --git a/packages/pwa-kit-create-app/scripts/trim-extensions.js b/packages/pwa-kit-create-app/scripts/trim-extensions.js index 8d1187dbb9..d961d234ac 100644 --- a/packages/pwa-kit-create-app/scripts/trim-extensions.js +++ b/packages/pwa-kit-create-app/scripts/trim-extensions.js @@ -11,6 +11,7 @@ const traverse = require('@babel/traverse').default const generate = require('@babel/generator').default const path = require('path') const pluginConfig = require('../assets/plugin-config') +const { execSync } = require('child_process') const removeComponentCandidates = [] // List of files that are candidates for removal, as a result of trimming. const SEPARATOR = path.sep // Use OS-specific path separator @@ -218,6 +219,8 @@ function processFile(filePath, plugins) { }).code // Replace the original file with the trimmed version fs.writeFileSync(filePath, output) + // prettify the file + execSync(`npx prettier --write ${filePath}`) console.log(`Updated file ${filePath}`) } catch (e) { console.error(`Error updating file ${filePath}: ${e.message}`) diff --git a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js index 47724e2612..f9242044d5 100644 --- a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js +++ b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js @@ -6,6 +6,7 @@ */ /* eslint-disable @typescript-eslint/no-var-requires */ const fs = require('fs') +const { execSync } = require('child_process') jest.mock('../assets/plugin-config', () => ({ plugins: { @@ -19,6 +20,37 @@ jest.mock('../assets/plugin-config', () => ({ })) jest.mock('fs') +jest.mock('child_process') + +// custom matcher to compare strings line by line with trimming +expect.extend({ + toEqualTrimmedLines(received, expected) { + const clean = str => + str + .split('\n') + .map(line => line.trim()) // Trim each line + .filter(line => line.length > 0) // Optional: remove empty lines + + const receivedLines = clean(received) + const expectedLines = clean(expected) + + const pass = this.equals(receivedLines, expectedLines) + + if (pass) { + return { + pass: true, + message: () => + `✅ Expected strings not to match line by line (but they did).\n\nExpected: ${this.utils.printExpected(expectedLines)}\nReceived: ${this.utils.printReceived(receivedLines)}`, + }; + } else { + return { + pass: false, + message: () => + `❌ Expected strings to match line by line (with trimming).\n\nExpected: ${this.utils.printExpected(expectedLines)}\nReceived: ${this.utils.printReceived(receivedLines)}`, + }; + } + }, + }) const trimExtensions = require('./trim-extensions') @@ -47,6 +79,7 @@ describe('trim-extensions', () => { } }) fs.unlinkSync.mockReturnValue(true) + execSync.mockReturnValue(true) }) it('handles OR operator correctly', () => { @@ -62,8 +95,9 @@ describe('trim-extensions', () => { trimExtensions('/mock/dir', {SFDC_EXT_featureA: true, SFDC_EXT_featureB: false}) expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - "const feature = 'Feature Enabled';" + expect.toEqualTrimmedLines("const feature = 'Feature Enabled';") ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') }) it('handles variable declarations correctly', () => { @@ -82,12 +116,13 @@ describe('trim-extensions', () => { expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - "const featureAFunc = () => 'Feature A';" + expect.toEqualTrimmedLines("const featureAFunc = () => 'Feature A';") ) expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), expect.not.stringContaining("const featureBFunc = () => 'Feature B';") ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') }) it('handles variable with ternary expressions correctly', () => { @@ -104,12 +139,13 @@ describe('trim-extensions', () => { expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - 'const showFeature = Feature_A;' + expect.toEqualTrimmedLines("const showFeature = Feature_A;") ) expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), expect.not.stringContaining('const showFeature = Feature_B') ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') }) it('handles return with ternary expressions correctly', () => { @@ -122,10 +158,56 @@ describe('trim-extensions', () => { trimExtensions('/mock/dir', {SFDC_EXT_featureA: true}) + const expected = ` + function test() { + return Feature_A; + } + ` expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - expect.stringContaining('return Feature_A') + expect.toEqualTrimmedLines(expected) ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + }) + + it('handles PropTypes declarations correctly', () => { + const code = ` + MyClass.PropTypes = { + name: PropTypes.string, + description: PropTypes.string + }; + SFDC_EXT_featureA && (MyClass.PropType = { + ...MyClass.PropType, + featureAProp: PropTypes.string + }); + SFDC_EXT_featureB && (MyClass.PropType = { + ...MyClass.PropType, + featureBProp: PropTypes.string + }); + ` + fs.readFileSync.mockReturnValue(code) + + trimExtensions('/mock/dir', {SFDC_EXT_featureA: true}) + + const expected = ` + MyClass.PropTypes = { + name: PropTypes.string, + description: PropTypes.string + }; + MyClass.PropType = { + ...MyClass.PropType, + featureAProp: PropTypes.string + }; + ` + expect(fs.writeFileSync).toHaveBeenCalledWith( + expect.any(String), + expect.toEqualTrimmedLines(expected) + ) + expect(fs.writeFileSync).not.toHaveBeenCalledWith( + expect.any(String), + expect.stringContaining('featureBProp: PropTypes.string') + ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') }) it('handles JSX elements in return statements correctly', () => { @@ -143,14 +225,23 @@ describe('trim-extensions', () => { trimExtensions('/mock/dir', {SFDC_EXT_featureA: true, SFDC_EXT_featureB: false}) + const expected = ` + function test() { + return ( +
+ +
); + } + ` expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - expect.stringContaining('') + expect.toEqualTrimmedLines(expected) ) expect(fs.writeFileSync).not.toHaveBeenCalledWith( expect.any(String), expect.stringContaining('') ) + expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') }) it('does not remove referenced imports', () => { From 9c70063a85d8755110b455423fc2912b7e479b04 Mon Sep 17 00:00:00 2001 From: kzheng Date: Fri, 27 Jun 2025 15:46:00 -0700 Subject: [PATCH 2/4] fixed lint errors --- .../scripts/trim-extensions.js | 2 +- .../scripts/trim-extensions.test.js | 84 +++++++++++-------- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/packages/pwa-kit-create-app/scripts/trim-extensions.js b/packages/pwa-kit-create-app/scripts/trim-extensions.js index d961d234ac..131e6f0e41 100644 --- a/packages/pwa-kit-create-app/scripts/trim-extensions.js +++ b/packages/pwa-kit-create-app/scripts/trim-extensions.js @@ -11,7 +11,7 @@ const traverse = require('@babel/traverse').default const generate = require('@babel/generator').default const path = require('path') const pluginConfig = require('../assets/plugin-config') -const { execSync } = require('child_process') +const {execSync} = require('child_process') const removeComponentCandidates = [] // List of files that are candidates for removal, as a result of trimming. const SEPARATOR = path.sep // Use OS-specific path separator diff --git a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js index f9242044d5..212bbadb5f 100644 --- a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js +++ b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js @@ -6,7 +6,7 @@ */ /* eslint-disable @typescript-eslint/no-var-requires */ const fs = require('fs') -const { execSync } = require('child_process') +const {execSync} = require('child_process') jest.mock('../assets/plugin-config', () => ({ plugins: { @@ -25,32 +25,36 @@ jest.mock('child_process') // custom matcher to compare strings line by line with trimming expect.extend({ toEqualTrimmedLines(received, expected) { - const clean = str => - str - .split('\n') - .map(line => line.trim()) // Trim each line - .filter(line => line.length > 0) // Optional: remove empty lines - - const receivedLines = clean(received) - const expectedLines = clean(expected) - - const pass = this.equals(receivedLines, expectedLines) - - if (pass) { - return { - pass: true, - message: () => - `✅ Expected strings not to match line by line (but they did).\n\nExpected: ${this.utils.printExpected(expectedLines)}\nReceived: ${this.utils.printReceived(receivedLines)}`, - }; - } else { - return { - pass: false, - message: () => - `❌ Expected strings to match line by line (with trimming).\n\nExpected: ${this.utils.printExpected(expectedLines)}\nReceived: ${this.utils.printReceived(receivedLines)}`, - }; - } - }, - }) + const clean = (str) => + str + .split('\n') + .map((line) => line.trim()) // Trim each line + .filter((line) => line.length > 0) // Optional: remove empty lines + + const receivedLines = clean(received) + const expectedLines = clean(expected) + + const pass = this.equals(receivedLines, expectedLines) + + if (pass) { + return { + pass: true, + message: () => + `✅ Expected strings not to match line by line (but they did).\n\nExpected: ${this.utils.printExpected( + expectedLines + )}\nReceived: ${this.utils.printReceived(receivedLines)}` + } + } else { + return { + pass: false, + message: () => + `❌ Expected strings to match line by line (with trimming).\n\nExpected: ${this.utils.printExpected( + expectedLines + )}\nReceived: ${this.utils.printReceived(receivedLines)}` + } + } + } +}) const trimExtensions = require('./trim-extensions') @@ -97,7 +101,9 @@ describe('trim-extensions', () => { expect.any(String), expect.toEqualTrimmedLines("const feature = 'Feature Enabled';") ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('handles variable declarations correctly', () => { @@ -122,7 +128,9 @@ describe('trim-extensions', () => { expect.any(String), expect.not.stringContaining("const featureBFunc = () => 'Feature B';") ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('handles variable with ternary expressions correctly', () => { @@ -139,13 +147,15 @@ describe('trim-extensions', () => { expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), - expect.toEqualTrimmedLines("const showFeature = Feature_A;") + expect.toEqualTrimmedLines('const showFeature = Feature_A;') ) expect(fs.writeFileSync).toHaveBeenCalledWith( expect.any(String), expect.not.stringContaining('const showFeature = Feature_B') ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('handles return with ternary expressions correctly', () => { @@ -167,7 +177,9 @@ describe('trim-extensions', () => { expect.any(String), expect.toEqualTrimmedLines(expected) ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('handles PropTypes declarations correctly', () => { @@ -207,7 +219,9 @@ describe('trim-extensions', () => { expect.any(String), expect.stringContaining('featureBProp: PropTypes.string') ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('handles JSX elements in return statements correctly', () => { @@ -241,7 +255,9 @@ describe('trim-extensions', () => { expect.any(String), expect.stringContaining('') ) - expect(execSync).toHaveBeenCalledWith('npx prettier --write /mock/dir/src/components/featureComponent.jsx') + expect(execSync).toHaveBeenCalledWith( + 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + ) }) it('does not remove referenced imports', () => { From 964ef17ac9457a9a4aaafc5f433ffdacf024615d Mon Sep 17 00:00:00 2001 From: kzheng Date: Sat, 28 Jun 2025 11:16:51 -0700 Subject: [PATCH 3/4] change log --- packages/pwa-kit-create-app/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pwa-kit-create-app/CHANGELOG.md b/packages/pwa-kit-create-app/CHANGELOG.md index b23ec2607b..de64d898f8 100644 --- a/packages/pwa-kit-create-app/CHANGELOG.md +++ b/packages/pwa-kit-create-app/CHANGELOG.md @@ -1,6 +1,7 @@ ## 4.0.0-extensibility-preview.5 - Deprecate V3 Extensibility and experimental V4 Extensibility (#2573) - Move extensibility logic to generator (#2573) +- Apply prettier to trimmed files (#2688) ## v3.10.0 (Feb 18, 2025) - Add Data Cloud API configuration to `default.js`. [#2318] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2229) From 7cade926771231ada1fadf7112b923712e7e6d53 Mon Sep 17 00:00:00 2001 From: kzheng Date: Mon, 30 Jun 2025 08:44:38 -0700 Subject: [PATCH 4/4] fixed windows path --- .../scripts/trim-extensions.test.js | 49 ++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js index 212bbadb5f..061b77e06c 100644 --- a/packages/pwa-kit-create-app/scripts/trim-extensions.test.js +++ b/packages/pwa-kit-create-app/scripts/trim-extensions.test.js @@ -7,6 +7,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ const fs = require('fs') const {execSync} = require('child_process') +const path = require('path') jest.mock('../assets/plugin-config', () => ({ plugins: { @@ -102,7 +103,13 @@ describe('trim-extensions', () => { expect.toEqualTrimmedLines("const feature = 'Feature Enabled';") ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) }) @@ -129,7 +136,13 @@ describe('trim-extensions', () => { expect.not.stringContaining("const featureBFunc = () => 'Feature B';") ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) }) @@ -154,7 +167,13 @@ describe('trim-extensions', () => { expect.not.stringContaining('const showFeature = Feature_B') ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) }) @@ -178,7 +197,13 @@ describe('trim-extensions', () => { expect.toEqualTrimmedLines(expected) ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) }) @@ -220,7 +245,13 @@ describe('trim-extensions', () => { expect.stringContaining('featureBProp: PropTypes.string') ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) }) @@ -256,7 +287,13 @@ describe('trim-extensions', () => { expect.stringContaining('') ) expect(execSync).toHaveBeenCalledWith( - 'npx prettier --write /mock/dir/src/components/featureComponent.jsx' + `npx prettier --write ${path.join( + '/mock', + 'dir', + 'src', + 'components', + 'featureComponent.jsx' + )}` ) })