test coverage for user creation
This commit is contained in:
parent
09af351e06
commit
3b57af74ca
|
@ -0,0 +1,86 @@
|
|||
const { map, reduce, filter, isEmpty, flatten, each, union } = require("lodash/fp");
|
||||
const { compileCode } = require("../common/compileCode");
|
||||
const { validateFieldParse, validateTypeConstraints } = require("../schema/types");
|
||||
import {
|
||||
validateFieldParse,
|
||||
validateTypeConstraints,
|
||||
} from "../schema/types/index.js"
|
||||
import { $, isNonEmptyString } from "../common/index.mjs"
|
||||
|
||||
const fieldParseError = (fieldName, value) => ({
|
||||
fields: [fieldName],
|
||||
message: `Could not parse field ${fieldName}:${value}`,
|
||||
})
|
||||
|
||||
const validateAllFieldParse = (record, model) =>
|
||||
$(model.fields, [
|
||||
map(f => ({ name: f.name, parseResult: validateFieldParse(f, record) })),
|
||||
reduce((errors, f) => {
|
||||
if (f.parseResult.success) return errors
|
||||
errors.push(fieldParseError(f.name, f.parseResult.value))
|
||||
return errors
|
||||
}, []),
|
||||
])
|
||||
|
||||
const validateAllTypeConstraints = (record, model) => {
|
||||
const errors = []
|
||||
for (const field of model.fields) {
|
||||
$(validateTypeConstraints(field, record), [
|
||||
filter(isNonEmptyString),
|
||||
map(m => ({ message: m, fields: [field.name] })),
|
||||
each(e => errors.push(e)),
|
||||
])
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
const runRecordValidationRules = (record, model) => {
|
||||
const runValidationRule = rule => {
|
||||
const isValid = compileCode(rule.expressionWhenValid)
|
||||
const expressionContext = { record }
|
||||
return isValid(expressionContext)
|
||||
? { valid: true }
|
||||
: {
|
||||
valid: false,
|
||||
fields: rule.invalidFields,
|
||||
message: rule.messageWhenInvalid,
|
||||
}
|
||||
}
|
||||
|
||||
return $(model.validationRules, [
|
||||
map(runValidationRule),
|
||||
flatten,
|
||||
filter(r => r.valid === false),
|
||||
map(r => ({ fields: r.fields, message: r.message })),
|
||||
])
|
||||
}
|
||||
|
||||
export const validateRecord = (schema, record) => {
|
||||
const model = schema.findModel(record._modelId)
|
||||
const fieldParseFails = validateAllFieldParse(record, model)
|
||||
|
||||
// non parsing would cause further issues - exit here
|
||||
if (!isEmpty(fieldParseFails)) {
|
||||
return { isValid: false, errors: fieldParseFails }
|
||||
}
|
||||
|
||||
const recordValidationRuleFails = runRecordValidationRules(record, model)
|
||||
const typeContraintFails = validateAllTypeConstraints(record, model)
|
||||
|
||||
if (
|
||||
isEmpty(fieldParseFails) &&
|
||||
isEmpty(recordValidationRuleFails) &&
|
||||
isEmpty(typeContraintFails)
|
||||
) {
|
||||
return { isValid: true, errors: [] }
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: false,
|
||||
errors: union(
|
||||
fieldParseFails,
|
||||
typeContraintFails,
|
||||
recordValidationRuleFails
|
||||
),
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { testSchema } from "./testSchema.mjs"
|
||||
import { validateRecord } from "../src/records/validateRecord.mjs"
|
||||
import { validateRecord } from "../src/records/validateRecord.js"
|
||||
import { getNewRecord } from "../src/records/getNewRecord.mjs"
|
||||
|
||||
describe("validateRecord", () => {
|
||||
|
|
|
@ -12,10 +12,20 @@ exports.fetch = async function(ctx) {
|
|||
|
||||
exports.create = async function(ctx) {
|
||||
const database = couchdb.db.use(ctx.params.databaseId);
|
||||
ctx.body = await database.insert(ctx.request.body);
|
||||
const response = await database.insert(ctx.request.body);
|
||||
ctx.body = {
|
||||
...response,
|
||||
message: `User created successfully.`,
|
||||
status: 200
|
||||
}
|
||||
};
|
||||
|
||||
exports.destroy = async function(ctx) {
|
||||
const database = couchdb.db.use(ctx.params.databaseId);
|
||||
ctx.body = await database.destroy(ctx.params.userId)
|
||||
const response = await database.destroy(ctx.params.userId)
|
||||
ctx.body = {
|
||||
...response,
|
||||
message: `User deleted.`,
|
||||
status: 200
|
||||
}
|
||||
};
|
|
@ -30,4 +30,9 @@ exports.createInstanceDatabase = async instanceId => {
|
|||
}
|
||||
}
|
||||
}, '_design/database');
|
||||
}
|
||||
|
||||
exports.insertDocument = async (databaseId, document) => {
|
||||
const { id, ...documentFields } = document;
|
||||
await couchdb.db.use(databaseId).insert(documentFields, id);
|
||||
}
|
|
@ -1,29 +1,68 @@
|
|||
const couchdb = require("../../../../db");
|
||||
const supertest = require("supertest");
|
||||
const app = require("../../../../app");
|
||||
const { createInstanceDatabase } = require("./couchTestUtils");
|
||||
const { createInstanceDatabase, insertDocument, destroyDatabase } = require("./couchTestUtils");
|
||||
|
||||
|
||||
const TEST_INSTANCE_ID = "testing-123";
|
||||
const TEST_USER = {
|
||||
name: "Dave"
|
||||
}
|
||||
|
||||
describe("/users", () => {
|
||||
let request;
|
||||
let server;
|
||||
|
||||
beforeAll(async () => {
|
||||
const server = await app({
|
||||
server = await app({
|
||||
config: {
|
||||
port: 3000
|
||||
}
|
||||
});
|
||||
request = supertest(server);
|
||||
createInstanceDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
app.close();
|
||||
server.close();
|
||||
})
|
||||
|
||||
describe("fetch", () => {
|
||||
beforeEach(async () => {
|
||||
await createInstanceDatabase(TEST_INSTANCE_ID);
|
||||
await insertDocument(TEST_INSTANCE_ID, {
|
||||
id: "cool-user-id",
|
||||
type: "user",
|
||||
name: "Dave"
|
||||
})
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await destroyDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
it("returns a list of users from an instance db", done => {
|
||||
request
|
||||
.get(`/api/${TEST_INSTANCE_ID}/users`)
|
||||
.set("Accept", "application/json")
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(async (err, res) => {
|
||||
const createdUser = res.body[0].doc;
|
||||
expect(createdUser.name).toEqual(TEST_USER.name);
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe("create", () => {
|
||||
beforeEach(async () => {
|
||||
await createInstanceDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await destroyDatabase(TEST_INSTANCE_ID);
|
||||
});
|
||||
|
||||
it("returns a success message when a user is successfully created", done => {
|
||||
request
|
||||
.post(`/api/${TEST_INSTANCE_ID}/users`)
|
||||
|
@ -32,7 +71,7 @@ describe("/users", () => {
|
|||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
.end(async (err, res) => {
|
||||
expect(res.body.message).toEqual("Instance Database testing-123 successfully provisioned.");
|
||||
expect(res.body.message).toEqual("User created successfully.");
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue