Building a Component the Redwood Way
What's our blog missing? Comments. Let's add a simple comment engine so people can leave their completely rational, well-reasoned comments on our blog posts. It's the internet, what could go wrong?
There are two main features we need to build:
- Comment form and creation
- Comment retrieval and display
Which order we build them in is up to us. To ease into things, let's start with the fetching and displaying comments first and then we'll move on to more complex work of adding a form and service to create a new comment. Of course, this is Redwood, so even forms and services aren't that complex!
#
StorybookLet's create a component for the display of a single comment. First up, the generator:
Storybook should refresh and our "Generated" Comment story will be ready to go:
Let's think about what we want to ask users for and then display in a comment. How about just their name and the content of the comment itself? And we'll throw in the date/time it was created. Let's update the Comment component to accept a comment
object with those three properties:
Once you save that file and Storybook reloads you'll see it blow up:
We need to update the story to include that comment object and pass it as a prop:
Note that Datetimes will come from GraphQL in ISO8601 format so we need to return one in that format here.
Storybook will reload and be much happier:
Let's add a little bit of styling and date conversion to get this Comment component looking like a nice, completed design element:
Our component looks great! Now let's verify that it does what we want it to do with a test.
#
TestingWe don't want Santa to skip our house so let's test our Comment component. We could test that the author's name and the body of the comment appear, as well as the date it was posted.
The default test that comes with a generated component just makes sure that no errors are thrown, which is the least we could ask of our components!
Let's add a sample comment to the test and check that the various parts are being rendered:
Here we're testing for both elements of the output createdAt
timestamp: the actual text that's output (similar to how we tested for an article's truncated body) but also that the element that wraps that text is a <time>
tag and that it contains a datetime
attribute with the raw value of comment.createdAt
. This might seem like overkill but the point of the datetime
attribute is to provide a machine-readable timestamp that the browser could (theoretically) hook into and do stuff with. This makes sure that we preserve that ability.
What happens if we change the formatted output of the timestamp? Wouldn't we have to change the test?
Yes, just like we'd have to change the truncation text if we changed the length of the truncation. One alternative approach to testing for the formatted output could be to move the date formatting formula into a function that you can export from the
Comment
component. Then you can import that in your test and use it to check the formatted output. Now if you change the formula the test keeps passing because it's sharing the function withComment
.