The first test we will write for this app, is for
App. So create
App.test.js in the
src directory.
We begin by importing these.
src/App.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import App from './App';
And the very first test, is for
App to render. We test to see if that string appears in the screen. This, by itself, isn't a great test, but it will do for a start.
src/App.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import App from './App';
describe("App", () => {
it('renders', () => {
render(<App />);
expect(screen.queryByText('Welcome to J-Trainer!')).toBeInTheDocument();
});
});
Run
npm test in the command line interface. This test should succeed.
Now we will test the
Header component. Create
Header.test.js in the
Header directory of the
components directory. We begin with the appropriate
import statements.
src/components/Header/Header.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";
import Header from './Header';
We define the getters and setters, because these are passed to the components.
src/components/Header/Header.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";
import Header from './Header';
let maxRemaining;
let started;
let setStarted = (val)=> {
started = val;
};
let charset;
let setCharset = (val)=> {
charset = val;
};
let remaining;
let setRemaining = (val)=> {
remaining = val;
};
let usedQuestions;
let setUsedQuestions = (val)=> {
usedQuestions = val;
};
let answer;
let setAnswer = (val)=> {
answer = val;
};
let result;
let setResult = (val)=> {
result = val;
};
let question;
let setQuestion = (val)=> {
question = val;
};
We then use the
describe() function, and pass in "Header" and a callback as arguments.
src/components/Header/Header.test.jslet question;
let setQuestion = (val)=> {
question = val;
};
describe("Header", () => {
});
The tests have an explanatory string passed in as an argument, and a callback. This makes it easy to see what the tests should test for.
src/components/Header/Header.test.jsdescribe("Header", () => {
it("should render with BEGIN button if not started and no charset selected", () => {
});
it("should render with CANCEL button if started, charset selected, has questions remaining", () => {
});
it("should render with RESTART button if started, charset selected, has no questions remaining", () => {
});
});
Time for the first test. We make sure that the operating conditions are as close to the actual operating conditions, by setting these variables. Note that
started is now
false and
charset is
null.
src/components/Header/Header.test.jsit("should render with BEGIN button if not started and no charset selected", () => {
maxRemaining = 20;
setCharset(null);
setStarted(false);
setUsedQuestions([]);
setRemaining(maxRemaining);
});
We render the
Header component with all the required attributes.
src/components/Header/Header.test.jsit("should render with BEGIN button if not started and no charset selected", () => {
maxRemaining = 20;
setCharset(null);
setStarted(false);
setUsedQuestions([]);
setRemaining(maxRemaining);
render(
<Header
charset={ charset }
started={ started }
remaining={ remaining }
usedQuestions={ usedQuestions }
maxRemaining={ maxRemaining }
setStarted={ setStarted }
setCharset={ setCharset }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setResult={ setResult }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
And then we have two asserts. Use the
expect() function. Ensure that the button's text is "BEGIN ➤" because
started is
false and it is disabled because
charset is
null.
src/components/Header/Header.test.jsit("should render with BEGIN button if not started and no charset selected", () => {
maxRemaining = 20;
setCharset(null);
setStarted(false);
setUsedQuestions([]);
setRemaining(maxRemaining);
render(
<Header
charset={ charset }
started={ started }
remaining={ remaining }
usedQuestions={ usedQuestions }
maxRemaining={ maxRemaining }
setStarted={ setStarted }
setCharset={ setCharset }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setResult={ setResult }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.getByTestId("BtnStartEnd").textContent).toBe("BEGIN ➤");
expect(screen.getByTestId("BtnStartEnd")).toBeDisabled();
});
We will also need to add this to the button.
src/components/Header.jsif (started) {
return (
<>
<div className="Title">
<h1>J-Trainer</h1>
</div>
<div className="Controls">
<div>
<br />
<button data-testid="BtnStartEnd" onClick={ ()=>{BtnEnd_click();}}>
{ remaining === 0 ? "RESTART ➤ " : "CANCEL ☓" }
</button>
</div>
</div>
</>
);
} else {
return (
<>
<div className="Title">
<h1>J-Trainer</h1>
</div>
<div className="Controls">
<div>
<input type="radio" name="charset" onClick={()=>{SetCurrentCharset('hiragana');}} /> Hiragana <br />
<input type="radio" name="charset" onClick={()=>{SetCurrentCharset('katakana');}} /> Katakana <br />
<br />
<button data-testid="BtnStartEnd" onClick={ ()=>{BtnStart_click();}} disabled={ charset === null ? true : false }>
BEGIN ➤
</button>
</div>
</div>
</>
);
}
Now for the next test! Again, pass what we need to. Just make sure that
remaining is more than 0 and
charset is not
null (even an empty array counts), and
started is
true.
src/components/Header/Header.test.jsit("should render with CANCEL button if started, charset selected, has questions remaining", () => {
maxRemaining = 20;
setCharset([]);
setStarted(true);
setUsedQuestions([]);
setRemaining(maxRemaining);
});
Next, render the
Header component with the appropriate attributes.
src/components/Header/Header.test.jsit("should render with CANCEL button if started, charset selected, has questions remaining", () => {
maxRemaining = 20;
setCharset([]);
setStarted(true);
setUsedQuestions([]);
setRemaining(maxRemaining);
render(
<Header
charset={ charset }
started={ started }
remaining={ remaining }
usedQuestions={ usedQuestions }
maxRemaining={ maxRemaining }
setStarted={ setStarted }
setCharset={ setCharset }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setResult={ setResult }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
Then assert that we will expect "CANCEL ☓" to be the button's text.
src/components/Header/Header.test.jsit("should render with CANCEL button if started, charset selected, has questions remaining", () => {
maxRemaining = 20;
setCharset([]);
setStarted(true);
setUsedQuestions([]);
setRemaining(maxRemaining);
render(
<Header
charset={ charset }
started={ started }
remaining={ remaining }
usedQuestions={ usedQuestions }
maxRemaining={ maxRemaining }
setStarted={ setStarted }
setCharset={ setCharset }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setResult={ setResult }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.getByTestId("BtnStartEnd").textContent).toBe("CANCEL ☓");
});
I feel like I shouldn't have to explain this last test. It's basically a repeat of the last two, but with a different assert.
src/components/Header/Header.test.jsit("should render with RESTART button if started, charset selected, has no questions remaining", () => {
maxRemaining = 20;
setCharset([]);
setStarted(true);
setUsedQuestions([]);
setRemaining(0);
render(
<Header
charset={ charset }
started={ started }
remaining={ remaining }
usedQuestions={ usedQuestions }
maxRemaining={ maxRemaining }
setStarted={ setStarted }
setCharset={ setCharset }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setResult={ setResult }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.getByTestId("BtnStartEnd").textContent).toBe("RESTART ➤ ");
});
Look at the console. You should see this!
Now let's start testing the
Display component. Create
Display.test.js in the
Display directory, and begin with the usual imports. We also want to import the utility
GetCharSet because it will be used in the testing.
src/components/Display/Display.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import Display from './Display';
import GetCharset from '../../utils/GetCharset';
Then we create the variables and their setters.
src/components/Display/Display.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import Display from './Display';
import GetCharset from '../../utils/GetCharset';
let maxRemaining;
let started;
let setStarted = (val)=> {
started = val;
};
let charset;
let setCharset = (val)=> {
charset = val;
};
let remaining;
let setRemaining = (val)=> {
remaining = val;
};
let usedQuestions;
let setUsedQuestions = (val)=> {
usedQuestions = val;
};
let answer;
let setAnswer = (val)=> {
answer = val;
};
let result;
let setResult = (val)=> {
result = val;
};
let question;
let setQuestion = (val)=> {
question = val;
};
And use the
describe() function, passing in the name of the component, and a callback.
src/components/Display/Display.test.jslet question;
let setQuestion = (val)=> {
question = val;
};
describe("Display", () => {
});
There are five tests in this. The strings passed in are descriptive of the tests.
src/components/Display/Display.test.jsdescribe("Display", () => {
it("should render with instructions and welcome message if not started", () => {
});
it("should render results if started and no questions remaining", () => {
});
it("should render remaining if started and has questions remaining", () => {
});
it("should render answer and tick if correct", () => {
});
it("should render answer and cross if incorrect", () => {
});
});
Just to save you some time, each of these tests will render the
Display component, with the same attributes. It's the values of the attributes that will vary.
src/components/Display/Display.test.jsdescribe("Display", () => {
it("should render with instructions and welcome message if not started", () => {
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
it("should render results if started and no questions remaining", () => {
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
it("should render remaining if started and has questions remaining", () => {
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
it("should render answer and tick if correct", () => {
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
it("should render answer and cross if incorrect", () => {
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
});
});
For the first test, we need
started to be
false. The rest doesn't really matter, but for the sake of neatness, we will set the others. And at the end of this test, we assert that "Welcome to J-Trainer!" is part of the document.
src/components/Display/Display.test.jsit("should render with instructions and welcome message if not started", () => {
maxRemaining = 20;
setCharset(null);
setStarted(false);
setUsedQuestions([]);
setRemaining(maxRemaining);
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.queryByText("Welcome to J-Trainer!")).toBeInTheDocument();
});
For the next test,
started should be
true and we should set
remaining to 0. Now we set
result to 1 as well. At the end, we should assert that the string "Practice more..." appears because 1 is a very poor result. And also we assert that
result and
maxRemaining will appear in the document in the string pattern specified.
src/components/Display/Display.test.jsit("should render results if started and no questions remaining", () => {
maxRemaining = 20;
setCharset(GetCharset("hiragana"));
setStarted(true);
setUsedQuestions([]);
setRemaining(0);
setResult(1);
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.queryByText("Practice more...")).toBeInTheDocument();
expect(screen.queryByText(result + " / " + maxRemaining)).toBeInTheDocument();
});
For this test, we set
started to
true and make sure that
remaining is greater than 0. In this case, we use 19. We assert that the button will show 1 less than
remaining, which is 18.
Also, we use the character set for Hiragana. For that, we use
GetCharset(). We set
question to an integer (use 0 because that's safe enough). So the
char property of the element in
charset pointed to by
question should appear in the document.
src/components/Display/Display.test.jsit("should render remaining if started and has questions remaining", () => {
maxRemaining = 20;
setCharset(GetCharset("hiragana"));
setStarted(true);
setUsedQuestions([]);
setRemaining(19);
setResult(1);
setQuestion(0);
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.getByTestId("BtnRemaining").textContent).toBe("18 REMAINING ➤");
expect(screen.queryByText(charset[question].char)).toBeInTheDocument();
});
And we want to make sure "btnRemaining" is added as a testing id.
src/components/Display.jsif (started && remaining > 0 && charset[question] !== undefined) {
return (
<>
<div className="Character">
{ charset[question].char }
</div>
<div className={ answer === "" ? "Result Hide" : "Result"}>
<span className={ charset[question].romaji === answer ? "Correct" : "Wrong" }>
{ charset[question].romaji === answer ? "✓" : "✗" }
</span>
{ answer }
</div>
<div className="Remaining">
<button data-testid="BtnRemaining" onClick={ ()=>{BtnNext_click();}} disabled={answer === ""}>
{ remaining - 1 } REMAINING ➤
</button>
</div>
</>
);
}
Now for this next test, we use Hiragana again. Set
question to 0. And set
answer to be the
romaji property of the first element (index 0) of
charset. And assert that
answer will appear in the document, and since it is the correct answer, we display the "✓".
src/components/Display/Display.test.jsit("should render answer and tick if correct", () => {
maxRemaining = 20;
setCharset(GetCharset("hiragana"));
setStarted(true);
setUsedQuestions([]);
setRemaining(19);
setResult(1);
setQuestion(0);
setAnswer(charset[0].romaji);
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.queryByText(answer)).toBeInTheDocument();
expect(screen.queryByText("✓")).toBeInTheDocument();
});
And here we have the opposite of the previous test. The variables are the same for the previous test, except that answer will be the
romaji property of the second element (index 1) of the
charset array, which is blatantly incorrect since
question is set to 0. Thus, we assert that "✗" will appear in the document.
src/components/Display/Display.test.jsit("should render answer and cross if incorrect", () => {
maxRemaining = 20;
setCharset(GetCharset("hiragana"));
setStarted(true);
setUsedQuestions([]);
setRemaining(19);
setResult(1);
setQuestion(0);
setAnswer(charset[1].romaji);
render(
<Display
charset={ charset }
started={ started }
remaining={ remaining }
maxRemaining={ maxRemaining }
answer={ answer }
question={ question }
usedQuestions={ usedQuestions }
result={ result }
setStarted={ setStarted }
setRemaining={ setRemaining }
setAnswer={ setAnswer }
setQuestion={ setQuestion }
setUsedQuestions={ setUsedQuestions }
/>
);
expect(screen.queryByText(answer)).toBeInTheDocument();
expect(screen.queryByText("✗")).toBeInTheDocument();
});
There you go, that's what the testing suite should show!
Finally, we test the
Keyboard component. For that, create
Keyboard.test.js in the
Keyboard directory. We begin with the usual imports and variable declarations, and because we will be making use of
charset, we import
GetCharset as well.
src/components/Keyboard/Keyboard.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";
import Keyboard from './Keyboard';
import GetCharset from '../../utils/GetCharset';
let result;
let setResult = (val)=> {
result = val;
};
let started;
let setStarted = (val)=> {
started = val;
};
let charset;
let setCharset = (val)=> {
charset = val;
};
let remaining;
let setRemaining = (val)=> {
remaining = val;
};
let usedQuestions;
let setUsedQuestions = (val)=> {
usedQuestions = val;
};
let answer;
let setAnswer = (val)=> {
answer = val;
};
let question;
let setQuestion = (val)=> {
question = val;
};
We describe the
Keyboard component test with five tests, each with a description and callback.
src/components/Keyboard/Keyboard.test.jsimport React from "react";
import { render, screen } from '@testing-library/react';
import userEvent from "@testing-library/user-event";
import Keyboard from './Keyboard';
import GetCharset from '../../utils/GetCharset';
let result;
let setResult = (val)=> {
result = val;
};
let started;
let setStarted = (val)=> {
started = val;
};
let charset;
let setCharset = (val)=> {
charset = val;
};
let remaining;
let setRemaining = (val)=> {
remaining = val;
};
let usedQuestions;
let setUsedQuestions = (val)=> {
usedQuestions = val;
};
let answer;
let setAnswer = (val)=> {
answer = val;
};
let question;
let setQuestion = (val)=> {
question = val;
};
describe("Keyboard", () => {
it("should render keys if started and there are remaining questions", () => {
});
it("should not render keys if not started", () => {
});
it("should not render keys if started and there are no remaining questions", () => {
});
it("should set result + 1 if key pressed correctly", () => {
});
it("should set result + 0 if key pressed incorrectly", () => {
});
});
As with the last component, we will render the component in the tests, with the requisite data.
src/components/Keyboard/Keyboard.test.jsdescribe("Keyboard", () => {
it("should render keys if started and there are remaining questions", () => {
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
});
it("should not render keys if not started", () => {
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
});
it("should not render keys if started and there are no remaining questions", () => {
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
});
it("should set result + 1 if key pressed correctly", () => {
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
});
it("should set result + 0 if key pressed incorrectly", () => {
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
});
});
For this test,
started is set to
true,
remaining is set to any value above 0, and we also set
charset. We then assert that the following test ids are found in the document. We'll just use "shi" and "yu", two random answers in the entire set.
src/components/Keyboard/Keyboard.test.jsit("should render keys if started and there are remaining questions", () => {
setRemaining(1);
setStarted(true);
setCharset(GetCharset("hiragana"));
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
expect(screen.getByTestId("btnAnswer_shi")).toBeInTheDocument();
expect(screen.getByTestId("btnAnswer_yu")).toBeInTheDocument();
});
We need to insert these test ids. So every button in the
Keyboard component will have that testing id, which is "btnAnswer_" with the answer appended.
src/components/Keyboard.jsconst answers = keyItems.map((item, index) => (
<div
key={'romaji_' + index}
className={item === '' ? 'Answer Hide' : ( answer === '' ? 'Answer' : 'Answer Greyed')}
onClick={()=>{BtnAnswer_click(item);}}
data-testid={'btnAnswer_' + item}
>
{item}
</div>
)
);
For this test, we test the opposite.
started is set to
false,
remaining is set to 0 (you could set it to
any value technically, but it would make no sense), and we set
charset. And we will ensure that the testing ids are not in there by making sure they are
null. Again, we will use "shi" and "yu", though you can pretty much use any of the romaji properties in the
charset array.
src/components/Keyboard/Keyboard.test.jsit("should not render keys if not started", () => {
setRemaining(0);
setStarted(false);
setCharset(GetCharset("hiragana"));
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
expect(screen.queryByText("shi")).toBe(null);
expect(screen.queryByText("yu")).toBe(null);
});
For this test, we also test the opposite.
started is set to
true,
remaining is set to 0, and we set
charset. And we will ensure that the testing ids are not in there by making sure they are
null. Again, we will use "shi" and "yu".
src/components/Keyboard/Keyboard.test.jsit("should not render keys if started and there are no remaining questions", () => {
setRemaining(0);
setStarted(true);
charset = GetCharset("hiragana");
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
expect(screen.queryByText("shi")).toBe(null);
expect(screen.queryByText("yu")).toBe(null);
});
Now this test. Set
started to
true, set
remaining to any number greater than 0, set
charset, set
question to 0, and set
result to, say, 5. These last two values will be important. After rendering the component, simulate a click event on the "a" button. "a" is the
romaji property at index 0 of
charset. Then we assert answer to be "a", and result to be (5 + 1) 6.
src/components/Keyboard/Keyboard.test.jsit("should set result + 1 if key pressed correctly", () => {
setRemaining(1);
setStarted(true);
setCharset(GetCharset("hiragana"));
setQuestion(0);
setResult(5);
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
userEvent.click(screen.getByTestId("btnAnswer_a"));
expect(answer).toBe("a");
expect(result).toBe(6);
});
And finally, this test! We do what we did before, but deliberately simulate a click event on the button "ka", which is
not at index 0. Naturally, we assert that the answer is "ka". Since we've set
result to 10, we assert that
result should
still be 10.
it("should set result + 0 if key pressed incorrectly", () => {
setRemaining(1);
setStarted(true);
setCharset(GetCharset("hiragana"));
setQuestion(0);
setResult(10);
render(
<Keyboard
charset={ charset }
remaining={ remaining }
started={ started }
answer={ answer }
question={ question }
result={ result }
setAnswer={ setAnswer }
setResult={ setResult }
/>
);
userEvent.click(screen.getByTestId("btnAnswer_ka"));
expect(answer).toBe("ka");
expect(result).toBe(10);
});
Yep, and now we have a full suite!
Final words
This app was fun to write. Not so fun to explain, but it actually was useful for teaching me to read and write in Japanese,
and level up in my ReactJS.
shi yu around,
T___T