Continuing the tutorial.
This commit is contained in:
@@ -21,8 +21,10 @@ const Routes = () => {
|
||||
<Route path="/posts" page={PostPostsPage} name="posts" />
|
||||
</Set>
|
||||
<Set wrap={BlogLayout}>
|
||||
<Route path="/article/{id:Int}" page={ArticlePage} name="article" />
|
||||
<Route path="/about" page={AboutPage} name="about" />
|
||||
<Route path="/" page={HomePage} name="home" />
|
||||
<Route path="/contact" page={ContactPage} name="contact" />
|
||||
</Set>
|
||||
<Route notfound page={NotFoundPage} />
|
||||
</Router>
|
||||
|
||||
17
web/src/components/Article/Article.js
Normal file
17
web/src/components/Article/Article.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Link, routes } from '@redwoodjs/router';
|
||||
|
||||
const Article = ({article}) => {
|
||||
return (
|
||||
<article>
|
||||
<header>
|
||||
<h2>
|
||||
<Link to={routes.article({ id: article.id })}>{article.title}</Link>
|
||||
</h2>
|
||||
</header>
|
||||
<div>{article.body}</div>
|
||||
<div>Posted at: {article.createdAt}</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
export default Article
|
||||
7
web/src/components/Article/Article.stories.js
Normal file
7
web/src/components/Article/Article.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import Article from './Article'
|
||||
|
||||
export const generated = () => {
|
||||
return <Article />
|
||||
}
|
||||
|
||||
export default { title: 'Components/Article' }
|
||||
14
web/src/components/Article/Article.test.js
Normal file
14
web/src/components/Article/Article.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import Article from './Article'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-components
|
||||
|
||||
describe('Article', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<Article />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
24
web/src/components/ArticleCell/ArticleCell.js
Normal file
24
web/src/components/ArticleCell/ArticleCell.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import Article from 'src/components/Article';
|
||||
|
||||
export const QUERY = gql`
|
||||
query FindArticleQuery($id: Int!) {
|
||||
article: post(id: $id) {
|
||||
id
|
||||
title
|
||||
body
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const Loading = () => <div>Loading...</div>
|
||||
|
||||
export const Empty = () => <div>Empty</div>
|
||||
|
||||
export const Failure = ({ error }) => (
|
||||
<div style={{ color: 'red' }}>Error: {error.message}</div>
|
||||
)
|
||||
|
||||
export const Success = ({ article }) => {
|
||||
return <Article article={article} />
|
||||
}
|
||||
6
web/src/components/ArticleCell/ArticleCell.mock.js
Normal file
6
web/src/components/ArticleCell/ArticleCell.mock.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Define your own mock data here:
|
||||
export const standard = () => ({
|
||||
article: {
|
||||
id: 42,
|
||||
},
|
||||
})
|
||||
20
web/src/components/ArticleCell/ArticleCell.stories.js
Normal file
20
web/src/components/ArticleCell/ArticleCell.stories.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Loading, Empty, Failure, Success } from './ArticleCell'
|
||||
import { standard } from './ArticleCell.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/ArticleCell' }
|
||||
41
web/src/components/ArticleCell/ArticleCell.test.js
Normal file
41
web/src/components/ArticleCell/ArticleCell.test.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
import { Loading, Empty, Failure, Success } from './ArticleCell'
|
||||
import { standard } from './ArticleCell.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('ArticleCell', () => {
|
||||
it('renders Loading successfully', () => {
|
||||
expect(() => {
|
||||
render(<Loading />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('renders Empty successfully', async () => {
|
||||
expect(() => {
|
||||
render(<Empty />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
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 () => {
|
||||
expect(() => {
|
||||
render(<Success article={standard().article} />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -1,3 +1,5 @@
|
||||
import Article from 'src/components/Article';
|
||||
|
||||
export const QUERY = gql`
|
||||
query ArticlesQuery {
|
||||
articles: posts {
|
||||
@@ -19,16 +21,10 @@ export const Failure = ({ error }) => (
|
||||
|
||||
export const Success = ({ articles }) => {
|
||||
return (
|
||||
<ul>
|
||||
<>
|
||||
{articles.map((article) => (
|
||||
<article key={article.id}>
|
||||
<header>
|
||||
<h2>{article.title}</h2>
|
||||
</header>
|
||||
<p>{article.body}</p>
|
||||
<div>Created at: {article.createdAt}</div>
|
||||
</article>
|
||||
<Article key={article.id} article={article} />
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
Label,
|
||||
TextField,
|
||||
Submit,
|
||||
TextAreaField
|
||||
} from '@redwoodjs/forms'
|
||||
|
||||
const PostForm = (props) => {
|
||||
@@ -48,7 +49,7 @@ const PostForm = (props) => {
|
||||
Body
|
||||
</Label>
|
||||
|
||||
<TextField
|
||||
<TextAreaField
|
||||
name="body"
|
||||
defaultValue={props.post?.body}
|
||||
className="rw-input"
|
||||
|
||||
@@ -14,6 +14,9 @@ const BlogLayout = ({ children }) => {
|
||||
<li>
|
||||
<Link to={routes.about()}>About</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link to={routes.contact()}>Contact Us</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
@@ -15,7 +15,7 @@ const PostsLayout = ({ children }) => {
|
||||
<div className="rw-button-icon">+</div> New Post
|
||||
</Link>
|
||||
</header>
|
||||
<main className="rw-main">{children}</main>
|
||||
<main className="rw-main" style={{marginLeft: 'auto', marginRight: 'auto', width: '50%'}}>{children}</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
13
web/src/pages/ArticlePage/ArticlePage.js
Normal file
13
web/src/pages/ArticlePage/ArticlePage.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MetaTags } from '@redwoodjs/web'
|
||||
import ArticleCell from 'src/components/ArticleCell';
|
||||
|
||||
const ArticlePage = ({id}) => {
|
||||
return (
|
||||
<>
|
||||
<MetaTags title="Article" description="Article page" />
|
||||
<ArticleCell id={id} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ArticlePage
|
||||
7
web/src/pages/ArticlePage/ArticlePage.stories.js
Normal file
7
web/src/pages/ArticlePage/ArticlePage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import ArticlePage from './ArticlePage'
|
||||
|
||||
export const generated = () => {
|
||||
return <ArticlePage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/ArticlePage' }
|
||||
14
web/src/pages/ArticlePage/ArticlePage.test.js
Normal file
14
web/src/pages/ArticlePage/ArticlePage.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import ArticlePage from './ArticlePage'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('ArticlePage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<ArticlePage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
24
web/src/pages/ContactPage/ContactPage.js
Normal file
24
web/src/pages/ContactPage/ContactPage.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { MetaTags } from '@redwoodjs/web'
|
||||
import { Form, TextField, Submit, TextAreaField } from '@redwoodjs/forms'
|
||||
|
||||
const ContactPage = () => {
|
||||
const onSubmit = (data) => {
|
||||
console.log(data)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<MetaTags title="Contact" description="Contact page" />
|
||||
<Form onSubmit={onSubmit}>
|
||||
<label htmlFor="name">Name</label>
|
||||
<TextField name="name" validation={{required: true}} />
|
||||
<label htmlFor="email">Email</label>
|
||||
<TextField name="email" validation={{required: true}} />
|
||||
<label htmlFor="message">Message</label>
|
||||
<TextAreaField name="message" validation={{required: true}} />
|
||||
<Submit>Save</Submit>
|
||||
</Form>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContactPage
|
||||
7
web/src/pages/ContactPage/ContactPage.stories.js
Normal file
7
web/src/pages/ContactPage/ContactPage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import ContactPage from './ContactPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <ContactPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/ContactPage' }
|
||||
14
web/src/pages/ContactPage/ContactPage.test.js
Normal file
14
web/src/pages/ContactPage/ContactPage.test.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import ContactPage from './ContactPage'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('ContactPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<ContactPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user