Show the Answer and Submit Button
Tags: react, typescript, testing, tutorial
Published: 2020-01-17 04:42:45

In this post we will:

* Make the `Answer` component that gets the current card from `CardContext`, keeps the answer hidden until it is told to show the answer, and shows the answer to the user when they are ready
* Make clicking the `Submit` button show the answer

In this post we will make clicking the `Submit` button show the answer to the user. In the next post we will move the `Submit` button into a new component called `Buttons`. `Buttons` will show the `Submit` button. After the user clicks `Submit` `Buttons` will show two buttons labeled `Right` and `Wrong`. Clicking `Right` or `Wrong` will let the user record if they got the answer right or wrong. 

#The Answer Component
In the last post we made the `Answering` scene. The `Answering` scene is where the user answers questions from the cards. It shows the user the question from the current card and gives them a box to type their answer in. The `Answer` component will appear on screen as a box that shows the answer after the user is done trying to answer the card.

Now we will make the `Answer` component that shows the answer to the current card. `Answer` will be hidden until after the user clicks the `Submit` button. We will put the `Answer` component inside the `Answering` scene. That way the user will see it when they need to.

##User Story
* The user sees a question displayed on the screen. The user writes an answer to the question. When the user is done with their answer, they click the `Submit` button. The app shows them the answer from the current card. The user compares their answer to the answer from the current card. The user decides they got the question right, and clicks the `Right Answer` button. Then the user sees the next question.

##Features
* a component that shows the answer to the user
* the answer is hidden and doesn't show up on the screen
* clicking Submit button shows answer

##Choose Components
We want to show the answer to the user when they are ready to see it. That means sometimes the answer will be hidden, but sometimes it will be shown. We'll use a [Transition](https://react.semantic-ui.com/modules/transition/) component to hide the answer and animate the answer when it appears. 

`Transition` takes a prop `visible` that tells it to show up or not. `visible` is boolean. It is either *true* or *false*. When `visible` is *true*, the `Transition` will show its contents. When `visible` is *false*, the `Transition` will hide its contents. When `visible` changes from *true* to *false* or from *false* to *true*, `Transition` will run an animation.

`Transition` needs its contents to be wrapped with a `div`. If the contents are not inside a `div` the `Transition` won't work right. So we'll put a div inside `Transition`. We'll put the the answer from the card inside the div so the user can see it.  

We'll put a `Header` inside the `div` too. A `Header` is a component that contains enlarged text that is used to label things. This `Header` will say 'Answer' so the user knows that they are seeing the answer. 

##Decide What to Test 
When you decide what to test, ask yourself "What does this component do? What part of that matters to the user?" I decided that there are four things we need to test in this component.

* when visible, it shows the answer
* shows the right answer (the answer from the current card, not some other card)
* has a header with 'Answer' in it so the user knows they are looking at the answer
* if it isn't visible, the answer doesn't show up on the screen

##Test 1: `Answer` Renders Without Crashing
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-1.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-1.tsx)

A lot of the time, when people do TDD the first test they write for a component is a test to see if it will render without crashing. We won't always start with a test that basic. But for the `Answer` component we will start with this basic test.

Make the necessary imports. We are importing `CardProvider` and the `initialState` object from `CardContext`. `Answer` will need access to the cards in `CardContext` so `Answer` can show the answer to the user. To get access to the `CardContext`, `Answer` must be inside the `CardProvider` component that is exported from the `CardContext` file.

We are importing the `CardProvider` to this test file because in the tests we will render `Answer` inside of the `CardProvider`. We render `Answer` inside of the `CardProvider` so that `Answer` can access the cards in `CardContext`. That way we can be confident that our tests actually show us how `Answer` will work when we use it in the app.

```javascript
import React from 'react';
import { render, cleanup } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { CardProvider, initialState } from '../../../../services/CardContext';
import Answer from './index';

afterEach(cleanup);
```
###Write the Helper Function renderAnswer
To test `Answer` we need to use the `render` method from React Testing Library. We need to render `Answer` inside of the `CardProvider` so that `Answer` can access the cards from `CardContext`. We will write the helper function `renderAnswer` to use the `render` method from React Testing Library to render `Answer` inside of the `CardProvider`. Writing `renderAnswer` means that we can call `renderAnswer` in each of our tests instead of rewriting the code in each test.

`renderAnswer` takes an optional boolean parameter `visible`. Optional means that we don't have to pass an argument for `visible`. `renderAnswer` will work fine without it. But if `visible` is defined, it will be passed to `Answer` as the value of `Answer`'s prop named visible. 

If the parameter `visible` is not defined, we will pass *true* to `Answer` as the value of the prop named visible. So when we call `renderAnswer()` without an argument, it will render a visible answer. If we do want to render a hidden answer, we will call `renderAnswer(false)`.

```javascript
//the ?: after visible tells typescript that it is optional
const renderAnswer = (visible?: boolean) => render(
  <CardProvider>
    <Answer visible={visible !== undefined ? visible : true}/>
  </CardProvider>
);
```

Write the test 'renders without crashing.' To test that `Answer` renders without crashing, call `renderAnswer`.

```javascript
it('renders without crashing', () => {
    renderAnswer();
});
```

It does not render without crashing.

![Answer fails to render](https://thepracticaldev.s3.amazonaws.com/i/1j2py6iyl2skpu9jr561.png)

##Pass Test 1: `Answer` Renders Without Crashing
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-1.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-1.tsx)

We'll render a div to pass the first test. One of the rules of test driven development is that you are only allowed to write the minimum amount of code required to pass the test. We don't always strictly follow that rule in this tutorial. But in this step we do. This is a minimal amount of code for a React component! It is a functional component that returns a div.

```javascript
import React from 'react';

const Answer = () => <div/>

export default Answer;
```
Now it renders without crashing!
![Renders](https://thepracticaldev.s3.amazonaws.com/i/u948flb59xsfq8p66ima.png)

##Test 2: Answer Has a Div that Will Show the Answer
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-2.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-2.tsx)

`Answer` will take a boolean prop `visible`. Let's test to make sure that when it is visible, it shows the answer. Remember, our helper component passes *true* as the value of the prop `visible` unless we tell it to do something else.

Let's put the three tests of the visible `Answer` inside a [describe()](https://jestjs.io/docs/en/api#describename-fn) block. describe() is a method that Jest provides so that you can organize your tests. You will see when you run these tests that Jest shows you the three tests under the name of the describe block.

Make a describe block named 'when visible, it shows the answer.' Write a comment for each of the tests we'll write inside the describe block.

```javascript
describe('when visible, it shows the answer', () => {
    //has the div that will show the answer
    
    // has a header with 'Answer'
    
    // shows the right answer
 });
```

When `Answer` is visible, `Answer` shows the div that will hold the answer:

```javascript
describe('when visible, it shows the answer', () => {
    //has the div that will show the answer
    it('has the answer div', () => {
        const { getByTestId } = renderAnswer();
        const answerDiv = getByTestId('answer')
        expect(answerDiv).toBeInTheDocument();
      });

    // shows the right answer

    // has a header with 'Answer'
    
 });
```
![Fails, no answer div](https://thepracticaldev.s3.amazonaws.com/i/ukvzcxwexf5t9puzcapq.png)

##Pass Test 2: Answer Has Div that Will Show the Answer
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-2.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-2.tsx)

Add the testId 'answer' to the div.

```javascript
const Answer = () => <div data-testid='answer'/>
``` 

##Test 3: Answer Div Shows the Right Answer 
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-3.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-3.tsx)

The most important feature of `Answer` is that it shows the right answer to the user. 

We want to test that the div that has the `Header` and the answer from the current card is actually showing the right answer to the user. We find the div by searching for its testId 'answer.' We find the current card by getting the current index from the `initialState` object that we imported from `CardContext`. Then we look at the current index in the array cards in `initialState`. We will compare the contents of the div to the answer from the current card.

```javascript
      // shows the right answer
    it('displays the right answer', () => {
        const { getByTestId } = renderAnswer();
        //find the answer div
        const answer = getByTestId('answer');
        //get the textContent
        const text = answer.textContent;
        
        //this is the answer from the card at index current in cards
        const initialAnswer = initialState.cards[initialState.current].answer;
        
        //expect the rendered text in the div 
        //to equal the answer from initial state, 
        expect(text).toEqual(initialAnswer); 
    });  
```

![Does Not Show Correct Answer](https://thepracticaldev.s3.amazonaws.com/i/1bf86s8u2c10euvizzum.png)

##Pass Test 3: Answer Div Shows the Right Answer
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-3.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-3.tsx)

Import `useContext` from React. `useContext` is the React Hook that lets you get values from a context.  Import `CardContext` from the CardContext file. `CardContext` is the context that we made. `CardContext` has the cards and the current index in it.

```javascript
import React, { useContext } from 'react';
import { CardContext } from '../../../../services/CardContext';
```
We call `useContext()` and pass it the `CardContext`. `useContext` will return the current value of the `CardState` inside `CardContext`. 

We use Object Destructuring to get the `cards` array and the `current` index out of `CardContext`. 

We use Object Destructuring again to get the `answer` out of the card at the current index in `cards`.

Return the `answer` inside of the answer div.

```javascript
const Answer = () => {
    const { cards, current } = useContext(CardContext);
    const { answer } = cards[current];

    return <div data-testid='answer'>{answer}</div>
};
```

![Passes Showing Correct Answer](https://thepracticaldev.s3.amazonaws.com/i/xsvu4sq7l1h701atsu5l.png)

##Test 4: Header 
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-4.tsx]
(https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-4.tsx)

We are going to add a `Header` with the word 'Answer' in it. Because we know what text will be inside the header, we can use the `getByText` query to find it instead of assigning a `testId`. See how we have passed '/answer/i' to `getByText`? That is a **regular expression, or regEx**. Regular Expressions are a powerful tool for searching and manipulating text. Regular expressions can get pretty complicated. This one just matches the text 'answer' and the /i means it is case insensitive.

####Write Your Tests to Find the Important Things
We use a case insensitive regEx because even though we decided it's important for the text 'Answer' to show up, we don't think that the capitalization is important. So we don't test for capitalization. Using a case insensitive regEx means that no matter how you capitalize the word 'Answer' in the `Header`, it will still pass the test. If capitalization was important, you could change the regEx or search for a string instead.

```javascript
// has a header with 'Answer' 
    it('has the answer header', () => {
        const { getByText } = renderAnswer();
        const header = getByText(/answer/i);
        expect(header).toBeInTheDocument();
    });
    
```
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ls5zesnognz1s066t5qf.png)


##Pass Test 4: Header
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-4.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-4.tsx)

Import the `Header` component from Semantic UI React.

```javascript
import { Header } from 'semantic-ui-react';
```

Rewrite the returned component. Add the `Header` to it. `as='h3'` tells the `Header` how large it should be. h1 is the biggest header size, h2 is a little smaller, and h3 is smaller than h2. `content` is the text that shows up inside the `Header`.
 
```javascript
    return (
        <div data-testid='answer'>
            <Header as='h3' content ='Answer'/>
            {answer}
        </div>
    )};
```

Passes the header test. But the test for the right answer fails!

![Header Pass, answer fails](https://thepracticaldev.s3.amazonaws.com/i/tukx0wepv8g8icw75473.png)

###What's Going On?
Look at the error that Jest is showing us. The div still has the answer text in it. But now it also has a `Header` component. Inside the `Header` is the string 'Answer.' Jest is finding the `textContent` of the `Header` and the `textContent` of the div, not just the `textContent` of the div. The result is right but the test is failing. So we need to change the test. To get the test to pass we need to change the way we test for the right answer.  

##Answer: Change Test Named 'displays the right answer'
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-5.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-5.tsx)

This is an example of the type of problem that comes up a lot when you are testing. You wrote the test the way you thought you needed. Then you wrote the code to do what you want. Now the code does what you want, but the test is failing. Once you look at your code and you are sure that the code is working, then you know that you need to change the test to fit the code.

What's making this test fail is that it is finding the div with the testId 'answer' and looking at all of the textContent inside of that div. The 'answer' div has the `Header` in it, so the textContent of the 'answer' div includes the string 'Answer' from the header as well as the answer from the current card. 

Here is what gets rendered inside the div with the testId 'answer.' To see this, you can scroll up when a test fails. You can also get the `debug` method from the call to render or your helper component, and call `debug()`. 
 
![The Answer div](https://thepracticaldev.s3.amazonaws.com/i/n7vyu9npp3kcy3oyrkee.png)

You can also use `console.log()` to see the `textContent` of the `answer` div.

```javascript
console.log(answer.textContent)
``` 
![Console log answer.textContent](https://thepracticaldev.s3.amazonaws.com/i/r993a34xskceenddozml.png)



So we make a const `fullAnswer` by adding the string 'Answer' to the `initialAnswer`. Then expect the textContent of the div to match `fullAnswer`.

```javascript
//...rest the test above
        const initialAnswer = initialState.cards[initialState.current].answer;
        
        //Answer header is in the div
        //add the string 'Answer' to initialAnswer
        const fullAnswer = 'Answer' + initialAnswer;
            
        //expect the rendered text in the div 
        //to equal the answer from initial state, 
        //plus the 'Answer' string from the header
        expect(text).toEqual(fullAnswer);  
    });
```

![Header and Answer pass](https://thepracticaldev.s3.amazonaws.com/i/zhbcrwgdta8g9d5ml8a3.png)


##Test 5: Answer is Invisible when Hidden
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-6.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-6.tsx)

This test is to make sure Answer doesn't show up when it is hidden. This test is outside of the describe block 'when visible, it shows the answer.'

We pass `false` to the helper function to tell it that we want Answer to be hidden. Then we use a query to search for the answer div by testId. But we aren't using `getByTestId`. We are using [queryByTestId()](https://jestjs.io/docs/en/setup-teardown#order-of-execution-of-describe-and-test-blocks), a new query that we haven't seen before.
 
####queryBy vs. getBy
The [getBy](https://testing-library.com/docs/dom-testing-library/api-queries#getby) queries will throw an error and fail the test if they don't find anything. That's normally good. But here we don't expect to find the testId. We expect that we won't find the testId because `Answer` shouldn't show up. `Answer` is hidden, so we expect that it won't show up on the page. So we use queryByTestId, because the [queryBy](https://testing-library.com/docs/dom-testing-library/api-queries#queryby) queries won't throw an error if they don't find anything. When a queryBy query doesn't find anything, it returns null without throwing an error. We set the variable `answer` equal to the result of the queryByTestId. We don't expect to find anything, so we expect our variable `answer` to be null.

[toBeNull()](https://jestjs.io/docs/en/expect#tobenull) is the assertion you use when you expect something to be null.

```javascript
 it('If not visible, it isnt visible', () => {
    const { queryByTestId } = renderAnswer(false);
    const answer = queryByTestId('answer');
    
    expect(answer).toBeNull();
});
```
![Invisible Fail](https://thepracticaldev.s3.amazonaws.com/i/hy7pxa6k4n5nm6qvy126.png)

##Pass Test 5: Answer is Invisible When Hidden
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-6.tsx]
(https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-6.tsx)
 
We import the `Transition` component from Semantic UI React. `Transition` takes a boolean prop called `visible`. `Transition` will show or hide its contents based on the value of `visible`. `Transition` will animate the appearance or disappearance of the contents when `visible` changes from *true* to *false* or from *false* to *true*. I find that Transition only works correctly when the contents are inside of a div. We will use the 'answer' div.

```javascript
import { Header, Transition } from 'semantic-ui-react';
```

Add a prop named visible to the Answer component. Use TypeScript to declare visible as type boolean. Wrap the div that Answer returns in the Transition component. Pass the visible prop to Transition.

####Transition Props
`animation='drop'` tells `Transition` what kind of animation to use. Semantic UI React has many types of animations that you can choose from. 

`duration={500}` tells `Transition` how long the animation should take.

`unmountOnHide` tells `Transition` to unmount the contents from the React component tree when the `Transition` is hidden. If you don't tell it to unmount on hide, the contents will stay in the component tree even when it is hidden and the user can't see it. This usually doesn't matter, but one of the tests in a later post won't pass unless we use `unmountOnHide`.

```javascript
const Answer = ({
    visible
}:{
    visible: boolean
}) => {
    const { cards, current } = useContext(CardContext);
    const { answer } = cards[current];

return (
    <Transition visible={visible} animation='drop' duration={500} unmountOnHide>
        <div data-testid='answer'>
            <Header as='h3' content ='Answer'/>
            {answer}
        </div>
    </Transition>
)};


export default Answer;
```
![Invisible Pass](https://thepracticaldev.s3.amazonaws.com/i/q1ldsmlocsw8krxk306f.png)


Great! It's passing all the tests. `Answer` works how we want it to. `Answer` is ready to be added to the `Answering` scene.

Read through the test file for `Answer`. Do you understand what features you are testing for? 

Read through the index file for `Answer`. Can you see some things that the component does that you aren't testing for?
 
#Add Answer to Answering
Now it is time to add `Answer` into the `Answering` scene. Once Answer is added, the answer will show up on screen so the user can see it.

##Features

* clicking the `Submit` button makes the answer to the question appear

##Choose Components
We will use the `Answer` component that we just made.

##Choose What to Test
Think about what you are going to need to test. You'll need to test that the `Submit` button controls the visibility of the Answer. And you'll want to test that the Answer shows the right answer.
* answer doesn't show up
* when `Submit` is clicked, answer shows up

##Answering Tests 1-2:
>File: src/scenes/Answering/index.test.tsx
>[Will Match: src/scenes/Answering/complete/test-10.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/complete/test-10.tsx)

In the `Answering` scene, `Answer` won't show up until the user clicks the `Submit` button. To test what happens when we click a button, we need to simulate clicking the button. RTL gives us the `fireEvent` method. `fireEvent` can be used to simulate clicks, mouseover, typing and other events. 

Import [fireEvent](https://testing-library.com/docs/dom-testing-library/api-events) from React Testing Library. You will simulate the click with fireEvent.click().

```javascript
import { render, cleanup, fireEvent } from '@testing-library/react';
```

Make a describe block near the bottom of the test file, but above the snapshot test. Name the describe block 'submit button controls display of the answer.' Write a comment for each test we are about to write.

```javascript
describe('submit button controls display of the answer', () => {
    //answer does not show up
    //clicking the submit button makes the answer show up
});
```

###Checking if the Answer Shows Up
For both of the tests we are going to write we will need to search for the text of the answer. Remember earlier, when we wrote the `Answer` component, we had to change our test to search for the string 'Answer' plus the answer after it? We had to do that because the div that shows the answer also has a header with the string 'Answer' in it. 

So now we know we could find the answer by doing the same thing we did in the tests for `Answer`. We could find the answer by putting the string 'Answer' in front of it and searching for that. But that is not the best way to do it. Why do you think that is not the best way to do it?

###Don't Test Features of Other Components
The reason the answer has extra text added to it is because of how the component `Answer` works. When we are testing the `Answering` scene, we don't care how the component `Answer` works. We don't care if it has a `Header`, or what's in the `Header`. Our test for `Answering` should not also be testing the other components inside it, like `Answer`. We don't want to test `Answer`. We only want to test `Answering`. We only really care about what the user sees and experiences. We only care if the user looking at `Answering` can see the answer when they should.

If our test for `Answering` looks for the correct answer the same way that the test in `Answer` looks for it, with the extra added string, then it will work at first. But what if we change `Answer`? What if we take the `Header` out of `Answer`? Then our tests for `Answering` would fail. But should those tests fail? The answer would still show up on the screen. `Answering` doesn't test for the `Header`. The `Header` being there or not shouldn't make `Answering` fail tests.

Let's use a different way to make sure that the text of the correct answer is showing up.

###Finding Text with a Custom Function
You have seen `queryByText` and `getByText`. You can use them to find an element by passing a string `('text goes here')`. You can also use them to find an element by passing a regular expression `(/text goes here/i)`. There is also a another way to find elements using these queries. You can find elements by writing a custom function and passing the custom function to the queries.

####Custom Functions for Queries
The queries look through the rendered component one element at a time. When you pass the query a function, the query will run that function on each element that it looks at. The query passes two arguments to the function. The first argument is the content of the element, which is a string. The second argument is the element itself. The function must return a boolean value, *true* or *false*.

A function for an RTL query has to be in this form: Accepts up to two parameters and returns a boolean value.

```javascript
(content : string, element: HTMLElement) => boolean
```

When the custom function returns *true*, the query will add that element to its results. Some queries only look for one element. Those queries will stop looking when they find the first element that returns *true*. Other queries look for an array of elements. Those queries will go through all the elements and add each one that returns *true* to the array of results.

###The Function to Find the Answer to the Current Question
Let's write the custom function that will find the element that contains the answer. We'll write this code inside the describe block, but before and outside the tests that we will write inside the describe block. That way, each test inside the describe block can use the function.

Get the answer to the current question from the `initialState`. Call it `initialAnswer`.

```javascript
   //the answer to the current question
    const initialAnswer = initialState.cards[initialState.current].answer;
```

####Removing LineBreaks
The `initialAnswer` is stored as a string literal. It may contain linebreaks. The linebreaks won't get rendered. So for the comparison to work, we need to remove any linebreaks from the `initialAnswer`. Let's create a variable called `withoutLineBreaks`, which is the `initialAnswer` without linebreaks. 

To make `withoutLineBreaks`, we'll use the [string.replace](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace) method. We'll use `string.replace` to replace any linebreaks with a space. The first argument passed to the `replace` method is a regular expression that identifies linebreaks. This regEx is more complicated than the regExs we have been using to find strings of text. But you should save that for later. Right now, all you need to know is that it will find the linebreaks so that we can replace them with a different value.

The second argument is what we are replacing linebreaks with, which is a space.

```javascript
    //remove linebreaks from initialAnswer for comparison to textContent of elements 
    const withoutLineBreaks = initialAnswer.replace(/\s{2,}/g, " ");
```

##What is going on in the RegEx?
####Short answer: 
You don't need to know! You can skip this section and come back later if you are curious.

####Long answer:
This function uses a regular expression `/\r\n|\r|\n/g` to identify linebreaks.  I got it from an answer on [StackOverflow](https://stackoverflow.com/questions/20056306/match-linebreaks-n-or-r-n). The answer to the StackOverflow question at this link explains that different operating systems will use different characters for linebreaks. Linux uses \n. Windows uses \r\n. Old Macs use \r. So this regEx looks for each of those.

####More than you want to know about lineBreaks:
[Newlines in JavaScript will always be 'linefeeds', or `\n`](https://stackoverflow.com/questions/49968130/line-endings-also-known-as-newlines-in-js-strings). So we could get the same effect just looking for `\n` instead of also looking for the other types of linebreaks. But the more complex regex will catch all linebreaks. So if we decided to later to store linebreaks in an answer in a different way, it would still work. I also decided to keep it as a good example of a slightly more complex regular expression.

####Copying and Pasting RegEx
Getting a regEx from the internet is great. You can often find a regular expression that someone else has written that does what you want. But as with all code that you copy and paste from the internet, if you don't understand it then you might make mistakes, use bad code, or use it incorrectly. 

An example of a problem with using copy pasted code without understanding it is that in the StackOverflow link above, the regEx is inside of parentheses: `/(\r\n|\r|\n)/g`. The parentheses are a [capturing group](https://www.rexegg.com/regex-capture.html), a way to group the results of the regEx. But I found out that the regEx inside the capture group split the array differently than I wanted in some of the tests that we use this regEx in, and made those tests fail. So I took the capturing group out. 

####Full Explanation of This RegEx 
For learning regex, I like the website www.rexegg.com and their [regEx cheatsheet] (https://www.rexegg.com/regex-quickstart.html). The website (https://regexr.com/) is a great tool for writing regular expressions. Here is a [link to this regular expression loaded into regexr](regexr.com/4s1vi). 

The pieces of this regex are:
`/` the regEx is inside of a pair of slashes. That tells the compiler that these are special characters, and it shouldn't read them the normal way. 
`|` the pipe character means 'or'.
`\r` matches a carriage return.
`\n` matches a line feed character.
`/g` is a 'flag' that means global search. This means that the regEx will find all possible matches in the string.

All together, the line `/\r\n|\r|\n/g` tells the compiler: this is a Regular Expression. Return a match when you find a carriage return followed by a linefeed, or a carriage return on its own, or a linefeed on its own. Find every match in the text.

####The Custom Function
Write a function that takes a string and compares it to the string `withoutLineBreaks`. This function will just look at the `textContent` string that it gets from the query. It won't do anything with the whole element, so we are not including a second parameter. That will work fine, the query doesn't need the function to accept both arguments. The query just needs the function to return a boolean value.

Now we can pass this function to queries and find any elements that contain the text of the `initialAnswer`.

```javascript
    const compareToInitialAnswer = (content: string) => content === withoutLineBreaks; 
```

####The Describe Block So Far
```javascript
describe('submit button controls display of the answer', () => {
    //the answer to the current question
    const initialAnswer = initialState.cards[initialState.current].answer;
    
    //remove lineBreaks from initialAnswer for comparison to textContent of elements 
    const withoutLineBreaks = initialAnswer.replace(/\s{2,}/g, " ");

    const compareToInitialAnswer = (content: string) => content === withoutLineBreaks;

    //answer does not show up
    //clicking the submit button makes the answer show up
});
```

##Answering Test 1: Answer Does Not Show Up Until Submit is Clicked

The first test checks that the answer does not show up before the submit button is clicked. Look how we are passing the `compareToInitialAnswer` function to `queryByText`. Do you know why we are using `queryByText` instead of `getByText`?

This test will pass because we haven't added `Answer` to `Answering` yet, so there is no way the answer will show up on screen. Once we do add `Answer`, it will give us confidence that `Answer` is working correctly and is not showing up before it should.

```javascript
//answer does not show up
it('the answer does not show up before the submit button is clicked', () => {
    const { queryByText } = renderAnswering();
    
    //use the custom function to search for the initial answer
    const answer = queryByText(compareToInitialAnswer);
    
    expect(answer).toBeNull();
});
```
##Answering Test 2: Clicking Submit Makes Answer Show Up

The second test shows that clicking the `Submit` button will make the answer show up. We use `getByText` to find the `Submit` button and `fireEvent.click()` to click it. Use the custom function `compareToInitialAnswer` to find the answer in the document.

```javascript
    //clicking the submit button makes the answer show up
it('clicks the submit button and shows the answer', () => {    
    const { getByText } = renderAnswering();
    
    //find the submit button
    const submit = getByText(/submit/i);
    //simulating a click on the submit button
    fireEvent.click(submit);
  
    //use a custom function to find the answer
    //the function returns true if content is equal to the initial answer withoutLineBreaks 
    const answer = getByText(compareToInitialAnswer);
    
    //assertion
    expect(answer).toBeInTheDocument();
  });
```

Tests done. Run them and make sure that your last test isn't passing. It should not pass because the answer should not show up yet.

![Button Does Not Control Answer](https://thepracticaldev.s3.amazonaws.com/i/iyc3nzneprcgz47zc00o.png)

##Pass Answering Tests 1-2
>File: src/scenes/Answering/index.tsx
>Will Match: [src/scenes/Answering/complete/index-8.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/complete/index-8.tsx)

To pass the tests we just wrote, we'll change Answering so the `Submit` button controls the visibility of `Answer`.

Import `useState` from React.
The [useState](https://reactjs.org/docs/hooks-state.html) hook holds a value and gives you a function to set the value to something else. We will use it to hold the value of `showAnswer`. `showAnswer` will be a boolean variable that determines whether we should show the answer or not.

```javascript
import React, { useContext, useState } from 'react';
```

Import the `Answer` component you just made.
```javascript
import Answer from './components/Answer';
```

Add the `useState` hook. `useState(startingValue)` returns an array with two values in it. 
```javascript
///the return value of useState
[ value, setValue ]
```

`value` is the value that useState currently holds. It starts as the starting value that was passed in to useState. 

`setValue` is a function that lets you change the value that useState currently holds.

In the code below, `const [showAnswer, setShowAnswer]` is the declaration of two const variables, `showAnswer` and `setShowAnswer`. Declaring a variable or variables by putting them in brackets with an object on the other side of an equals sign means you are using [Array Destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring). Array Destructuring is like Object Destructuring, except you are getting elements out of an array instead of properties out of an object. 

`showAnswer` is a boolean variable. So `showAnswer` will either be *true* or *false*. We pass `useState` a starting value of *false*. Because the starting value is boolean, TypeScript will assume that the value inside this `useState` always be boolean and that the function to set it will take a single argument with a boolean value. If we wanted something else, we could explicitly declare the type of the `useState` values. But we want it to be boolean, so we are letting TypeScript 'infer' the type. 'Infer' the type means TypeScript will figure out the type from the code. When TypeScript inference works, it is nice. When it doesn't do what you want, then you have to explicitly declare the type.

`setShowAnswer` is a function. It takes one argument. The argument that `setShowAnswer` takes is boolean. So you can only invoke `setShowAnswer` with *true* or *false*. After you invoke `setShowAnswer`, the value of `showAnswer` will be set to the value that you passed to `setShowAnswer`.

We will pass the function `setShowAnswer` to the `Submit` button. When the value of `showAnswer` changes, the answer will become visible.


```javascript
const Answering = () => {
    //get cards, current index and dispatch from CardContext
    const { cards, current, dispatch } = useContext(CardContext);

    //get the question from the current card
    const { question } = cards[current];

    const [showAnswer, setShowAnswer] = useState(false);

return (
```

Add an `onClick` function to the `Submit` button that calls `setShowAnswer(true)`. Add the `Answer` below the `Submit` button. Pass `showAnswer` as the value of `Answer`'s `visible` prop. 

Now clicking the `Submit` button will set the value of `showAnswer` to *true*. We are passing `showAnswer` to `Answer` as the value of the prop `visible.` So when we set `showAnswer` to *true*, we are making `Answer` visible. 

```javascript
</Form>
        <Button onClick={() => setShowAnswer(true)}>Submit</Button>
        <Answer visible={showAnswer}/>
    </Container>
```

![Tests Pass](https://thepracticaldev.s3.amazonaws.com/i/0fe07g4w4naqbir4u0wr.png)

Run the app. The answer is not there. Click `Submit` and the answer will show up!

![Click submit and the answer shows up](https://thepracticaldev.s3.amazonaws.com/i/tmmcg9nhhqb4wwy1jf4m.png)


#Show Linebreaks In the Answer
Ok, the answer shows up. But it's all on one line. Let's change `Answer` so that it respects the linebreaks stored in the template literal. 

##Answer: Change the Test Named 'displays the right answer' so it Looks for Multiple Lines
>File: src/scenes/Answering/components/Answer/index.test.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/test-7.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/test-7.tsx)

We are going to rewrite the test named 'displays the right answer'. To make sure that we are testing for an answer that has linebreaks, we are going to make a new `CardState` object called `testState`. We'll pass `testState` to the `CardProvider` instead of the default `initialState`. 

Import `CardState` from `types`.
```javascript
import { CardState } from '../../../../types';
```
We'll need to pass the `testState` to `CardProvider`. Make renderAnswer accept a second optional parameter, `testState`. Declare testState as a type `CardState`. Pass `testState` to `CardProvider` as a prop.

```javascript
const renderAnswer = (visible?: boolean, testState?: CardState) => render(
  <CardProvider testState={testState}>
    <Answer visible={visible !== undefined ? visible : true}/>
  </CardProvider>
);
```

Now we'll rewrite the 'displays the right answer' test.

Declare a const `testAnswer`. `testAnswer` is a template literal inside of backticks. That sounds complicated, but it just means that we can use linebreaks inside it.

Declare a const cards. Use the spread operator to make a new array from the array `initialState.cards`. 

Set the answer property of the object at `testAnswer.cards[0]` equal to `testAnswer`.

Declare a const `testState`. Use the spread operator to make a new object from the initialState. Overwrite the existing cards property with the array `cards`. Overwrite the existing current property with the number 0.

Then call `renderAnswer(true, testState)`. Remember, the first argument tells `renderAnswer` that `Answer` should be visible. The second argument is the `testState` object that we just made.

Use the `getByTestId` matcher to find the answer `div`.

We expect the answer div to contain a Header, and also to contain one other `div` for each line in the answer. The `testAnswer` has three lines in it, so we'll expect the answer `div` to contain four `divs` total.

You can look at the `children` property of an element to see how many other elements are inside it. The `children` property of an element is an array. So we will make assertions about the length of the `children` array and the contents of the `children` array.

The first element inside the answer `div` is the Header. So `answer.children[0]` is the header.

Every other element inside the answer `div` will be a div that contains a line of the answer. So `answer.children[1]` will be a div with the first line of `testAnswer`. `answer.children[2]` will be a div with the second line of `testAnswer.`

`testAnswer` is a string. We can't tell what each line is. We need an array with each line of `testAnswer`. Use `String.split()` to split the string into an array of strings. Pass the regular expression `/\n/g` to `String.split()` to split the string at every linebreak.
 
Then we expect that the textContent of each child of the element matches one of the lines in the answer.

```javascript
    // shows the right answer
        // shows the right answer
    it('displays the right answer', () => {
      //testAnswer is a template literal with linebreaks
      const testAnswer = `This has linebreaks
        Here's the second line
        and the third line`;

        //create a new array using initialState.cards
        const cards = [...initialState.cards];
        //set the answer of the card at index 0 = to testAnswer
        cards[0].answer = testAnswer;

        //create a new CardState with cards, set current to 0
        const testState = {
          ...initialState,
          cards,
          current: 0
        };

        //call renderAnswer with visible = true, testState
        const { getByTestId } = renderAnswer(true, testState);

        //find the answer div
        const answer = getByTestId('answer');

        //the answer div should have 4 children
        //one child is the Header
        //plus three more child divs, one for each line in testAnswer
        expect(answer.children).toHaveLength(4);

        //use Array.split to split testAnswer into an array
        //the regular expression /\n/g identifies all the linebreaks
        const testAnswerArray = testAnswer.split(/\n/g);

        const firstLine = answer.children[1];
        const secondLine = answer.children[2];
        const thirdLine = answer.children[3];

        expect(firstLine.textContent).toEqual(testAnswerArray[0]);
        expect(secondLine.textContent).toEqual(testAnswerArray[1]);
        expect(thirdLine.textContent).toEqual(testAnswerArray[2]);
    });  
```

####toEqual instead of toHaveTextContent
Notice that we do not expect `firstLine` `toHaveTextContent` of the line from the answer. Instead we expect `firstLine.textContent` `toEqual` the line from the answer. The reason to access the textContent of the element and use `toEqual` instead using the whole element and using `toHaveTextContent` is because of the way `toHaveTextContent` works. 

When you pass a string to `toHaveTextContent` it will compare that string to the textContent of the element. It looks for a partial match. It doesn't tell you that it is an exact match. So `toHaveTextContent('apple')` tells you that the element text contains the string 'apple.' It doesn't tell you that the element text matches the string 'apple.' It would match whether the textContent was 'apple,' 'apples and oranges,' or 'apples, oranges, and pears.' 

We want this test to show us that the textContent of each div exactly matches that line of the answer. `toEqual` tells us that the text content is actually equal to the the string in the answer array, without any extra text.

####Optional Experiment to Compare toEqual and toHaveTextContent
You can use the [string.slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice) method to cut off part of the answer string and see that toHaveTextContent still matches. If you are curious about this, try adding these lines to your test.

The code
```javascript
testAnswerArray[0].slice(0, testAnswerArray[0].length - 7)
```
Creates a new string that is the first string in `testAnswerArray` with the last seven characters cut off.

This will still pass: 
```javascript
        expect(firstLine).toHaveTextContent(testAnswerArray[0].slice(0, testAnswerArray[0].length - 7));
```

While `toEqual` won't:
```javascript
        expect(firstLine.textContent).toEqual(testAnswerArray[0].slice(0, testAnswerArray[0].length - 7));
```

This test works. But it only tests one answer. It tests an answer with linebreaks. Do you feel like it tests enough that you are certain the app will work? There's no right answer. That's something you'll decide when you develop your own apps.

How would you test to make sure the component correctly displays an answer without any linebreaks? Or an answer with five lines?

##Rewrite the Answer Component to Show Multiple Lines
>File: src/scenes/Answering/components/Answer/index.tsx
>Will Match: [src/scenes/Answering/components/Answer/complete/index-7.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/components/Answer/complete/index-7.tsx)

We just rewrote the test 'displays the right answer' to expect that multiple lines will be displayed when the stored answer contains lineBreaks. To make the `Answer` component display multiple lines, we will first use the `String.split` method to make an array of strings from the `answer` string. Then we'll use the `Array.map` method to make that an array of React elements from the array of strings.

```javascript
const Answer = ({
    visible
}:{
    visible: boolean
}) => {
    const { cards, current } = useContext(CardContext);
    const { answer } = cards[current];

    const content = answer
        //use string.split and a regEx to split the string into an array
        .split(/\n/g)
        //use Array.map to make an array of div elements
        .map((string, index) => <div key={index}>{string}</div>);
        
return (
    <Transition visible={visible} animation='drop' duration={500} unmountOnHide>
        <div data-testid='answer'>
            <Header as='h3' content ='Answer'/>
            {content}
        </div>
    </Transition>
)};
```

When you run all the tests, the test in `Answering` named 'clicks the submit button and shows the answer' will fail.
 
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/8bnf7v6hirmwahmg0mog.png)

##Answering Test: Fix Test 'clicks the submit button and shows the answer'
>File: src/scenes/Answering/index.test.tsx
>[Will Match: src/scenes/Answering/complete/test-11.tsx](https://github.com/jacobwicks/flashcard/blob/master/src/scenes/Answering/complete/test-11.tsx)

The test failed and Jest gave us an error message. The error message says: 
```
Unable to find an element with the text: content => content === withoutLineBreaks. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
```

If you scroll down the screen that displays the failed test, you can see that it failed at the line where we try to use the custom function `compareToInitialAnswer` to find the element that contains the answer.
```
      134 |     //because the Answer component sticks a header with text in the answer div
      135 |     //the function returns true if content is equal to the initial answer withoutLineBreaks
    > 136 |     const answer = getByText(compareToInitialAnswer);
```

The error message tells us that the function `compareToInitialAnswer` did not return true for any of the elements in the document. Here's the code for `compareToInitialAnswer`:

```javascript
const compareToInitialAnswer = (content: string) => content === withoutLineBreaks;
```
##CompareToInitialAnswer No Longer Finds the Answer
Now you know that `compareToInitialAnswer` no longer finds the answer. `compareToInitialAnswer` no longer finds the answer because the rendered code looks different now that the answer is split up into multiple divs. So the test 'clicks the submit button and shows the answer' fails, and we need to fix it.

But there is something else that you should be concerned about. Take a look at the whole test file for `Answering`. Is 'clicks the submit button and shows the answer' the only test that uses `compareToInitialAnswer`? 

No! The test named 'the answer does not show up before the submit button is clicked' also uses `compareToInitialAnswer`. But that test still passes. Why does that test still pass, even though it is using `compareToInitialAnswer` and `compareToInitialAnswer` doesn't work? 

The test named 'the answer does not show up before the submit button is clicked' still passes because it expects to find nothing when it passes `compareToInitialAnswer` to a query. Now that `compareToInitialAnswer` doesn't work, it will still find nothing. It passes when it finds nothing, and will only fail when the query using `compareToInitialAnswer` returns a result.

This is a good example of why it's important to understand how your tests work. You need to know when your tests are actually giving you useful information and when they aren't.

##Fix the compareToInitialAnswer Function
Earlier we learned that a custom function for a query can have two parameters: 

```javascript
(content : string, element: HTMLElement) => boolean
```

`compareToInitialAnswer` only has one parameter, content. It just tests if content is equal to the variable `withoutLineBreaks`. `compareToInitialAnswer` doesn't do anything with the second argument, the element. We can fix the test by changing how `compareToInitialAnswer` works. 

Instead of looking at the `content` string, we'll look at the `textContent` of each element. Change `compareToInitialAnswer` to this:
 
```javascript
    const compareToInitialAnswer = (
        content: string, 
        { textContent } : HTMLElement
    ) => !!textContent && 
        textContent
        .replace(/\s{2,}/g, " ")
        .slice(6, textContent.length) === withoutLineBreaks;
```
Here's a line by line explanation of the changes.

```javascript
        { textContent } : HTMLElement
```
We add a second parameter. The second parameter is of the type `HTMLElement`. `HTMLElement` has `textContent` that we can look at. We aren't interested in any of the other properties, so we'll use Object Destructuring to pull the `textContent` property out of the element that gets passed to the function.

```javascript
 ) => !!textContent && 
```

This anonymous function has an implicit return. It will return either the value of `textContent` cast to boolean, or the value of the strict equality comparison of the string that we make from `textContent` to `withoutLineBreaks`.

[!!](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_NOT) is the Double Not operator. It casts the value to boolean. The `textContent` property of an `HTMLElement` will either be a string or *null*. If the `textContent` is *null*, the function will cast *null* to boolean, get *false*, and return *false*. 

[&&](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators#Logical_AND) is the Logical And operator. The first condition in this expression is casting `textContent` to boolean. If `textContent` is a string, it will be cast to boolean, and evaluate to *true*. Because the first condition is *true*, the code after the && operator will then be evaluated.

```javascript
 textContent
```
We know that the next lines will only be run if `textContent` is a string. So we can use the string methods `.replace` and `.slice` to create a new string that we'll compare to `withoutLineBreaks`. We can use those methods on different lines in the code. They do not have to be written all on one line to work.

```javascript
.replace(/\s{2,}/g, " ")
```
We use `String.replace` to replace any linebreaks and multiple spaces with a single space. You can look at this [regEx on regExr](https://regexr.com/4s7hp) if you want to.

```javascript
 .slice(6, textContent.length) === withoutLineBreaks;
```

We are looking for the element that holds both the `Header` with the string 'Answer' in it and also holds a div for each line in the answer. So the `textContent` that we want will start with the string 'Answer.' Use the `String.slice` method to cut off the first 6 characters and return a new string. This cuts off the 'Answer' from the start of the string and lets us compare to `withoutLineBreaks`.

`===` is the [strict equality operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness).

Once you save the changed `compareToInitialAnswer`, all tests will pass. 

![All Tests Pass](https://thepracticaldev.s3.amazonaws.com/i/vsycw6c2wczkas27mczp.png)

###Next Post
In the next post we will make a new component called `Buttons`. We will move the `Submit` button into `Buttons`. `Buttons` will also show the `Right` and `Wrong` buttons after `Submit` is clicked. To make the buttons work we will make some changes to the `types.ts` file and `CardContext`.