- Mastering React Test:Driven Development
- Daniel Irvine
- 1139字
- 2021-06-24 14:45:04
Rendering the list of appointments
We'll add our new component into the same file we've been using already because there's not much code in there so far.
In test/Appointment.test.js, create a new describe block under the first one, with a single test, as follows. This test checks that we render a div with a particular ID. That's important in this case because we load a CSS file that looks for this element. The expectations in this test use the DOM method, querySelector. This searches the DOM tree for a single element with the tag provided:
describe('AppointmentsDayView', () => {
let container;
beforeEach(() => {
container = document.createElement('div');
});
const render = component =>
ReactDOM.render(component, container);
it('renders a div with the right id', () => {
render(<AppointmentsDayView appointments={[]} />);
expect(container.querySelector('div#appointmentsDayView')).not.toBeNull();
});
});
This test uses the exact same render function from the first describe block, as well as the same let container declaration and beforeEach block. In other words, we've introduced duplicated code. By duplicating code from our first test suite, we're making a mess straight after cleaning up our code! Well, we're allowed to do it when we're in the first stage of the TDD cycle. Once we've got the test passing, we can think about the right structure for the code.
Run npm test and let's look at the output:
FAIL test/Appointment.test.js
Appointment
? renders the customer first name (18ms)
? renders another customer first name (2ms)
AppointmentsDayView
? renders a div with the right id (7ms)
● AppointmentsDayView ? renders a div with the right id
ReferenceError: AppointmentsDayView is not defined
Let's work on getting this test to pass!
- To fix this, change the last import in your test file to read as follows:
import {
Appointment,
AppointmentsDayView
} from '../src/Appointment';
- In src/Appointment.js, add this functional component below Appointment:
export const AppointmentsDayView = () => null;
- Run your tests again:
● AppointmentsDayView ? renders a div with the right id
expect(received).not.toBeNull()
Received: null
47 | it('renders a div with the right id', () => {
48 | render(<AppointmentsDayView appointments={[]} />);
> 49 | expect(container.querySelector('div#appointmentsDayView')).not.toBeNull();
| ^
50 | });
- Finally, a test failure! Let's get that div in place:
export const AppointmentsDayView = () =>
<div id="appointmentsDayView"></div>;
- Your test should now be passing. Let's move on to the next test. Add the following text, just below the last test in test/Appointment.test.js, still inside the AppointmentsDayView describe block:
it('renders multiple appointments in an ol element', () => {
const today = new Date();
const appointments = [
{ startsAt: today.setHours(12, 0) },
{ startsAt: today.setHours(13, 0) }
];
render(<AppointmentsDayView appointments={appointments} />);
expect(container.querySelector('ol')).not.toBeNull();
expect(
container.querySelector('ol').children
).toHaveLength(2);
});
- Run your tests:
expect(received).not.toBeNull()
Received: null
57 | ];
58 | render(<AppointmentsDayView appointments={appointments} />);
> 59 | expect(container.querySelector('ol')).not.toBeNull();
| ^
60 | expect(container.querySelector('ol').children).toHaveLength(2);
61 | });
62 | });
at Object.toBeNull (test/Appointment.test.js:48:47)
- Let's add the ol element. Remember not to jump ahead; at this point, we just need ol to be there, not including the two items:
export const AppointmentsDayView = () => (
<div id="appointmentsDayView">
<ol />
</div>
);
- Run npm test again. The test output is now as follows:
Expected length: 2
Received length: 0
Received object: []
47 | render(<Appointments appointments={appointments} />);
48 | expect(container.querySelector('ol')).not.toBeNull();
> 49 | expect(container.querySelector('ol').children).toHaveLength(2);
| ^
50 | });
51 | });
52 |
- Since we've got multiple expectations in this test, the stack trace is essential in highlighting which expectation failed. This time, it's the second expectation: we've got zero children in the ol element but we want two. To fix this, as always, we'll do the simplest thing that will possibly work, as follows:
export const AppointmentsDayView = ({ appointments }) => (
<div id="appointmentsDayView">
<ol>
{appointments.map(() => (
<div />
))}
</ol>
</div>
);
- If we're being strict, this isn't quite right: ol elements should not have div elements for children. But, that's all we should need to pass the test. We can use the next test to make sure the children are li elements. Let's see what Jest says; run npm test again:
PASS test/Appointment.test.js
Appointment
? renders the customer first name (19ms)
? renders another customer first name (2ms)
AppointmentsDayView
? renders a div with the right id (7ms)
? renders multiple appointments in an ol element (16ms)
console.error node_modules/react/cjs/react.development.js:217
Warning: Each child in an array or iterator should have a unique "key" prop.
- Our test passed, but we got a warning from React. It's telling us to set a key value on each li element. We can use startsAt as a key:
<ol>
{appointments.map(appointment => (
<div key={appointment.startsAt} />
))}
</ol>
The best we can do is set a key to get rid of this warning message. Any value will do: unfortunately we can't use TDD to specify how keys are formed.
In this case, I'd quite like a test that uses the startsAt timestamp for each li key. Let's just imagine that we have that test in place.
- Learning Microsoft Windows Server 2012 Dynamic Access Control
- Kibana Essentials
- Java 9 Concurrency Cookbook(Second Edition)
- JavaScript 網(wǎng)頁編程從入門到精通 (清華社"視頻大講堂"大系·網(wǎng)絡(luò)開發(fā)視頻大講堂)
- 云原生Spring實戰(zhàn)
- OpenStack Cloud Computing Cookbook(Fourth Edition)
- Mastering Unity Shaders and Effects
- 大模型RAG實戰(zhàn):RAG原理、應(yīng)用與系統(tǒng)構(gòu)建
- Salesforce Reporting and Dashboards
- Python算法指南:程序員經(jīng)典算法分析與實現(xiàn)
- Learning YARN
- Distributed Computing in Java 9
- HTML5+CSS3+JavaScript 從入門到項目實踐(超值版)
- UI動效設(shè)計從入門到精通
- Learning NHibernate 4