/* 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/. */
"use strict";
/**
* When the Previous Month button is pressed, calendar should display
* the dates for the previous month.
*/
add_task(async function test_datepicker_prev_month_btn() {
const inputValue = "2016-12-15";
const prevMonth = "2016-11-01";
await helper.openPicker(
`data:text/html, `
);
// Move focus from the selected date to the Previous Month button:
EventUtils.synthesizeKey("KEY_Tab", { repeat: 2 });
EventUtils.synthesizeKey(" ", {});
// 2016-11-15:
const focusableDay = getDayEl(15);
Assert.equal(
helper.getElement(MONTH_YEAR).textContent,
DATE_FORMAT(new Date(prevMonth))
);
Assert.deepEqual(
getCalendarText(),
[
"30",
"31",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
],
"The calendar is updated to show the previous month (2016-11)"
);
Assert.ok(
helper.getElement(BTN_PREV_MONTH).matches(":focus"),
"Focus stays on a Previous Month button after it's pressed"
);
Assert.equal(
focusableDay.textContent,
"15",
"The same day of the month is present within a calendar grid"
);
Assert.equal(
focusableDay,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
// Move focus from the Previous Month button to the same day of the month (2016-11-15):
EventUtils.synthesizeKey("KEY_Tab", { repeat: 3 });
Assert.ok(
focusableDay.matches(":focus"),
"The same day of the previous month can be focused with a keyboard"
);
await helper.tearDown();
});
/**
* When the Next Month button is clicked, calendar should display the dates for
* the next month.
*/
add_task(async function test_datepicker_next_month_btn() {
const inputValue = "2016-12-15";
const nextMonth = "2017-01-01";
await helper.openPicker(
`data:text/html, `
);
// Move focus from the selected date to the Next Month button:
EventUtils.synthesizeKey("KEY_Tab", { repeat: 4 });
EventUtils.synthesizeKey(" ", {});
// 2017-01-15:
const focusableDay = getDayEl(15);
Assert.equal(
helper.getElement(MONTH_YEAR).textContent,
DATE_FORMAT(new Date(nextMonth))
);
Assert.deepEqual(
getCalendarText(),
[
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30",
"31",
"1",
"2",
"3",
"4",
],
"The calendar is updated to show the next month (2017-01)."
);
Assert.ok(
helper.getElement(BTN_NEXT_MONTH).matches(":focus"),
"Focus stays on a Next Month button after it's pressed"
);
Assert.equal(
focusableDay.textContent,
"15",
"The same day of the month is present within a calendar grid"
);
Assert.equal(
focusableDay,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
// Move focus from the Next Month button to the same day of the month (2017-01-15):
EventUtils.synthesizeKey("KEY_Tab", {});
Assert.ok(
focusableDay.matches(":focus"),
"The same day of the next month can be focused with a keyboard"
);
await helper.tearDown();
});
/**
* When the Previous Month button is pressed, calendar should display
* the dates for the previous month on RTL build (bug 1806823).
*/
add_task(async function test_datepicker_prev_month_btn_rtl() {
const inputValue = "2016-12-15";
const prevMonth = "2016-11-01";
await SpecialPowers.pushPrefEnv({ set: [["intl.l10n.pseudo", "bidi"]] });
await helper.openPicker(
`data:text/html, `
);
// Move focus from the selected date to the Previous Month button:
EventUtils.synthesizeKey("KEY_Tab", { repeat: 2 });
EventUtils.synthesizeKey(" ", {});
// 2016-11-15:
const focusableDay = getDayEl(15);
Assert.equal(
helper.getElement(MONTH_YEAR).textContent,
DATE_FORMAT(new Date(prevMonth)),
"The calendar is updated to show the previous month (2016-11)"
);
Assert.ok(
helper.getElement(BTN_PREV_MONTH).matches(":focus"),
"Focus stays on a Previous Month button after it's pressed"
);
Assert.equal(
focusableDay.textContent,
"15",
"The same day of the month is present within a calendar grid"
);
Assert.equal(
focusableDay,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
// Move focus from the Previous Month button to the same day of the month (2016-11-15):
EventUtils.synthesizeKey("KEY_Tab", { repeat: 3 });
Assert.ok(
focusableDay.matches(":focus"),
"The same day of the previous month can be focused with a keyboard"
);
await helper.tearDown();
await SpecialPowers.popPrefEnv();
});
/**
* When the Next Month button is clicked, calendar should display the dates for
* the next month on RTL build (bug 1806823).
*/
add_task(async function test_datepicker_next_month_btn_rtl() {
const inputValue = "2016-12-15";
const nextMonth = "2017-01-01";
await SpecialPowers.pushPrefEnv({ set: [["intl.l10n.pseudo", "bidi"]] });
await helper.openPicker(
`data:text/html, `
);
// Move focus from the selected date to the Next Month button:
EventUtils.synthesizeKey("KEY_Tab", { repeat: 4 });
EventUtils.synthesizeKey(" ", {});
// 2017-01-15:
const focusableDay = getDayEl(15);
Assert.equal(
helper.getElement(MONTH_YEAR).textContent,
DATE_FORMAT(new Date(nextMonth)),
"The calendar is updated to show the next month (2017-01)."
);
Assert.ok(
helper.getElement(BTN_NEXT_MONTH).matches(":focus"),
"Focus stays on a Next Month button after it's pressed"
);
Assert.equal(
focusableDay.textContent,
"15",
"The same day of the month is present within a calendar grid"
);
Assert.equal(
focusableDay,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
// Move focus from the Next Month button to the same day of the month (2017-01-15):
EventUtils.synthesizeKey("KEY_Tab", {});
Assert.ok(
focusableDay.matches(":focus"),
"The same day of the next month can be focused with a keyboard"
);
await helper.tearDown();
await SpecialPowers.popPrefEnv();
});
/**
* When Previous/Next Month buttons or arrow keys are used to change a month view
* when a time value is incomplete for datetime-local inputs,
* calendar should update the month (bug 1817785).
*/
add_task(async function test_datepicker_reopened_prev_next_month_btn() {
info("Setup a datetime-local datepicker to its reopened state for testing");
let inputValueDT = "2023-05-02T01:01";
let prevMonth = new Date("2023-04-02");
await helper.openPicker(
`data:text/html, `
);
let closed = helper.promisePickerClosed();
EventUtils.synthesizeKey("KEY_Escape", {});
await closed;
Assert.equal(
helper.panel.state,
"closed",
"Date picker panel should be closed"
);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
const input = content.document.querySelector("input");
const shadowRoot = SpecialPowers.wrap(input).openOrClosedShadowRoot;
const editFields = shadowRoot.querySelectorAll(".datetime-edit-field");
const amPm = editFields[5];
amPm.focus();
Assert.ok(
amPm.matches(":focus"),
"Period of the day within the input is focused"
);
});
// Use Backspace key to clear the value of the AM/PM section of the input
// and wait for input.value to change to null (bug 1833988):
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async () => {
const input = content.document.querySelector("input");
const EventUtils = ContentTaskUtils.getEventUtils(content);
EventUtils.synthesizeKey("KEY_Backspace", {}, content);
await ContentTaskUtils.waitForMutationCondition(
input,
{ attributeFilter: ["value"] },
() => input.value == ""
);
Assert.ok(
!input.value,
`Expected an input value to be changed to 'null' when a time value became incomplete, instead got ${input.value}`
);
});
let ready = helper.waitForPickerReady();
// Move focus to a day section of the input and open a picker:
EventUtils.synthesizeKey("KEY_Tab", {});
EventUtils.synthesizeKey(" ", {});
await ready;
Assert.equal(
helper.panel.querySelector("#dateTimePopupFrame").contentDocument
.activeElement.textContent,
"2",
"Picker is opened with a focus set to the currently selected date"
);
info("Test the Previous Month button behavior");
// Move focus from the selected date to the Previous Month button,
// and activate it to move calendar from 2023-05-02 to 2023-04-02:
EventUtils.synthesizeKey("KEY_Tab", {
repeat: 2,
});
EventUtils.synthesizeKey(" ", {});
// Same date of the previous month should be visible and focusable
// (2023-04-02) but the focus should remain on the Previous Month button:
const focusableDayPrevMonth = getDayEl(2);
const monthYearEl = helper.getElement(MONTH_YEAR);
await BrowserTestUtils.waitForMutationCondition(
monthYearEl,
{
childList: true,
},
() => {
return monthYearEl.textContent == DATE_FORMAT(new Date(prevMonth));
},
`Should change to the previous month (April 2023), instead got ${
helper.getElement(MONTH_YEAR).textContent
}`
);
Assert.ok(
true,
`The date on both the Calendar and Month-Year button was updated
when Previous Month button was used`
);
Assert.ok(
helper.getElement(BTN_PREV_MONTH).matches(":focus"),
"Focus stays on a Previous Month button after it's pressed"
);
Assert.equal(
focusableDayPrevMonth,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
Assert.equal(
focusableDayPrevMonth.textContent,
"2",
"The same day of the month is present within a calendar grid"
);
// Move focus from the Previous Month button to the same day of the month (2023-04-02):
EventUtils.synthesizeKey("KEY_Tab", {
repeat: 3,
});
Assert.ok(
focusableDayPrevMonth.matches(":focus"),
"The same day of the previous month can be focused with a keyboard"
);
info("Test the Next Month button behavior");
// Move focus from the focused date to the Next Month button and activate it,
// (from 2023-04-02 to 2023-05-02):
EventUtils.synthesizeKey("KEY_Tab", {
repeat: 4,
});
EventUtils.synthesizeKey(" ", {});
// Same date of the next month should be visible and focusable
// (2023-05-02) but the focus should remain on the Next Month button:
const focusableDayNextMonth = getDayEl(2);
await BrowserTestUtils.waitForMutationCondition(
monthYearEl,
{
childList: true,
},
() => {
return monthYearEl.textContent == DATE_FORMAT(new Date(inputValueDT));
},
`Should change to May 2023, instead got ${
helper.getElement(MONTH_YEAR).textContent
}`
);
Assert.ok(
true,
`The date on both the Calendar and Month-Year button was updated
when Next Month button was used`
);
Assert.ok(
helper.getElement(BTN_NEXT_MONTH).matches(":focus"),
"Focus stays on a Next Month button after it's pressed"
);
Assert.equal(
focusableDayNextMonth,
helper.getElement(DAYS_VIEW).querySelector('[tabindex="0"]'),
"The same day of the month is focusable within a calendar grid"
);
Assert.equal(
focusableDayNextMonth.textContent,
"2",
"The same day of the month is present within a calendar grid"
);
// Move focus from the Next Month button to the focusable day of the month (2023-05-02):
EventUtils.synthesizeKey("KEY_Tab", {});
Assert.ok(
focusableDayNextMonth.matches(":focus"),
"The same day of the month can be focused with a keyboard"
);
info("Test the arrow navigation behavior");
// Move focus from the focused date to the same weekday of the previous month,
// (From 2023-05-02 to 2023-04-25):
EventUtils.synthesizeKey("KEY_ArrowUp", {});
await BrowserTestUtils.waitForMutationCondition(
monthYearEl,
{
childList: true,
},
() => {
return monthYearEl.textContent == DATE_FORMAT(new Date(prevMonth));
},
`Should change to the previous month, instead got ${
helper.getElement(MONTH_YEAR).textContent
}`
);
Assert.ok(
true,
`The date on both the Calendar and Month-Year button was updated
when an Up Arrow key was used`
);
// Move focus from the focused date to the same weekday of the next month,
// (from 2023-04-25 to 2023-05-02):
EventUtils.synthesizeKey("KEY_ArrowDown", {});
await BrowserTestUtils.waitForMutationCondition(
monthYearEl,
{
childList: true,
},
() => {
return monthYearEl.textContent == DATE_FORMAT(new Date(inputValueDT));
},
`Should change to the previous month, instead got ${
helper.getElement(MONTH_YEAR).textContent
}`
);
Assert.ok(
true,
`The date on both the Calendar and Month-Year button was updated
when a Down Arrow key was used`
);
await helper.tearDown();
});