Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@salesforce/core": "^8.23.7",
"@salesforce/kit": "^3.2.3",
"@salesforce/sf-plugins-core": "^12.2.6",
"@salesforce/source-deploy-retrieve": "^12.31.0",
"@salesforce/source-deploy-retrieve": "^12.31.2",
"@salesforce/types": "^1.5.0",
"ansis": "^3.3.2",
"fast-xml-parser": "^4.5.1",
Expand Down
231 changes: 119 additions & 112 deletions test/nuts/shared-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { join } from 'node:path';
import { Duration, TestSession } from '@salesforce/cli-plugins-testkit';
import { ComponentSetBuilder } from '@salesforce/source-deploy-retrieve';
import { Org, User } from '@salesforce/core';
import { Org, SfError, User } from '@salesforce/core';
import { sleep } from '@salesforce/kit';

/* eslint-disable no-console */
Expand All @@ -44,122 +44,129 @@ export async function getTestSession(): Promise<TestSession> {
}

// Create the TestSession (only once, even if called from multiple test files simultaneously)
// @ts-expect-error it can throw an error
testSessionPromise = (async (): Promise<TestSession> => {
console.log('Creating shared TestSession with scratch org...');
const session = await TestSession.create({
project: {
sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
},
devhubAuthStrategy: 'AUTO',
scratchOrgs: [
{
alias: 'default',
setDefault: true,
config: 'config/project-scratch-def.json',
try {
console.log('Creating shared TestSession with scratch org...');
const session = await TestSession.create({
project: {
sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
},
],
});

testSession = session;
console.log('TestSession created successfully');

// Get the scratch org username and assign permission set
const orgs = session.orgs;
const defaultOrg = orgs.get('default');

if (orgs && orgs.size > 0) {
if (defaultOrg?.username) {
console.log(`Using scratch org: ${defaultOrg.username}`);
const org = await Org.create({ aliasOrUsername: defaultOrg.username });
const connection = org.getConnection();

// assign the EinsteinGPTPromptTemplateManager to the scratch org admin user
const queryResult = await connection.singleRecordQuery<{ Id: string; Name: string }>(
`SELECT Id, Name FROM User WHERE Username='${defaultOrg.username}'`
);
const user = await User.create({ org });
await user.assignPermissionSets(queryResult.Id, ['EinsteinGPTPromptTemplateManager']);
console.log(`Permission set assigned to scratch org user: ${queryResult.Name}`);
// Create a new agent user with required permission sets
console.log('Creating agent user...');

// Get the 'Einstein Agent User' profile
const profileResult = await connection.singleRecordQuery<{ Id: string }>(
"SELECT Id FROM Profile WHERE Name='Einstein Agent User'"
);

// Generate a unique username using timestamp to avoid duplicates
const timestamp = Date.now();
const domain = defaultOrg.username.split('@')[1];
agentUsername = `agent.user.${timestamp}@${domain}`;
const agentUserRecord = await connection.sobject('User').create({
FirstName: 'Agent',
LastName: 'User',
Alias: 'agentusr',
Email: agentUsername,
Username: agentUsername,
ProfileId: profileResult.Id,
TimeZoneSidKey: 'America/Los_Angeles',
LocaleSidKey: 'en_US',
EmailEncodingKey: 'UTF-8',
LanguageLocaleKey: 'en_US',
});

if (!agentUserRecord.success || !agentUserRecord.id) {
throw new Error(`Failed to create agent user: ${agentUserRecord.errors?.join(', ')}`);
}

const agentUserId = agentUserRecord.id;
console.log(`Agent user created: ${agentUsername} (${agentUserId})`);

// Assign permission sets to the agent user individually to identify any failures
const permissionSets = [
'AgentforceServiceAgentBase',
'AgentforceServiceAgentUser',
'EinsteinGPTPromptTemplateUser',
];

// I had issues assigning all permission sets in one pass, assign individually for now
for (const permissionSet of permissionSets) {
// eslint-disable-next-line no-await-in-loop
await user.assignPermissionSets(agentUserId, [permissionSet]);
console.log(`Permission set assigned: ${permissionSet}`);
}
console.log('Permission set assignment completed');

// Set environment variable for string replacement
process.env.AGENT_USER_USERNAME = agentUsername;

console.log('deploying metadata (no AiEvaluationDefinition)');

const cs1 = await ComponentSetBuilder.build({
manifest: {
manifestPath: join(testSession.project.dir, 'noTest.xml'),
directoryPaths: [testSession.homeDir],
devhubAuthStrategy: 'AUTO',
scratchOrgs: [
{
alias: 'default',
setDefault: true,
config: 'config/project-scratch-def.json',
},
});
const deploy1 = await cs1.deploy({ usernameOrConnection: defaultOrg.username });
await deploy1.pollStatus({ frequency: Duration.seconds(10) });

console.log('deploying metadata (AiEvaluationDefinition)');

const cs2 = await ComponentSetBuilder.build({
manifest: {
manifestPath: join(testSession.project.dir, 'test.xml'),
directoryPaths: [testSession.homeDir],
},
});
const deploy2 = await cs2.deploy({ usernameOrConnection: defaultOrg.username });
await deploy2.pollStatus({ frequency: Duration.seconds(10) });
],
});

testSession = session;
console.log('TestSession created successfully');

// Get the scratch org username and assign permission set
const orgs = session.orgs;
const defaultOrg = orgs.get('default');

if (orgs && orgs.size > 0) {
if (defaultOrg?.username) {
console.log(`Using scratch org: ${defaultOrg.username}`);
const org = await Org.create({ aliasOrUsername: defaultOrg.username });
const connection = org.getConnection();

// assign the EinsteinGPTPromptTemplateManager to the scratch org admin user
const queryResult = await connection.singleRecordQuery<{ Id: string; Name: string }>(
`SELECT Id, Name FROM User WHERE Username='${defaultOrg.username}'`
);
const user = await User.create({ org });
await user.assignPermissionSets(queryResult.Id, ['EinsteinGPTPromptTemplateManager']);
console.log(`Permission set assigned to scratch org user: ${queryResult.Name}`);
// Create a new agent user with required permission sets
console.log('Creating agent user...');

// Get the 'Einstein Agent User' profile
const profileResult = await connection.singleRecordQuery<{ Id: string }>(
"SELECT Id FROM Profile WHERE Name='Einstein Agent User'"
);

// Generate a unique username using timestamp to avoid duplicates
const timestamp = Date.now();
const domain = defaultOrg.username.split('@')[1];
agentUsername = `agent.user.${timestamp}@${domain}`;
const agentUserRecord = await connection.sobject('User').create({
FirstName: 'Agent',
LastName: 'User',
Alias: 'agentusr',
Email: agentUsername,
Username: agentUsername,
ProfileId: profileResult.Id,
TimeZoneSidKey: 'America/Los_Angeles',
LocaleSidKey: 'en_US',
EmailEncodingKey: 'UTF-8',
LanguageLocaleKey: 'en_US',
});

if (!agentUserRecord.success || !agentUserRecord.id) {
throw new Error(`Failed to create agent user: ${agentUserRecord.errors?.join(', ')}`);
}

const agentUserId = agentUserRecord.id;
console.log(`Agent user created: ${agentUsername} (${agentUserId})`);

// Assign permission sets to the agent user individually to identify any failures
const permissionSets = [
'AgentforceServiceAgentBase',
'AgentforceServiceAgentUser',
'EinsteinGPTPromptTemplateUser',
];

// I had issues assigning all permission sets in one pass, assign individually for now
for (const permissionSet of permissionSets) {
// eslint-disable-next-line no-await-in-loop
await user.assignPermissionSets(agentUserId, [permissionSet]);
console.log(`Permission set assigned: ${permissionSet}`);
}
console.log('Permission set assignment completed');

// Set environment variable for string replacement
process.env.AGENT_USER_USERNAME = agentUsername;

console.log('deploying metadata (no AiEvaluationDefinition)');

const cs1 = await ComponentSetBuilder.build({
manifest: {
manifestPath: join(testSession.project.dir, 'noTest.xml'),
directoryPaths: [testSession.homeDir],
},
});
const deploy1 = await cs1.deploy({ usernameOrConnection: defaultOrg.username });
await deploy1.pollStatus({ frequency: Duration.seconds(10) });

console.log('deploying metadata (AiEvaluationDefinition)');

const cs2 = await ComponentSetBuilder.build({
manifest: {
manifestPath: join(testSession.project.dir, 'test.xml'),
directoryPaths: [testSession.homeDir],
},
});
const deploy2 = await cs2.deploy({ usernameOrConnection: defaultOrg.username });
await deploy2.pollStatus({ frequency: Duration.seconds(10) });
}
}
}

// Wait for org to be ready - longer wait on Windows CI where things can be slower
const isWindows = process.platform === 'win32';
const waitTime = isWindows ? 10 * 60 * 1000 : 5 * 60 * 1000; // 10 minutes on Windows, 5 minutes otherwise
console.log(`waiting ${waitTime / 1000 / 60} minutes for org to be ready (platform: ${process.platform})`);
await sleep(waitTime);
return session;
// Wait for org to be ready - longer wait on Windows CI where things can be slower
const isWindows = process.platform === 'win32';
const waitTime = isWindows ? 10 * 60 * 1000 : 5 * 60 * 1000; // 10 minutes on Windows, 5 minutes otherwise
console.log(`waiting ${waitTime / 1000 / 60} minutes for org to be ready (platform: ${process.platform})`);
await sleep(waitTime);
return session;
} catch (e) {
console.log('XXXXXX ERROR XXXXXXX');
console.dir(SfError.wrap(e).toObject());
void Promise.reject(e);
}
})();

return testSessionPromise;
Expand Down
Loading
Loading