- Log swallowed errors in file watcher and window operations (lib.rs, watcher.rs) - Propagate recovery errors from bridge::recover_pending to SyncResult.errors so the frontend can display them instead of silently dropping failures - Fix useTauriEvent/useTauriEvents race condition where cleanup fires before async listen() resolves, leaking the listener (cancelled flag pattern) - Guard computeStaleness against invalid date strings (NaN -> 'normal' instead of incorrectly returning 'urgent') - Strengthen isMcError type guard to check field types, not just presence - Log warning when data directory resolution falls back to '.' (state.rs, bridge.rs) - Add test for computeStaleness with invalid date inputs
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { computeStaleness, isMcError } from "@/lib/types";
|
|
|
|
describe("computeStaleness", () => {
|
|
it("returns 'normal' for null timestamp", () => {
|
|
expect(computeStaleness(null)).toBe("normal");
|
|
});
|
|
|
|
it("returns 'fresh' for items less than 1 day old", () => {
|
|
const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
|
|
expect(computeStaleness(twoHoursAgo)).toBe("fresh");
|
|
});
|
|
|
|
it("returns 'normal' for items 1-2 days old", () => {
|
|
const thirtyHoursAgo = new Date(
|
|
Date.now() - 30 * 60 * 60 * 1000
|
|
).toISOString();
|
|
expect(computeStaleness(thirtyHoursAgo)).toBe("normal");
|
|
});
|
|
|
|
it("returns 'amber' for items 3-6 days old", () => {
|
|
const fourDaysAgo = new Date(
|
|
Date.now() - 4 * 24 * 60 * 60 * 1000
|
|
).toISOString();
|
|
expect(computeStaleness(fourDaysAgo)).toBe("amber");
|
|
});
|
|
|
|
it("returns 'urgent' for items 7+ days old", () => {
|
|
const tenDaysAgo = new Date(
|
|
Date.now() - 10 * 24 * 60 * 60 * 1000
|
|
).toISOString();
|
|
expect(computeStaleness(tenDaysAgo)).toBe("urgent");
|
|
});
|
|
|
|
it("returns 'normal' for invalid date strings instead of 'urgent'", () => {
|
|
expect(computeStaleness("not-a-date")).toBe("normal");
|
|
expect(computeStaleness("")).toBe("normal");
|
|
expect(computeStaleness("2026-13-99T99:99:99Z")).toBe("normal");
|
|
});
|
|
});
|
|
|
|
describe("isMcError", () => {
|
|
it("returns true for valid McError objects", () => {
|
|
const error = {
|
|
code: "LORE_UNAVAILABLE",
|
|
message: "lore CLI not found",
|
|
recoverable: true,
|
|
};
|
|
expect(isMcError(error)).toBe(true);
|
|
});
|
|
|
|
it("returns false for plain strings", () => {
|
|
expect(isMcError("some error")).toBe(false);
|
|
});
|
|
|
|
it("returns false for null", () => {
|
|
expect(isMcError(null)).toBe(false);
|
|
});
|
|
|
|
it("returns false for objects missing required fields", () => {
|
|
expect(isMcError({ code: "TEST" })).toBe(false);
|
|
expect(isMcError({ message: "test" })).toBe(false);
|
|
expect(isMcError({ recoverable: true })).toBe(false);
|
|
});
|
|
});
|