model creation and fetching with tests
This commit is contained in:
parent
3b57af74ca
commit
093e52afb0
|
@ -4,6 +4,7 @@
|
|||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"useWorkspaces": true,
|
||||
"command": {
|
||||
"publish": {
|
||||
"ignoreChanges": [
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"name": "root",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^6.8.0",
|
||||
|
|
|
@ -1,10 +1,59 @@
|
|||
const couchdb = require("../../db");
|
||||
|
||||
const MODEL_SCHEMA = {
|
||||
id: "foo",
|
||||
name: "Contact",
|
||||
key: "wutwut",
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
constraints: {
|
||||
min: "",
|
||||
max: ""
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "age",
|
||||
type: "number",
|
||||
constraints: {
|
||||
min: 0,
|
||||
max: 100
|
||||
}
|
||||
}
|
||||
],
|
||||
validationRules: [
|
||||
]
|
||||
}
|
||||
|
||||
exports.fetch = async function(ctx) {
|
||||
const db = couchdb.db.use(ctx.params.instanceId);
|
||||
const body = await db.view("database", "by_type", {
|
||||
include_docs: true,
|
||||
key: ["model"]
|
||||
});
|
||||
ctx.body = body.rows;
|
||||
}
|
||||
|
||||
exports.create = async function(ctx) {
|
||||
const db = couchdb.db.use(ctx.params.instanceId)
|
||||
ctx.body = await db.insert(ctx.request.body);
|
||||
// Create the "all" view for that model
|
||||
|
||||
const db = couchdb.db.use(ctx.params.instanceId);
|
||||
const newModel = await db.insert(ctx.request.body);
|
||||
const designDoc = await db.get("_design/database");
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[`all_${newModel.id}`]: {
|
||||
map: function(doc) {
|
||||
emit([doc.modelId], doc._id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await db.insert(designDoc, designDoc._id);
|
||||
ctx.body = {
|
||||
...newModel,
|
||||
message: `Model ${ctx.request.body.name} created successfully.`,
|
||||
status: 200,
|
||||
}
|
||||
}
|
||||
|
||||
exports.update = async function(ctx) {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
const couchdb = require("../../db")
|
||||
const { mapValues, keyBy } = require("lodash/fp")
|
||||
const { mapValues, keyBy, compose } = require("lodash/fp")
|
||||
const {
|
||||
validateRecord,
|
||||
} = require("../../../common/src/records/validateRecord")
|
||||
const { events } = require("../../../common/src/common/events")
|
||||
const { $ } = require("../../../common/src/common")
|
||||
const { safeParseField } = require("../../../common/src/schema/types");
|
||||
|
||||
exports.save = async function(ctx) {
|
||||
|
@ -80,12 +79,12 @@ async function _findRecord({ db, schema, id }) {
|
|||
|
||||
const model = schema.findModel(storedData._modelId)
|
||||
|
||||
// TODO refactor
|
||||
const loadedRecord = $(model.fields, [
|
||||
keyBy("name"),
|
||||
const loadRecord = compose(
|
||||
mapValues(f => safeParseField(f, storedData)),
|
||||
])
|
||||
|
||||
keyBy("name")
|
||||
);
|
||||
|
||||
const loadedRecord = loadRecord(model.fields);
|
||||
|
||||
return {
|
||||
...loadedRecord,
|
||||
|
|
|
@ -20,6 +20,7 @@ const databaseRoutes = require("./routes/neo/database");
|
|||
const neoUserRoutes = require("./routes/neo/user");
|
||||
const clientRoutes = require("./routes/neo/client");
|
||||
const applicationRoutes = require("./routes/neo/application");
|
||||
const modelsRoutes = require("./routes/neo/model");
|
||||
|
||||
const builderPath = resolve(__dirname, "../builder")
|
||||
|
||||
|
@ -128,11 +129,14 @@ module.exports = (config, app) => {
|
|||
ctx.status = err.status || 500;
|
||||
ctx.body = {
|
||||
message: err.message,
|
||||
status: ctx.status
|
||||
status: ctx.status
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
router.use(modelsRoutes.routes());
|
||||
router.use(modelsRoutes.allowedMethods());
|
||||
|
||||
router.use(applicationRoutes.routes());
|
||||
router.use(applicationRoutes.allowedMethods());
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ const router = Router();
|
|||
router
|
||||
.get("/api/:instanceId/models", controller.fetch)
|
||||
.post("/api/:instanceId/models", controller.create)
|
||||
.patch("/api/:instanceId/models", controller.update)
|
||||
.delete("/api/:instanceId/models/:modelId", controller.delete)
|
||||
// .patch("/api/:instanceId/models", controller.update)
|
||||
// .delete("/api/:instanceId/models/:modelId", controller.delete)
|
||||
|
||||
|
||||
module.exports = router;
|
|
@ -4,6 +4,22 @@ const CLIENT_DB_ID = "client-testing";
|
|||
|
||||
exports.destroyDatabase = couchdb.db.destroy;
|
||||
|
||||
exports.createModel = async instanceId => {
|
||||
const model = {
|
||||
"name": "TestModel",
|
||||
"type": "model",
|
||||
"key": "name",
|
||||
"fields": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
await couchdb.db.use(instanceId).insert(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
exports.createClientDatabase = async () => {
|
||||
await couchdb.db.create(CLIENT_DB_ID);
|
||||
|
||||
|
@ -30,6 +46,8 @@ exports.createInstanceDatabase = async instanceId => {
|
|||
}
|
||||
}
|
||||
}, '_design/database');
|
||||
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
exports.insertDocument = async (databaseId, document) => {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
const couchdb = require("../../../../db");
|
||||
const supertest = require("supertest");
|
||||
const app = require("../../../../app");
|
||||
const { createInstanceDatabase, destroyDatabase } = require("./couchTestUtils");
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
const supertest = require("supertest");
|
||||
const app = require("../../../../app");
|
||||
const { createInstanceDatabase, createModel, destroyDatabase } = require("./couchTestUtils");
|
||||
|
||||
|
||||
const TEST_INSTANCE_ID = "testing-123";
|
||||
|
||||
describe("/models", () => {
|
||||
let request;
|
||||
let server;
|
||||
|
||||
beforeAll(async () => {
|
||||
server = await app({
|
||||
config: {
|
||||
port: 3000
|
||||
}
|
||||
});
|
||||
request = supertest(server);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
server.close();
|
||||
})
|
||||
|
||||
describe("create", () => {
|
||||
beforeEach(async () => {
|
||||
await createInstanceDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await destroyDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
it("returns a success message when the model is successfully created", done => {
|
||||
request
|
||||
.post(`/api/${TEST_INSTANCE_ID}/models`)
|
||||
.send({
|
||||
name: "TestModel",
|
||||
key: "name",
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string"
|
||||
}
|
||||
]
|
||||
})
|
||||
.set("Accept", "application/json")
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(async (err, res) => {
|
||||
expect(res.body.message).toEqual("Model TestModel created successfully.");
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe("fetch", () => {
|
||||
let testModel;
|
||||
|
||||
beforeEach(async () => {
|
||||
await createInstanceDatabase(TEST_INSTANCE_ID);
|
||||
testModel = await createModel(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await destroyDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
it("returns all the models for that instance in the response body", done => {
|
||||
request
|
||||
.get(`/api/${TEST_INSTANCE_ID}/models`)
|
||||
.set("Accept", "application/json")
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(async (_, res) => {
|
||||
const fetchedModel = res.body[0].doc;
|
||||
expect(fetchedModel.name).toEqual(testModel.name);
|
||||
expect(fetchedModel.type).toEqual("model");
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue