Skip to content

Commit

Permalink
Moar unit tests!
Browse files Browse the repository at this point in the history
  • Loading branch information
AJGeel committed Oct 22, 2024
1 parent f36d4c6 commit b9e48f9
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 7 deletions.
8 changes: 1 addition & 7 deletions src/pages/history/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,12 @@ import {
getHoursWithHistory,
organiseHistory,
} from "@/src/services/history";
import { formatHourDisplay } from "@/src/utils/date/formatHourDisplay";

import HistoryItem from "./components/HistoryItem";
import SearchHeader from "./components/SearchHeader";
import TimelineView from "./components/TimelineView";

const formatHourDisplay = (dateStr: string, hourStr: string) => {
const fullDateTime = `${dateStr}T${hourStr}:00:00Z`;
const date = new Date(fullDateTime);
// Format just the hour in local time
return format(date, "HH:00");
};

const History = () => {
const [searchQuery, setSearchQuery] = useState("");
const { debouncedValue: debouncedSearchQuery } = useDebounce(
Expand Down
57 changes: 57 additions & 0 deletions src/utils/date/formatHourDisplay.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { describe, it, expect, beforeAll, afterAll } from "vitest";

import { formatHourDisplay } from "./formatHourDisplay";

const originalTimezone = process.env.TZ;

// Test cases in different timezones
const timezones = ["UTC", "America/New_York", "Asia/Tokyo", "Europe/London"];

describe("Time formatting functions", () => {
describe("formatHourDisplay", () => {
for (const timezone of timezones) {
describe(`in ${timezone} timezone`, () => {
beforeAll(() => {
process.env.TZ = timezone;
});

afterAll(() => {
process.env.TZ = originalTimezone;
});

it("should format midnight UTC correctly", () => {
const result = formatHourDisplay("2024-01-01", "00");
expect(result).toMatch(/^\d{2}:00$/);
});

it("should format noon UTC correctly", () => {
const result = formatHourDisplay("2024-01-01", "12");
expect(result).toMatch(/^\d{2}:00$/);
});

it("should format evening UTC correctly", () => {
const result = formatHourDisplay("2024-01-01", "20");
expect(result).toMatch(/^\d{2}:00$/);
});

it("should handle single-digit hours correctly", () => {
const result = formatHourDisplay("2024-01-01", "05");
expect(result).toMatch(/^\d{2}:00$/);
});

it("should handle date transitions correctly", () => {
const result = formatHourDisplay("2024-01-01", "23");
expect(result).toMatch(/^\d{2}:00$/);
});
});
}

it("should handle invalid date strings gracefully", () => {
expect(() => formatHourDisplay("invalid-date", "12")).toThrow();
});

it("should handle invalid hour strings gracefully", () => {
expect(() => formatHourDisplay("2024-01-01", "25")).toThrow();
});
});
});
8 changes: 8 additions & 0 deletions src/utils/date/formatHourDisplay.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { format } from "date-fns";

export const formatHourDisplay = (dateStr: string, hourStr: string) => {
const fullDateTime = `${dateStr}T${hourStr}:00:00Z`;
const date = new Date(fullDateTime);

return format(date, "HH:00");
};
60 changes: 60 additions & 0 deletions src/utils/date/formatTime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { afterAll, beforeAll, describe, expect, it } from "vitest";

import { formatTime } from "./formatTime";

const originalTimezone = process.env.TZ;
const timezones = ["UTC", "America/New_York", "Asia/Tokyo", "Europe/London"];

describe("formatTime", () => {
for (const timezone of timezones) {
describe(`in ${timezone} timezone`, () => {
beforeAll(() => {
process.env.TZ = timezone;
});

afterAll(() => {
process.env.TZ = originalTimezone;
});

it("should format midnight correctly", () => {
const midnight = new Date("2024-01-01T00:00:00Z").getTime();
const result = formatTime(midnight);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});

it("should format noon correctly", () => {
const noon = new Date("2024-01-01T12:00:00Z").getTime();
const result = formatTime(noon);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});

it("should format time with seconds correctly", () => {
const timeWithSeconds = new Date("2024-01-01T12:34:56Z").getTime();
const result = formatTime(timeWithSeconds);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});

it("should handle millisecond precision", () => {
const timeWithMs = new Date("2024-01-01T12:34:56.789Z").getTime();
const result = formatTime(timeWithMs);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});
});
}

it("should handle invalid timestamps gracefully", () => {
expect(() => formatTime(NaN)).toThrow();
});

it("should handle very large timestamps", () => {
const farFuture = new Date("2100-01-01T00:00:00Z").getTime();
const result = formatTime(farFuture);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});

it("should handle very small timestamps", () => {
const farPast = new Date("1900-01-01T00:00:00Z").getTime();
const result = formatTime(farPast);
expect(result).toMatch(/^\d{2}:\d{2}:\d{2}$/);
});
});
7 changes: 7 additions & 0 deletions src/utils/date/formatTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { format } from "date-fns";

export const formatTime = (timestamp: number) => {
const date = new Date(timestamp);

return format(date, "HH:mm:ss");
};

0 comments on commit b9e48f9

Please sign in to comment.