Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions components/ballotquestions/CommitteeHearing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,43 @@ describe("CommitteeHearing", () => {
})

it("shows hearing context copy", () => {
render(<CommitteeHearing hearing={{ id: "1", startsAt: FUTURE_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "1", startsAt: FUTURE_MS, videoURLs: [] }}
/>
)
expect(screen.getByText("Committee Hearing")).toBeInTheDocument()
expect(
screen.getByText("Committee hearings are public meetings.")
).toBeInTheDocument()
})

it("formats the hearing date", () => {
render(<CommitteeHearing hearing={{ id: "1", startsAt: PAST_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "1", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(screen.getByText(/December 14, 2025/)).toBeInTheDocument()
})

it("shows a hearing page link when an id is present", () => {
render(
<CommitteeHearing hearing={{ id: "hearing-1", startsAt: PAST_MS }} />
<CommitteeHearing
hearing={{ id: "hearing-1", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(
screen.getByRole("link", { name: /Open hearing page/i })
).toHaveAttribute("href", "/hearing/1")
})

it("hides the hearing page link when no hearing id is available", () => {
render(<CommitteeHearing hearing={{ id: "", startsAt: PAST_MS }} />)
render(
<CommitteeHearing
hearing={{ id: "", startsAt: PAST_MS, videoURLs: [] }}
/>
)
expect(screen.queryByRole("link")).not.toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion components/ballotquestions/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type Hearing = {
id: string
videoURL?: string
videoURLs: string[]
startsAt: number // milliseconds since epoch, converted from Firestore Timestamp server-side
}

Expand Down
6 changes: 3 additions & 3 deletions docs/ballot-questions-frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ For each relevant hearing, display:

- **Status**: "Occurred" if `hearing.content.startsAt` is in the past, "Scheduled" if in the future
- **Date**: formatted from `hearing.content.startsAt`
- **Watch link**: "Watch the committee hearing here." linked to `hearing.videoURL` — hidden if no video
- **Watch link**: "Watch the committee hearing here." linked to `hearing.videoURLs` — hidden if no videos

Since ballot questions are always under SJ42 and typically have one hearing, render a single hearing block. If there are multiple, render them in reverse chronological order (most recent first).

**Hearing data model recap:**

- `bill.hearingIds?: string[]` — event IDs; doc path is `/events/hearing-{id}`
- `bill.nextHearingAt?: Timestamp` — convenience field for upcoming hearing only (not sufficient alone — we need date + videoURL from the full document)
- `hearing.videoURL?: string` — link for the "Watch" CTA
- `bill.nextHearingAt?: Timestamp` — convenience field for upcoming hearing only (not sufficient alone — we need date + videoURLs from the full document)
- `hearing.videoURLs: string[]` — link for the "Watch" CTA
- `hearing.content.startsAt` — determines "Occurred" vs. "Scheduled" status

No new components are needed for hearing display — build a simple `CommitteeHearing` component local to `components/ballotquestions/`.
Expand Down
2 changes: 2 additions & 0 deletions functions/src/bills/updateBillReferences.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ function createHearing(
type: "hearing",
startsAt,
fetchedAt: Timestamp.fromMillis(Date.now()),
videos: [],
transcriptionIds: [],
content: {
EventId: 1,
EventDate: "2026-02-01T10:00:00",
Expand Down
Loading
Loading