-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into timeout-faq
- Loading branch information
Showing
30 changed files
with
1,357 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { describe, it, expect, vi, beforeEach } from "vitest"; | ||
import { getSystemNotifs } from "./getSystemNotifs"; | ||
import * as util from "shared-utils"; | ||
|
||
vi.mock("shared-utils", () => ({ | ||
getExport: vi.fn(), | ||
getSecret: vi.fn(), | ||
})); | ||
|
||
describe("notif handler", () => { | ||
beforeEach(() => { | ||
vi.resetAllMocks(); | ||
}); | ||
|
||
it("returns 200 and notifs if secret exists", async () => { | ||
vi.stubEnv("notificationSecretArn", "test_secret"); | ||
vi.spyOn(util, "getSecret").mockImplementation(async () => "[]"); | ||
const result = await getSystemNotifs(); | ||
expect(result.statusCode).toBe(200); | ||
expect(result.body).toBe("[]"); | ||
}); | ||
|
||
it("returns 200 and empty array if no notifs", async () => { | ||
vi.stubEnv("notificationSecretArn", "test_secret"); | ||
vi.spyOn(util, "getSecret").mockImplementation(async () => null as unknown as string); | ||
const result = await getSystemNotifs(); | ||
expect(result.statusCode).toBe(200); | ||
expect(result.body).toBe("[]"); | ||
}); | ||
|
||
it("returns 502 with specific error", async () => { | ||
vi.stubEnv("notificationSecretArn", "error"); | ||
vi.spyOn(util, "getSecret").mockImplementation(async () => { | ||
throw new Error("test error"); | ||
}); | ||
const result = await getSystemNotifs(); | ||
expect(result.statusCode).toBe(502); | ||
expect(JSON.parse(result.body).error).toBe("test error"); | ||
}); | ||
|
||
it("returns 502 with generic error", async () => { | ||
vi.stubEnv("notificationSecretArn", undefined); | ||
vi.spyOn(util, "getSecret").mockImplementation(async () => { | ||
throw new Error(); | ||
}); | ||
const result = await getSystemNotifs(); | ||
expect(result.statusCode).toBe(502); | ||
expect(JSON.parse(result.body).error).toBe("Internal server error"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { getSecret } from "shared-utils"; | ||
import { response } from "libs/handler-lib"; | ||
|
||
export const getSystemNotifs = async () => { | ||
try { | ||
const notifs = await getSecret(process.env.notificationSecretArn!); | ||
|
||
return response({ | ||
statusCode: 200, | ||
body: JSON.parse(notifs) || [], | ||
}); | ||
} catch (error: any) { | ||
console.error("Error:", error); | ||
return response({ | ||
statusCode: 502, | ||
body: { | ||
error: error.message ? error.message : "Internal server error", | ||
}, | ||
}); | ||
} | ||
}; | ||
|
||
export const handler = getSystemNotifs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export interface BannerNotification { | ||
notifId: string; | ||
header: string; | ||
body: string; | ||
buttonText?: string; | ||
buttonLink?: string; | ||
pubDate: string; | ||
expDate?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,54 @@ | ||
import moment from "moment-timezone"; | ||
import * as fedHolidays from "@18f/us-federal-holidays"; | ||
import { TZDate } from "@date-fns/tz"; | ||
import { UTCDate } from "@date-fns/utc"; | ||
import { format, startOfDay, isWeekend, addDays } from "date-fns"; | ||
import { isAHoliday } from "@18f/us-federal-holidays"; | ||
|
||
// Takes a local epoch for a moment in time, and returns the UTC epoch for that same moment | ||
export const offsetToUtc = (date: Date): Date => { | ||
return new Date(date.getTime() - date.getTimezoneOffset() * 60000); | ||
/** | ||
* Returns the epoch timestamp for midnight UTC time for the date provided. | ||
* If no date is provided, it returns the timestamp of midnight UTC time today. | ||
* | ||
* @param date the date object or date string to return the timestamp for | ||
* @returns epoch timestamp for midnight UTC of the date or today, if none provided | ||
*/ | ||
export const seaToolFriendlyTimestamp = (date?: Date | string): number => { | ||
const utcDate = date ? new UTCDate(date) : new UTCDate(); | ||
return startOfDay(utcDate).getTime(); | ||
}; | ||
|
||
// Takes a UTC epoch for a moment in time, and returns the local epoch for that same moment | ||
export const offsetFromUtc = (date: Date): Date => { | ||
return new Date(date.getTime() + date.getTimezoneOffset() * 60000); | ||
}; | ||
|
||
// This creates a Date for midnight today, then accounts for timezone offset. | ||
export const seaToolFriendlyTimestamp = (date?: Date): number => { | ||
// If you don't pass a date, we assume you want today the timestamp for today, midnight, utc. | ||
if (!date) { | ||
date = new Date(); | ||
date.setHours(0, 0, 0, 0); | ||
} | ||
return offsetToUtc(date).getTime(); | ||
}; | ||
|
||
// This takes an epoch string and converts it to a standard format for display | ||
export const formatSeatoolDate = (date: string): string => { | ||
return moment(date).tz("UTC").format("MM/DD/yyyy"); | ||
/** | ||
* Returns the formatted date string of the UTC timezone for the date provided. | ||
* If no date is provided, it returns an empty string. | ||
* | ||
* @param date the date object or date string to return the formatted time of | ||
* @returns the `MM/dd/yyyy` formatted date string for the UTC time of the date provided | ||
* or an empty string if no date was provided | ||
*/ | ||
export const formatSeatoolDate = (date?: Date | string): string => { | ||
if (!date) return ""; | ||
return format(new UTCDate(date), "MM/dd/yyyy"); | ||
}; | ||
|
||
/** | ||
* Returns the epoch timestamp for midnight UTC time for the date provided. | ||
* If no date is provided, it returns the timestamp of midnight UTC time today. | ||
* If the date is after 5pm Eastern time, it returns midnight UTC the next day. | ||
* If the date is on a federal holiday or weekend, it returns midnight UTC of the | ||
* next business day. | ||
* | ||
* @param date the date object to return the timestamp for | ||
* @returns epoch timestamp for midnight UTC of the date or today, if none provided | ||
*/ | ||
export const getNextBusinessDayTimestamp = (date: Date = new Date()): number => { | ||
const localeStringDate = date.toLocaleString("en-US", { | ||
timeZone: "America/New_York", | ||
dateStyle: "short", | ||
}); | ||
const localeStringHours24 = date.toLocaleString("en-US", { | ||
timeZone: "America/New_York", | ||
hour: "numeric", | ||
hour12: false, | ||
}); | ||
const localeDate = new Date(localeStringDate); | ||
const after5pmEST = parseInt(localeStringHours24, 10) >= 17; | ||
const isHoliday = fedHolidays.isAHoliday(localeDate); | ||
const isWeekend = !(localeDate.getDay() % 6); | ||
if (after5pmEST || isHoliday || isWeekend) { | ||
const nextDate = localeDate; | ||
nextDate.setDate(nextDate.getDate() + 1); | ||
nextDate.setHours(12, 0, 0, 0); | ||
return getNextBusinessDayTimestamp(nextDate); | ||
// Get the date in Eastern time | ||
const nyDateTime = new TZDate(date.toISOString(), "America/New_York"); | ||
|
||
// Check if the time is after 5pm Eastern time or if the day is not a business day. | ||
// If any of those are true, check again for the next day. | ||
if (nyDateTime.getHours() >= 17 || isAHoliday(nyDateTime) || isWeekend(nyDateTime)) { | ||
return getNextBusinessDayTimestamp(startOfDay(addDays(nyDateTime, 1))); | ||
} | ||
|
||
// Return the next business day's epoch for midnight UTC | ||
const ret = offsetToUtc(localeDate).getTime(); | ||
return ret; | ||
// If the date is a business day before 5pm Eastern time, return the timestamp | ||
// of midnight UTC on that day | ||
return startOfDay(new UTCDate(date)).getTime(); | ||
}; |
Oops, something went wrong.