1
0
Fork 0
mirror of synced 2024-05-04 12:33:42 +12:00

Test fixes

This commit is contained in:
Rory Powell 2022-11-11 15:43:41 +00:00
parent 0bad2dd9ae
commit 80b823f6cf
33 changed files with 285 additions and 189 deletions

View file

@ -21,7 +21,6 @@ export const buildMatcherRegex = (
const suffix = match.endsWith("/") ? "/" : ""
const pattern = "/.*" + suffix
route = route.replace(match, pattern)
console.log(route)
}
}

View file

@ -225,6 +225,7 @@ export const getTenantIDFromCtx = (
}
}
// path
if (isAllowed(TenantResolutionStrategy.PATH)) {
// params - have to parse manually due to koa-router not run yet
const match = ctx.matched.find(

View file

@ -1 +1,7 @@
import { v4 as uuid } from "uuid"
export { v4 as uuid } from "uuid"
export const email = () => {
return `${uuid()}@test.com`
}

View file

@ -51,3 +51,9 @@ export interface SearchUsersRequest {
appId?: string
userIds?: string[]
}
export interface CreateAdminUserRequest {
email: string
password: string
tenantId: string
}

View file

@ -5,6 +5,7 @@ import {
BulkUserRequest,
BulkUserResponse,
CloudAccount,
CreateAdminUserRequest,
InviteUserRequest,
InviteUsersRequest,
SearchUsersRequest,
@ -67,7 +68,8 @@ const parseBooleanParam = (param: any) => {
}
export const adminUser = async (ctx: any) => {
const { email, password, tenantId } = ctx.request.body
const { email, password, tenantId } = ctx.request
.body as CreateAdminUserRequest
await tenancy.doInTenant(tenantId, async () => {
// account portal sends a pre-hashed password - honour param to prevent double hashing
const hashPassword = parseBooleanParam(ctx.request.query.hashPassword)

View file

@ -11,8 +11,8 @@ const _delete = async (ctx: BBContext) => {
}
try {
await deprovisioning.deleteTenant(tenantId)
await quotas.bustCache()
await deprovisioning.deleteTenant(tenantId)
ctx.status = 204
} catch (err) {
ctx.log.error(err)

View file

@ -1,11 +1,10 @@
jest.mock("nodemailer")
import { TestConfiguration, mocks, API } from "../../../../tests"
import { TestConfiguration, mocks } from "../../../../tests"
const sendMailMock = mocks.email.mock()
import { events } from "@budibase/backend-core"
describe("/api/global/auth", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -20,12 +19,14 @@ describe("/api/global/auth", () => {
})
it("should logout", async () => {
await api.auth.logout()
await config.api.auth.logout()
expect(events.auth.logout).toBeCalledTimes(1)
})
it("should be able to generate password reset email", async () => {
const { res, code } = await api.auth.requestPasswordReset(sendMailMock)
const { res, code } = await config.api.auth.requestPasswordReset(
sendMailMock
)
const user = await config.getUser("test@test.com")
expect(res.body).toEqual({
@ -39,11 +40,11 @@ describe("/api/global/auth", () => {
})
it("should allow resetting user password with code", async () => {
const { code } = await api.auth.requestPasswordReset(sendMailMock)
const { code } = await config.api.auth.requestPasswordReset(sendMailMock)
const user = await config.getUser("test@test.com")
delete user.password
const res = await api.auth.updatePassword(code)
const res = await config.api.auth.updatePassword(code)
expect(res.body).toEqual({ message: "password reset successfully." })
expect(events.user.passwordReset).toBeCalledTimes(1)
@ -80,7 +81,7 @@ describe("/api/global/auth", () => {
describe("oidc configs", () => {
it("should load strategy and delegate to passport", async () => {
await api.configs.getOIDCConfig(configId)
await config.api.configs.getOIDCConfig(configId)
expect(passportSpy).toBeCalledWith(mockStrategyReturn, {
scope: ["profile", "email", "offline_access"],
@ -91,7 +92,7 @@ describe("/api/global/auth", () => {
describe("oidc callback", () => {
it("should load strategy and delegate to passport", async () => {
await api.configs.OIDCCallback(configId)
await config.api.configs.OIDCCallback(configId)
expect(passportSpy).toBeCalledWith(
mockStrategyReturn,

View file

@ -1,12 +1,11 @@
// mock the email system
jest.mock("nodemailer")
import { TestConfiguration, structures, mocks, API } from "../../../../tests"
import { TestConfiguration, structures, mocks } from "../../../../tests"
mocks.email.mock()
import { Configs, events } from "@budibase/backend-core"
describe("configs", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -28,7 +27,7 @@ describe("configs", () => {
_rev,
}
const res = await api.configs.saveConfig(data)
const res = await config.api.configs.saveConfig(data)
return {
...data,
@ -266,7 +265,7 @@ describe("configs", () => {
it("should return the correct checklist status based on the state of the budibase installation", async () => {
await config.saveSmtpConfig()
const res = await api.configs.getConfigChecklist()
const res = await config.api.configs.getConfigChecklist()
const checklist = res.body
expect(checklist.apps.checked).toBeFalsy()

View file

@ -1,11 +1,10 @@
jest.mock("nodemailer")
import { TestConfiguration, mocks, API } from "../../../../tests"
import { TestConfiguration, mocks } from "../../../../tests"
const sendMailMock = mocks.email.mock()
import { EmailTemplatePurpose } from "../../../../constants"
describe("/api/global/email", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -20,7 +19,9 @@ describe("/api/global/email", () => {
await config.saveSmtpConfig()
await config.saveSettingsConfig()
const res = await api.emails.sendEmail(EmailTemplatePurpose.INVITATION)
const res = await config.api.emails.sendEmail(
EmailTemplatePurpose.INVITATION
)
expect(res.body.message).toBeDefined()
expect(sendMailMock).toHaveBeenCalled()

View file

@ -1,8 +1,9 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
// TODO
describe("/api/global/license", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -16,7 +17,9 @@ describe("/api/global/license", () => {
jest.clearAllMocks()
})
describe("POST /api/global/license/activate", () => {})
describe("POST /api/global/license/activate", () => {
it("activates license", () => {})
})
describe("POST /api/global/license/refresh", () => {})

View file

@ -1,4 +1,4 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
import { EmailTemplatePurpose } from "../../../../constants"
const nodemailer = require("nodemailer")
const fetch = require("node-fetch")
@ -8,7 +8,6 @@ jest.setTimeout(30000)
describe("/api/global/email", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -35,7 +34,7 @@ describe("/api/global/email", () => {
await Promise.race([config.saveEtherealSmtpConfig(), timeout()])
await Promise.race([config.saveSettingsConfig(), timeout()])
const res = await api.emails.sendEmail(purpose).timeout(20000)
const res = await config.api.emails.sendEmail(purpose).timeout(20000)
// ethereal hiccup, can't test right now
if (res.status >= 300) {
return

View file

@ -1,8 +1,9 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
// TODO
describe("/api/global/roles", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -16,7 +17,9 @@ describe("/api/global/roles", () => {
jest.clearAllMocks()
})
describe("GET /api/global/roles", () => {})
describe("GET /api/global/roles", () => {
it("retrieves roles", () => {})
})
describe("GET /api/global/roles/:appId", () => {})

View file

@ -1,10 +1,9 @@
jest.mock("nodemailer")
import { TestConfiguration, API, mocks } from "../../../../tests"
import { TestConfiguration, mocks } from "../../../../tests"
import { events } from "@budibase/backend-core"
describe("/api/global/self", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -24,7 +23,7 @@ describe("/api/global/self", () => {
await config.createSession(user)
delete user.password
const res = await api.self.updateSelf(user)
const res = await config.api.self.updateSelf(user)
const dbUser = await config.getUser(user.email)
user._rev = dbUser._rev
@ -40,7 +39,7 @@ describe("/api/global/self", () => {
await config.createSession(user)
user.password = "newPassword"
const res = await api.self.updateSelf(user)
const res = await config.api.self.updateSelf(user)
const dbUser = await config.getUser(user.email)
user._rev = dbUser._rev

View file

@ -1,8 +1,9 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
// TODO
describe("/api/global/template", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -16,7 +17,9 @@ describe("/api/global/template", () => {
jest.clearAllMocks()
})
describe("GET /api/global/template/definitions", () => {})
describe("GET /api/global/template/definitions", () => {
it("retrieves definitions", () => {})
})
describe("POST /api/global/template", () => {})

View file

@ -6,14 +6,12 @@ import {
mocks,
structures,
TENANT_1,
API,
} from "../../../../tests"
const sendMailMock = mocks.email.mock()
import { events, tenancy } from "@budibase/backend-core"
describe("/api/global/users", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -30,7 +28,10 @@ describe("/api/global/users", () => {
describe("invite", () => {
it("should be able to generate an invitation", async () => {
const email = structures.users.newEmail()
const { code, res } = await api.users.sendUserInvite(sendMailMock, email)
const { code, res } = await config.api.users.sendUserInvite(
sendMailMock,
email
)
expect(res.body).toEqual({ message: "Invitation has been sent." })
expect(sendMailMock).toHaveBeenCalled()
@ -39,7 +40,7 @@ describe("/api/global/users", () => {
})
it("should not be able to generate an invitation for existing user", async () => {
const { code, res } = await api.users.sendUserInvite(
const { code, res } = await config.api.users.sendUserInvite(
sendMailMock,
config.defaultUser!.email,
400
@ -53,9 +54,12 @@ describe("/api/global/users", () => {
it("should be able to create new user from invite", async () => {
const email = structures.users.newEmail()
const { code } = await api.users.sendUserInvite(sendMailMock, email)
const { code } = await config.api.users.sendUserInvite(
sendMailMock,
email
)
const res = await api.users.acceptInvite(code)
const res = await config.api.users.acceptInvite(code)
expect(res.body._id).toBeDefined()
const user = await config.getUser(email)
@ -74,7 +78,7 @@ describe("/api/global/users", () => {
})
const request = [newUserInvite(), newUserInvite()]
const res = await api.users.sendMultiUserInvite(request)
const res = await config.api.users.sendMultiUserInvite(request)
const body = res.body as InviteUsersResponse
expect(body.successful.length).toBe(2)
@ -86,7 +90,7 @@ describe("/api/global/users", () => {
it("should not be able to generate an invitation for existing user", async () => {
const request = [{ email: config.defaultUser!.email, userInfo: {} }]
const res = await api.users.sendMultiUserInvite(request)
const res = await config.api.users.sendMultiUserInvite(request)
const body = res.body as InviteUsersResponse
expect(body.successful.length).toBe(0)
@ -102,7 +106,7 @@ describe("/api/global/users", () => {
const user = await config.createUser()
jest.clearAllMocks()
const response = await api.users.bulkCreateUsers([user])
const response = await config.api.users.bulkCreateUsers([user])
expect(response.created?.successful.length).toBe(0)
expect(response.created?.unsuccessful.length).toBe(1)
@ -115,7 +119,7 @@ describe("/api/global/users", () => {
jest.resetAllMocks()
await tenancy.doInTenant(TENANT_1, async () => {
const response = await api.users.bulkCreateUsers([user])
const response = await config.api.users.bulkCreateUsers([user])
expect(response.created?.successful.length).toBe(0)
expect(response.created?.unsuccessful.length).toBe(1)
@ -126,11 +130,11 @@ describe("/api/global/users", () => {
it("should ignore accounts using the same email", async () => {
const account = structures.accounts.account()
const resp = await api.accounts.saveMetadata(account)
const resp = await config.api.accounts.saveMetadata(account)
const user = structures.users.user({ email: resp.email })
jest.clearAllMocks()
const response = await api.users.bulkCreateUsers([user])
const response = await config.api.users.bulkCreateUsers([user])
expect(response.created?.successful.length).toBe(0)
expect(response.created?.unsuccessful.length).toBe(1)
@ -143,7 +147,11 @@ describe("/api/global/users", () => {
const admin = structures.users.adminUser()
const user = structures.users.user()
const response = await api.users.bulkCreateUsers([builder, admin, user])
const response = await config.api.users.bulkCreateUsers([
builder,
admin,
user,
])
expect(response.created?.successful.length).toBe(3)
expect(response.created?.successful[0].email).toBe(builder.email)
@ -160,7 +168,7 @@ describe("/api/global/users", () => {
it("should be able to create a basic user", async () => {
const user = structures.users.user()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).toBeCalledTimes(1)
expect(events.user.updated).not.toBeCalled()
@ -171,7 +179,7 @@ describe("/api/global/users", () => {
it("should be able to create an admin user", async () => {
const user = structures.users.adminUser()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).toBeCalledTimes(1)
expect(events.user.updated).not.toBeCalled()
@ -182,7 +190,7 @@ describe("/api/global/users", () => {
it("should be able to create a builder user", async () => {
const user = structures.users.builderUser()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).toBeCalledTimes(1)
expect(events.user.updated).not.toBeCalled()
@ -197,7 +205,7 @@ describe("/api/global/users", () => {
app_456: "role2",
}
await api.users.saveUser(user)
await config.api.users.saveUser(user)
const savedUser = await config.getUser(user.email)
expect(events.user.created).toBeCalledTimes(1)
@ -213,7 +221,7 @@ describe("/api/global/users", () => {
delete user._id
delete user._rev
const response = await api.users.saveUser(user, 400)
const response = await config.api.users.saveUser(user, 400)
expect(response.body.message).toBe(`Unavailable`)
expect(events.user.created).toBeCalledTimes(0)
@ -225,7 +233,7 @@ describe("/api/global/users", () => {
await tenancy.doInTenant(TENANT_1, async () => {
delete user._id
const response = await api.users.saveUser(user, 400)
const response = await config.api.users.saveUser(user, 400)
expect(response.body.message).toBe(`Unavailable`)
expect(events.user.created).toBeCalledTimes(0)
@ -237,7 +245,7 @@ describe("/api/global/users", () => {
const account = structures.accounts.cloudAccount()
mocks.accounts.getAccount.mockReturnValueOnce(account)
const response = await api.users.saveUser(user, 400)
const response = await config.api.users.saveUser(user, 400)
expect(response.body.message).toBe(`Unavailable`)
expect(events.user.created).toBeCalledTimes(0)
@ -245,20 +253,20 @@ describe("/api/global/users", () => {
it("should not be able to create a user with the same email and different casing", async () => {
const user = structures.users.user()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
user.email = user.email.toUpperCase()
await api.users.saveUser(user, 400)
await config.api.users.saveUser(user, 400)
expect(events.user.created).toBeCalledTimes(1)
})
it("should not be able to bulk create a user with the same email and different casing", async () => {
const user = structures.users.user()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
user.email = user.email.toUpperCase()
await api.users.bulkCreateUsers([user])
await config.api.users.bulkCreateUsers([user])
expect(events.user.created).toBeCalledTimes(1)
})
@ -269,7 +277,7 @@ describe("/api/global/users", () => {
const user = await config.createUser()
jest.clearAllMocks()
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -284,7 +292,7 @@ describe("/api/global/users", () => {
user.forceResetPassword = true
user.password = "tempPassword"
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -297,7 +305,7 @@ describe("/api/global/users", () => {
const user = await config.createUser()
jest.clearAllMocks()
await api.users.saveUser(structures.users.adminUser(user))
await config.api.users.saveUser(structures.users.adminUser(user))
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -309,7 +317,7 @@ describe("/api/global/users", () => {
const user = await config.createUser()
jest.clearAllMocks()
await api.users.saveUser(structures.users.builderUser(user))
await config.api.users.saveUser(structures.users.builderUser(user))
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -323,7 +331,7 @@ describe("/api/global/users", () => {
user.admin!.global = false
user.builder!.global = false
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -336,7 +344,7 @@ describe("/api/global/users", () => {
jest.clearAllMocks()
user.builder!.global = false
await api.users.saveUser(user)
await config.api.users.saveUser(user)
expect(events.user.created).not.toBeCalled()
expect(events.user.updated).toBeCalledTimes(1)
@ -352,7 +360,7 @@ describe("/api/global/users", () => {
app_456: "role2",
}
await api.users.saveUser(user)
await config.api.users.saveUser(user)
const savedUser = await config.getUser(user.email)
expect(events.user.created).not.toBeCalled()
@ -372,7 +380,7 @@ describe("/api/global/users", () => {
jest.clearAllMocks()
user.roles = {}
await api.users.saveUser(user)
await config.api.users.saveUser(user)
const savedUser = await config.getUser(user.email)
expect(events.user.created).not.toBeCalled()
@ -395,7 +403,7 @@ describe("/api/global/users", () => {
app_456: "role2-edit",
}
await api.users.saveUser(user)
await config.api.users.saveUser(user)
const savedUser = await config.getUser(user.email)
expect(events.user.created).not.toBeCalled()
@ -411,7 +419,7 @@ describe("/api/global/users", () => {
const user = await config.createUser(structures.users.user({ email }))
user.email = "new@test.com"
const response = await api.users.saveUser(user, 400)
const response = await config.api.users.saveUser(user, 400)
const dbUser = await config.getUser(email)
user.email = email
@ -424,7 +432,7 @@ describe("/api/global/users", () => {
it("should not be able to bulk delete current user", async () => {
const user = await config.defaultUser!
const response = await api.users.bulkDeleteUsers([user._id!], 400)
const response = await config.api.users.bulkDeleteUsers([user._id!], 400)
expect(response.message).toBe("Unable to delete self.")
expect(events.user.deleted).not.toBeCalled()
@ -436,7 +444,7 @@ describe("/api/global/users", () => {
account.budibaseUserId = user._id!
mocks.accounts.getAccountByTenantId.mockReturnValue(account)
const response = await api.users.bulkDeleteUsers([user._id!])
const response = await config.api.users.bulkDeleteUsers([user._id!])
expect(response.deleted?.successful.length).toBe(0)
expect(response.deleted?.unsuccessful.length).toBe(1)
@ -454,7 +462,7 @@ describe("/api/global/users", () => {
const builder = structures.users.builderUser()
const admin = structures.users.adminUser()
const user = structures.users.user()
const createdUsers = await api.users.bulkCreateUsers([
const createdUsers = await config.api.users.bulkCreateUsers([
builder,
admin,
user,
@ -463,7 +471,7 @@ describe("/api/global/users", () => {
const toDelete = createdUsers.created?.successful.map(
u => u._id!
) as string[]
const response = await api.users.bulkDeleteUsers(toDelete)
const response = await config.api.users.bulkDeleteUsers(toDelete)
expect(response.deleted?.successful.length).toBe(3)
expect(response.deleted?.unsuccessful.length).toBe(0)
@ -478,7 +486,7 @@ describe("/api/global/users", () => {
const user = await config.createUser()
jest.clearAllMocks()
await api.users.deleteUser(user._id!)
await config.api.users.deleteUser(user._id!)
expect(events.user.deleted).toBeCalledTimes(1)
expect(events.user.permissionBuilderRemoved).not.toBeCalled()
@ -489,7 +497,7 @@ describe("/api/global/users", () => {
const user = await config.createUser(structures.users.adminUser())
jest.clearAllMocks()
await api.users.deleteUser(user._id!)
await config.api.users.deleteUser(user._id!)
expect(events.user.deleted).toBeCalledTimes(1)
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
@ -500,7 +508,7 @@ describe("/api/global/users", () => {
const user = await config.createUser(structures.users.builderUser())
jest.clearAllMocks()
await api.users.deleteUser(user._id!)
await config.api.users.deleteUser(user._id!)
expect(events.user.deleted).toBeCalledTimes(1)
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
@ -512,7 +520,7 @@ describe("/api/global/users", () => {
const account = structures.accounts.cloudAccount()
mocks.accounts.getAccount.mockReturnValueOnce(account)
const response = await api.users.deleteUser(user._id!, 400)
const response = await config.api.users.deleteUser(user._id!, 400)
expect(response.body.message).toBe("Account holder cannot be deleted")
})
@ -523,7 +531,7 @@ describe("/api/global/users", () => {
account.email = user.email
mocks.accounts.getAccount.mockReturnValueOnce(account)
const response = await api.users.deleteUser(user._id!, 400)
const response = await config.api.users.deleteUser(user._id!, 400)
expect(response.body.message).toBe("Unable to delete self.")
})

View file

@ -1,8 +1,9 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
// TODO
describe("/api/global/workspaces", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -16,7 +17,9 @@ describe("/api/global/workspaces", () => {
jest.clearAllMocks()
})
describe("GET /api/global/workspaces", () => {})
describe("GET /api/global/workspaces", () => {
it("retrieves workspaces", () => {})
})
describe("DELETE /api/global/workspaces/:id", () => {})

View file

@ -1,10 +1,9 @@
import sdk from "../../../../sdk"
import { TestConfiguration, structures, API } from "../../../../tests"
import { TestConfiguration, structures } from "../../../../tests"
import { v4 as uuid } from "uuid"
describe("accounts", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -23,7 +22,7 @@ describe("accounts", () => {
it("saves account metadata", async () => {
let account = structures.accounts.account()
const response = await api.accounts.saveMetadata(account)
const response = await config.api.accounts.saveMetadata(account)
const id = sdk.accounts.formatAccountMetadataId(account.accountId)
const metadata = await sdk.accounts.getMetadata(id)
@ -34,9 +33,9 @@ describe("accounts", () => {
describe("destroyMetadata", () => {
it("destroys account metadata", async () => {
const account = structures.accounts.account()
await api.accounts.saveMetadata(account)
await config.api.accounts.saveMetadata(account)
await api.accounts.destroyMetadata(account.accountId)
await config.api.accounts.destroyMetadata(account.accountId)
const deleted = await sdk.accounts.getMetadata(account.accountId)
expect(deleted).toBe(undefined)
@ -45,7 +44,7 @@ describe("accounts", () => {
it("destroys account metadata that does not exist", async () => {
const id = uuid()
const response = await api.accounts.destroyMetadata(id)
const response = await config.api.accounts.destroyMetadata(id)
expect(response.status).toBe(204)
})

View file

@ -1,8 +1,7 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
describe("/api/system/environment", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -18,7 +17,7 @@ describe("/api/system/environment", () => {
describe("GET /api/system/environment", () => {
it("returns the expected environment", async () => {
const env = await api.environment.getEnvironment()
const env = await config.api.environment.getEnvironment()
expect(env.body).toEqual({
cloud: true,
disableAccountPortal: false,

View file

@ -1,6 +1,6 @@
const migrateFn = jest.fn()
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
jest.mock("../../../../migrations", () => {
return {
@ -11,7 +11,6 @@ jest.mock("../../../../migrations", () => {
describe("/api/system/migrations", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -27,7 +26,7 @@ describe("/api/system/migrations", () => {
describe("POST /api/system/migrations/run", () => {
it("fails with no internal api key", async () => {
const res = await api.migrations.runMigrations({
const res = await config.api.migrations.runMigrations({
headers: {},
status: 403,
})
@ -36,7 +35,7 @@ describe("/api/system/migrations", () => {
})
it("runs migrations", async () => {
const res = await api.migrations.runMigrations()
const res = await config.api.migrations.runMigrations()
expect(res.text).toBe("OK")
expect(migrateFn).toBeCalledTimes(1)
})
@ -44,7 +43,7 @@ describe("/api/system/migrations", () => {
describe("DELETE /api/system/migrations/definitions", () => {
it("fails with no internal api key", async () => {
const res = await api.migrations.getMigrationDefinitions({
const res = await config.api.migrations.getMigrationDefinitions({
headers: {},
status: 403,
})
@ -52,7 +51,7 @@ describe("/api/system/migrations", () => {
})
it("returns definitions", async () => {
const res = await api.migrations.getMigrationDefinitions()
const res = await config.api.migrations.getMigrationDefinitions()
expect(res.body).toEqual([
{
name: "global_info_sync_users",

View file

@ -1,8 +1,7 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
describe("/api/system/restore", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -18,7 +17,7 @@ describe("/api/system/restore", () => {
describe("POST /api/global/restore", () => {
it("doesn't allow restore in cloud", async () => {
const res = await api.restore.restored({ status: 405 })
const res = await config.api.restore.restored({ status: 405 })
expect(res.body).toEqual({
message: "This operation is not allowed in cloud.",
status: 405,
@ -27,7 +26,7 @@ describe("/api/system/restore", () => {
it("restores in self host", async () => {
config.modeSelf()
const res = await api.restore.restored()
const res = await config.api.restore.restored()
expect(res.body).toEqual({
message: "System prepared after restore.",
})

View file

@ -1,10 +1,9 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
import { accounts } from "@budibase/backend-core"
import { mocks } from "@budibase/backend-core/tests"
describe("/api/system/status", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -21,7 +20,7 @@ describe("/api/system/status", () => {
describe("GET /api/system/status", () => {
it("returns status in self host", async () => {
config.modeSelf()
const res = await api.status.getStatus()
const res = await config.api.status.getStatus()
expect(res.body).toEqual({
health: {
passing: true,
@ -40,7 +39,7 @@ describe("/api/system/status", () => {
mocks.accounts.getStatus.mockReturnValueOnce(value)
const res = await api.status.getStatus()
const res = await config.api.status.getStatus()
expect(accounts.getStatus).toBeCalledTimes(1)
expect(res.body).toEqual(value)

View file

@ -1,8 +1,8 @@
import { TestConfiguration, API } from "../../../../tests"
import { TestConfiguration } from "../../../../tests"
import { tenancy } from "@budibase/backend-core"
describe("/api/global/workspaces", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -19,14 +19,43 @@ describe("/api/global/workspaces", () => {
describe("DELETE /api/system/tenants/:tenantId", () => {
it("allows deleting the current tenant", async () => {
const user = await config.createTenant()
await config.createSession(user)
const res = await api.tenants.delete(user.tenantId, {
await config.api.tenants.delete(user.tenantId, {
headers: config.authHeaders(user),
})
})
it("rejects deleting another tenant", () => {})
it("rejects deleting another tenant", async () => {
const user1 = await config.createTenant()
// create a second user in another tenant
const user2 = await config.createTenant()
it("requires admin", () => {})
const status = 403
const res = await config.api.tenants.delete(user1.tenantId, {
status,
headers: config.authHeaders(user2),
})
expect(res.body).toEqual({
message: "Tenant ID does not match current user",
status,
})
})
it("rejects non-admin", async () => {
const user1 = await config.createTenant()
// create an internal non-admin user
const user2 = await tenancy.doInTenant(user1.tenantId, () => {
return config.createUser()
})
await config.createSession(user2)
const res = await config.api.tenants.delete(user1.tenantId, {
status: 403,
headers: config.authHeaders(user2),
})
expect(res.body).toEqual(config.adminOnlyResponse())
})
})
})

View file

@ -1,9 +1,8 @@
import { TestConfiguration, API, structures } from "../../tests"
import { TestConfiguration, structures } from "../../tests"
import { constants } from "@budibase/backend-core"
describe("tenancy middleware", () => {
const config = new TestConfiguration()
const api = new API(config)
beforeAll(async () => {
await config.beforeAll()
@ -20,7 +19,7 @@ describe("tenancy middleware", () => {
it("should get tenant id from user", async () => {
const user = await config.createTenant()
await config.createSession(user)
const res = await api.self.getSelf(user)
const res = await config.api.self.getSelf(user)
expect(res.headers[constants.Headers.TENANT_ID]).toBe(user.tenantId)
})

View file

@ -2,7 +2,6 @@ import "./mocks"
import dbConfig from "../db"
dbConfig.init()
import env from "../environment"
import { env as coreEnv } from "@budibase/backend-core"
import controllers from "./controllers"
const supertest = require("supertest")
import { Configs } from "../constants"
@ -14,9 +13,11 @@ import {
sessions,
auth,
constants,
env as coreEnv,
} from "@budibase/backend-core"
import structures, { TENANT_ID, TENANT_1, CSRF_TOKEN } from "./structures"
import { CreateUserResponse, User, AuthToken } from "@budibase/types"
import API from "./api"
enum Mode {
CLOUD = "cloud",
@ -26,6 +27,7 @@ enum Mode {
class TestConfiguration {
server: any
request: any
api: API
defaultUser?: User
tenant1User?: User
@ -47,6 +49,8 @@ class TestConfiguration {
// we need the request for logging in, involves cookies, hard to fake
this.request = supertest(this.server)
}
this.api = new API(this)
}
getRequest() {
@ -119,14 +123,23 @@ class TestConfiguration {
// TENANCY
createTenant = async (tenantId?: string): Promise<User> => {
createTenant = async (): Promise<User> => {
// create user / new tenant
if (!tenantId) {
tenantId = structures.uuid()
}
return tenancy.doInTenant(tenantId, async () => {
return this.createUser()
const res = await this.api.users.createAdminUser()
// return the created user
const userRes = await this.api.users.getUser(res.userId, {
headers: {
...this.internalAPIHeaders(),
[constants.Headers.TENANT_ID]: res.tenantId,
},
})
// create a session for the new user
const user = userRes.body
await this.createSession(user)
return user
}
getTenantId() {
@ -137,30 +150,24 @@ class TestConfiguration {
}
}
// USER / AUTH
// AUTH
async createDefaultUser() {
const user = structures.users.adminUser({
email: "test@test.com",
password: "test",
async _createSession({
userId,
tenantId,
}: {
userId: string
tenantId: string
}) {
await sessions.createASession(userId!, {
sessionId: "sessionid",
tenantId: tenantId,
csrfToken: CSRF_TOKEN,
})
this.defaultUser = await this.createUser(user)
}
async createTenant1User() {
const user = structures.users.adminUser({
email: "tenant1@test.com",
password: "test",
})
this.tenant1User = await this.createUser(user)
}
async createSession(user: User) {
await sessions.createASession(user._id!, {
sessionId: "sessionid",
tenantId: user.tenantId,
csrfToken: CSRF_TOKEN,
})
return this._createSession({ userId: user._id!, tenantId: user.tenantId })
}
cookieHeader(cookies: any) {
@ -198,6 +205,28 @@ class TestConfiguration {
return { [constants.Headers.API_KEY]: env.INTERNAL_API_KEY }
}
adminOnlyResponse = () => {
return { message: "Admin user only endpoint.", status: 403 }
}
// USERS
async createDefaultUser() {
const user = structures.users.adminUser({
email: "test@test.com",
password: "test",
})
this.defaultUser = await this.createUser(user)
}
async createTenant1User() {
const user = structures.users.adminUser({
email: "tenant1@test.com",
password: "test",
})
this.tenant1User = await this.createUser(user)
}
async getUser(email: string): Promise<User> {
return tenancy.doInTenant(this.getTenantId(), () => {
return users.getGlobalUserByEmail(email)

View file

@ -1,20 +1,17 @@
import { Account, AccountMetadata } from "@budibase/types"
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class AccountAPI {
config: TestConfiguration
request: any
export class AccountAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
saveMetadata = async (account: Account) => {
const res = await this.request
.put(`/api/system/accounts/${account.accountId}/metadata`)
.send(account)
.set(this.config.defaultHeaders())
.set(this.config.internalAPIHeaders())
.expect("Content-Type", /json/)
.expect(200)
return res.body as AccountMetadata
@ -23,6 +20,6 @@ export class AccountAPI {
destroyMetadata = (accountId: string) => {
return this.request
.del(`/api/system/accounts/${accountId}/metadata`)
.set(this.config.defaultHeaders())
.set(this.config.internalAPIHeaders())
}
}

View file

@ -1,12 +1,9 @@
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class AuthAPI {
config: TestConfiguration
request: any
export class AuthAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
updatePassword = (code: string) => {

View file

@ -1,12 +1,9 @@
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class ConfigAPI {
config: TestConfiguration
request: any
export class ConfigAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
getConfigChecklist = () => {

View file

@ -1,12 +1,9 @@
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class EmailAPI {
config: TestConfiguration
request: any
export class EmailAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
sendEmail = (purpose: string) => {

View file

@ -1,12 +1,9 @@
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class EnvironmentAPI {
config: TestConfiguration
request: any
export class EnvironmentAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
getEnvironment = () => {

View file

@ -1,13 +1,10 @@
import TestConfiguration from "../TestConfiguration"
import { User } from "@budibase/types"
import { TestAPI } from "./base"
export class SelfAPI {
config: TestConfiguration
request: any
export class SelfAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
updateSelf = (user: User) => {

View file

@ -1,12 +1,9 @@
import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base"
export class StatusAPI {
config: TestConfiguration
request: any
export class StatusAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
getStatus = () => {

View file

@ -10,6 +10,6 @@ export class TenantAPI extends TestAPI {
return this.request
.delete(`/api/system/tenants/${tenantId}`)
.set(opts?.headers)
.expect(opts?.status ? opts.status : 200)
.expect(opts?.status ? opts.status : 204)
}
}

View file

@ -3,16 +3,16 @@ import {
BulkUserRequest,
InviteUsersRequest,
User,
CreateAdminUserRequest,
} from "@budibase/types"
import * as structures from "../structures"
import { generator } from "@budibase/backend-core/tests"
import TestConfiguration from "../TestConfiguration"
import { TestAPI, TestAPIOpts } from "./base"
export class UserAPI {
config: TestConfiguration
request: any
export class UserAPI extends TestAPI {
constructor(config: TestConfiguration) {
this.config = config
this.request = config.request
super(config)
}
// INVITE
@ -91,6 +91,30 @@ export class UserAPI {
// USER
createAdminUser = async (
request?: CreateAdminUserRequest,
opts?: TestAPIOpts
) => {
if (!request) {
request = {
email: structures.email(),
password: generator.string(),
tenantId: structures.uuid(),
}
}
const res = await this.request
.post(`/api/global/users/init`)
.send(request)
.set(this.config.internalAPIHeaders())
.expect("Content-Type", /json/)
.expect(opts?.status ? opts.status : 200)
return {
...request,
userId: res.body._id,
}
}
saveUser = (user: User, status?: number) => {
return this.request
.post(`/api/global/users`)
@ -107,4 +131,12 @@ export class UserAPI {
.expect("Content-Type", /json/)
.expect(status ? status : 200)
}
getUser = (userId: string, opts?: TestAPIOpts) => {
return this.request
.get(`/api/global/users/${userId}`)
.set(opts?.headers ? opts.headers : this.config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(opts?.status ? opts.status : 200)
}
}