browser_markup_links_aria_attributes.js (6226B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Tests that the contextual menu shows the right items when clicking on a link 7 // in aria attributes. 8 9 const TEST_URL = URL_ROOT + "doc_markup_links_aria_attributes.html"; 10 11 // The test case array contains objects with the following properties: 12 // - selector: css selector for the node to select in the inspector 13 // - attributeName: name of the attribute to test 14 // - links: an array of id strings that are expected to be in the attribute 15 const TEST_DATA = [ 16 { 17 selector: "#aria-activedescendant", 18 attributeName: "aria-activedescendant", 19 links: [{ id: "activedescendant01" }], 20 }, 21 { 22 selector: "#aria-controls", 23 attributeName: "aria-controls", 24 links: [{ id: "controls01" }, { id: "controls02" }], 25 }, 26 { 27 selector: "#aria-describedby", 28 attributeName: "aria-describedby", 29 links: [{ id: "describedby01" }, { id: "describedby02" }], 30 }, 31 { 32 selector: "#aria-details", 33 attributeName: "aria-details", 34 links: [{ id: "details01" }, { id: "details02" }], 35 }, 36 { 37 selector: "#aria-errormessage", 38 attributeName: "aria-errormessage", 39 links: [{ id: "errormessage01" }], 40 }, 41 { 42 selector: "#aria-flowto", 43 attributeName: "aria-flowto", 44 links: [{ id: "flowto01" }, { id: "flowto02" }], 45 }, 46 { 47 selector: "#aria-labelledby", 48 attributeName: "aria-labelledby", 49 links: [{ id: "labelledby01" }, { id: "labelledby02" }], 50 }, 51 { 52 selector: "#aria-owns", 53 attributeName: "aria-owns", 54 links: [{ id: "owns01" }, { id: "owns02" }], 55 }, 56 { 57 getContainer: async inspector => { 58 info("Find and expand the test-component shadow DOM host."); 59 const hostFront = await getNodeFront("test-component", inspector); 60 const hostContainer = inspector.markup.getContainer(hostFront); 61 await expandContainer(inspector, hostContainer); 62 63 info("Expand the shadow root"); 64 const shadowRootContainer = hostContainer.getChildContainers()[0]; 65 await expandContainer(inspector, shadowRootContainer); 66 67 info("Expand the slot"); 68 const slotContainer = shadowRootContainer.getChildContainers()[0]; 69 70 is( 71 slotContainer.elt 72 .querySelector(`[data-attr="id"]`) 73 .getAttribute("data-value"), 74 "aria-describedby-shadow-dom", 75 `This is the container for button#aria-describedby-shadow-dom` 76 ); 77 78 // The test expect the node to be selected 79 const updated = inspector.once("inspector-updated"); 80 inspector.selection.setNodeFront(slotContainer.node, { reason: "test" }); 81 await updated; 82 83 return slotContainer; 84 }, 85 attributeName: "aria-describedby", 86 links: [{ id: "describedby01", valid: false }, { id: "describedbyshadow" }], 87 }, 88 { 89 selector: "#empty-attributes", 90 attributeName: "aria-activedescendant", 91 links: [], 92 }, 93 { 94 selector: "#empty-attributes", 95 attributeName: "aria-details", 96 links: [], 97 }, 98 ]; 99 100 add_task(async function () { 101 const { inspector } = await openInspectorForURL(TEST_URL); 102 103 for (const test of TEST_DATA) { 104 let editor; 105 if (typeof test.getContainer === "function") { 106 ({ editor } = await test.getContainer(inspector)); 107 } else { 108 info("Selecting test node " + test.selector); 109 await selectNode(test.selector, inspector); 110 info("Finding the popupNode to anchor the context-menu to"); 111 ({ editor } = await getContainerForSelector(test.selector, inspector)); 112 } 113 114 const attributeEl = editor.attrElements.get(test.attributeName); 115 const linksEl = attributeEl.querySelectorAll(".link"); 116 117 is( 118 linksEl.length, 119 test.links.length, 120 "We have the expected number of links in attribute " + test.attributeName 121 ); 122 123 for (let i = 0; i < test.links.length; i++) { 124 info(`Checking link # ${i} for attribute "${test.attributeName}"`); 125 126 const linkEl = linksEl[i]; 127 ok(linkEl, "Found the link"); 128 129 info("Simulating a context click on the link"); 130 const allMenuItems = openContextMenuAndGetAllItems(inspector, { 131 target: linkEl, 132 }); 133 134 const linkFollow = allMenuItems.find( 135 ({ id }) => id === "node-menu-link-follow" 136 ); 137 const linkCopy = allMenuItems.find( 138 ({ id }) => id === "node-menu-link-copy" 139 ); 140 141 is(linkFollow.visible, true, "The follow-link item is visible"); 142 is(linkCopy.visible, false, "The copy-link item is not visible"); 143 const { id: expectedReferencedNodeId } = test.links[i]; 144 const linkFollowItemLabel = INSPECTOR_L10N.getFormatStr( 145 "inspector.menu.selectElement.label", 146 expectedReferencedNodeId 147 ); 148 is( 149 linkFollow.label, 150 linkFollowItemLabel, 151 "the follow-link label is correct" 152 ); 153 154 info("Check that select node button is displayed"); 155 const buttonEl = linkEl.querySelector("button.select-node"); 156 ok(buttonEl, "Found the select node button"); 157 is( 158 buttonEl.getAttribute("title"), 159 linkFollowItemLabel, 160 "Button has expected title" 161 ); 162 163 if (test.links[i].valid !== false) { 164 info("Check that clicking on button selects the associated node"); 165 const onSelection = inspector.selection.once("new-node-front"); 166 buttonEl.click(); 167 await onSelection; 168 169 is( 170 inspector.selection.nodeFront.id, 171 expectedReferencedNodeId, 172 "The expected new node was selected" 173 ); 174 } else { 175 info( 176 "Check that clicking on button triggers idref-attribute-link-failed event" 177 ); 178 const onIdrefAttributeLinkFailed = inspector.markup.once( 179 "idref-attribute-link-failed" 180 ); 181 const onSelection = inspector.selection.once("new-node-front"); 182 const onTimeout = wait(500).then(() => "TIMEOUT"); 183 buttonEl.click(); 184 await onIdrefAttributeLinkFailed; 185 ok(true, "Got expected idref-attribute-link-failed event"); 186 const res = await Promise.race([onSelection, onTimeout]); 187 is(res, "TIMEOUT", "Clicking the button did not select a new node"); 188 } 189 } 190 } 191 });