cadfa70e60
* #708 apply strictier linting rules and fix simple eslint bugs * #708 fix eslint errors relate to promise * #708 fix eslint import/no-extraneous-dependencies * #708 fix eslint errors of react-hook * #708 enable eslint check for typescript --------- Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
247 lines
6.7 KiB
TypeScript
247 lines
6.7 KiB
TypeScript
import CalendarApp from '@/components/Calendar/Calendar'
|
||
import * as calendarUtils from '@/components/Calendar/utils/calendarUtils'
|
||
import { updateSlotLabelVisibility } from '@/components/Calendar/utils/calendarUtils'
|
||
import EventPreviewModal from '@/features/Events/EventPreview'
|
||
import { CalendarEvent } from '@/features/Events/EventsTypes'
|
||
import * as SettingsSlice from '@/features/Settings/SettingsSlice'
|
||
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||
import { renderWithProviders } from '../../utils/Renderwithproviders'
|
||
|
||
describe('Calendar - Timezone Integration', () => {
|
||
const mockCalendarRef = { current: null }
|
||
|
||
const baseState = {
|
||
user: {
|
||
userData: {
|
||
sub: 'test',
|
||
email: 'test@test.com',
|
||
sid: 'testSid',
|
||
openpaasId: 'user1'
|
||
}
|
||
},
|
||
calendars: {
|
||
list: {
|
||
'user1/cal1': {
|
||
id: 'user1/cal1',
|
||
link: '/calendars/user1/cal1.json',
|
||
name: 'Test Calendar',
|
||
description: '',
|
||
color: '#33B679',
|
||
owner: { firstname: 'user1', emails: ['test@test.com'] },
|
||
visibility: 'public',
|
||
events: {}
|
||
}
|
||
},
|
||
timeZone: 'America/New_York',
|
||
pending: false
|
||
}
|
||
}
|
||
|
||
beforeEach(() => {
|
||
jest.clearAllMocks()
|
||
})
|
||
|
||
it('renders TimezoneSelector in week view', async () => {
|
||
renderWithProviders(
|
||
<CalendarApp calendarRef={mockCalendarRef} />,
|
||
baseState
|
||
)
|
||
|
||
// Look for timezone selector button (should show offset)
|
||
await waitFor(() => {
|
||
expect(screen.getByText(/UTC/)).toBeInTheDocument()
|
||
})
|
||
})
|
||
|
||
it('dispatches setTimeZone action when timezone is changed', async () => {
|
||
const setTimeZoneSpy = jest.spyOn(SettingsSlice, 'setTimeZone')
|
||
|
||
renderWithProviders(
|
||
<CalendarApp calendarRef={mockCalendarRef} />,
|
||
baseState
|
||
)
|
||
|
||
// Find and click timezone selector
|
||
await waitFor(() => {
|
||
const timezoneButton = screen.getByText(/UTC/i)
|
||
fireEvent.click(timezoneButton)
|
||
|
||
// Select a different timezone
|
||
const autocomplete = screen.getByRole('combobox')
|
||
fireEvent.change(autocomplete, { target: { value: 'Tokyo' } })
|
||
})
|
||
const option = await screen.findByText(/Tokyo/i)
|
||
fireEvent.click(option)
|
||
|
||
expect(setTimeZoneSpy).toHaveBeenCalledWith('Asia/Tokyo')
|
||
})
|
||
})
|
||
|
||
describe('Calendar - Timezone Slot Label Visibility', () => {
|
||
it('hides slot labels within 15 minutes of current time', () => {
|
||
const currentTime = new Date('2025-01-15T14:30:00Z')
|
||
const timezone = 'UTC'
|
||
jest
|
||
.spyOn(calendarUtils, 'checkIfCurrentWeekOrDay')
|
||
.mockImplementation(() => true)
|
||
|
||
// 14:25 - within 15 minutes
|
||
const slot1425 = { text: '14:25' }
|
||
expect(updateSlotLabelVisibility(currentTime, slot1425, timezone)).toBe(
|
||
'timegrid-slot-label-hidden'
|
||
)
|
||
|
||
// 14:30 - exact match
|
||
const slot1430 = { text: '14:30' }
|
||
expect(updateSlotLabelVisibility(currentTime, slot1430, timezone)).toBe(
|
||
'timegrid-slot-label-hidden'
|
||
)
|
||
|
||
// 14:35 - within 15 minutes
|
||
const slot1435 = { text: '14:35' }
|
||
expect(updateSlotLabelVisibility(currentTime, slot1435, timezone)).toBe(
|
||
'timegrid-slot-label-hidden'
|
||
)
|
||
})
|
||
|
||
it('shows slot labels more than 15 minutes from current time', () => {
|
||
jest
|
||
.spyOn(calendarUtils, 'checkIfCurrentWeekOrDay')
|
||
.mockImplementation(() => true)
|
||
|
||
const currentTime = new Date('2025-01-15T14:30:00')
|
||
const timezone = 'UTC'
|
||
|
||
// 14:00 - 30 minutes before
|
||
const slot1400 = { text: '14:00' }
|
||
expect(updateSlotLabelVisibility(currentTime, slot1400, timezone)).toBe(
|
||
'fc-timegrid-slot-label'
|
||
)
|
||
|
||
// 15:00 - 30 minutes after
|
||
const slot1500 = { text: '15:00' }
|
||
expect(updateSlotLabelVisibility(currentTime, slot1500, timezone)).toBe(
|
||
'fc-timegrid-slot-label'
|
||
)
|
||
})
|
||
|
||
it('returns visible class when not in current week/day', () => {
|
||
jest
|
||
.spyOn(calendarUtils, 'checkIfCurrentWeekOrDay')
|
||
.mockImplementation(() => false)
|
||
const currentTime = new Date('2025-01-15T14:30:00')
|
||
const timezone = 'UTC'
|
||
const slot = { text: '14:30' }
|
||
|
||
// Should return visible class when not in current view
|
||
const result = updateSlotLabelVisibility(currentTime, slot, timezone)
|
||
expect(result).toBe('fc-timegrid-slot-label')
|
||
})
|
||
})
|
||
|
||
describe('EventDisplayPreview - Timezone Display', () => {
|
||
const mockOnClose = jest.fn()
|
||
|
||
const baseEvent: CalendarEvent = {
|
||
uid: 'event1',
|
||
title: 'Team Meeting',
|
||
start: new Date('2025-01-15T14:00:00Z'),
|
||
end: new Date('2025-01-15T15:00:00Z'),
|
||
calendarId: 'user1/cal1',
|
||
allday: false
|
||
}
|
||
|
||
const allDayEvent = {
|
||
...baseEvent,
|
||
allday: true,
|
||
start: new Date('2025-01-15'),
|
||
end: new Date('2025-01-16')
|
||
}
|
||
|
||
const baseState = {
|
||
user: {
|
||
userData: {
|
||
sub: 'test',
|
||
email: 'test@test.com',
|
||
sid: 'testSid',
|
||
openpaasId: 'user1'
|
||
}
|
||
},
|
||
calendars: {
|
||
list: {
|
||
'user1/cal1': {
|
||
id: 'user1/cal1',
|
||
name: 'Test Calendar',
|
||
color: '#33B679',
|
||
owner: { firstname: 'user1', emails: ['test@test.com'] },
|
||
visibility: 'public',
|
||
events: {
|
||
event1: baseEvent,
|
||
allDayEvent
|
||
}
|
||
}
|
||
},
|
||
timeZone: 'America/New_York',
|
||
pending: false
|
||
}
|
||
}
|
||
|
||
beforeEach(() => {
|
||
jest.clearAllMocks()
|
||
})
|
||
|
||
it('does not show timezone offset for all-day events', async () => {
|
||
renderWithProviders(
|
||
<EventPreviewModal
|
||
open={true}
|
||
onClose={mockOnClose}
|
||
eventId="allDayEvent"
|
||
calId="user1/cal1"
|
||
/>,
|
||
baseState
|
||
)
|
||
|
||
await waitFor(() => {
|
||
const title = screen.getByText(/Team Meeting/i)
|
||
expect(title).toBeInTheDocument()
|
||
})
|
||
|
||
// Should not show UTC offset
|
||
expect(screen.queryByText(/UTC[+-]\d+/i)).not.toBeInTheDocument()
|
||
})
|
||
|
||
it('displays correct timezone offset for different timezones', async () => {
|
||
const timezones = [
|
||
{ tz: 'America/New_York', expectedOffset: /UTC[-−][45]/ },
|
||
{ tz: 'Europe/Paris', expectedOffset: /UTC\+[12]/ },
|
||
{ tz: 'Asia/Tokyo', expectedOffset: /UTC\+9/ },
|
||
{ tz: 'Australia/Sydney', expectedOffset: /UTC\+1[01]/ },
|
||
{ tz: 'Asia/Kolkata', expectedOffset: /UTC\+5:30/ }
|
||
]
|
||
|
||
for (const { tz, expectedOffset } of timezones) {
|
||
const state = {
|
||
...baseState,
|
||
settings: {
|
||
timeZone: tz
|
||
}
|
||
}
|
||
|
||
renderWithProviders(
|
||
<EventPreviewModal
|
||
open={true}
|
||
eventId="event1"
|
||
calId="user1/cal1"
|
||
onClose={mockOnClose}
|
||
/>,
|
||
state
|
||
)
|
||
|
||
await waitFor(() => {
|
||
const content = document.body.textContent || ''
|
||
expect(content).toMatch(expectedOffset)
|
||
})
|
||
}
|
||
})
|
||
})
|