Initial work on test refactoring, laying the utilities down which will be the basis of new testing framework, interacting directly with the controllers.
This commit is contained in:
parent
2beba28700
commit
6d9b8a6678
|
@ -52,7 +52,8 @@
|
||||||
"collectCoverageFrom": [
|
"collectCoverageFrom": [
|
||||||
"src/**/*.js",
|
"src/**/*.js",
|
||||||
"!**/node_modules/**",
|
"!**/node_modules/**",
|
||||||
"!src/db/views/*.js"
|
"!src/db/views/*.js",
|
||||||
|
"!src/api/routes/tests"
|
||||||
],
|
],
|
||||||
"coverageReporters": [
|
"coverageReporters": [
|
||||||
"lcov",
|
"lcov",
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
const {
|
const {
|
||||||
createApplication,
|
|
||||||
builderEndpointShouldBlockNormalUsers,
|
|
||||||
supertest,
|
supertest,
|
||||||
clearApplications,
|
|
||||||
defaultHeaders,
|
defaultHeaders,
|
||||||
} = require("./couchTestUtils")
|
} = require("./utilities")
|
||||||
|
const TestConfig = require("./utilities/TestConfiguration")
|
||||||
|
const { clearAllApps, checkBuilderEndpoint } = require("./utilities/TestFunctions")
|
||||||
|
|
||||||
describe("/applications", () => {
|
describe("/applications", () => {
|
||||||
let request
|
let request
|
||||||
let server
|
let server
|
||||||
|
let config
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
({ request, server } = await supertest())
|
({ request, server } = await supertest())
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await clearApplications(request)
|
await clearAllApps()
|
||||||
|
config = new TestConfig(request)
|
||||||
|
await config.init()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
|
@ -35,23 +37,20 @@ describe("/applications", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
const otherApplication = await createApplication(request)
|
await checkBuilderEndpoint({
|
||||||
const appId = otherApplication.instance._id
|
config,
|
||||||
await builderEndpointShouldBlockNormalUsers({
|
|
||||||
request,
|
request,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: `/api/applications`,
|
url: `/api/applications`,
|
||||||
appId: appId,
|
|
||||||
body: { name: "My App" }
|
body: { name: "My App" }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("fetch", () => {
|
describe("fetch", () => {
|
||||||
it("lists all applications", async () => {
|
it("lists all applications", async () => {
|
||||||
await createApplication(request, "app1")
|
await config.createApp(request, "app1")
|
||||||
await createApplication(request, "app2")
|
await config.createApp(request, "app2")
|
||||||
|
|
||||||
const res = await request
|
const res = await request
|
||||||
.get("/api/applications")
|
.get("/api/applications")
|
||||||
|
@ -59,17 +58,16 @@ describe("/applications", () => {
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(res.body.length).toBe(2)
|
// two created apps + the inited app
|
||||||
|
expect(res.body.length).toBe(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should apply authorization to endpoint", async () => {
|
it("should apply authorization to endpoint", async () => {
|
||||||
const otherApplication = await createApplication(request)
|
await checkBuilderEndpoint({
|
||||||
const appId = otherApplication.instance._id
|
config,
|
||||||
await builderEndpointShouldBlockNormalUsers({
|
|
||||||
request,
|
request,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `/api/applications`,
|
url: `/api/applications`,
|
||||||
appId: appId,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
const { BUILTIN_ROLE_IDS } = require("../../../../utilities/security/roles")
|
||||||
|
const env = require("../../../../environment")
|
||||||
|
const { basicTable, basicRow, basicRole } = require("./structures")
|
||||||
|
const tableController = require("../../../controllers/table")
|
||||||
|
const rowController = require("../../../controllers/row")
|
||||||
|
const roleController = require("../../../controllers/role")
|
||||||
|
const permsController = require("../../../controllers/permission")
|
||||||
|
const viewController = require("../../../controllers/view")
|
||||||
|
const appController = require("../../../controllers/application")
|
||||||
|
const userController = require("../../../controllers/user")
|
||||||
|
|
||||||
|
const EMAIL = "babs@babs.com"
|
||||||
|
const PASSWORD = "babs_password"
|
||||||
|
|
||||||
|
class TestConfiguration {
|
||||||
|
constructor(request) {
|
||||||
|
// we need the request for logging in, involves cookies, hard to fake
|
||||||
|
this.request = request
|
||||||
|
this.appId = null
|
||||||
|
this.table = null
|
||||||
|
this.linkedTable = null
|
||||||
|
}
|
||||||
|
|
||||||
|
async _req(config, params, controlFunc) {
|
||||||
|
const request = {}
|
||||||
|
// fake cookies, we don't need them
|
||||||
|
request.cookies = { set: () => {}, get: () => {} }
|
||||||
|
request.config = { jwtSecret: env.JWT_SECRET }
|
||||||
|
request.appId = this.appId
|
||||||
|
request.user = { appId: this.appId }
|
||||||
|
request.request = {
|
||||||
|
body: config,
|
||||||
|
}
|
||||||
|
if (params) {
|
||||||
|
request.params = params
|
||||||
|
}
|
||||||
|
await controlFunc(request)
|
||||||
|
return request.body
|
||||||
|
}
|
||||||
|
|
||||||
|
async init(appName = "test_application") {
|
||||||
|
return this.createApp(appName)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createApp(appName) {
|
||||||
|
this.app = await this._req({ name: appName }, null, appController.create)
|
||||||
|
this.appId = this.app._id
|
||||||
|
return this.app
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateTable(config = null) {
|
||||||
|
config = config || basicTable()
|
||||||
|
this.table = await this._req(config, null, tableController.save)
|
||||||
|
return this.table
|
||||||
|
}
|
||||||
|
|
||||||
|
async createTable(config = null) {
|
||||||
|
if (config != null && config._id) {
|
||||||
|
delete config._id
|
||||||
|
}
|
||||||
|
return this.updateTable(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createLinkedTables() {
|
||||||
|
const table = await this.createTable()
|
||||||
|
table.primaryDisplay = "name"
|
||||||
|
table.schema.link = {
|
||||||
|
type: "link",
|
||||||
|
fieldName: "link",
|
||||||
|
tableId: table._id,
|
||||||
|
}
|
||||||
|
const linkedTable = await this.createTable(table)
|
||||||
|
this.table = table
|
||||||
|
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."
|
||||||
|
}
|
||||||
|
config = config || basicRow(this.table._id)
|
||||||
|
return this._req(config, { tableId: this.table._id }, rowController.save)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRole(config = null) {
|
||||||
|
config = config || basicRole()
|
||||||
|
return this._req(config, null, roleController.save)
|
||||||
|
}
|
||||||
|
|
||||||
|
async addPermission(roleId, resourceId, level = "read") {
|
||||||
|
return this._req(
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
roleId,
|
||||||
|
resourceId,
|
||||||
|
level,
|
||||||
|
},
|
||||||
|
permsController.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,
|
||||||
|
}
|
||||||
|
return this._req(view, null, viewController.save)
|
||||||
|
}
|
||||||
|
|
||||||
|
async createUser(
|
||||||
|
email = EMAIL,
|
||||||
|
password = PASSWORD,
|
||||||
|
roleId = BUILTIN_ROLE_IDS.POWER
|
||||||
|
) {
|
||||||
|
return this._req(
|
||||||
|
{
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
roleId,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
userController.create
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(email, password) {
|
||||||
|
if (!email || !password) {
|
||||||
|
await this.createUser()
|
||||||
|
email = EMAIL
|
||||||
|
password = PASSWORD
|
||||||
|
}
|
||||||
|
const result = await this.request
|
||||||
|
.post(`/api/authenticate`)
|
||||||
|
.set({
|
||||||
|
"x-budibase-app-id": this.appId,
|
||||||
|
})
|
||||||
|
.send({ email, password })
|
||||||
|
|
||||||
|
// returning necessary request headers
|
||||||
|
return {
|
||||||
|
Accept: "application/json",
|
||||||
|
Cookie: result.headers["set-cookie"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TestConfiguration
|
|
@ -0,0 +1,75 @@
|
||||||
|
const rowController = require("../../../controllers/row")
|
||||||
|
const appController = require("../../../controllers/application")
|
||||||
|
const CouchDB = require("../../../../db")
|
||||||
|
|
||||||
|
function Request(appId, params) {
|
||||||
|
this.user = { appId }
|
||||||
|
this.params = params
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getAllTableRows = async (appId, tableId) => {
|
||||||
|
const req = new Request(appId, { tableId })
|
||||||
|
await rowController.fetchTableRows(req)
|
||||||
|
return req.body
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.clearAllApps = async () => {
|
||||||
|
const req = {}
|
||||||
|
await appController.fetch(req)
|
||||||
|
const apps = req.body
|
||||||
|
if (!apps || apps.length <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (let app of apps) {
|
||||||
|
const appId = app._id
|
||||||
|
await appController.delete(new Request(null, { appId }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.createRequest = (request, method, url, body) => {
|
||||||
|
let req
|
||||||
|
|
||||||
|
if (method === "POST") req = request.post(url).send(body)
|
||||||
|
else if (method === "GET") req = request.get(url)
|
||||||
|
else if (method === "DELETE") req = request.delete(url)
|
||||||
|
else if (method === "PATCH") req = request.patch(url).send(body)
|
||||||
|
else if (method === "PUT") req = request.put(url).send(body)
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.checkBuilderEndpoint = async ({
|
||||||
|
config,
|
||||||
|
request,
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
body,
|
||||||
|
}) => {
|
||||||
|
const headers = await config.login()
|
||||||
|
await exports
|
||||||
|
.createRequest(request, method, url, body)
|
||||||
|
.set(headers)
|
||||||
|
.expect(403)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw DB insert utility.
|
||||||
|
*/
|
||||||
|
exports.insertDocument = async (databaseId, document) => {
|
||||||
|
const { id, ...documentFields } = document
|
||||||
|
return await new CouchDB(databaseId).put({ _id: id, ...documentFields })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw DB delete utility.
|
||||||
|
*/
|
||||||
|
exports.destroyDocument = async (databaseId, documentId) => {
|
||||||
|
return await new CouchDB(databaseId).destroy(documentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw DB get utility.
|
||||||
|
*/
|
||||||
|
exports.getDocument = async (databaseId, documentId) => {
|
||||||
|
return await new CouchDB(databaseId).get(documentId)
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
const supertest = require("supertest")
|
||||||
|
const { BUILTIN_ROLE_IDS } = require("../../../../utilities/security/roles")
|
||||||
|
const jwt = require("jsonwebtoken")
|
||||||
|
const env = require("../../../../environment")
|
||||||
|
|
||||||
|
const TEST_CLIENT_ID = "test-client-id"
|
||||||
|
|
||||||
|
exports.TEST_CLIENT_ID = TEST_CLIENT_ID
|
||||||
|
exports.supertest = async () => {
|
||||||
|
let request
|
||||||
|
let server
|
||||||
|
env.PORT = 4002
|
||||||
|
server = require("../../../../app")
|
||||||
|
|
||||||
|
request = supertest(server)
|
||||||
|
return { request, server }
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.defaultHeaders = appId => {
|
||||||
|
const builderUser = {
|
||||||
|
userId: "BUILDER",
|
||||||
|
roleId: BUILTIN_ROLE_IDS.BUILDER,
|
||||||
|
}
|
||||||
|
|
||||||
|
const builderToken = jwt.sign(builderUser, env.JWT_SECRET)
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
Accept: "application/json",
|
||||||
|
Cookie: [`budibase:builder:local=${builderToken}`],
|
||||||
|
}
|
||||||
|
if (appId) {
|
||||||
|
headers["x-budibase-app-id"] = appId
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.publicHeaders = appId => {
|
||||||
|
const headers = {
|
||||||
|
Accept: "application/json",
|
||||||
|
}
|
||||||
|
if (appId) {
|
||||||
|
headers["x-budibase-app-id"] = appId
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
const { BUILTIN_ROLE_IDS } = require("../../../../utilities/security/roles")
|
||||||
|
const {
|
||||||
|
BUILTIN_PERMISSION_IDS,
|
||||||
|
} = require("../../../../utilities/security/permissions")
|
||||||
|
|
||||||
|
exports.basicTable = () => {
|
||||||
|
return {
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
key: "name",
|
||||||
|
schema: {
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.basicRow = tableId => {
|
||||||
|
return {
|
||||||
|
name: "Test Contact",
|
||||||
|
description: "original description",
|
||||||
|
status: "new",
|
||||||
|
tableId: tableId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.basicRole = () => {
|
||||||
|
return {
|
||||||
|
name: "NewRole",
|
||||||
|
inherits: BUILTIN_ROLE_IDS.BASIC,
|
||||||
|
permissionId: BUILTIN_PERMISSION_IDS.READ_ONLY,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue