From af37210c0bd7bf343fe366ddd2b253e2214f5547 Mon Sep 17 00:00:00 2001 From: Josh Morel Date: Sat, 15 Dec 2018 08:51:51 -0500 Subject: [PATCH] throw error if MailDev doesn't run also allow calling in multiple file --- server/tests/api/server/email.ts | 4 +- server/tests/api/users/users-verification.ts | 4 +- shared/utils/miscs/email-child-process.js | 27 ++++++++ shared/utils/miscs/email.ts | 66 ++++++++++++++------ 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 shared/utils/miscs/email-child-process.js diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts index 13df772c6..b8d29ef81 100644 --- a/server/tests/api/server/email.ts +++ b/server/tests/api/server/email.ts @@ -20,7 +20,7 @@ import { ServerInfo, setAccessTokensToServers } from '../../../../shared/utils' -import { mockSmtpServer } from '../../../../shared/utils/miscs/email' +import { MockSmtpServer } from '../../../../shared/utils/miscs/email' import { waitJobs } from '../../../../shared/utils/server/jobs' const expect = chai.expect @@ -41,7 +41,7 @@ describe('Test emails', function () { before(async function () { this.timeout(30000) - await mockSmtpServer(emails) + await MockSmtpServer.Instance.collectEmails(emails) await flushTests() diff --git a/server/tests/api/users/users-verification.ts b/server/tests/api/users/users-verification.ts index b1733e45e..afc8a0059 100644 --- a/server/tests/api/users/users-verification.ts +++ b/server/tests/api/users/users-verification.ts @@ -7,7 +7,7 @@ import { userLogin, login, runServer, ServerInfo, verifyEmail, updateCustomSubConfig } from '../../../../shared/utils' import { setAccessTokensToServers } from '../../../../shared/utils/users/login' -import { mockSmtpServer } from '../../../../shared/utils/miscs/email' +import { MockSmtpServer } from '../../../../shared/utils/miscs/email' import { waitJobs } from '../../../../shared/utils/server/jobs' const expect = chai.expect @@ -30,7 +30,7 @@ describe('Test users account verification', function () { before(async function () { this.timeout(30000) - await mockSmtpServer(emails) + await MockSmtpServer.Instance.collectEmails(emails) await flushTests() diff --git a/shared/utils/miscs/email-child-process.js b/shared/utils/miscs/email-child-process.js new file mode 100644 index 000000000..40ae37d70 --- /dev/null +++ b/shared/utils/miscs/email-child-process.js @@ -0,0 +1,27 @@ +const MailDev = require('maildev') + +// must run maildev as forked ChildProcess +// failed instantiation stops main process with exit code 0 +process.on('message', (msg) => { + if (msg.start) { + const maildev = new MailDev({ + ip: '127.0.0.1', + smtp: 1025, + disableWeb: true, + silent: true + }) + + maildev.on('new', email => { + process.send({ email }) + }) + + maildev.listen(err => { + if (err) { + // cannot send as Error object + return process.send({ err: err.message }) + } + + return process.send({ err: null }) + }) + } +}) diff --git a/shared/utils/miscs/email.ts b/shared/utils/miscs/email.ts index 21accd09d..108f7d3d9 100644 --- a/shared/utils/miscs/email.ts +++ b/shared/utils/miscs/email.ts @@ -1,25 +1,55 @@ -import * as MailDev from 'maildev' - -function mockSmtpServer (emailsCollection: object[]) { - const maildev = new MailDev({ - ip: '127.0.0.1', - smtp: 1025, - disableWeb: true, - silent: true - }) - maildev.on('new', email => emailsCollection.push(email)) - - return new Promise((res, rej) => { - maildev.listen(err => { - if (err) return rej(err) - - return res() +import * as child from 'child_process' + +class MockSmtpServer { + + private static instance: MockSmtpServer + private started = false + private emailChildProcess: child.ChildProcess + private emails: object[] + + private constructor () { + this.emailChildProcess = child.fork(`${__dirname}/email-child-process`, [], { silent: true }) + this.emailChildProcess.on('message', (msg) => { + if (msg.email) { + return this.emails.push(msg.email) + } + }) + process.on('exit', () => { + this.emailChildProcess.kill() }) - }) + } + + collectEmails (emailsCollection: object[]) { + return new Promise((res, rej) => { + if (this.started) { + this.emails = emailsCollection + return res() + } + + // ensure maildev isn't started until + // unexpected exit can be reported to test runner + this.emailChildProcess.send({ start: true }) + this.emailChildProcess.on('exit', () => { + return rej(new Error('maildev exited unexpectedly, confirm port not in use')) + }) + this.emailChildProcess.on('message', (msg) => { + if (msg.err) { + return rej(new Error(msg.err)) + } + this.started = true + this.emails = emailsCollection + return res() + }) + }) + } + + static get Instance () { + return this.instance || (this.instance = new this()) + } } // --------------------------------------------------------------------------- export { - mockSmtpServer + MockSmtpServer } -- 2.25.1