Tests updating, all now passing, fixed some issues discovered by them.

This commit is contained in:
mike12345567 2022-01-28 15:43:51 +00:00
parent d3a90acc55
commit d5f8cc1023
12 changed files with 195 additions and 129 deletions

View File

@ -59,6 +59,10 @@ exports.updateTenantId = tenantId => {
exports.updateAppId = appId => { exports.updateAppId = appId => {
try { try {
cls.setOnContext(ContextKeys.APP_ID, appId) cls.setOnContext(ContextKeys.APP_ID, appId)
cls.setOnContext(ContextKeys.PROD_DB, null)
cls.setOnContext(ContextKeys.DEV_DB, null)
cls.setOnContext(ContextKeys.CURRENT_DB, null)
cls.setOnContext(ContextKeys.DB_OPTS, null)
} catch (err) { } catch (err) {
if (env.isTest()) { if (env.isTest()) {
TEST_APP_ID = appId TEST_APP_ID = appId

View File

@ -6,6 +6,7 @@ const db = jest.fn(() => {
} }
}) })
jest.mock("../../../../../db", () => db) jest.mock("../../../../../db", () => db)
require("@budibase/backend-core").init(require("../../../../../db"))
const { RestImporter } = require("../index") const { RestImporter } = require("../index")

View File

@ -60,7 +60,7 @@ exports.fetch = async ctx => {
} }
exports.clientFetch = async ctx => { exports.clientFetch = async ctx => {
const routing = await getRoutingStructure(ctx.appId) const routing = await getRoutingStructure()
let roleId = ctx.user.role._id let roleId = ctx.user.role._id
const roleIds = await getUserRoleHierarchy(roleId) const roleIds = await getUserRoleHierarchy(roleId)
for (let topLevel of Object.values(routing.routes)) { for (let topLevel of Object.values(routing.routes)) {

View File

@ -145,6 +145,7 @@ describe("/automations", () => {
let table = await config.createTable() let table = await config.createTable()
automation.definition.trigger.inputs.tableId = table._id automation.definition.trigger.inputs.tableId = table._id
automation.definition.steps[0].inputs.row.tableId = table._id automation.definition.steps[0].inputs.row.tableId = table._id
automation.appId = config.appId
automation = await config.createAutomation(automation) automation = await config.createAutomation(automation)
await setup.delay(500) await setup.delay(500)
const res = await testAutomation(config, automation) const res = await testAutomation(config, automation)

View File

@ -1,10 +1,15 @@
const setup = require("./utilities") const setup = require("./utilities")
const { basicScreen } = setup.structures const { basicScreen } = setup.structures
const { checkBuilderEndpoint } = require("./utilities/TestFunctions") const { checkBuilderEndpoint, runInProd } = require("./utilities/TestFunctions")
const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
const { doInAppContext } = require("@budibase/backend-core/context")
const route = "/test" const route = "/test"
// there are checks which are disabled in test env,
// these checks need to be enabled for this test
describe("/routing", () => { describe("/routing", () => {
let request = setup.getRequest() let request = setup.getRequest()
let config = setup.getConfig() let config = setup.getConfig()
@ -26,20 +31,24 @@ describe("/routing", () => {
describe("fetch", () => { describe("fetch", () => {
it("prevents a public user from accessing development app", async () => { it("prevents a public user from accessing development app", async () => {
await request await runInProd(() => {
.get(`/api/routing/client`) return request
.set(config.publicHeaders({ prodApp: false })) .get(`/api/routing/client`)
.expect(302) .set(config.publicHeaders({ prodApp: false }))
.expect(302)
})
}) })
it("prevents a non builder from accessing development app", async () => { it("prevents a non builder from accessing development app", async () => {
await request await runInProd(async () => {
.get(`/api/routing/client`) return request
.set(await config.roleHeaders({ .get(`/api/routing/client`)
roleId: BUILTIN_ROLE_IDS.BASIC, .set(await config.roleHeaders({
prodApp: false roleId: BUILTIN_ROLE_IDS.BASIC,
})) prodApp: false
.expect(302) }))
.expect(302)
})
}) })
it("returns the correct routing for basic user", async () => { it("returns the correct routing for basic user", async () => {
const res = await request const res = await request

View File

@ -3,7 +3,8 @@ const appController = require("../../../controllers/application")
const { AppStatus } = require("../../../../db/utils") const { AppStatus } = require("../../../../db/utils")
const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
const { TENANT_ID } = require("../../../../tests/utilities/structures") const { TENANT_ID } = require("../../../../tests/utilities/structures")
const { getAppDB } = require("@budibase/backend-core/context") const { getAppDB, doInAppContext } = require("@budibase/backend-core/context")
const env = require("../../../../environment")
function Request(appId, params) { function Request(appId, params) {
this.appId = appId this.appId = appId
@ -11,9 +12,15 @@ function Request(appId, params) {
this.request = {} this.request = {}
} }
function runRequest(appId, controlFunc, request) {
return doInAppContext(appId, async () => {
return controlFunc(request)
})
}
exports.getAllTableRows = async config => { exports.getAllTableRows = async config => {
const req = new Request(config.appId, { tableId: config.table._id }) const req = new Request(config.appId, { tableId: config.table._id })
await rowController.fetch(req) await runRequest(config.appId, rowController.fetch, req)
return req.body return req.body
} }
@ -26,14 +33,17 @@ exports.clearAllApps = async (tenantId = TENANT_ID) => {
} }
for (let app of apps) { for (let app of apps) {
const { appId } = app const { appId } = app
await appController.delete(new Request(null, { appId })) const req = new Request(null, { appId })
await runRequest(appId, appController.delete, req)
} }
} }
exports.clearAllAutomations = async config => { exports.clearAllAutomations = async config => {
const automations = await config.getAllAutomations() const automations = await config.getAllAutomations()
for (let auto of automations) { for (let auto of automations) {
await config.deleteAutomation(auto) await doInAppContext(config.appId, async () => {
await config.deleteAutomation(auto)
})
} }
} }
@ -101,15 +111,27 @@ exports.getDB = () => {
} }
exports.testAutomation = async (config, automation) => { exports.testAutomation = async (config, automation) => {
return await config.request return runRequest(automation.appId, async () => {
.post(`/api/automations/${automation._id}/test`) return await config.request
.send({ .post(`/api/automations/${automation._id}/test`)
row: { .send({
name: "Test", row: {
description: "TEST", name: "Test",
}, description: "TEST",
}) },
.set(config.defaultHeaders()) })
.expect("Content-Type", /json/) .set(config.defaultHeaders())
.expect(200) .expect("Content-Type", /json/)
.expect(200)
})
}
exports.runInProd = async func => {
const nodeEnv = env.NODE_ENV
const workerId = env.JEST_WORKER_ID
env._set("NODE_ENV", "PRODUCTION")
env._set("JEST_WORKER_ID", null)
await func()
env._set("NODE_ENV", nodeEnv)
env._set("JEST_WORKER_ID", workerId)
} }

View File

@ -2,7 +2,8 @@ function isTest() {
return ( return (
process.env.NODE_ENV === "jest" || process.env.NODE_ENV === "jest" ||
process.env.NODE_ENV === "cypress" || process.env.NODE_ENV === "cypress" ||
process.env.JEST_WORKER_ID != null (process.env.JEST_WORKER_ID != null &&
process.env.JEST_WORKER_ID !== "null")
) )
} }

View File

@ -13,6 +13,7 @@ const { isUserInAppTenant } = require("@budibase/backend-core/tenancy")
const { getCachedSelf } = require("../utilities/global") const { getCachedSelf } = require("../utilities/global")
const env = require("../environment") const env = require("../environment")
const { isWebhookEndpoint } = require("./utils") const { isWebhookEndpoint } = require("./utils")
const { doInAppContext } = require("@budibase/backend-core/context")
module.exports = async (ctx, next) => { module.exports = async (ctx, next) => {
// try to get the appID from the request // try to get the appID from the request
@ -40,13 +41,15 @@ module.exports = async (ctx, next) => {
} }
// deny access to application preview // deny access to application preview
if ( if (!env.isTest()) {
isDevAppID(requestAppId) && if (
!isWebhookEndpoint(ctx) && isDevAppID(requestAppId) &&
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global) !isWebhookEndpoint(ctx) &&
) { (!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
clearCookie(ctx, Cookies.CurrentApp) ) {
return ctx.redirect("/") clearCookie(ctx, Cookies.CurrentApp)
return ctx.redirect("/")
}
} }
let appId, let appId,
@ -67,44 +70,46 @@ module.exports = async (ctx, next) => {
return next() return next()
} }
let noCookieSet = false return doInAppContext(appId, async () => {
// if the user not in the right tenant then make sure they have no permissions let noCookieSet = false
// need to judge this only based on the request app ID, // if the user not in the right tenant then make sure they have no permissions
if ( // need to judge this only based on the request app ID,
env.MULTI_TENANCY && if (
ctx.user && env.MULTI_TENANCY &&
requestAppId && ctx.user &&
!isUserInAppTenant(requestAppId) requestAppId &&
) { !isUserInAppTenant(requestAppId)
// don't error, simply remove the users rights (they are a public user) ) {
delete ctx.user.builder // don't error, simply remove the users rights (they are a public user)
delete ctx.user.admin delete ctx.user.builder
delete ctx.user.roles delete ctx.user.admin
roleId = BUILTIN_ROLE_IDS.PUBLIC delete ctx.user.roles
noCookieSet = true roleId = BUILTIN_ROLE_IDS.PUBLIC
} noCookieSet = true
ctx.appId = appId
if (roleId) {
ctx.roleId = roleId
const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null
ctx.user = {
...ctx.user,
// override userID with metadata one
_id: userId,
userId,
roleId,
role: await getRole(appId, roleId),
} }
}
if (
(requestAppId !== appId ||
appCookie == null ||
appCookie.appId !== requestAppId) &&
!noCookieSet
) {
setCookie(ctx, { appId }, Cookies.CurrentApp)
}
return next() ctx.appId = appId
if (roleId) {
ctx.roleId = roleId
const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null
ctx.user = {
...ctx.user,
// override userID with metadata one
_id: userId,
userId,
roleId,
role: await getRole(roleId),
}
}
if (
(requestAppId !== appId ||
appCookie == null ||
appCookie.appId !== requestAppId) &&
!noCookieSet
) {
setCookie(ctx, { appId }, Cookies.CurrentApp)
}
return next()
})
} }

View File

@ -11,6 +11,9 @@ const authorizedMiddleware = require("../authorized")
const env = require("../../environment") const env = require("../../environment")
const { PermissionTypes, PermissionLevels } = require("@budibase/backend-core/permissions") const { PermissionTypes, PermissionLevels } = require("@budibase/backend-core/permissions")
require("@budibase/backend-core").init(require("../../db")) require("@budibase/backend-core").init(require("../../db"))
const { doInAppContext } = require("@budibase/backend-core/context")
const APP_ID = ""
class TestConfiguration { class TestConfiguration {
constructor(role) { constructor(role) {
@ -22,7 +25,7 @@ class TestConfiguration {
request: { request: {
url: "" url: ""
}, },
appId: "", appId: APP_ID,
auth: {}, auth: {},
next: this.next, next: this.next,
throw: this.throw throw: this.throw
@ -30,7 +33,9 @@ class TestConfiguration {
} }
executeMiddleware() { executeMiddleware() {
return this.middleware(this.ctx, this.next) return doInAppContext(APP_ID, () => {
return this.middleware(this.ctx, this.next)
})
} }
setUser(user) { setUser(user) {

View File

@ -1,6 +1,11 @@
mockAuthWithNoCookie() mockAuthWithNoCookie()
mockWorker() mockWorker()
jest.mock("@budibase/backend-core/db", () => ({
...jest.requireActual("@budibase/backend-core/db"),
dbExists: () => true,
}))
function mockWorker() { function mockWorker() {
jest.mock("../../utilities/workerRequests", () => ({ jest.mock("../../utilities/workerRequests", () => ({
getGlobalSelf: () => { getGlobalSelf: () => {
@ -50,6 +55,7 @@ function mockAuthWithCookie() {
return "app_test" return "app_test"
}, },
setCookie: jest.fn(), setCookie: jest.fn(),
clearCookie: jest.fn(),
getCookie: () => ({appId: "app_different", roleId: "PUBLIC"}), getCookie: () => ({appId: "app_different", roleId: "PUBLIC"}),
})) }))
jest.mock("@budibase/backend-core/constants", () => ({ jest.mock("@budibase/backend-core/constants", () => ({

View File

@ -1,3 +1,6 @@
const core = require("@budibase/backend-core")
const CouchDB = require("../../db")
core.init(CouchDB)
const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
const env = require("../../environment") const env = require("../../environment")
const { const {
@ -17,14 +20,11 @@ const supertest = require("supertest")
const { cleanup } = require("../../utilities/fileSystem") const { cleanup } = require("../../utilities/fileSystem")
const { Cookies, Headers } = require("@budibase/backend-core/constants") const { Cookies, Headers } = require("@budibase/backend-core/constants")
const { jwt } = require("@budibase/backend-core/auth") const { jwt } = require("@budibase/backend-core/auth")
const core = require("@budibase/backend-core")
const { getGlobalDB } = require("@budibase/backend-core/tenancy") const { getGlobalDB } = require("@budibase/backend-core/tenancy")
const { createASession } = require("@budibase/backend-core/sessions") const { createASession } = require("@budibase/backend-core/sessions")
const { user: userCache } = require("@budibase/backend-core/cache") const { user: userCache } = require("@budibase/backend-core/cache")
const CouchDB = require("../../db")
const newid = require("../../db/newid") const newid = require("../../db/newid")
const context = require("@budibase/backend-core/context") const context = require("@budibase/backend-core/context")
core.init(CouchDB)
const GLOBAL_USER_ID = "us_uuid1" const GLOBAL_USER_ID = "us_uuid1"
const EMAIL = "babs@babs.com" const EMAIL = "babs@babs.com"
@ -51,7 +51,6 @@ class TestConfiguration {
} }
async _req(config, params, controlFunc) { async _req(config, params, controlFunc) {
context.updateAppId(this.appId)
const request = {} const request = {}
// fake cookies, we don't need them // fake cookies, we don't need them
request.cookies = { set: () => {}, get: () => {} } request.cookies = { set: () => {}, get: () => {} }
@ -62,11 +61,21 @@ class TestConfiguration {
request.request = { request.request = {
body: config, body: config,
} }
if (params) { async function run() {
request.params = params if (params) {
request.params = params
}
await controlFunc(request)
return request.body
}
// check if already in a context
if (context.getAppId() == null) {
return context.doInAppContext(this.appId, async () => {
return run()
})
} else {
return run()
} }
await controlFunc(request)
return request.body
} }
async globalUser({ async globalUser({
@ -182,12 +191,14 @@ class TestConfiguration {
async deploy() { async deploy() {
await this._req(null, null, controllers.deploy.deployApp) await this._req(null, null, controllers.deploy.deployApp)
const prodAppId = this.getAppId().replace("_dev", "") const prodAppId = this.getAppId().replace("_dev", "")
const appPackage = await this._req( return context.doInAppContext(prodAppId, async () => {
null, const appPackage = await this._req(
{ appId: prodAppId }, null,
controllers.app.fetchAppPackage { appId: prodAppId },
) controllers.app.fetchAppPackage
return appPackage.application )
return appPackage.application
})
} }
async updateTable(config = null) { async updateTable(config = null) {
@ -416,46 +427,47 @@ class TestConfiguration {
async login({ roleId, userId, builder, prodApp = false } = {}) { async login({ roleId, userId, builder, prodApp = false } = {}) {
const appId = prodApp ? this.prodAppId : this.appId const appId = prodApp ? this.prodAppId : this.appId
return context.doInAppContext(appId, async () => {
userId = !userId ? `us_uuid1` : userId userId = !userId ? `us_uuid1` : userId
if (!this.request) { if (!this.request) {
throw "Server has not been opened, cannot login." throw "Server has not been opened, cannot login."
} }
// make sure the user exists in the global DB // make sure the user exists in the global DB
if (roleId !== BUILTIN_ROLE_IDS.PUBLIC) { if (roleId !== BUILTIN_ROLE_IDS.PUBLIC) {
await this.globalUser({ await this.globalUser({
userId, id: userId,
builder, builder,
roles: { [this.prodAppId]: roleId }, roles: { [this.prodAppId]: roleId },
})
}
await createASession(userId, {
sessionId: "sessionid",
tenantId: TENANT_ID,
}) })
} // have to fake this
await createASession(userId, { const auth = {
sessionId: "sessionid", userId,
tenantId: TENANT_ID, sessionId: "sessionid",
}) tenantId: TENANT_ID,
// have to fake this }
const auth = { const app = {
userId, roleId: roleId,
sessionId: "sessionid", appId,
tenantId: TENANT_ID, }
} const authToken = jwt.sign(auth, env.JWT_SECRET)
const app = { const appToken = jwt.sign(app, env.JWT_SECRET)
roleId: roleId,
appId,
}
const authToken = jwt.sign(auth, env.JWT_SECRET)
const appToken = jwt.sign(app, env.JWT_SECRET)
// returning necessary request headers // returning necessary request headers
await userCache.invalidateUser(userId) await userCache.invalidateUser(userId)
return { return {
Accept: "application/json", Accept: "application/json",
Cookie: [ Cookie: [
`${Cookies.Auth}=${authToken}`, `${Cookies.Auth}=${authToken}`,
`${Cookies.CurrentApp}=${appToken}`, `${Cookies.CurrentApp}=${appToken}`,
], ],
[Headers.APP_ID]: appId, [Headers.APP_ID]: appId,
} }
})
} }
} }

View File

@ -48,7 +48,7 @@ exports.getCachedSelf = async (ctx, appId) => {
// this has to be tenant aware, can't depend on the context to find it out // this has to be tenant aware, can't depend on the context to find it out
// running some middlewares before the tenancy causes context to break // running some middlewares before the tenancy causes context to break
const user = await userCache.getUser(ctx.user._id) const user = await userCache.getUser(ctx.user._id)
return processUser(user, appId) return processUser(user, { appId })
} }
exports.getRawGlobalUser = async userId => { exports.getRawGlobalUser = async userId => {