From 3de35ad68fdefb207a58d7d65f9dd4ddd1ee5b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Tue, 19 Apr 2022 14:51:27 +0200 Subject: [PATCH 1/2] :zap: Implement timeout in SMTP tests --- .../integration/passwordReset.api.test.ts | 51 +++--- packages/cli/test/integration/shared/utils.ts | 5 + .../cli/test/integration/users.api.test.ts | 169 ++++++++++-------- 3 files changed, 125 insertions(+), 100 deletions(-) diff --git a/packages/cli/test/integration/passwordReset.api.test.ts b/packages/cli/test/integration/passwordReset.api.test.ts index ef1ffdbf2f390..e0ef853861e98 100644 --- a/packages/cli/test/integration/passwordReset.api.test.ts +++ b/packages/cli/test/integration/passwordReset.api.test.ts @@ -40,35 +40,40 @@ beforeEach(async () => { config.set('userManagement.isInstanceOwnerSetUp', true); config.set('userManagement.emails.mode', ''); - - jest.setTimeout(30000); // fake SMTP service might be slow }); afterAll(async () => { await testDb.terminate(testDbName); }); -test('POST /forgot-password should send password reset email', async () => { - const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - - const authlessAgent = utils.createAgent(app); - const member = await testDb.createUser({ email: 'test@test.com', globalRole: globalMemberRole }); - - await utils.configureSmtp(); - - await Promise.all( - [{ email: owner.email }, { email: member.email.toUpperCase() }].map(async (payload) => { - const response = await authlessAgent.post('/forgot-password').send(payload); - - expect(response.statusCode).toBe(200); - expect(response.body).toEqual({}); - - const user = await Db.collections.User!.findOneOrFail({ email: payload.email }); - expect(user.resetPasswordToken).toBeDefined(); - expect(user.resetPasswordTokenExpiration).toBeGreaterThan(Math.ceil(Date.now() / 1000)); - }), - ); -}); +test( + 'POST /forgot-password should send password reset email', + async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + + const authlessAgent = utils.createAgent(app); + const member = await testDb.createUser({ + email: 'test@test.com', + globalRole: globalMemberRole, + }); + + await utils.configureSmtp(); + + await Promise.all( + [{ email: owner.email }, { email: member.email.toUpperCase() }].map(async (payload) => { + const response = await authlessAgent.post('/forgot-password').send(payload); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual({}); + + const user = await Db.collections.User!.findOneOrFail({ email: payload.email }); + expect(user.resetPasswordToken).toBeDefined(); + expect(user.resetPasswordTokenExpiration).toBeGreaterThan(Math.ceil(Date.now() / 1000)); + }), + ); + }, + utils.SMTP_TEST_TIMEOUT, +); test('POST /forgot-password should fail if emailing is not set up', async () => { const owner = await testDb.createUser({ globalRole: globalOwnerRole }); diff --git a/packages/cli/test/integration/shared/utils.ts b/packages/cli/test/integration/shared/utils.ts index 4127eb98db5c2..bec5d3fceb775 100644 --- a/packages/cli/test/integration/shared/utils.ts +++ b/packages/cli/test/integration/shared/utils.ts @@ -229,6 +229,11 @@ export async function configureSmtp() { config.set('userManagement.emails.smtp.auth.pass', pass); } +/** + * Timeout (in milliseconds) to account for fake SMTP service being slow to respond. + */ +export const SMTP_TEST_TIMEOUT = 30_000; + // ---------------------------------- // misc // ---------------------------------- diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index f139cd4351f09..7c8a386cedeb2 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -47,8 +47,6 @@ beforeAll(async () => { utils.initTestTelemetry(); utils.initTestLogger(); - - jest.setTimeout(30000); // fake SMTP service might be slow }); beforeEach(async () => { @@ -481,91 +479,108 @@ test('POST /users should fail if user management is disabled', async () => { expect(response.statusCode).toBe(500); }); -test('POST /users should email invites and create user shells but ignore existing', async () => { - const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const member = await testDb.createUser({ globalRole: globalMemberRole }); - const memberShell = await testDb.createUserShell(globalMemberRole); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - - await utils.configureSmtp(); - - const testEmails = [randomEmail(), randomEmail().toUpperCase(), memberShell.email, member.email]; - - const payload = testEmails.map((e) => ({ email: e })); - - const response = await authOwnerAgent.post('/users').send(payload); - - expect(response.statusCode).toBe(200); - - for (const { - user: { id, email: receivedEmail }, - error, - } of response.body.data) { - expect(validator.isUUID(id)).toBe(true); - expect(id).not.toBe(member.id); - - const lowerCasedEmail = receivedEmail.toLowerCase(); - expect(receivedEmail).toBe(lowerCasedEmail); - expect(payload.some(({ email }) => email.toLowerCase() === lowerCasedEmail)).toBe(true); - - if (error) { - expect(error).toBe('Email could not be sent'); - } - - const storedUser = await Db.collections.User!.findOneOrFail(id); - const { firstName, lastName, personalizationAnswers, password, resetPasswordToken } = - storedUser; - - expect(firstName).toBeNull(); - expect(lastName).toBeNull(); - expect(personalizationAnswers).toBeNull(); - expect(password).toBeNull(); - expect(resetPasswordToken).toBeNull(); - } -}); - -test('POST /users should fail with invalid inputs', async () => { - const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); +test( + 'POST /users should email invites and create user shells but ignore existing', + async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const member = await testDb.createUser({ globalRole: globalMemberRole }); + const memberShell = await testDb.createUserShell(globalMemberRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - await utils.configureSmtp(); + await utils.configureSmtp(); - const invalidPayloads = [ - randomEmail(), - [randomEmail()], - {}, - [{ name: randomName() }], - [{ email: randomName() }], - ]; + const testEmails = [ + randomEmail(), + randomEmail().toUpperCase(), + memberShell.email, + member.email, + ]; - await Promise.all( - invalidPayloads.map(async (invalidPayload) => { - const response = await authOwnerAgent.post('/users').send(invalidPayload); - expect(response.statusCode).toBe(400); + const payload = testEmails.map((e) => ({ email: e })); - const users = await Db.collections.User!.find(); - expect(users.length).toBe(1); // DB unaffected - }), - ); -}); + const response = await authOwnerAgent.post('/users').send(payload); -test('POST /users should ignore an empty payload', async () => { - const owner = await testDb.createUser({ globalRole: globalOwnerRole }); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + expect(response.statusCode).toBe(200); - await utils.configureSmtp(); + for (const { + user: { id, email: receivedEmail }, + error, + } of response.body.data) { + expect(validator.isUUID(id)).toBe(true); + expect(id).not.toBe(member.id); - const response = await authOwnerAgent.post('/users').send([]); + const lowerCasedEmail = receivedEmail.toLowerCase(); + expect(receivedEmail).toBe(lowerCasedEmail); + expect(payload.some(({ email }) => email.toLowerCase() === lowerCasedEmail)).toBe(true); - const { data } = response.body; + if (error) { + expect(error).toBe('Email could not be sent'); + } - expect(response.statusCode).toBe(200); - expect(Array.isArray(data)).toBe(true); - expect(data.length).toBe(0); + const storedUser = await Db.collections.User!.findOneOrFail(id); + const { firstName, lastName, personalizationAnswers, password, resetPasswordToken } = + storedUser; - const users = await Db.collections.User!.find(); - expect(users.length).toBe(1); -}); + expect(firstName).toBeNull(); + expect(lastName).toBeNull(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeNull(); + expect(resetPasswordToken).toBeNull(); + } + }, + utils.SMTP_TEST_TIMEOUT, +); + +test( + 'POST /users should fail with invalid inputs', + async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + + await utils.configureSmtp(); + + const invalidPayloads = [ + randomEmail(), + [randomEmail()], + {}, + [{ name: randomName() }], + [{ email: randomName() }], + ]; + + await Promise.all( + invalidPayloads.map(async (invalidPayload) => { + const response = await authOwnerAgent.post('/users').send(invalidPayload); + expect(response.statusCode).toBe(400); + + const users = await Db.collections.User!.find(); + expect(users.length).toBe(1); // DB unaffected + }), + ); + }, + utils.SMTP_TEST_TIMEOUT, +); + +test( + 'POST /users should ignore an empty payload', + async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + + await utils.configureSmtp(); + + const response = await authOwnerAgent.post('/users').send([]); + + const { data } = response.body; + + expect(response.statusCode).toBe(200); + expect(Array.isArray(data)).toBe(true); + expect(data.length).toBe(0); + + const users = await Db.collections.User!.find(); + expect(users.length).toBe(1); + }, + utils.SMTP_TEST_TIMEOUT, +); // TODO: /users/:id/reinvite route tests missing From 8b7b9e1fbd8a501c0f21e6d2ea060215b1bf895a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 20 Apr 2022 11:47:07 +0200 Subject: [PATCH 2/2] :truck: Move timeout to constants --- packages/cli/test/integration/passwordReset.api.test.ts | 3 ++- packages/cli/test/integration/shared/constants.ts | 5 +++++ packages/cli/test/integration/shared/utils.ts | 5 ----- packages/cli/test/integration/users.api.test.ts | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/cli/test/integration/passwordReset.api.test.ts b/packages/cli/test/integration/passwordReset.api.test.ts index e0ef853861e98..9d083fe3087db 100644 --- a/packages/cli/test/integration/passwordReset.api.test.ts +++ b/packages/cli/test/integration/passwordReset.api.test.ts @@ -13,6 +13,7 @@ import { } from './shared/random'; import * as testDb from './shared/testDb'; import type { Role } from '../../src/databases/entities/Role'; +import { SMTP_TEST_TIMEOUT } from './shared/constants'; jest.mock('../../src/telemetry'); @@ -72,7 +73,7 @@ test( }), ); }, - utils.SMTP_TEST_TIMEOUT, + SMTP_TEST_TIMEOUT, ); test('POST /forgot-password should fail if emailing is not set up', async () => { diff --git a/packages/cli/test/integration/shared/constants.ts b/packages/cli/test/integration/shared/constants.ts index 03865412d0ee8..75c2a69a38ba6 100644 --- a/packages/cli/test/integration/shared/constants.ts +++ b/packages/cli/test/integration/shared/constants.ts @@ -57,3 +57,8 @@ export const BOOTSTRAP_POSTGRES_CONNECTION_NAME: Readonly = 'n8n_bs_post * for each suite test run. */ export const BOOTSTRAP_MYSQL_CONNECTION_NAME: Readonly = 'n8n_bs_mysql'; + +/** + * Timeout (in milliseconds) to account for fake SMTP service being slow to respond. + */ +export const SMTP_TEST_TIMEOUT = 30_000; diff --git a/packages/cli/test/integration/shared/utils.ts b/packages/cli/test/integration/shared/utils.ts index bec5d3fceb775..4127eb98db5c2 100644 --- a/packages/cli/test/integration/shared/utils.ts +++ b/packages/cli/test/integration/shared/utils.ts @@ -229,11 +229,6 @@ export async function configureSmtp() { config.set('userManagement.emails.smtp.auth.pass', pass); } -/** - * Timeout (in milliseconds) to account for fake SMTP service being slow to respond. - */ -export const SMTP_TEST_TIMEOUT = 30_000; - // ---------------------------------- // misc // ---------------------------------- diff --git a/packages/cli/test/integration/users.api.test.ts b/packages/cli/test/integration/users.api.test.ts index 7c8a386cedeb2..b5db3dc3385d8 100644 --- a/packages/cli/test/integration/users.api.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -4,7 +4,7 @@ import { v4 as uuid } from 'uuid'; import { Db } from '../../src'; import config from '../../config'; -import { SUCCESS_RESPONSE_BODY } from './shared/constants'; +import { SMTP_TEST_TIMEOUT, SUCCESS_RESPONSE_BODY } from './shared/constants'; import { randomEmail, randomValidPassword, @@ -528,7 +528,7 @@ test( expect(resetPasswordToken).toBeNull(); } }, - utils.SMTP_TEST_TIMEOUT, + SMTP_TEST_TIMEOUT, ); test( @@ -557,7 +557,7 @@ test( }), ); }, - utils.SMTP_TEST_TIMEOUT, + SMTP_TEST_TIMEOUT, ); test( @@ -579,7 +579,7 @@ test( const users = await Db.collections.User!.find(); expect(users.length).toBe(1); }, - utils.SMTP_TEST_TIMEOUT, + SMTP_TEST_TIMEOUT, ); // TODO: /users/:id/reinvite route tests missing