relations.js (7163B)
1 /* import-globals-from common.js */ 2 3 // ////////////////////////////////////////////////////////////////////////////// 4 // Constants 5 6 var RELATION_CONTROLLED_BY = nsIAccessibleRelation.RELATION_CONTROLLED_BY; 7 var RELATION_CONTROLLER_FOR = nsIAccessibleRelation.RELATION_CONTROLLER_FOR; 8 var RELATION_DEFAULT_BUTTON = nsIAccessibleRelation.RELATION_DEFAULT_BUTTON; 9 var RELATION_DESCRIBED_BY = nsIAccessibleRelation.RELATION_DESCRIBED_BY; 10 var RELATION_DESCRIPTION_FOR = nsIAccessibleRelation.RELATION_DESCRIPTION_FOR; 11 var RELATION_EMBEDDED_BY = nsIAccessibleRelation.RELATION_EMBEDDED_BY; 12 var RELATION_EMBEDS = nsIAccessibleRelation.RELATION_EMBEDS; 13 var RELATION_FLOWS_FROM = nsIAccessibleRelation.RELATION_FLOWS_FROM; 14 var RELATION_FLOWS_TO = nsIAccessibleRelation.RELATION_FLOWS_TO; 15 var RELATION_LABEL_FOR = nsIAccessibleRelation.RELATION_LABEL_FOR; 16 var RELATION_LABELLED_BY = nsIAccessibleRelation.RELATION_LABELLED_BY; 17 var RELATION_MEMBER_OF = nsIAccessibleRelation.RELATION_MEMBER_OF; 18 var RELATION_NODE_CHILD_OF = nsIAccessibleRelation.RELATION_NODE_CHILD_OF; 19 var RELATION_NODE_PARENT_OF = nsIAccessibleRelation.RELATION_NODE_PARENT_OF; 20 var RELATION_PARENT_WINDOW_OF = nsIAccessibleRelation.RELATION_PARENT_WINDOW_OF; 21 var RELATION_POPUP_FOR = nsIAccessibleRelation.RELATION_POPUP_FOR; 22 var RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF; 23 var RELATION_CONTAINING_DOCUMENT = 24 nsIAccessibleRelation.RELATION_CONTAINING_DOCUMENT; 25 var RELATION_CONTAINING_TAB_PANE = 26 nsIAccessibleRelation.RELATION_CONTAINING_TAB_PANE; 27 var RELATION_CONTAINING_APPLICATION = 28 nsIAccessibleRelation.RELATION_CONTAINING_APPLICATION; 29 const RELATION_DETAILS = nsIAccessibleRelation.RELATION_DETAILS; 30 const RELATION_DETAILS_FOR = nsIAccessibleRelation.RELATION_DETAILS_FOR; 31 const RELATION_ERRORMSG = nsIAccessibleRelation.RELATION_ERRORMSG; 32 const RELATION_ERRORMSG_FOR = nsIAccessibleRelation.RELATION_ERRORMSG_FOR; 33 const RELATION_LINKS_TO = nsIAccessibleRelation.RELATION_LINKS_TO; 34 const RELATION_ACTION = nsIAccessibleRelation.RELATION_ACTION; 35 const RELATION_ACTION_FOR = nsIAccessibleRelation.RELATION_ACTION_FOR; 36 37 // ////////////////////////////////////////////////////////////////////////////// 38 // General 39 40 /** 41 * Test the accessible relation. 42 * 43 * @param aIdentifier [in] identifier to get an accessible, may be ID 44 * attribute or DOM element or accessible object 45 * @param aRelType [in] relation type (see constants above) 46 * @param aRelatedIdentifiers [in] identifier or array of identifiers of 47 * expected related accessibles 48 */ 49 function testRelation(aIdentifier, aRelType, aRelatedIdentifiers) { 50 var relation = getRelationByType(aIdentifier, aRelType); 51 52 var relDescr = getRelationErrorMsg(aIdentifier, aRelType); 53 var relDescrStart = getRelationErrorMsg(aIdentifier, aRelType, true); 54 55 if (!relation || !relation.targetsCount) { 56 if (!aRelatedIdentifiers) { 57 ok(true, "No" + relDescr); 58 return; 59 } 60 61 var msg = 62 relDescrStart + 63 "has no expected targets: '" + 64 prettyName(aRelatedIdentifiers) + 65 "'"; 66 67 ok(false, msg); 68 return; 69 } else if (!aRelatedIdentifiers) { 70 ok(false, "There are unexpected targets of " + relDescr); 71 return; 72 } 73 74 var relatedIds = 75 aRelatedIdentifiers instanceof Array 76 ? aRelatedIdentifiers 77 : [aRelatedIdentifiers]; 78 79 var targets = []; 80 for (let idx = 0; idx < relatedIds.length; idx++) { 81 targets.push(getAccessible(relatedIds[idx])); 82 } 83 84 if (targets.length != relatedIds.length) { 85 return; 86 } 87 88 var actualTargets = relation.getTargets(); 89 90 // Check if all given related accessibles are targets of obtained relation. 91 for (let idx = 0; idx < targets.length; idx++) { 92 var isFound = false; 93 for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) { 94 if (targets[idx] == relatedAcc) { 95 isFound = true; 96 break; 97 } 98 } 99 100 ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr); 101 } 102 103 // Check if all obtained targets are given related accessibles. 104 for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) { 105 let idx; 106 // eslint-disable-next-line no-empty 107 for (idx = 0; idx < targets.length && relatedAcc != targets[idx]; idx++) {} 108 109 if (idx == targets.length) { 110 ok( 111 false, 112 "There is unexpected target" + prettyName(relatedAcc) + "of" + relDescr 113 ); 114 } 115 } 116 } 117 118 /** 119 * Test that the given accessible relations don't exist. 120 * 121 * @param aIdentifier [in] identifier to get an accessible, may be ID 122 * attribute or DOM element or accessible object 123 * @param aRelType [in] relation type (see constants above) 124 * @param aUnrelatedIdentifiers [in] identifier or array of identifiers of 125 * accessibles that shouldn't exist for this 126 * relation. 127 */ 128 function testAbsentRelation(aIdentifier, aRelType, aUnrelatedIdentifiers) { 129 var relation = getRelationByType(aIdentifier, aRelType); 130 131 var relDescr = getRelationErrorMsg(aIdentifier, aRelType); 132 133 if (!aUnrelatedIdentifiers) { 134 ok(false, "No identifiers given for unrelated accessibles."); 135 return; 136 } 137 138 if (!relation || !relation.targetsCount) { 139 ok(true, "No relations exist."); 140 return; 141 } 142 143 var relatedIds = 144 aUnrelatedIdentifiers instanceof Array 145 ? aUnrelatedIdentifiers 146 : [aUnrelatedIdentifiers]; 147 148 var targets = []; 149 for (let idx = 0; idx < relatedIds.length; idx++) { 150 targets.push(getAccessible(relatedIds[idx])); 151 } 152 153 if (targets.length != relatedIds.length) { 154 return; 155 } 156 157 var actualTargets = relation.getTargets(); 158 159 // Any found targets that match given accessibles should be called out. 160 for (let idx = 0; idx < targets.length; idx++) { 161 var notFound = true; 162 for (let relatedAcc of actualTargets.enumerate(Ci.nsIAccessible)) { 163 if (targets[idx] == relatedAcc) { 164 notFound = false; 165 break; 166 } 167 } 168 169 ok(notFound, prettyName(relatedIds[idx]) + " is a target of " + relDescr); 170 } 171 } 172 173 /** 174 * Return related accessible for the given relation type. 175 * 176 * @param aIdentifier [in] identifier to get an accessible, may be ID attribute 177 * or DOM element or accessible object 178 * @param aRelType [in] relation type (see constants above) 179 */ 180 function getRelationByType(aIdentifier, aRelType) { 181 var acc = getAccessible(aIdentifier); 182 if (!acc) { 183 return null; 184 } 185 186 var relation = null; 187 try { 188 relation = acc.getRelationByType(aRelType); 189 } catch (e) { 190 ok(false, "Can't get" + getRelationErrorMsg(aIdentifier, aRelType)); 191 } 192 193 return relation; 194 } 195 196 // ////////////////////////////////////////////////////////////////////////////// 197 // Private implementation details 198 199 function getRelationErrorMsg(aIdentifier, aRelType, aIsStartSentence) { 200 var relStr = relationTypeToString(aRelType); 201 var msg = aIsStartSentence ? "Relation of '" : " relation of '"; 202 msg += relStr + "' type for '" + prettyName(aIdentifier) + "'"; 203 msg += aIsStartSentence ? " " : "."; 204 205 return msg; 206 }