@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
152 lines (123 loc) • 4.79 kB
text/typescript
/**
* @jest-environment jsdom
*/
// Mock the bridge to avoid loading all bridge implementations with ESM dependencies
jest.mock("../../bridge", () => ({
getCurrencyBridge: jest.fn(),
}));
import { renderHook, act } from "@testing-library/react";
import { getRemainingTime, useTimeRemaining } from "./react";
const MILLISECOND = 1000;
const SECOND = 1 * MILLISECOND;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
describe("getRemainingTime", () => {
test("should return empty string for negative or zero diff", () => {
expect(getRemainingTime(0)).toBe("");
expect(getRemainingTime(-1000)).toBe("");
expect(getRemainingTime(-100000)).toBe("");
});
test("should format seconds only", () => {
expect(getRemainingTime(30 * SECOND)).toBe("30s");
expect(getRemainingTime(59 * SECOND)).toBe("59s");
expect(getRemainingTime(1 * SECOND)).toBe("01s");
});
test("should format minutes and seconds", () => {
expect(getRemainingTime(1 * MINUTE + 30 * SECOND)).toBe("01m 30s");
expect(getRemainingTime(5 * MINUTE + 15 * SECOND)).toBe("05m 15s");
expect(getRemainingTime(59 * MINUTE + 59 * SECOND)).toBe("59m 59s");
});
test("should format hours, minutes and seconds", () => {
expect(getRemainingTime(1 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe("01h 30m 15s");
expect(getRemainingTime(2 * HOUR + 5 * MINUTE + 10 * SECOND)).toBe("02h 05m 10s");
expect(getRemainingTime(23 * HOUR + 59 * MINUTE + 59 * SECOND)).toBe("23h 59m 59s");
});
test("should format days, hours, minutes and seconds", () => {
expect(getRemainingTime(1 * DAY + 2 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe(
"01d 02h 30m 15s",
);
expect(getRemainingTime(5 * DAY + 10 * HOUR + 5 * MINUTE + 10 * SECOND)).toBe(
"05d 10h 05m 10s",
);
expect(getRemainingTime(10 * DAY + 23 * HOUR + 59 * MINUTE + 59 * SECOND)).toBe(
"10d 23h 59m 59s",
);
});
test("should skip zero values", () => {
expect(getRemainingTime(1 * DAY)).toBe("01d 00h 00m 00s");
expect(getRemainingTime(1 * HOUR)).toBe("01h 00m 00s");
expect(getRemainingTime(1 * MINUTE)).toBe("01m 00s");
expect(getRemainingTime(1 * DAY + 1 * MINUTE)).toBe("01d 00h 01m 00s");
expect(getRemainingTime(1 * DAY + 1 * HOUR)).toBe("01d 01h 00m 00s");
});
});
describe("useTimeRemaining", () => {
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.runOnlyPendingTimers();
jest.useRealTimers();
});
beforeEach(() => {
jest.setSystemTime(new Date("2024-01-01T12:00:00Z"));
});
test("should return empty string when proposal is null", () => {
const { result } = renderHook(() => useTimeRemaining());
expect(result.current).toBe("");
});
test("should return empty string when proposal is expired", () => {
const proposal = {
expiresAt: (Date.now() - 1000) * 1000, // 1 second ago
isExpired: true,
};
const { result } = renderHook(() => useTimeRemaining(proposal.expiresAt, proposal.isExpired));
expect(result.current).toBe("");
});
test("should return formatted time remaining for valid proposal", () => {
const expiresAt = Date.now() + 2 * HOUR + 30 * MINUTE + 15 * SECOND;
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
expect(result.current).toBe("02h 30m 15s");
});
test("should update time remaining every second", () => {
const expiresAt = Date.now() + 2 * MINUTE + 30 * SECOND;
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
expect(result.current).toBe("02m 30s");
act(() => {
jest.advanceTimersByTime(1 * SECOND);
});
expect(result.current).toBe("02m 29s");
act(() => {
jest.advanceTimersByTime(1 * SECOND);
});
expect(result.current).toBe("02m 28s");
act(() => {
jest.advanceTimersByTime(30 * SECOND);
});
expect(result.current).toBe("01m 58s");
});
test("should return empty string when time expires", () => {
const expiresAt = Date.now() + 2 * SECOND;
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
expect(result.current).toBe("02s");
act(() => {
jest.advanceTimersByTime(1 * SECOND);
});
expect(result.current).toBe("01s");
act(() => {
jest.advanceTimersByTime(1 * SECOND);
});
expect(result.current).toBe("");
});
test("should clear interval on unmount", () => {
const expiresAt = Date.now() + 1 * HOUR;
const { result, unmount } = renderHook(() => useTimeRemaining(expiresAt * 1000));
expect(result.current).toBe("01h 00m 00s");
unmount();
// Advance time after unmount - should not cause errors
act(() => {
jest.advanceTimersByTime(1 * SECOND);
});
});
});