Chapter 6 - Adding Comments to Schema - Complete

This commit is contained in:
Colin Diem
2022-04-26 01:24:39 -04:00
parent e180c93ada
commit ac15c86840
15 changed files with 307 additions and 11 deletions

View File

@@ -1,4 +1,5 @@
import { Link, routes } from '@redwoodjs/router'
import CommentsCell from 'src/components/CommentsCell'
const truncate = (text, length) => {
return text.substring(0, length) + '...'
@@ -15,6 +16,11 @@ const Article = ({ article, summary = false }) => {
<div className="mt-2 text-gray-900 font-light">
{summary ? truncate(article.body, 100) : article.body}
</div>
{!summary && (
<div className="mt-12">
<CommentsCell />
</div>
)}
</article>
)
}

View File

@@ -10,7 +10,7 @@ export const full = () => {
return <Article article={ARTICLE} />
}
export const summart = () => {
export const summary = () => {
return <Article article={ARTICLE} summary={true} />
}

View File

@@ -1,4 +1,5 @@
import { render, screen } from '@redwoodjs/testing'
import { render, screen, waitFor } from '@redwoodjs/testing'
import { standard } from 'src/components/CommentsCell/CommentsCell.mock'
import Article from './Article'
@@ -17,6 +18,15 @@ describe('Article', () => {
expect(screen.getByText(ARTICLE.body)).toBeInTheDocument()
})
it('renders comments when displaying a full blog post', async () => {
const comment = standard().comments[0]
render(<Article article={ARTICLE} />)
await waitFor(() =>
expect(screen.getByText(comment.body)).toBeInTheDocument()
)
})
it('renders a summary of a blog post', () => {
render(<Article article={ARTICLE} summary={true} />)
@@ -27,4 +37,13 @@ describe('Article', () => {
)
).toBeInTheDocument()
})
it('does not render comments when displaying a summary', async () => {
const comment = standard().comments[0]
render(<Article article={ARTICLE} summary={true} />)
await waitFor(() =>
expect(screen.queryByText(comment.body)).not.toBeInTheDocument()
)
})
})

View File

@@ -10,7 +10,7 @@ const Comment = ({ comment }) => {
<header className="flex justify-between">
<h2 className="font-semibold text-gray-700">{comment.name}</h2>
<time className="text-xs text-gray-500" dateTime={comment.createdAt}>
{comment.createdAt}
{formattedDate(comment.createdAt)}
</time>
</header>
<p className="text-sm mt-2">{comment.body}</p>

View File

@@ -1,4 +1,4 @@
import { render } from '@redwoodjs/testing/web'
import { render, screen } from '@redwoodjs/testing/web'
import Comment from './Comment'
@@ -7,8 +7,17 @@ import Comment from './Comment'
describe('Comment', () => {
it('renders successfully', () => {
expect(() => {
render(<Comment />)
}).not.toThrow()
const comment = {
name: 'John Doe',
body: 'This is my comment',
createdAt: '2020-01-02T12:34:56Z',
}
render(<Comment comment={comment} />)
expect(screen.getByText(comment.name)).toBeInTheDocument()
expect(screen.getByText(comment.body)).toBeInTheDocument()
const dateExpect = screen.getByText('2 January 2020')
expect(dateExpect).toBeInTheDocument()
expect(dateExpect.nodeName).toEqual('TIME')
expect(dateExpect).toHaveAttribute('datetime', comment.createdAt)
})
})

View File

@@ -0,0 +1,32 @@
import Comment from 'src/components/Comment'
export const QUERY = gql`
query CommentsQuery {
comments {
id
name
body
createdAt
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => (
<div className="text-center text-gray-500">No comments yet</div>
)
export const Failure = ({ error }) => (
<div style={{ color: 'red' }}>Error: {error.message}</div>
)
export const Success = ({ comments }) => {
return (
<div className="space-y-8">
{comments.map((comment) => (
// eslint-disable-next-line prettier/prettier
<Comment key={comment.id} comment={comment} />
))}
</div>
)
}

View File

@@ -0,0 +1,17 @@
// Define your own mock data here:
export const standard = () => ({
comments: [
{
id: 1,
name: 'Rob Cameron',
body: 'First comment',
createdAt: '2020-01-02T12:34:56Z',
},
{
id: 2,
name: 'David Price',
body: 'Second comment',
createdAt: '2020-02-03T23:00:00Z',
},
],
})

View File

@@ -0,0 +1,20 @@
import { Loading, Empty, Failure, Success } from './CommentsCell'
import { standard } from './CommentsCell.mock'
export const loading = () => {
return Loading ? <Loading /> : null
}
export const empty = () => {
return Empty ? <Empty /> : null
}
export const failure = () => {
return Failure ? <Failure error={new Error('Oh no')} /> : null
}
export const success = () => {
return Success ? <Success {...standard()} /> : null
}
export default { title: 'Cells/CommentsCell' }

View File

@@ -0,0 +1,43 @@
import { render, screen } from '@redwoodjs/testing/web'
import { Loading, Empty, Failure, Success } from './CommentsCell'
import { standard } from './CommentsCell.mock'
// Generated boilerplate tests do not account for all circumstances
// and can fail without adjustments, e.g. Float and DateTime types.
// Please refer to the RedwoodJS Testing Docs:
// https://redwoodjs.com/docs/testing#testing-cells
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
describe('CommentsCell', () => {
it('renders Loading successfully', () => {
expect(() => {
render(<Loading />)
}).not.toThrow()
})
it('renders Empty successfully', async () => {
render(<Empty />)
expect(screen.getByText('No comments yet')).toBeInTheDocument()
})
it('renders Failure successfully', async () => {
expect(() => {
render(<Failure error={new Error('Oh no')} />)
}).not.toThrow()
})
// When you're ready to test the actual output of your component render
// you could test that, for example, certain text is present:
//
// 1. import { screen } from '@redwoodjs/testing/web'
// 2. Add test: expect(screen.getByText('Hello, world')).toBeInTheDocument()
it('renders Success successfully', async () => {
const comments = standard().comments
render(<Success comments={comments} />)
comments.forEach((comment) => {
expect(screen.getByText(comment.body)).toBeInTheDocument()
})
})
})