Server flaky tests fixes - improving tenancy config

This commit is contained in:
Rory Powell 2023-02-23 13:43:01 +00:00
parent 2d993adec8
commit 4e1bebe897
8 changed files with 62 additions and 61 deletions

View File

@ -10,7 +10,6 @@ import {
isCloudAccount,
isSSOAccount,
TenantGroup,
SettingsConfig,
CloudAccount,
UserIdentity,
InstallationGroup,

View File

@ -58,7 +58,7 @@ export async function exportApps(ctx: Ctx) {
}
async function checkHasBeenImported() {
if (!env.SELF_HOSTED || env.MULTI_TENANCY) {
if (!env.SELF_HOSTED) {
return true
}
const apps = await dbCore.getAllApps({ all: true })
@ -72,7 +72,7 @@ export async function hasBeenImported(ctx: Ctx) {
}
export async function importApps(ctx: Ctx) {
if (!env.SELF_HOSTED || env.MULTI_TENANCY) {
if (!env.SELF_HOSTED) {
ctx.throw(400, "Importing only allowed in self hosted environments.")
}
const beenImported = await checkHasBeenImported()

View File

@ -1,3 +1,5 @@
import { App } from "@budibase/types"
jest.setTimeout(30000)
import { AppStatus } from "../../../db/utils"
@ -5,6 +7,7 @@ import { AppStatus } from "../../../db/utils"
import * as setup from "./utilities"
import { wipeDb } from "./utilities/TestFunctions"
import { tenancy } from "@budibase/backend-core"
describe("/cloud", () => {
let request = setup.getRequest()!
@ -12,18 +15,10 @@ describe("/cloud", () => {
afterAll(setup.afterAll)
beforeAll(() => {
beforeAll(async () => {
// Importing is only allowed in self hosted environments
config.modeSelf()
})
beforeEach(async () => {
await config.init()
})
afterEach(async () => {
// clear all mocks
jest.clearAllMocks()
config.modeSelf()
})
describe("import", () => {
@ -32,30 +27,28 @@ describe("/cloud", () => {
// import will not run
await wipeDb()
// get a count of apps before the import
const preImportApps = await request
.get(`/api/applications?status=${AppStatus.ALL}`)
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
// Perform the import
const res = await request
.post(`/api/cloud/import`)
.set(config.publicHeaders())
.attach("importFile", "src/api/routes/tests/data/export-test.tar.gz")
.set(config.defaultHeaders())
.expect(200)
expect(res.body.message).toEqual("Apps successfully imported.")
// get a count of apps after the import
const postImportApps = await request
.get(`/api/applications?status=${AppStatus.ALL}`)
.set(config.defaultHeaders())
.set(config.publicHeaders())
.expect("Content-Type", /json/)
.expect(200)
const apps = postImportApps.body as App[]
// There are two apps in the file that was imported so check for this
expect(postImportApps.body.length).toEqual(2)
expect(apps.length).toEqual(2)
// The new tenant id was assigned to the imported apps
expect(tenancy.getTenantIDFromAppID(apps[0].appId)).toBe(
config.getTenantId()
)
})
})
})

View File

@ -2,7 +2,6 @@ import * as rowController from "../../../controllers/row"
import * as appController from "../../../controllers/application"
import { AppStatus } from "../../../../db/utils"
import { roles, tenancy, context } from "@budibase/backend-core"
import { TENANT_ID } from "../../../../tests/utilities/structures"
import env from "../../../../environment"
import { db } from "@budibase/backend-core"
import Nano from "@budibase/nano"
@ -33,7 +32,7 @@ export const getAllTableRows = async (config: any) => {
}
export const clearAllApps = async (
tenantId = TENANT_ID,
tenantId: string,
exceptions: Array<string> = []
) => {
await tenancy.doInTenant(tenantId, async () => {

View File

@ -8,9 +8,8 @@ jest.mock("@budibase/backend-core", () => {
}
}
})
const { tenancy, db: dbCore } = require("@budibase/backend-core")
const { context, db: dbCore } = require("@budibase/backend-core")
const TestConfig = require("../../../tests/utilities/TestConfiguration")
const { TENANT_ID } = require("../../../tests/utilities/structures")
// mock email view creation
@ -26,8 +25,8 @@ describe("run", () => {
afterAll(config.end)
it("runs successfully", async () => {
await tenancy.doInTenant(TENANT_ID, async () => {
const globalDb = tenancy.getGlobalDB()
await config.doInTenant(async () => {
const globalDb = context.getGlobalDB()
await migration.run(globalDb)
expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
})

View File

@ -8,3 +8,4 @@ process.env.BUDIBASE_DIR = tmpdir("budibase-unittests")
process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
process.env.ENABLE_4XX_HTTP_LOGGING = "0"
process.env.MOCK_REDIS = "1"
process.env.PLATFORM_URL = "http://localhost:10000"

View File

@ -21,7 +21,6 @@ import {
basicScreen,
basicLayout,
basicWebhook,
TENANT_ID,
} from "./structures"
import {
constants,
@ -41,8 +40,8 @@ import { generateUserMetadataID } from "../../db/utils"
import { startup } from "../../startup"
import supertest from "supertest"
import {
App,
AuthToken,
Database,
Datasource,
Row,
SourceName,
@ -63,7 +62,7 @@ class TestConfiguration {
started: boolean
appId: string | null
allApps: any[]
app: any
app?: App
prodApp: any
prodAppId: any
user: any
@ -73,7 +72,7 @@ class TestConfiguration {
linkedTable: any
automation: any
datasource: any
tenantId: string | null
tenantId?: string
defaultUserValues: DefaultUserValues
constructor(openServer = true) {
@ -89,7 +88,6 @@ class TestConfiguration {
}
this.appId = null
this.allApps = []
this.tenantId = null
this.defaultUserValues = this.populateDefaultUserValues()
}
@ -154,19 +152,10 @@ class TestConfiguration {
// use a new id as the name to avoid name collisions
async init(appName = newid()) {
this.defaultUserValues = this.populateDefaultUserValues()
if (context.isMultiTenant()) {
this.tenantId = structures.tenant.id()
}
if (!this.started) {
await startup()
}
this.user = await this.globalUser()
this.globalUserId = this.user._id
this.userMetadataId = generateUserMetadataID(this.globalUserId)
return this.createApp(appName)
return this.newTenant(appName)
}
end() {
@ -182,24 +171,22 @@ class TestConfiguration {
}
// MODES
#setMultiTenancy = (value: boolean) => {
setMultiTenancy = (value: boolean) => {
env._set("MULTI_TENANCY", value)
coreEnv._set("MULTI_TENANCY", value)
}
#setSelfHosted = (value: boolean) => {
setSelfHosted = (value: boolean) => {
env._set("SELF_HOSTED", value)
coreEnv._set("SELF_HOSTED", value)
}
modeCloud = () => {
this.#setSelfHosted(false)
this.#setMultiTenancy(true)
this.setSelfHosted(false)
}
modeSelf = () => {
this.#setSelfHosted(true)
this.#setMultiTenancy(false)
this.setSelfHosted(true)
}
// UTILS
@ -354,6 +341,8 @@ class TestConfiguration {
})
}
// HEADERS
defaultHeaders(extras = {}) {
const tenantId = this.getTenantId()
const authObj: AuthToken = {
@ -374,6 +363,7 @@ class TestConfiguration {
`${constants.Cookie.CurrentApp}=${appToken}`,
],
[constants.Header.CSRF_TOKEN]: this.defaultUserValues.csrfToken,
Host: this.tenantHost(),
...extras,
}
@ -383,10 +373,6 @@ class TestConfiguration {
return headers
}
getTenantId() {
return this.tenantId || TENANT_ID
}
publicHeaders({ prodApp = true } = {}) {
const appId = prodApp ? this.prodAppId : this.appId
@ -397,9 +383,7 @@ class TestConfiguration {
headers[constants.Header.APP_ID] = appId
}
if (this.tenantId) {
headers[constants.Header.TENANT_ID] = this.tenantId
}
headers[constants.Header.TENANT_ID] = this.getTenantId()
return headers
}
@ -413,6 +397,34 @@ class TestConfiguration {
return this.login({ email, roleId, builder, prodApp })
}
// TENANCY
tenantHost() {
const tenantId = this.getTenantId()
const platformHost = new URL(coreEnv.PLATFORM_URL).host.split(":")[0]
return `${tenantId}.${platformHost}`
}
getTenantId() {
if (!this.tenantId) {
throw new Error("no test tenant id - init has not been called")
}
return this.tenantId
}
async newTenant(appName = newid()): Promise<App> {
this.defaultUserValues = this.populateDefaultUserValues()
this.tenantId = structures.tenant.id()
this.user = await this.globalUser()
this.globalUserId = this.user._id
this.userMetadataId = generateUserMetadataID(this.globalUserId)
return this.createApp(appName)
}
doInTenant(task: any) {
return context.doInTenant(this.getTenantId(), task)
}
// API
async generateApiKey(userId = this.defaultUserValues.globalUserId) {
@ -432,7 +444,7 @@ class TestConfiguration {
}
// APP
async createApp(appName: string) {
async createApp(appName: string): Promise<App> {
// create dev app
// clear any old app
this.appId = null
@ -442,7 +454,7 @@ class TestConfiguration {
null,
controllers.app.create
)
this.appId = this.app.appId
this.appId = this.app?.appId!
})
return await context.doInAppContext(this.appId, async () => {
// create production app

View File

@ -13,8 +13,6 @@ import {
const { v4: uuidv4 } = require("uuid")
export const TENANT_ID = "default"
export function basicTable() {
return {
name: "TestTable",