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
26 changes: 22 additions & 4 deletions src/commands/agent/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
selectedAgent = await Agent.init({ connection: conn, project: this.project!, apiNameOrId });
} else {
const previewableAgents = await Agent.listPreviewable(conn, this.project!);
const choices = previewableAgents.map((agent) => ({
name: agent.source === AgentSource.PUBLISHED ? `${agent.name} (Published)` : `${agent.name} (Agent Script)`,
value: agent,
}));
const choices = getPreviewChoices(previewableAgents);
const choice = await select<PreviewableAgent>({
message: 'Select an agent',
choices,
Expand Down Expand Up @@ -162,3 +159,24 @@ export const validateAgent = (agent: AgentData): boolean => {

return true;
};

export const sortPreviewableAgents = (agents: PreviewableAgent[]): PreviewableAgent[] =>
[...agents].sort((a, b) => {
if (a.source !== b.source) {
return a.source === AgentSource.SCRIPT ? -1 : 1;
}
return a.name.localeCompare(b.name);
});

export const getPreviewChoiceLabel = (agent: PreviewableAgent): string =>
agent.source === AgentSource.PUBLISHED
? `${agent.developerName ?? agent.name} (Published)`
: `${agent.name} (Agent Script)`;

export const getPreviewChoices = (
agents: PreviewableAgent[]
): Array<{ name: string; value: PreviewableAgent }> =>
sortPreviewableAgents(agents).map((agent) => ({
name: getPreviewChoiceLabel(agent),
value: agent,
}));
95 changes: 95 additions & 0 deletions test/commands/agent/preview/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
import { expect } from 'chai';
// import { Messages } from '@salesforce/core/messages';
import sinon from 'sinon';
import { AgentSource, type PreviewableAgent } from '@salesforce/agents';
import {
type AgentData,
UNSUPPORTED_AGENTS,
agentIsUnsupported,
agentIsInactive,
validateAgent,
sortPreviewableAgents,
getPreviewChoiceLabel,
getPreviewChoices,
} from '../../../../src/commands/agent/preview.js';

// TODO - pull in error messages
Expand Down Expand Up @@ -158,4 +162,95 @@ describe('Agent Preview', () => {
expect(publishedAgent.source).to.equal('published');
});
});

describe('sortPreviewableAgents', () => {
it('places script agents before published agents', () => {
const agents: PreviewableAgent[] = [
{ name: 'Published_Agent', source: AgentSource.PUBLISHED, developerName: 'Published_Agent' },
{ name: 'Script_Agent', source: AgentSource.SCRIPT },
];
const sorted = sortPreviewableAgents(agents);
expect(sorted[0].source).to.equal(AgentSource.SCRIPT);
expect(sorted[1].source).to.equal(AgentSource.PUBLISHED);
});

it('sorts alphabetically within the same source type', () => {
const agents: PreviewableAgent[] = [
{ name: 'Zebra_Agent', source: AgentSource.SCRIPT },
{ name: 'Alpha_Agent', source: AgentSource.SCRIPT },
{ name: 'Middle_Agent', source: AgentSource.SCRIPT },
];
const sorted = sortPreviewableAgents(agents);
expect(sorted.map((a) => a.name)).to.deep.equal(['Alpha_Agent', 'Middle_Agent', 'Zebra_Agent']);
});

it('sorts by type first, then alphabetically', () => {
const agents: PreviewableAgent[] = [
{ name: 'Zebra_Published', source: AgentSource.PUBLISHED, developerName: 'Zebra_Published' },
{ name: 'Beta_Script', source: AgentSource.SCRIPT },
{ name: 'Alpha_Published', source: AgentSource.PUBLISHED, developerName: 'Alpha_Published' },
{ name: 'Alpha_Script', source: AgentSource.SCRIPT },
];
const sorted = sortPreviewableAgents(agents);
expect(sorted.map((a) => a.name)).to.deep.equal([
'Alpha_Script',
'Beta_Script',
'Alpha_Published',
'Zebra_Published',
]);
});

it('does not mutate the original array', () => {
const agents: PreviewableAgent[] = [
{ name: 'B_Agent', source: AgentSource.SCRIPT },
{ name: 'A_Agent', source: AgentSource.SCRIPT },
];
sortPreviewableAgents(agents);
expect(agents[0].name).to.equal('B_Agent');
});
});

describe('getPreviewChoiceLabel', () => {
it('uses developerName for published agents', () => {
const agent: PreviewableAgent = {
name: 'My Friendly Label',
source: AgentSource.PUBLISHED,
developerName: 'My_Api_Name',
};
expect(getPreviewChoiceLabel(agent)).to.equal('My_Api_Name (Published)');
});

it('falls back to name when developerName is undefined for published agents', () => {
const agent: PreviewableAgent = {
name: 'Fallback_Name',
source: AgentSource.PUBLISHED,
};
expect(getPreviewChoiceLabel(agent)).to.equal('Fallback_Name (Published)');
});

it('uses name for script agents', () => {
const agent: PreviewableAgent = {
name: 'My_Script_Agent',
source: AgentSource.SCRIPT,
};
expect(getPreviewChoiceLabel(agent)).to.equal('My_Script_Agent (Agent Script)');
});
});

describe('getPreviewChoices', () => {
it('returns sorted choices with correct labels', () => {
const agents: PreviewableAgent[] = [
{ name: 'Published Label', source: AgentSource.PUBLISHED, developerName: 'Published_Api' },
{ name: 'Script_Agent', source: AgentSource.SCRIPT },
];
const choices = getPreviewChoices(agents);
expect(choices).to.have.length(2);
expect(choices[0].name).to.equal('Script_Agent (Agent Script)');
expect(choices[1].name).to.equal('Published_Api (Published)');
});

it('returns empty array for empty input', () => {
expect(getPreviewChoices([])).to.deep.equal([]);
});
});
});
Loading