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( , 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( , 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( , 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( , state ) await waitFor(() => { const content = document.body.textContent || '' expect(content).toMatch(expectedOffset) }) } }) })