Skip to content
Merged
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
1 change: 1 addition & 0 deletions frontends/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@mitodl/course-search-utils": "^3.5.2",
"@mitodl/mitxonline-api-axios": "2026.5.28-1",
"@mitodl/smoot-design": "^6.27.0",
"@mui/base": "5.0.0-beta.70",
"@mui/material": "^6.4.5",
"@mui/material-nextjs": "^6.4.3",
"@opentelemetry/api": "^1.9.1",
Expand Down
83 changes: 83 additions & 0 deletions frontends/main/src/app-pages/HomePage/VideoShortsModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,89 @@ describe("VideoShortsModal", () => {
expect(slides.length).toBe(defaultProps.videoData.length)
})

test("overlay has dialog role and aria-modal attributes", () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

const dialog = screen.getByRole("dialog")
expect(dialog).toHaveAttribute("aria-modal", "true")
expect(dialog).toHaveAttribute("aria-label", "Video Shorts")
})

test("close button has aria-label Close", () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

expect(screen.getByRole("button", { name: "Close" })).toBeInTheDocument()
})

test("mute button receives focus on open", async () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

await act(async () => {
await new Promise((resolve) => requestAnimationFrame(resolve))
})

expect(screen.getByRole("button", { name: "Unmute" })).toHaveFocus()
})

test("mute button has correct aria-label reflecting muted state", async () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

expect(screen.getByRole("button", { name: "Unmute" })).toBeInTheDocument()

await user.click(screen.getByRole("button", { name: "Unmute" }))

expect(screen.getByRole("button", { name: "Mute" })).toBeInTheDocument()
})

test("play/pause button renders only for the selected slide", () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

// Only one play/pause button should exist — for the selected (first) slide
const playButtons = screen.getAllByRole("button", { name: /play|pause/i })
expect(playButtons).toHaveLength(1)
expect(playButtons[0]).toHaveAttribute("aria-label", "Play")
})

test("play/pause button updates aria-label when clicked", async () => {
const videoData = [makeVideoResource({ title: "Test Video" })]
renderWithProviders(
<VideoShortsModal
startIndex={0}
videoData={videoData}
onClose={jest.fn()}
/>,
)

await act(async () => {
mockHandles[0]?.triggerReady()
})

const handle = mockHandles[0]
handle.player.paused.mockReturnValue(true)

const playButton = screen.getByRole("button", { name: "Play" })
await user.click(playButton)

expect(handle.player.play).toHaveBeenCalled()
await screen.findByRole("button", { name: "Pause" })
})
Comment thread
daniellefrappier18 marked this conversation as resolved.

test("Enter key on selected slide triggers play/pause", async () => {
renderWithProviders(<VideoShortsModal {...defaultProps} />)

await act(async () => {
mockHandles[0]?.triggerReady()
})

const handle = mockHandles[0]
handle.player.paused.mockReturnValue(true)

const slide = document.querySelector("[data-index='0']")!
fireEvent.keyDown(slide, { key: "Enter" })

expect(handle.player.play).toHaveBeenCalled()
})

test("handles empty videoData gracefully", () => {
renderWithProviders(
<VideoShortsModal startIndex={0} videoData={[]} onClose={jest.fn()} />,
Expand Down
Loading
Loading