Skip to content

Commit 3910d11

Browse files
committed
fix: unit tests
1 parent 827f907 commit 3910d11

8 files changed

Lines changed: 754 additions & 5 deletions

File tree

.claude/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"permissions": {
3+
"allow": ["Bash(npx mocha *)", "Bash(npx nyc *)"]
4+
}
5+
}

src/common/utils.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,14 @@ export async function getFormattedDeployComponentsByAyncOpId(
182182
? await selectDeployComponentsForCheckDeployByAsynchOpId(con, asyncOpId)
183183
: await selectDeployComponentsByAsyncOpId(con, asyncOpId);
184184

185-
return components.map((component) => ({
186-
...component,
187-
Type: component.sf_devops__Source_Component__c.split(':')[0],
188-
Name: component.sf_devops__Source_Component__c.split(':')[1],
189-
}));
185+
components.forEach((component) => {
186+
// eslint-disable-next-line no-param-reassign
187+
component.Type = component.sf_devops__Source_Component__c.split(':')[0];
188+
// eslint-disable-next-line no-param-reassign
189+
component.Name = component.sf_devops__Source_Component__c.split(':')[1];
190+
});
191+
192+
return components;
190193
}
191194

192195
/**
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
import { expect, test } from '@oclif/test';
9+
import { TestContext } from '@salesforce/core/lib/testSetup';
10+
import * as sinon from 'sinon';
11+
import { Org } from '@salesforce/core';
12+
13+
describe('devops project list', () => {
14+
const $$ = new TestContext();
15+
let sandbox: sinon.SinonSandbox;
16+
17+
beforeEach(() => {
18+
sandbox = sinon.createSandbox();
19+
});
20+
21+
afterEach(() => {
22+
sandbox.restore();
23+
$$.restore();
24+
});
25+
26+
describe('returns projects', () => {
27+
test
28+
.stdout()
29+
.do(() => {
30+
const queryStub = sandbox.stub().resolves({
31+
records: [
32+
{ Id: '001', Name: 'Project A', Description: 'Desc A' },
33+
{ Id: '002', Name: 'Project B', Description: null },
34+
],
35+
});
36+
const mockOrg = {
37+
id: '1',
38+
getOrgId: () => '1',
39+
getConnection: () => ({ query: queryStub, getApiVersion: () => '65.0' }),
40+
};
41+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
42+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
43+
})
44+
.command(['devops:project:list', '--target-org', 'testOrg'])
45+
.it('lists projects when found', (ctx) => {
46+
expect(ctx.stdout).to.contain('Project A');
47+
});
48+
});
49+
50+
describe('no projects found', () => {
51+
test
52+
.stdout()
53+
.do(() => {
54+
const queryStub = sandbox.stub().resolves({ records: [] });
55+
const mockOrg = {
56+
id: '1',
57+
getOrgId: () => '1',
58+
getConnection: () => ({ query: queryStub, getApiVersion: () => '65.0' }),
59+
};
60+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
61+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
62+
})
63+
.command(['devops:project:list', '--target-org', 'testOrg'])
64+
.it('logs message when no projects', (ctx) => {
65+
expect(ctx.stdout).to.contain('No DevOps Center projects found');
66+
});
67+
});
68+
69+
describe('DevOps Center not enabled', () => {
70+
test
71+
.stdout()
72+
.stderr()
73+
.do(() => {
74+
const queryStub = sandbox.stub().rejects(new Error("sObject type 'DevopsProject' is not supported"));
75+
const mockOrg = {
76+
id: '1',
77+
getOrgId: () => '1',
78+
getConnection: () => ({ query: queryStub, getApiVersion: () => '65.0' }),
79+
};
80+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
81+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
82+
})
83+
.command(['devops:project:list', '--target-org', 'testOrg'])
84+
.catch(() => {})
85+
.it('shows DevOps Center not enabled error', (ctx) => {
86+
expect(ctx.stderr).to.contain('DevOps Center is not enabled');
87+
});
88+
});
89+
90+
describe('rethrows other errors', () => {
91+
test
92+
.stdout()
93+
.stderr()
94+
.do(() => {
95+
const queryStub = sandbox.stub().rejects(new Error('Network error'));
96+
const mockOrg = {
97+
id: '1',
98+
getOrgId: () => '1',
99+
getConnection: () => ({ query: queryStub, getApiVersion: () => '65.0' }),
100+
};
101+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
102+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
103+
})
104+
.command(['devops:project:list', '--target-org', 'testOrg'])
105+
.catch((err) => {
106+
expect(err.message).to.contain('Network error');
107+
})
108+
.it('rethrows non-DevOps errors', () => {});
109+
});
110+
});
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
import { expect, test } from '@oclif/test';
9+
import * as sinon from 'sinon';
10+
import { Org } from '@salesforce/core';
11+
import * as createWorkItemModule from '../../../../src/utils/createWorkItem';
12+
13+
describe('devops work-item create', () => {
14+
let sandbox: sinon.SinonSandbox;
15+
const mockConnection = { getApiVersion: () => '65.0' };
16+
const mockOrg = { id: '1', getOrgId: () => '1', getConnection: () => mockConnection };
17+
18+
beforeEach(() => {
19+
sandbox = sinon.createSandbox();
20+
});
21+
22+
afterEach(() => {
23+
sandbox.restore();
24+
});
25+
26+
describe('successful creation', () => {
27+
test
28+
.stdout()
29+
.do(() => {
30+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
31+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
32+
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
33+
success: true,
34+
workItemId: 'WI001',
35+
workItemName: 'WI-001',
36+
subject: 'Fix bug',
37+
});
38+
})
39+
.command([
40+
'devops:work-item:create',
41+
'--target-org',
42+
'testOrg',
43+
'--project-id',
44+
'PROJ001',
45+
'--subject',
46+
'Fix bug',
47+
])
48+
.it('logs success message', (ctx) => {
49+
expect(ctx.stdout).to.contain('Successfully created work item');
50+
});
51+
});
52+
53+
describe('successful creation with no workItemName', () => {
54+
test
55+
.stdout()
56+
.do(() => {
57+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
58+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
59+
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
60+
success: true,
61+
workItemId: 'WI001',
62+
subject: 'Fix bug',
63+
});
64+
})
65+
.command([
66+
'devops:work-item:create',
67+
'--target-org',
68+
'testOrg',
69+
'--project-id',
70+
'PROJ001',
71+
'--subject',
72+
'Fix bug',
73+
])
74+
.it('falls back to workItemId in log', (ctx) => {
75+
expect(ctx.stdout).to.contain('WI001');
76+
});
77+
});
78+
79+
describe('creation failure', () => {
80+
test
81+
.stdout()
82+
.stderr()
83+
.do(() => {
84+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
85+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
86+
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
87+
success: false,
88+
error: 'Not found',
89+
});
90+
})
91+
.command([
92+
'devops:work-item:create',
93+
'--target-org',
94+
'testOrg',
95+
'--project-id',
96+
'PROJ001',
97+
'--subject',
98+
'Fix bug',
99+
])
100+
.catch(() => {})
101+
.it('shows failure error', (ctx) => {
102+
expect(ctx.stderr).to.contain('Failed to create work item');
103+
});
104+
});
105+
106+
describe('DevOps Center not enabled', () => {
107+
test
108+
.stdout()
109+
.stderr()
110+
.do(() => {
111+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
112+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
113+
sandbox
114+
.stub(createWorkItemModule, 'createWorkItem')
115+
.rejects(new Error("sObject type 'WorkItem' is not supported"));
116+
})
117+
.command([
118+
'devops:work-item:create',
119+
'--target-org',
120+
'testOrg',
121+
'--project-id',
122+
'PROJ001',
123+
'--subject',
124+
'Fix bug',
125+
])
126+
.catch(() => {})
127+
.it('shows DevOps Center not enabled error', (ctx) => {
128+
expect(ctx.stderr).to.contain('DevOps Center is not enabled');
129+
});
130+
});
131+
132+
describe('rethrows other errors', () => {
133+
test
134+
.stdout()
135+
.stderr()
136+
.do(() => {
137+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
138+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
139+
sandbox.stub(createWorkItemModule, 'createWorkItem').rejects(new Error('Network error'));
140+
})
141+
.command([
142+
'devops:work-item:create',
143+
'--target-org',
144+
'testOrg',
145+
'--project-id',
146+
'PROJ001',
147+
'--subject',
148+
'Fix bug',
149+
])
150+
.catch((err) => {
151+
expect(err.message).to.contain('Network error');
152+
})
153+
.it('rethrows non-DevOps errors', () => {});
154+
});
155+
});
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
import { expect, test } from '@oclif/test';
9+
import * as sinon from 'sinon';
10+
import { Org } from '@salesforce/core';
11+
import * as workItemsModule from '../../../../src/utils/workItems';
12+
import { WorkItem } from '../../../../src/utils/types';
13+
14+
const MOCK_WORK_ITEM: WorkItem = {
15+
id: 'WI001',
16+
name: 'WI-001',
17+
subject: 'Fix bug',
18+
description: 'Details',
19+
status: 'In Progress',
20+
owner: 'USER001',
21+
DevopsProjectId: 'PROJ001',
22+
WorkItemBranch: 'feature/branch',
23+
TargetBranch: 'main',
24+
};
25+
26+
describe('devops work-item list', () => {
27+
let sandbox: sinon.SinonSandbox;
28+
const mockOrg = { id: '1', getOrgId: () => '1', getConnection: () => ({ getApiVersion: () => '65.0' }) };
29+
30+
beforeEach(() => {
31+
sandbox = sinon.createSandbox();
32+
});
33+
34+
afterEach(() => {
35+
sandbox.restore();
36+
});
37+
38+
describe('lists work items', () => {
39+
test
40+
.stdout()
41+
.do(() => {
42+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
43+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
44+
sandbox.stub(workItemsModule, 'fetchWorkItems').resolves([MOCK_WORK_ITEM]);
45+
})
46+
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', 'PROJ001'])
47+
.it('displays work items in table', (ctx) => {
48+
expect(ctx.stdout).to.contain('WI-001');
49+
});
50+
});
51+
52+
describe('no work items found', () => {
53+
test
54+
.stdout()
55+
.do(() => {
56+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
57+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
58+
sandbox.stub(workItemsModule, 'fetchWorkItems').resolves([]);
59+
})
60+
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', 'PROJ001'])
61+
.it('logs message when no work items', (ctx) => {
62+
expect(ctx.stdout).to.contain('No work items found');
63+
});
64+
});
65+
66+
describe('DevOps Center not enabled', () => {
67+
test
68+
.stdout()
69+
.stderr()
70+
.do(() => {
71+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
72+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
73+
sandbox.stub(workItemsModule, 'fetchWorkItems').rejects(new Error("sObject type 'WorkItem' is not supported"));
74+
})
75+
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', 'PROJ001'])
76+
.catch(() => {})
77+
.it('shows DevOps Center not enabled error', (ctx) => {
78+
expect(ctx.stderr).to.contain('DevOps Center is not enabled');
79+
});
80+
});
81+
82+
describe('rethrows other errors', () => {
83+
test
84+
.stdout()
85+
.stderr()
86+
.do(() => {
87+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
88+
sandbox.stub(Org, 'create' as any).returns(mockOrg);
89+
sandbox.stub(workItemsModule, 'fetchWorkItems').rejects(new Error('Network error'));
90+
})
91+
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', 'PROJ001'])
92+
.catch((err) => {
93+
expect(err.message).to.contain('Network error');
94+
})
95+
.it('rethrows non-DevOps errors', () => {});
96+
});
97+
});

0 commit comments

Comments
 (0)