Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
97ab303
config: small refactor
MateuszKikmunter Feb 9, 2022
ea89959
config spec init
MateuszKikmunter Feb 9, 2022
f6bcbf6
config tests WIP
MateuszKikmunter Feb 9, 2022
a741eb5
fixed req.query undefined case
MateuszKikmunter Feb 9, 2022
70d996f
added config.filter tests
MateuszKikmunter Feb 9, 2022
65ccf6c
added config.sort tests
MateuszKikmunter Feb 9, 2022
29e0b3c
addef page and offset tests
MateuszKikmunter Feb 9, 2022
09818a5
added limit tests
MateuszKikmunter Feb 9, 2022
0fee0ce
added all params test
MateuszKikmunter Feb 9, 2022
8a4ba28
removed not needed handler
MateuszKikmunter Feb 9, 2022
93fa75b
removed not used controller
MateuszKikmunter Feb 13, 2022
7e006f8
added mockingoose
MateuszKikmunter Feb 13, 2022
ca0d833
made book controller bit more modern
MateuszKikmunter Feb 13, 2022
b5b2a83
WIP
MateuszKikmunter Feb 13, 2022
6981b9e
added api controller tests
MateuszKikmunter Feb 14, 2022
c7eeddc
book api controller tests
MateuszKikmunter Feb 14, 2022
a444370
removed not used method
MateuszKikmunter Feb 14, 2022
477bc5d
chapter api spec init
MateuszKikmunter Feb 14, 2022
d6ca10a
removed some commented code
MateuszKikmunter Feb 14, 2022
4e8d8fd
removed some commented code
MateuszKikmunter Feb 14, 2022
b68d649
changed chapter to use async await
MateuszKikmunter Feb 14, 2022
4d65e33
added chapter tests
MateuszKikmunter Feb 14, 2022
d62478e
character api spec init
MateuszKikmunter Feb 14, 2022
15bcb70
made character more modern
MateuszKikmunter Feb 14, 2022
d40c8f8
added character controller tests
MateuszKikmunter Feb 14, 2022
c6f416f
movie spec init
MateuszKikmunter Feb 14, 2022
f0204c1
removed not used action
MateuszKikmunter Feb 14, 2022
8a46c71
removed not used import
MateuszKikmunter Feb 14, 2022
7e9afbe
modenized movie controller
MateuszKikmunter Feb 14, 2022
f61aae0
added movie spec
MateuszKikmunter Feb 14, 2022
94e5e71
modernized quote api
MateuszKikmunter Feb 14, 2022
ed4e8e2
quote api spec init
MateuszKikmunter Feb 14, 2022
7bb3439
added quote spec
MateuszKikmunter Feb 14, 2022
47df6ab
moved error reponse to shared const
MateuszKikmunter Feb 14, 2022
22aacf7
added HttpCode
MateuszKikmunter Feb 14, 2022
a2da065
modernized auth a bit
MateuszKikmunter Feb 16, 2022
de179d9
auth spec init
MateuszKikmunter Feb 16, 2022
6d8e897
added tests for auth
MateuszKikmunter Feb 16, 2022
b13e291
Merge branch 'release' into add-some-backend-tests
MateuszKikmunter Feb 16, 2022
4274288
added note about running tests
Feb 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ With Version 2, this Open Source project is now open for contribution! You can h
- use your favorite Mongo client to access user documents and get your new access_token for using the secured APIs
- OR login with your credentials in the Frontend to get your token

### Running tests

- navigate to the specific project (*backend* or *frontend*) and execute `npm test`.

### **HACK AWAY!** 🔨🔨🔨

### 🔃 Create a new pull request
Expand Down
66 changes: 0 additions & 66 deletions backend/controllers/api.js

This file was deleted.

32 changes: 16 additions & 16 deletions backend/controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const { nanoid } = require("nanoid");
const lambda_func = process.env.AWS_LAMBDA_NEWUSER_URL || null;
const fetch = require('node-fetch');

const { errorResponse, HttpCode } = require('../helpers/constants');

function generatePasswordHash(password) {
let hash = password;
let salt = bcrypt.genSaltSync(10);
Expand All @@ -20,7 +22,7 @@ module.exports = {
try {
req.login(user, { session: false }, async (error) => {
if (error)
return res.status(500).send({
return res.status(HttpCode.SERVER_ERROR).send({
success: false,
message: "Login failed",
});
Expand All @@ -37,7 +39,7 @@ module.exports = {
});
});
} catch (e) {
return res.status(500).send({
return res.status(HttpCode.SERVER_ERROR).send({
success: false,
message: "Login failed",
});
Expand All @@ -47,31 +49,29 @@ module.exports = {
const { email, password } = req.body;
const doesUserExit = await User.exists({ email: email });
if (doesUserExit) {
return res.status(500).send({
return res.status(HttpCode.SERVER_ERROR).send({
success: false,
message: "User already exists",
});
} else if (validator.isEmail(email) && !validator.isEmpty(password)) {
const hash = generatePasswordHash(password);
const access_token = nanoid(20);
var newUser = new User({
email: email,
password: hash,
access_token: access_token,
});
newUser.save(function (err) {
if (err) return res.status(500).send(err);
try {
await User.create({
email: email,
password: hash,
access_token: access_token,
});
// send notification email via aws lambda in prod
if (lambda_func) fetch(process.env.AWS_LAMBDA_NEWUSER_URL);
return res.json({
success: true,
});
});
} catch (err) {
return res.status(HttpCode.SERVER_ERROR).send(err);
}
} else {
return res.status(500).send({
success: false,
message: "Something went wrong.",
});
return res.status(HttpCode.SERVER_ERROR).send(errorResponse);
}
},
}
};
63 changes: 63 additions & 0 deletions backend/controllers/auth.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const express = require('express');
const request = require('supertest');
const mockingoose = require('mockingoose');

const { HttpCode } = require('../helpers/constants');

const userModel = require('../models/user.model');
const authController = require('./auth');

const app = express();
const router = express.Router();

router.route("/register").post(authController.register);

app.use(express.json());
app.use('/auth', router);

const requestBody = { email: 'email@mail.com', password: 'P@$$1' };

describe('auth controller', () => {

beforeEach(() => {
mockingoose.resetAll();
});

it('/register/ should return HTTP 500 if user already exists', async () => {
//to mock exists we need to use 'findOne' -> https://github.com/alonronin/mockingoose/issues/69
mockingoose(userModel).toReturn({}, 'findOne');
const response = await request(app).post('/auth/register/').send(requestBody);
expect(response.statusCode).toEqual(HttpCode.SERVER_ERROR);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('User already exists');
});

it('/register/ should return HTTP 500 when email validation fails', async () => {
mockingoose(userModel).toReturn(null, 'findOne');
const response = await request(app).post('/auth/register/').send({ ...requestBody, email: 'invalid.email.com' });
expect(response.statusCode).toEqual(HttpCode.SERVER_ERROR);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Something went wrong.');
});

it('/register/ should return HTTP 500 when password is empty', async () => {
mockingoose(userModel).toReturn(null, 'findOne');
const response = await request(app).post('/auth/register/').send({ ...requestBody, password: '' });
expect(response.statusCode).toEqual(HttpCode.SERVER_ERROR);
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Something went wrong.');
});

it('/register/ should return HTTP 200 when user saved', async () => {
mockingoose(userModel).toReturn({ email: 'email@mail.com' }, 'save');
const response = await request(app).post('/auth/register/').send(requestBody);
expect(response.statusCode).toEqual(HttpCode.OK);
expect(response.body.success).toEqual(true);
});

it('/register/ should return HTTP 500 when registration failed', async () => {
mockingoose(userModel).toReturn(new Error('error'), 'save');
const response = await request(app).post('/auth/register/').send(requestBody);
expect(response.statusCode).toEqual(HttpCode.SERVER_ERROR);
});
});
64 changes: 29 additions & 35 deletions backend/controllers/book.api.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,43 @@
const Book = require("./../models/book.model");
const Chapter = require("./../models/chapter.model");
const mongoose = require("mongoose");
const config = require("./../helpers/config");
const Book = require('./../models/book.model');
const Chapter = require('./../models/chapter.model');
const mongoose = require('mongoose');
const config = require('./../helpers/config');

const { errorResponse } = require('../helpers/constants');

module.exports = {
getBooks: async function (req, res) {
getBooks: async (req, res) => {
const options = await config.getOptions(req);
await Book.paginate(options.filter, options, async function (err, books) {
if (err) {
return res.json({
success: false,
message: "Something went wrong.",
});
}
try {
const books = await Book.paginate(options.filter, options);
return res.json(books);
});
} catch (err) {
return res.json(errorResponse);
}
},
getBook: async function (req, res) {
getBook: async (req, res) => {
const options = await config.getOptions(req);

const id = req.params.id;
await Book.paginate({ _id: id }, options, async function (err, book) {
if (err) {
return res.json({
success: false,
message: "Something went wrong.",
});
}
try {
const id = req.params.id;
const book = await Book.paginate({ _id: id }, options);
return res.json(book);
});
} catch (err) {
return res.json(errorResponse);
}
},
getChaptersByBook: async function (req, res) {
getChaptersByBook: async (req, res) => {
const options = await config.getOptions(req);

const id = req.params.id;
await Chapter.paginate({book: mongoose.Types.ObjectId(id)}, {
select: {chapterName: 1, bookName: 1},
...options
}, async function (err, book) {
if (err) {
return res.json({
success: false,
});
}
try {
const id = req.params.id;
const book = await Chapter.paginate({ book: mongoose.Types.ObjectId(id) }, {
select: { chapterName: 1, bookName: 1 },
...options
});
return res.json(book);
});
} catch (err) {
return res.json(errorResponse);
}
},
};
100 changes: 100 additions & 0 deletions backend/controllers/book.api.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const express = require('express');
const request = require('supertest');
const mockingoose = require('mockingoose');

const { HttpCode } = require('../helpers/constants');

const chapterModel = require('../models/chapter.model');

const bookController = require('./book.api');
const bookModel = require('../models/book.model');

const app = express();
const router = express.Router();

router.route("/book").get(bookController.getBooks);
router.route("/book/:id").get(bookController.getBook);
router.route("/book/:id/chapter").get(bookController.getChaptersByBook);

app.use(express.json());
app.use('/v2', router);

describe('book controller', () => {

beforeEach(() => {
mockingoose.resetAll();
});

it('/book/ should return list of books', async () => {
const fakeBooks = [
{
"_id": "5cf5805fb53e011a64671582",
"name": "The Fellowship Of The Ring"
},
{
"_id": "5cf58077b53e011a64671583",
"name": "The Two Towers"
},
{
"_id": "5cf58080b53e011a64671584",
"name": "The Return Of The King"
}
];
mockingoose(bookModel).toReturn(fakeBooks);
const response = await request(app).get('/v2/book/');
expect(response.statusCode).toEqual(HttpCode.OK);
expect(response.body.docs).toEqual(fakeBooks);
});


it('/book/ should handle error correctly when getting all books', async () => {
mockingoose(bookModel).toReturn(new Error('error'));
const response = await request(app).get('/v2/book/');
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Something went wrong.');
});

it('/book/:id should return a single book', async () => {
const fakeBook = {
"_id": "5cf58080b53e011a64671584",
"name": "The Return Of The King"
};
mockingoose(bookModel).toReturn(fakeBook);
const response = await request(app).get('/v2/book/5cf5805fb53e011a64671582');
expect(response.statusCode).toEqual(HttpCode.OK);
expect(response.body.docs).toEqual(fakeBook);
});


it('/book/:id should handle error correctly when getting a single book', async () => {
mockingoose(bookModel).toReturn(new Error('error'));
const response = await request(app).get('/v2/book/5cf5805fb53e011a64671582');
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Something went wrong.');
});

it('/book/:id/chapter should return chapters from book', async () => {
const fakeChapters = [
{
"_id": "6091b6d6d58360f988133bb6",
"chapterName": "Minas Tirith"
},
{
"_id": "6091b6d6d58360f988133bb7",
"chapterName": "The Passing of the Grey Company"
}
];
mockingoose(chapterModel).toReturn(fakeChapters);
const response = await request(app).get('/v2/book/5cf58080b53e011a64671584/chapter');
expect(response.statusCode).toEqual(HttpCode.OK);
expect(response.body.docs).toEqual(fakeChapters);
});


it('/book/:id/chapter should handle error correctly when getting chapters from book', async () => {
mockingoose(chapterModel).toReturn(new Error('error'));
const response = await request(app).get('/v2/book/5cf58080b53e011a64671584/chapter');
expect(response.body.success).toEqual(false);
expect(response.body.message).toEqual('Something went wrong.');
});
});
Loading