Skip to content

Commit b9795b4

Browse files
committed
fix: Fixing getNotificationStartDate to also fetch the previous start of a notification period, not simply the date X days prior to the scheduled digest. This should be more resilient to data errors going forward. Includes unit tests for getNotificationStartDate
1 parent 08f53c9 commit b9795b4

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

functions/src/notifications/helpers.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getNextDigestAt } from "./helpers"
1+
import { getNextDigestAt, getNotificationStartDate } from "./helpers"
22
import { Timestamp } from "../firebase"
33
import { Frequency } from "../auth/types"
44

@@ -80,3 +80,21 @@ describe("getNextDigestAt", () => {
8080
consoleSpy.mockRestore()
8181
})
8282
})
83+
84+
describe("getNotificationStartDate", () => {
85+
it("should return the previous Tuesday for weekly frequency", () => {
86+
const fixedDate = Timestamp.fromDate(new Date(2025, 2, 11))
87+
const expectedDate = Timestamp.fromDate(new Date(2025, 2, 4))
88+
89+
const result = getNotificationStartDate("Weekly", fixedDate)
90+
expect(result).toEqual(expectedDate)
91+
})
92+
93+
it("should return the previous 1st of the month for monthly frequency", () => {
94+
const fixedDate = Timestamp.fromDate(new Date(2025, 2, 1))
95+
const expectedDate = Timestamp.fromDate(new Date(2025, 1, 1))
96+
97+
const result = getNotificationStartDate("Monthly", fixedDate)
98+
expect(result).toEqual(expectedDate)
99+
})
100+
})

functions/src/notifications/helpers.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import { Timestamp } from "../firebase"
22
import { Frequency } from "../auth/types"
3-
import { startOfDay, addDays, addMonths, setDay, setDate } from "date-fns"
3+
import {
4+
startOfDay,
5+
addMonths,
6+
setDate,
7+
previousTuesday,
8+
nextTuesday,
9+
subMonths
10+
} from "date-fns"
411

512
export const getNextDigestAt = (notificationFrequency: Frequency) => {
613
const now = startOfDay(new Date())
714
let nextDigestAt = null
815
switch (notificationFrequency) {
916
case "Weekly":
10-
// Weekly notifications are sent on Tuesdays
11-
// - this should be the next available Tuesday
12-
const nextTuesday = setDay(now, 2, { weekStartsOn: 1 })
13-
nextDigestAt = Timestamp.fromDate(
14-
nextTuesday <= now ? addDays(nextTuesday, 7) : nextTuesday
15-
)
17+
nextDigestAt = Timestamp.fromDate(nextTuesday(now))
1618
break
1719
case "Monthly":
1820
// Monthly notifications are sent on the 1st of the month
@@ -30,21 +32,18 @@ export const getNextDigestAt = (notificationFrequency: Frequency) => {
3032
return nextDigestAt
3133
}
3234

33-
// TODO: Rewrite with date-fns for consistency
34-
// TODO: Unit tests
35+
// TODO: Get the stupid Firebase WARN logs out of the unit tests
3536
export const getNotificationStartDate = (
3637
notificationFrequency: Frequency,
3738
now: Timestamp
3839
) => {
3940
switch (notificationFrequency) {
4041
case "Weekly":
41-
const weekAgo = new Date(now.toDate())
42-
weekAgo.setDate(weekAgo.getDate() - 7)
43-
return Timestamp.fromDate(weekAgo)
42+
return Timestamp.fromDate(previousTuesday(now.toDate()))
4443
case "Monthly":
45-
const monthAgo = new Date(now.toDate())
46-
monthAgo.setMonth(monthAgo.getMonth() - 1)
47-
return Timestamp.fromDate(monthAgo)
44+
const firstOfMonth = setDate(now.toDate(), 1)
45+
const previousFirstOfMonth = subMonths(firstOfMonth, 1)
46+
return Timestamp.fromDate(previousFirstOfMonth)
4847
// We can safely fallthrough here because if the user has no notification frequency set,
4948
// we won't even send a notification
5049
default:

0 commit comments

Comments
 (0)