Skip to content

Commit b7a37a6

Browse files
committed
more tweaks
1 parent 5029178 commit b7a37a6

File tree

5 files changed

+300
-67
lines changed

5 files changed

+300
-67
lines changed

frontends/main/src/page-components/LearningResourceExpanded/InfoSection.test.tsx

Lines changed: 98 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,29 @@ import { formatRunDate } from "ol-utilities"
66
import invariant from "tiny-invariant"
77
import user from "@testing-library/user-event"
88
import { renderWithTheme } from "../../test-utils"
9+
import { factories } from "api/test-utils"
910

1011
// This is a pipe followed by a zero-width space
1112
const SEPARATOR = "|​"
1213

14+
// Helper function to create a date N days from today
15+
const daysFromToday = (days: number): string => {
16+
const date = new Date()
17+
date.setDate(date.getDate() + days)
18+
return date.toISOString()
19+
}
20+
21+
// Helper to format date as "Month DD, YYYY"
22+
const formatTestDate = (isoDate: string): string => {
23+
const date = new Date(isoDate)
24+
const options: Intl.DateTimeFormatOptions = {
25+
year: "numeric",
26+
month: "long",
27+
day: "2-digit",
28+
}
29+
return date.toLocaleDateString("en-US", options)
30+
}
31+
1332
describe("Learning resource info section pricing", () => {
1433
test("Free course, no certificate", () => {
1534
renderWithTheme(<InfoSection resource={courses.free.noCertificate} />)
@@ -118,65 +137,71 @@ describe("Learning resource info section start date", () => {
118137
test("Uses best_run_id when available", () => {
119138
const run = courses.free.dated.runs?.[0]
120139
invariant(run)
140+
const startDate = daysFromToday(30)
141+
const enrollmentStart = daysFromToday(15)
121142
const course = {
122143
...courses.free.dated,
123144
best_run_id: 1,
124145
runs: [
125146
{
126147
...run,
127148
id: 1,
128-
start_date: "2024-03-15",
129-
enrollment_start: "2024-03-01",
149+
start_date: startDate,
150+
enrollment_start: enrollmentStart,
130151
},
131152
],
132153
}
133154
renderWithTheme(<InfoSection resource={course} />)
134155

135156
const section = screen.getByTestId("drawer-info-items")
136157
within(section).getByText("Starts:")
137-
within(section).getByText("March 15, 2024")
158+
within(section).getByText(formatTestDate(startDate))
138159
})
139160

140-
test("Falls back to run date when best_run_id is null", () => {
161+
test("Shows run date when best_run_id matches a run", () => {
162+
const startDate = daysFromToday(45)
163+
const run = factories.learningResources.run({
164+
id: 1,
165+
start_date: startDate,
166+
enrollment_start: null,
167+
})
141168
const course = {
142169
...courses.free.dated,
143-
best_run_id: null,
170+
best_run_id: 1,
171+
runs: [run],
144172
}
145-
const run = course.runs?.[0]
146-
invariant(run)
147-
const runDate = formatRunDate(run, false)
148-
invariant(runDate)
149173
renderWithTheme(<InfoSection resource={course} />)
150174

151175
const section = screen.getByTestId("drawer-info-items")
152176
within(section).getByText("Starts:")
153-
within(section).getByText(runDate)
154-
expect(within(section).queryByText("March 15, 2024")).toBeNull()
177+
within(section).getByText(formatTestDate(startDate))
155178
})
156179

157180
test("Uses enrollment_start when it is later than start_date", () => {
158181
const run = courses.free.dated.runs?.[0]
159182
invariant(run)
183+
const startDate = daysFromToday(30)
184+
const enrollmentStart = daysFromToday(40) // Later than start_date
160185
const course = {
161186
...courses.free.dated,
162187
best_run_id: 1,
163188
runs: [
164189
{
165190
...run,
166191
id: 1,
167-
start_date: "2024-03-01",
168-
enrollment_start: "2024-03-15",
192+
start_date: startDate,
193+
enrollment_start: enrollmentStart,
169194
},
170195
],
171196
}
172197
renderWithTheme(<InfoSection resource={course} />)
173198

174199
const section = screen.getByTestId("drawer-info-items")
175200
within(section).getByText("Starts:")
176-
within(section).getByText("March 15, 2024")
201+
within(section).getByText(formatTestDate(enrollmentStart))
177202
})
178203

179-
test("Falls back to run date when best_run_id does not match any run", () => {
204+
test("Falls back to null when best_run_id does not match any run", () => {
180205
const course = {
181206
...courses.free.dated,
182207
best_run_id: 999,
@@ -192,34 +217,73 @@ describe("Learning resource info section start date", () => {
192217
within(section).getByText(runDate)
193218
})
194219

195-
test("Falls back to run date when best run has no dates", () => {
220+
test("Shows today's date when best run start date is in the past", () => {
196221
const run = courses.free.dated.runs?.[0]
197222
invariant(run)
223+
const pastStartDate = daysFromToday(-30) // 30 days ago
224+
const pastEnrollmentStart = daysFromToday(-45) // 45 days ago
225+
const todayDate = new Date().toISOString()
198226
const course = {
199227
...courses.free.dated,
200228
best_run_id: 1,
229+
runs: [
230+
{
231+
...run,
232+
id: 1,
233+
start_date: pastStartDate,
234+
enrollment_start: pastEnrollmentStart,
235+
},
236+
],
237+
}
238+
renderWithTheme(<InfoSection resource={course} />)
239+
240+
const section = screen.getByTestId("drawer-info-items")
241+
within(section).getByText("Starts:")
242+
within(section).getByText(formatTestDate(todayDate))
243+
})
244+
245+
test("Shows no start date when best_run_id is null", () => {
246+
const run = courses.free.dated.runs?.[0]
247+
invariant(run)
248+
const course = {
249+
...courses.free.dated,
250+
best_run_id: null,
201251
runs: [
202252
{
203253
...run,
204254
id: 1,
205255
start_date: null,
206256
enrollment_start: null,
207257
},
258+
],
259+
}
260+
renderWithTheme(<InfoSection resource={course} />)
261+
262+
const section = screen.getByTestId("drawer-info-items")
263+
// Should not show a start date section at all when best run is null and no dates exist
264+
expect(within(section).queryByText("Starts:")).toBeNull()
265+
})
266+
267+
test("Shows no start date when best run has null dates", () => {
268+
const run = courses.free.dated.runs?.[0]
269+
invariant(run)
270+
const course = {
271+
...courses.free.dated,
272+
best_run_id: 1,
273+
runs: [
208274
{
209275
...run,
210-
id: 2,
211-
start_date: "2024-05-01",
276+
id: 1,
277+
start_date: null,
212278
enrollment_start: null,
213279
},
214280
],
215281
}
216-
const runDate = formatRunDate(course.runs[1], false)
217-
invariant(runDate)
218282
renderWithTheme(<InfoSection resource={course} />)
219283

220284
const section = screen.getByTestId("drawer-info-items")
221-
within(section).getByText("Starts:")
222-
within(section).getByText(runDate)
285+
// Should not show a start date section when best run has null dates
286+
expect(within(section).queryByText("Starts:")).toBeNull()
223287
})
224288

225289
test("As taught in date(s)", () => {
@@ -261,15 +325,17 @@ describe("Learning resource info section start date", () => {
261325
test("Multiple run dates with best_run_id uses best_run_id as first date", () => {
262326
const firstRun = courses.multipleRuns.sameData.runs?.[0]
263327
invariant(firstRun)
328+
const bestRunStartDate = daysFromToday(50)
329+
const bestRunEnrollmentStart = daysFromToday(35)
264330
const course = {
265331
...courses.multipleRuns.sameData,
266332
best_run_id: 1,
267333
runs: [
268334
{
269335
...firstRun,
270336
id: 1,
271-
start_date: "2024-01-15",
272-
enrollment_start: "2024-01-01",
337+
start_date: bestRunStartDate,
338+
enrollment_start: bestRunEnrollmentStart,
273339
},
274340
...(courses.multipleRuns.sameData.runs?.slice(1) ?? []),
275341
],
@@ -285,7 +351,7 @@ describe("Learning resource info section start date", () => {
285351
.filter((date) => date !== null)
286352

287353
// First date should be from best_run_id, second should be original second date
288-
const expectedDateText = `January 15, 2024${SEPARATOR}${sortedDates?.[1]}Show more`
354+
const expectedDateText = `${formatTestDate(bestRunStartDate)}${SEPARATOR}${sortedDates?.[1]}Show more`
289355
renderWithTheme(<InfoSection resource={course} />)
290356

291357
const section = screen.getByTestId("drawer-info-items")
@@ -319,15 +385,17 @@ describe("Learning resource info section start date", () => {
319385
test("Anytime courses with best_run_id should not replace first date in 'As taught in' section", () => {
320386
const firstRun = courses.free.anytime.runs?.[0]
321387
invariant(firstRun)
388+
const bestRunStartDate = daysFromToday(25)
389+
const bestRunEnrollmentStart = daysFromToday(10)
322390
const course = {
323391
...courses.free.anytime,
324392
best_run_id: 1,
325393
runs: [
326394
{
327395
...firstRun,
328396
id: 1,
329-
start_date: "2024-03-15",
330-
enrollment_start: "2024-03-01",
397+
start_date: bestRunStartDate,
398+
enrollment_start: bestRunEnrollmentStart,
331399
},
332400
],
333401
}
@@ -341,7 +409,9 @@ describe("Learning resource info section start date", () => {
341409

342410
within(section).getByText("As taught in:")
343411

344-
expect(within(section).queryByText("March 15, 2024")).toBeNull()
412+
expect(
413+
within(section).queryByText(formatTestDate(bestRunStartDate)),
414+
).toBeNull()
345415

346416
const runDates = within(section).getByTestId("drawer-run-dates")
347417
expect(runDates).toBeInTheDocument()

frontends/main/src/page-components/LearningResourceExpanded/InfoSection.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ const totalRunsWithDates = (resource: LearningResource) => {
182182
const RunDates: React.FC<{ resource: LearningResource }> = ({ resource }) => {
183183
const [showingMore, setShowingMore] = useState(false)
184184
const anytime = showStartAnytime(resource)
185+
185186
let sortedDates = resource.runs
186187
?.sort((a, b) => {
187188
if (a?.start_date && b?.start_date) {
@@ -202,7 +203,7 @@ const RunDates: React.FC<{ resource: LearningResource }> = ({ resource }) => {
202203
sortedDates = [bestStartDate, ...sortedDates.slice(1)]
203204
}
204205
if (!sortedDates || sortedDates.length === 0) {
205-
return null
206+
return [bestStartDate]
206207
}
207208
const totalDates = sortedDates?.length || 0
208209
const showMore = totalDates > 2

0 commit comments

Comments
 (0)