Introduce test error propagation to public API endpoints.
This commit is contained in:
parent
433c20d80c
commit
5b285940f1
|
@ -48,7 +48,7 @@ function getUser(ctx: UserCtx, userId?: string) {
|
||||||
if (userId) {
|
if (userId) {
|
||||||
ctx.params = { userId }
|
ctx.params = { userId }
|
||||||
} else if (!ctx.params?.userId) {
|
} else if (!ctx.params?.userId) {
|
||||||
throw "No user ID provided for getting"
|
throw new Error("No user ID provided for getting")
|
||||||
}
|
}
|
||||||
return readGlobalUser(ctx)
|
return readGlobalUser(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { paramResource, paramSubResource } from "../../../middleware/resourceId"
|
||||||
import { PermissionLevel, PermissionType } from "@budibase/types"
|
import { PermissionLevel, PermissionType } from "@budibase/types"
|
||||||
import { CtxFn } from "./utils/Endpoint"
|
import { CtxFn } from "./utils/Endpoint"
|
||||||
import mapperMiddleware from "./middleware/mapper"
|
import mapperMiddleware from "./middleware/mapper"
|
||||||
|
import testErrorHandling from "./middleware/testErrorHandling"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { middleware, redis } from "@budibase/backend-core"
|
import { middleware, redis } from "@budibase/backend-core"
|
||||||
import { SelectableDatabase } from "@budibase/backend-core/src/redis/utils"
|
import { SelectableDatabase } from "@budibase/backend-core/src/redis/utils"
|
||||||
|
@ -144,6 +145,10 @@ function applyRoutes(
|
||||||
// add the output mapper middleware
|
// add the output mapper middleware
|
||||||
addMiddleware(endpoints.read, mapperMiddleware, { output: true })
|
addMiddleware(endpoints.read, mapperMiddleware, { output: true })
|
||||||
addMiddleware(endpoints.write, mapperMiddleware, { output: true })
|
addMiddleware(endpoints.write, mapperMiddleware, { output: true })
|
||||||
|
if (env.isTest()) {
|
||||||
|
addMiddleware(endpoints.read, testErrorHandling)
|
||||||
|
addMiddleware(endpoints.write, testErrorHandling)
|
||||||
|
}
|
||||||
addToRouter(endpoints.read)
|
addToRouter(endpoints.read)
|
||||||
addToRouter(endpoints.write)
|
addToRouter(endpoints.write)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { Ctx } from "@budibase/types"
|
||||||
|
import environment from "../../../../environment"
|
||||||
|
|
||||||
|
export default async (ctx: Ctx, next: any) => {
|
||||||
|
try {
|
||||||
|
await next()
|
||||||
|
} catch (err: any) {
|
||||||
|
if (
|
||||||
|
!(environment.isTest() && ctx.headers["x-budibase-include-stacktrace"])
|
||||||
|
) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
|
||||||
|
const status = err.status || err.statusCode || 500
|
||||||
|
|
||||||
|
let error = err
|
||||||
|
while (error.cause) {
|
||||||
|
error = error.cause
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.status = status
|
||||||
|
ctx.body = { status, message: error.message, stack: error.stack }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
import * as setup from "../../tests/utilities"
|
import * as setup from "../../tests/utilities"
|
||||||
import { User } from "@budibase/types"
|
import { User } from "@budibase/types"
|
||||||
import { mocks } from "@budibase/backend-core/tests"
|
import { generator, mocks } from "@budibase/backend-core/tests"
|
||||||
import nock from "nock"
|
import nock from "nock"
|
||||||
import environment from "../../../../environment"
|
import environment from "../../../../environment"
|
||||||
import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
|
import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
|
||||||
|
|
||||||
const config = new TestConfiguration()
|
const config = new TestConfiguration()
|
||||||
let globalUser: User
|
let globalUser: User
|
||||||
|
let users: Record<string, User> = {}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await config.init()
|
await config.init()
|
||||||
|
@ -16,25 +17,26 @@ afterAll(setup.afterAll)
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
globalUser = await config.globalUser()
|
globalUser = await config.globalUser()
|
||||||
|
users[globalUser._id!] = globalUser
|
||||||
|
|
||||||
nock.cleanAll()
|
nock.cleanAll()
|
||||||
nock(environment.WORKER_URL!)
|
nock(environment.WORKER_URL!)
|
||||||
.get(`/api/global/users/${globalUser._id}`)
|
.get(new RegExp(`/api/global/users/.*`))
|
||||||
.reply(200, (uri, body) => {
|
.reply(200, (uri, body) => {
|
||||||
return globalUser
|
const id = uri.split("/").pop()
|
||||||
|
return users[id!]
|
||||||
})
|
})
|
||||||
.persist()
|
.persist()
|
||||||
|
|
||||||
nock(environment.WORKER_URL!)
|
nock(environment.WORKER_URL!)
|
||||||
.post(`/api/global/users`)
|
.post(`/api/global/users`)
|
||||||
.reply(200, (uri, body) => {
|
.reply(200, (uri, body) => {
|
||||||
const updatedUser = body as User
|
const newUser = body as User
|
||||||
if (updatedUser._id === globalUser._id) {
|
if (!newUser._id) {
|
||||||
globalUser = updatedUser
|
newUser._id = `us_${generator.guid()}`
|
||||||
return globalUser
|
|
||||||
} else {
|
|
||||||
throw new Error("User not found")
|
|
||||||
}
|
}
|
||||||
|
users[newUser._id!] = newUser
|
||||||
|
return newUser
|
||||||
})
|
})
|
||||||
.persist()
|
.persist()
|
||||||
})
|
})
|
||||||
|
@ -47,7 +49,7 @@ function base() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe.only("check user endpoints", () => {
|
describe("check user endpoints", () => {
|
||||||
it("should not allow a user to update their own roles", async () => {
|
it("should not allow a user to update their own roles", async () => {
|
||||||
await config.withUser(globalUser, () =>
|
await config.withUser(globalUser, () =>
|
||||||
config.api.public.user.update({
|
config.api.public.user.update({
|
||||||
|
@ -67,14 +69,12 @@ describe.only("check user endpoints", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("no user role update in free", () => {
|
describe("no user role update in free", () => {
|
||||||
it("should not allow 'roles' to be updated", async () => {
|
it.only("should not allow 'roles' to be updated", async () => {
|
||||||
const res = await makeRequest("post", "/users", {
|
const newUser = await config.api.public.user.create({
|
||||||
...base(),
|
email: generator.email({ domain: "example.com" }),
|
||||||
roles: { app_a: "BASIC" },
|
roles: { app_a: "BASIC" },
|
||||||
})
|
})
|
||||||
expect(res.status).toBe(200)
|
expect(newUser.roles["app_a"]).toBeUndefined()
|
||||||
expect(res.body.data.roles["app_a"]).toBeUndefined()
|
|
||||||
expect(res.body.message).toBeDefined()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not allow 'admin' to be updated", async () => {
|
it("should not allow 'admin' to be updated", async () => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { User } from "@budibase/types"
|
import { UnsavedUser, User } from "@budibase/types"
|
||||||
import { Expectations, PublicAPI } from "../base"
|
import { Expectations, PublicAPI } from "../base"
|
||||||
|
|
||||||
export class UserPublicAPI extends PublicAPI {
|
export class UserPublicAPI extends PublicAPI {
|
||||||
|
@ -16,4 +16,15 @@ export class UserPublicAPI extends PublicAPI {
|
||||||
destroy = async (id: string, expectations?: Expectations): Promise<void> => {
|
destroy = async (id: string, expectations?: Expectations): Promise<void> => {
|
||||||
return await this._delete(`/users/${id}`, { expectations })
|
return await this._delete(`/users/${id}`, { expectations })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create = async (
|
||||||
|
user: UnsavedUser,
|
||||||
|
expectations?: Expectations
|
||||||
|
): Promise<User> => {
|
||||||
|
const response = await this._post<{ data: User }>("/users", {
|
||||||
|
body: user,
|
||||||
|
expectations,
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue