From befb61c91590581db60fb552d2aa21298fdbd966 Mon Sep 17 00:00:00 2001 From: Rory Powell Date: Wed, 6 Apr 2022 16:57:56 +0100 Subject: [PATCH] smtp events + centralise worker test config --- .../src/tests/utilities/TestConfiguration.js | 670 +++++++++--------- .../worker/src/api/routes/tests/auth.spec.js | 14 +- .../src/api/routes/tests/configs.spec.js | 68 +- .../worker/src/api/routes/tests/email.spec.js | 15 +- .../src/api/routes/tests/realEmail.spec.js | 10 +- .../worker/src/api/routes/tests/users.spec.js | 12 +- .../api/routes/tests/utilities/controllers.js | 7 - .../src/api/routes/tests/utilities/index.js | 41 -- .../api/routes/tests/utilities/mocks/index.js | 1 - .../api/routes/tests/utilities/structures.js | 2 - .../utilities => tests}/TestConfiguration.js | 169 ++--- packages/worker/src/tests/controllers.js | 7 + packages/worker/src/tests/index.js | 12 + .../tests/utilities => tests}/mocks/core.js | 0 packages/worker/src/tests/mocks/email.js | 10 + packages/worker/src/tests/mocks/index.js | 6 + .../worker/src/tests/structures/configs.js | 76 ++ packages/worker/src/tests/structures/index.js | 10 + 18 files changed, 600 insertions(+), 530 deletions(-) delete mode 100644 packages/worker/src/api/routes/tests/utilities/controllers.js delete mode 100644 packages/worker/src/api/routes/tests/utilities/index.js delete mode 100644 packages/worker/src/api/routes/tests/utilities/mocks/index.js delete mode 100644 packages/worker/src/api/routes/tests/utilities/structures.js rename packages/worker/src/{api/routes/tests/utilities => tests}/TestConfiguration.js (65%) create mode 100644 packages/worker/src/tests/controllers.js create mode 100644 packages/worker/src/tests/index.js rename packages/worker/src/{api/routes/tests/utilities => tests}/mocks/core.js (100%) create mode 100644 packages/worker/src/tests/mocks/email.js create mode 100644 packages/worker/src/tests/mocks/index.js create mode 100644 packages/worker/src/tests/structures/configs.js create mode 100644 packages/worker/src/tests/structures/index.js diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 87c8f4f4b1..16658bec3c 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -60,6 +60,26 @@ class TestConfiguration { return this.prodAppId } + // SETUP / TEARDOWN + + // use a new id as the name to avoid name collisions + async init(appName = newid()) { + await this.globalUser() + return this.createApp(appName) + } + + end() { + if (!this) { + return + } + if (this.server) { + this.server.close() + } + cleanup(this.allApps.map(app => app.appId)) + } + + // UTILS + async _req(config, params, controlFunc) { const request = {} // fake cookies, we don't need them @@ -88,19 +108,7 @@ class TestConfiguration { } } - async generateApiKey(userId = GLOBAL_USER_ID) { - const db = getGlobalDB(TENANT_ID) - const id = generateDevInfoID(userId) - let devInfo - try { - devInfo = await db.get(id) - } catch (err) { - devInfo = { _id: id, userId } - } - devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`) - await db.put(devInfo) - return devInfo.apiKey - } + // USER / AUTH async globalUser({ id = GLOBAL_USER_ID, @@ -138,314 +146,6 @@ class TestConfiguration { } } - // use a new id as the name to avoid name collisions - async init(appName = newid()) { - await this.globalUser() - return this.createApp(appName) - } - - end() { - if (!this) { - return - } - if (this.server) { - this.server.close() - } - cleanup(this.allApps.map(app => app.appId)) - } - - defaultHeaders(extras = {}) { - const auth = { - userId: GLOBAL_USER_ID, - sessionId: "sessionid", - tenantId: TENANT_ID, - } - const app = { - roleId: BUILTIN_ROLE_IDS.ADMIN, - appId: this.appId, - } - const authToken = jwt.sign(auth, env.JWT_SECRET) - const appToken = jwt.sign(app, env.JWT_SECRET) - const headers = { - Accept: "application/json", - Cookie: [ - `${Cookies.Auth}=${authToken}`, - `${Cookies.CurrentApp}=${appToken}`, - ], - [Headers.CSRF_TOKEN]: CSRF_TOKEN, - ...extras, - } - if (this.appId) { - headers[Headers.APP_ID] = this.appId - } - return headers - } - - publicHeaders({ prodApp = true } = {}) { - const appId = prodApp ? this.prodAppId : this.appId - - const headers = { - Accept: "application/json", - } - if (appId) { - headers[Headers.APP_ID] = appId - } - return headers - } - - async roleHeaders({ - email = EMAIL, - roleId = BUILTIN_ROLE_IDS.ADMIN, - builder = false, - prodApp = true, - } = {}) { - return this.login({ email, roleId, builder, prodApp }) - } - - async createApp(appName) { - // create dev app - this.app = await this._req({ name: appName }, null, controllers.app.create) - this.appId = this.app.appId - context.updateAppId(this.appId) - - // create production app - this.prodApp = await this.deploy() - this.prodAppId = this.prodApp.appId - - this.allApps.push(this.prodApp) - this.allApps.push(this.app) - - return this.app - } - - async deploy() { - await this._req(null, null, controllers.deploy.deployApp) - const prodAppId = this.getAppId().replace("_dev", "") - return context.doInAppContext(prodAppId, async () => { - const appPackage = await this._req( - null, - { appId: prodAppId }, - controllers.app.fetchAppPackage - ) - return appPackage.application - }) - } - - async updateTable(config = null) { - config = config || basicTable() - this.table = await this._req(config, null, controllers.table.save) - return this.table - } - - async createTable(config = null) { - if (config != null && config._id) { - delete config._id - } - return this.updateTable(config) - } - - async getTable(tableId = null) { - tableId = tableId || this.table._id - return this._req(null, { tableId }, controllers.table.find) - } - - async createLinkedTable(relationshipType = null, links = ["link"]) { - if (!this.table) { - throw "Must have created a table first." - } - const tableConfig = basicTable() - tableConfig.primaryDisplay = "name" - for (let link of links) { - tableConfig.schema[link] = { - type: "link", - fieldName: link, - tableId: this.table._id, - name: link, - } - if (relationshipType) { - tableConfig.schema[link].relationshipType = relationshipType - } - } - const linkedTable = await this.createTable(tableConfig) - this.linkedTable = linkedTable - return linkedTable - } - - async createAttachmentTable() { - const table = basicTable() - table.schema.attachment = { - type: "attachment", - } - return this.createTable(table) - } - - async createRow(config = null) { - if (!this.table) { - throw "Test requires table to be configured." - } - const tableId = (config && config.tableId) || this.table._id - config = config || basicRow(tableId) - return this._req(config, { tableId }, controllers.row.save) - } - - async getRow(tableId, rowId) { - return this._req(null, { tableId, rowId }, controllers.row.find) - } - - async getRows(tableId) { - if (!tableId && this.table) { - tableId = this.table._id - } - return this._req(null, { tableId }, controllers.row.fetch) - } - - async createRole(config = null) { - config = config || basicRole() - return this._req(config, null, controllers.role.save) - } - - async addPermission(roleId, resourceId, level = "read") { - return this._req( - null, - { - roleId, - resourceId, - level, - }, - controllers.perms.addPermission - ) - } - - async createView(config) { - if (!this.table) { - throw "Test requires table to be configured." - } - const view = config || { - map: "function(doc) { emit(doc[doc.key], doc._id); } ", - tableId: this.table._id, - name: "ViewTest", - } - return this._req(view, null, controllers.view.save) - } - - async createAutomation(config) { - config = config || basicAutomation() - if (config._rev) { - delete config._rev - } - this.automation = ( - await this._req(config, null, controllers.automation.create) - ).automation - return this.automation - } - - async getAllAutomations() { - return this._req(null, null, controllers.automation.fetch) - } - - async deleteAutomation(automation = null) { - automation = automation || this.automation - if (!automation) { - return - } - return this._req( - null, - { id: automation._id, rev: automation._rev }, - controllers.automation.destroy - ) - } - - async createDatasource(config = null) { - config = config || basicDatasource() - const response = await this._req(config, null, controllers.datasource.save) - this.datasource = response.datasource - return this.datasource - } - - async updateDatasource(datasource) { - const response = await this._req( - datasource, - { datasourceId: datasource._id }, - controllers.datasource.update - ) - this.datasource = response.datasource - return this.datasource - } - - async restDatasource(cfg) { - return this.createDatasource({ - datasource: { - ...basicDatasource().datasource, - source: "REST", - config: cfg || {}, - }, - }) - } - - async dynamicVariableDatasource() { - let datasource = await this.restDatasource() - const basedOnQuery = await this.createQuery({ - ...basicQuery(datasource._id), - fields: { - path: "www.google.com", - }, - }) - datasource = await this.updateDatasource({ - ...datasource, - config: { - dynamicVariables: [ - { - queryId: basedOnQuery._id, - name: "variable3", - value: "{{ data.0.[value] }}", - }, - ], - }, - }) - return { datasource, query: basedOnQuery } - } - - async previewQuery(request, config, datasource, fields) { - return request - .post(`/api/queries/preview`) - .send({ - datasourceId: datasource._id, - parameters: {}, - fields, - queryVerb: "read", - name: datasource.name, - }) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(200) - } - - async createQuery(config = null) { - if (!this.datasource && !config) { - throw "No data source created for query." - } - config = config || basicQuery(this.datasource._id) - return this._req(config, null, controllers.query.save) - } - - async createScreen(config = null) { - config = config || basicScreen() - return this._req(config, null, controllers.screen.save) - } - - async createWebhook(config = null) { - if (!this.automation) { - throw "Must create an automation before creating webhook." - } - config = config || basicWebhook(this.automation._id) - return (await this._req(config, null, controllers.webhook.save)).webhook - } - - async createLayout(config = null) { - config = config || basicLayout() - return await this._req(config, null, controllers.layout.save) - } - async createUser(id = null, email = EMAIL) { const globalId = !id ? `us_${Math.random()}` : `us_${id}` const resp = await this.globalUser({ id: globalId, email }) @@ -500,6 +200,334 @@ class TestConfiguration { } }) } + + defaultHeaders(extras = {}) { + const auth = { + userId: GLOBAL_USER_ID, + sessionId: "sessionid", + tenantId: TENANT_ID, + } + const app = { + roleId: BUILTIN_ROLE_IDS.ADMIN, + appId: this.appId, + } + const authToken = jwt.sign(auth, env.JWT_SECRET) + const appToken = jwt.sign(app, env.JWT_SECRET) + const headers = { + Accept: "application/json", + Cookie: [ + `${Cookies.Auth}=${authToken}`, + `${Cookies.CurrentApp}=${appToken}`, + ], + [Headers.CSRF_TOKEN]: CSRF_TOKEN, + ...extras, + } + if (this.appId) { + headers[Headers.APP_ID] = this.appId + } + return headers + } + + publicHeaders({ prodApp = true } = {}) { + const appId = prodApp ? this.prodAppId : this.appId + + const headers = { + Accept: "application/json", + } + if (appId) { + headers[Headers.APP_ID] = appId + } + return headers + } + + async roleHeaders({ + email = EMAIL, + roleId = BUILTIN_ROLE_IDS.ADMIN, + builder = false, + prodApp = true, + } = {}) { + return this.login({ email, roleId, builder, prodApp }) + } + + // API + + async generateApiKey(userId = GLOBAL_USER_ID) { + const db = getGlobalDB(TENANT_ID) + const id = generateDevInfoID(userId) + let devInfo + try { + devInfo = await db.get(id) + } catch (err) { + devInfo = { _id: id, userId } + } + devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`) + await db.put(devInfo) + return devInfo.apiKey + } + + // APP + + async createApp(appName) { + // create dev app + this.app = await this._req({ name: appName }, null, controllers.app.create) + this.appId = this.app.appId + context.updateAppId(this.appId) + + // create production app + this.prodApp = await this.deploy() + this.prodAppId = this.prodApp.appId + + this.allApps.push(this.prodApp) + this.allApps.push(this.app) + + return this.app + } + + async deploy() { + await this._req(null, null, controllers.deploy.deployApp) + const prodAppId = this.getAppId().replace("_dev", "") + return context.doInAppContext(prodAppId, async () => { + const appPackage = await this._req( + null, + { appId: prodAppId }, + controllers.app.fetchAppPackage + ) + return appPackage.application + }) + } + + // TABLE + + async updateTable(config = null) { + config = config || basicTable() + this.table = await this._req(config, null, controllers.table.save) + return this.table + } + + async createTable(config = null) { + if (config != null && config._id) { + delete config._id + } + return this.updateTable(config) + } + + async getTable(tableId = null) { + tableId = tableId || this.table._id + return this._req(null, { tableId }, controllers.table.find) + } + + async createLinkedTable(relationshipType = null, links = ["link"]) { + if (!this.table) { + throw "Must have created a table first." + } + const tableConfig = basicTable() + tableConfig.primaryDisplay = "name" + for (let link of links) { + tableConfig.schema[link] = { + type: "link", + fieldName: link, + tableId: this.table._id, + name: link, + } + if (relationshipType) { + tableConfig.schema[link].relationshipType = relationshipType + } + } + const linkedTable = await this.createTable(tableConfig) + this.linkedTable = linkedTable + return linkedTable + } + + async createAttachmentTable() { + const table = basicTable() + table.schema.attachment = { + type: "attachment", + } + return this.createTable(table) + } + + // ROW + + async createRow(config = null) { + if (!this.table) { + throw "Test requires table to be configured." + } + const tableId = (config && config.tableId) || this.table._id + config = config || basicRow(tableId) + return this._req(config, { tableId }, controllers.row.save) + } + + async getRow(tableId, rowId) { + return this._req(null, { tableId, rowId }, controllers.row.find) + } + + async getRows(tableId) { + if (!tableId && this.table) { + tableId = this.table._id + } + return this._req(null, { tableId }, controllers.row.fetch) + } + + // ROLE + + async createRole(config = null) { + config = config || basicRole() + return this._req(config, null, controllers.role.save) + } + + async addPermission(roleId, resourceId, level = "read") { + return this._req( + null, + { + roleId, + resourceId, + level, + }, + controllers.perms.addPermission + ) + } + + // VIEW + + async createView(config) { + if (!this.table) { + throw "Test requires table to be configured." + } + const view = config || { + map: "function(doc) { emit(doc[doc.key], doc._id); } ", + tableId: this.table._id, + name: "ViewTest", + } + return this._req(view, null, controllers.view.save) + } + + // AUTOMATION + + async createAutomation(config) { + config = config || basicAutomation() + if (config._rev) { + delete config._rev + } + this.automation = ( + await this._req(config, null, controllers.automation.create) + ).automation + return this.automation + } + + async getAllAutomations() { + return this._req(null, null, controllers.automation.fetch) + } + + async deleteAutomation(automation = null) { + automation = automation || this.automation + if (!automation) { + return + } + return this._req( + null, + { id: automation._id, rev: automation._rev }, + controllers.automation.destroy + ) + } + + async createWebhook(config = null) { + if (!this.automation) { + throw "Must create an automation before creating webhook." + } + config = config || basicWebhook(this.automation._id) + return (await this._req(config, null, controllers.webhook.save)).webhook + } + + // DATASOURCE + + async createDatasource(config = null) { + config = config || basicDatasource() + const response = await this._req(config, null, controllers.datasource.save) + this.datasource = response.datasource + return this.datasource + } + + async updateDatasource(datasource) { + const response = await this._req( + datasource, + { datasourceId: datasource._id }, + controllers.datasource.update + ) + this.datasource = response.datasource + return this.datasource + } + + async restDatasource(cfg) { + return this.createDatasource({ + datasource: { + ...basicDatasource().datasource, + source: "REST", + config: cfg || {}, + }, + }) + } + + async dynamicVariableDatasource() { + let datasource = await this.restDatasource() + const basedOnQuery = await this.createQuery({ + ...basicQuery(datasource._id), + fields: { + path: "www.google.com", + }, + }) + datasource = await this.updateDatasource({ + ...datasource, + config: { + dynamicVariables: [ + { + queryId: basedOnQuery._id, + name: "variable3", + value: "{{ data.0.[value] }}", + }, + ], + }, + }) + return { datasource, query: basedOnQuery } + } + + // QUERY + + async previewQuery(request, config, datasource, fields) { + return request + .post(`/api/queries/preview`) + .send({ + datasourceId: datasource._id, + parameters: {}, + fields, + queryVerb: "read", + name: datasource.name, + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + } + + async createQuery(config = null) { + if (!this.datasource && !config) { + throw "No data source created for query." + } + config = config || basicQuery(this.datasource._id) + return this._req(config, null, controllers.query.save) + } + + // SCREEN + + async createScreen(config = null) { + config = config || basicScreen() + return this._req(config, null, controllers.screen.save) + } + + // LAYOUT + + async createLayout(config = null) { + config = config || basicLayout() + return await this._req(config, null, controllers.layout.save) + } } module.exports = TestConfiguration diff --git a/packages/worker/src/api/routes/tests/auth.spec.js b/packages/worker/src/api/routes/tests/auth.spec.js index 419c477882..9426b9f779 100644 --- a/packages/worker/src/api/routes/tests/auth.spec.js +++ b/packages/worker/src/api/routes/tests/auth.spec.js @@ -1,20 +1,20 @@ jest.mock("nodemailer") -const setup = require("./utilities") -const sendMailMock = setup.emailMock() +const { config, request, mocks, structures } = require("../../../tests") +const sendMailMock = mocks.email.mock() const { events } = require("@budibase/backend-core") -const TENANT_ID = "default" +const TENANT_ID = structures.TENANT_ID describe("/api/global/auth", () => { - let request = setup.getRequest() - let config = setup.getConfig() let code beforeAll(async () => { - await config.init() + await config.beforeAll() }) - afterAll(setup.afterAll) + afterAll(async () => { + await config.afterAll() + }) afterEach(() => { jest.clearAllMocks() diff --git a/packages/worker/src/api/routes/tests/configs.spec.js b/packages/worker/src/api/routes/tests/configs.spec.js index 9f0570023e..98e0fef17f 100644 --- a/packages/worker/src/api/routes/tests/configs.spec.js +++ b/packages/worker/src/api/routes/tests/configs.spec.js @@ -1,16 +1,14 @@ // mock the email system jest.mock("nodemailer") -const setup = require("./utilities") -setup.emailMock() +const { config, structures, mocks, request } = require("../../../tests") +mocks.email.mock() const { Configs } = require("@budibase/backend-core/constants") const { events } = require("@budibase/backend-core") describe("configs", () => { - let request = setup.getRequest() - let config = setup.getConfig() beforeAll(async () => { - await config.init() + await config.beforeAll() }) beforeEach(() => { @@ -18,15 +16,14 @@ describe("configs", () => { }) afterAll(async () => { - await setup.afterAll() + await config.afterAll() }) describe("post /api/global/configs", () => { - const saveConfig = async (conf, type, _id, _rev) => { + const saveConfig = async (conf, _id, _rev) => { const data = { - type, - config: conf, + ...conf, _id, _rev } @@ -46,14 +43,8 @@ describe("configs", () => { describe("google", () => { const saveGoogleConfig = async (conf, _id, _rev) => { - const googleConfig = { - clientID: "clientID", - clientSecret: "clientSecret", - activated: true, - ...conf - } - - return saveConfig(googleConfig, Configs.GOOGLE, _id, _rev) + const googleConfig = structures.configs.google(conf) + return saveConfig(googleConfig, _id, _rev) } describe("create", () => { @@ -106,19 +97,8 @@ describe("configs", () => { describe("oidc", () => { const saveOIDCConfig = async (conf, _id, _rev) => { - const oidcConfig = { - configs: [{ - clientID: "clientID", - clientSecret: "clientSecret", - configUrl: "http://example.com", - logo: "logo", - name: "oidc", - uuid: "uuid", - activated: true, - ...conf - }] - } - return saveConfig(oidcConfig, Configs.OIDC, _id, _rev) + const oidcConfig = structures.configs.oidc(conf) + return saveConfig(oidcConfig, _id, _rev) } describe("create", () => { @@ -169,6 +149,34 @@ describe("configs", () => { }) }) + + describe("smtp", () => { + const saveSMTPConfig = async (conf, _id, _rev) => { + const smtpConfig = structures.configs.smtp(conf) + return saveConfig(smtpConfig, _id, _rev) + } + + describe("create", () => { + it ("should create SMTP config", async () => { + await config.deleteConfig(Configs.SMTP) + await saveSMTPConfig() + expect(events.email.SMTPUpdated).not.toBeCalled() + expect(events.email.SMTPCreated).toBeCalledTimes(1) + await config.deleteConfig(Configs.SMTP) + }) + }) + + describe("update", () => { + it ("should update SMTP config", async () => { + const smtpConf = await saveSMTPConfig() + jest.clearAllMocks() + await saveSMTPConfig(smtpConf.config, smtpConf._id, smtpConf._rev) + expect(events.email.SMTPCreated).not.toBeCalled() + expect(events.email.SMTPUpdated).toBeCalledTimes(1) + await config.deleteConfig(Configs.SMTP) + }) + }) + }) }) it("should return the correct checklist status based on the state of the budibase installation", async () => { diff --git a/packages/worker/src/api/routes/tests/email.spec.js b/packages/worker/src/api/routes/tests/email.spec.js index 4cc7ca2d26..e90d953880 100644 --- a/packages/worker/src/api/routes/tests/email.spec.js +++ b/packages/worker/src/api/routes/tests/email.spec.js @@ -1,19 +1,20 @@ jest.mock("nodemailer") -const setup = require("./utilities") -const sendMailMock = setup.emailMock() +const { config, mocks, structures, request } = require("../../../tests") +const sendMailMock = mocks.email.mock() const { EmailTemplatePurpose } = require("../../../constants") -const { TENANT_ID } = require("./utilities/structures") + +const TENANT_ID = structures.TENANT_ID describe("/api/global/email", () => { - let request = setup.getRequest() - let config = setup.getConfig() beforeAll(async () => { - await config.init() + await config.beforeAll() }) - afterAll(setup.afterAll) + afterAll(async () => { + await config.afterAll() + }) it("should be able to send an email (with mocking)", async () => { // initially configure settings diff --git a/packages/worker/src/api/routes/tests/realEmail.spec.js b/packages/worker/src/api/routes/tests/realEmail.spec.js index d0cfd24010..c440eb13b3 100644 --- a/packages/worker/src/api/routes/tests/realEmail.spec.js +++ b/packages/worker/src/api/routes/tests/realEmail.spec.js @@ -1,17 +1,17 @@ -const setup = require("./utilities") +const { config, request } = require("../../../tests") const { EmailTemplatePurpose } = require("../../../constants") const nodemailer = require("nodemailer") const fetch = require("node-fetch") describe("/api/global/email", () => { - let request = setup.getRequest() - let config = setup.getConfig() beforeAll(async () => { - await config.init() + await config.beforeAll() }) - afterAll(setup.afterAll) + afterAll(async () => { + await config.afterAll() + }) async function sendRealEmail(purpose) { let response, text diff --git a/packages/worker/src/api/routes/tests/users.spec.js b/packages/worker/src/api/routes/tests/users.spec.js index 310ae0fe20..be9807c5d4 100644 --- a/packages/worker/src/api/routes/tests/users.spec.js +++ b/packages/worker/src/api/routes/tests/users.spec.js @@ -1,17 +1,17 @@ jest.mock("nodemailer") -const setup = require("./utilities") -const sendMailMock = setup.emailMock() +const { config, request, mocks } = require("../../../tests") +const sendMailMock = mocks.email.mock() describe("/api/global/users", () => { - let request = setup.getRequest() - let config = setup.getConfig() let code beforeAll(async () => { - await config.init() + await config.beforeAll() }) - afterAll(setup.afterAll) + afterAll(async () => { + await config.afterAll() + }) it("should be able to generate an invitation", async () => { // initially configure settings diff --git a/packages/worker/src/api/routes/tests/utilities/controllers.js b/packages/worker/src/api/routes/tests/utilities/controllers.js deleted file mode 100644 index 45216ae634..0000000000 --- a/packages/worker/src/api/routes/tests/utilities/controllers.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - email: require("../../../controllers/global/email"), - workspaces: require("../../../controllers/global/workspaces"), - config: require("../../../controllers/global/configs"), - templates: require("../../../controllers/global/templates"), - users: require("../../../controllers/global/users"), -} diff --git a/packages/worker/src/api/routes/tests/utilities/index.js b/packages/worker/src/api/routes/tests/utilities/index.js deleted file mode 100644 index a639caef60..0000000000 --- a/packages/worker/src/api/routes/tests/utilities/index.js +++ /dev/null @@ -1,41 +0,0 @@ -const TestConfig = require("./TestConfiguration") - -let request, config - -exports.beforeAll = () => { - config = new TestConfig() - request = config.getRequest() -} - -exports.afterAll = async () => { - if (config) { - await config.end() - } - request = null - config = null -} - -exports.getRequest = () => { - if (!request) { - exports.beforeAll() - } - return request -} - -exports.getConfig = () => { - if (!config) { - exports.beforeAll() - } - return config -} - -exports.emailMock = () => { - // mock the email system - const sendMailMock = jest.fn() - const nodemailer = require("nodemailer") - nodemailer.createTransport.mockReturnValue({ - sendMail: sendMailMock, - verify: jest.fn(), - }) - return sendMailMock -} diff --git a/packages/worker/src/api/routes/tests/utilities/mocks/index.js b/packages/worker/src/api/routes/tests/utilities/mocks/index.js deleted file mode 100644 index 1e7730932f..0000000000 --- a/packages/worker/src/api/routes/tests/utilities/mocks/index.js +++ /dev/null @@ -1 +0,0 @@ -require("./core") diff --git a/packages/worker/src/api/routes/tests/utilities/structures.js b/packages/worker/src/api/routes/tests/utilities/structures.js deleted file mode 100644 index 45f1f0077c..0000000000 --- a/packages/worker/src/api/routes/tests/utilities/structures.js +++ /dev/null @@ -1,2 +0,0 @@ -exports.TENANT_ID = "default" -exports.CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306" diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/tests/TestConfiguration.js similarity index 65% rename from packages/worker/src/api/routes/tests/utilities/TestConfiguration.js rename to packages/worker/src/tests/TestConfiguration.js index 0de0ca3234..a718f7b8b9 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/tests/TestConfiguration.js @@ -1,22 +1,22 @@ require("./mocks") -require("../../../../db").init() -const env = require("../../../../environment") +require("../db").init() +const env = require("../environment") const controllers = require("./controllers") const supertest = require("supertest") const { jwt } = require("@budibase/backend-core/auth") const { Cookies, Headers } = require("@budibase/backend-core/constants") -const { Configs, LOGO_URL } = require("../../../../constants") +const { Configs } = require("../constants") const { getGlobalUserByEmail } = require("@budibase/backend-core/utils") const { createASession } = require("@budibase/backend-core/sessions") -const { newid } = require("@budibase/backend-core/src/hashing") const { TENANT_ID, CSRF_TOKEN } = require("./structures") +const structures = require("./structures") const { doInTenant } = require("@budibase/backend-core/tenancy") class TestConfiguration { constructor(openServer = true) { if (openServer) { - env.PORT = 4012 - this.server = require("../../../../index") + env.PORT = "0" // random port + this.server = require("../index") // we need the request for logging in, involves cookies, hard to fake this.request = supertest(this.server) } @@ -26,6 +26,8 @@ class TestConfiguration { return this.request } + // UTILS + async _req(config, params, controlFunc) { const request = {} // fake cookies, we don't need them @@ -49,25 +51,37 @@ class TestConfiguration { return request.body } - async init(createUser = true) { - if (createUser) { - // create a test user - await this._req( - { - email: "test@test.com", - password: "test", - _id: "us_uuid1", - builder: { - global: true, - }, - admin: { - global: true, - }, - }, - null, - controllers.users.save - ) + // SETUP / TEARDOWN + + async beforeAll() { + await this.login() + } + + async afterAll() { + if (this.server) { + await this.server.close() } + } + + // USER / AUTH + + async login() { + // create a test user + await this._req( + { + email: "test@test.com", + password: "test", + _id: "us_uuid1", + builder: { + global: true, + }, + admin: { + global: true, + }, + }, + null, + controllers.users.save + ) await createASession("us_uuid1", { sessionId: "sessionid", tenantId: TENANT_ID, @@ -75,12 +89,6 @@ class TestConfiguration { }) } - async end() { - if (this.server) { - await this.server.close() - } - } - cookieHeader(cookies) { return { Cookie: [cookies], @@ -123,6 +131,20 @@ class TestConfiguration { ) } + async saveAdminUser() { + await this._req( + { + email: "testuser@test.com", + password: "test@test.com", + tenantId: TENANT_ID, + }, + null, + controllers.users.adminUser + ) + } + + // CONFIGS + async deleteConfig(type) { try { const cfg = await this._req( @@ -147,37 +169,26 @@ class TestConfiguration { } } + // CONFIGS - SETTINGS + async saveSettingsConfig() { await this.deleteConfig(Configs.SETTINGS) await this._req( - { - type: Configs.SETTINGS, - config: { - platformUrl: "http://localhost:10000", - logoUrl: LOGO_URL, - company: "Budibase", - }, - }, + structures.configs.settings(), null, controllers.config.save ) } - async saveOAuthConfig() { + // CONFIGS - GOOGLE + + async saveGoogleConfig() { await this.deleteConfig(Configs.GOOGLE) - await this._req( - { - type: Configs.GOOGLE, - config: { - clientID: "clientId", - clientSecret: "clientSecret", - }, - }, - null, - controllers.config.save - ) + await this._req(structures.configs.google(), null, controllers.config.save) } + // CONFIGS - OIDC + getOIDConfigCookie(configId) { const token = jwt.sign(configId, env.JWT_SECRET) return this.cookieHeader([[`${Cookies.OIDC_CONFIG}=${token}`]]) @@ -185,75 +196,27 @@ class TestConfiguration { async saveOIDCConfig() { await this.deleteConfig(Configs.OIDC) - const config = { - type: Configs.OIDC, - config: { - configs: [ - { - configUrl: "http://someconfigurl", - clientID: "clientId", - clientSecret: "clientSecret", - logo: "Microsoft", - name: "Active Directory", - uuid: newid(), - }, - ], - }, - } + const config = structures.configs.oidc() await this._req(config, null, controllers.config.save) return config } + // CONFIGS - SMTP + async saveSmtpConfig() { await this.deleteConfig(Configs.SMTP) - await this._req( - { - type: Configs.SMTP, - config: { - port: 12345, - host: "smtptesthost.com", - from: "testfrom@test.com", - subject: "Hello!", - }, - }, - null, - controllers.config.save - ) + await this._req(structures.configs.smtp(), null, controllers.config.save) } async saveEtherealSmtpConfig() { await this.deleteConfig(Configs.SMTP) await this._req( - { - type: Configs.SMTP, - config: { - port: 587, - host: "smtp.ethereal.email", - secure: false, - auth: { - user: "don.bahringer@ethereal.email", - pass: "yCKSH8rWyUPbnhGYk9", - }, - connectionTimeout: 1000, // must be less than the jest default of 5000 - }, - }, + structures.configs.smtpEthereal(), null, controllers.config.save ) } - - async saveAdminUser() { - await this._req( - { - email: "testuser@test.com", - password: "test@test.com", - tenantId: TENANT_ID, - }, - null, - controllers.users.adminUser - ) - } } module.exports = TestConfiguration diff --git a/packages/worker/src/tests/controllers.js b/packages/worker/src/tests/controllers.js new file mode 100644 index 0000000000..226355506f --- /dev/null +++ b/packages/worker/src/tests/controllers.js @@ -0,0 +1,7 @@ +module.exports = { + email: require("../api/controllers/global/email"), + workspaces: require("../api/controllers/global/workspaces"), + config: require("../api/controllers/global/configs"), + templates: require("../api/controllers/global/templates"), + users: require("../api/controllers/global/users"), +} diff --git a/packages/worker/src/tests/index.js b/packages/worker/src/tests/index.js new file mode 100644 index 0000000000..9aa88dc444 --- /dev/null +++ b/packages/worker/src/tests/index.js @@ -0,0 +1,12 @@ +const TestConfiguration = require("./TestConfiguration") +const structures = require("./structures") +const mocks = require("./mocks") +const config = new TestConfiguration() +const request = config.getRequest() + +module.exports = { + structures, + mocks, + config, + request, +} diff --git a/packages/worker/src/api/routes/tests/utilities/mocks/core.js b/packages/worker/src/tests/mocks/core.js similarity index 100% rename from packages/worker/src/api/routes/tests/utilities/mocks/core.js rename to packages/worker/src/tests/mocks/core.js diff --git a/packages/worker/src/tests/mocks/email.js b/packages/worker/src/tests/mocks/email.js new file mode 100644 index 0000000000..5e34c38f41 --- /dev/null +++ b/packages/worker/src/tests/mocks/email.js @@ -0,0 +1,10 @@ +exports.mock = () => { + // mock the email system + const sendMailMock = jest.fn() + const nodemailer = require("nodemailer") + nodemailer.createTransport.mockReturnValue({ + sendMail: sendMailMock, + verify: jest.fn(), + }) + return sendMailMock +} diff --git a/packages/worker/src/tests/mocks/index.js b/packages/worker/src/tests/mocks/index.js new file mode 100644 index 0000000000..575938870b --- /dev/null +++ b/packages/worker/src/tests/mocks/index.js @@ -0,0 +1,6 @@ +require("./core") +const email = require("./email") + +module.exports = { + email, +} diff --git a/packages/worker/src/tests/structures/configs.js b/packages/worker/src/tests/structures/configs.js new file mode 100644 index 0000000000..4856df572c --- /dev/null +++ b/packages/worker/src/tests/structures/configs.js @@ -0,0 +1,76 @@ +const { Configs, LOGO_URL } = require("../../constants") +const { utils } = require("@budibase/backend-core") + +exports.oidc = conf => { + return { + type: Configs.OIDC, + config: { + configs: [ + { + configUrl: "http://someconfigurl", + clientID: "clientId", + clientSecret: "clientSecret", + logo: "Microsoft", + name: "Active Directory", + uuid: utils.newid(), + activated: true, + ...conf, + }, + ], + }, + } +} + +exports.google = conf => { + return { + type: Configs.GOOGLE, + config: { + clientID: "clientId", + clientSecret: "clientSecret", + activated: true, + ...conf, + }, + } +} + +exports.smtp = conf => { + return { + type: Configs.SMTP, + config: { + port: 12345, + host: "smtptesthost.com", + from: "testfrom@test.com", + subject: "Hello!", + secure: false, + ...conf, + }, + } +} + +exports.smtpEthereal = () => { + return { + type: Configs.SMTP, + config: { + port: 587, + host: "smtp.ethereal.email", + secure: false, + auth: { + user: "don.bahringer@ethereal.email", + pass: "yCKSH8rWyUPbnhGYk9", + }, + connectionTimeout: 1000, // must be less than the jest default of 5000 + }, + } +} + +exports.settings = conf => { + return { + type: Configs.SETTINGS, + config: { + platformUrl: "http://localhost:10000", + logoUrl: LOGO_URL, + company: "Budibase", + ...conf, + }, + } +} diff --git a/packages/worker/src/tests/structures/index.js b/packages/worker/src/tests/structures/index.js new file mode 100644 index 0000000000..0d82b67d5e --- /dev/null +++ b/packages/worker/src/tests/structures/index.js @@ -0,0 +1,10 @@ +const configs = require("./configs") + +const TENANT_ID = "default" +const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306" + +module.exports = { + configs, + TENANT_ID, + CSRF_TOKEN, +}