novaapp-sdk 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,689 @@
1
+ import { al as Message, ae as InteractionType, ac as Interaction, ai as Member, y as BotApplication, c as SendMessageOptions, Z as EditMessageOptions, a7 as FetchMessagesOptions, L as BulkDeleteResult, aL as RespondInteractionOptions, aU as SingleMember, a6 as FetchMembersOptions, O as Channel, aM as Role, at as NovaServer, af as Invite, r as NovaClientEvents, p as NovaClient } from '../client-DbKa6yJo.js';
2
+ import { EventEmitter } from 'node:events';
3
+
4
+ /**
5
+ * @module testing/types
6
+ * Shared types for the Nova test harness.
7
+ */
8
+
9
+ /**
10
+ * A single recorded call to a mock API namespace.
11
+ * Stored in {@link MockClient.calls} and inspected by assertion helpers.
12
+ */
13
+ interface RecordedCall {
14
+ /** Which API namespace was called, e.g. `'messages'`, `'interactions'`. */
15
+ api: string;
16
+ /** Method name, e.g. `'send'`, `'respond'`, `'ban'`. */
17
+ method: string;
18
+ /** Arguments passed to the method (in order). */
19
+ args: unknown[];
20
+ /** The mock value that was returned. */
21
+ result: unknown;
22
+ /** Wall-clock time of the call. */
23
+ timestamp: Date;
24
+ }
25
+ /** Minimal fields needed to simulate a message event. */
26
+ interface SimulateMessageInput {
27
+ content?: string;
28
+ channelId?: string;
29
+ serverId?: string;
30
+ authorId?: string;
31
+ authorName?: string;
32
+ id?: string;
33
+ /** Extra fields merged into the Message object. */
34
+ extra?: Partial<Message>;
35
+ }
36
+ /** Minimal fields needed to simulate an interaction. */
37
+ interface SimulateInteractionInput {
38
+ type?: InteractionType;
39
+ /** For slash-commands / prefix commands. */
40
+ commandName?: string;
41
+ /** For button / select / modal interactions. */
42
+ customId?: string;
43
+ /** For SELECT_MENU. */
44
+ values?: string[];
45
+ /** For MODAL_SUBMIT. */
46
+ modalData?: Record<string, string>;
47
+ userId?: string;
48
+ channelId?: string;
49
+ serverId?: string;
50
+ /** Slash-command options forwarded as `data`. */
51
+ data?: Record<string, unknown>;
52
+ extra?: Partial<Interaction>;
53
+ }
54
+ /** Minimal fields needed to simulate a slash-command specifically. */
55
+ interface SimulateSlashCommandInput {
56
+ name: string;
57
+ options?: Record<string, unknown>;
58
+ userId?: string;
59
+ channelId?: string;
60
+ serverId?: string;
61
+ }
62
+ /** Minimal fields needed to simulate a button click. */
63
+ interface SimulateButtonInput {
64
+ customId: string;
65
+ userId?: string;
66
+ channelId?: string;
67
+ serverId?: string;
68
+ triggerMsgId?: string;
69
+ }
70
+ /** Minimal fields needed to simulate a select-menu choice. */
71
+ interface SimulateSelectInput {
72
+ customId: string;
73
+ values: string[];
74
+ userId?: string;
75
+ channelId?: string;
76
+ serverId?: string;
77
+ }
78
+ /** Minimal fields needed to simulate a modal submission. */
79
+ interface SimulateModalInput {
80
+ customId: string;
81
+ modalData: Record<string, string>;
82
+ userId?: string;
83
+ channelId?: string;
84
+ serverId?: string;
85
+ }
86
+ /** Minimal fields needed to simulate a member join. */
87
+ interface SimulateMemberInput {
88
+ userId?: string;
89
+ serverId?: string;
90
+ role?: 'OWNER' | 'ADMIN' | 'MEMBER';
91
+ extra?: Partial<Member>;
92
+ }
93
+ /** Minimal fields needed to simulate a voice-state event. */
94
+ interface SimulateVoiceInput {
95
+ userId?: string;
96
+ channelId?: string;
97
+ serverId?: string;
98
+ muted?: boolean;
99
+ deafened?: boolean;
100
+ }
101
+ /** Minimal fields needed to simulate a reaction event. */
102
+ interface SimulateReactionInput {
103
+ messageId: string;
104
+ emoji: string;
105
+ userId?: string;
106
+ channelId?: string;
107
+ serverId?: string;
108
+ }
109
+ /** Options to `harness.assert.sent()`. */
110
+ interface AssertSentOptions {
111
+ /** Expected message content (partial match). */
112
+ content?: string;
113
+ /** Expected channelId. If omitted, any channel matches. */
114
+ channelId?: string;
115
+ /** Assert the embed's title. */
116
+ embedTitle?: string;
117
+ /** Assert any embed field by name. */
118
+ embedField?: string;
119
+ /** Number of times this kind of message should have been sent. @default ≥1 */
120
+ times?: number;
121
+ }
122
+ /** Options to `harness.assert.replied()`. */
123
+ interface AssertRepliedOptions {
124
+ /** Expected content of the reply payload (partial match). */
125
+ content?: string;
126
+ /** Assert the embed title. */
127
+ embedTitle?: string;
128
+ /** Number of times. @default ≥1 */
129
+ times?: number;
130
+ }
131
+
132
+ /**
133
+ * @module testing/MockClient
134
+ *
135
+ * A lightweight in-memory substitute for {@link NovaClient} used in unit tests.
136
+ *
137
+ * `MockClient` shares the same EventEmitter interface as `NovaClient`, exposes
138
+ * the same API sub-namespaces, and records every API call for later inspection.
139
+ * It never opens a network connection.
140
+ *
141
+ * Use through {@link TestHarness} — or directly if you need lower-level control:
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * import { MockClient } from 'novaapp-sdk/testing'
146
+ *
147
+ * const client = new MockClient()
148
+ * setupBot(client as unknown as NovaClient)
149
+ *
150
+ * // fire a message
151
+ * client.emit('message', buildMockMessage({ content: '!ping' }))
152
+ *
153
+ * // inspect what the bot sent
154
+ * const [call] = client.findCalls('messages', 'send')
155
+ * console.log(call?.args) // [channelId, { content: 'Pong!' }]
156
+ * ```
157
+ */
158
+
159
+ /**
160
+ * Drop-in test double for `NovaClient`.
161
+ *
162
+ * Cast to `NovaClient` with `client as unknown as NovaClient` when passing to
163
+ * bot setup functions. The {@link TestHarness} does this automatically.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const client = new MockClient()
168
+ * client.botUser = defaultBotApplication()
169
+ * setupMyBot(client as unknown as NovaClient)
170
+ * ```
171
+ */
172
+ declare class MockClient extends EventEmitter {
173
+ /** All recorded API calls, in chronological order. */
174
+ readonly calls: RecordedCall[];
175
+ /** Simulated bot application info. Pre-set to a default test value. */
176
+ botUser: BotApplication;
177
+ /** Mocked `client.messages` — same method names as the real MessagesAPI. */
178
+ readonly messages: {
179
+ send(channelId: string, options: SendMessageOptions): Promise<Message>;
180
+ edit(messageId: string, options: EditMessageOptions): Promise<Message>;
181
+ delete(messageId: string): Promise<{
182
+ ok: true;
183
+ }>;
184
+ fetch(channelId: string, options?: FetchMessagesOptions): Promise<Message[]>;
185
+ bulkDelete(channelId: string, messageIds: string[]): Promise<BulkDeleteResult>;
186
+ pin(messageId: string): Promise<{
187
+ ok: true;
188
+ }>;
189
+ unpin(messageId: string): Promise<{
190
+ ok: true;
191
+ }>;
192
+ };
193
+ /** Mocked `client.interactions` — records `respond()` calls. */
194
+ readonly interactions: {
195
+ respond(interactionId: string, options: RespondInteractionOptions): Promise<{
196
+ ok: true;
197
+ }>;
198
+ followUp(interactionId: string, options: SendMessageOptions): Promise<Message>;
199
+ edit(interactionId: string, options: SendMessageOptions): Promise<{
200
+ ok: true;
201
+ }>;
202
+ delete(interactionId: string): Promise<{
203
+ ok: true;
204
+ }>;
205
+ };
206
+ /** Mocked `client.members` */
207
+ readonly members: {
208
+ fetch(serverId: string, userId: string): Promise<SingleMember>;
209
+ list(serverId: string, options?: FetchMembersOptions): Promise<Member[]>;
210
+ kick(serverId: string, userId: string, reason?: string): Promise<{
211
+ ok: true;
212
+ }>;
213
+ ban(serverId: string, userId: string, reason?: string): Promise<{
214
+ ok: true;
215
+ }>;
216
+ unban(serverId: string, userId: string): Promise<{
217
+ ok: true;
218
+ }>;
219
+ mute(serverId: string, userId: string, muted: boolean): Promise<{
220
+ ok: true;
221
+ }>;
222
+ timeout(serverId: string, userId: string, duration: number, reason?: string): Promise<{
223
+ ok: true;
224
+ }>;
225
+ };
226
+ /** Mocked `client.channels` */
227
+ readonly channels: {
228
+ fetch(channelId: string): Promise<Channel>;
229
+ list(serverId: string): Promise<Channel[]>;
230
+ };
231
+ /** Mocked `client.roles` */
232
+ readonly roles: {
233
+ list(serverId: string): Promise<Role[]>;
234
+ add(serverId: string, userId: string, roleId: string): Promise<{
235
+ ok: true;
236
+ }>;
237
+ remove(serverId: string, userId: string, roleId: string): Promise<{
238
+ ok: true;
239
+ }>;
240
+ };
241
+ /** Mocked `client.servers` */
242
+ readonly servers: {
243
+ fetch(serverId: string): Promise<NovaServer>;
244
+ leave(serverId: string): Promise<{
245
+ ok: true;
246
+ }>;
247
+ };
248
+ /** Mocked `client.invites` */
249
+ readonly invites: {
250
+ create(serverId: string, options?: Record<string, unknown>): Promise<Invite>;
251
+ delete(code: string): Promise<{
252
+ ok: true;
253
+ }>;
254
+ list(serverId: string): Promise<Invite[]>;
255
+ };
256
+ readonly webhooks: Record<string, unknown>;
257
+ readonly reactions: Record<string, unknown>;
258
+ readonly permissions: Record<string, unknown>;
259
+ readonly auditlog: Record<string, unknown>;
260
+ readonly forum: Record<string, unknown>;
261
+ readonly events: Record<string, unknown>;
262
+ readonly categories: Record<string, unknown>;
263
+ readonly automod: Record<string, unknown>;
264
+ readonly users: Record<string, unknown>;
265
+ /**
266
+ * Recorded WS sends (via `client.wsSend`).
267
+ * Inspected by `harness.assert.wsSent()`.
268
+ */
269
+ readonly wsSends: Array<{
270
+ channelId: string;
271
+ content: string;
272
+ }>;
273
+ wsSend(channelId: string, content: string): void;
274
+ wsTypingStart(channelId: string): void;
275
+ wsTypingStop(channelId: string): void;
276
+ setStatus(_status: string): void;
277
+ /** Simulated `client.connect()` — no-op in tests. */
278
+ connect(): Promise<this>;
279
+ /** Simulated `client.disconnect()` — emits `disconnect`. */
280
+ disconnect(): void;
281
+ /**
282
+ * Find all recorded calls to a given API namespace + method.
283
+ *
284
+ * @example
285
+ * ```ts
286
+ * const sends = client.findCalls('messages', 'send')
287
+ * // sends[0].args → [channelId, options]
288
+ * ```
289
+ */
290
+ findCalls(api: string, method: string): RecordedCall[];
291
+ /**
292
+ * Find all `messages.send` calls targeting a specific channel.
293
+ */
294
+ sentTo(channelId: string): RecordedCall[];
295
+ /**
296
+ * Find all `interactions.respond` calls for a specific interaction ID.
297
+ */
298
+ repliedTo(interactionId: string): RecordedCall[];
299
+ /** Reset all recorded calls and WS sends. */
300
+ resetCalls(): void;
301
+ on<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
302
+ on(event: string | symbol, listener: (...args: unknown[]) => void): this;
303
+ once<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
304
+ once(event: string | symbol, listener: (...args: unknown[]) => void): this;
305
+ off<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
306
+ off(event: string | symbol, listener: (...args: unknown[]) => void): this;
307
+ emit<K extends keyof NovaClientEvents>(event: K, ...args: Parameters<NovaClientEvents[K]>): boolean;
308
+ emit(event: string | symbol, ...args: unknown[]): boolean;
309
+ }
310
+ /** Convenience cast: use a MockClient anywhere a NovaClient is expected. */
311
+ declare function asMockClient(client: MockClient): NovaClient;
312
+
313
+ /**
314
+ * @module testing/EventSimulator
315
+ *
316
+ * Typed helpers for firing every Nova gateway event on a {@link MockClient}.
317
+ *
318
+ * `EventSimulator` is exposed as `harness.simulate` — but you can also use it
319
+ * standalone:
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * import { MockClient, EventSimulator } from 'novaapp-sdk/testing'
324
+ *
325
+ * const client = new MockClient()
326
+ * const sim = new EventSimulator(client)
327
+ *
328
+ * // Fire a message
329
+ * const msg = sim.message({ content: '!ping', channelId: 'ch-1', serverId: 'srv-1' })
330
+ *
331
+ * // Fire a slash command
332
+ * const interaction = sim.slashCommand({ name: 'ban', options: { user: 'user-123' } })
333
+ *
334
+ * // Fire a button click
335
+ * sim.buttonClick({ customId: 'confirm_delete', triggerMsgId: 'msg-456' })
336
+ * ```
337
+ */
338
+
339
+ /**
340
+ * Fires typed events on a {@link MockClient}, returning the emitted payload
341
+ * so test code can reference it in assertions.
342
+ *
343
+ * Accessed via `harness.simulate`.
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * const msg = harness.simulate.message({ content: '/help' })
348
+ * await nextTick() // let async listeners run
349
+ * harness.assert.sent({ channelId: msg.channelId })
350
+ * ```
351
+ */
352
+ declare class EventSimulator {
353
+ private readonly client;
354
+ constructor(client: MockClient);
355
+ /** Await all already-queued microtasks (useful after async event handlers). */
356
+ flush(): Promise<void>;
357
+ /**
358
+ * Emit a `message` event (bot received a message in a text channel).
359
+ *
360
+ * @example
361
+ * ```ts
362
+ * sim.message({ content: '!ping', channelId: 'ch-1' })
363
+ * ```
364
+ */
365
+ message(input?: SimulateMessageInput): Message;
366
+ /**
367
+ * Emit a `messageEdit` event.
368
+ */
369
+ messageEdit(input?: SimulateMessageInput & {
370
+ newContent?: string;
371
+ }): Message;
372
+ /**
373
+ * Emit a `messageDelete` event.
374
+ */
375
+ messageDelete(messageId?: string, channelId?: string): {
376
+ messageId: string;
377
+ channelId: string;
378
+ };
379
+ /**
380
+ * Emit an `interaction` event for any interaction type.
381
+ *
382
+ * @example
383
+ * ```ts
384
+ * sim.interaction({ type: 'PREFIX_COMMAND', commandName: 'help' })
385
+ * ```
386
+ */
387
+ interaction(input?: SimulateInteractionInput): Interaction;
388
+ /**
389
+ * Fire a `SLASH_COMMAND` interaction.
390
+ *
391
+ * @example
392
+ * ```ts
393
+ * sim.slashCommand({ name: 'ping' })
394
+ * sim.slashCommand({ name: 'ban', options: { user: 'user-123', reason: 'spam' } })
395
+ * ```
396
+ */
397
+ slashCommand(input: SimulateSlashCommandInput): Interaction;
398
+ /**
399
+ * Fire a `BUTTON_CLICK` interaction.
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * sim.buttonClick({ customId: 'confirm_delete' })
404
+ * ```
405
+ */
406
+ buttonClick(input: SimulateButtonInput): Interaction;
407
+ /**
408
+ * Fire a `SELECT_MENU` interaction.
409
+ *
410
+ * @example
411
+ * ```ts
412
+ * sim.selectMenu({ customId: 'role_picker', values: ['mod', 'admin'] })
413
+ * ```
414
+ */
415
+ selectMenu(input: SimulateSelectInput): Interaction;
416
+ /**
417
+ * Fire a `MODAL_SUBMIT` interaction.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * sim.modalSubmit({ customId: 'report_modal', modalData: { reason: 'spam' } })
422
+ * ```
423
+ */
424
+ modalSubmit(input: SimulateModalInput): Interaction;
425
+ /**
426
+ * Fire a `PREFIX_COMMAND` interaction.
427
+ *
428
+ * @example
429
+ * ```ts
430
+ * sim.prefixCommand({ name: 'kick', userId: 'user-1' })
431
+ * ```
432
+ */
433
+ prefixCommand(input: SimulateSlashCommandInput): Interaction;
434
+ /**
435
+ * Emit a `memberJoin` event.
436
+ *
437
+ * @example
438
+ * ```ts
439
+ * sim.memberJoin({ userId: 'user-123', serverId: 'srv-1' })
440
+ * ```
441
+ */
442
+ memberJoin(input?: SimulateMemberInput): Member;
443
+ /**
444
+ * Emit a `memberLeave` event.
445
+ */
446
+ memberLeave(input?: SimulateMemberInput): Member;
447
+ /**
448
+ * Emit a `memberUpdate` event.
449
+ */
450
+ memberUpdate(serverId?: string, userId?: string): void;
451
+ /**
452
+ * Emit a `voiceJoin` event.
453
+ *
454
+ * @example
455
+ * ```ts
456
+ * sim.voiceJoin({ userId: 'user-1', channelId: 'vc-1', serverId: 'srv-1' })
457
+ * ```
458
+ */
459
+ voiceJoin(input?: SimulateVoiceInput): {
460
+ userId: string;
461
+ channelId: string;
462
+ serverId: string;
463
+ };
464
+ /**
465
+ * Emit a `voiceLeave` event.
466
+ */
467
+ voiceLeave(input?: SimulateVoiceInput): {
468
+ userId: string;
469
+ channelId: string;
470
+ serverId: string;
471
+ };
472
+ /**
473
+ * Emit a `reactionAdd` event.
474
+ *
475
+ * @example
476
+ * ```ts
477
+ * sim.reactionAdd({ messageId: 'msg-1', emoji: '👍' })
478
+ * ```
479
+ */
480
+ reactionAdd(input: SimulateReactionInput): void;
481
+ /**
482
+ * Emit a `reactionRemove` event.
483
+ */
484
+ reactionRemove(input: SimulateReactionInput): void;
485
+ /**
486
+ * Emit a `channelCreate` event.
487
+ */
488
+ channelCreate(partial: Partial<Channel> & {
489
+ serverId: string;
490
+ }): Channel;
491
+ /**
492
+ * Emit a `channelDelete` event.
493
+ */
494
+ channelDelete(id: string, serverId: string): void;
495
+ /**
496
+ * Emit a `roleCreate` event.
497
+ */
498
+ roleCreate(partial: Partial<Role> & {
499
+ serverId: string;
500
+ }): Role;
501
+ /**
502
+ * Emit a `roleDelete` event.
503
+ */
504
+ roleDelete(id: string, serverId: string): void;
505
+ /**
506
+ * Emit a `memberBanned` event.
507
+ */
508
+ memberBanned(userId: string, serverId: string, reason?: string): void;
509
+ /**
510
+ * Emit a `memberUnbanned` event.
511
+ */
512
+ memberUnbanned(userId: string, serverId: string): void;
513
+ /**
514
+ * Emit the `ready` event (simulates successful bot connection).
515
+ */
516
+ ready(): void;
517
+ /**
518
+ * Emit the `disconnect` event.
519
+ */
520
+ disconnect(reason?: string): void;
521
+ }
522
+
523
+ /**
524
+ * @module testing/TestHarness
525
+ *
526
+ * Orchestration layer for the Nova test harness.
527
+ *
528
+ * `TestHarness` wires together a {@link MockClient}, an {@link EventSimulator},
529
+ * and a set of assertion helpers so you can write concise, readable tests.
530
+ *
531
+ * @example
532
+ * ```ts
533
+ * import { TestHarness } from 'novaapp-sdk/testing'
534
+ * import { setupPingCommand } from './src/commands/ping.js'
535
+ *
536
+ * test('ping replies', async () => {
537
+ * const harness = new TestHarness()
538
+ * harness.use(setupPingCommand)
539
+ *
540
+ * harness.simulate.slashCommand({ name: 'ping', channelId: 'ch-1' })
541
+ * await harness.flush()
542
+ *
543
+ * harness.assert.replied({ content: 'Pong!' })
544
+ * })
545
+ * ```
546
+ */
547
+
548
+ /** Assertion helpers exposed as `harness.assert`. */
549
+ declare class HarnessAssertions {
550
+ private readonly client;
551
+ constructor(client: MockClient);
552
+ /**
553
+ * Assert that `messages.send` was called **at least once** (or exactly `times`
554
+ * times), optionally matching specific call properties.
555
+ */
556
+ sent(options?: AssertSentOptions): void;
557
+ /**
558
+ * Assert that `interactions.respond` was called, optionally matching content.
559
+ */
560
+ replied(options?: AssertRepliedOptions): void;
561
+ /**
562
+ * Assert that `client.wsSend` was called (optionally matching channel/content).
563
+ */
564
+ wsSent(channelId?: string, content?: string): void;
565
+ /**
566
+ * Assert that a specific API method was called exactly `expected` times.
567
+ *
568
+ * @example
569
+ * ```ts
570
+ * harness.assert.callCount('members', 'kick', 1)
571
+ * ```
572
+ */
573
+ callCount(api: string, method: string, expected: number): void;
574
+ /**
575
+ * Assert that no API calls have been recorded.
576
+ */
577
+ noCalls(): void;
578
+ /**
579
+ * Assert that no messages were sent (neither via `messages.send` nor `wsSend`).
580
+ */
581
+ noMessagesSent(): void;
582
+ /**
583
+ * Assert that a specific API method was called at least once.
584
+ *
585
+ * @example
586
+ * ```ts
587
+ * harness.assert.called('members', 'kick')
588
+ * ```
589
+ */
590
+ called(api: string, method: string): void;
591
+ /**
592
+ * Assert that a specific API method was **never** called.
593
+ *
594
+ * @example
595
+ * ```ts
596
+ * harness.assert.notCalled('members', 'ban')
597
+ * ```
598
+ */
599
+ notCalled(api: string, method: string): void;
600
+ }
601
+ /**
602
+ * Central coordinator for Nova bot tests.
603
+ *
604
+ * Provides:
605
+ * - `client` — the in-memory {@link MockClient}
606
+ * - `simulate` — typed event-firing helpers ({@link EventSimulator})
607
+ * - `assert` — expectation helpers ({@link HarnessAssertions})
608
+ * - `use(fn)` — wire your setup functions against the mock client
609
+ * - `reset()` — clear state between tests
610
+ * - `flush()` — drain all pending microtasks
611
+ *
612
+ * @example
613
+ * ```ts
614
+ * const harness = new TestHarness()
615
+ * harness.use(client => registerCommands(client))
616
+ *
617
+ * harness.simulate.slashCommand({ name: 'ping' })
618
+ * await harness.flush()
619
+ *
620
+ * harness.assert.replied({ content: 'Pong!' })
621
+ * ```
622
+ */
623
+ declare class TestHarness {
624
+ /** The in-memory mock client. */
625
+ readonly client: MockClient;
626
+ /** Typed event simulators. */
627
+ readonly simulate: EventSimulator;
628
+ /** Assertion helpers. */
629
+ readonly assert: HarnessAssertions;
630
+ constructor();
631
+ /**
632
+ * Run a setup function against the mock client (e.g. register commands /
633
+ * event handlers). Supports both sync and async setups.
634
+ *
635
+ * Chainable — call `use` multiple times to compose setup:
636
+ *
637
+ * @example
638
+ * ```ts
639
+ * harness
640
+ * .use(registerCommands)
641
+ * .use(registerEventHandlers)
642
+ * ```
643
+ */
644
+ use(fn: (client: NovaClient) => void | Promise<void>): this;
645
+ /**
646
+ * Clear all recorded API calls, wsSend history, and event listeners.
647
+ * Returns `this` so you can chain: `harness.reset().use(...)`.
648
+ */
649
+ reset(): this;
650
+ /**
651
+ * Awaits all queued microtasks and setImmediate callbacks so that any async
652
+ * event handlers registered with `use()` have fully run.
653
+ *
654
+ * @example
655
+ * ```ts
656
+ * harness.simulate.slashCommand({ name: 'ban', options: { user: 'u-1' } })
657
+ * await harness.flush()
658
+ * harness.assert.called('members', 'ban')
659
+ * ```
660
+ */
661
+ flush(): Promise<void>;
662
+ /**
663
+ * All recorded API calls (shorthand for `harness.client.calls`).
664
+ */
665
+ get calls(): RecordedCall[];
666
+ /**
667
+ * All `messages.send` calls targeting `channelId` (or all if omitted).
668
+ */
669
+ getSent(channelId?: string): Array<{
670
+ channelId: string;
671
+ args: unknown[];
672
+ }>;
673
+ /**
674
+ * All `interactions.respond` call payloads.
675
+ */
676
+ getReplies(): Array<{
677
+ interactionId: string;
678
+ args: unknown[];
679
+ }>;
680
+ }
681
+ /**
682
+ * Thrown by assertion helpers when an expectation fails. Extends `Error`
683
+ * so it's naturally caught by any test runner.
684
+ */
685
+ declare class HarnessAssertionError extends Error {
686
+ constructor(message: string);
687
+ }
688
+
689
+ export { type AssertRepliedOptions, type AssertSentOptions, EventSimulator, HarnessAssertionError, MockClient, type RecordedCall, type SimulateButtonInput, type SimulateInteractionInput, type SimulateMemberInput, type SimulateMessageInput, type SimulateModalInput, type SimulateReactionInput, type SimulateSelectInput, type SimulateSlashCommandInput, type SimulateVoiceInput, TestHarness, asMockClient };