import googleCalendarPlugin from '@fullcalendar/google-calendar' import dayGridPlugin from '@fullcalendar/daygrid' import { DayGridViewWrapper } from '../lib/wrappers/DayGridViewWrapper.js' import { CalendarWrapper } from '../lib/wrappers/CalendarWrapper.js' // In our CI setup, requests to the google-calendar api were failing for some reason // (requests to other services were working however) const noGCal = (window as any).__karma__.config.cliArgs.includes('--no-gcal') if (noGCal) { console.log('skipping google-calendar') // eslint-disable-line no-console } // eslint-disable-next-line noGCal || describe('Google Calendar plugin', () => { const API_KEY = 'AIzaSyDcnW6WejpTOCffshGDDb4neIrXVUA1EAE' const HOLIDAY_CALENDAR_ID = 'en.usa#holiday@group.v.calendar.google.com' // Google sometimes stops returning old events. Will need to update this sometimes. const DEFAULT_MONTH = '2023-05' const NUM_EVENTS = 5 // number of holidays pushOptions({ plugins: [googleCalendarPlugin, dayGridPlugin], initialView: 'dayGridMonth', initialDate: DEFAULT_MONTH + '-01', }) it('request/receives correctly when local timezone', (done) => { let calendar = initCalendar({ googleCalendarApiKey: API_KEY, events: { googleCalendarId: HOLIDAY_CALENDAR_ID }, timeZone: 'local', }) afterEventsLoaded(calendar, () => { let events = calendar.getEvents() let i expect(events.length).toBe(NUM_EVENTS) for (i = 0; i < events.length; i += 1) { expect(events[i].url).not.toMatch('ctz=') } done() }) }) it('request/receives correctly when UTC timezone', (done) => { let calendar = initCalendar({ googleCalendarApiKey: API_KEY, events: { googleCalendarId: HOLIDAY_CALENDAR_ID }, timeZone: 'UTC', }) afterEventsLoaded(calendar, () => { let events = calendar.getEvents() let i expect(events.length).toBe(NUM_EVENTS) for (i = 0; i < events.length; i += 1) { expect(events[i].url).toMatch('ctz=UTC') } done() }) }) it('request/receives correctly when named timezone, defaults to not editable', (done) => { let calendar = initCalendar({ googleCalendarApiKey: API_KEY, events: { googleCalendarId: HOLIDAY_CALENDAR_ID }, timeZone: 'America/New_York', }) afterEventsLoaded(calendar, () => { let events = calendar.getEvents() let dayGridWrapper = new DayGridViewWrapper(calendar).dayGrid let eventEls = dayGridWrapper.getEventEls() let i expect(events.length).toBe(NUM_EVENTS) for (i = 0; i < events.length; i += 1) { expect(events[i].url).toMatch('ctz=America/New_York') } expect(eventEls.length).toBe(NUM_EVENTS) expect($('.' + CalendarWrapper.EVENT_RESIZER_CLASSNAME, eventEls[0]).length).toBe(0) // not editable done() }) }) it('allows editable to explicitly be set to true', (done) => { let calendar = initCalendar({ googleCalendarApiKey: API_KEY, events: { googleCalendarId: HOLIDAY_CALENDAR_ID, editable: true, }, }) afterEventsLoaded(calendar, () => { let dayGridWrapper = new DayGridViewWrapper(calendar).dayGrid let eventEls = dayGridWrapper.getEventEls() expect(eventEls.length).toBe(NUM_EVENTS) for (let eventEl of eventEls) { expect($('.' + CalendarWrapper.EVENT_RESIZER_CLASSNAME, eventEl).length).toBeGreaterThan(0) // editable! } done() }) }) it('fetches events correctly when API key is in the event source', (done) => { let calendar = initCalendar({ events: { googleCalendarId: HOLIDAY_CALENDAR_ID, googleCalendarApiKey: API_KEY, }, }) afterEventsLoaded(calendar, () => { let events = calendar.getEvents() expect(events.length).toBe(NUM_EVENTS) // 5 holidays in November 2016 (and end of Oct) done() }) }) describe('when not given an API key', () => { it('calls error handlers, raises warning, and receives no events', (done) => { let options = { events: { failure(err) { expect(typeof err).toBe('object') }, googleCalendarId: HOLIDAY_CALENDAR_ID, }, eventSourceFailure(err) { expect(typeof err).toBe('object') setTimeout(() => { // wait for potential render let events = this.getEvents() expect(events.length).toBe(0) expect(options.events.failure).toHaveBeenCalled() done() }, 0) }, } spyOn(options.events, 'failure').and.callThrough() initCalendar(options) }) }) describe('when given a bad API key', () => { it('calls error handlers, raises warning, and receives no event', (done) => { let options = { googleCalendarApiKey: 'asdfasdfasdf', events: { failure(err) { expect(typeof err).toBe('object') }, googleCalendarId: HOLIDAY_CALENDAR_ID, }, eventSourceFailure(err) { expect(typeof err).toBe('object') setTimeout(() => { // wait for potential render let events = this.getEvents() expect(events.length).toBe(0) expect(options.events.failure).toHaveBeenCalled() done() }, 0) }, } spyOn(options.events, 'failure').and.callThrough() initCalendar(options) }) }) it('calls loading with true then false', (done) => { let cmds = [] initCalendar({ googleCalendarApiKey: API_KEY, events: { googleCalendarId: HOLIDAY_CALENDAR_ID }, loading(bool) { cmds.push(bool) if (cmds.length === 1) { expect(cmds).toEqual([true]) } else if (cmds.length === 2) { expect(cmds).toEqual([true, false]) done() } }, }) }) describe('EventSource::remove', () => { it('works when specifying only the Google Calendar ID', (done) => { let called = false let calendar = initCalendar({ googleCalendarApiKey: API_KEY, eventSources: [{ googleCalendarId: HOLIDAY_CALENDAR_ID }], }) afterEventsLoaded(calendar, () => { let events if (called) { return } // only the first time called = true events = calendar.getEvents() expect(events.length).toBe(NUM_EVENTS) // 5 holidays in November 2016 (and end of Oct) setTimeout(() => { calendar.getEventSources()[0].remove() events = calendar.getEvents() expect(events.length).toBe(0) done() }, 0) }) }) it('works when specifying a raw Google Calendar source object', (done) => { let googleSource = { googleCalendarId: HOLIDAY_CALENDAR_ID } let called = false let calendar = initCalendar({ googleCalendarApiKey: API_KEY, eventSources: [googleSource], }) afterEventsLoaded(calendar, () => { let events if (called) { return } // only the first time called = true events = calendar.getEvents() expect(events.length).toBe(NUM_EVENTS) // 5 holidays in November 2016 (and end of Oct) setTimeout(() => { calendar.getEventSources()[0].remove() events = calendar.getEvents() expect(events.length).toBe(0) done() }, 0) }) }) }) function afterEventsLoaded(calendar, callback: () => void) { calendar.on('eventsSet', () => { setTimeout(callback) // because nothing is rendered yet when eventSourceSuccess fires }) } })