michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // Constants michael@0: michael@0: const RELATION_CONTROLLED_BY = nsIAccessibleRelation.RELATION_CONTROLLED_BY; michael@0: const RELATION_CONTROLLER_FOR = nsIAccessibleRelation.RELATION_CONTROLLER_FOR; michael@0: const RELATION_DEFAULT_BUTTON = nsIAccessibleRelation.RELATION_DEFAULT_BUTTON; michael@0: const RELATION_DESCRIBED_BY = nsIAccessibleRelation.RELATION_DESCRIBED_BY; michael@0: const RELATION_DESCRIPTION_FOR = nsIAccessibleRelation.RELATION_DESCRIPTION_FOR; michael@0: const RELATION_EMBEDDED_BY = nsIAccessibleRelation.RELATION_EMBEDDED_BY; michael@0: const RELATION_EMBEDS = nsIAccessibleRelation.RELATION_EMBEDS; michael@0: const RELATION_FLOWS_FROM = nsIAccessibleRelation.RELATION_FLOWS_FROM; michael@0: const RELATION_FLOWS_TO = nsIAccessibleRelation.RELATION_FLOWS_TO; michael@0: const RELATION_LABEL_FOR = nsIAccessibleRelation.RELATION_LABEL_FOR; michael@0: const RELATION_LABELLED_BY = nsIAccessibleRelation.RELATION_LABELLED_BY; michael@0: const RELATION_MEMBER_OF = nsIAccessibleRelation.RELATION_MEMBER_OF; michael@0: const RELATION_NODE_CHILD_OF = nsIAccessibleRelation.RELATION_NODE_CHILD_OF; michael@0: const RELATION_NODE_PARENT_OF = nsIAccessibleRelation.RELATION_NODE_PARENT_OF; michael@0: const RELATION_PARENT_WINDOW_OF = nsIAccessibleRelation.RELATION_PARENT_WINDOW_OF; michael@0: const RELATION_POPUP_FOR = nsIAccessibleRelation.RELATION_POPUP_FOR; michael@0: const RELATION_SUBWINDOW_OF = nsIAccessibleRelation.RELATION_SUBWINDOW_OF; michael@0: const RELATION_CONTAINING_DOCUMENT = nsIAccessibleRelation.RELATION_CONTAINING_DOCUMENT; michael@0: const RELATION_CONTAINING_TAB_PANE = nsIAccessibleRelation.RELATION_CONTAINING_TAB_PANE; michael@0: const RELATION_CONTAINING_APPLICATION = nsIAccessibleRelation.RELATION_CONTAINING_APPLICATION; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // General michael@0: michael@0: /** michael@0: * Test the accessible relation. michael@0: * michael@0: * @param aIdentifier [in] identifier to get an accessible, may be ID michael@0: * attribute or DOM element or accessible object michael@0: * @param aRelType [in] relation type (see constants above) michael@0: * @param aRelatedIdentifiers [in] identifier or array of identifiers of michael@0: * expected related accessibles michael@0: */ michael@0: function testRelation(aIdentifier, aRelType, aRelatedIdentifiers) michael@0: { michael@0: var relation = getRelationByType(aIdentifier, aRelType); michael@0: michael@0: var relDescr = getRelationErrorMsg(aIdentifier, aRelType); michael@0: var relDescrStart = getRelationErrorMsg(aIdentifier, aRelType, true); michael@0: michael@0: if (!relation || !relation.targetsCount) { michael@0: if (!aRelatedIdentifiers) { michael@0: ok(true, "No" + relDescr); michael@0: return; michael@0: } michael@0: michael@0: var msg = relDescrStart + "has no expected targets: '" + michael@0: prettyName(aRelatedIdentifiers) + "'"; michael@0: michael@0: ok(false, msg); michael@0: return; michael@0: michael@0: } else if (!aRelatedIdentifiers) { michael@0: ok(false, "There are unexpected targets of " + relDescr); michael@0: return; michael@0: } michael@0: michael@0: var relatedIds = (aRelatedIdentifiers instanceof Array) ? michael@0: aRelatedIdentifiers : [aRelatedIdentifiers]; michael@0: michael@0: var targets = []; michael@0: for (var idx = 0; idx < relatedIds.length; idx++) michael@0: targets.push(getAccessible(relatedIds[idx])); michael@0: michael@0: if (targets.length != relatedIds.length) michael@0: return; michael@0: michael@0: var actualTargets = relation.getTargets(); michael@0: michael@0: // Check if all given related accessibles are targets of obtained relation. michael@0: for (var idx = 0; idx < targets.length; idx++) { michael@0: var isFound = false; michael@0: var enumerate = actualTargets.enumerate(); michael@0: while (enumerate.hasMoreElements()) { michael@0: var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible); michael@0: if (targets[idx] == relatedAcc) { michael@0: isFound = true; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr); michael@0: } michael@0: michael@0: // Check if all obtained targets are given related accessibles. michael@0: var enumerate = actualTargets.enumerate(); michael@0: while (enumerate.hasMoreElements()) { michael@0: var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible); michael@0: for (var idx = 0; idx < targets.length && relatedAcc != targets[idx]; idx++); michael@0: michael@0: if (idx == targets.length) michael@0: ok(false, "There is unexpected target" + prettyName(relatedAcc) + "of" + relDescr); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Test that the given accessible relations don't exist. michael@0: * michael@0: * @param aIdentifier [in] identifier to get an accessible, may be ID michael@0: * attribute or DOM element or accessible object michael@0: * @param aRelType [in] relation type (see constants above) michael@0: * @param aUnrelatedIdentifiers [in] identifier or array of identifiers of michael@0: * accessibles that shouldn't exist for this michael@0: * relation. michael@0: */ michael@0: function testAbsentRelation(aIdentifier, aRelType, aUnrelatedIdentifiers) michael@0: { michael@0: var relation = getRelationByType(aIdentifier, aRelType); michael@0: michael@0: var relDescr = getRelationErrorMsg(aIdentifier, aRelType); michael@0: var relDescrStart = getRelationErrorMsg(aIdentifier, aRelType, true); michael@0: michael@0: if (!aUnrelatedIdentifiers) { michael@0: ok(false, "No identifiers given for unrelated accessibles."); michael@0: return; michael@0: } michael@0: michael@0: if (!relation || !relation.targetsCount) { michael@0: ok(true, "No relations exist."); michael@0: return; michael@0: } michael@0: michael@0: var relatedIds = (aUnrelatedIdentifiers instanceof Array) ? michael@0: aUnrelatedIdentifiers : [aUnrelatedIdentifiers]; michael@0: michael@0: var targets = []; michael@0: for (var idx = 0; idx < relatedIds.length; idx++) michael@0: targets.push(getAccessible(relatedIds[idx])); michael@0: michael@0: if (targets.length != relatedIds.length) michael@0: return; michael@0: michael@0: var actualTargets = relation.getTargets(); michael@0: michael@0: // Any found targets that match given accessibles should be called out. michael@0: for (var idx = 0; idx < targets.length; idx++) { michael@0: var notFound = true; michael@0: var enumerate = actualTargets.enumerate(); michael@0: while (enumerate.hasMoreElements()) { michael@0: var relatedAcc = enumerate.getNext().QueryInterface(nsIAccessible); michael@0: if (targets[idx] == relatedAcc) { michael@0: notFound = false; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: ok(notFound, prettyName(relatedIds[idx]) + " is a target of " + relDescr); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Return related accessible for the given relation type. michael@0: * michael@0: * @param aIdentifier [in] identifier to get an accessible, may be ID attribute michael@0: * or DOM element or accessible object michael@0: * @param aRelType [in] relation type (see constants above) michael@0: */ michael@0: function getRelationByType(aIdentifier, aRelType) michael@0: { michael@0: var acc = getAccessible(aIdentifier); michael@0: if (!acc) michael@0: return; michael@0: michael@0: var relation = null; michael@0: try { michael@0: relation = acc.getRelationByType(aRelType); michael@0: } catch (e) { michael@0: ok(false, "Can't get" + getRelationErrorMsg(aIdentifier, aRelType)); michael@0: } michael@0: michael@0: return relation; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // Private implementation details michael@0: michael@0: function getRelationErrorMsg(aIdentifier, aRelType, aIsStartSentence) michael@0: { michael@0: var relStr = relationTypeToString(aRelType); michael@0: var msg = aIsStartSentence ? "Relation of '" : " relation of '"; michael@0: msg += relStr + "' type for '" + prettyName(aIdentifier) + "'"; michael@0: msg += aIsStartSentence ? " " : "."; michael@0: michael@0: return msg; michael@0: }