Skip to content

Commit d131a5e

Browse files
test: replace custom assert helper with direct imports
1 parent f16a215 commit d131a5e

31 files changed

Lines changed: 385 additions & 523 deletions

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ test/types/ # tsd type tests
171171
### Test Conventions
172172

173173
- **Test files** use `*.spec.ts` suffix
174-
- **Assertions** use the local `test/unit/helpers/assert.ts` compatibility helper backed by Node.js `assert` and Sinon assertions
174+
- **Assertions** in tests use direct `node:assert/strict` and `sinon.assert` imports
175175
- **Mocking** uses sinon (`stub`, `spy`, `fake`) and proxyquire for module-level dependency replacement
176176
- **Test config** lives in `package.json` scripts plus direct `node:test` imports in the spec files
177177
- **Where to put new tests:** Mirror the source structure. For `src/Foo.ts`, add `test/unit/Foo.spec.ts`. For `src/receivers/Bar.ts`, add `test/unit/receivers/Bar.spec.ts`.

test/unit/App/basic.spec.ts

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { LogLevel } from '@slack/logger';
2-
import { assert } from '../helpers/assert';
2+
import assert from 'node:assert/strict';
33
import sinon from 'sinon';
44
import { ErrorCode } from '../../../src/errors';
55
import SocketModeReceiver from '../../../src/receivers/SocketModeReceiver';
@@ -35,13 +35,17 @@ describe('App basic features', () => {
3535
const MockApp = importApp(overrides);
3636
const app = new MockApp({ token: '', signingSecret: '', port: 9999 });
3737
// biome-ignore lint/complexity/useLiteralKeys: reaching into private fields
38-
assert.propertyVal(app['receiver'], 'port', 9999);
38+
assert.ok(app['receiver'] && typeof app['receiver'] === 'object');
39+
assert.ok('port' in app['receiver']);
40+
assert.deepStrictEqual((app['receiver'] as unknown as Record<PropertyKey, unknown>)['port'], 9999);
3941
});
4042
it('should accept a port value under installerOptions', async () => {
4143
const MockApp = importApp(overrides);
4244
const app = new MockApp({ token: '', signingSecret: '', port: 7777, installerOptions: { port: 9999 } });
4345
// biome-ignore lint/complexity/useLiteralKeys: reaching into private fields
44-
assert.propertyVal(app['receiver'], 'port', 9999);
46+
assert.ok(app['receiver'] && typeof app['receiver'] === 'object');
47+
assert.ok('port' in app['receiver']);
48+
assert.deepStrictEqual((app['receiver'] as unknown as Record<PropertyKey, unknown>)['port'], 9999);
4549
});
4650
});
4751

@@ -66,7 +70,9 @@ describe('App basic features', () => {
6670
installationStore,
6771
});
6872
// biome-ignore lint/complexity/useLiteralKeys: reaching into private fields
69-
assert.propertyVal(app['receiver'], 'httpServerPort', 9999);
73+
assert.ok(app['receiver'] && typeof app['receiver'] === 'object');
74+
assert.ok('httpServerPort' in app['receiver']);
75+
assert.deepStrictEqual((app['receiver'] as unknown as Record<PropertyKey, unknown>)['httpServerPort'], 9999);
7076
});
7177
it('should accept a port value under installerOptions', async () => {
7278
const MockApp = importApp(overrides);
@@ -83,7 +89,9 @@ describe('App basic features', () => {
8389
installationStore,
8490
});
8591
// biome-ignore lint/complexity/useLiteralKeys: reaching into private fields
86-
assert.propertyVal(app['receiver'], 'httpServerPort', 9999);
92+
assert.ok(app['receiver'] && typeof app['receiver'] === 'object');
93+
assert.ok('httpServerPort' in app['receiver']);
94+
assert.deepStrictEqual((app['receiver'] as unknown as Record<PropertyKey, unknown>)['httpServerPort'], 9999);
8795
});
8896
});
8997

@@ -94,12 +102,12 @@ describe('App basic features', () => {
94102
const MockApp = importApp(overrides);
95103
const app = new MockApp({ token: '', signingSecret: '' });
96104
// TODO: verify that the fake bot ID and fake bot user ID are retrieved
97-
assert.instanceOf(app, MockApp);
105+
assert.ok(app instanceof MockApp);
98106
});
99107
it('should pass the given token to app.client', async () => {
100108
const MockApp = importApp(overrides);
101109
const app = new MockApp({ token: 'xoxb-foo-bar', signingSecret: '' });
102-
assert.isDefined(app.client);
110+
assert.notStrictEqual(app.client, undefined);
103111
assert.equal(app.client.token, 'xoxb-foo-bar');
104112
});
105113
});
@@ -115,7 +123,9 @@ describe('App basic features', () => {
115123
new MockApp({ signingSecret: '' });
116124
assert.fail();
117125
} catch (error) {
118-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
126+
assert.ok(error && typeof error === 'object');
127+
assert.ok('code' in error);
128+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
119129
}
120130
});
121131
it('should fail when both a token and authorize callback are specified', async () => {
@@ -125,7 +135,9 @@ describe('App basic features', () => {
125135
new MockApp({ token: '', authorize: authorizeCallback, signingSecret: '' });
126136
assert.fail();
127137
} catch (error) {
128-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
138+
assert.ok(error && typeof error === 'object');
139+
assert.ok('code' in error);
140+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
129141
assert(authorizeCallback.notCalled);
130142
}
131143
});
@@ -136,7 +148,9 @@ describe('App basic features', () => {
136148
new MockApp({ token: '', clientId: '', clientSecret: '', stateSecret: '', signingSecret: '' });
137149
assert.fail();
138150
} catch (error) {
139-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
151+
assert.ok(error && typeof error === 'object');
152+
assert.ok('code' in error);
153+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
140154
assert(authorizeCallback.notCalled);
141155
}
142156
});
@@ -153,7 +167,9 @@ describe('App basic features', () => {
153167
});
154168
assert.fail();
155169
} catch (error) {
156-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
170+
assert.ok(error && typeof error === 'object');
171+
assert.ok('code' in error);
172+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
157173
assert(authorizeCallback.notCalled);
158174
}
159175
});
@@ -172,7 +188,9 @@ describe('App basic features', () => {
172188
new MockApp({ authorize: noop });
173189
assert.fail();
174190
} catch (error) {
175-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
191+
assert.ok(error && typeof error === 'object');
192+
assert.ok('code' in error);
193+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
176194
}
177195
});
178196
it('should fail when both socketMode and a custom receiver are specified', async () => {
@@ -182,7 +200,9 @@ describe('App basic features', () => {
182200
new MockApp({ token: '', signingSecret: '', socketMode: true, receiver: fakeReceiver });
183201
assert.fail();
184202
} catch (error) {
185-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
203+
assert.ok(error && typeof error === 'object');
204+
assert.ok('code' in error);
205+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
186206
}
187207
});
188208
it('should succeed when both socketMode and SocketModeReceiver are specified', async () => {
@@ -221,7 +241,7 @@ describe('App basic features', () => {
221241
const dummyConvoStore = createFakeConversationStore();
222242
const MockApp = importApp(overrides);
223243
const app = new MockApp({ convoStore: dummyConvoStore, authorize: noop, signingSecret: '' });
224-
assert.instanceOf(app, MockApp);
244+
assert.ok(app instanceof MockApp);
225245
assert(fakeConversationContext.firstCall.calledWith(dummyConvoStore));
226246
});
227247
});
@@ -232,7 +252,9 @@ describe('App basic features', () => {
232252
new MockApp({ token: '', signingSecret: '', redirectUri: 'http://example.com/redirect' }); // eslint-disable-line no-new
233253
assert.fail();
234254
} catch (error) {
235-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
255+
assert.ok(error && typeof error === 'object');
256+
assert.ok('code' in error);
257+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
236258
}
237259
});
238260
it('should fail when missing installerOptions.redirectUriPath', async () => {
@@ -246,7 +268,9 @@ describe('App basic features', () => {
246268
});
247269
assert.fail();
248270
} catch (error) {
249-
assert.propertyVal(error, 'code', ErrorCode.AppInitializationError);
271+
assert.ok(error && typeof error === 'object');
272+
assert.ok('code' in error);
273+
assert.deepStrictEqual((error as unknown as Record<PropertyKey, unknown>)['code'], ErrorCode.AppInitializationError);
250274
}
251275
});
252276
});
@@ -307,23 +331,23 @@ describe('App basic features', () => {
307331
signingSecret: 'invalid-one',
308332
deferInitialization: true,
309333
});
310-
assert.instanceOf(app, MockApp);
334+
assert.ok(app instanceof MockApp);
311335
try {
312336
await app.start();
313337
assert.fail('The start() method should fail before init() call');
314338
} catch (err) {
315-
assert.propertyVal(
316-
err,
317-
'message',
318-
'This App instance is not yet initialized. Call `await App#init()` before starting the app.',
319-
);
339+
assert.ok(err && typeof err === 'object');
340+
assert.ok('message' in err);
341+
assert.deepStrictEqual((err as unknown as Record<PropertyKey, unknown>)['message'], 'This App instance is not yet initialized. Call `await App#init()` before starting the app.');
320342
}
321343
try {
322344
await app.init();
323345
assert.fail('The init() method should fail here');
324346
} catch (err) {
325347
console.log(err);
326-
assert.propertyVal(err, 'message', exception);
348+
assert.ok(err && typeof err === 'object');
349+
assert.ok('message' in err);
350+
assert.deepStrictEqual((err as unknown as Record<PropertyKey, unknown>)['message'], exception);
327351
}
328352
});
329353
});
@@ -337,8 +361,12 @@ describe('App basic features', () => {
337361
const fakeLogger = createFakeLogger();
338362
const MockApp = importApp(overrides);
339363
const app = new MockApp({ logger: fakeLogger, token: '', appToken: fakeAppToken, developerMode: true });
340-
assert.propertyVal(app, 'logLevel', LogLevel.DEBUG);
341-
assert.propertyVal(app, 'socketMode', true);
364+
assert.ok(app && typeof app === 'object');
365+
assert.ok('logLevel' in app);
366+
assert.deepStrictEqual((app as unknown as Record<PropertyKey, unknown>)['logLevel'], LogLevel.DEBUG);
367+
assert.ok(app && typeof app === 'object');
368+
assert.ok('socketMode' in app);
369+
assert.deepStrictEqual((app as unknown as Record<PropertyKey, unknown>)['socketMode'], true);
342370
});
343371
});
344372

test/unit/App/middlewares/arguments.spec.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { WebClient } from '@slack/web-api';
2-
import { assert } from '../../helpers/assert';
2+
import assert from 'node:assert/strict';
33
import sinon, { type SinonSpy } from 'sinon';
44
import { LogLevel } from '../../../../src/App';
55
import type { SayStreamFn } from '../../../../src/context/create-say-stream';
@@ -429,7 +429,7 @@ describe('App middleware and listener arguments', () => {
429429

430430
sinon.assert.calledThrice(fakeAck);
431431

432-
assert.isUndefined(app.client.token);
432+
assert.strictEqual(app.client.token, undefined);
433433
assert.equal(clients[0].token, 'xoxb-123');
434434
assert.equal(clients[1].token, 'xoxp-456');
435435
assert.equal(clients[2].token, 'xoxb-123');
@@ -546,8 +546,12 @@ describe('App middleware and listener arguments', () => {
546546
// Assert that each call to fakePostMessage had the right arguments
547547
for (const call of fakePostMessage.getCalls()) {
548548
const firstArg = call.args[0];
549-
assert.propertyVal(firstArg, 'text', dummyMessage);
550-
assert.propertyVal(firstArg, 'channel', dummyChannelId);
549+
assert.ok(firstArg && typeof firstArg === 'object');
550+
assert.ok('text' in firstArg);
551+
assert.deepStrictEqual((firstArg as unknown as Record<PropertyKey, unknown>)['text'], dummyMessage);
552+
assert.ok(firstArg && typeof firstArg === 'object');
553+
assert.ok('channel' in firstArg);
554+
assert.deepStrictEqual((firstArg as unknown as Record<PropertyKey, unknown>)['channel'], dummyChannelId);
551555
}
552556
sinon.assert.notCalled(fakeErrorHandler);
553557
});
@@ -573,8 +577,12 @@ describe('App middleware and listener arguments', () => {
573577
// Assert that each call to fakePostMessage had the right arguments
574578
for (const call of fakePostMessage.getCalls()) {
575579
const firstArg = call.args[0];
576-
assert.propertyVal(firstArg, 'channel', dummyChannelId);
577-
assert.propertyVal(firstArg, 'text', dummyMessage.text);
580+
assert.ok(firstArg && typeof firstArg === 'object');
581+
assert.ok('channel' in firstArg);
582+
assert.deepStrictEqual((firstArg as unknown as Record<PropertyKey, unknown>)['channel'], dummyChannelId);
583+
assert.ok(firstArg && typeof firstArg === 'object');
584+
assert.ok('text' in firstArg);
585+
assert.deepStrictEqual((firstArg as unknown as Record<PropertyKey, unknown>)['text'], dummyMessage.text);
578586
}
579587
sinon.assert.notCalled(fakeErrorHandler);
580588
});
@@ -635,7 +643,7 @@ describe('App middleware and listener arguments', () => {
635643

636644
const app = new MockApp({ receiver: fakeReceiver, authorize: sinon.fake.resolves(dummyAuthorizationResult) });
637645
app.use(async (args) => {
638-
assert.notProperty(args, 'say');
646+
assert.ok(!('say' in args));
639647
// If the above assertion fails, then it would throw an AssertionError and the following line will not be
640648
// called
641649
assertionAggregator();
@@ -679,7 +687,7 @@ describe('App middleware and listener arguments', () => {
679687
app.use(async (args) => {
680688
// biome-ignore lint/suspicious/noExplicitAny: test utility
681689
const sayStream = (args as any).sayStream as SayStreamFn;
682-
assert.isFunction(sayStream);
690+
assert.strictEqual(typeof sayStream, 'function');
683691
assertionAggregator();
684692
});
685693
app.error(fakeErrorHandler);
@@ -743,7 +751,7 @@ describe('App middleware and listener arguments', () => {
743751
const assertionAggregator = sinon.fake();
744752
const app = new MockApp({ receiver: fakeReceiver, authorize: sinon.fake.resolves(dummyAuthorizationResult) });
745753
app.use(async (args) => {
746-
assert.notProperty(args, 'sayStream');
754+
assert.ok(!('sayStream' in args));
747755
assertionAggregator();
748756
});
749757

@@ -773,7 +781,7 @@ describe('App middleware and listener arguments', () => {
773781
app.use(async (args) => {
774782
// biome-ignore lint/suspicious/noExplicitAny: test utility
775783
const setStatus = (args as any).setStatus as SetStatusFn;
776-
assert.isFunction(setStatus);
784+
assert.strictEqual(typeof setStatus, 'function');
777785
assertionAggregator();
778786
});
779787
app.error(fakeErrorHandler);
@@ -802,7 +810,7 @@ describe('App middleware and listener arguments', () => {
802810
const assertionAggregator = sinon.fake();
803811
const app = new MockApp({ receiver: fakeReceiver, authorize: sinon.fake.resolves(dummyAuthorizationResult) });
804812
app.use(async (args) => {
805-
assert.notProperty(args, 'setStatus');
813+
assert.ok(!('setStatus' in args));
806814
assertionAggregator();
807815
});
808816

@@ -959,7 +967,7 @@ describe('App middleware and listener arguments', () => {
959967
ack: fakeAck,
960968
});
961969

962-
assert.isTrue(called);
970+
assert.strictEqual(called, true);
963971
sinon.assert.calledOnce(fakeAck);
964972
});
965973

0 commit comments

Comments
 (0)