Skip to content
173 changes: 149 additions & 24 deletions web/src/features/sfmsInsights/pages/SFMSInsightsPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ vi.mock('@/features/sfmsInsights/components/RasterTypeDropdown', () => ({
)
}))

// Create spies for local storage
const setItemSpy = vi.spyOn(Storage.prototype, 'setItem')
const getItemSpy = vi.spyOn(Storage.prototype, 'getItem')

describe('SFMSInsightsPage', () => {
const dateTimeNow = DateTime.fromISO('2025-11-02')
const dateTimeNowPlusTen = dateTimeNow.plus({ days: 10 })
Expand Down Expand Up @@ -146,7 +150,8 @@ describe('SFMSInsightsPage', () => {
}
}

const renderWithStore = (sfmsBounds?: any) => {
const renderWithStore = (hideModal: string, sfmsBounds?: any) => {
getItemSpy.mockReturnValue(hideModal)
const store = createTestStore({
authentication: defaultAuthentication,
runDates: {
Expand Down Expand Up @@ -196,10 +201,13 @@ describe('SFMSInsightsPage', () => {
}
}
})
localStorage.clear()
getItemSpy.mockClear()
setItemSpy.mockClear()
})

it('should load rasterDate from SFMS bounds in store', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

// Verify that the rasterDate was set from the sfmsBounds in the store
Expand All @@ -209,7 +217,7 @@ describe('SFMSInsightsPage', () => {
})

it('should set date picker max date based on SFMS bounds', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

// The date picker should be rendered with max date from SFMS bounds (2025-11-02)
Expand All @@ -218,21 +226,21 @@ describe('SFMSInsightsPage', () => {
})

it('should render the snow checkbox', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()
const checkbox = screen.getByRole('checkbox', { name: /show latest snow/i })
expect(checkbox).toBeInTheDocument()
})

it('should have the snow checkbox checked by default', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()
const checkbox = screen.getByRole('checkbox', { name: /show latest snow/i }) as HTMLInputElement
expect(checkbox.checked).toBe(true)
})

it('should toggle snow checkbox when clicked', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const checkbox = screen.getByRole('checkbox', { name: /show latest snow/i }) as HTMLInputElement
Expand All @@ -246,15 +254,15 @@ describe('SFMSInsightsPage', () => {
})

it('should pass showSnow prop to SFMSMap when checkbox is checked', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const map = screen.getByTestId('sfms-map')
expect(map).toHaveAttribute('data-show-snow', 'true')
})

it('should pass showSnow=false to SFMSMap when checkbox is unchecked', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const checkbox = screen.getByRole('checkbox', { name: /show latest snow/i })
Expand All @@ -267,7 +275,7 @@ describe('SFMSInsightsPage', () => {
})

it('should render raster type dropdown next to snow checkbox', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const rasterDropdown = screen.getByTestId('raster-type-dropdown')
Expand All @@ -278,14 +286,14 @@ describe('SFMSInsightsPage', () => {
})

it('should fetch snow data on mount with initial rasterDate', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

expect(getMostRecentProcessedSnowByDate).toHaveBeenCalledWith(DateTime.fromISO('2025-11-02'))
})

it('should pass fetched snow date to SFMSMap', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const map = screen.getByTestId('sfms-map')
Expand All @@ -294,7 +302,7 @@ describe('SFMSInsightsPage', () => {
})

it('should display snow date in checkbox label when available', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const checkbox = screen.getByRole('checkbox', { name: /show latest snow: nov 2, 2025/i })
Expand All @@ -304,7 +312,7 @@ describe('SFMSInsightsPage', () => {
it('should display "Show Latest Snow" without date when no snow data available', async () => {
;(getMostRecentProcessedSnowByDate as Mock).mockResolvedValue(null)

renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const checkbox = screen.getByRole('checkbox', { name: 'Show Latest Snow' })
Expand All @@ -324,7 +332,7 @@ describe('SFMSInsightsPage', () => {
snowSource: 'viirs'
})

renderWithStore()
renderWithStore('true')
await waitForPageLoad()

// Wait for initial fetch
Expand All @@ -349,23 +357,23 @@ describe('SFMSInsightsPage', () => {
})

it('should set maxDate from latestSFMSBounds.maximum', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const maxDate = screen.getByTestId('historical-max-date')
expect(maxDate.textContent).toBe(dateTimeNowPlusTen.toISODate())
})

it('should set minDate from earliestSFMSBounds.minimum', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const minDate = screen.getByTestId('historical-min-date')
expect(minDate.textContent).toBe('2024-01-01')
})

it('should pass both min and max dates to ASADatePicker', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const minDate = screen.getByTestId('current-year-min-date')
Expand All @@ -376,7 +384,7 @@ describe('SFMSInsightsPage', () => {
})

it('should update min bounds when latestBounds changes', async () => {
renderWithStore({
renderWithStore('true', {
'2025': {
forecast: {
minimum: '2025-05-01',
Expand All @@ -394,7 +402,7 @@ describe('SFMSInsightsPage', () => {
// Mock getSFMSBounds to return null
;(getSFMSBounds as Mock).mockResolvedValueOnce({ sfms_bounds: null })

renderWithStore(null)
renderWithStore('true', null)

// Wait for fetch to complete
await waitFor(() => {
Expand All @@ -413,7 +421,7 @@ describe('SFMSInsightsPage', () => {
})

it('should set rasterDate to today when latestBounds.maximum is empty', async () => {
renderWithStore({
renderWithStore('true', {
'2025': {
forecast: {
minimum: '2025-05-01',
Expand All @@ -435,7 +443,7 @@ describe('SFMSInsightsPage', () => {
})

it('should not set minDate when earliestBounds.minimum is empty', async () => {
renderWithStore({
renderWithStore('true', {
'2025': {
forecast: {
minimum: '',
Expand All @@ -452,7 +460,7 @@ describe('SFMSInsightsPage', () => {
})

it('should set rasterDate to today when all years have empty maximum', async () => {
renderWithStore({
renderWithStore('true', {
'2024': {
forecast: {
minimum: '2024-01-01',
Expand Down Expand Up @@ -480,17 +488,134 @@ describe('SFMSInsightsPage', () => {
})

it('should disable raster dropdown options when no SFMS bounds data available', async () => {
renderWithStore(null)
renderWithStore('true', null)

const dropdown = screen.getByTestId('raster-type-dropdown')
expect(dropdown).toHaveAttribute('data-raster-data-available', 'false')
})

it('should enable raster dropdown options when SFMS bounds data available', async () => {
renderWithStore()
renderWithStore('true')
await waitForPageLoad()

const dropdown = screen.getByTestId('raster-type-dropdown')
expect(dropdown).toHaveAttribute('data-raster-data-available', 'true')
})

it('should display warning tooltip when rasterDate greater than March 8, 2026 and snowDate is March 8, 2026.', async () => {
;(getDateTimeNowPST as Mock).mockReturnValue(DateTime.fromISO('2026-03-10'))
;(getMostRecentProcessedSnowByDate as Mock).mockResolvedValue({
forDate: DateTime.fromISO('2026-03-08'),
processedDate: DateTime.fromISO('2025-03-09'),
snowSource: 'viirs'
})

renderWithStore('true')
await waitForPageLoad()

const warningIcon = screen.queryByTestId('WarningAmberIcon')
expect(warningIcon).toBeInTheDocument()
})

it('should not display warning tooltip when rasterDate equal to March 8, 2026 and snowDate is March 8, 2026.', async () => {
;(getDateTimeNowPST as Mock).mockReturnValue(DateTime.fromISO('2026-03-08'))
;(getMostRecentProcessedSnowByDate as Mock).mockResolvedValue({
forDate: DateTime.fromISO('2026-03-08'),
processedDate: DateTime.fromISO('2025-03-09'),
snowSource: 'viirs'
})

renderWithStore('true')
await waitForPageLoad()

const warningIcon = screen.queryByTestId('WarningAmberIcon')
expect(warningIcon).toBe(null)
})

it('should not display warning tooltip when rasterDate greater than March 8, 2026 and snowDate greater than March 8, 2026.', async () => {
;(getDateTimeNowPST as Mock).mockReturnValue(DateTime.fromISO('2026-03-09'))
;(getMostRecentProcessedSnowByDate as Mock).mockResolvedValue({
forDate: DateTime.fromISO('2026-03-10'),
processedDate: DateTime.fromISO('2025-03-09'),
snowSource: 'viirs'
})

renderWithStore('true')
await waitForPageLoad()

const warningIcon = screen.queryByTestId('WarningAmberIcon')
expect(warningIcon).toBe(null)
})

it('should not display warning tooltip when rasterDate less than March 8, 2026 and snowDate greater than March 8, 2026.', async () => {
;(getDateTimeNowPST as Mock).mockReturnValue(DateTime.fromISO('2026-03-07'))
;(getMostRecentProcessedSnowByDate as Mock).mockResolvedValue({
forDate: DateTime.fromISO('2026-03-10'),
processedDate: DateTime.fromISO('2025-03-09'),
snowSource: 'viirs'
})

renderWithStore('true')
await waitForPageLoad()

const warningIcon = screen.queryByTestId('WarningAmberIcon')
expect(warningIcon).toBe(null)
})

it("should display modal warning when user hasn't permanently dismissed", async () => {
renderWithStore('false')
await waitForPageLoad()
const modalHeading = screen.queryByText('Snow Coverage Imagery Warning')
expect(modalHeading).toBeInTheDocument()
})

it('should not display modal warning if user has permanently dismissed', async () => {
renderWithStore('true')
await waitForPageLoad()
const modalHeading = screen.queryByText('Snow Coverage Imagery Warning')
expect(modalHeading).not.toBeInTheDocument()
})

it('modal dismiss button should dismiss modal', async () => {
renderWithStore('false')
await waitForPageLoad()

const modalHeading = screen.queryByText('Snow Coverage Imagery Warning')
expect(modalHeading).toBeInTheDocument()

const dismissButton = screen.getByRole('button', { name: 'Dismiss' })
expect(dismissButton).toBeInTheDocument()

fireEvent.click(dismissButton)

await waitFor(() => {
const modalHeading = screen.queryByText('Snow Coverage Imagery Warning')
expect(modalHeading).not.toBeInTheDocument()
})
})

it("modal don't show again toggle should call localStorage.setItem", async () => {
renderWithStore('false')
await waitForPageLoad()

const checkbox = screen.getByRole('checkbox', { name: /don't show again/i })
expect(checkbox).toBeInTheDocument()
expect(checkbox).not.toBeChecked()

// Toggle checkbox on
fireEvent.click(checkbox)

await waitFor(() => {
expect(checkbox).toBeChecked()
expect(setItemSpy).toHaveBeenCalledWith('SFMSInsightsAlwaysHideSnowMessage', 'true')
})

// Toggle checkbox off
fireEvent.click(checkbox)

await waitFor(() => {
expect(checkbox).not.toBeChecked()
expect(setItemSpy).toHaveBeenCalledWith('SFMSInsightsAlwaysHideSnowMessage', 'false')
})
})
})
Loading
Loading