@salesforce/salesforcedx-vscode-test-tools
Version:
Test automation framework for Salesforce Extensions for VS Code
295 lines • 13.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.runCliCommand = runCliCommand;
exports.deleteScratchOrg = deleteScratchOrg;
exports.orgLoginSfdxUrl = orgLoginSfdxUrl;
exports.orgDisplay = orgDisplay;
exports.orgList = orgList;
exports.aliasList = aliasList;
exports.scratchOrgCreate = scratchOrgCreate;
exports.setAlias = setAlias;
exports.installJestUTToolsForLwc = installJestUTToolsForLwc;
exports.createUser = createUser;
exports.removeEscapedCharacters = removeEscapedCharacters;
exports.generateSfProject = generateSfProject;
const child_process_1 = require("child_process");
const core_1 = require("../core");
const environmentSettings_1 = require("../environmentSettings");
const retryUtils_1 = require("../retryUtils");
/**
* Runs a Salesforce CLI command with optional stdin input
* @param command - The SF CLI command to run
* @param args - Command arguments and options
* @returns Promise resolving to command results
*/
async function runCliCommand(command, ...args) {
const commandArgs = args.filter(arg => typeof arg === 'string');
const hadJsonFlag = commandArgs.some(arg => arg === '--json');
const options = args.find(arg => typeof arg !== 'string');
let message = `running CLI command ${command} ${commandArgs.join(' ')}`;
if (options) {
message += `\nspawn options: ${JSON.stringify(options)}`;
}
const logLevel = environmentSettings_1.EnvironmentSettings.getInstance().logLevel;
(0, core_1.log)(message);
// Extract stdin data if provided
const stdinData = options?.stdin;
// add NODE_ENV=production and remove stdin from spawn options
const spawnOptions = {
...(options ?? {}),
env: {
...process.env, // Ensure existing environment variables are included
NODE_ENV: 'production',
SF_LOG_LEVEL: logLevel,
...(options?.env ?? {}) // Ensure any additional env vars in options are included
},
// On Windows, use shell to resolve executable extensions (.exe, .cmd, .bat)
shell: process.platform === 'win32'
};
delete spawnOptions.stdin;
return new Promise((resolve, reject) => {
const sfProcess = (0, child_process_1.spawn)('sf', [command, ...commandArgs], spawnOptions);
let stdout = '';
let stderr = '';
sfProcess.stdout?.on('data', data => {
stdout += data.toString();
});
sfProcess.stderr?.on('data', data => {
stderr += data.toString();
});
sfProcess.on('close', code => {
// Post-command processing
const result = { stdout, stderr, exitCode: code ?? 0 };
result.stdout = hadJsonFlag ? removeEscapedCharacters(result.stdout) : result.stdout;
// Perform any necessary post-processing here
// For example, you can modify the result object or log additional information
(0, core_1.log)(`Command finished with exit code ${result.exitCode}`);
resolve(result);
});
sfProcess.on('error', err => {
reject(new Error(`Failed to start process: ${err.message}`));
});
// Handle stdin input if provided
if (stdinData) {
if (sfProcess.stdin) {
sfProcess.stdin.write(stdinData);
sfProcess.stdin.end();
}
else {
reject(new Error('Failed to write to stdin'));
}
}
});
}
/**
* Deletes a scratch org by alias name
* @param orgAliasName - The alias of the scratch org to delete
*/
async function deleteScratchOrg(orgAliasName) {
if (orgAliasName) {
// The Terminal view can be a bit unreliable, so directly call exec() instead:
const sfOrgDeleteResults = await runCliCommand('org:delete:scratch', '--target-org', orgAliasName, '--no-prompt');
if (sfOrgDeleteResults.exitCode > 0) {
(0, core_1.log)(`deleteScratchOrg for org ${orgAliasName} failed with exit code ${sfOrgDeleteResults.exitCode}.\nRaw stderr ${sfOrgDeleteResults.stderr}.`);
}
}
}
/**
* Logs into an org using an SFDX auth URL file
* @param authFilePath - Path to the auth file containing the SFDX URL
* @returns Results of the login command
* @throws Error if login fails
*/
async function orgLoginSfdxUrl() {
const sfdxAuthUrl = process.env.SFDX_AUTH_URL;
if (!sfdxAuthUrl) {
throw new Error('SFDX_AUTH_URL environment variable is not set');
}
const sfSfdxUrlStoreResult = await runCliCommand('org:login:sfdx-url', '-d', '--sfdx-url-stdin', { stdin: sfdxAuthUrl });
if (sfSfdxUrlStoreResult.exitCode > 0) {
(0, core_1.debug)('sfSfdxUrlStoreResult.exitCode = ' + sfSfdxUrlStoreResult.exitCode);
(0, core_1.debug)('sfSfdxUrlStoreResult.stdout = ' + sfSfdxUrlStoreResult.stdout);
throw new Error(`orgLoginSfdxUrl failed with exit code ${sfSfdxUrlStoreResult.exitCode}\nRaw stderr: ${sfSfdxUrlStoreResult.stderr}\nRaw stdout: ${sfSfdxUrlStoreResult.stdout}`);
}
(0, core_1.debug)(`orgLoginSfdxUrl results ${JSON.stringify(sfSfdxUrlStoreResult)}`);
return sfSfdxUrlStoreResult;
}
/**
* Displays information about a Salesforce org
* @param usernameOrAlias - Username or alias of the org to display
* @returns Results of the org display command
* @throws Error if the command fails
*/
async function orgDisplay(usernameOrAlias) {
if (!usernameOrAlias) {
throw new Error('No usernameOrAlias provided');
}
const sfOrgDisplayResult = await runCliCommand('org:display', '--target-org', usernameOrAlias, '--verbose', '--json');
if (sfOrgDisplayResult.exitCode > 0) {
const message = `sf org display failed with exit code: ${sfOrgDisplayResult.exitCode}.\n${sfOrgDisplayResult.stderr}`;
(0, core_1.log)(message);
throw new Error(message);
}
(0, core_1.debug)(`orgDisplay results ${JSON.stringify(sfOrgDisplayResult)}`);
return sfOrgDisplayResult;
}
/**
* Lists all Salesforce orgs
* @returns Results of the org list command
* @throws Error if the command fails
*/
async function orgList() {
const sfOrgListResult = await runCliCommand('org:list', '--json');
if (sfOrgListResult.exitCode > 0) {
const message = `org list failed with exit code ${sfOrgListResult.exitCode}\n stderr ${sfOrgListResult.stderr}`;
(0, core_1.log)(message);
throw new Error(message);
}
(0, core_1.debug)(`orgList results ${JSON.stringify(sfOrgListResult)}`);
return sfOrgListResult;
}
/**
* Lists all aliases
* @returns Results of the alias list command
* @throws Error if the command fails
*/
async function aliasList() {
const sfAliasListResult = await runCliCommand('alias:list', '--json');
if (sfAliasListResult.exitCode > 0) {
const message = `alias list failed with exit code ${sfAliasListResult.exitCode}\n stderr ${sfAliasListResult.stderr}`;
(0, core_1.log)(message);
throw new Error(message);
}
(0, core_1.debug)(`aliasList results ${JSON.stringify(sfAliasListResult)}`);
return sfAliasListResult;
}
/**
* Creates a scratch org and makes it the project default
* @param edition - The org edition to use (developer or enterprise)
* @param definitionFileOrNone - Path to the scratch org definition file or 'NONE'
* @param scratchOrgAliasName - Alias to assign to the scratch org
* @param durationDays - Number of days before the scratch org expires
* @returns Results of the scratch org creation command
* @throws Error if scratch org creation fails
*/
async function scratchOrgCreate(edition, definitionFileOrNone, scratchOrgAliasName, durationDays) {
(0, core_1.log)('calling "sf org:create:scratch"...');
const args = [
'--edition',
edition,
'--alias',
scratchOrgAliasName,
'--duration-days',
durationDays.toString(),
'--set-default',
'--wait',
'30',
'--json',
...(definitionFileOrNone !== 'NONE' ? ['--definition-file', definitionFileOrNone] : [])
];
const sfOrgCreateResult = await (0, retryUtils_1.retryOperation)(async () => {
return await runCliCommand('org:create:scratch', ...args);
});
if (sfOrgCreateResult.exitCode > 0) {
(0, core_1.log)(`create scratch org failed. Exit code: ${sfOrgCreateResult.exitCode}. \ncreate scratch org failed. Raw stderr: ${sfOrgCreateResult.stderr} \ncreate scratch org failed. Raw stdout: ${sfOrgCreateResult.stdout}`);
throw new Error(sfOrgCreateResult.stderr);
}
(0, core_1.log)(`..."sf org:create:scratch" finished`);
(0, core_1.debug)(`scratchOrgCreate results ${JSON.stringify(sfOrgCreateResult)}`);
return sfOrgCreateResult;
}
/**
* Sets an alias for a Salesforce org username
* @param devHubAliasName - The alias to set
* @param devHubUserName - The username to associate with the alias
* @returns Results of the alias set command
* @throws Error if alias setting fails
*/
async function setAlias(devHubAliasName, devHubUserName) {
const setAliasResult = await runCliCommand('alias:set', `${devHubAliasName}=${devHubUserName}`);
if (setAliasResult.exitCode > 0) {
(0, core_1.log)(`alias failed. Exit code: ${setAliasResult.exitCode}. \nRaw stderr: ${setAliasResult.stderr}`);
throw new Error(setAliasResult.stderr);
}
return setAliasResult;
}
/**
* Installs Jest testing tools for LWC
* @param projectFolder - Path to the project folder
* @throws Error if installation fails or project folder is undefined
*/
async function installJestUTToolsForLwc(projectFolder) {
(0, core_1.log)(`SetUp - Started Install @salesforce/sfdx-lwc-jest Node module...`);
if (!projectFolder) {
throw new Error('cannot setup lwc tests without a project folder.');
}
const command = 'npm install @lwc/eslint-plugin-lwc@^2.0.0 --save-dev --ignore-scripts && npm install --ignore-scripts && npm uninstall husky --force && npm install eslint@^8 --save-dev --ignore-scripts && npm install --save-dev --ignore-scripts && npm install @salesforce/sfdx-lwc-jest --save-dev --ignore-scripts';
return new Promise((resolve, reject) => {
(0, child_process_1.exec)(command, {
cwd: projectFolder,
env: {
...process.env,
HUSKY_SKIP_INSTALL: '1',
NPM_CONFIG_LEGACY_PEER_DEPS: 'true'
}
}, (error, stdout, stderr) => {
if (error) {
(0, core_1.log)(`Error with ${command}`);
reject(error);
return;
}
if (stderr) {
(0, core_1.log)(`Error stderr received for ${command}`);
(0, core_1.log)(`stderr: ${stderr}`);
}
(0, core_1.log)(stdout);
(0, core_1.log)(`...SetUp - Finished Install @salesforce/sfdx-lwc-jest Node module`);
resolve();
});
});
}
/**
* Creates a user in a Salesforce org
* @param systemAdminUserDefPath - Path to the user definition file
* @param targetOrg - The org where the user should be created
* @returns Results of the user creation command
* @throws Error if user creation fails or target org is undefined
*/
async function createUser(systemAdminUserDefPath, targetOrg) {
if (!targetOrg) {
throw new Error('cannot create user with target');
}
const sfOrgCreateUserResult = await runCliCommand('org:create:user', '--definition-file', systemAdminUserDefPath, '--target-org', targetOrg);
if (sfOrgCreateUserResult.exitCode > 0) {
(0, core_1.log)(`org create user failed Exit code: ${sfOrgCreateUserResult.exitCode}. \nRaw stderr: ${sfOrgCreateUserResult.stderr}`);
throw new Error(sfOrgCreateUserResult.stderr);
}
(0, core_1.debug)(`createUser results ${JSON.stringify(sfOrgCreateUserResult)}`);
return sfOrgCreateUserResult;
}
/**
* Removes escape characters from CLI command output
* @param result - The string to clean up
* @returns The string with escape characters removed
*/
function removeEscapedCharacters(result) {
const resultJson = result.replace(/\u001B\[\d\dm/g, '').replace(/\\n/g, '');
return resultJson;
}
/**
* Generates a Salesforce project
* @param name - The name of the project
* @param path - Optional path where the project should be created
* @param template - Optional template to use for project creation
* @returns Results of the project generation command
*/
async function generateSfProject(name, path, template) {
const sfProjectGenerateResult = await runCliCommand('project:generate', '--name', name, '--template', template ?? 'standard', ...(path ? ['-d', path] : []));
if (sfProjectGenerateResult.exitCode > 0) {
(0, core_1.log)(`project generate failed Exit code: ${sfProjectGenerateResult.exitCode}. \nRaw stderr: ${sfProjectGenerateResult.stderr}`);
throw new Error(sfProjectGenerateResult.stderr);
}
(0, core_1.debug)(`generateSfProject results ${JSON.stringify(sfProjectGenerateResult)}`);
return sfProjectGenerateResult;
}
//# sourceMappingURL=cliCommands.js.map