I use vitest to test my components and hooks.
I have a useLocalTime
hook that I want to test, but the renderHook
function from @testing-library/react
always returns null.
Any idea why ?
Here is the hook :
import {useEffect, useState} from "react";
import {Dayjs} from "dayjs";
interface Props {
dayJsObject: Dayjs;
format?: string;
}
const capitalizeFirstLetters = (text: string) => {
return text
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};
export const useLocalTime = ({dayJsObject, format}: Props) => {
const [formattedTime, setFormattedTime] = useState<string | null>(null);
useEffect(() => {
const updateTime = () => {
const currentTime = dayJsObject.format(format ?? "D MMMM YYYY LTS");
setFormattedTime(capitalizeFirstLetters(currentTime));
};
const interval = setInterval(updateTime, 1000);
return () => clearInterval(interval);
}, [dayJsObject, format]);
return formattedTime;
};
Here is the test :
import {renderHook} from "@testing-library/react";
import dayjs from "dayjs";
import {useLocalTime} from "ui/hooks/useLocalTime";
describe("useLocalTime", () => {
it("should return the formatted time", () => {
const dayJsObject = dayjs("2022-06-16T14:49:35.718Z");
const {result} = renderHook(() => useLocalTime({dayJsObject}));
expect(result.current).toEqual("16 June 2022 14:49:35");
});
});
Here is the error :
AssertionError: expected null to deeply equal '16 June 2022 14:49:35'
- Expected:
"16 June 2022 14:49:35"
+ Received:
null
That's because updateTime
in your useLocalTime
hook isn't firing due to it being in an 1000ms interval. It's returning the default state (null
) provided in the hook.
describe("useLocalTime", () => {
it("should return the formatted time", () => {
jest.useFakeTimers();
const dayJsObject = dayjs("2022-06-16T14:49:35.718Z");
const {result} = renderHook(() => useLocalTime({dayJsObject}));
act(() => {
jest.advanceTimersByTime(1100);
});
expect(result.current).toEqual("16 June 2022 14:49:35");
});
});
updateTime
on initial load.