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:
Hanna Jones
2024-12-12 18:27:15 +00:00
parent 96be4d693e
commit 766b91402a
4 changed files with 111 additions and 90 deletions

View File

@@ -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.`
);
}
/**

View File

@@ -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() {

View File

@@ -19,7 +19,7 @@
</moz-radio-group>
`;
await testHelpers.setupInputTests({ templateFn });
testHelpers.checkable = true;
testHelpers.activatedProperty = "checked";
});
add_task(async function testMozRadioProperties() {

View File

@@ -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>