refactor view tests

This commit is contained in:
Martin McKeaveney 2021-03-04 17:55:24 +00:00
parent 0be5eb0b98
commit e2a6bb935e
2 changed files with 107 additions and 421 deletions

View File

@ -1,326 +0,0 @@
const CouchDB = require("../../../db")
const supertest = require("supertest")
const { BUILTIN_ROLE_IDS } = require("../../../utilities/security/roles")
const packageJson = require("../../../../package")
const jwt = require("jsonwebtoken")
const env = require("../../../environment")
const {
BUILTIN_PERMISSION_IDS,
} = require("../../../utilities/security/permissions")
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
}
exports.BASE_TABLE = {
name: "TestTable",
type: "table",
key: "name",
schema: {
name: {
type: "string",
constraints: {
type: "string",
},
},
description: {
type: "string",
constraints: {
type: "string",
},
},
},
}
exports.createTable = async (request, appId, table, removeId = true) => {
if (removeId && table != null && table._id) {
delete table._id
}
table = table || exports.BASE_TABLE
const res = await request
.post(`/api/tables`)
.set(exports.defaultHeaders(appId))
.send(table)
return res.body
}
exports.makeBasicRow = tableId => {
return {
name: "Test Contact",
description: "original description",
status: "new",
tableId: tableId,
}
}
exports.createRow = async (request, appId, tableId, row = null) => {
row = row || exports.makeBasicRow(tableId)
const res = await request
.post(`/api/${tableId}/rows`)
.send(row)
.set(exports.defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
return res.body
}
exports.createRole = async (request, appId) => {
const roleBody = {
name: "NewRole",
inherits: BUILTIN_ROLE_IDS.BASIC,
permissionId: BUILTIN_PERMISSION_IDS.READ_ONLY,
}
const res = await request
.post(`/api/roles`)
.send(roleBody)
.set(exports.defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
return res.body
}
exports.addPermission = async (
request,
appId,
role,
resource,
level = "read"
) => {
const res = await request
.post(`/api/permission/${role}/${resource}/${level}`)
.set(exports.defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
return res.body
}
exports.createLinkedTable = async (request, appId) => {
// get the ID to link to
const table = await exports.createTable(request, appId)
table.primaryDisplay = "name"
table.schema.link = {
type: "link",
fieldName: "link",
tableId: table._id,
}
return exports.createTable(request, appId, table, false)
}
exports.createAttachmentTable = async (request, appId) => {
const table = await exports.createTable(request, appId)
table.schema.attachment = {
type: "attachment",
}
return exports.createTable(request, appId, table, false)
}
exports.getAllFromTable = async (request, appId, tableId) => {
const res = await request
.get(`/api/${tableId}/rows`)
.set(exports.defaultHeaders(appId))
return res.body
}
exports.createView = async (request, appId, tableId, view) => {
view = view || {
map: "function(doc) { emit(doc[doc.key], doc._id); } ",
tableId: tableId,
}
const res = await request
.post(`/api/views`)
.set(exports.defaultHeaders(appId))
.send(view)
return res.body
}
exports.createApplication = async (request, name = "test_application") => {
const res = await request
.post("/api/applications")
.send({
name,
})
.set(exports.defaultHeaders())
return res.body
}
exports.clearApplications = async request => {
const res = await request
.get("/api/applications")
.set(exports.defaultHeaders())
for (let app of res.body) {
const appId = app._id
await request
.delete(`/api/applications/${appId}`)
.set(exports.defaultHeaders(appId))
}
}
exports.createUser = async (
request,
appId,
email = "babs@babs.com",
password = "babs_password"
) => {
const res = await request
.post(`/api/users`)
.set(exports.defaultHeaders(appId))
.send({
name: "Bill",
email,
password,
roleId: BUILTIN_ROLE_IDS.POWER,
})
return res.body
}
const createUserWithRole = async (request, appId, roleId, email) => {
const password = `password_${email}`
await request
.post(`/api/users`)
.set(exports.defaultHeaders(appId))
.send({
email,
password,
roleId,
})
const anonUser = {
userId: "ANON",
roleId: BUILTIN_ROLE_IDS.PUBLIC,
appId: appId,
version: packageJson.version,
}
const anonToken = jwt.sign(anonUser, env.JWT_SECRET)
const loginResult = await request
.post(`/api/authenticate`)
.set({
Cookie: `budibase:${appId}:local=${anonToken}`,
"x-budibase-app-id": appId,
})
.send({ email, password })
// returning necessary request headers
return {
Accept: "application/json",
Cookie: loginResult.headers["set-cookie"],
}
}
exports.testPermissionsForEndpoint = async ({
request,
method,
url,
body,
appId,
passRole,
failRole,
}) => {
const passHeader = await createUserWithRole(
request,
appId,
passRole,
"passUser@budibase.com"
)
await createRequest(request, method, url, body)
.set(passHeader)
.expect(200)
const failHeader = await createUserWithRole(
request,
appId,
failRole,
"failUser@budibase.com"
)
await createRequest(request, method, url, body)
.set(failHeader)
.expect(403)
}
exports.builderEndpointShouldBlockNormalUsers = async ({
request,
method,
url,
body,
appId,
}) => {
const headers = await createUserWithRole(
request,
appId,
BUILTIN_ROLE_IDS.BASIC,
"basicUser@budibase.com"
)
await createRequest(request, method, url, body)
.set(headers)
.expect(403)
}
const 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.insertDocument = async (databaseId, document) => {
const { id, ...documentFields } = document
return await new CouchDB(databaseId).put({ _id: id, ...documentFields })
}
exports.destroyDocument = async (databaseId, documentId) => {
return await new CouchDB(databaseId).destroy(documentId)
}
exports.getDocument = async (databaseId, documentId) => {
return await new CouchDB(databaseId).get(documentId)
}

View File

@ -1,65 +1,67 @@
const {
createApplication,
createTable,
supertest,
defaultHeaders,
getDocument
} = require("./couchTestUtils")
const TestConfig = require("./utilities/TestConfiguration");
describe("/views", () => {
let request
let server
let app
let appId
let table
const createView = async (config = {
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id
}) =>
await request
.post(`/api/views`)
.send(config)
.set(defaultHeaders(appId))
.expect('Content-Type', /json/)
.expect(200)
const createRow = async row => request
.post(`/api/${table._id}/rows`)
.send(row)
.set(defaultHeaders(appId))
.expect('Content-Type', /json/)
.expect(200)
let request;
let server;
let app;
let config;
let appId;
let table;
beforeAll(async () => {
({ request, server } = await supertest())
})
config = new TestConfig();
request = config.request;
});
beforeEach(async () => {
app = await createApplication(request)
appId = app.instance._id
})
app = await config.init();
appId = app.instance._id;
});
afterAll(() => {
server.close()
})
config.end();
});
describe("create", () => {
beforeEach(async () => {
table = await createTable(request, appId);
})
table = await config.createTable();
});
it("returns a success message when the view is successfully created", async () => {
const res = await createView()
expect(res.res.statusMessage).toEqual("View TestView saved successfully.");
})
const res = await request
.post(`/api/views`)
.send({
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200);
expect(res.res.statusMessage).toEqual(
"View TestView saved successfully."
);
});
it("updates the table row with the new view metadata", async () => {
const res = await createView()
expect(res.res.statusMessage).toEqual("View TestView saved successfully.");
const updatedTable = await getDocument(appId, table._id)
const res = await request
.post(`/api/views`)
.send({
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200);
expect(res.res.statusMessage).toEqual(
"View TestView saved successfully."
);
const updatedTable = await config.getTable(table._id);
expect(updatedTable.views).toEqual({
TestView: {
field: "Price",
@ -88,88 +90,98 @@ describe("/views", () => {
field: {
type: "string",
},
}
}
},
},
});
})
});
});
describe("fetch", () => {
beforeEach(async () => {
table = await createTable(request, appId);
table = await config.createTable();
});
it("returns only custom views", async () => {
await createView()
await config.createView({
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
});
const res = await request
.get(`/api/views`)
.set(defaultHeaders(appId))
.expect('Content-Type', /json/)
.expect(200)
expect(res.body.length).toBe(1)
expect(res.body.find(({ name }) => name === "TestView")).toBeDefined()
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200);
expect(res.body.length).toBe(1);
expect(res.body.find(({ name }) => name === "TestView")).toBeDefined();
});
});
describe("query", () => {
beforeEach(async () => {
table = await createTable(request, appId);
table = await config.createTable();
});
it("returns data for the created view", async () => {
await createView()
await createRow({
await config.createView({
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
Price: 1000
})
await createRow({
});
await config.createRow({
tableId: table._id,
Price: 2000
})
await createRow({
Price: 1000,
});
await config.createRow({
tableId: table._id,
Price: 4000
})
Price: 2000,
});
await config.createRow({
tableId: table._id,
Price: 4000,
});
const res = await request
.get(`/api/views/TestView?calculation=stats`)
.set(defaultHeaders(appId))
.expect('Content-Type', /json/)
.expect(200)
expect(res.body.length).toBe(1)
expect(res.body).toMatchSnapshot()
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200);
expect(res.body.length).toBe(1);
expect(res.body).toMatchSnapshot();
});
it("returns data for the created view using a group by", async () => {
await createView({
await config.createView({
calculation: "stats",
name: "TestView",
field: "Price",
groupBy: "Category",
tableId: table._id
})
await createRow({
tableId: table._id,
});
await config.createRow({
tableId: table._id,
Price: 1000,
Category: "One"
})
await createRow({
Category: "One",
});
await config.createRow({
tableId: table._id,
Price: 2000,
Category: "One"
})
await createRow({
Category: "One",
});
await config.createRow({
tableId: table._id,
Price: 4000,
Category: "Two"
})
Category: "Two",
});
const res = await request
.get(`/api/views/TestView?calculation=stats&group=Category`)
.set(defaultHeaders(appId))
.expect('Content-Type', /json/)
.expect(200)
expect(res.body.length).toBe(2)
expect(res.body).toMatchSnapshot()
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200);
expect(res.body.length).toBe(2);
expect(res.body).toMatchSnapshot();
});
});
});
});