mirror of
https://github.com/usatiuk/ustk-todolist.git
synced 2025-10-28 07:37:49 +01:00
require authentication for todos,
use in-memody db for tests
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -2,4 +2,5 @@
|
||||
"editor.tabSize": 2,
|
||||
"prettier.eslintIntegration": true,
|
||||
"editor.insertSpaces": true,
|
||||
}
|
||||
"jest.pathToJest": "npm test --"
|
||||
}
|
||||
|
||||
15
app.js
15
app.js
@@ -6,24 +6,27 @@ const cors = require('cors');
|
||||
const config = require('./config');
|
||||
const db = require('./config/db');
|
||||
|
||||
require('./models/TodoList');
|
||||
require('./models/User');
|
||||
require('./models/Todo');
|
||||
|
||||
const app = express();
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(cors());
|
||||
app.use(morgan('dev'));
|
||||
|
||||
require('./models/User');
|
||||
require('./models/TodoList');
|
||||
require('./models/Todo');
|
||||
|
||||
const passport = require('./config/passport');
|
||||
|
||||
app.use(passport.initialize());
|
||||
|
||||
app.use('/lists', require('./routes/lists'));
|
||||
app.use('/todos', require('./routes/todos'));
|
||||
app.use('/users', require('./routes/users'));
|
||||
|
||||
const auth = require('./routes/auth');
|
||||
|
||||
app.use('/lists', auth.required, require('./routes/lists'));
|
||||
app.use('/todos', auth.required, require('./routes/todos'));
|
||||
|
||||
// 404 route
|
||||
app.use((req, res) => {
|
||||
res.status(404);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
const mongoose = require('mongoose');
|
||||
const config = require('./');
|
||||
|
||||
const { host, port, name } = config.db;
|
||||
const connectionString = `mongodb://${host}:${port}/${name}`;
|
||||
|
||||
async function connect() {
|
||||
const { host, port, name } = config.db;
|
||||
const connectionString = `mongodb://${host}:${port}/${name}`;
|
||||
|
||||
await mongoose.connect(connectionString);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,8 @@ const dev = {
|
||||
},
|
||||
secret: process.env.DEV_SECRET || 'devsecret',
|
||||
};
|
||||
|
||||
const test = {
|
||||
app: {
|
||||
port: process.env.TEST_APP_PORT || 4001,
|
||||
},
|
||||
db: {
|
||||
host: process.env.TEST_DB_HOST || 'localhost',
|
||||
port: process.env.TEST_DB_PORT || 27017,
|
||||
name: process.env.TEST_DB_NAME || 'todolistTest',
|
||||
},
|
||||
secret: process.env.TEST_SECRET || 'testsecret',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const TodoSchema = Schema({
|
||||
@@ -9,17 +8,26 @@ const TodoSchema = Schema({
|
||||
required: true,
|
||||
},
|
||||
list: { type: Schema.Types.ObjectId, ref: 'TodoList', required: true },
|
||||
user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
||||
completed: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
TodoSchema.pre('save', async function () {
|
||||
const list = await TodoList.findById(this.list);
|
||||
const user = await this.model('User').findById(this.user);
|
||||
user.todos.push(this._id);
|
||||
await user.save();
|
||||
|
||||
const list = await this.model('TodoList').findById(this.list);
|
||||
list.todos.push(this._id);
|
||||
await list.save();
|
||||
});
|
||||
|
||||
TodoSchema.pre('remove', async function () {
|
||||
const list = await TodoList.findById(this.list);
|
||||
const user = await this.model('User').findById(this.user);
|
||||
user.todos.splice(user.todos.indexOf(this._id), 1);
|
||||
await user.save();
|
||||
|
||||
const list = await this.model('TodoList').findById(this.list);
|
||||
list.todos.splice(list.todos.indexOf(this._id), 1);
|
||||
await list.save();
|
||||
});
|
||||
@@ -29,6 +37,7 @@ TodoSchema.methods.toJson = function () {
|
||||
id: this._id.toString(),
|
||||
text: this.text,
|
||||
list: this.list.toString(),
|
||||
user: this.user.toString(),
|
||||
completed: this.completed,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,18 +8,27 @@ const TodoListSchema = Schema({
|
||||
required: true,
|
||||
},
|
||||
todos: [{ type: Schema.Types.ObjectId, ref: 'Todo' }],
|
||||
user: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
||||
});
|
||||
|
||||
TodoListSchema.pre('save', async function () {
|
||||
const user = await this.model('User').findById(this.user);
|
||||
user.lists.push(this._id);
|
||||
await user.save();
|
||||
});
|
||||
|
||||
TodoListSchema.pre('remove', async function () {
|
||||
this.todos.forEach(async (todo) => {
|
||||
await todo.remove();
|
||||
});
|
||||
const user = await this.model('User').findById(this.user);
|
||||
user.lists.splice(user.todos.indexOf(this._id), 1);
|
||||
await user.save();
|
||||
await this.model('Todo').remove({ list: this._id });
|
||||
});
|
||||
|
||||
TodoListSchema.methods.toJson = function () {
|
||||
const todos = this.populated('todos') ? this.todos.map(todo => todo.toJson()) : this.todos;
|
||||
return {
|
||||
id: this._id.toString(),
|
||||
user: this.user.toString(),
|
||||
name: this.name,
|
||||
todos,
|
||||
};
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
const mongoose = require('mongoose');
|
||||
const passportLocalMongoose = require('passport-local-mongoose');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const uniqueValidator = require('mongoose-unique-validator');
|
||||
|
||||
const { secret } = require('../config');
|
||||
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const UserSchema = Schema({ username: { type: String, required: true } });
|
||||
const UserSchema = Schema({
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
validate: /^\S*$/,
|
||||
},
|
||||
lists: [{ type: Schema.Types.ObjectId, ref: 'TodoList' }],
|
||||
todos: [{ type: Schema.Types.ObjectId, ref: 'Todo' }],
|
||||
});
|
||||
|
||||
UserSchema.plugin(passportLocalMongoose);
|
||||
UserSchema.plugin(uniqueValidator);
|
||||
|
||||
UserSchema.pre('remove', async function () {
|
||||
await this.model('TodoList').remove({ user: this._id });
|
||||
await this.model('Todo').remove({ user: this._id });
|
||||
});
|
||||
|
||||
UserSchema.methods.generateJwt = function () {
|
||||
return jwt.sign({ id: this._id, username: this.username }, secret, { expiresIn: '1y' });
|
||||
return jwt.sign({ id: this._id, username: this.username }, secret, { expiresIn: '6m' });
|
||||
};
|
||||
|
||||
UserSchema.methods.toAuthJson = function () {
|
||||
|
||||
394
package-lock.json
generated
394
package-lock.json
generated
@@ -1033,6 +1033,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
|
||||
"integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
|
||||
"dev": true
|
||||
},
|
||||
"basic-auth": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz",
|
||||
@@ -1057,6 +1063,16 @@
|
||||
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
|
||||
"dev": true
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"readable-stream": "^2.3.5",
|
||||
"safe-buffer": "^5.1.1"
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz",
|
||||
@@ -1169,11 +1185,50 @@
|
||||
"resolved": "https://registry.npmjs.org/bson/-/bson-1.0.6.tgz",
|
||||
"integrity": "sha512-D8zmlb46xfuK2gGvKmUjIklQEouN2nQ0LEHHeZ/NoHM2LDiMk2EYzZ5Ntw/Urk+bgMDosOZxaRzXxvhI5TcAVQ=="
|
||||
},
|
||||
"buffer": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz",
|
||||
"integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base64-js": "0.0.8",
|
||||
"ieee754": "^1.1.4",
|
||||
"isarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"buffer-alloc": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
|
||||
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-alloc-unsafe": "^1.1.0",
|
||||
"buffer-fill": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"buffer-alloc-unsafe": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
|
||||
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
|
||||
},
|
||||
"buffer-fill": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
|
||||
"integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz",
|
||||
@@ -1554,6 +1609,15 @@
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
}
|
||||
},
|
||||
"compare-versions": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.2.1.tgz",
|
||||
@@ -1764,6 +1828,95 @@
|
||||
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
|
||||
"dev": true
|
||||
},
|
||||
"decompress": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz",
|
||||
"integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"decompress-tar": "^4.0.0",
|
||||
"decompress-tarbz2": "^4.0.0",
|
||||
"decompress-targz": "^4.0.0",
|
||||
"decompress-unzip": "^4.0.1",
|
||||
"graceful-fs": "^4.1.10",
|
||||
"make-dir": "^1.0.0",
|
||||
"pify": "^2.3.0",
|
||||
"strip-dirs": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"decompress-tar": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
|
||||
"integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"file-type": "^5.2.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"tar-stream": "^1.5.2"
|
||||
}
|
||||
},
|
||||
"decompress-tarbz2": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
|
||||
"integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"decompress-tar": "^4.1.0",
|
||||
"file-type": "^6.1.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"seek-bzip": "^1.0.5",
|
||||
"unbzip2-stream": "^1.0.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
|
||||
"integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"decompress-targz": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
|
||||
"integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"decompress-tar": "^4.1.1",
|
||||
"file-type": "^5.2.0",
|
||||
"is-stream": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"decompress-unzip": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
|
||||
"integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"file-type": "^3.8.0",
|
||||
"get-stream": "^2.2.0",
|
||||
"pify": "^2.3.0",
|
||||
"yauzl": "^2.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=",
|
||||
"dev": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
|
||||
"integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-assign": "^4.0.1",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deep-extend": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
|
||||
@@ -1983,6 +2136,15 @@
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
|
||||
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
|
||||
@@ -2574,6 +2736,15 @@
|
||||
"bser": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fd-slicer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
|
||||
"integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"figures": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||
@@ -2593,6 +2764,12 @@
|
||||
"object-assign": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"file-type": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
|
||||
"integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=",
|
||||
"dev": true
|
||||
},
|
||||
"filename-regex": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
|
||||
@@ -2734,6 +2911,23 @@
|
||||
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
|
||||
"dev": true
|
||||
},
|
||||
"fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
|
||||
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -3292,6 +3486,12 @@
|
||||
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
|
||||
"dev": true
|
||||
},
|
||||
"get-port": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz",
|
||||
"integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=",
|
||||
"dev": true
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
@@ -3304,6 +3504,26 @@
|
||||
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
|
||||
"dev": true
|
||||
},
|
||||
"getos": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/getos/-/getos-3.1.0.tgz",
|
||||
"integrity": "sha512-i9vrxtDu5DlLVFcrbqUqGWYlZN/zZ4pGMICCAcZoYsX3JA54nYp8r5EThw5K+m2q3wszkx4Th746JstspB0H4Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "2.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.4.0.tgz",
|
||||
"integrity": "sha1-SZAgDxjqW4N8LMT4wDGmmFw4VhE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.14.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
@@ -3400,6 +3620,12 @@
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
||||
"dev": true
|
||||
},
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
||||
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
|
||||
"dev": true
|
||||
},
|
||||
"growly": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
|
||||
@@ -3608,6 +3834,12 @@
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz",
|
||||
"integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==",
|
||||
"dev": true
|
||||
},
|
||||
"ignore": {
|
||||
"version": "3.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz",
|
||||
@@ -3880,6 +4112,12 @@
|
||||
"is-path-inside": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-natural-number": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
|
||||
"integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=",
|
||||
"dev": true
|
||||
},
|
||||
"is-npm": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
|
||||
@@ -4653,6 +4891,15 @@
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||
"dev": true
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"jsonify": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
|
||||
@@ -4800,11 +5047,25 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lockfile": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz",
|
||||
"integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.10",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
},
|
||||
"lodash.foreach": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
||||
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
|
||||
},
|
||||
"lodash.get": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
|
||||
@@ -4940,6 +5201,15 @@
|
||||
"integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
|
||||
"dev": true
|
||||
},
|
||||
"md5-file": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/md5-file/-/md5-file-3.2.3.tgz",
|
||||
"integrity": "sha512-3Tkp1piAHaworfcCgH0jKbTvj1jWWFgbvh2cXaNCgHwyTCBxxvD1Y04rmfpvdPm1P4oXMOpm6+2H7sr7v9v8Fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-alloc": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
@@ -5086,6 +5356,38 @@
|
||||
"require_optional": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"mongodb-memory-server": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-1.7.4.tgz",
|
||||
"integrity": "sha512-8CNbBV80cBradJEuyAl+Vw45Wf0MJYTplDphGE9z3qqaQVRYG25PhZ2Uk+kyVVF6HqF4obe+meCMpoOoeXwJ8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"debug": "^3.1.0",
|
||||
"decompress": "^4.2.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"get-port": "^3.2.0",
|
||||
"getos": "^3.1.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"md5-file": "^3.2.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"request": "^2.85.0",
|
||||
"request-promise": "^4.2.2",
|
||||
"tmp": "^0.0.33",
|
||||
"uuid": "^3.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mongoose": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.1.2.tgz",
|
||||
@@ -5116,6 +5418,15 @@
|
||||
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
|
||||
"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ=="
|
||||
},
|
||||
"mongoose-unique-validator": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mongoose-unique-validator/-/mongoose-unique-validator-2.0.1.tgz",
|
||||
"integrity": "sha512-Eqq7lZMy0nPSojG8UyDZvlBie1aBZJXk68GDMBXXQH0TAi0hZHf76nCrwuipReNK1jLkjyKzV7eIZotja5eEBw==",
|
||||
"requires": {
|
||||
"lodash.foreach": "^4.1.0",
|
||||
"lodash.get": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"morgan": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz",
|
||||
@@ -5697,6 +6008,12 @@
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
||||
"dev": true
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
@@ -6098,6 +6415,18 @@
|
||||
"uuid": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"request-promise": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
|
||||
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"request-promise-core": "1.1.1",
|
||||
"stealthy-require": "^1.1.0",
|
||||
"tough-cookie": ">=2.3.3"
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
||||
@@ -6588,6 +6917,15 @@
|
||||
"resolved": "https://registry.npmjs.org/scmp/-/scmp-2.0.0.tgz",
|
||||
"integrity": "sha1-JHEQ7yLM+JexOj8KvdtSeCOTzWo="
|
||||
},
|
||||
"seek-bzip": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
|
||||
"integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "~2.8.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
|
||||
@@ -7058,6 +7396,15 @@
|
||||
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
|
||||
"dev": true
|
||||
},
|
||||
"strip-dirs": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
|
||||
"integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-natural-number": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
@@ -7135,6 +7482,21 @@
|
||||
"string-width": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz",
|
||||
"integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bl": "^1.0.0",
|
||||
"buffer-alloc": "^1.1.0",
|
||||
"end-of-stream": "^1.0.0",
|
||||
"fs-constants": "^1.0.0",
|
||||
"readable-stream": "^2.3.0",
|
||||
"to-buffer": "^1.1.0",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"term-size": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
|
||||
@@ -7526,6 +7888,12 @@
|
||||
"integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=",
|
||||
"dev": true
|
||||
},
|
||||
"to-buffer": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
|
||||
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==",
|
||||
"dev": true
|
||||
},
|
||||
"to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
@@ -7689,6 +8057,16 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"unbzip2-stream": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz",
|
||||
"integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer": "^3.0.1",
|
||||
"through": "^2.3.6"
|
||||
}
|
||||
},
|
||||
"undefsafe": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz",
|
||||
@@ -7742,6 +8120,12 @@
|
||||
"crypto-random-string": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
|
||||
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
|
||||
"dev": true
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
@@ -8185,6 +8569,16 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz",
|
||||
"integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"express-jwt": "^5.3.1",
|
||||
"jsonwebtoken": "^8.2.1",
|
||||
"mongoose": "^5.1.1",
|
||||
"mongoose-unique-validator": "^2.0.1",
|
||||
"morgan": "^1.9.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
@@ -30,6 +31,7 @@
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-jest": "^21.15.2",
|
||||
"jest": "^22.4.4",
|
||||
"mongodb-memory-server": "^1.7.4",
|
||||
"nodemon": "^1.17.5",
|
||||
"supertest": "^3.1.0"
|
||||
},
|
||||
|
||||
@@ -6,12 +6,14 @@ const router = express.Router();
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
|
||||
const asyncHelper = require('../asyncHelper');
|
||||
const auth = require('./auth');
|
||||
const { NotFoundError } = require('../errors');
|
||||
|
||||
// index
|
||||
router.get(
|
||||
'/',
|
||||
asyncHelper(async (req, res) => {
|
||||
const lists = await TodoList.find({})
|
||||
const lists = await TodoList.find({ user: req.user.id })
|
||||
.populate('todos')
|
||||
.exec();
|
||||
res.json({ success: true, data: lists.map(list => list.toJson()) });
|
||||
@@ -23,7 +25,7 @@ router.post(
|
||||
'/',
|
||||
asyncHelper(async (req, res) => {
|
||||
const { name } = req.body;
|
||||
const newList = new TodoList({ name });
|
||||
const newList = new TodoList({ name, user: req.user.id });
|
||||
await newList.save();
|
||||
res.json({ success: true, data: newList.toJson() });
|
||||
}),
|
||||
@@ -34,7 +36,7 @@ router.delete(
|
||||
'/:listId',
|
||||
asyncHelper(async (req, res) => {
|
||||
const { listId } = req.params;
|
||||
const list = await TodoList.findById(listId)
|
||||
const list = await TodoList.find({ _id: listId, user: req.user.id })
|
||||
.populate('todos')
|
||||
.exec();
|
||||
await list.remove();
|
||||
@@ -48,15 +50,13 @@ router.patch(
|
||||
asyncHelper(async (req, res) => {
|
||||
const { listId } = req.params;
|
||||
const { name } = req.body;
|
||||
const patch = {};
|
||||
if (name !== undefined) {
|
||||
patch.name = name;
|
||||
const list = await TodoList.find({ _id: listId, user: req.user.id });
|
||||
if (!list) {
|
||||
throw new NotFoundError("can't find list");
|
||||
}
|
||||
if (name !== undefined) {
|
||||
list.name = name;
|
||||
}
|
||||
const list = await TodoList.findByIdAndUpdate(
|
||||
{ _id: listId },
|
||||
{ $set: patch },
|
||||
{ new: true },
|
||||
).exec();
|
||||
await list.save();
|
||||
res.json({ success: true, data: list.toJson() });
|
||||
}),
|
||||
|
||||
@@ -13,7 +13,7 @@ router.get(
|
||||
'/',
|
||||
asyncHelper(async (req, res) => {
|
||||
const { listId } = res.locals || req.body;
|
||||
const todos = await Todo.find({ list: listId }).exec();
|
||||
const todos = await Todo.find({ list: listId, user: req.user.id }).exec();
|
||||
res.json({ success: true, data: todos.map(todo => todo.toJson()) });
|
||||
}),
|
||||
);
|
||||
@@ -24,7 +24,7 @@ router.post(
|
||||
asyncHelper(async (req, res) => {
|
||||
const { listId } = res.locals || req.body;
|
||||
const { text } = req.body;
|
||||
const todo = new Todo({ text, list: listId });
|
||||
const todo = new Todo({ text, list: listId, user: req.user.id });
|
||||
await todo.save();
|
||||
res.json({ success: true, data: todo.toJson() });
|
||||
}),
|
||||
@@ -36,16 +36,15 @@ router.patch(
|
||||
asyncHelper(async (req, res) => {
|
||||
const { todoId } = req.params;
|
||||
const { text, completed } = req.body;
|
||||
const patch = {};
|
||||
const todo = await Todo.find({ _id: todoId, user: req.user.id });
|
||||
if (!todo) {
|
||||
throw new NotFoundError("can't find todo");
|
||||
}
|
||||
if (text !== undefined) {
|
||||
patch.text = text;
|
||||
todo.text = text;
|
||||
}
|
||||
if (completed !== undefined) {
|
||||
patch.completed = completed;
|
||||
}
|
||||
const todo = await Todo.findByIdAndUpdate(todoId, { $set: patch }, { new: true }).exec();
|
||||
if (!todo) {
|
||||
throw new NotFoundError(`can't find todo with id ${todoId}`);
|
||||
todo.completed = completed;
|
||||
}
|
||||
res.json({ success: true, data: todo.toJson() });
|
||||
}),
|
||||
@@ -56,7 +55,7 @@ router.delete(
|
||||
'/:todoId',
|
||||
asyncHelper(async (req, res) => {
|
||||
const { todoId } = req.params;
|
||||
const todo = await Todo.findById(todoId).exec();
|
||||
const todo = await Todo.find({ _id: todoId, user: req.user.id }).exec();
|
||||
if (!todo) {
|
||||
throw new NotFoundError(`can't find todo with id ${todoId}`);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,11 @@ router.patch(
|
||||
if (username !== undefined) {
|
||||
patch.username = username;
|
||||
}
|
||||
const user = await User.findByIdAndUpdate(req.user.id, { $set: patch }, { new: true }).exec();
|
||||
const user = await User.findOneAndUpdate(
|
||||
{ _id: req.user.id },
|
||||
{ $set: patch },
|
||||
{ runValidators: true, context: 'query', new: true },
|
||||
).exec();
|
||||
if (!user) {
|
||||
throw new NotFoundError(`can't find user with username ${req.user.username}`);
|
||||
}
|
||||
|
||||
@@ -3,65 +3,57 @@ const server = require('../../app.js');
|
||||
const request = require('supertest');
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const db = require('../../config/db');
|
||||
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
const Todo = mongoose.model('Todo');
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
const User = mongoose.model('User');
|
||||
|
||||
let lists;
|
||||
let listsPopulated;
|
||||
let todos;
|
||||
jest.setTimeout(60000);
|
||||
const MongoDBMemoryServer = require('mongodb-memory-server').default;
|
||||
const { seed, clean } = require('./utils');
|
||||
|
||||
let user;
|
||||
let token;
|
||||
let list;
|
||||
let todo;
|
||||
let mongoServer;
|
||||
|
||||
beforeAll(async () => {
|
||||
mongoServer = new MongoDBMemoryServer();
|
||||
const mongoUri = await mongoServer.getConnectionString();
|
||||
await mongoose.connect(mongoUri);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.connect();
|
||||
|
||||
// seed lists and todos
|
||||
const list1 = new TodoList({ name: 'List1' });
|
||||
const todo1 = new Todo({ text: 'Todo1', list: list1._id });
|
||||
const todo2 = new Todo({ text: 'Todo2', list: list1._id });
|
||||
|
||||
await list1.save();
|
||||
await todo1.save();
|
||||
await todo2.save();
|
||||
lists = await TodoList.find({}).exec();
|
||||
listsPopulated = await TodoList.find({})
|
||||
.populate('todos')
|
||||
.exec();
|
||||
todos = await Todo.find({}).exec();
|
||||
({
|
||||
user, token, list, todo,
|
||||
} = await seed());
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await TodoList.remove({}).exec();
|
||||
await Todo.remove({}).exec();
|
||||
await db.disconnect();
|
||||
await clean();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await mongoose.disconnect();
|
||||
await mongoServer.stop();
|
||||
await server.close();
|
||||
});
|
||||
|
||||
describe('test lists', () => {
|
||||
test('should index lists', async () => {
|
||||
const response = await request(server)
|
||||
test('should not index lists without authentication', async () => {
|
||||
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);
|
||||
expect(response.body.data).toEqual(listsPopulated.map(list => list.toJson()));
|
||||
.expect(401);
|
||||
});
|
||||
test('should create list', async () => {
|
||||
const response = await request(server)
|
||||
test('should not create list without authentication', async () => {
|
||||
await request(server)
|
||||
.post('/lists')
|
||||
.send({
|
||||
name: 'List2',
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.set('Accept', 'application/json')
|
||||
.expect(200)
|
||||
.expect('Content-Type', 'application/json; charset=utf-8');
|
||||
expect(response.body.success).toBeTruthy();
|
||||
expect(await TodoList.findOne({ name: 'List2' })).toBeTruthy();
|
||||
.expect(401);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,26 +3,43 @@ const server = require('../../app.js');
|
||||
const request = require('supertest');
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const Todo = require('../../models/Todo');
|
||||
const TodoList = require('../../models/TodoList');
|
||||
const Todo = mongoose.model('Todo');
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
const User = mongoose.model('User');
|
||||
|
||||
const db = require('../../config/db');
|
||||
jest.setTimeout(60000);
|
||||
const MongoDBMemoryServer = require('mongodb-memory-server').default;
|
||||
const { seed, clean } = require('./utils');
|
||||
|
||||
let user;
|
||||
let token;
|
||||
let list;
|
||||
let todo;
|
||||
let mongoServer;
|
||||
|
||||
beforeAll(async () => {
|
||||
mongoServer = new MongoDBMemoryServer();
|
||||
const mongoUri = await mongoServer.getConnectionString();
|
||||
await mongoose.connect(mongoUri);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.connect();
|
||||
({
|
||||
user, token, list, todo,
|
||||
} = await seed());
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await db.disconnect();
|
||||
await clean();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await TodoList.remove({}).exec();
|
||||
await Todo.remove({}).exec();
|
||||
await mongoose.disconnect();
|
||||
await mongoServer.stop();
|
||||
await server.close();
|
||||
});
|
||||
|
||||
describe('Test not found', () => {
|
||||
describe('test not found', () => {
|
||||
test('respond not found with json', async () => {
|
||||
const response = await request(server)
|
||||
.get('/')
|
||||
|
||||
@@ -4,29 +4,40 @@ const request = require('supertest');
|
||||
const mongoose = require('mongoose');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const db = require('../../config/db');
|
||||
const { secret } = require('../../config');
|
||||
|
||||
const Todo = mongoose.model('Todo');
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
const User = mongoose.model('User');
|
||||
|
||||
jest.setTimeout(60000);
|
||||
const MongoDBMemoryServer = require('mongodb-memory-server').default;
|
||||
const { seed, clean } = require('./utils');
|
||||
const { secret } = require('../../config');
|
||||
|
||||
let user;
|
||||
let token;
|
||||
let list;
|
||||
let todo;
|
||||
let mongoServer;
|
||||
|
||||
beforeAll(async () => {
|
||||
mongoServer = new MongoDBMemoryServer();
|
||||
const mongoUri = await mongoServer.getConnectionString();
|
||||
await mongoose.connect(mongoUri);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.connect();
|
||||
|
||||
user = new User({ username: 'User' });
|
||||
await user.setPassword('password');
|
||||
await user.save();
|
||||
token = user.generateJwt();
|
||||
({
|
||||
user, token, list, todo,
|
||||
} = await seed());
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await User.remove({}).exec();
|
||||
await db.disconnect();
|
||||
await clean();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await mongoose.disconnect();
|
||||
await mongoServer.stop();
|
||||
await server.close();
|
||||
});
|
||||
|
||||
@@ -35,8 +46,8 @@ describe('test users', () => {
|
||||
const response = await request(server)
|
||||
.post('/users')
|
||||
.send({
|
||||
username: 'User 2',
|
||||
password: 'password 2',
|
||||
username: 'User2',
|
||||
password: 'password2',
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.set('Accept', 'application/json')
|
||||
@@ -44,8 +55,8 @@ describe('test users', () => {
|
||||
.expect('Content-Type', 'application/json; charset=utf-8');
|
||||
expect(response.body.success).toBeTruthy();
|
||||
const tokenDecoded = jwt.verify(response.body.data.jwt, secret);
|
||||
expect(tokenDecoded.username).toEqual('User 2');
|
||||
const userAuth = await User.authenticate()('User 2', 'password 2');
|
||||
expect(tokenDecoded.username).toEqual('User2');
|
||||
const userAuth = await User.authenticate()('User2', 'password2');
|
||||
expect(userAuth.user).toBeTruthy();
|
||||
});
|
||||
test('should not create user with no username', async () => {
|
||||
@@ -53,7 +64,7 @@ describe('test users', () => {
|
||||
.post('/users')
|
||||
.send({
|
||||
username: '',
|
||||
password: 'password 2',
|
||||
password: 'password2',
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.set('Accept', 'application/json')
|
||||
@@ -78,8 +89,8 @@ describe('test users', () => {
|
||||
const response = await request(server)
|
||||
.post('/users/login')
|
||||
.send({
|
||||
username: 'User',
|
||||
password: 'password',
|
||||
username: 'User1',
|
||||
password: 'password1',
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.set('Accept', 'application/json')
|
||||
@@ -87,7 +98,7 @@ describe('test users', () => {
|
||||
.expect('Content-Type', 'application/json; charset=utf-8');
|
||||
expect(response.body.success).toBeTruthy();
|
||||
const tokenDecoded = jwt.verify(response.body.data.jwt, secret);
|
||||
expect(tokenDecoded.username).toEqual('User');
|
||||
expect(tokenDecoded.username).toEqual('User1');
|
||||
});
|
||||
test('should not login user with no name', async () => {
|
||||
await request(server)
|
||||
@@ -115,7 +126,7 @@ describe('test users', () => {
|
||||
const response = await request(server)
|
||||
.patch('/users/user')
|
||||
.send({
|
||||
username: 'User 2',
|
||||
username: 'User2',
|
||||
password: 'password2',
|
||||
})
|
||||
.set('Authorization', `Bearer ${token}`)
|
||||
@@ -125,15 +136,15 @@ describe('test users', () => {
|
||||
.expect('Content-Type', 'application/json; charset=utf-8');
|
||||
expect(response.body.success).toBeTruthy();
|
||||
const tokenDecoded = jwt.verify(response.body.data.jwt, secret);
|
||||
expect(tokenDecoded.username).toEqual('User 2');
|
||||
const userAuth = await User.authenticate()('User 2', 'password2');
|
||||
expect(tokenDecoded.username).toEqual('User2');
|
||||
const userAuth = await User.authenticate()('User2', 'password2');
|
||||
expect(userAuth.user).toBeTruthy();
|
||||
});
|
||||
test('should not update user without authentication', async () => {
|
||||
const response = await request(server)
|
||||
.patch('/users/user')
|
||||
.send({
|
||||
username: 'User 2',
|
||||
username: 'User2',
|
||||
password: 'password2',
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
@@ -148,7 +159,7 @@ describe('test users', () => {
|
||||
.set('Accept', 'application/json')
|
||||
.expect(401);
|
||||
expect(response.body.success).toBeFalsy();
|
||||
expect(await User.findOne({ username: 'User' }).exec()).toBeTruthy();
|
||||
expect(await User.findOne({ username: 'User1' }).exec()).toBeTruthy();
|
||||
});
|
||||
test('should delete user', async () => {
|
||||
const response = await request(server)
|
||||
@@ -159,6 +170,6 @@ describe('test users', () => {
|
||||
.expect(200)
|
||||
.expect('Content-Type', 'application/json; charset=utf-8');
|
||||
expect(response.body.success).toBeTruthy();
|
||||
expect(await User.findOne({ username: 'User' }).exec()).toBeFalsy();
|
||||
expect(await User.findOne({ username: 'User1' }).exec()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
33
tests/integration/utils.js
Normal file
33
tests/integration/utils.js
Normal file
@@ -0,0 +1,33 @@
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const User = mongoose.model('User');
|
||||
const Todo = mongoose.model('Todo');
|
||||
const TodoList = mongoose.model('TodoList');
|
||||
|
||||
async function seed() {
|
||||
const user = new User({ username: 'User1' });
|
||||
await user.setPassword('password1');
|
||||
await user.save();
|
||||
const token = user.generateJwt();
|
||||
|
||||
const list = new TodoList({ name: 'List1', user: user._id });
|
||||
const todo = new Todo({ text: 'Todo1', list: list._id, user: user._id });
|
||||
|
||||
await list.save();
|
||||
await todo.save();
|
||||
|
||||
return {
|
||||
user,
|
||||
token,
|
||||
list,
|
||||
todo,
|
||||
};
|
||||
}
|
||||
|
||||
async function clean() {
|
||||
await TodoList.remove({}).exec();
|
||||
await Todo.remove({}).exec();
|
||||
await User.remove({}).exec();
|
||||
}
|
||||
|
||||
module.exports = { seed, clean };
|
||||
Reference in New Issue
Block a user