mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-07-19 13:19:42 +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
9
.editorconfig
Normal file
9
.editorconfig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
root = false
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
15
.eslintrc
Normal file
15
.eslintrc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"codex"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"chai-friendly"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-unused-expressions": 0,
|
||||||
|
"chai-friendly/no-unused-expressions": 2
|
||||||
|
}
|
||||||
|
}
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -61,4 +61,7 @@ typings/
|
||||||
.next
|
.next
|
||||||
|
|
||||||
# JetBrains IDE environment
|
# JetBrains IDE environment
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# Database files
|
||||||
|
db/
|
13
app.js
13
app.js
|
@ -4,8 +4,7 @@ const path = require('path');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const logger = require('morgan');
|
const logger = require('morgan');
|
||||||
|
|
||||||
const indexRouter = require('./routes/index');
|
const routes = require('./routes');
|
||||||
const usersRouter = require('./routes/users');
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
@ -15,20 +14,18 @@ app.set('view engine', 'twig');
|
||||||
|
|
||||||
app.use(logger('dev'));
|
app.use(logger('dev'));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.urlencoded({ extended: false }));
|
app.use(express.urlencoded({extended: true}));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.static(path.join(__dirname, 'public')));
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
|
||||||
app.use('/', indexRouter);
|
app.use('/', routes);
|
||||||
app.use('/users', usersRouter);
|
|
||||||
|
|
||||||
// catch 404 and forward to error handler
|
// catch 404 and forward to error handler
|
||||||
app.use(function(req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
next(createError(404));
|
next(createError(404));
|
||||||
});
|
});
|
||||||
|
|
||||||
// error handler
|
// error handler
|
||||||
app.use(function(err, req, res, next) {
|
app.use(function (err, req, res, next) {
|
||||||
// set locals, only providing error in development
|
// set locals, only providing error in development
|
||||||
res.locals.message = err.message;
|
res.locals.message = err.message;
|
||||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||||
|
|
21
bin/www
21
bin/www
|
@ -3,21 +3,21 @@
|
||||||
/**
|
/**
|
||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
const app = require('../app')
|
const app = require('../app');
|
||||||
const debug = require('debug')('codex.editor.docs:server')
|
const debug = require('debug')('codex.editor.docs:server');
|
||||||
const http = require('http')
|
const http = require('http');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
||||||
*/
|
*/
|
||||||
const port = normalizePort(process.env.PORT || '3000')
|
const port = normalizePort(process.env.PORT || '3000');
|
||||||
|
|
||||||
app.set('port', port);
|
app.set('port', port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create HTTP server.
|
* Create HTTP server.
|
||||||
*/
|
*/
|
||||||
const server = http.createServer(app)
|
const server = http.createServer(app);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen on provided port, on all network interfaces.
|
* Listen on provided port, on all network interfaces.
|
||||||
|
@ -32,7 +32,7 @@ server.on('listening', onListening);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function normalizePort(val) {
|
function normalizePort(val) {
|
||||||
const port = parseInt(val, 10)
|
const port = parseInt(val, 10);
|
||||||
|
|
||||||
if (isNaN(port)) {
|
if (isNaN(port)) {
|
||||||
// named pipe
|
// named pipe
|
||||||
|
@ -58,7 +58,7 @@ function onError(error) {
|
||||||
|
|
||||||
const bind = typeof port === 'string'
|
const bind = typeof port === 'string'
|
||||||
? 'Pipe ' + port
|
? 'Pipe ' + port
|
||||||
: 'Port ' + port
|
: 'Port ' + port;
|
||||||
|
|
||||||
// handle specific listen errors with friendly messages
|
// handle specific listen errors with friendly messages
|
||||||
switch (error.code) {
|
switch (error.code) {
|
||||||
|
@ -80,9 +80,12 @@ function onError(error) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function onListening() {
|
function onListening() {
|
||||||
const addr = server.address()
|
const addr = server.address();
|
||||||
const bind = typeof addr === 'string'
|
const bind = typeof addr === 'string'
|
||||||
? 'pipe ' + addr
|
? 'pipe ' + addr
|
||||||
: 'port ' + addr.port
|
: 'port ' + addr.port;
|
||||||
|
|
||||||
debug('Listening on ' + bind);
|
debug('Listening on ' + bind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {server, app};
|
106
controllers/pages.js
Normal file
106
controllers/pages.js
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
const Model = require('../models/page');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Pages
|
||||||
|
* @classdesc Pages controller
|
||||||
|
*/
|
||||||
|
class Pages {
|
||||||
|
/**
|
||||||
|
* @static
|
||||||
|
* Fields required for page model creation
|
||||||
|
*
|
||||||
|
* @returns {['title', 'body']}
|
||||||
|
*/
|
||||||
|
static get REQUIRED_FIELDS() {
|
||||||
|
return ['title', 'body'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @static
|
||||||
|
* Find and return page model with passed id
|
||||||
|
*
|
||||||
|
* @param {string} id - page id
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
static async get(id) {
|
||||||
|
const page = await Model.get(id);
|
||||||
|
|
||||||
|
if (!page._id) {
|
||||||
|
throw new Error('Page with given id does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all pages
|
||||||
|
*
|
||||||
|
* @returns {Promise<Page[]>}
|
||||||
|
*/
|
||||||
|
static async getAll() {
|
||||||
|
return Model.getAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new page model and save it in the database
|
||||||
|
*
|
||||||
|
* @param {PageData} data
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
static async insert(data) {
|
||||||
|
if (!Pages.validate(data)) {
|
||||||
|
throw new Error('Invalid request format');
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = new Model(data);
|
||||||
|
|
||||||
|
return page.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check PageData object for required fields
|
||||||
|
*
|
||||||
|
* @param {PageData} data
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static validate(data) {
|
||||||
|
return Pages.REQUIRED_FIELDS.every(field => typeof data[field] !== 'undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update page with given id in the database
|
||||||
|
*
|
||||||
|
* @param {string} id - page id
|
||||||
|
* @param {PageData} data
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
static async update(id, data) {
|
||||||
|
const page = await Model.get(id);
|
||||||
|
|
||||||
|
if (!page._id) {
|
||||||
|
throw new Error('Page with given id does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
page.data = data;
|
||||||
|
|
||||||
|
return page.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove page with given id from the database
|
||||||
|
*
|
||||||
|
* @param {string} id - page id
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
static async remove(id) {
|
||||||
|
const page = await Model.get(id);
|
||||||
|
|
||||||
|
if (!page._id) {
|
||||||
|
throw new Error('Page with given id does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
return page.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Pages;
|
146
database/index.js
Normal file
146
database/index.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
const pages = require('./pages');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Database
|
||||||
|
* @classdesc Simple decorator class to work with nedb datastore
|
||||||
|
*
|
||||||
|
* @property db - nedb Datastore object
|
||||||
|
*/
|
||||||
|
class Database {
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {Object} nedbInstance - nedb Datastore object
|
||||||
|
*/
|
||||||
|
constructor(nedbInstance) {
|
||||||
|
this.db = nedbInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert new document into the database
|
||||||
|
* @see https://github.com/louischatriot/nedb#inserting-documents
|
||||||
|
*
|
||||||
|
* @param {Object} doc - object to insert
|
||||||
|
* @returns {Promise<Object|Error>} - inserted doc or Error object
|
||||||
|
*/
|
||||||
|
async insert(doc) {
|
||||||
|
return new Promise((resolve, reject) => this.db.insert(doc, (err, newDoc) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(newDoc);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find documents that match passed query
|
||||||
|
* @see https://github.com/louischatriot/nedb#finding-documents
|
||||||
|
*
|
||||||
|
* @param {Object} query - query object
|
||||||
|
* @param {Object} projection - projection object
|
||||||
|
* @returns {Promise<Array<Object>|Error>} - found docs or Error object
|
||||||
|
*/
|
||||||
|
async find(query, projection) {
|
||||||
|
const cbk = (resolve, reject) => (err, docs) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(docs);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (projection) {
|
||||||
|
this.db.find(query, projection, cbk(resolve, reject));
|
||||||
|
} else {
|
||||||
|
this.db.find(query, cbk(resolve, reject));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find one document matches passed query
|
||||||
|
* @see https://github.com/louischatriot/nedb#finding-documents
|
||||||
|
*
|
||||||
|
* @param {Object} query - query object
|
||||||
|
* @param {Object} projection - projection object
|
||||||
|
* @returns {Promise<Object|Error>} - found doc or Error object
|
||||||
|
*/
|
||||||
|
async findOne(query, projection) {
|
||||||
|
const cbk = (resolve, reject) => (err, doc) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(doc);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (projection) {
|
||||||
|
this.db.findOne(query, projection, cbk(resolve, reject));
|
||||||
|
} else {
|
||||||
|
this.db.findOne(query, cbk(resolve, reject));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update document matches query
|
||||||
|
* @see https://github.com/louischatriot/nedb#updating-documents
|
||||||
|
*
|
||||||
|
* @param {Object} query - query object
|
||||||
|
* @param {Object} update - fields to update
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Boolean} options.multi - (false) allows update several documents
|
||||||
|
* @param {Boolean} options.upsert - (false) if true, upsert document with update fields.
|
||||||
|
* Method will return inserted doc or number of affected docs if doc hasn't been inserted
|
||||||
|
* @param {Boolean} options.returnUpdatedDocs - (false) if true, returns affected docs
|
||||||
|
* @returns {Promise<number|Object|Object[]|Error>} - number of updated rows or affected docs or Error object
|
||||||
|
*/
|
||||||
|
async update(query, update, options = {}) {
|
||||||
|
return new Promise((resolve, reject) => this.db.update(query, update, options, (err, result, affectedDocs) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case options.returnUpdatedDocs:
|
||||||
|
resolve(affectedDocs);
|
||||||
|
break;
|
||||||
|
case options.upsert:
|
||||||
|
if (affectedDocs) {
|
||||||
|
resolve(affectedDocs);
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove document matches passed query
|
||||||
|
* @see https://github.com/louischatriot/nedb#removing-documents
|
||||||
|
*
|
||||||
|
* @param {Object} query - query object
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Boolean} options.multi - (false) if true, remove several docs
|
||||||
|
* @returns {Promise<number|Error>} - number of removed rows or Error object
|
||||||
|
*/
|
||||||
|
async remove(query, options = {}) {
|
||||||
|
return new Promise((resolve, reject) => this.db.remove(query, options, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(result);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
class: Database,
|
||||||
|
pages: new Database(pages)
|
||||||
|
};
|
5
database/pages.js
Normal file
5
database/pages.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const Datastore = require('nedb');
|
||||||
|
|
||||||
|
const db = new Datastore({filename: './db/pages.db', autoload: true});
|
||||||
|
|
||||||
|
module.exports = db;
|
160
models/page.js
Normal file
160
models/page.js
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
const {pages} = require('../database');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PageData
|
||||||
|
* @property {string} _id - page id
|
||||||
|
* @property {string} title - page title
|
||||||
|
* @property {*} body - page body
|
||||||
|
* @property {string} parent - id of parent page
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Page
|
||||||
|
* @class Page model
|
||||||
|
*
|
||||||
|
* @property {string} _id - page id
|
||||||
|
* @property {string} title - page title
|
||||||
|
* @property {*} body - page body
|
||||||
|
* @property {string} _parent - id of parent page
|
||||||
|
*/
|
||||||
|
class Page {
|
||||||
|
/**
|
||||||
|
* Find and return model of page with given id
|
||||||
|
* @param {string} _id - page id
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
static async get(_id) {
|
||||||
|
const data = await pages.findOne({_id});
|
||||||
|
|
||||||
|
return new Page(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all pages which match passed query object
|
||||||
|
*
|
||||||
|
* @param {Object} query
|
||||||
|
* @returns {Promise<Page[]>}
|
||||||
|
*/
|
||||||
|
static async getAll(query = {}) {
|
||||||
|
const docs = await pages.find(query);
|
||||||
|
|
||||||
|
return Promise.all(docs.map(doc => new Page(doc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*
|
||||||
|
* @param {PageData} data
|
||||||
|
*/
|
||||||
|
constructor(data = {}) {
|
||||||
|
if (data === null) {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.db = pages;
|
||||||
|
|
||||||
|
if (data._id) {
|
||||||
|
this._id = data._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set PageData object fields to internal model fields
|
||||||
|
*
|
||||||
|
* @param {PageData} pageData
|
||||||
|
*/
|
||||||
|
set data(pageData) {
|
||||||
|
const {title, body, parent} = pageData;
|
||||||
|
|
||||||
|
this.title = title || this.title;
|
||||||
|
this.body = body || this.body;
|
||||||
|
this._parent = parent || this._parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return PageData object
|
||||||
|
*
|
||||||
|
* @returns {PageData}
|
||||||
|
*/
|
||||||
|
get data() {
|
||||||
|
return {
|
||||||
|
_id: this._id,
|
||||||
|
title: this.title,
|
||||||
|
body: this.body,
|
||||||
|
parent: this._parent
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link given page as parent
|
||||||
|
*
|
||||||
|
* @param {Page} parentPage
|
||||||
|
*/
|
||||||
|
set parent(parentPage) {
|
||||||
|
this._parent = parentPage._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return parent page model
|
||||||
|
*
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
get parent() {
|
||||||
|
return this.db.findOne({_id: this._parent})
|
||||||
|
.then(data => new Page(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return child pages models
|
||||||
|
*
|
||||||
|
* @returns {Promise<Page[]>}
|
||||||
|
*/
|
||||||
|
get children() {
|
||||||
|
return this.db.find({parent: this._id})
|
||||||
|
.then(data => data.map(page => new Page(page)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save or update page data in the database
|
||||||
|
*
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
async save() {
|
||||||
|
if (!this._id) {
|
||||||
|
const insertedRow = await this.db.insert(this.data);
|
||||||
|
|
||||||
|
this._id = insertedRow._id;
|
||||||
|
} else {
|
||||||
|
await this.db.update({_id: this._id}, this.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove page data from the database
|
||||||
|
*
|
||||||
|
* @returns {Promise<Page>}
|
||||||
|
*/
|
||||||
|
async destroy() {
|
||||||
|
await this.db.remove({_id: this._id});
|
||||||
|
|
||||||
|
delete this._id;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return readable page data
|
||||||
|
*
|
||||||
|
* @returns {PageData}
|
||||||
|
*/
|
||||||
|
toJSON() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Page;
|
22
package.json
22
package.json
|
@ -3,14 +3,32 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./bin/www"
|
"start": "nodemon ./bin/www",
|
||||||
|
"test": "mocha --recursive ./test",
|
||||||
|
"lint": "eslint --fix ./**/*.js",
|
||||||
|
"precommit": "yarn lint && yarn test --exit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"body-parser": "latest",
|
||||||
"cookie-parser": "~1.4.3",
|
"cookie-parser": "~1.4.3",
|
||||||
"debug": "~2.6.9",
|
"debug": "~2.6.9",
|
||||||
"express": "~4.16.0",
|
"express": "~4.16.0",
|
||||||
"http-errors": "~1.6.2",
|
"http-errors": "~1.6.2",
|
||||||
"morgan": "~1.9.0",
|
"morgan": "~1.9.0",
|
||||||
"twig": "~0.10.3"
|
"multer": "^1.3.1",
|
||||||
|
"nedb": "^1.8.0",
|
||||||
|
"nodemon": "^1.18.3",
|
||||||
|
"twig": "~0.10.3",
|
||||||
|
"uuid4": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^4.1.2",
|
||||||
|
"chai-http": "^4.0.0",
|
||||||
|
"eslint": "^5.3.0",
|
||||||
|
"eslint-config-codex": "github:codex-team/eslint-config",
|
||||||
|
"eslint-plugin-chai-friendly": "^0.4.1",
|
||||||
|
"husky": "^0.14.3",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"nyc": "^12.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
routes/home.js
Normal file
9
routes/home.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
/* GET home page. */
|
||||||
|
router.get('/', function (req, res, next) {
|
||||||
|
res.render('index', { title: 'Express' });
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -1,9 +1,10 @@
|
||||||
const express = require('express')
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
/* GET home page. */
|
const home = require('./home');
|
||||||
router.get('/', function(req, res, next) {
|
const pages = require('./pages');
|
||||||
res.render('index', { title: 'Express' });
|
|
||||||
});
|
router.use('/', home);
|
||||||
|
router.use('/', pages);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
115
routes/pages.js
Normal file
115
routes/pages.js
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const multer = require('multer')();
|
||||||
|
const Pages = require('../controllers/pages');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /page/:id
|
||||||
|
*
|
||||||
|
* Return PageData of page with given id
|
||||||
|
*/
|
||||||
|
router.get('/page/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const page = await Pages.get(req.params.id);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page.data
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /pages
|
||||||
|
*
|
||||||
|
* Return PageData for all pages
|
||||||
|
*/
|
||||||
|
router.get('/pages', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const pages = await Pages.getAll();
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: pages
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /page
|
||||||
|
*
|
||||||
|
* Create new page in the database
|
||||||
|
*/
|
||||||
|
router.put('/page', multer.any(), async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {title, body, parent} = req.body;
|
||||||
|
const page = await Pages.insert({title, body, parent});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /page/:id
|
||||||
|
*
|
||||||
|
* Update page data in the database
|
||||||
|
*/
|
||||||
|
router.post('/page/:id', multer.any(), async (req, res) => {
|
||||||
|
const {id} = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const {title, body, parent} = req.body;
|
||||||
|
const page = await Pages.update(id, {title, body, parent});
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /page/:id
|
||||||
|
*
|
||||||
|
* Remove page from the database
|
||||||
|
*/
|
||||||
|
router.delete('/page/:id', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const page = await Pages.remove(req.params.id);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
result: page
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -1,9 +0,0 @@
|
||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
/* GET users listing. */
|
|
||||||
router.get('/', function(req, res, next) {
|
|
||||||
res.send('respond with a resource');
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
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