/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* globals TodayPane */ var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm"); var { formatDate, formatTime } = ChromeUtils.import( "resource://testing-common/calendar/ItemEditingHelpers.jsm" ); XPCOMUtils.defineLazyModuleGetters(this, { CalDateTime: "resource:///modules/CalDateTime.jsm", CalEvent: "resource:///modules/CalEvent.jsm", CalRecurrenceInfo: "resource:///modules/CalRecurrenceInfo.jsm", }); let calendar = CalendarTestUtils.createCalendar(); Services.prefs.setIntPref("calendar.agenda.days", 7); registerCleanupFunction(() => { CalendarTestUtils.removeCalendar(calendar); Services.prefs.clearUserPref("calendar.agenda.days"); }); let today = cal.dtz.now(); let startHour = today.hour; today.hour = today.minute = today.second = 0; let todayPanePanel = document.getElementById("today-pane-panel"); let todayPaneStatusButton = document.getElementById("calendar-status-todaypane-button"); // Go to mail tab. selectFolderTab(); // Verify today pane open. if (todayPanePanel.hasAttribute("collapsed")) { EventUtils.synthesizeMouseAtCenter(todayPaneStatusButton, {}); } Assert.ok(!todayPanePanel.hasAttribute("collapsed"), "Today Pane is open"); // Verify today pane's date. Assert.equal(document.getElementById("datevalue-label").value, today.day, "Today Pane shows today"); async function addEvent(title, relativeStart, relativeEnd, isAllDay) { let event = new CalEvent(); event.id = cal.getUUID(); event.title = title; event.startDate = today.clone(); event.startDate.addDuration(cal.createDuration(relativeStart)); event.startDate.isDate = isAllDay; event.endDate = today.clone(); event.endDate.addDuration(cal.createDuration(relativeEnd)); event.endDate.isDate = isAllDay; return calendar.addItem(event); } function checkEvent(row, { dateHeader, time, title, relative, overlap, classes = [] }) { let dateHeaderElement = row.querySelector(".agenda-date-header"); if (dateHeader) { Assert.ok(BrowserTestUtils.is_visible(dateHeaderElement), "date header is visible"); if (dateHeader instanceof CalDateTime || dateHeader instanceof Ci.calIDateTime) { dateHeader = cal.dtz.formatter.formatDateLongWithoutYear(dateHeader); } Assert.equal(dateHeaderElement.textContent, dateHeader, "date header has correct value"); } else { Assert.ok(BrowserTestUtils.is_hidden(dateHeaderElement), "date header is hidden"); } let calendarElement = row.querySelector(".agenda-listitem-calendar"); let timeElement = row.querySelector(".agenda-listitem-time"); if (time) { Assert.ok(BrowserTestUtils.is_visible(calendarElement), "calendar is visible"); Assert.ok(BrowserTestUtils.is_visible(timeElement), "time is visible"); if (time instanceof CalDateTime || time instanceof Ci.calIDateTime) { time = cal.dtz.formatter.formatTime(time); } Assert.equal(timeElement.textContent, time, "time has correct value"); } else if (time === "") { Assert.ok(BrowserTestUtils.is_visible(calendarElement), "calendar is visible"); Assert.ok(BrowserTestUtils.is_hidden(timeElement), "time is hidden"); } else { Assert.ok(BrowserTestUtils.is_hidden(calendarElement), "calendar is hidden"); Assert.ok(BrowserTestUtils.is_hidden(timeElement), "time is hidden"); } let titleElement = row.querySelector(".agenda-listitem-title"); Assert.ok(BrowserTestUtils.is_visible(titleElement), "title is visible"); Assert.equal(titleElement.textContent, title, "title has correct value"); let relativeElement = row.querySelector(".agenda-listitem-relative"); if (Array.isArray(relative)) { Assert.ok(BrowserTestUtils.is_visible(relativeElement), "relative time is visible"); Assert.report( !relative.includes(relativeElement.textContent), relative, relativeElement.textContent, "relative time is correct", "includes" ); } else if (relative !== undefined) { Assert.ok(BrowserTestUtils.is_hidden(relativeElement), "relative time is hidden"); } let overlapElement = row.querySelector(".agenda-listitem-overlap"); if (overlap) { Assert.ok(BrowserTestUtils.is_visible(overlapElement), "overlap is visible"); Assert.equal( overlapElement.src, `chrome://messenger/skin/icons/new/event-${overlap}.svg`, "overlap has correct image" ); Assert.equal( overlapElement.dataset.l10nId, `calendar-editable-item-multiday-event-icon-${overlap}`, "overlap has correct alt text" ); } else { Assert.ok(BrowserTestUtils.is_hidden(overlapElement), "overlap is hidden"); } for (let className of classes) { Assert.ok(row.classList.contains(className), `row has ${className} class`); } } function checkEvents(...expectedEvents) { Assert.equal(TodayPane.agenda.rowCount, expectedEvents.length, "expected number of rows shown"); for (let i = 0; i < expectedEvents.length; i++) { Assert.ok(TodayPane.agenda.rows[i].getAttribute("is"), "agenda-listitem"); checkEvent(TodayPane.agenda.rows[i], expectedEvents[i]); } } add_task(async function testBasicAllDay() { let todaysEvent = await addEvent("Today's Event", "P0D", "P1D", true); checkEvents({ dateHeader: "Today", title: "Today's Event" }); let tomorrowsEvent = await addEvent("Tomorrow's Event", "P1D", "P2D", true); checkEvents( { dateHeader: "Today", title: "Today's Event" }, { dateHeader: "Tomorrow", title: "Tomorrow's Event" } ); let events = []; for (let i = 2; i < 7; i++) { events.push(await addEvent(`Event ${i + 1}`, `P${i}D`, `P${i + 1}D`, true)); checkEvents( { dateHeader: "Today", title: "Today's Event" }, { dateHeader: "Tomorrow", title: "Tomorrow's Event" }, ...events.map(e => { return { dateHeader: e.startDate, title: e.title }; }) ); } await calendar.deleteItem(todaysEvent); checkEvents( { dateHeader: "Tomorrow", title: "Tomorrow's Event" }, ...events.map(e => { return { dateHeader: e.startDate, title: e.title }; }) ); await calendar.deleteItem(tomorrowsEvent); checkEvents( ...events.map(e => { return { dateHeader: e.startDate, title: e.title }; }) ); while (events.length) { await calendar.deleteItem(events.shift()); checkEvents( ...events.map(e => { return { dateHeader: e.startDate, title: e.title }; }) ); } }); add_task(async function testBasic() { let time = today.clone(); time.hour = 23; let todaysEvent = await addEvent("Today's Event", "P0DT23H", "P1D"); checkEvents({ dateHeader: "Today", time, title: "Today's Event" }); let tomorrowsEvent = await addEvent("Tomorrow's Event", "P1DT23H", "P2D"); checkEvents( { dateHeader: "Today", time, title: "Today's Event" }, { dateHeader: "Tomorrow", time, title: "Tomorrow's Event" } ); let events = []; for (let i = 2; i < 7; i++) { events.push(await addEvent(`Event ${i + 1}`, `P${i}DT23H`, `P${i + 1}D`)); checkEvents( { dateHeader: "Today", time, title: "Today's Event" }, { dateHeader: "Tomorrow", time, title: "Tomorrow's Event" }, ...events.map(e => { return { dateHeader: e.startDate, time, title: e.title }; }) ); } await calendar.deleteItem(todaysEvent); checkEvents( { dateHeader: "Tomorrow", time, title: "Tomorrow's Event" }, ...events.map(e => { return { dateHeader: e.startDate, time, title: e.title }; }) ); await calendar.deleteItem(tomorrowsEvent); checkEvents( ...events.map(e => { return { dateHeader: e.startDate, time, title: e.title }; }) ); while (events.length) { await calendar.deleteItem(events.shift()); checkEvents( ...events.map(e => { return { dateHeader: e.startDate, time, title: e.title }; }) ); } }); /** * Adds and removes events in a different order from which they occur. * This checks that the events are inserted in the right place, and that the * date header is shown/hidden appropriately. */ add_task(async function testSortOrder() { let afternoonEvent = await addEvent("Afternoon Event", "P1DT13H", "P1DT17H"); checkEvents({ dateHeader: "Tomorrow", time: afternoonEvent.startDate, title: "Afternoon Event", }); let morningEvent = await addEvent("Morning Event", "P1DT8H", "P1DT12H"); checkEvents( { dateHeader: "Tomorrow", time: morningEvent.startDate, title: "Morning Event" }, { time: afternoonEvent.startDate, title: "Afternoon Event" } ); let allDayEvent = await addEvent("All Day Event", "P1D", "P2D", true); checkEvents( { dateHeader: "Tomorrow", title: "All Day Event" }, { time: morningEvent.startDate, title: "Morning Event" }, { time: afternoonEvent.startDate, title: "Afternoon Event" } ); let eveningEvent = await addEvent("Evening Event", "P1DT18H", "P1DT22H"); checkEvents( { dateHeader: "Tomorrow", title: "All Day Event" }, { time: morningEvent.startDate, title: "Morning Event" }, { time: afternoonEvent.startDate, title: "Afternoon Event" }, { time: eveningEvent.startDate, title: "Evening Event" } ); await calendar.deleteItem(afternoonEvent); checkEvents( { dateHeader: "Tomorrow", title: "All Day Event" }, { time: morningEvent.startDate, title: "Morning Event" }, { time: eveningEvent.startDate, title: "Evening Event" } ); await calendar.deleteItem(morningEvent); checkEvents( { dateHeader: "Tomorrow", title: "All Day Event" }, { time: eveningEvent.startDate, title: "Evening Event" } ); await calendar.deleteItem(allDayEvent); checkEvents({ dateHeader: "Tomorrow", time: eveningEvent.startDate, title: "Evening Event", }); await calendar.deleteItem(eveningEvent); checkEvents(); }); /** * Check events that begin and end on different days inside the date range. * All-day events are still sorted ahead of non-all-day events. */ add_task(async function testOverlapInside() { let allDayEvent = await addEvent("All Day Event", "P0D", "P2D", true); checkEvents( { dateHeader: "Today", title: "All Day Event", overlap: "start" }, { dateHeader: "Tomorrow", title: "All Day Event", overlap: "end" } ); let timedEvent = await addEvent("Timed Event", "P1H", "P1D23H"); checkEvents( { dateHeader: "Today", title: "All Day Event", overlap: "start" }, { time: timedEvent.startDate, title: "Timed Event", overlap: "start" }, { dateHeader: "Tomorrow", title: "All Day Event", overlap: "end" }, { time: timedEvent.endDate, title: "Timed Event", overlap: "end" } ); await calendar.deleteItem(allDayEvent); await calendar.deleteItem(timedEvent); }); /** * Check events that begin and end on different days and that end at midnight. * The list item for the end of the event should be the last one on the day * before the end midnight, and its time label should display "24:00". */ add_task(async function testOverlapEndAtMidnight() { // Start with an event that begins outside the displayed dates. let timedEvent = await addEvent("Timed Event", "-P1D", "P1D"); // Ends an hour before `timedEvent` to prove the ordering is correct. let duringEvent = await addEvent("During Event", "P22H", "P23H"); // Starts at the same time as `timedEvent` ends to prove the ordering is correct. let nextEvent = await addEvent("Next Event", "P1D", "P2D", true); checkEvents( { dateHeader: "Today", time: duringEvent.startDate, title: "During Event" }, { // Should show "24:00" as the time and end today. time: cal.dtz.formatter.formatTime(timedEvent.endDate, true), title: "Timed Event", overlap: "end", }, { dateHeader: "Tomorrow", title: "Next Event" } ); // Move the event fully into the displayed range. let timedClone = timedEvent.clone(); timedClone.startDate.day += 2; timedClone.endDate.day += 2; await calendar.modifyItem(timedClone, timedEvent); let duringClone = duringEvent.clone(); duringClone.startDate.day += 2; duringClone.endDate.day += 2; await calendar.modifyItem(duringClone, duringEvent); let nextClone = nextEvent.clone(); nextClone.startDate.day += 2; nextClone.endDate.day += 2; await calendar.modifyItem(nextClone, nextEvent); let realEndDate = today.clone(); realEndDate.day += 2; checkEvents( { dateHeader: "Tomorrow", time: timedClone.startDate, title: "Timed Event", overlap: "start", }, { dateHeader: realEndDate, time: duringClone.startDate, title: "During Event" }, { // Should show "24:00" as the time and end on the day after tomorrow. time: cal.dtz.formatter.formatTime(timedClone.endDate, true), title: "Timed Event", overlap: "end", }, { dateHeader: nextClone.startDate, title: "Next Event" } ); await calendar.deleteItem(timedClone); await calendar.deleteItem(duringClone); await calendar.deleteItem(nextClone); }); /** * Check events that begin and/or end outside the date range. Events that have * already started are listed as "Today", but still sorted by start time. * All-day events are still sorted ahead of non-all-day events. */ add_task(async function testOverlapOutside() { let before = await addEvent("Starts Before", "-P1D", "P1D", true); checkEvents({ dateHeader: "Today", title: "Starts Before", overlap: "end" }); let after = await addEvent("Ends After", "P0D", "P9D", true); checkEvents( { dateHeader: "Today", title: "Starts Before", overlap: "end" }, { title: "Ends After", overlap: "start" } ); let both = await addEvent("Beyond Start and End", "-P2D", "P9D", true); checkEvents( { dateHeader: "Today", title: "Beyond Start and End", overlap: "continue" }, { title: "Starts Before", overlap: "end" }, { title: "Ends After", overlap: "start" } ); // Change `before` to begin earlier than `both`. They should swap places. let startClone = before.clone(); startClone.startDate.day -= 2; await calendar.modifyItem(startClone, before); checkEvents( { dateHeader: "Today", title: "Starts Before", overlap: "end" }, { title: "Beyond Start and End", overlap: "continue" }, { title: "Ends After", overlap: "start" } ); let beforeWithTime = await addEvent("Starts Before with time", "-PT5H", "PT15H"); checkEvents( { dateHeader: "Today", title: "Starts Before", overlap: "end" }, { title: "Beyond Start and End", overlap: "continue" }, { title: "Ends After", overlap: "start" }, // This is the end of the event so the end time is used. { time: beforeWithTime.endDate, title: "Starts Before with time", overlap: "end" } ); let afterWithTime = await addEvent("Ends After with time", "PT6H", "P8DT12H"); checkEvents( { dateHeader: "Today", title: "Starts Before", overlap: "end" }, { title: "Beyond Start and End", overlap: "continue" }, { title: "Ends After", overlap: "start" }, { time: afterWithTime.startDate, title: "Ends After with time", overlap: "start" }, // This is the end of the event so the end time is used. { time: beforeWithTime.endDate, title: "Starts Before with time", overlap: "end" } ); let bothWithTime = await addEvent("Beyond Start and End with time", "-P2DT10H", "P9DT1H"); checkEvents( { dateHeader: "Today", title: "Starts Before", overlap: "end" }, { title: "Beyond Start and End", overlap: "continue" }, { title: "Ends After", overlap: "start" }, { time: "", title: "Beyond Start and End with time", overlap: "continue" }, { time: afterWithTime.startDate, title: "Ends After with time", overlap: "start" }, // This is the end of the event so the end time is used. { time: beforeWithTime.endDate, title: "Starts Before with time", overlap: "end" } ); await calendar.deleteItem(before); await calendar.deleteItem(after); await calendar.deleteItem(both); await calendar.deleteItem(beforeWithTime); await calendar.deleteItem(afterWithTime); await calendar.deleteItem(bothWithTime); }); /** * Checks that events that happened earlier today are marked as in the past, * and events happening now are marked as such. * * This test may fail if run within a minute either side of midnight. * * It would be nice to test that as time passes events are changed * appropriately, but that means waiting around for minutes and probably won't * be very reliable, so we don't do that. */ add_task(async function testActive() { let now = cal.dtz.now(); let pastEvent = await addEvent("Past Event", "PT0M", "PT1M"); let presentEvent = await addEvent("Present Event", `PT${now.hour}H`, `PT${now.hour + 1}H`); let futureEvent = await addEvent("Future Event", "PT23H59M", "PT24H"); checkEvents( { dateHeader: "Today", time: pastEvent.startDate, title: "Past Event" }, { time: presentEvent.startDate, title: "Present Event" }, { time: futureEvent.startDate, title: "Future Event" } ); let [pastRow, presentRow, futureRow] = TodayPane.agenda.rows; Assert.ok(pastRow.classList.contains("agenda-listitem-past"), "past event is marked past"); Assert.ok(!pastRow.classList.contains("agenda-listitem-now"), "past event is not marked now"); Assert.ok( !presentRow.classList.contains("agenda-listitem-past"), "present event is not marked past" ); Assert.ok(presentRow.classList.contains("agenda-listitem-now"), "present event is marked now"); Assert.ok( !futureRow.classList.contains("agenda-listitem-past"), "future event is not marked past" ); Assert.ok(!futureRow.classList.contains("agenda-listitem-now"), "future event is not marked now"); await calendar.deleteItem(pastEvent); await calendar.deleteItem(presentEvent); await calendar.deleteItem(futureEvent); }); /** * Checks events in different time zones are displayed correctly. */ add_task(async function testOtherTimeZones() { // Johannesburg is UTC+2. let johannesburg = cal.timezoneService.getTimezone("Africa/Johannesburg"); // Panama is UTC-5. let panama = cal.timezoneService.getTimezone("America/Panama"); // All-day events are displayed on the day of the event, the time zone is ignored. let allDayEvent = new CalEvent(); allDayEvent.id = cal.getUUID(); allDayEvent.title = "All-day event in Johannesburg"; allDayEvent.startDate = cal.createDateTime(); allDayEvent.startDate.resetTo(today.year, today.month, today.day + 1, 0, 0, 0, johannesburg); allDayEvent.startDate.isDate = true; allDayEvent.endDate = cal.createDateTime(); allDayEvent.endDate.resetTo(today.year, today.month, today.day + 2, 0, 0, 0, johannesburg); allDayEvent.endDate.isDate = true; allDayEvent = await calendar.addItem(allDayEvent); checkEvents({ dateHeader: "Tomorrow", title: "All-day event in Johannesburg", }); await calendar.deleteItem(allDayEvent); // The event time must be displayed in the local time zone, and the event must be sorted correctly. let beforeEvent = await addEvent("Before", "P1DT5H", "P1DT6H"); let afterEvent = await addEvent("After", "P1DT7H", "P1DT8H"); let timedEvent = new CalEvent(); timedEvent.id = cal.getUUID(); timedEvent.title = "Morning in Johannesburg"; timedEvent.startDate = cal.createDateTime(); timedEvent.startDate.resetTo(today.year, today.month, today.day + 1, 8, 0, 0, johannesburg); timedEvent.endDate = cal.createDateTime(); timedEvent.endDate.resetTo(today.year, today.month, today.day + 1, 12, 0, 0, johannesburg); timedEvent = await calendar.addItem(timedEvent); checkEvents( { dateHeader: "Tomorrow", time: beforeEvent.startDate, title: "Before", }, { time: cal.dtz.formatter.formatTime(cal.createDateTime("20000101T060000Z")), // The date used here is irrelevant. title: "Morning in Johannesburg", }, { time: afterEvent.startDate, title: "After", } ); Assert.stringContains( TodayPane.agenda.rows[1].querySelector(".agenda-listitem-time").getAttribute("datetime"), "T08:00:00+02:00" ); await calendar.deleteItem(beforeEvent); await calendar.deleteItem(afterEvent); await calendar.deleteItem(timedEvent); // Events that cross midnight in the local time zone (but not in the event time zone) // must have a start row and an end row. let overnightEvent = new CalEvent(); overnightEvent.id = cal.getUUID(); overnightEvent.title = "Evening in Panama"; overnightEvent.startDate = cal.createDateTime(); overnightEvent.startDate.resetTo(today.year, today.month, today.day, 17, 0, 0, panama); overnightEvent.endDate = cal.createDateTime(); overnightEvent.endDate.resetTo(today.year, today.month, today.day, 23, 0, 0, panama); overnightEvent = await calendar.addItem(overnightEvent); checkEvents( { dateHeader: "Today", time: cal.dtz.formatter.formatTime(cal.createDateTime("20000101T220000Z")), // The date used here is irrelevant. title: "Evening in Panama", overlap: "start", }, { dateHeader: "Tomorrow", time: cal.dtz.formatter.formatTime(cal.createDateTime("20000101T040000Z")), // The date used here is irrelevant. title: "Evening in Panama", overlap: "end", } ); Assert.stringContains( TodayPane.agenda.rows[0].querySelector(".agenda-listitem-time").getAttribute("datetime"), "T17:00:00-05:00" ); Assert.stringContains( TodayPane.agenda.rows[1].querySelector(".agenda-listitem-time").getAttribute("datetime"), "T23:00:00-05:00" ); await calendar.deleteItem(overnightEvent); }); /** * Checks events in different time zones are displayed correctly. */ add_task(async function testRelativeTime() { let formatter = new Intl.RelativeTimeFormat(undefined, { style: "short" }); let now = cal.dtz.now(); now.second = 0; info(`The time is now ${now}`); let testData = [ { name: "two hours ago", start: "-PT1H55M", expected: { classes: ["agenda-listitem-past"], }, minHour: 2, }, { name: "one hour ago", start: "-PT1H5M", expected: { classes: ["agenda-listitem-past"], }, minHour: 2, }, { name: "23 minutes ago", start: "-PT23M", expected: { classes: ["agenda-listitem-past"], }, minHour: 1, }, { name: "now", start: "-PT5M", expected: { relative: ["now"], classes: ["agenda-listitem-now"], }, minHour: 1, maxHour: 22, }, { name: "19 minutes ahead", start: "PT19M", expected: { relative: [formatter.format(19, "minute"), formatter.format(18, "minute")], }, maxHour: 22, }, { name: "one hour ahead", start: "PT1H25M", expected: { relative: [formatter.format(85, "minute"), formatter.format(84, "minute")], }, maxHour: 21, }, { name: "one and half hours ahead", start: "PT1H35M", expected: { relative: [formatter.format(2, "hour")], }, maxHour: 21, }, { name: "two hours ahead", start: "PT1H49M", expected: { relative: [formatter.format(2, "hour")], }, maxHour: 21, }, ]; let events = []; let expectedEvents = []; for (let { name, start, expected, minHour, maxHour } of testData) { if (minHour && now.hour < minHour) { info(`Skipping ${name} because it's too early.`); continue; } if (maxHour && now.hour > maxHour) { info(`Skipping ${name} because it's too late.`); continue; } let event = new CalEvent(); event.id = cal.getUUID(); event.title = name; event.startDate = now.clone(); event.startDate.addDuration(cal.createDuration(start)); event.endDate = event.startDate.clone(); event.endDate.addDuration(cal.createDuration("PT10M")); events.push(await calendar.addItem(event)); expectedEvents.push({ ...expected, title: name, time: event.startDate }); } expectedEvents[0].dateHeader = "Today"; checkEvents(...expectedEvents); for (let event of events) { await calendar.deleteItem(event); } }); /** * Tests the today pane opens events in the summary dialog for both * non-recurring and recurring events. */ add_task(async function testOpenEvent() { let noRepeatEvent = new CalEvent(); noRepeatEvent.id = "no repeat event"; noRepeatEvent.title = "No Repeat Event"; noRepeatEvent.startDate = today.clone(); noRepeatEvent.startDate.hour = startHour; noRepeatEvent.endDate = noRepeatEvent.startDate.clone(); noRepeatEvent.endDate.hour++; let repeatEvent = new CalEvent(); repeatEvent.id = "repeated event"; repeatEvent.title = "Repeated Event"; repeatEvent.startDate = today.clone(); repeatEvent.startDate.hour = startHour; repeatEvent.endDate = noRepeatEvent.startDate.clone(); repeatEvent.endDate.hour++; repeatEvent.recurrenceInfo = new CalRecurrenceInfo(repeatEvent); repeatEvent.recurrenceInfo.appendRecurrenceItem( cal.createRecurrenceRule("RRULE:FREQ=DAILY;COUNT=5") ); for (let event of [noRepeatEvent, repeatEvent]) { let addedEvent = await calendar.addItem(event); if (event == noRepeatEvent) { Assert.equal(TodayPane.agenda.rowCount, 1); } else { Assert.equal(TodayPane.agenda.rowCount, 5); } Assert.equal( TodayPane.agenda.rows[0].querySelector(".agenda-listitem-title").textContent, event.title, "event title is correct" ); let dialogWindowPromise = CalendarTestUtils.waitForEventDialog(); EventUtils.synthesizeMouseAtCenter(TodayPane.agenda.rows[0], { clickCount: 2 }); let dialogWindow = await dialogWindowPromise; let docUri = dialogWindow.document.documentURI; Assert.ok( docUri === "chrome://calendar/content/calendar-summary-dialog.xhtml", "event summary dialog shown" ); await BrowserTestUtils.closeWindow(dialogWindow); await calendar.deleteItem(addedEvent); } }); /** * Tests that the "New Event" button begins creating an event on the date * selected in the Today Pane. */ add_task(async function testNewEvent() { async function checkEventDialogDate() { let dialogWindowPromise = CalendarTestUtils.waitForEventDialog("edit"); EventUtils.synthesizeMouseAtCenter(newEventButton, {}, window); await dialogWindowPromise.then(async function (dialogWindow) { let iframe = dialogWindow.document.querySelector("#calendar-item-panel-iframe"); let iframeDocument = iframe.contentDocument; let startDate = iframeDocument.getElementById("event-starttime"); Assert.equal( startDate._datepicker._inputField.value, formatDate(expectedDate), "date should match the expected date" ); Assert.equal( startDate._timepicker._inputField.value, formatTime(expectedDate), "time should be the next hour after now" ); await BrowserTestUtils.closeWindow(dialogWindow); }); } let newEventButton = document.getElementById("todaypane-new-event-button"); // Check today with the "day" view. TodayPane.displayMiniSection("miniday"); EventUtils.synthesizeMouseAtCenter(document.getElementById("today-button"), {}, window); let expectedDate = cal.dtz.now(); expectedDate.hour++; expectedDate.minute = 0; await checkEventDialogDate(); // Check tomorrow with the "day" view. EventUtils.synthesizeMouseAtCenter(document.getElementById("next-day-button"), {}, window); expectedDate.day++; await checkEventDialogDate(); // Check today with the "month" view; TodayPane.displayMiniSection("minimonth"); let minimonth = document.getElementById("today-minimonth"); minimonth.value = new Date(); expectedDate.day--; await checkEventDialogDate(); // Check a date in the past with the "month" view; minimonth.value = new Date(Date.UTC(2018, 8, 1)); expectedDate.resetTo(2018, 8, 1, expectedDate.hour, 0, 0, cal.dtz.UTC); await checkEventDialogDate(); }).__skipMe = new Date().getUTCHours() == 23;