mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-08-04 21:15:23 +02:00
Page model (#1)
* Initial database and page MVC * Add mocha tests * Add docs * Add docs about nedb query options * Add eslint and editorconfig + husky * Improve precommit script * Remove unnecessary dependencies
This commit is contained in:
parent
2e717f6415
commit
7add63d90b
20 changed files with 4361 additions and 42 deletions
178
test/database.js
Normal file
178
test/database.js
Normal file
|
@ -0,0 +1,178 @@
|
|||
const fs = require('fs');
|
||||
const {expect} = require('chai');
|
||||
|
||||
const {class: Database} = require('../database');
|
||||
const Datastore = require('nedb');
|
||||
|
||||
describe('Database', () => {
|
||||
const pathToDB = './db/test.db';
|
||||
let nedbInstance;
|
||||
let db;
|
||||
|
||||
before(() => {
|
||||
if (fs.existsSync(pathToDB)) {
|
||||
fs.unlinkSync(pathToDB);
|
||||
}
|
||||
});
|
||||
|
||||
it('Creating db instance', async () => {
|
||||
nedbInstance = new Datastore({filename: pathToDB, autoload: true});
|
||||
db = new Database(nedbInstance);
|
||||
});
|
||||
|
||||
it('Inserting document', async () => {
|
||||
const data = 'Text data';
|
||||
|
||||
const insertedDoc = await db.insert({data});
|
||||
|
||||
expect(insertedDoc).to.be.a('object');
|
||||
expect(insertedDoc.data).to.equal(data);
|
||||
});
|
||||
|
||||
it('Finding document', async () => {
|
||||
const data = 'Text data';
|
||||
|
||||
const insertedDoc = await db.insert({data});
|
||||
|
||||
expect(insertedDoc).to.be.a('object');
|
||||
expect(insertedDoc.data).to.equal(data);
|
||||
|
||||
const foundDoc = await db.findOne({_id: insertedDoc._id});
|
||||
|
||||
expect(foundDoc).not.be.null;
|
||||
expect(foundDoc._id).to.equal(insertedDoc._id);
|
||||
expect(foundDoc.data).to.equal(data);
|
||||
|
||||
const projectedDoc = await db.findOne({_id: insertedDoc._id}, {data: 1, _id: 0});
|
||||
|
||||
expect(Object.keys(projectedDoc).length).to.equal(1);
|
||||
expect(Object.keys(projectedDoc).pop()).to.equal('data');
|
||||
});
|
||||
|
||||
it('Updating document', async () => {
|
||||
const data = 'Text data';
|
||||
|
||||
const insertedDoc = await db.insert({data});
|
||||
|
||||
expect(insertedDoc).to.be.a('object');
|
||||
expect(insertedDoc.data).to.equal(data);
|
||||
|
||||
const updatedData = 'Updated text data';
|
||||
|
||||
await db.update({_id: insertedDoc._id}, {data: updatedData});
|
||||
|
||||
const updatedDoc = await db.findOne({_id: insertedDoc._id});
|
||||
|
||||
expect(updatedDoc).not.be.null;
|
||||
expect(updatedDoc.data).not.equal(data);
|
||||
expect(updatedDoc.data).to.equal(updatedData);
|
||||
});
|
||||
|
||||
it('Updating documents with options', async () => {
|
||||
const data = {update: true, data: 'Text data'};
|
||||
|
||||
await db.insert(data);
|
||||
await db.insert(data);
|
||||
|
||||
let numberOfUpdatedDocs = await db.update({update: true}, {$set: {data: 'First update'}}, {multi: true});
|
||||
|
||||
expect(numberOfUpdatedDocs).to.equal(2);
|
||||
|
||||
const affectedDocs = await db.update({update: true}, {$set: {data: 'Second update'}}, {multi: true, returnUpdatedDocs: true});
|
||||
|
||||
expect(affectedDocs).to.be.a('array');
|
||||
affectedDocs.forEach(doc => {
|
||||
expect(doc.data).to.equal('Second update');
|
||||
});
|
||||
|
||||
const upsertedDoc = await db.update({update: true, data: 'First update'}, {$set: {data: 'Third update'}}, {upsert: true});
|
||||
|
||||
expect(upsertedDoc.update).to.be.true;
|
||||
expect(upsertedDoc.data).to.equal('Third update');
|
||||
|
||||
numberOfUpdatedDocs = await db.update({data: 'Third update'}, {$set: {data: 'Fourth update'}}, {upsert: true});
|
||||
|
||||
expect(numberOfUpdatedDocs).to.equal(1);
|
||||
});
|
||||
|
||||
it('Finding documents', async () => {
|
||||
const data1 = 'Text data 1';
|
||||
const data2 = 'Text data 2';
|
||||
|
||||
const insertedDoc1 = await db.insert({data: data1, flag: true, no: 1});
|
||||
const insertedDoc2 = await db.insert({data: data2, flag: true, no: 2});
|
||||
|
||||
const foundDocs = await db.find({flag: true});
|
||||
|
||||
expect(foundDocs).to.be.a('array');
|
||||
expect(foundDocs.length).to.equal(2);
|
||||
|
||||
foundDocs.sort(({no: a}, {no: b}) => a - b);
|
||||
|
||||
expect(foundDocs[0]._id).to.equal(insertedDoc1._id);
|
||||
expect(foundDocs[0].data).to.equal(insertedDoc1.data);
|
||||
expect(foundDocs[1]._id).to.equal(insertedDoc2._id);
|
||||
expect(foundDocs[1].data).to.equal(insertedDoc2.data);
|
||||
|
||||
const projectedDocs = await db.find({flag: true}, {no: 1, _id: 0});
|
||||
|
||||
expect(projectedDocs.length).to.equal(2);
|
||||
projectedDocs.forEach(data => {
|
||||
expect(Object.keys(data).length).to.equal(1);
|
||||
expect(Object.keys(data).pop()).to.equal('no');
|
||||
});
|
||||
});
|
||||
|
||||
it('Removing document', async () => {
|
||||
const data = 'Text data';
|
||||
|
||||
const insertedDoc = await db.insert({data});
|
||||
|
||||
expect(insertedDoc).to.be.a('object');
|
||||
expect(insertedDoc.data).to.equal(data);
|
||||
|
||||
await db.remove({_id: insertedDoc._id});
|
||||
|
||||
const deletedDoc = await db.findOne({_id: insertedDoc._id});
|
||||
|
||||
expect(deletedDoc).to.be.null;
|
||||
});
|
||||
|
||||
it('Test invalid database queries', async () => {
|
||||
try {
|
||||
await db.insert();
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Cannot read property \'_id\' of undefined');
|
||||
}
|
||||
|
||||
try {
|
||||
await db.find({size: {$invalidComparator: 1}});
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Unknown comparison function $invalidComparator');
|
||||
}
|
||||
|
||||
try {
|
||||
await db.findOne({field: {$invalidComparator: 1}});
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Unknown comparison function $invalidComparator');
|
||||
}
|
||||
|
||||
try {
|
||||
await db.update({field: {$undefinedComparator: 1}});
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Unknown comparison function $undefinedComparator');
|
||||
}
|
||||
|
||||
try {
|
||||
await db.remove({field: {$undefinedComparator: 1}});
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Unknown comparison function $undefinedComparator');
|
||||
}
|
||||
});
|
||||
|
||||
after(() => {
|
||||
if (fs.existsSync(pathToDB)) {
|
||||
fs.unlinkSync(pathToDB);
|
||||
}
|
||||
});
|
||||
});
|
19
test/express.js
Normal file
19
test/express.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
const {app} = require('../bin/www');
|
||||
const chai = require('chai');
|
||||
const chaiHTTP = require('chai-http');
|
||||
const {expect} = chai;
|
||||
|
||||
chai.use(chaiHTTP);
|
||||
|
||||
describe('Express app', () => {
|
||||
it('App is available', (done) => {
|
||||
chai
|
||||
.request(app)
|
||||
.get('/')
|
||||
.end((err, res) => {
|
||||
expect(err).to.be.null;
|
||||
expect(res).to.have.status(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
165
test/models/page.js
Normal file
165
test/models/page.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
const {expect} = require('chai');
|
||||
const Page = require('../../models/page');
|
||||
const {pages} = require('../../database');
|
||||
|
||||
describe('Page model', () => {
|
||||
it('Working with empty model', async () => {
|
||||
let page = new Page();
|
||||
|
||||
expect(page.data).to.be.a('object');
|
||||
|
||||
let {data} = page;
|
||||
|
||||
expect(data._id).to.be.undefined;
|
||||
expect(data.title).to.be.undefined;
|
||||
expect(data.body).to.be.undefined;
|
||||
expect(data.parent).to.be.undefined;
|
||||
|
||||
page = new Page(null);
|
||||
|
||||
data = page.data;
|
||||
|
||||
expect(data._id).to.be.undefined;
|
||||
expect(data.title).to.be.undefined;
|
||||
expect(data.body).to.be.undefined;
|
||||
expect(data.parent).to.be.undefined;
|
||||
|
||||
const initialData = {_id: 'page_id', title: 'Test page', body: 'Test page body'};
|
||||
|
||||
page = new Page(initialData);
|
||||
|
||||
const json = page.toJSON();
|
||||
|
||||
data = page.data;
|
||||
|
||||
expect(data._id).to.equal(initialData._id);
|
||||
expect(data.title).to.equal(initialData.title);
|
||||
expect(data.body).to.equal(initialData.body);
|
||||
expect(data.parent).to.be.undefined;
|
||||
|
||||
expect(json._id).to.equal(initialData._id);
|
||||
expect(json.title).to.equal(initialData.title);
|
||||
expect(json.body).to.equal(initialData.body);
|
||||
expect(json.parent).to.be.undefined;
|
||||
|
||||
const update = {
|
||||
_id: 12345,
|
||||
title: 'Test page',
|
||||
body: 'Test page body'
|
||||
};
|
||||
|
||||
page.data = update;
|
||||
|
||||
data = page.data;
|
||||
|
||||
expect(data._id).to.equal(initialData._id);
|
||||
expect(data.title).to.equal(update.title);
|
||||
expect(data.body).to.equal(update.body);
|
||||
expect(data.parent).to.be.undefined;
|
||||
});
|
||||
|
||||
it('Saving, updating and deleting model in the database', async () => {
|
||||
const initialData = {title: 'Test page', body: 'Test page body'};
|
||||
const page = new Page(initialData);
|
||||
|
||||
let savedPage = await page.save();
|
||||
|
||||
expect(savedPage._id).not.be.undefined;
|
||||
expect(savedPage.title).to.equal(initialData.title);
|
||||
expect(savedPage.body).to.equal(initialData.body);
|
||||
expect(page._id).not.be.undefined;
|
||||
|
||||
const insertedPage = await pages.findOne({_id: page._id});
|
||||
|
||||
expect(insertedPage._id).to.equal(page._id);
|
||||
expect(insertedPage.title).to.equal(page.title);
|
||||
expect(insertedPage.body).to.equal(page.body);
|
||||
|
||||
const updateData = {title: 'Updated test page', body: 'Updated test page body'};
|
||||
|
||||
page.data = updateData;
|
||||
await page.save();
|
||||
|
||||
expect(page._id).to.equal(insertedPage._id);
|
||||
|
||||
const updatedPage = await pages.findOne({_id: page._id});
|
||||
|
||||
expect(updatedPage._id).to.equal(savedPage._id);
|
||||
expect(updatedPage.title).to.equal(updateData.title);
|
||||
expect(updatedPage.body).to.equal(updateData.body);
|
||||
|
||||
await page.destroy();
|
||||
|
||||
expect(page._id).to.be.undefined;
|
||||
|
||||
const removedPage = await pages.findOne({_id: updatedPage._id});
|
||||
|
||||
expect(removedPage).to.be.null;
|
||||
});
|
||||
|
||||
it('Static get method', async () => {
|
||||
const initialData = {title: 'Test page', body: 'Test page body'};
|
||||
const page = new Page(initialData);
|
||||
|
||||
const savedPage = await page.save();
|
||||
|
||||
const foundPage = await Page.get(savedPage._id);
|
||||
|
||||
const {data} = foundPage;
|
||||
|
||||
expect(data._id).to.equal(savedPage._id);
|
||||
expect(data.title).to.equal(initialData.title);
|
||||
expect(data.body).to.equal(initialData.body);
|
||||
|
||||
await page.destroy();
|
||||
});
|
||||
|
||||
it('Static getAll method', async () => {
|
||||
const pagesToSave = [
|
||||
new Page({title: 'Page 1', body: 'Page 1 body'}),
|
||||
new Page({title: 'Page 2', body: 'Page 2 body'})
|
||||
];
|
||||
|
||||
const savedPages = await Promise.all(pagesToSave.map(page => page.save()));
|
||||
|
||||
const foundPages = await Page.getAll({_id: {$in: savedPages.map(page => page._id)}});
|
||||
|
||||
expect(foundPages.length).to.equal(2);
|
||||
foundPages.forEach((page, i) => {
|
||||
expect(page.title).to.equal(pagesToSave[i].title);
|
||||
expect(page.body).to.equal(pagesToSave[i].body);
|
||||
});
|
||||
});
|
||||
|
||||
it('Parent pages', async () => {
|
||||
const parent = new Page({title: 'Parent page', body: 'Parent page body'});
|
||||
const {_id: parentId} = await parent.save();
|
||||
|
||||
const child = new Page({title: 'Child page', body: 'Child page body'});
|
||||
|
||||
child.parent = parent;
|
||||
|
||||
const {_id: childId} = await child.save();
|
||||
|
||||
const testedParent = await child.parent;
|
||||
|
||||
expect(testedParent._id).to.equal(parentId);
|
||||
expect(testedParent.title).to.equal(parent.title);
|
||||
expect(testedParent.body).to.equal(parent.body);
|
||||
|
||||
const children = await parent.children;
|
||||
|
||||
expect(children.length).to.equal(1);
|
||||
|
||||
const testedChild = children.pop();
|
||||
|
||||
expect(testedChild._id).to.equal(childId);
|
||||
expect(testedChild.title).to.equal(child.title);
|
||||
expect(testedChild.body).to.equal(child.body);
|
||||
expect(testedChild._parent).to.equal(child._parent);
|
||||
expect(testedChild._parent).to.equal(parent._id);
|
||||
|
||||
parent.destroy();
|
||||
child.destroy();
|
||||
});
|
||||
});
|
202
test/rest/pages.js
Normal file
202
test/rest/pages.js
Normal file
|
@ -0,0 +1,202 @@
|
|||
const {app} = require('../../bin/www');
|
||||
const model = require('../../models/page');
|
||||
|
||||
const chai = require('chai');
|
||||
const chaiHTTP = require('chai-http');
|
||||
const {expect} = chai;
|
||||
|
||||
chai.use(chaiHTTP);
|
||||
|
||||
describe('Pages REST: ', () => {
|
||||
let agent;
|
||||
|
||||
before(async () => {
|
||||
agent = chai.request.agent(app);
|
||||
});
|
||||
|
||||
it('Creating page', async () => {
|
||||
const title = 'Test page';
|
||||
const body = 'Test page body';
|
||||
|
||||
const res = await agent
|
||||
.put('/page')
|
||||
.send({title, body});
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, result} = res.body;
|
||||
|
||||
expect(success).to.be.true;
|
||||
expect(result._id).to.be.a('string');
|
||||
expect(result.title).to.equal(title);
|
||||
expect(result.body).to.equal(body);
|
||||
|
||||
const createdPage = await model.get(result._id);
|
||||
|
||||
expect(createdPage).not.be.null;
|
||||
expect(createdPage._id).to.equal(result._id);
|
||||
expect(createdPage.title).to.equal(title);
|
||||
expect(createdPage.body).to.equal(body);
|
||||
|
||||
createdPage.destroy();
|
||||
});
|
||||
|
||||
it('Page data validation on create', async () => {
|
||||
const res = await agent
|
||||
.put('/page')
|
||||
.send({someField: 'Some text'});
|
||||
|
||||
expect(res).to.have.status(400);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, error} = res.body;
|
||||
|
||||
expect(success).to.be.false;
|
||||
expect(error).to.equal('Invalid request format');
|
||||
});
|
||||
|
||||
it('Finding page', async () => {
|
||||
const title = 'Test page';
|
||||
const body = 'Test page body';
|
||||
|
||||
const put = await agent
|
||||
.put('/page')
|
||||
.send({title, body});
|
||||
|
||||
expect(put).to.have.status(200);
|
||||
expect(put).to.be.json;
|
||||
|
||||
const {result: {_id}} = put.body;
|
||||
|
||||
const get = await agent.get(`/page/${_id}`);
|
||||
|
||||
expect(get).to.have.status(200);
|
||||
expect(get).to.be.json;
|
||||
|
||||
const {success} = get.body;
|
||||
|
||||
expect(success).to.be.true;
|
||||
|
||||
const foundPage = await model.get(_id);
|
||||
|
||||
expect(foundPage._id).to.equal(_id);
|
||||
expect(foundPage.title).to.equal(title);
|
||||
expect(foundPage.body).to.equal(body);
|
||||
|
||||
foundPage.destroy();
|
||||
});
|
||||
|
||||
it('Finding page with not existing id', async () => {
|
||||
const res = await agent.get('/page/not-existing-id');
|
||||
|
||||
expect(res).to.have.status(400);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, error} = res.body;
|
||||
|
||||
expect(success).to.be.false;
|
||||
expect(error).to.equal('Page with given id does not exist');
|
||||
});
|
||||
|
||||
it('Updating page', async () => {
|
||||
const title = 'Test page';
|
||||
const body = 'Test page body';
|
||||
|
||||
let res = await agent
|
||||
.put('/page')
|
||||
.send({title, body});
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {result: {_id}} = res.body;
|
||||
|
||||
const updatedTitle = 'Updated test page';
|
||||
const updatedBody = 'Updated test page body';
|
||||
|
||||
res = await agent
|
||||
.post(`/page/${_id}`)
|
||||
.send({title: updatedTitle, body: updatedBody});
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, result} = res.body;
|
||||
|
||||
expect(success).to.be.true;
|
||||
expect(result._id).to.equal(_id);
|
||||
expect(result.title).not.equal(title);
|
||||
expect(result.title).to.equal(updatedTitle);
|
||||
expect(result.body).not.equal(body);
|
||||
expect(result.body).to.equal(updatedBody);
|
||||
|
||||
const updatedPage = await model.get(_id);
|
||||
|
||||
expect(updatedPage._id).to.equal(_id);
|
||||
expect(updatedPage.title).not.equal(title);
|
||||
expect(updatedPage.title).to.equal(updatedTitle);
|
||||
expect(updatedPage.body).not.equal(body);
|
||||
expect(updatedPage.body).to.equal(updatedBody);
|
||||
|
||||
updatedPage.destroy();
|
||||
});
|
||||
|
||||
it('Updating page with not existing id', async () => {
|
||||
const res = await agent
|
||||
. post('/page/not-existing-id')
|
||||
.send({title: 'Updated title', body: 'Updated body'});
|
||||
|
||||
expect(res).to.have.status(400);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, error} = res.body;
|
||||
|
||||
expect(success).to.be.false;
|
||||
expect(error).to.equal('Page with given id does not exist');
|
||||
});
|
||||
|
||||
it('Removing page', async () => {
|
||||
const title = 'Test page';
|
||||
const body = 'Test page body';
|
||||
|
||||
let res = await agent
|
||||
.put('/page')
|
||||
.send({title, body});
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {result: {_id}} = res.body;
|
||||
|
||||
res = await agent
|
||||
.delete(`/page/${_id}`);
|
||||
|
||||
expect(res).to.have.status(200);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, result} = res.body;
|
||||
|
||||
expect(success).to.be.true;
|
||||
expect(result._id).to.be.undefined;
|
||||
expect(result.title).to.equal(title);
|
||||
expect(result.body).to.equal(body);
|
||||
|
||||
const deletedPage = await model.get(_id);
|
||||
|
||||
expect(deletedPage._id).to.be.undefined;
|
||||
});
|
||||
|
||||
it('Removing page with not existing id', async () => {
|
||||
const res = await agent
|
||||
.delete('/page/not-existing-id');
|
||||
|
||||
expect(res).to.have.status(400);
|
||||
expect(res).to.be.json;
|
||||
|
||||
const {success, error} = res.body;
|
||||
|
||||
expect(success).to.be.false;
|
||||
expect(error).to.equal('Page with given id does not exist');
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue