You have a frontend app that shows current time. I mean - you built a clock. Pretty simple, working fine. But how to test it properly?
If you new to testing, you may not see the problem. What's the issue, right? You check what time is it in the system, then you check in test if UI shows the same thing. Not really...
This approach won't work cause time may be different when you check it is the system and then (after a while) check it in your test. Your goal needs to be different - you need to control system time in tests and check things based on that.
Let's assume we have really simple React component, the only thing it does is showing hours and minutes (we don't care if this shows '02' when it 2 o'clock, let's make if super simple). The component looks like this:
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.div`
text-align: center;
`;
const Time = () => {
const today = new Date();
return (
<Wrapper>
<h2>Current time is: {today.getHours()}:{today.getMinutes()}</h2>
</Wrapper>
);
}
export default Time;
Now, let's write a unit test for it. We will be using jest and React Testing Library. If we want to test anything related to time, we shouldn't use real time methods (no setTimeout
and things like this) cause they rely on real time. We need fake time here. So first we want to tell jest
to do that before our test start executing. We can achieve it by using jest.useFakeTimers()
. Having that we can set system time we want. And now test the UI! Just don't forget to go back to real timers after all tests that needed fake ones.
This is how the test may look like:
import { render, screen } from '@testing-library/react';
import Time from './Time';
describe('Time component', () => {
beforeAll(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date('20 Aug 2020 02:12:00 GMT').getTime())
});
afterAll(() => {
jest.useRealTimers();
});
test('renders current time', () => {
render(<Time />);
expect(screen.getByText(/current time is/i)).toBeInTheDocument();
expect(screen.getByText(/2/i)).toBeInTheDocument();
expect(screen.getByText(/12/i)).toBeInTheDocument();
})
});
I hope you got the idea :) Happy coding and testing!
Top comments (1)
This is not allowing to change the input value...