Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
17 changes: 16 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
3 changes: 3 additions & 0 deletions packages/pwa-kit-create-app/scripts/trim-extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}`)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call prettier in a child process because it requires ES module, which this package doesn't support.

console.log(`Updated file ${filePath}`)
} catch (e) {
console.error(`Error updating file ${filePath}: ${e.message}`)
Expand Down
117 changes: 112 additions & 5 deletions packages/pwa-kit-create-app/scripts/trim-extensions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -19,6 +20,41 @@ 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')

Expand Down Expand Up @@ -47,6 +83,7 @@ describe('trim-extensions', () => {
}
})
fs.unlinkSync.mockReturnValue(true)
execSync.mockReturnValue(true)
})

it('handles OR operator correctly', () => {
Expand All @@ -62,7 +99,10 @@ 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'
)
})

Expand All @@ -82,12 +122,15 @@ 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', () => {
Expand All @@ -104,12 +147,15 @@ 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', () => {
Expand All @@ -122,9 +168,59 @@ 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.toEqualTrimmedLines(expected)
)
expect(execSync).toHaveBeenCalledWith(
'npx prettier --write /mock/dir/src/components/featureComponent.jsx'
)
})

it('handles PropTypes declarations correctly', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new test case to demonstrate how to extend PropType declaration

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.stringContaining('return Feature_A')
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'
)
})

Expand All @@ -143,14 +239,25 @@ describe('trim-extensions', () => {

trimExtensions('/mock/dir', {SFDC_EXT_featureA: true, SFDC_EXT_featureB: false})

const expected = `
function test() {
return (
<div>
<ComponentA />
</div>);
}
`
expect(fs.writeFileSync).toHaveBeenCalledWith(
expect.any(String),
expect.stringContaining('<ComponentA />')
expect.toEqualTrimmedLines(expected)
)
expect(fs.writeFileSync).not.toHaveBeenCalledWith(
expect.any(String),
expect.stringContaining('<ComponentB />')
)
expect(execSync).toHaveBeenCalledWith(
'npx prettier --write /mock/dir/src/components/featureComponent.jsx'
)
})

it('does not remove referenced imports', () => {
Expand Down
Loading