diff --git a/errors/index.js b/errors/index.js index bd78a41..f0ad2e4 100644 --- a/errors/index.js +++ b/errors/index.js @@ -1,16 +1,18 @@ class NotFoundError extends Error { - constructor(...args) { + constructor(text, ...args) { super(...args); Error.captureStackTrace(this, NotFoundError); this.name = 'NotFound'; + this.text = text; } } class BadRequestError extends Error { - constructor(...args) { + constructor(text, ...args) { super(...args); Error.captureStackTrace(this, NotFoundError); this.name = 'BadRequest'; + this.text = text; } } diff --git a/models/Todo.js b/models/Todo.js index 0779cb5..2f41151 100644 --- a/models/Todo.js +++ b/models/Todo.js @@ -14,14 +14,22 @@ const TodoSchema = Schema({ TodoSchema.pre('save', async function () { const list = await TodoList.findById(this.list); - list.todos.push(this.id); + list.todos.push(this._id); await list.save(); }); TodoSchema.pre('remove', async function () { const list = await TodoList.findById(this.list); - list.todos.remove(this.id); + list.todos.splice(list.todos.indexOf(this._id), 1); await list.save(); }); +TodoSchema.methods.toJson = function () { + return { + id: this._id, + text: this.text, + list: this.list, + }; +}; + mongoose.model('Todo', TodoSchema); diff --git a/models/TodoList.js b/models/TodoList.js index 1aa395b..e7a8311 100644 --- a/models/TodoList.js +++ b/models/TodoList.js @@ -33,4 +33,14 @@ TodoListSchema.pre('remove', async function () { }); }); +TodoListSchema.methods.toJson = function () { + const todos = this.populated('todos') ? this.todos.map(todo => todo.toJson()) : this.todos; + return { + id: this._id, + name: this.name, + slug: this.slug, + todos, + }; +}; + mongoose.model('TodoList', TodoListSchema); diff --git a/routes/listIdMiddleware.js b/routes/listIdMiddleware.js index f0066e4..ee3f7ae 100644 --- a/routes/listIdMiddleware.js +++ b/routes/listIdMiddleware.js @@ -10,7 +10,7 @@ module.exports = asyncHelper(async (req, res, next) => { const { slug } = req.params; const list = await TodoList.findOne({ slug }).exec(); if (!list) { - throw new NotFoundError(); + throw new NotFoundError('cant find list'); } res.locals.listId = list._id; next(); diff --git a/routes/lists.js b/routes/lists.js index 4c8b5f0..6dba0b8 100644 --- a/routes/lists.js +++ b/routes/lists.js @@ -16,7 +16,7 @@ router.get( const lists = await TodoList.find({}) .populate('todos') .exec(); - res.json(lists); + res.json({ success: true, data: lists.map(list => list.toJson()) }); }), ); diff --git a/routes/todos.js b/routes/todos.js index e60e5a7..1fc13af 100644 --- a/routes/todos.js +++ b/routes/todos.js @@ -7,13 +7,14 @@ const Todo = mongoose.model('Todo'); const asyncHelper = require('../asyncHelper'); +const { NotFoundError } = require('../errors'); // index router.get( '/', asyncHelper(async (req, res) => { const { listId } = res.locals; const todos = await Todo.find({ list: listId }).exec(); - res.json(todos); + res.json({ success: true, data: todos.map(todo => todo.toJson()) }); }), ); @@ -52,7 +53,11 @@ router.delete( '/:todoId', asyncHelper(async (req, res) => { const { todoId } = req.params; - await Todo.findByIdAndRemove(todoId).exec(); + const todo = await Todo.findById(todoId).exec(); + if (!todo) { + throw new NotFoundError('cant find todo'); + } + await todo.remove(); res.json({ success: true }); }), ); diff --git a/tests/integration/lists.test.js b/tests/integration/lists.test.js new file mode 100644 index 0000000..05dfa9e --- /dev/null +++ b/tests/integration/lists.test.js @@ -0,0 +1,22 @@ +const server = require('../../app.js'); + +const request = require('supertest'); +const mongoose = require('mongoose'); + +afterAll(async () => { + await mongoose.connection.dropDatabase(); + await mongoose.disconnect(); + await server.close(); +}); + +describe('test lists', () => { + test('index lists', async () => { + const response = await request(server) + .get('/lists') + .set('Accept', 'application/json') + .expect(200) + .expect('Content-Type', 'application/json; charset=utf-8'); + expect(response.body.success).toBe(true); + expect(response.body.data).toBeInstanceOf(Array); + }); +});