Skip to content

Commit 54b0dba

Browse files
authored
chore: add more e2e tests W-19718256 (#256)
* chore: add e2e tests * fix: resolved the username * chore: add assertion for scratch and devhub * chore: add aliases for testing
1 parent 684aa4b commit 54b0dba

File tree

4 files changed

+283
-2
lines changed

4 files changed

+283
-2
lines changed

packages/mcp-provider-dx-core/src/tools/create_scratch_org.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import { directoryParam, usernameOrAliasParam } from '../shared/params.js';
4747
* - textResponse:
4848
*/
4949

50-
const createScratchOrgParams = z.object({
50+
export const createScratchOrgParams = z.object({
5151
directory: directoryParam,
5252
devHub: usernameOrAliasParam.describe(
5353
'The default devhub username, use the #get_username tool to get the default devhub if unsure',

packages/mcp-provider-dx-core/src/tools/list_all_orgs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { directoryParam } from '../shared/params.js';
3232
* - textResponse: List of configured Salesforce orgs
3333
*/
3434

35-
const listAllOrgsParamsSchema = z.object({
35+
export const listAllOrgsParamsSchema = z.object({
3636
directory: directoryParam,
3737
});
3838

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright 2025, Salesforce, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { expect } from 'chai';
18+
import { McpTestClient, DxMcpTransport } from '@salesforce/mcp-test-client';
19+
import { TestSession } from '@salesforce/cli-plugins-testkit';
20+
import { z } from 'zod';
21+
import { matchesAccessToken } from '@salesforce/core';
22+
import { createScratchOrgParams } from '../../src/tools/create_scratch_org.js';
23+
24+
describe('create_scratch_org', () => {
25+
const client = new McpTestClient({
26+
timeout: 120_000,
27+
});
28+
29+
const devHubUsername = process.env.TESTKIT_HUB_USERNAME as string;
30+
31+
let testSession: TestSession;
32+
let resolvedDevHubUsername: string;
33+
34+
const createScratchOrgSchema = {
35+
name: z.literal('create_scratch_org'),
36+
params: createScratchOrgParams,
37+
};
38+
39+
before(async () => {
40+
testSession = await TestSession.create({
41+
project: {
42+
name: 'MyTestProject',
43+
},
44+
devhubAuthStrategy: 'AUTO',
45+
});
46+
47+
const hubUsername = testSession.hubOrg?.username;
48+
resolvedDevHubUsername = hubUsername ?? devHubUsername;
49+
50+
if (!resolvedDevHubUsername) {
51+
throw new Error('No DevHub username available from TestSession or TESTKIT_HUB_USERNAME environment variable');
52+
}
53+
54+
const transport = DxMcpTransport({
55+
args: ['--orgs', 'ALLOW_ALL_ORGS', '--no-telemetry', '--toolsets', 'all', '--allow-non-ga-tools'],
56+
});
57+
58+
await client.connect(transport);
59+
});
60+
61+
after(async () => {
62+
if (client?.connected) {
63+
await client.disconnect();
64+
}
65+
if (testSession) {
66+
await testSession.clean();
67+
}
68+
});
69+
70+
it('should create a scratch org', async () => {
71+
const result = await client.callTool(createScratchOrgSchema, {
72+
name: 'create_scratch_org',
73+
params: {
74+
directory: testSession.project.dir,
75+
devHub: resolvedDevHubUsername,
76+
},
77+
});
78+
79+
expect(result.isError).to.be.false;
80+
expect(result.content.length).to.equal(1);
81+
expect(result.content[0].type).to.equal('text');
82+
83+
const responseText = result.content[0].text as string;
84+
expect(matchesAccessToken(responseText)).to.be.false;
85+
expect(responseText).to.include('Successfully created scratch org');
86+
});
87+
88+
it('should create scratch org asynchronously', async () => {
89+
const asyncResult = await client.callTool(createScratchOrgSchema, {
90+
name: 'create_scratch_org',
91+
params: {
92+
directory: testSession.project.dir,
93+
devHub: resolvedDevHubUsername,
94+
async: true,
95+
alias: 'test-async-org'
96+
},
97+
});
98+
expect(asyncResult.isError).to.be.false;
99+
expect(asyncResult.content.length).to.equal(1);
100+
expect(asyncResult.content[0].type).to.equal('text');
101+
102+
const asyncResponseText = asyncResult.content[0].text;
103+
expect(asyncResponseText).to.include('Successfully enqueued scratch org with job Id:');
104+
});
105+
106+
it('should create scratch org with optional parameters', async () => {
107+
const result = await client.callTool(createScratchOrgSchema, {
108+
name: 'create_scratch_org',
109+
params: {
110+
directory: testSession.project.dir,
111+
devHub: resolvedDevHubUsername,
112+
alias: 'test-custom-org',
113+
duration: 3,
114+
edition: 'developer',
115+
description: 'Test scratch org with custom parameters',
116+
orgName: 'Test Org Name'
117+
},
118+
});
119+
120+
expect(result.isError).to.be.false;
121+
expect(result.content.length).to.equal(1);
122+
expect(result.content[0].type).to.equal('text');
123+
124+
const responseText = result.content[0].text;
125+
expect(responseText).to.include('Successfully created scratch org');
126+
});
127+
128+
it('should handle invalid devHub username', async () => {
129+
const result = await client.callTool(createScratchOrgSchema, {
130+
name: 'create_scratch_org',
131+
params: {
132+
directory: testSession.project.dir,
133+
devHub: '[email protected]',
134+
alias: 'test-invalid-devhub'
135+
},
136+
});
137+
138+
expect(result.isError).to.be.true;
139+
expect(result.content.length).to.equal(1);
140+
expect(result.content[0].type).to.equal('text');
141+
142+
const responseText = result.content[0].text;
143+
expect(responseText).to.include('Failed to create org:');
144+
});
145+
});
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright 2025, Salesforce, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { expect } from 'chai';
18+
import { McpTestClient, DxMcpTransport } from '@salesforce/mcp-test-client';
19+
import { TestSession } from '@salesforce/cli-plugins-testkit';
20+
import { z } from 'zod';
21+
import { listAllOrgsParamsSchema } from '../../src/tools/list_all_orgs.js';
22+
23+
describe('list_all_orgs', () => {
24+
let testSession: TestSession;
25+
const orgAlias ='dreamhouseOrg';
26+
27+
const listAllOrgsSchema = {
28+
name: z.literal('list_all_orgs'),
29+
params: listAllOrgsParamsSchema,
30+
};
31+
32+
before(async () => {
33+
testSession = await TestSession.create({
34+
project: {
35+
name: 'MyTestProject',
36+
},
37+
scratchOrgs: [{ edition: 'developer', setDefault: true, alias: orgAlias }],
38+
devhubAuthStrategy: 'AUTO',
39+
});
40+
});
41+
42+
after(async () => {
43+
if (testSession) {
44+
await testSession.clean();
45+
}
46+
});
47+
48+
describe('with ALLOW_ALL_ORGS', () => {
49+
const client = new McpTestClient();
50+
51+
before(async () => {
52+
const transport = DxMcpTransport({
53+
args: ['--orgs', 'ALLOW_ALL_ORGS', '--toolsets', 'all', '--no-telemetry', '--allow-non-ga-tools'],
54+
});
55+
await client.connect(transport);
56+
});
57+
58+
after(async () => {
59+
if (client?.connected) {
60+
await client.disconnect();
61+
}
62+
});
63+
64+
it('should list all orgs', async () => {
65+
const result = await client.callTool(listAllOrgsSchema, {
66+
name: 'list_all_orgs',
67+
params: {
68+
directory: testSession.project.dir,
69+
},
70+
});
71+
72+
expect(result.isError).to.be.false;
73+
expect(result.content.length).to.equal(1);
74+
expect(result.content[0].type).to.equal('text');
75+
76+
const responseText = result.content[0].text;
77+
78+
expect(responseText).to.contain('"isScratchOrg": true');
79+
expect(responseText).to.contain('"isDevHub": true');
80+
expect(responseText).to.contain('List of configured Salesforce orgs:');
81+
});
82+
83+
it('should return error message when directory does not exist', async () => {
84+
const result = await client.callTool(listAllOrgsSchema, {
85+
name: 'list_all_orgs',
86+
params: {
87+
directory: '/nonexistent/directory/path',
88+
},
89+
});
90+
91+
expect(result.isError).to.be.true;
92+
expect(result.content.length).to.equal(1);
93+
expect(result.content[0].type).to.equal('text');
94+
95+
const responseText = result.content[0].text;
96+
expect(responseText).to.contain('Failed to list orgs');
97+
});
98+
});
99+
100+
describe('with DEFAULT_TARGET_ORG only', () => {
101+
const defaultOrgClient = new McpTestClient();
102+
103+
before(async () => {
104+
const transport = DxMcpTransport({
105+
args: ['--orgs', 'DEFAULT_TARGET_ORG', '--toolsets', 'all', '--no-telemetry', '--allow-non-ga-tools'],
106+
});
107+
await defaultOrgClient.connect(transport);
108+
});
109+
110+
after(async () => {
111+
if (defaultOrgClient?.connected) {
112+
await defaultOrgClient.disconnect();
113+
}
114+
});
115+
116+
it('should only list the default org', async () => {
117+
const result = await defaultOrgClient.callTool(listAllOrgsSchema, {
118+
name: 'list_all_orgs',
119+
params: {
120+
directory: testSession.project.dir,
121+
},
122+
});
123+
124+
expect(result.isError).to.be.false;
125+
expect(result.content.length).to.equal(1);
126+
expect(result.content[0].type).to.equal('text');
127+
128+
const responseText = result.content[0].text;
129+
130+
expect(responseText).to.contain('"isScratchOrg": true');
131+
expect(responseText).to.contain('"isDevHub": false');
132+
expect(responseText).to.contain('List of configured Salesforce orgs:');
133+
expect(responseText).to.contain(`"aliases": [\n "${orgAlias}"\n ]`);
134+
});
135+
});
136+
});

0 commit comments

Comments
 (0)