Skip to content

Commit 89b2582

Browse files
committed
test: add comprehensive unit tests for the MeetingDetail component
1 parent 1e7e0cf commit 89b2582

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import React from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import "@testing-library/jest-dom";
4+
import MeetingDetail from "./MeetingDetail";
5+
import { BrowserRouter } from "react-router";
6+
import { vi } from "vitest";
7+
import { IMeeting } from "@/types/sessions";
8+
import { ISpeaker } from "@/types/speakers";
9+
10+
// Mock framer-motion
11+
vi.mock("framer-motion", () => ({
12+
motion: {
13+
div: ({
14+
children,
15+
...props
16+
}: {
17+
children: React.ReactNode;
18+
[key: string]: unknown;
19+
}) => <div {...props}>{children}</div>,
20+
img: (props: { [key: string]: unknown }) => <img {...props} />,
21+
},
22+
}));
23+
24+
// Mock add-to-calendar-button-react
25+
vi.mock("add-to-calendar-button-react", () => ({
26+
AddToCalendarButton: () => (
27+
<button data-testid="add-to-calendar">Add to Calendar</button>
28+
),
29+
}));
30+
31+
// Mock useWindowSize
32+
vi.mock("react-use", () => ({
33+
useWindowSize: () => ({ width: 1200, height: 800 }),
34+
}));
35+
36+
const mockMeeting: IMeeting = {
37+
id: 12345,
38+
title: "Test Talk Title",
39+
description: "This is a test talk description with important content.",
40+
videoUrl: "https://www.youtube.com/embed/test123",
41+
slidesURL: "https://slides.example.com/test",
42+
videoTags: ["React", "TypeScript", "Testing"],
43+
speakers: [
44+
{ id: "speaker-1", name: "John Doe" },
45+
{ id: "speaker-2", name: "Jane Smith" },
46+
],
47+
level: "Intermediate",
48+
type: "Talk",
49+
language: "English",
50+
track: "Frontend",
51+
startDate: "2024-06-17",
52+
endDate: "2024-06-17",
53+
startTime: "10:00",
54+
endTime: "11:00",
55+
};
56+
57+
const mockSpeakers: ISpeaker[] = [
58+
{
59+
id: "speaker-1",
60+
fullName: "John Doe",
61+
speakerImage: "/images/speakers/john.jpg",
62+
bio: "Test bio",
63+
tagLine: "Test tagline",
64+
sessions: [],
65+
links: [],
66+
},
67+
{
68+
id: "speaker-2",
69+
fullName: "Jane Smith",
70+
speakerImage: "/images/speakers/jane.jpg",
71+
bio: "Test bio 2",
72+
tagLine: "Test tagline 2",
73+
sessions: [],
74+
links: [],
75+
},
76+
];
77+
78+
const renderMeetingDetail = (
79+
meeting: Partial<IMeeting> = {},
80+
speakers: ISpeaker[] = mockSpeakers
81+
) => {
82+
return render(
83+
<BrowserRouter>
84+
<MeetingDetail
85+
meeting={{ ...mockMeeting, ...meeting }}
86+
speakers={speakers}
87+
openFeedbackId="test-feedback-id"
88+
/>
89+
</BrowserRouter>
90+
);
91+
};
92+
93+
describe("MeetingDetail", () => {
94+
it("renders the meeting title", () => {
95+
renderMeetingDetail();
96+
expect(screen.getByText(/Test Talk Title/)).toBeInTheDocument();
97+
});
98+
99+
it("renders the meeting description", () => {
100+
renderMeetingDetail();
101+
expect(
102+
screen.getByText(/This is a test talk description/)
103+
).toBeInTheDocument();
104+
});
105+
106+
it("renders speaker names with links", () => {
107+
renderMeetingDetail();
108+
expect(screen.getByText("John Doe")).toBeInTheDocument();
109+
expect(screen.getByText("Jane Smith")).toBeInTheDocument();
110+
});
111+
112+
it("renders speaker images", () => {
113+
renderMeetingDetail();
114+
const speakerImages = screen.getAllByRole("img", { name: /John Doe|Jane Smith/ });
115+
expect(speakerImages).toHaveLength(2);
116+
});
117+
118+
it("renders vote talk link with correct href", () => {
119+
renderMeetingDetail();
120+
const voteLink = screen.getByText(/Vote this talk/).closest("a");
121+
expect(voteLink).toHaveAttribute(
122+
"href",
123+
"https://openfeedback.io/test-feedback-id/0/12345"
124+
);
125+
});
126+
127+
it("renders video iframe when videoUrl is provided", () => {
128+
renderMeetingDetail();
129+
const iframe = screen.getByTitle("Test Talk Title");
130+
expect(iframe).toBeInTheDocument();
131+
expect(iframe).toHaveAttribute(
132+
"src",
133+
"https://www.youtube.com/embed/test123"
134+
);
135+
});
136+
137+
it("does not render video iframe when videoUrl is empty", () => {
138+
renderMeetingDetail({ videoUrl: undefined });
139+
expect(screen.queryByTitle("Test Talk Title")).not.toBeInTheDocument();
140+
});
141+
142+
it("renders slides link when slidesURL is provided", () => {
143+
renderMeetingDetail();
144+
const slidesLink = screen.getByText(/Session Slides/).closest("a");
145+
expect(slidesLink).toHaveAttribute(
146+
"href",
147+
"https://slides.example.com/test"
148+
);
149+
});
150+
151+
it("does not render slides link when slidesURL is empty", () => {
152+
renderMeetingDetail({ slidesURL: "" });
153+
expect(screen.queryByText(/Session Slides/)).not.toBeInTheDocument();
154+
});
155+
156+
it("renders video tags", () => {
157+
renderMeetingDetail();
158+
expect(screen.getByText("React")).toBeInTheDocument();
159+
expect(screen.getByText("TypeScript")).toBeInTheDocument();
160+
expect(screen.getByText("Testing")).toBeInTheDocument();
161+
});
162+
163+
it("renders track information", () => {
164+
renderMeetingDetail();
165+
expect(screen.getByText(/Track:/)).toBeInTheDocument();
166+
expect(screen.getByText(/Frontend/)).toBeInTheDocument();
167+
});
168+
169+
it("renders level and type information", () => {
170+
renderMeetingDetail();
171+
expect(screen.getByText(/Talk Intermediate/)).toBeInTheDocument();
172+
});
173+
174+
it("renders go back link", () => {
175+
renderMeetingDetail();
176+
const backLink = screen.getByText("Go back");
177+
expect(backLink).toBeInTheDocument();
178+
expect(backLink.closest("a")).toHaveAttribute("href", "/talks");
179+
});
180+
181+
it("renders add to calendar button", () => {
182+
renderMeetingDetail();
183+
expect(screen.getByTestId("add-to-calendar")).toBeInTheDocument();
184+
});
185+
});

0 commit comments

Comments
 (0)