/* 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"; /* eslint-disable camelcase */ // From https://learn.microsoft.com/en-us/windows/win32/winauto/landmark-type-identifiers const UIA_CustomLandmarkTypeId = 80000; const UIA_MainLandmarkTypeId = 80002; /* eslint-enable camelcase */ /** * Test the Name property. */ addUiaTask( `
div
`, async function testName(browser) { await definePyVar("doc", `getDocUia()`); await assignPyVarToUiaWithId("button"); is( await runPython(`button.CurrentName`), "before", "button has correct name" ); await assignPyVarToUiaWithId("div"); is(await runPython(`div.CurrentName`), "", "div has no name"); info("Setting aria-label on button"); await setUpWaitForUiaPropEvent("Name", "button"); await invokeSetAttribute(browser, "button", "aria-label", "after"); await waitForUiaEvent(); ok(true, "Got Name prop change event on button"); is( await runPython(`button.CurrentName`), "after", "button has correct name" ); } ); /** * Test the FullDescription property. */ addUiaTask( `
div
`, async function testFullDescription(browser) { await definePyVar("doc", `getDocUia()`); await assignPyVarToUiaWithId("button"); is( await runPython(`button.CurrentFullDescription`), "before", "button has correct FullDescription" ); await assignPyVarToUiaWithId("div"); is( await runPython(`div.CurrentFullDescription`), "", "div has no FullDescription" ); info("Setting aria-description on button"); await setUpWaitForUiaPropEvent("FullDescription", "button"); await invokeSetAttribute(browser, "button", "aria-description", "after"); await waitForUiaEvent(); ok(true, "Got FullDescription prop change event on button"); is( await runPython(`button.CurrentFullDescription`), "after", "button has correct FullDescription" ); }, // The IA2 -> UIA proxy doesn't support FullDescription. { uiaEnabled: true, uiaDisabled: false } ); /** * Test the IsEnabled property. */ addUiaTask( `

p

`, async function testIsEnabled(browser) { await definePyVar("doc", `getDocUia()`); await assignPyVarToUiaWithId("button"); ok(await runPython(`button.CurrentIsEnabled`), "button has IsEnabled true"); // The IA2 -> UIA proxy doesn't fire IsEnabled prop change events. if (gIsUiaEnabled) { info("Setting disabled on button"); await setUpWaitForUiaPropEvent("IsEnabled", "button"); await invokeSetAttribute(browser, "button", "disabled", true); await waitForUiaEvent(); ok(true, "Got IsEnabled prop change event on button"); ok( !(await runPython(`button.CurrentIsEnabled`)), "button has IsEnabled false" ); } await assignPyVarToUiaWithId("p"); ok(await runPython(`p.CurrentIsEnabled`), "p has IsEnabled true"); } ); async function testGroupPos(id, level, pos, size) { await assignPyVarToUiaWithId(id); is(await runPython(`${id}.CurrentLevel`), level, `${id} Level correct`); is( await runPython(`${id}.CurrentPositionInSet`), pos, `${id} PositionInSet correct` ); is( await runPython(`${id}.CurrentSizeOfSet`), size, `${id} SizeOfSet correct` ); } /** * Test the Level, PositionInSet and SizeOfSet properties. */ addUiaTask( `

h2

`, async function testGroupPosProps(browser) { await definePyVar("doc", `getDocUia()`); await testGroupPos("li1", 1, 1, 1); await testGroupPos("li2a", 2, 1, 2); await testGroupPos("li2c", 2, 2, 2); info("Showing li2b"); // There aren't events in any API for a change to group position properties // because this would be too spammy and isn't particularly useful given // how frequently these can change. let shown = waitForEvent(EVENT_SHOW, "li2b"); await invokeContentTask(browser, [], () => { content.document.getElementById("li2b").hidden = false; }); await shown; await testGroupPos("li2a", 2, 1, 3); await testGroupPos("li2b", 2, 2, 3); await testGroupPos("li2c", 2, 3, 3); // The IA2 -> UIA proxy doesn't map heading level to the Level property. if (gIsUiaEnabled) { await testGroupPos("h2", 2, 0, 0); } await testGroupPos("button", 0, 0, 0); } ); /** * Test the FrameworkId property. */ addUiaTask( ``, async function testFrameworkId() { await definePyVar("doc", `getDocUia()`); is( await runPython(`doc.CurrentFrameworkId`), "Gecko", "doc FrameworkId is correct" ); await assignPyVarToUiaWithId("button"); is( await runPython(`button.CurrentFrameworkId`), "Gecko", "button FrameworkId is correct" ); } ); /** * Test the ClassName property. */ addUiaTask( `

p

`, async function testClassName(browser, docAcc) { await definePyVar("doc", `getDocUia()`); await assignPyVarToUiaWithId("p"); ok(!(await runPython(`p.CurrentClassName`)), "p has no ClassName"); await assignPyVarToUiaWithId("button"); is( await runPython(`button.CurrentClassName`), "c1", "button has correct ClassName" ); info("Changing button class"); await invokeSetAttribute(browser, "button", "class", "c2 c3"); // Gecko doesn't fire an event for class changes, as this isn't useful for // clients. const button = findAccessibleChildByID(docAcc, "button"); await untilCacheIs( () => button.attributes.getStringProperty("class"), "c2 c3", "button class updated" ); is( await runPython(`button.CurrentClassName`), "c2 c3", "button has correct ClassName" ); }, // The IA2 -> UIA proxy doesn't support ClassName. { uiaEnabled: true, uiaDisabled: false } ); /** * Test the AriaRole property. */ addUiaTask( `
button
main
unknown

computedHeading

computedMain
generic
`, async function testAriaRole() { await definePyVar("doc", `getDocUia()`); is( await runPython(`findUiaByDomId(doc, "button").CurrentAriaRole`), "button", "button has correct AriaRole" ); is( await runPython(`findUiaByDomId(doc, "main").CurrentAriaRole`), "main", "main has correct AriaRole" ); is( await runPython(`findUiaByDomId(doc, "unknown").CurrentAriaRole`), "unknown", "unknown has correct AriaRole" ); // The IA2 -> UIA proxy doesn't compute ARIA roles. if (gIsUiaEnabled) { is( await runPython( `findUiaByDomId(doc, "computedButton").CurrentAriaRole` ), "button", "computedButton has correct AriaRole" ); is( await runPython(`findUiaByDomId(doc, "computedMain").CurrentAriaRole`), "main", "computedMain has correct AriaRole" ); is( await runPython( `findUiaByDomId(doc, "computedHeading").CurrentAriaRole` ), "heading", "computedHeading has correct AriaRole" ); is( await runPython(`findUiaByDomId(doc, "generic").CurrentAriaRole`), "generic", "generic has correct AriaRole" ); } } ); /** * Test the LocalizedControlType property. We don't support this ourselves, but * the system provides it based on ControlType and AriaRole. */ addUiaTask( `

h1

main
`, async function testLocalizedControlType() { await definePyVar("doc", `getDocUia()`); is( await runPython( `findUiaByDomId(doc, "button").CurrentLocalizedControlType` ), "button", "button has correct LocalizedControlType" ); // The IA2 -> UIA proxy doesn't compute ARIA roles, so it can't compute the // correct LocalizedControlType for these either. if (gIsUiaEnabled) { is( await runPython( `findUiaByDomId(doc, "h1").CurrentLocalizedControlType` ), "heading", "h1 has correct LocalizedControlType" ); is( await runPython( `findUiaByDomId(doc, "main").CurrentLocalizedControlType` ), "main", "main has correct LocalizedControlType" ); } } ); /** * Test the LandmarkType property. */ addUiaTask( `
main
htmlMain
region
unnamedRegion
mainBanner
none
`, async function testLandmarkType() { await definePyVar("doc", `getDocUia()`); is( await runPython(`findUiaByDomId(doc, "main").CurrentLandmarkType`), UIA_MainLandmarkTypeId, "main has correct LandmarkType" ); is( await runPython(`findUiaByDomId(doc, "htmlMain").CurrentLandmarkType`), UIA_MainLandmarkTypeId, "htmlMain has correct LandmarkType" ); is( await runPython(`findUiaByDomId(doc, "banner").CurrentLandmarkType`), UIA_CustomLandmarkTypeId, "banner has correct LandmarkType" ); is( await runPython(`findUiaByDomId(doc, "header").CurrentLandmarkType`), UIA_CustomLandmarkTypeId, "header has correct LandmarkType" ); is( await runPython(`findUiaByDomId(doc, "region").CurrentLandmarkType`), UIA_CustomLandmarkTypeId, "region has correct LandmarkType" ); is( await runPython( `findUiaByDomId(doc, "unnamedRegion").CurrentLandmarkType` ), 0, "unnamedRegion has correct LandmarkType" ); // ARIA role takes precedence. is( await runPython(`findUiaByDomId(doc, "mainBanner").CurrentLandmarkType`), UIA_CustomLandmarkTypeId, "mainBanner has correct LandmarkType" ); is( await runPython(`findUiaByDomId(doc, "none").CurrentLandmarkType`), 0, "none has correct LandmarkType" ); } ); /** * Test the LocalizedLandmarkType property. */ addUiaTask( `
main
region
unnamedRegion
mainBanner
none
`, async function testLocalizedLandmarkType() { await definePyVar("doc", `getDocUia()`); // Provided by the system. is( await runPython( `findUiaByDomId(doc, "main").CurrentLocalizedLandmarkType` ), "main", "main has correct LocalizedLandmarkType" ); // The IA2 -> UIA proxy doesn't follow the Core AAM spec for this role. if (gIsUiaEnabled) { // Provided by us. is( await runPython( `findUiaByDomId(doc, "contentinfo").CurrentLocalizedLandmarkType` ), "content information", "contentinfo has correct LocalizedLandmarkType" ); } is( await runPython( `findUiaByDomId(doc, "region").CurrentLocalizedLandmarkType` ), "region", "region has correct LocalizedLandmarkType" ); // Invalid landmark. is( await runPython( `findUiaByDomId(doc, "unnamedRegion").CurrentLocalizedLandmarkType` ), "", "unnamedRegion has correct LocalizedLandmarkType" ); // ARIA role takes precedence. is( await runPython( `findUiaByDomId(doc, "mainBanner").CurrentLocalizedLandmarkType` ), "banner", "mainBanner has correct LocalizedLandmarkType" ); is( await runPython( `findUiaByDomId(doc, "none").CurrentLocalizedLandmarkType` ), "", "none has correct LocalizedLandmarkType" ); } );