Bug 1917305 - Part 3: Update moz-toggle tests to use the input test helpers r=reusable-components-reviewers,mstriemer
Differential Revision: https://phabricator.services.mozilla.com/D226721
This commit is contained in:
@@ -76,12 +76,17 @@ class InputTestHelpers {
|
||||
*/
|
||||
getInputEventHelpers() {
|
||||
let seenEvents = [];
|
||||
let { activatedProperty } = this;
|
||||
|
||||
function trackEvent(event) {
|
||||
let reactiveProps = event.target.constructor.properties;
|
||||
seenEvents.push({
|
||||
type: event.type,
|
||||
value: event.target.value,
|
||||
checked: event.target.checked,
|
||||
localName: event.currentTarget.localName,
|
||||
...(reactiveProps.hasOwnProperty(activatedProperty) && {
|
||||
[activatedProperty]: event.target[activatedProperty],
|
||||
}),
|
||||
});
|
||||
}
|
||||
function verifyEvents(expectedEvents) {
|
||||
@@ -103,11 +108,11 @@ class InputTestHelpers {
|
||||
eventInfo.localName,
|
||||
"Event is emitted from the correct element."
|
||||
);
|
||||
if (eventInfo.hasOwnProperty("checked")) {
|
||||
if (activatedProperty) {
|
||||
is(
|
||||
seenEventInfo.checked,
|
||||
eventInfo.checked,
|
||||
"Event checked state is correct."
|
||||
seenEventInfo[activatedProperty],
|
||||
eventInfo[activatedProperty],
|
||||
`Event ${activatedProperty} state is correct.`
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -133,8 +138,8 @@ class InputTestHelpers {
|
||||
await this.verifySupportPage(elementName);
|
||||
await this.verifyAccesskey(elementName);
|
||||
await this.verifyNoWhitespace(elementName);
|
||||
if (this.checkable) {
|
||||
await this.verifyChecked(elementName);
|
||||
if (this.activatedProperty) {
|
||||
await this.verifyActivated(elementName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,6 +337,7 @@ class InputTestHelpers {
|
||||
*/
|
||||
async verifySupportPage(selector) {
|
||||
const LEARN_MORE_TEXT = "Learn more";
|
||||
const CUSTOM_TEXT = "Help me!";
|
||||
|
||||
let templatesArgs = [
|
||||
[{ "support-page": "test-page", label: "A label" }],
|
||||
@@ -400,7 +406,7 @@ class InputTestHelpers {
|
||||
);
|
||||
is(
|
||||
slottedSupportLink.innerText,
|
||||
"Help me!",
|
||||
CUSTOM_TEXT,
|
||||
"Slotted link uses non-default label text."
|
||||
);
|
||||
is(
|
||||
@@ -439,6 +445,7 @@ class InputTestHelpers {
|
||||
async verifyAccesskey(selector) {
|
||||
const UNIQUE_ACCESS_KEY = "t";
|
||||
const SHARED_ACCESS_KEY = "d";
|
||||
let { activatedProperty } = this;
|
||||
|
||||
let attrs = [
|
||||
{ value: "first", label: "First", accesskey: UNIQUE_ACCESS_KEY },
|
||||
@@ -459,7 +466,9 @@ class InputTestHelpers {
|
||||
firstInput.inputEl,
|
||||
"Input element is not focused."
|
||||
);
|
||||
ok(!firstInput.checked, "Input is not checked.");
|
||||
if (activatedProperty) {
|
||||
ok(!firstInput[activatedProperty], `Input is not ${activatedProperty}.`);
|
||||
}
|
||||
|
||||
synthesizeKey(
|
||||
UNIQUE_ACCESS_KEY,
|
||||
@@ -478,8 +487,11 @@ class InputTestHelpers {
|
||||
firstInput.inputEl,
|
||||
"Input element is focused after accesskey is pressed."
|
||||
);
|
||||
if (this.checkable) {
|
||||
ok(firstInput.checked, "Input is checked after accesskey is pressed.");
|
||||
if (activatedProperty) {
|
||||
ok(
|
||||
firstInput[activatedProperty],
|
||||
`Input is ${activatedProperty} after accesskey is pressed.`
|
||||
);
|
||||
}
|
||||
|
||||
// Validate that activating a shared accesskey toggles focus between inputs.
|
||||
@@ -495,8 +507,11 @@ class InputTestHelpers {
|
||||
secondInput,
|
||||
"Focus moves to the input with the shared accesskey."
|
||||
);
|
||||
if (this.checkable) {
|
||||
ok(!secondInput.checked, "Second input is not checked.");
|
||||
if (activatedProperty) {
|
||||
ok(
|
||||
!secondInput[activatedProperty],
|
||||
`Second input is not ${activatedProperty}.`
|
||||
);
|
||||
}
|
||||
|
||||
synthesizeKey(
|
||||
@@ -511,37 +526,56 @@ class InputTestHelpers {
|
||||
thirdInput,
|
||||
"Focus cycles between inputs with the same accesskey."
|
||||
);
|
||||
if (this.checkable) {
|
||||
ok(!thirdInput.checked, "Third input is not checked.");
|
||||
if (activatedProperty) {
|
||||
ok(
|
||||
!thirdInput[activatedProperty],
|
||||
`Third input is not ${activatedProperty}.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the checked state of the input element.
|
||||
* Verifies the activated state of the input element.
|
||||
*
|
||||
* @param {string} selector - HTML tag of the element under test.
|
||||
*/
|
||||
async verifyChecked(selector) {
|
||||
async verifyActivated(selector) {
|
||||
let renderTarget = await this.renderInputElements();
|
||||
let firstInput = renderTarget.querySelector(selector);
|
||||
ok(
|
||||
!firstInput.inputEl.checked,
|
||||
"Input name is not checked on initial render."
|
||||
);
|
||||
firstInput.checked = true;
|
||||
await firstInput.updateComplete;
|
||||
ok(firstInput.inputEl.checked, "Input is checked.");
|
||||
ok(firstInput.checked, "Checked state is propagated.");
|
||||
let { activatedProperty } = this;
|
||||
|
||||
// Reset checked state so that the radio input doesn't
|
||||
ok(
|
||||
!firstInput.inputEl[activatedProperty] && !firstInput[activatedProperty],
|
||||
`Input is not ${activatedProperty} on initial render.`
|
||||
);
|
||||
|
||||
firstInput[activatedProperty] = true;
|
||||
await firstInput.updateComplete;
|
||||
|
||||
ok(firstInput[activatedProperty], `Input is ${activatedProperty}.`);
|
||||
ok(
|
||||
firstInput.inputEl[activatedProperty] ||
|
||||
firstInput.inputEl.getAttribute(`aria-${activatedProperty}`) == "true",
|
||||
`${activatedProperty} state is propagated.`
|
||||
);
|
||||
|
||||
// Reset state so that the radio input doesn't
|
||||
// give a false negative
|
||||
firstInput.checked = false;
|
||||
firstInput[activatedProperty] = false;
|
||||
await firstInput.updateComplete;
|
||||
|
||||
synthesizeMouseAtCenter(firstInput.inputEl, {});
|
||||
await firstInput.updateComplete;
|
||||
ok(firstInput.inputEl.checked, "Input is checked via mouse.");
|
||||
ok(firstInput.checked, "Checked state is propagated.");
|
||||
|
||||
ok(
|
||||
firstInput[activatedProperty],
|
||||
`Input is ${activatedProperty} via mouse.`
|
||||
);
|
||||
ok(
|
||||
firstInput.inputEl[activatedProperty] ||
|
||||
firstInput.inputEl.getAttribute(`aria-${activatedProperty}`) == "true",
|
||||
`${activatedProperty} state is propagated.`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
templateFn: (attrs, children) =>
|
||||
html`<moz-checkbox ${attrs}>${children}</moz-checkbox>`,
|
||||
});
|
||||
testHelpers.checkable = true;
|
||||
testHelpers.activatedProperty = "checked";
|
||||
});
|
||||
|
||||
add_task(async function testMozCheckboxProperties() {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</moz-radio-group>
|
||||
`;
|
||||
await testHelpers.setupInputTests({ templateFn });
|
||||
testHelpers.checkable = true;
|
||||
testHelpers.activatedProperty = "checked";
|
||||
});
|
||||
|
||||
add_task(async function testMozRadioProperties() {
|
||||
|
||||
@@ -10,100 +10,87 @@
|
||||
solution for token variables for the new widgets -->
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||
<script type="module" src="chrome://global/content/elements/moz-toggle.mjs"></script>
|
||||
<script src="input-test-helpers.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="max-width: fit-content">
|
||||
<moz-toggle label="Label" description="Description" pressed="true"></moz-toggle>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
const { BrowserTestUtils } = ChromeUtils.importESModule(
|
||||
"resource://testing-common/BrowserTestUtils.sys.mjs"
|
||||
);
|
||||
let testHelpers = new InputTestHelpers();
|
||||
|
||||
add_task(async function testMozToggleDisplay() {
|
||||
const mozToggle = document.querySelector("moz-toggle");
|
||||
ok(mozToggle, "moz-toggle is rendered");
|
||||
add_setup(async function setup() {
|
||||
let { html } = await testHelpers.setupLit();
|
||||
let templateFn = (attrs, children) => html`
|
||||
<moz-toggle ${attrs}>${children}</moz-toggle>
|
||||
`;
|
||||
await testHelpers.setupInputTests({ templateFn });
|
||||
testHelpers.activatedProperty = "pressed";
|
||||
});
|
||||
|
||||
const label = mozToggle.labelEl;
|
||||
ok(label, "moz-toggle contains a label");
|
||||
ok(label.textContent.includes("Label"), "The expected label text is shown");
|
||||
|
||||
const description = mozToggle.descriptionEl;
|
||||
ok(description, "moz-toggle contains a description");
|
||||
ok(description.textContent.includes("Description"), "The expected description text is shown");
|
||||
|
||||
const button = mozToggle.buttonEl;
|
||||
ok(button, "moz-toggle contains a button");
|
||||
is(button.getAttribute("aria-pressed"), "true", "The button is pressed");
|
||||
add_task(async function testMozToggleProperties() {
|
||||
await testHelpers.testCommonInputProperties("moz-toggle");
|
||||
});
|
||||
|
||||
add_task(async function testMozToggleInteraction() {
|
||||
const mozToggle = document.querySelector("moz-toggle");
|
||||
let { trackEvent, verifyEvents } = testHelpers.getInputEventHelpers();
|
||||
let interactionTemplate = testHelpers.templateFn({ value: "default", label: "Label" });
|
||||
let renderTarget = await testHelpers.renderInputElements(interactionTemplate);
|
||||
const mozToggle = renderTarget.querySelector("moz-toggle");
|
||||
const button = mozToggle.buttonEl;
|
||||
mozToggle.pressed = true;
|
||||
await mozToggle.updateComplete;
|
||||
|
||||
mozToggle.addEventListener("click", trackEvent);
|
||||
mozToggle.addEventListener("toggle", trackEvent);
|
||||
|
||||
is(mozToggle.pressed, true, "moz-toggle is pressed initially");
|
||||
is(button.getAttribute("aria-pressed"), "true", "aria-pressed reflects the pressed state");
|
||||
|
||||
synthesizeMouseAtCenter(button, {});
|
||||
await mozToggle.updateComplete;
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
verifyEvents([
|
||||
{ type: "click", localName: "moz-toggle", pressed: false, value: "default" },
|
||||
{ type: "toggle", localName: "moz-toggle", pressed: false, value: "default" },
|
||||
]);
|
||||
|
||||
is(mozToggle.pressed, false, "The toggle pressed state changes on click");
|
||||
is(button.getAttribute("aria-pressed"), "false", "aria-pressed reflects this change");
|
||||
|
||||
synthesizeMouseAtCenter(mozToggle.labelEl, {});
|
||||
await mozToggle.updateComplete;
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
// Clicking the label element emits an additional click event that doesn't update the pressed state.
|
||||
verifyEvents([
|
||||
{ type: "click", localName: "moz-toggle", pressed: false, value: "default" },
|
||||
{ type: "click", localName: "moz-toggle", pressed: true, value: "default" },
|
||||
{ type: "toggle", localName: "moz-toggle", pressed: true, value: "default" },
|
||||
]);
|
||||
|
||||
is(mozToggle.pressed, true, "The toggle pressed state changes on label click");
|
||||
is(button.getAttribute("aria-pressed"), "true", "aria-pressed reflects this change");
|
||||
|
||||
mozToggle.focus();
|
||||
synthesizeKey(" ", {});
|
||||
await mozToggle.updateComplete;
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
verifyEvents([
|
||||
{ type: "click", localName: "moz-toggle", pressed: false, value: "default" },
|
||||
{ type: "toggle", localName: "moz-toggle", pressed: false, value: "default" },
|
||||
]);
|
||||
|
||||
is(mozToggle.pressed, false, "The toggle pressed state can be changed via space bar");
|
||||
is(button.getAttribute("aria-pressed"), "false", "aria-pressed reflects this change");
|
||||
|
||||
let descriptionClicked = BrowserTestUtils.waitForEvent(mozToggle, "click");
|
||||
synthesizeMouseAtCenter(mozToggle.descriptionEl, {});
|
||||
await descriptionClicked;
|
||||
await TestUtils.waitForTick();
|
||||
|
||||
verifyEvents([]);
|
||||
|
||||
isnot(
|
||||
mozToggle.shadowRoot.activeElement,
|
||||
mozToggle.buttonEl,
|
||||
"Clicking the description should not focus the toggle button"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function testSupportsAccesskey() {
|
||||
const mozToggle = document.querySelector("moz-toggle");
|
||||
let nextAccesskey = "l";
|
||||
mozToggle.setAttribute("accesskey", nextAccesskey);
|
||||
await new Promise(requestAnimationFrame);
|
||||
|
||||
mozToggle.blur();
|
||||
isnot(
|
||||
mozToggle.shadowRoot.activeElement,
|
||||
mozToggle.buttonEl,
|
||||
"Toggle button should not be focused."
|
||||
);
|
||||
await mozToggle.updateComplete;
|
||||
|
||||
mozToggle.pressed = false;
|
||||
ok(!mozToggle.pressed, "Toggle is off");
|
||||
synthesizeKey(
|
||||
nextAccesskey,
|
||||
navigator.platform.includes("Mac")
|
||||
? { altKey: true, ctrlKey: true }
|
||||
: { altKey: true, shiftKey: true }
|
||||
);
|
||||
|
||||
is(
|
||||
mozToggle.shadowRoot.activeElement,
|
||||
mozToggle.buttonEl,
|
||||
"Focus has moved to the toggle button."
|
||||
);
|
||||
ok(mozToggle.pressed, "Toggle is on");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user