- Mastering React Test:Driven Development
- Daniel Irvine
- 610字
- 2021-06-24 14:45:03
Backtracking on ourselves
There's only one piece of shared state that our tests use and that's document. It must not be getting cleared each time the tests are run, and so we see the output of each test inside the document.
Even if we fixed our production code to remove the hard-coding, it still wouldn't pass; instead, we'd see the text AshleyJordan.
One solution is to clear the document DOM tree before each test run. But there's a simpler solution: we can rework our tests to not append our container element to the DOM at all, and instead work directly with the container element. In other words, we can change our expectation to check not document.body.textContent but container.textContent.
Unfortunately, there's a problem. We're in the middle of a red test. We should never refactor, rework, or otherwise change course while we're red.
What we'll have to do is ignore, or pend, this test we're working on. We do that by changing the word it to it.skip. Do that now for the second test:
it.skip('renders another customer first name', () => {
Run tests. You'll see Jest ignores the second test, and the first one still passes:
PASS test/Appointment.test.js
Appointment
? renders the customer first name (19ms)
○ skipped 1 test
Test Suites: 1 passed, 1 total
Tests: 1 skipped, 1 passed, 2 total
For this refactor, we need to make two changes:
- Change the expectation to match on container.textContent.
- Remove the line that calls appendChild on the document body.
We can also take this opportunity to inline the component variable. Change the test to read as follows:
it('renders the customer first name', () => {
const customer = { firstName: 'Ashley' };
const container = document.createElement('div');
ReactDOM.render(<Appointment customer={customer} />, container);
expect(container.textContent).toMatch('Ashley');
});
Run your tests: the result should be the same as earlier, with one passing test and one skipped.
It's time to bring that second test back in, by removing the .skip from the function name, and this time, let's update the test code to make the same changes we made in the first, as follows:
it('renders another customer first name', () => {
const customer = { firstName: 'Jordan' };
const container = document.createElement('div');
ReactDOM.render(<Appointment customer={customer} />, container);
expect(container.textContent).toMatch('Jordan');
});
Running tests now should give us the error that we were originally expecting:
FAIL test/Appointment.test.js
Appointment
? renders the customer first name (18ms)
? renders another customer first name (8ms)
● Appointment ? renders another customer first name
expect(received).toMatch(expected)
Expected value to match:
"Jordan"
Received:
"Ashley"
To fix this, we need to introduce the variable and use it within our JSX, which supports embedding JavaScript expressions within elements. We can also use destructuring assignment to avoid creating unnecessary variables.
Change the definition of Appointment to look as follows:
export const Appointment = ({ customer }) => (
<div>{customer.firstName}</div>
);
Note that I haven't fully destructured this. I could have written this function like this:
export const Appointment = ({ customer: { firstName } }) => (
<div>{firstName}</div>
);
The first version is no longer than the second; however, if you're counting tokens, it has one less set of curly braces. The most concise solution always wins!
Run tests; we expect this test to now pass, as follows:
PASS test/Appointment.test.js
Appointment
? renders the customer first name (21ms)
? renders another customer first name (2ms)
Great work! We're done with our passing test.
- 在最好的年紀學Python:小學生趣味編程
- 大學計算機應用基礎實踐教程
- Visual Basic編程:從基礎到實踐(第2版)
- Hadoop+Spark大數據分析實戰
- Python時間序列預測
- Learning Salesforce Einstein
- 劍指Java:核心原理與應用實踐
- 區塊鏈底層設計Java實戰
- Learning iOS Penetration Testing
- Isomorphic JavaScript Web Development
- C++面向對象程序設計教程
- 交互設計語言:與萬物對話的藝術(全兩冊)
- Getting Started with SQL Server 2014 Administration
- Microsoft Hyper-V PowerShell Automation
- 精通Django 3 Web開發