Skip to content

Commit cbac995

Browse files
committed
feat: use ts objects and not ejs templates over json for config files
1 parent df12496 commit cbac995

19 files changed

Lines changed: 224 additions & 630 deletions

File tree

packages/salesforcedx-aura-language-server/jest.config.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,6 @@ module.exports = {
2121
'^@salesforce/salesforcedx-lightning-lsp-common/providers/fileSystemDataProvider$':
2222
'<rootDir>/../salesforcedx-lightning-lsp-common/out/src/providers/fileSystemDataProvider',
2323
'^@salesforce/salesforcedx-lightning-lsp-common$': '<rootDir>/../salesforcedx-lightning-lsp-common/out/src/index',
24-
// Map relative imports from baseContext.js - these resolve from where baseContext.js is located
25-
// When baseContext.js does require("./resources/core/jsconfig-core.json"), it resolves from out/src/baseContext.js
26-
// We need to map these relative paths as Jest resolves them
27-
'^\\./resources/core/jsconfig-core\\.json$':
28-
'<rootDir>/../salesforcedx-lightning-lsp-common/out/src/resources/core/jsconfig-core.json',
29-
'^\\./resources/core/settings-core\\.json$':
30-
'<rootDir>/../salesforcedx-lightning-lsp-common/out/src/resources/core/settings-core.json',
31-
'^\\./resources/sfdx/jsconfig-sfdx\\.json$':
32-
'<rootDir>/../salesforcedx-lightning-lsp-common/out/src/resources/sfdx/jsconfig-sfdx.json',
3324
// Map tern plugin .js imports to .ts files for Jest (dynamic imports use .js but Jest needs .ts)
3425
// These are needed when ternServer.ts calls loadPlugins() which does dynamic imports
3526
'^\\./ternAura\\.js$': '<rootDir>/src/tern-server/ternAura',

packages/salesforcedx-aura-language-server/src/aura-indexer/__tests__/indexer.spec.ts

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,6 @@
66
*/
77

88
// Mock JSON imports from baseContext.ts - these are runtime require() calls in compiled code
9-
const mockJsonFromCommon = (relativePath: string) => {
10-
// eslint-disable-next-line @typescript-eslint/no-var-requires
11-
const fs = require('node:fs');
12-
// eslint-disable-next-line @typescript-eslint/no-var-requires
13-
const pathModule = require('node:path');
14-
let current = __dirname;
15-
while (!fs.existsSync(pathModule.join(current, 'package.json'))) {
16-
const parent = pathModule.resolve(current, '..');
17-
if (parent === current) break;
18-
current = parent;
19-
}
20-
const packagesDir = pathModule.resolve(current, '..');
21-
const filePath = pathModule.join(packagesDir, 'salesforcedx-lightning-lsp-common', 'src', relativePath);
22-
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
23-
return { default: content, ...content };
24-
};
25-
269
// Mock JSON imports from indexer.ts
2710
const mockJsonFromAuraServer = (relativePath: string) => {
2811
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -43,27 +26,6 @@ const mockJsonFromAuraServer = (relativePath: string) => {
4326
// Mock relative imports from baseContext.js - these need to match the exact paths Jest resolves when baseContext.js
4427
// executes require("./resources/..."). Since baseContext.js is in out/src/, the relative path
4528
// resolves to out/src/resources/... which we mock using paths relative to the test file.
46-
jest.mock(
47-
'../../../../salesforcedx-lightning-lsp-common/out/src/resources/core/jsconfig-core.json',
48-
() => mockJsonFromCommon('resources/core/jsconfig-core.json'),
49-
{
50-
virtual: true
51-
}
52-
);
53-
jest.mock(
54-
'../../../../salesforcedx-lightning-lsp-common/out/src/resources/core/settings-core.json',
55-
() => mockJsonFromCommon('resources/core/settings-core.json'),
56-
{
57-
virtual: true
58-
}
59-
);
60-
jest.mock(
61-
'../../../../salesforcedx-lightning-lsp-common/out/src/resources/sfdx/jsconfig-sfdx.json',
62-
() => mockJsonFromCommon('resources/sfdx/jsconfig-sfdx.json'),
63-
{
64-
virtual: true
65-
}
66-
);
6729

6830
// Mock JSON imports for aura indexer - from indexer.ts which is in src/aura-indexer/
6931
// So the relative path from indexer.ts is ../resources/, but from test file (src/aura-indexer/__tests__/) it's ../../resources/
@@ -82,8 +44,8 @@ import AuraIndexer from '../indexer';
8244
// Normalize paths for cross-platform test consistency
8345
const normalize = (start: string, p: string): string => {
8446
// Convert backslashes to forward slashes and normalize to POSIX format
85-
const normalizedStart = path.posix.normalize(start.replace(/\\/g, '/'));
86-
const normalizedP = path.posix.normalize(p.replace(/\\/g, '/'));
47+
const normalizedStart = path.posix.normalize(start.replaceAll('\\', '/'));
48+
const normalizedP = path.posix.normalize(p.replaceAll('\\', '/'));
8749

8850
// Handle Windows case-insensitive paths by comparing lowercase
8951
if (normalizedP.toLowerCase().startsWith(normalizedStart.toLowerCase())) {
@@ -104,8 +66,7 @@ describe('indexer parsing content', () => {
10466
await auraIndexer.configureAndIndex();
10567
context.addIndexingProvider({ name: 'aura', indexer: auraIndexer });
10668

107-
let markup = await context.findAllAuraMarkup();
108-
markup = markup.map(p => normalize(SFDX_WORKSPACE_ROOT, p)).sort();
69+
const markup = (await context.findAllAuraMarkup()).map(p => normalize(SFDX_WORKSPACE_ROOT, p)).toSorted();
10970
expect(markup).toMatchSnapshot();
11071
const tags = auraIndexer.getAuraTags();
11172
tags.forEach(taginfo => {
@@ -116,18 +77,18 @@ describe('indexer parsing content', () => {
11677
taginfo.location.uri = normalize(SFDX_WORKSPACE_ROOT, uriToFile(taginfo.location.uri));
11778
}
11879
if (taginfo.attributes) {
119-
taginfo.attributes = taginfo.attributes.sort((a, b) => a.name.localeCompare(b.name));
80+
taginfo.attributes = taginfo.attributes.toSorted((a, b) => a.name.localeCompare(b.name));
12081
for (const attribute of taginfo.attributes) {
12182
if (attribute.location?.uri) {
12283
attribute.location.uri = normalize(SFDX_WORKSPACE_ROOT, uriToFile(attribute.location.uri));
12384
}
12485
}
12586
}
12687
});
127-
const sortedTags = new Map([...tags.entries()].sort());
88+
const sortedTags = new Map([...tags.entries()].toSorted());
12889
expect(sortedTags).toMatchSnapshot();
12990

130-
const namespaces = auraIndexer.getAuraNamespaces().sort();
91+
const namespaces = auraIndexer.getAuraNamespaces().toSorted();
13192
expect(namespaces).toMatchSnapshot();
13293
});
13394

packages/salesforcedx-aura-language-server/src/messages/i18n.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,3 @@ export const messages = {
3030
invalid_browser_definition_message: 'Invalid browser definition: type=%s, isNull=%s, isUndefined=%s, keys=%s',
3131
invalid_ecmascript_definition_message: 'Invalid ecmascript definition: type=%s, isNull=%s, isUndefined=%s, keys=%s'
3232
} as const;
33-
34-
export type MessageKey = keyof typeof messages;

packages/salesforcedx-lightning-lsp-common/src/__tests__/context.test.ts

Lines changed: 1 addition & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
77
import * as path from 'node:path';
8-
import { processTemplate, getModulesDirs } from '../baseContext';
8+
import { getModulesDirs } from '../baseContext';
99
import '../../jest/matchers';
1010
import { FileSystemDataProvider } from '../providers/fileSystemDataProvider';
1111
import { normalizePath } from '../utils';
@@ -35,62 +35,6 @@ const CORE_WORKSPACE_PATH = normalizePath(
3535
);
3636

3737
// Mock JSON imports using fs.readFileSync since Jest cannot directly import JSON files
38-
jest.mock('../resources/core/jsconfig-core.json', () => {
39-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
40-
const fs = require('node:fs');
41-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
42-
const pathModule = require('node:path');
43-
// Always read from source: go up to package root (from out/src/__tests__ or src/__tests__)
44-
let current = __dirname;
45-
while (!fs.existsSync(pathModule.join(current, 'package.json'))) {
46-
const parent = pathModule.resolve(current, '..');
47-
if (parent === current) break; // reached filesystem root
48-
current = parent;
49-
}
50-
const filePath = pathModule.join(current, 'src', 'resources', 'core', 'jsconfig-core.json');
51-
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
52-
// JSON imports in TypeScript are treated as default exports
53-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
54-
return { default: content, ...content };
55-
});
56-
57-
jest.mock('../resources/core/settings-core.json', () => {
58-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
59-
const fs = require('node:fs');
60-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
61-
const pathModule = require('node:path');
62-
// Always read from source: go up to package root (from out/src/__tests__ or src/__tests__)
63-
let current = __dirname;
64-
while (!fs.existsSync(pathModule.join(current, 'package.json'))) {
65-
const parent = pathModule.resolve(current, '..');
66-
if (parent === current) break; // reached filesystem root
67-
current = parent;
68-
}
69-
const filePath = pathModule.join(current, 'src', 'resources', 'core', 'settings-core.json');
70-
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
71-
// JSON imports in TypeScript are treated as default exports
72-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
73-
return { default: content, ...content };
74-
});
75-
76-
jest.mock('../resources/sfdx/jsconfig-sfdx.json', () => {
77-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
78-
const fs = require('node:fs');
79-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment
80-
const pathModule = require('node:path');
81-
// Always read from source: go up to package root (from out/src/__tests__ or src/__tests__)
82-
let current = __dirname;
83-
while (!fs.existsSync(pathModule.join(current, 'package.json'))) {
84-
const parent = pathModule.resolve(current, '..');
85-
if (parent === current) break; // reached filesystem root
86-
current = parent;
87-
}
88-
const filePath = pathModule.join(current, 'src', 'resources', 'sfdx', 'jsconfig-sfdx.json');
89-
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
90-
// JSON imports in TypeScript are treated as default exports
91-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
92-
return { default: content, ...content };
93-
});
9438

9539
beforeAll(() => {
9640
// make sure test runner config doesn't overlap with test workspace
@@ -201,29 +145,6 @@ describe('WorkspaceContext', () => {
201145
}
202146
});
203147

204-
it('processTemplate() with EJS', async () => {
205-
const templateString = `
206-
{
207-
"compilerOptions": {
208-
"baseUrl": "<%= project_root %>",
209-
"paths": {
210-
"@/*": ["<%= project_root %>/src/*"]
211-
}
212-
}
213-
}`;
214-
215-
const variableMap = {
216-
project_root: '/path/to/project'
217-
};
218-
219-
// Use the standalone function
220-
const result = processTemplate(templateString, variableMap);
221-
222-
expect(result).toContain('"baseUrl": "/path/to/project"');
223-
expect(result).toContain('"@/*": ["/path/to/project/src/*"]');
224-
expect(result).not.toContain('${project_root}');
225-
});
226-
227148
it('configureSfdxProject()', async () => {
228149
const context = new WorkspaceContext(SFDX_WORKSPACE_PATH, sfdxFileSystemProvider);
229150
await context.initialize();

packages/salesforcedx-lightning-lsp-common/src/__tests__/testUtils.ts

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const PACKAGE_CORE_ALL_ROOT = resolve(
5353

5454
// Export the appropriate paths based on whether we're running from source or compiled code
5555
// Check for 'out' directory in path (cross-platform: Windows uses '\', Unix uses '/')
56-
const normalizedDirname = __dirname.replace(/\\/g, '/');
56+
const normalizedDirname = __dirname.replaceAll('\\', '/');
5757
const isCommonPackage = __dirname.includes('salesforcedx-lightning-lsp-common') && !normalizedDirname.includes('/out/');
5858

5959
// Normalize workspace roots to ensure consistent path format (especially Windows drive letter casing)
@@ -554,31 +554,6 @@ export const populateFileSystemProvider = (
554554
);
555555
}
556556

557-
// Add template files for SFDX configuration
558-
const jsconfigSfdxTemplate = JSON.stringify({
559-
compilerOptions: {
560-
experimentalDecorators: true,
561-
baseUrl: '.',
562-
paths: {
563-
'c/*': ['*']
564-
}
565-
},
566-
include: ['**/*', '<%= project_root %>/.sfdx/typings/lwc/**/*.d.ts'],
567-
typeAcquisition: {
568-
include: ['jest']
569-
}
570-
});
571-
572-
const jsconfigSfdxPath = normalizePath(join(__dirname, '..', 'resources', 'sfdx', 'jsconfig-sfdx.json'));
573-
fileSystemProvider.updateFileStat(jsconfigSfdxPath, {
574-
type: 'file',
575-
exists: true,
576-
ctime: 0,
577-
mtime: 0,
578-
size: jsconfigSfdxTemplate.length
579-
});
580-
fileSystemProvider.updateFileContent(jsconfigSfdxPath, jsconfigSfdxTemplate);
581-
582557
// Add typings files that the test expects to be created
583558
const ldsTypingsPath = normalizePath(join(__dirname, '..', 'resources', 'sfdx', 'lds.d.ts'));
584559
const ldsTypingsContent = 'declare module "@salesforce/lds" { /* LDS types */ }';
@@ -624,53 +599,6 @@ export const populateFileSystemProvider = (
624599
});
625600
fileSystemProvider.updateFileContent(apexTypingsPath, apexTypingsContent);
626601

627-
// Add Core template files
628-
const jsconfigCoreTemplate = JSON.stringify({
629-
compilerOptions: {
630-
experimentalDecorators: true,
631-
baseUrl: '.',
632-
paths: {
633-
'c/*': ['*']
634-
}
635-
},
636-
include: ['**/*', '<%= project_root %>/.vscode/typings/lwc/**/*.d.ts'],
637-
typeAcquisition: {
638-
include: ['jest']
639-
}
640-
});
641-
642-
const jsconfigCorePath = normalizePath(join(__dirname, '..', 'resources', 'core', 'jsconfig-core.json'));
643-
fileSystemProvider.updateFileStat(jsconfigCorePath, {
644-
type: 'file',
645-
exists: true,
646-
ctime: 0,
647-
mtime: 0,
648-
size: jsconfigCoreTemplate.length
649-
});
650-
fileSystemProvider.updateFileContent(jsconfigCorePath, jsconfigCoreTemplate);
651-
652-
// Add Core settings template
653-
const settingsCoreTemplate = JSON.stringify({
654-
'files.watcherExclude': {
655-
'**/.git/objects/**': true,
656-
'**/.git/subtree-cache/**': true,
657-
'**/node_modules/**': true
658-
},
659-
'perforce.client': 'username-localhost-blt',
660-
'perforce.user': 'username',
661-
'perforce.port': 'ssl:host:port'
662-
});
663-
664-
const settingsCorePath = normalizePath(join(__dirname, '..', 'resources', 'core', 'settings-core.json'));
665-
fileSystemProvider.updateFileStat(settingsCorePath, {
666-
type: 'file',
667-
exists: true,
668-
ctime: 0,
669-
mtime: 0,
670-
size: settingsCoreTemplate.length
671-
});
672-
fileSystemProvider.updateFileContent(settingsCorePath, settingsCoreTemplate);
673-
674602
// Add Core typings files for Core workspaces
675603
// For CORE_PARTIAL, the typings should be in the parent directory (CORE_ALL_ROOT)
676604
if (structure === CORE_PARTIAL_WORKSPACE_STRUCTURE) {

0 commit comments

Comments
 (0)