Skip to content

Commit 37f84fc

Browse files
committed
part 3a
1 parent 9384c06 commit 37f84fc

13 files changed

Lines changed: 934 additions & 2 deletions

File tree

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
part1/courseinfo/.env
1+
22
.vscode/settings.json
33
node_modules
4-
part3/phonebook/.eslintignore
4+
.eslintignore
55
part3/phonebook/vercel.json
6+
.env

part4/blog/controllers/blog.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const blogRouter = require("express").Router();
2+
const Blog = require("../models/blog");
3+
4+
blogRouter
5+
.route("/")
6+
.get((req, res, next) => {
7+
Blog.find({})
8+
.then((blogs) => {
9+
res.json(blogs);
10+
})
11+
.catch((err) => next(err));
12+
})
13+
.post((req, res, next) => {
14+
const blog = new Blog(req.body);
15+
16+
blog
17+
.save()
18+
.then((result) => {
19+
res.status(201).json(result);
20+
})
21+
.catch((err) => next(err));
22+
});
23+
24+
module.exports = blogRouter;

part4/blog/index.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const express = require("express");
2+
const app = express();
3+
const cors = require("cors");
4+
const mongoose = require("mongoose");
5+
const config = require("./utils/config");
6+
const blogRouter = require("./controllers/blog");
7+
const morgan = require("morgan")
8+
const middleware = require("./utils/middleware")
9+
10+
morgan.token("body", function (req, res) {
11+
return JSON.stringify(req.body);
12+
});
13+
14+
mongoose.connect(config.mongoUrl, {
15+
useNewUrlParser: true,
16+
useUnifiedTopology: true,
17+
useFindAndModify: false,
18+
useCreateIndex: true,
19+
});
20+
21+
app.use(cors());
22+
app.use(express.json());
23+
app.use(
24+
morgan(":method :url :status :res[content-length] - :response-time ms :body")
25+
);
26+
app.use("/api/blog", blogRouter);
27+
app.use(middleware.unknownEndpoint)
28+
app.use(middleware.errorHandler)
29+
app.listen(config.PORT, () => {
30+
console.log(`Server running on port ${config.PORT}`);
31+
});

part4/blog/models/blog.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const mongoose = require("mongoose");
2+
const uniqueValidator = require("mongoose-unique-validator");
3+
4+
const blogSchema = new mongoose.Schema({
5+
title: { type: String, required: true, unique: true },
6+
author: { type: String, required: true, unique: true },
7+
url: { type: String, required: true, unique: true },
8+
likes: { type: Number },
9+
});
10+
11+
blogSchema.plugin(uniqueValidator);
12+
13+
blogSchema.set("toJSON", {
14+
transform: (document, returnedObject) => {
15+
returnedObject.id = returnedObject._id.toString();
16+
delete returnedObject._id;
17+
delete returnedObject.__v;
18+
},
19+
});
20+
21+
module.exports = mongoose.model("Blog", blogSchema);

part4/blog/package.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "blog",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"start": "node index.js",
7+
"dev": "nodemon index.js",
8+
"test": "jest --verbose"
9+
},
10+
"author": "Joseph Odunsi",
11+
"license": "MIT",
12+
"dependencies": {
13+
"cors": "^2.8.5",
14+
"dotenv": "^8.2.0",
15+
"express": "^4.17.1",
16+
"mongoose": "^5.12.5",
17+
"morgan": "^1.10.0"
18+
},
19+
"devDependencies": {
20+
"mongoose-unique-validator": "^2.0.3"
21+
}
22+
}

part4/blog/test/dummy.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const listHelper = require("../utils/list_helper")
2+
3+
test("dummy returns one", () => {
4+
const blogs = [];
5+
6+
const result = listHelper.dummy(blogs);
7+
expect(result).toBe(1);
8+
});
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
const favoriteBlog = require("../utils/list_helper").favoriteBlog;
2+
3+
describe("favorite blog", () => {
4+
const blogs = [
5+
{
6+
_id: "5a422a851b54a676234d17f7",
7+
title: "React patterns",
8+
author: "Michael Chan",
9+
url: "https://reactpatterns.com/",
10+
likes: 7,
11+
__v: 0,
12+
},
13+
{
14+
_id: "5a422aa71b54a676234d17f8",
15+
title: "Go To Statement Considered Harmful",
16+
author: "Edsger W. Dijkstra",
17+
url:
18+
"http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html",
19+
likes: 5,
20+
__v: 0,
21+
},
22+
{
23+
_id: "5a422b3a1b54a676234d17f9",
24+
title: "Canonical string reduction",
25+
author: "Edsger W. Dijkstra",
26+
url: "http://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD808.html",
27+
likes: 12,
28+
__v: 0,
29+
},
30+
{
31+
_id: "5a422b891b54a676234d17fa",
32+
title: "First class tests",
33+
author: "Robert C. Martin",
34+
url:
35+
"http://blog.cleancoder.com/uncle-bob/2017/05/05/TestDefinitions.htmll",
36+
likes: 10,
37+
__v: 0,
38+
},
39+
{
40+
_id: "5a422ba71b54a676234d17fb",
41+
title: "TDD harms architecture",
42+
author: "Robert C. Martin",
43+
url:
44+
"http://blog.cleancoder.com/uncle-bob/2017/03/03/TDD-Harms-Architecture.html",
45+
likes: 0,
46+
__v: 0,
47+
},
48+
{
49+
_id: "5a422bc61b54a676234d17fc",
50+
title: "Type wars",
51+
author: "Robert C. Martin",
52+
url: "http://blog.cleancoder.com/uncle-bob/2016/05/01/TypeWars.html",
53+
likes: 2,
54+
__v: 0,
55+
},
56+
];
57+
58+
test("blog with the most likes", () => {
59+
const result = {
60+
title: "Canonical string reduction",
61+
author: "Edsger W. Dijkstra",
62+
likes: 12,
63+
};
64+
65+
expect(favoriteBlog(blogs)).toEqual(result);
66+
});
67+
});

part4/blog/test/totalLikes.test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
const totalLikes = require("../utils/list_helper").totalLikes;
2+
3+
describe("get the total likes in a blog list", () => {
4+
const blogs = [
5+
{
6+
_id: "5a422a851b54a676234d17f7",
7+
title: "React patterns",
8+
author: "Michael Chan",
9+
url: "https://reactpatterns.com/",
10+
likes: 7,
11+
__v: 0,
12+
},
13+
{
14+
_id: "5a422aa71b54a676234d17f8",
15+
title: "Go To Statement Considered Harmful",
16+
author: "Edsger W. Dijkstra",
17+
url:
18+
"http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html",
19+
likes: 5,
20+
__v: 0,
21+
},
22+
{
23+
_id: "5a422b3a1b54a676234d17f9",
24+
title: "Canonical string reduction",
25+
author: "Edsger W. Dijkstra",
26+
url: "http://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD808.html",
27+
likes: 12,
28+
__v: 0,
29+
},
30+
{
31+
_id: "5a422b891b54a676234d17fa",
32+
title: "First class tests",
33+
author: "Robert C. Martin",
34+
url:
35+
"http://blog.cleancoder.com/uncle-bob/2017/05/05/TestDefinitions.htmll",
36+
likes: 10,
37+
__v: 0,
38+
},
39+
{
40+
_id: "5a422ba71b54a676234d17fb",
41+
title: "TDD harms architecture",
42+
author: "Robert C. Martin",
43+
url:
44+
"http://blog.cleancoder.com/uncle-bob/2017/03/03/TDD-Harms-Architecture.html",
45+
likes: 0,
46+
__v: 0,
47+
},
48+
{
49+
_id: "5a422bc61b54a676234d17fc",
50+
title: "Type wars",
51+
author: "Robert C. Martin",
52+
url: "http://blog.cleancoder.com/uncle-bob/2016/05/01/TypeWars.html",
53+
likes: 2,
54+
__v: 0,
55+
},
56+
];
57+
const blog = [
58+
{
59+
_id: "5a422a851b54a676234d17f7",
60+
title: "React patterns",
61+
author: "Michael Chan",
62+
url: "https://reactpatterns.com/",
63+
likes: 7,
64+
__v: 0,
65+
},
66+
];
67+
test("expects zero when list is empty", ()=>{
68+
expect(totalLikes([])).toBe(0)
69+
});
70+
71+
test("when list has only one blog equals the likes of that", ()=>{
72+
expect(totalLikes(blog)).toBe(7)
73+
})
74+
75+
test("with bigger list", ()=>{
76+
expect(totalLikes(blogs)).toBe(36)
77+
})
78+
});

part4/blog/utils/config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require("dotenv").config();
2+
const mongoUrl = process.env.MONGO_URL;
3+
const PORT = process.env.PORT;
4+
5+
module.exports = { mongoUrl , PORT};

part4/blog/utils/list_helper.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const dummy = (blogs) => {
2+
return 1;
3+
};
4+
5+
const totalLikes = (blogs) => {
6+
return blogs.reduce((acc, cur) => {
7+
return acc + cur.likes;
8+
}, 0);
9+
};
10+
11+
const favoriteBlog = (blogs) => {
12+
const fav = blogs.sort((a, b) => b.likes - a.likes)[0];
13+
return { title: fav.title, author: fav.author, likes: fav.likes };
14+
};
15+
16+
const mostBlogs = (blogs) => {
17+
const most = blogs.sort((a, b) => b.likes - a.likes)[0];
18+
19+
}
20+
21+
module.exports = {
22+
dummy,
23+
totalLikes,
24+
favoriteBlog,
25+
};

0 commit comments

Comments
 (0)