Skip to content

Commit bf63989

Browse files
committed
fix: tests
1 parent f263971 commit bf63989

25 files changed

Lines changed: 1375 additions & 1338 deletions

.mocharc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"node-option": ["import=tsx"],
2+
"node-option": ["import=tsx", "loader=esmock"],
33
"recursive": true,
44
"reporter": "spec",
55
"timeout": 5000

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
"@salesforce/dev-scripts": "^11",
2222
"@salesforce/plugin-command-reference": "^3.1.38",
2323
"@salesforce/ts-sinon": "^1.4.30",
24+
"@types/chai": "^5.2.3",
25+
"chai": "^6.2.2",
2426
"eslint-plugin-sf-plugin": "^1.20.13",
27+
"esmock": "^2.7.6",
2528
"oclif": "^4",
2629
"tsx": "^4",
2730
"typescript": "^5.7.2"

test/.eslintrc.cjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,11 @@ module.exports = {
2121
'@typescript-eslint/no-empty-function': 'off',
2222
// Easily return a promise in a mocked method.
2323
'@typescript-eslint/require-await': 'off',
24+
// esmock returns untyped dynamic imports, so these are expected in tests.
25+
'@typescript-eslint/no-unsafe-assignment': 'off',
26+
'@typescript-eslint/no-unsafe-call': 'off',
27+
'@typescript-eslint/no-unsafe-member-access': 'off',
28+
'@typescript-eslint/no-unsafe-argument': 'off',
29+
'@typescript-eslint/no-unsafe-return': 'off',
2430
},
2531
};

test/commands/devops/work-item/create.test.ts

Lines changed: 75 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,31 @@
1414
* limitations under the License.
1515
*/
1616

17+
import esmock from 'esmock';
1718
import { expect, test } from '@oclif/test';
1819
import * as sinon from 'sinon';
1920
import { Org } from '@salesforce/core';
20-
import * as createWorkItemModule from '../../../../src/utils/createWorkItem.js';
2121

2222
describe('devops work-item create', () => {
2323
let sandbox: sinon.SinonSandbox;
24+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
25+
let CreateCommand: any;
2426
const mockConnection = { getApiVersion: () => '65.0' };
2527
const mockOrg = { id: '1', getOrgId: () => '1', getConnection: () => mockConnection };
28+
const createWorkItemStub = sinon.stub();
29+
30+
before(async () => {
31+
const mod = await esmock('../../../../src/commands/devops/work-item/create.js', {
32+
'../../../../src/utils/createWorkItem.js': {
33+
createWorkItem: createWorkItemStub,
34+
},
35+
});
36+
CreateCommand = mod.default;
37+
});
2638

2739
beforeEach(() => {
2840
sandbox = sinon.createSandbox();
41+
createWorkItemStub.reset();
2942
});
3043

3144
afterEach(() => {
@@ -35,52 +48,38 @@ describe('devops work-item create', () => {
3548
describe('successful creation', () => {
3649
test
3750
.stdout()
38-
.do(() => {
51+
.stderr()
52+
.it('logs success message', async (ctx) => {
3953
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4054
sandbox.stub(Org, 'create' as any).returns(mockOrg);
41-
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
55+
createWorkItemStub.resolves({
4256
success: true,
4357
workItemId: 'WI001',
4458
workItemName: 'WI-001',
4559
subject: 'Fix bug',
4660
});
47-
})
48-
.command([
49-
'devops:work-item:create',
50-
'--target-org',
51-
'testOrg',
52-
'--project-id',
53-
'1Qg000000000001',
54-
'--subject',
55-
'Fix bug',
56-
])
57-
.it('logs success message', (ctx) => {
61+
62+
await CreateCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001', '--subject', 'Fix bug']);
63+
5864
expect(ctx.stdout).to.contain('Successfully created work item');
5965
});
6066
});
6167

6268
describe('successful creation with no workItemName', () => {
6369
test
6470
.stdout()
65-
.do(() => {
71+
.stderr()
72+
.it('falls back to workItemId in log', async (ctx) => {
6673
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6774
sandbox.stub(Org, 'create' as any).returns(mockOrg);
68-
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
75+
createWorkItemStub.resolves({
6976
success: true,
7077
workItemId: 'WI001',
7178
subject: 'Fix bug',
7279
});
73-
})
74-
.command([
75-
'devops:work-item:create',
76-
'--target-org',
77-
'testOrg',
78-
'--project-id',
79-
'1Qg000000000001',
80-
'--subject',
81-
'Fix bug',
82-
])
83-
.it('falls back to workItemId in log', (ctx) => {
80+
81+
await CreateCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001', '--subject', 'Fix bug']);
82+
8483
expect(ctx.stdout).to.contain('WI001');
8584
});
8685
});
@@ -89,25 +88,27 @@ describe('devops work-item create', () => {
8988
test
9089
.stdout()
9190
.stderr()
92-
.do(() => {
91+
.it('shows failure error', async (ctx) => {
9392
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9493
sandbox.stub(Org, 'create' as any).returns(mockOrg);
95-
sandbox.stub(createWorkItemModule, 'createWorkItem').resolves({
94+
createWorkItemStub.resolves({
9695
success: false,
9796
error: 'Not found',
9897
});
99-
})
100-
.command([
101-
'devops:work-item:create',
102-
'--target-org',
103-
'testOrg',
104-
'--project-id',
105-
'1Qg000000000001',
106-
'--subject',
107-
'Fix bug',
108-
])
109-
.catch(() => {})
110-
.it('shows failure error', (ctx) => {
98+
99+
try {
100+
await CreateCommand.run([
101+
'--target-org',
102+
'testOrg',
103+
'--project-id',
104+
'1Qg000000000001',
105+
'--subject',
106+
'Fix bug',
107+
]);
108+
} catch (e) {
109+
// expected
110+
}
111+
111112
expect(ctx.stderr).to.contain('Failed to create work item');
112113
});
113114
});
@@ -116,24 +117,24 @@ describe('devops work-item create', () => {
116117
test
117118
.stdout()
118119
.stderr()
119-
.do(() => {
120+
.it('shows DevOps Center not enabled error', async (ctx) => {
120121
// eslint-disable-next-line @typescript-eslint/no-explicit-any
121122
sandbox.stub(Org, 'create' as any).returns(mockOrg);
122-
sandbox
123-
.stub(createWorkItemModule, 'createWorkItem')
124-
.rejects(new Error("sObject type 'WorkItem' is not supported"));
125-
})
126-
.command([
127-
'devops:work-item:create',
128-
'--target-org',
129-
'testOrg',
130-
'--project-id',
131-
'1Qg000000000001',
132-
'--subject',
133-
'Fix bug',
134-
])
135-
.catch(() => {})
136-
.it('shows DevOps Center not enabled error', (ctx) => {
123+
createWorkItemStub.rejects(new Error("sObject type 'WorkItem' is not supported"));
124+
125+
try {
126+
await CreateCommand.run([
127+
'--target-org',
128+
'testOrg',
129+
'--project-id',
130+
'1Qg000000000001',
131+
'--subject',
132+
'Fix bug',
133+
]);
134+
} catch (e) {
135+
// expected
136+
}
137+
137138
expect(ctx.stderr).to.contain("DevOps Center isn't enabled");
138139
});
139140
});
@@ -142,23 +143,24 @@ describe('devops work-item create', () => {
142143
test
143144
.stdout()
144145
.stderr()
145-
.do(() => {
146+
.it('rethrows non-DevOps errors', async () => {
146147
// eslint-disable-next-line @typescript-eslint/no-explicit-any
147148
sandbox.stub(Org, 'create' as any).returns(mockOrg);
148-
sandbox.stub(createWorkItemModule, 'createWorkItem').rejects(new Error('Network error'));
149-
})
150-
.command([
151-
'devops:work-item:create',
152-
'--target-org',
153-
'testOrg',
154-
'--project-id',
155-
'1Qg000000000001',
156-
'--subject',
157-
'Fix bug',
158-
])
159-
.catch((err) => {
160-
expect(err.message).to.contain('Network error');
161-
})
162-
.it('rethrows non-DevOps errors', () => {});
149+
createWorkItemStub.rejects(new Error('Network error'));
150+
151+
try {
152+
await CreateCommand.run([
153+
'--target-org',
154+
'testOrg',
155+
'--project-id',
156+
'1Qg000000000001',
157+
'--subject',
158+
'Fix bug',
159+
]);
160+
expect.fail('should have thrown');
161+
} catch (e: unknown) {
162+
expect((e as Error).message).to.contain('Network error');
163+
}
164+
});
163165
});
164166
});

test/commands/devops/work-item/list.test.ts

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17+
import esmock from 'esmock';
1718
import { expect, test } from '@oclif/test';
1819
import * as sinon from 'sinon';
1920
import { Org } from '@salesforce/core';
20-
import * as workItemsModule from '../../../../src/utils/workItems.js';
2121
import { WorkItem } from '../../../../src/utils/types.js';
2222

2323
const MOCK_WORK_ITEM: WorkItem = {
@@ -34,10 +34,23 @@ const MOCK_WORK_ITEM: WorkItem = {
3434

3535
describe('devops work-item list', () => {
3636
let sandbox: sinon.SinonSandbox;
37+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
38+
let ListCommand: any;
3739
const mockOrg = { id: '1', getOrgId: () => '1', getConnection: () => ({ getApiVersion: () => '65.0' }) };
40+
const fetchWorkItemsStub = sinon.stub();
41+
42+
before(async () => {
43+
const mod = await esmock('../../../../src/commands/devops/work-item/list.js', {
44+
'../../../../src/utils/workItems.js': {
45+
fetchWorkItems: fetchWorkItemsStub,
46+
},
47+
});
48+
ListCommand = mod.default;
49+
});
3850

3951
beforeEach(() => {
4052
sandbox = sinon.createSandbox();
53+
fetchWorkItemsStub.reset();
4154
});
4255

4356
afterEach(() => {
@@ -47,27 +60,29 @@ describe('devops work-item list', () => {
4760
describe('lists work items', () => {
4861
test
4962
.stdout()
50-
.do(() => {
63+
.stderr()
64+
.it('displays work items in table', async (ctx) => {
5165
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5266
sandbox.stub(Org, 'create' as any).returns(mockOrg);
53-
sandbox.stub(workItemsModule, 'fetchWorkItems').resolves([MOCK_WORK_ITEM]);
54-
})
55-
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', '1Qg000000000001'])
56-
.it('displays work items in table', (ctx) => {
67+
fetchWorkItemsStub.resolves([MOCK_WORK_ITEM]);
68+
69+
await ListCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001']);
70+
5771
expect(ctx.stdout).to.contain('WI-001');
5872
});
5973
});
6074

6175
describe('no work items found', () => {
6276
test
6377
.stdout()
64-
.do(() => {
78+
.stderr()
79+
.it('logs message when no work items', async (ctx) => {
6580
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6681
sandbox.stub(Org, 'create' as any).returns(mockOrg);
67-
sandbox.stub(workItemsModule, 'fetchWorkItems').resolves([]);
68-
})
69-
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', '1Qg000000000001'])
70-
.it('logs message when no work items', (ctx) => {
82+
fetchWorkItemsStub.resolves([]);
83+
84+
await ListCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001']);
85+
7186
expect(ctx.stdout).to.contain('No work items found');
7287
});
7388
});
@@ -76,14 +91,17 @@ describe('devops work-item list', () => {
7691
test
7792
.stdout()
7893
.stderr()
79-
.do(() => {
94+
.it('shows DevOps Center not enabled error', async (ctx) => {
8095
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8196
sandbox.stub(Org, 'create' as any).returns(mockOrg);
82-
sandbox.stub(workItemsModule, 'fetchWorkItems').rejects(new Error("sObject type 'WorkItem' is not supported"));
83-
})
84-
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', '1Qg000000000001'])
85-
.catch(() => {})
86-
.it('shows DevOps Center not enabled error', (ctx) => {
97+
fetchWorkItemsStub.rejects(new Error("sObject type 'WorkItem' is not supported"));
98+
99+
try {
100+
await ListCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001']);
101+
} catch (e) {
102+
// expected
103+
}
104+
87105
expect(ctx.stderr).to.contain("DevOps Center isn't enabled");
88106
});
89107
});
@@ -92,15 +110,17 @@ describe('devops work-item list', () => {
92110
test
93111
.stdout()
94112
.stderr()
95-
.do(() => {
113+
.it('rethrows non-DevOps errors', async () => {
96114
// eslint-disable-next-line @typescript-eslint/no-explicit-any
97115
sandbox.stub(Org, 'create' as any).returns(mockOrg);
98-
sandbox.stub(workItemsModule, 'fetchWorkItems').rejects(new Error('Network error'));
99-
})
100-
.command(['devops:work-item:list', '--target-org', 'testOrg', '--project-id', '1Qg000000000001'])
101-
.catch((err) => {
102-
expect(err.message).to.contain('Network error');
103-
})
104-
.it('rethrows non-DevOps errors', () => {});
116+
fetchWorkItemsStub.rejects(new Error('Network error'));
117+
118+
try {
119+
await ListCommand.run(['--target-org', 'testOrg', '--project-id', '1Qg000000000001']);
120+
expect.fail('should have thrown');
121+
} catch (e: unknown) {
122+
expect((e as Error).message).to.contain('Network error');
123+
}
124+
});
105125
});
106126
});

0 commit comments

Comments
 (0)