const mongoose = require('mongoose') const supertest = require('supertest') const app = require('../app') const api = supertest(app) const Blog = require('../models/blog') const bcrypt = require('bcrypt') const User = require('../models/user') const helper = require('./test_helper') beforeEach(async () => { await Blog.deleteMany({}) await Blog.insertMany(helper.initialBlogs) }) describe('getting blogs', () => { test('blogs are returned as json', async () => { await api .get('/api/blogs') .expect(200) .expect('Content-Type', /application\/json/) }) test('all blogs are returned', async () => { const response = await api.get('/api/blogs') expect(response.body).toHaveLength(helper.initialBlogs.length) }) test('a specific blog is within the returned blogs', async () => { const response = await api.get('/api/blogs') const contents = response.body.map((r) => r.title) expect(contents).toContain('Another blog') }) }) describe('adding blog', () => { test('a valid blog can be added ', async () => { const newBlog = { title: 'Test', author: 'Tester', url: 'http:/test.com', likes: 999 } await api .post('/api/blogs') .send(newBlog) .expect(201) .expect('Content-Type', /application\/json/) const blogsAtEnd = await helper.blogsInDb() expect(blogsAtEnd).toHaveLength(helper.initialBlogs.length + 1) const contents = blogsAtEnd.map((n) => n.title) expect(contents).toContain('Test') }) test('blog without title or url is not added', async () => { const newBlog = { author: 'Tester', likes: 999 } await api.post('/api/blogs').send(newBlog).expect(400) const blogsAtEnd = await helper.blogsInDb() expect(blogsAtEnd).toHaveLength(helper.initialBlogs.length) }) test('blog without likes is added with 0 likes', async () => { const newBlog = { title: 'Another test', author: 'Tester', url: 'http:/test.com' } await api .post('/api/blogs') .send(newBlog) .expect(201) .expect('Content-Type', /application\/json/) const blogsAtEnd = await helper.blogsInDb() const addedBlog = blogsAtEnd.find(blog => blog.title === 'Another test') expect(addedBlog.likes).toBe(0) }) }) describe('deleting blog', () => { test('a blog can be deleted', async () => { const blogsAtStart = await helper.blogsInDb() const blogToDelete = blogsAtStart[0] await api.delete(`/api/blogs/${blogToDelete.id}`).expect(204) const blogsAtEnd = await helper.blogsInDb() expect(blogsAtEnd).toHaveLength(helper.initialBlogs.length - 1) const contents = blogsAtEnd.map((r) => r.title) expect(contents).not.toContain(blogToDelete.title) }) }) describe('updating blog', () => { test('a blog can be updated', async () => { const blogsAtStart = await helper.blogsInDb() const blogToUpdate = blogsAtStart[0] const newBlog = { title: 'Updated blog', author: blogToUpdate.author, url: blogToUpdate.url, likes: blogToUpdate.likes } await api.put(`/api/blogs/${blogToUpdate.id}`).send(newBlog).expect(200) const blogsAtEnd = await helper.blogsInDb() expect(blogsAtEnd).toHaveLength(helper.initialBlogs.length) const contents = blogsAtEnd.map((r) => r.title) expect(contents).toContain('Updated blog') }) test('creation fails with proper statuscode and message if username already taken', async () => { const usersAtStart = await helper.usersInDb() const newUser = { username: 'root', name: 'Superuser', password: 'salainen', } const result = await api .post('/api/users') .send(newUser) .expect(400) .expect('Content-Type', /application\/json/) expect(result.body.error).toContain('expected `username` to be unique') const usersAtEnd = await helper.usersInDb() expect(usersAtEnd).toEqual(usersAtStart) }) }) describe('blog id check', () => { test('blog id is defined', async () => { const response = await api.get('/api/blogs') expect(response.body[0].id).toBeDefined() }) }) describe('when there is initially one user in db', () => { beforeEach(async () => { await User.deleteMany({}) const passwordHash = await bcrypt.hash('sekret', 10) const user = new User({ username: 'root', passwordHash }) await user.save() }) test('creation succeeds with a fresh username', async () => { const usersAtStart = await helper.usersInDb() const newUser = { username: 'mluukkai', name: 'Matti Luukkainen', password: 'salainen', } await api .post('/api/users') .send(newUser) .expect(201) .expect('Content-Type', /application\/json/) const usersAtEnd = await helper.usersInDb() expect(usersAtEnd).toHaveLength(usersAtStart.length + 1) const usernames = usersAtEnd.map(u => u.username) expect(usernames).toContain(newUser.username) }) }) describe('user validation', () => { test('username must be at least 3 characters long', async () => { const newUser = { username: 'ml', name: 'Matti Luukkainen', password: 'salainen', } await api.post('/api/users').send(newUser).expect(400) }) test('password must be at least 3 characters long', async () => { const newUser = { username: 'mluukkai', name: 'Matti Luukkainen', password: 'sa', } await api.post('/api/users').send(newUser).expect(400) }) }) afterAll(async () => { await mongoose.connection.close() })