diff --git a/src/fake_mailer.ts b/src/fake_mailer.ts index 22c33fb..c56a9cc 100644 --- a/src/fake_mailer.ts +++ b/src/fake_mailer.ts @@ -23,6 +23,7 @@ import type { MailerContract, MailerMessenger, MessageSearchOptions, + NormalizeConstructor, MessageComposeCallback, } from './types.js' @@ -63,7 +64,7 @@ class MailsCollection { * Assert the mentioned mail was sent during the fake * mode */ - assertSent( + assertSent>( mailConstructor: T, findFn?: (mail: InstanceType) => boolean ) { @@ -85,7 +86,7 @@ class MailsCollection { * Assert the mentioned mail was NOT sent during the fake * mode */ - assertNotSent( + assertNotSent>( mailConstructor: T, findFn?: (mail: InstanceType) => boolean ) { @@ -112,8 +113,11 @@ class MailsCollection { * Assert the mentioned mail was sent for expected number * of times */ - assertSentCount(mailConstructor: typeof BaseMail, count: number): void - assertSentCount(mailConstructor: typeof BaseMail | number, count?: number): void { + assertSentCount(mailConstructor: NormalizeConstructor, count: number): void + assertSentCount( + mailConstructor: NormalizeConstructor | number, + count?: number + ): void { if (typeof mailConstructor === 'number') { const actual = this.#sent.length const expected = mailConstructor @@ -161,7 +165,7 @@ class MailsCollection { * Assert the mentioned mail was queued during the fake * mode */ - assertQueued( + assertQueued>( mailConstructor: T, findFn?: (mail: InstanceType) => boolean ) { @@ -183,7 +187,7 @@ class MailsCollection { * Assert the mentioned mail was NOT queued during the fake * mode */ - assertNotQueued( + assertNotQueued>( mailConstructor: T, findFn?: (mail: InstanceType) => boolean ) { @@ -210,8 +214,11 @@ class MailsCollection { * Assert the mentioned mail was sequeuednt for expected number * of times */ - assertQueuedCount(mailConstructor: typeof BaseMail, count: number): void - assertQueuedCount(mailConstructor: typeof BaseMail | number, count?: number): void { + assertQueuedCount(mailConstructor: NormalizeConstructor, count: number): void + assertQueuedCount( + mailConstructor: NormalizeConstructor | number, + count?: number + ): void { if (typeof mailConstructor === 'number') { const actual = this.#queued.length const expected = mailConstructor diff --git a/src/types.ts b/src/types.ts index 28f4ec6..9c92c1f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -498,3 +498,8 @@ export interface MailService extends MailManager< MailersList extends Record ? MailersList : never > {} + +export type Constructor = abstract new (...args: any[]) => any +export type NormalizeConstructor = { + new (...args: any[]): InstanceType +} & Omit diff --git a/tests/unit/fake_mailer/mails.spec.ts b/tests/unit/fake_mailer/mails.spec.ts index 4847a4a..33e54fd 100644 --- a/tests/unit/fake_mailer/mails.spec.ts +++ b/tests/unit/fake_mailer/mails.spec.ts @@ -191,6 +191,41 @@ test.group('Fake mailer | mails | send', (group) => { return true }) }) + + test('assert using mail class that accepts constructor arguments', async ({ assert, expectTypeOf }) => { + const emitter = new Emitter(app) + const mailer = new FakeMailer('mailgun', emitter, {}) + const { mails } = mailer + + class VerifyEmail extends BaseMail { + from: string = 'foo@bar.com' + subject: string = 'Verify your email address' + + constructor(public userId: UserId) { + super() + } + + prepare() { + this.message.to('bar@baz.com') + } + } + + const response = await mailer.send(new VerifyEmail(1)) + assert.exists(response.messageId) + assert.deepEqual(response.envelope, { from: 'foo@bar.com', to: ['bar@baz.com'] }) + + mails.assertSent(VerifyEmail) + mails.assertSent(VerifyEmail, (mail) => { + expectTypeOf(mail).toMatchTypeOf> + return mail.message.hasTo('bar@baz.com') && mail.message.hasFrom('foo@bar.com') + }) + + assert.throws(() => { + return mails.assertSent(VerifyEmail, (mail) => { + return mail.message.hasTo('bar@example.com') + }) + }, 'Expected mail "VerifyEmail" was not sent') + }) }) test.group('Fake mailer | mails | sendLater', (group) => {