Upload 5.16

This commit is contained in:
Andrew Trieu
2023-06-22 14:25:32 +03:00
parent bb55cbad5b
commit 24a4e4cc2f
8 changed files with 516 additions and 98 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3,9 +3,6 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.2.3",
"prop-types": "^15.8.1",
"react": "^18.2.0",
@@ -18,7 +15,8 @@
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"eslint": "eslint ."
"eslint": "eslint .",
"dev": "NODE_ENV=development nodemon index.js"
},
"eslintConfig": {
"extends": [
@@ -40,6 +38,11 @@
},
"proxy": "http://localhost:3001/",
"devDependencies": {
"eslint-plugin-jest": "^27.2.2"
}
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"eslint-plugin-jest": "^27.2.2",
"nodemon": "^2.0.22"
},
"type": "module"
}

View File

@@ -1,10 +1,10 @@
import { useState, useEffect, useRef } from 'react'
import Blog from './components/Blog'
import { BlogForm } from './components/BlogForm'
import Notification from './components/Notification'
import blogService from './services/blogs'
import loginService from './services/login'
import Togglable from './components/Togglable'
import Blog from './components/Blog.js'
import { BlogForm } from './components/BlogForm.js'
import Notification from './components/Notification.js'
import blogService from './services/blogs.js'
import loginService from './services/login.js'
import Togglable from './components/Togglable.js'
const App = () => {
const [blogs, setBlogs] = useState([])
@@ -24,12 +24,12 @@ const App = () => {
setSuccessMessage(message)
setTimeout(() => {
setSuccessMessage(null)
}, 5000)
}, 3000)
} else if (type === 'error') {
setErrorMessage(message)
setTimeout(() => {
setErrorMessage(null)
}, 5000)
}, 3000)
}
}
@@ -113,7 +113,7 @@ const App = () => {
<input
type="text"
value={username}
name="Username"
name="username"
onChange={({ target }) => setUsername(target.value)}
/>
</div>
@@ -122,7 +122,7 @@ const App = () => {
<input
type="password"
value={password}
name="Password"
name="password"
onChange={({ target }) => setPassword(target.value)}
/>
</div>

View File

@@ -1,6 +1,6 @@
import { useState } from 'react'
import blogService from '../services/blogs'
import Togglable from './Togglable'
import blogService from '../services/blogs.js'
import Togglable from './Togglable.js'
const Blog = ({ blog, setNotification, removeBlog }) => {
const blogStyle = {
@@ -26,13 +26,26 @@ const Blog = ({ blog, setNotification, removeBlog }) => {
})
}
const findUser = async (blogId) => {
const blogs = await blogService.getAll()
const blogToFind = blogs.filter((blog) => blog.user).find((blog) => blog.id === blogId)
blog.user = blogToFind?.user
}
if (!blog.user) {
findUser(blog.id)
}
return (
<div style={blogStyle}>
<div style={blogStyle} className="blog">
<div>
<em>{blog.title}</em>
<Togglable buttonLabel="View">
<em>
{blog.title} by {blog.author}
</em>
<Togglable buttonLabel="View" className="blogButton">
<ul>
<li> Author: {blog.author}</li>
<li>User: {blog.user?.name || 'Unknown' }</li>
<li> URL: {blog.url}</li>
<li>
{likes} likes&nbsp;

View File

@@ -0,0 +1,88 @@
import React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Blog } from './Blog'
import { BlogForm } from './BlogForm'
const testSubject = {
blog: {
id: '62e5309ba56f29d013ebe184',
author: 'Andrew Trieu',
title: 'How to be a good programmer',
url: 'https://lmgtfy.app/',
likes: 10000000,
user: {
username: 'andyyyyy',
name: 'Andrew Trieu',
},
},
}
describe('test for blogs', () => {
test('blog\'s title and author is rendered, but not url or likes', () => {
const { container } = render(
<Blog blog={testSubject.blog}/>
)
const div = container.querySelector('.blog')
expect(div).toHaveTextContent('How to be a good programmer by Andrew Trieu')
})
test('blog\'s url and likes are rendered when button is clicked', async () => {
render(<Blog blog={testSubject.blog}/>)
const user = userEvent.setup()
const button = screen.getByText('How to be a good programmer by Andrew Trieu')
await user.click(button)
const url = screen.getByText('https://lmgtfy.app/')
expect(url).toBeDefined()
const likes = screen.getByText('10000000')
expect(likes).toBeDefined()
})
test('clicking the like button twice calls event handler twice', async () => {
// Blog does not have updateBlog function
const mockHandler = jest.fn()
render(<Blog blog={testSubject.blog}/>)
const user = userEvent.setup()
const button = screen.getByText('How to be a good programmer by Andrew Trieu')
await user.click(button)
const likeButton = screen.getByText('+')
await user.click(likeButton)
await user.click(likeButton)
// 3 times because the blog is viewed once and the like button is clicked twice
expect(mockHandler.mock.calls).toHaveLength(3)
})
test('new blog form calls event handler with correct details', async () => {
const createBlog = jest.fn()
const component = render(
<BlogForm createBlog={createBlog}/>
)
const user = userEvent.setup()
const title = component.container.getElementsByName('title')
const author = component.container.getElementsByName('author')
const url = component.container.getElementsByName('urlAddress')
const form = component.container.getElementsByName('form')
await user.type(title, 'How to be a good programmer')
await user.type(author, 'Andrew Trieu')
await user.type(url, 'https://lmgtfy.app/')
await user.submit(form)
expect(createBlog.mock.calls).toHaveLength(1)
expect(createBlog.mock.calls[0][0].title).toBe('How to be a good programmer')
expect(createBlog.mock.calls[0][0].author).toBe('Andrew Trieu')
expect(createBlog.mock.calls[0][0].url).toBe('https://lmgtfy.app/')
})
})

View File

@@ -24,7 +24,7 @@ export const BlogForm = ({ createBlog }) => {
return (
<div>
<h2> Create new blog</h2>
<form onSubmit={addBlog}>
<form onSubmit={addBlog} name='form'>
<div>
Title:
<input

View File

@@ -1,5 +1,5 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import App from './App.js'
ReactDOM.createRoot(document.getElementById('root')).render(<App />)