Skip to content

Instantly share code, notes, and snippets.

@SimonMueller
Last active February 11, 2022 09:20
Show Gist options
  • Save SimonMueller/ff17be6c6acb8b3e5d760981072a0cba to your computer and use it in GitHub Desktop.
Save SimonMueller/ff17be6c6acb8b3e5d760981072a0cba to your computer and use it in GitHub Desktop.
Simple text timer in seconds written in React with Typescript
import React from 'react';
import { render, act } from '@testing-library/react';
import TextSecondTimer from './TextSecondTimer';
describe('Text second timer component', () => {
beforeEach(() => jest.useFakeTimers());
it('shows zero if timeout is zero', () => {
const { getByText } = render(<TextSecondTimer timeoutInSeconds={0} />);
expect(getByText('0')).toBeVisible();
});
it('shows initial timeout value if timeout is below zero', () => {
const { getByText } = render(<TextSecondTimer timeoutInSeconds={-5} />);
expect(getByText('-5')).toBeVisible();
});
it('shows initial timeout value if timeout is greater than zero', () => {
const { getByText } = render(<TextSecondTimer timeoutInSeconds={20} />);
expect(getByText('20')).toBeVisible();
});
it('shows timeout value minus advanced time', () => {
const { getByText } = render(<TextSecondTimer timeoutInSeconds={20} />);
act(() => {
jest.advanceTimersByTime(10000);
});
expect(getByText('10')).toBeVisible();
act(() => {
jest.advanceTimersByTime(10000);
});
expect(getByText('0')).toBeVisible();
});
it('shows zero after all timers have run', () => {
const { getByText } = render(<TextSecondTimer timeoutInSeconds={20} />);
act(() => {
jest.runAllTimers();
});
expect(getByText('0')).toBeVisible();
});
});
import React, { useEffect, useState } from 'react';
interface Props {
timeoutInSeconds: number;
}
export default function TextSecondTimer({ timeoutInSeconds }: Props) {
const [timeLeftInSeconds, setTimeLeftInSeconds] = useState<number>(timeoutInSeconds);
useEffect(() => {
setTimeLeftInSeconds(timeoutInSeconds);
}, [timeoutInSeconds]);
useEffect(() => {
const interval: number = setInterval(() => {
const newTimeLeftInMillis = timeLeftInSeconds - 1;
return newTimeLeftInMillis < 0
? clearInterval(interval)
: setTimeLeftInSeconds(timeLeftInSeconds - 1);
}, 1000);
return () => clearInterval(interval);
});
return (<>{ timeLeftInSeconds }</>);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment