From 1af9ee02df63d5803a98485c93bfa60fbb8cd87b Mon Sep 17 00:00:00 2001 From: Dmytro Stanchiev Date: Mon, 25 May 2026 11:01:01 -0400 Subject: [PATCH] fix: isolate EventCard tests and clean compose refs hook --- src/lib/compose-refs.ts | 9 ++-- tests/event-card.test.ts | 113 +++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 54 deletions(-) diff --git a/src/lib/compose-refs.ts b/src/lib/compose-refs.ts index b37ca3b..39224c3 100644 --- a/src/lib/compose-refs.ts +++ b/src/lib/compose-refs.ts @@ -54,9 +54,12 @@ function composeRefs(...refs: PossibleRef[]): React.RefCallback { * A custom hook that composes multiple refs * Accepts callback refs and RefObject(s) */ -function useComposedRefs(...refs: PossibleRef[]): React.RefCallback { - // biome-ignore lint/correctness/useExhaustiveDependencies: we want to memoize by all values - return React.useCallback(composeRefs(...refs), refs); +function useComposedRefs( + ref1: PossibleRef, + ref2: PossibleRef, + ref3?: PossibleRef, +): React.RefCallback { + return React.useMemo(() => composeRefs(ref1, ref2, ref3), [ref1, ref2, ref3]); } export { composeRefs, useComposedRefs }; diff --git a/tests/event-card.test.ts b/tests/event-card.test.ts index 6fcc005..0dbb135 100644 --- a/tests/event-card.test.ts +++ b/tests/event-card.test.ts @@ -1,65 +1,76 @@ -import { describe, expect, test } from "bun:test"; +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import { renderToStaticMarkup } from "react-dom/server"; import { EventCard } from "@/components/event-card"; import type { CalendarEvent } from "@/lib/types"; const sampleEvent: CalendarEvent = { - id: "evt_1", - title: "Design Review", - start: "2026-04-09T10:00:00+00:00", - end: "2026-04-09T11:00:00+00:00", - description: "Review the updated event list UI.", - location: "Studio A", - url: "https://example.com/event", - allDay: false, + id: "evt_1", + title: "Design Review", + start: "2026-04-09T10:00:00+00:00", + end: "2026-04-09T11:00:00+00:00", + description: "Review the updated event list UI.", + location: "Studio A", + url: "https://example.com/event", + allDay: false, }; describe("EventCard actions trigger", () => { - test("shows the triple-dots trigger without requiring hover and exposes an aria-label for the icon-only button", () => { - const markup = renderToStaticMarkup( - EventCard({ - event: sampleEvent, - onEdit: () => {}, - onDelete: () => {}, - }), - ); + beforeEach(() => { + globalThis.document = { + addEventListener: () => {}, + removeEventListener: () => {}, + } as unknown as Document; + }); - expect(markup).toContain('aria-label="Event actions"'); - expect(markup).not.toContain("opacity-0"); - expect(markup).not.toContain("group-hover:opacity-100"); - }); + afterEach(() => { + delete (globalThis as { document?: Document }).document; + }); - test("renders friendly shared date formatting instead of native locale strings", () => { - const markup = renderToStaticMarkup( - EventCard({ - event: sampleEvent, - onEdit: () => {}, - onDelete: () => {}, - }), - ); + test("shows the triple-dots trigger without requiring hover and exposes an aria-label for the icon-only button", () => { + const markup = renderToStaticMarkup( + EventCard({ + event: sampleEvent, + onEdit: () => {}, + onDelete: () => {}, + }), + ); - expect(markup).toContain("10:00–11:00"); - expect(markup).not.toContain("AM"); - }); + expect(markup).toContain('aria-label="Event actions"'); + expect(markup).not.toContain("opacity-0"); + expect(markup).not.toContain("group-hover:opacity-100"); + }); - test("renders inline warning copy for invalid event ranges", () => { - const markup = renderToStaticMarkup( - EventCard({ - event: { - id: "evt_invalid", - title: "Broken Event", - start: "2026-04-09T11:00:00+00:00", - end: "2026-04-09T10:00:00+00:00", - allDay: false, - }, - onEdit: () => {}, - onDelete: () => {}, - }), - ); + test("renders friendly shared date formatting instead of native locale strings", () => { + const markup = renderToStaticMarkup( + EventCard({ + event: sampleEvent, + onEdit: () => {}, + onDelete: () => {}, + }), + ); - expect(markup).toContain("Warning:"); - expect(markup).toContain("end time is before start time"); - expect(markup).not.toContain("Preview"); - expect(markup).not.toContain("Ship"); - }); + expect(markup).toContain("10:00–11:00"); + expect(markup).not.toContain("AM"); + }); + + test("renders inline warning copy for invalid event ranges", () => { + const markup = renderToStaticMarkup( + EventCard({ + event: { + id: "evt_invalid", + title: "Broken Event", + start: "2026-04-09T11:00:00+00:00", + end: "2026-04-09T10:00:00+00:00", + allDay: false, + }, + onEdit: () => {}, + onDelete: () => {}, + }), + ); + + expect(markup).toContain("Warning:"); + expect(markup).toContain("end time is before start time"); + expect(markup).not.toContain("Preview"); + expect(markup).not.toContain("Ship"); + }); });