//////////////////////////////////////////////////////////////////////////////// // Public const BOUNDARY_CHAR = nsIAccessibleText.BOUNDARY_CHAR; const BOUNDARY_WORD_START = nsIAccessibleText.BOUNDARY_WORD_START; const BOUNDARY_WORD_END = nsIAccessibleText.BOUNDARY_WORD_END; const BOUNDARY_LINE_START = nsIAccessibleText.BOUNDARY_LINE_START; const BOUNDARY_LINE_END = nsIAccessibleText.BOUNDARY_LINE_END; const BOUNDARY_ATTRIBUTE_RANGE = nsIAccessibleText.BOUNDARY_ATTRIBUTE_RANGE; const kTodo = 1; const kOk = 2; /** * Test characterCount for the given array of accessibles. * * @param aCount [in] the expected character count * @param aIDs [in] array of accessible identifiers to test */ function testCharacterCount(aIDs, aCount) { for (var i = 0; i < aIDs.length; i++) { var textacc = getAccessible(aIDs[i], [nsIAccessibleText]); is(textacc.characterCount, aCount, "Wrong character count for " + prettyName(aIDs[i])); } } /** * Test text between two given offsets * * @param aIDs [in] an array of accessible IDs to test * @param aStartOffset [in] the start offset within the text to test * @param aEndOffset [in] the end offset up to which the text is tested * @param aText [in] the expected result from the test */ function testText(aIDs, aStartOffset, aEndOffset, aText) { for (var i = 0; i < aIDs.length; i++) { var acc = getAccessible(aIDs[i], nsIAccessibleText); try { is(acc.getText(aStartOffset, aEndOffset), aText, "getText: wrong text between start and end offsets '" + aStartOffset + "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'"); } catch (e) { ok(false, "getText fails between start and end offsets '" + aStartOffset + "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'"); } } } /** * Test password text between two given offsets * * @param aIDs [in] an array of accessible IDs to test * @param aStartOffset [in] the start offset within the text to test * @param aEndOffset [in] the end offset up to which the text is tested * @param aText [in] the expected result from the test * * @note All this function does is test that getText doe snot expose the * password text itself, but something else. */ function testPasswordText(aIDs, aStartOffset, aEndOffset, aText) { for (var i = 0; i < aIDs.length; i++) { var acc = getAccessible(aIDs[i], nsIAccessibleText); try { isnot(acc.getText(aStartOffset, aEndOffset), aText, "getText: plain text between start and end offsets '" + aStartOffset + "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'"); } catch (e) { ok(false, "getText fails between start and end offsets '" + aStartOffset + "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'"); } } } /** * Test getTextAtOffset for BOUNDARY_CHAR over different elements. * * @param aIDs [in] the accessible identifier or array of accessible * identifiers * @param aOffset [in] the offset to get a character at it * @param aChar [in] the expected character * @param aStartOffset [in] expected start offset of the character * @param aEndOffset [in] expected end offset of the character */ function testCharAtOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) { var IDs = (aIDs instanceof Array) ? aIDs : [ aIDs ]; for (var i = 0; i < IDs.length; i++) { var acc = getAccessible(IDs[i], nsIAccessibleText); testTextHelper(IDs[i], aOffset, BOUNDARY_CHAR, aChar, aStartOffset, aEndOffset, kOk, kOk, kOk, acc.getTextAtOffset, "getTextAtOffset "); } } /** * Test getTextAtOffset function over different elements * * @param aOffset [in] the offset to get the text at * @param aBoundaryType [in] Boundary type for text to be retrieved * @param aText [in] expected return text for getTextAtOffset * @param aStartOffset [in] expected return start offset for getTextAtOffset * @param aEndOffset [in] expected return end offset for getTextAtOffset * @param ... [in] list of tuples made of: * element identifier * kTodo or kOk for returned text * kTodo or kOk for returned start offset * kTodo or kOk for returned offset result * */ function testTextAtOffset(aOffset, aBoundaryType, aText, aStartOffset, aEndOffset) { for (var i = 5; i < arguments.length; i = i + 4) { var ID = arguments[i]; var acc = getAccessible(ID, nsIAccessibleText); var toDoFlag1 = arguments[i + 1]; var toDoFlag2 = arguments[i + 2]; var toDoFlag3 = arguments[i + 3]; testTextHelper(ID, aOffset, aBoundaryType, aText, aStartOffset, aEndOffset, toDoFlag1, toDoFlag2, toDoFlag3, acc.getTextAtOffset, "getTextAtOffset "); } } /** * Test getTextAfterOffset for BOUNDARY_CHAR over different elements. * * @param aIDs [in] the accessible identifier or array of accessible * identifiers * @param aOffset [in] the offset to get a character after it * @param aChar [in] the expected character * @param aStartOffset [in] expected start offset of the character * @param aEndOffset [in] expected end offset of the character */ function testCharAfterOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) { var IDs = (aIDs instanceof Array) ? aIDs : [ aIDs ]; for (var i = 0; i < IDs.length; i++) { var acc = getAccessible(IDs[i], nsIAccessibleText); testTextHelper(IDs[i], aOffset, BOUNDARY_CHAR, aChar, aStartOffset, aEndOffset, kOk, kOk, kOk, acc.getTextAfterOffset, "getTextAfterOffset "); } } /** * Test getTextAfterOffset function over different elements * * @param aOffset [in] the offset to get the text after * @param aBoundaryType [in] Boundary type for text to be retrieved * @param aText [in] expected return text for getTextAfterOffset * @param aStartOffset [in] expected return start offset for getTextAfterOffset * @param aEndOffset [in] expected return end offset for getTextAfterOffset * @param ... [in] list of tuples made of: * element identifier * kTodo or kOk for returned text * kTodo or kOk for returned start offset * kTodo or kOk for returned offset result */ function testTextAfterOffset(aOffset, aBoundaryType, aText, aStartOffset, aEndOffset) { for (var i = 5; i < arguments.length; i = i + 4) { var ID = arguments[i]; var acc = getAccessible(ID, nsIAccessibleText); var toDoFlag1 = arguments[i + 1]; var toDoFlag2 = arguments[i + 2]; var toDoFlag3 = arguments[i + 3]; testTextHelper(ID, aOffset, aBoundaryType, aText, aStartOffset, aEndOffset, toDoFlag1, toDoFlag2, toDoFlag3, acc.getTextAfterOffset, "getTextAfterOffset "); } } /** * Test getTextBeforeOffset for BOUNDARY_CHAR over different elements. * * @param aIDs [in] the accessible identifier or array of accessible * identifiers * @param aOffset [in] the offset to get a character before it * @param aChar [in] the expected character * @param aStartOffset [in] expected start offset of the character * @param aEndOffset [in] expected end offset of the character */ function testCharBeforeOffset(aIDs, aOffset, aChar, aStartOffset, aEndOffset) { var IDs = (aIDs instanceof Array) ? aIDs : [ aIDs ]; for (var i = 0; i < IDs.length; i++) { var acc = getAccessible(IDs[i], nsIAccessibleText); testTextHelper(IDs[i], aOffset, BOUNDARY_CHAR, aChar, aStartOffset, aEndOffset, kOk, kOk, kOk, acc.getTextBeforeOffset, "getTextBeforeOffset "); } } /** * Test getTextBeforeOffset function over different elements * * @param aOffset [in] the offset to get the text before * @param aBoundaryType [in] Boundary type for text to be retrieved * @param aText [in] expected return text for getTextBeforeOffset * @param aStartOffset [in] expected return start offset for getTextBeforeOffset * @param aEndOffset [in] expected return end offset for getTextBeforeOffset * @param ... [in] list of tuples made of: * element identifier * kTodo or kOk for returned text * kTodo or kOk for returned start offset * kTodo or kOk for returned offset result * */ function testTextBeforeOffset(aOffset, aBoundaryType, aText, aStartOffset, aEndOffset) { for (var i = 5; i < arguments.length; i = i + 4) { var ID = arguments[i]; var acc = getAccessible(ID, nsIAccessibleText); var toDoFlag1 = arguments[i + 1]; var toDoFlag2 = arguments[i + 2]; var toDoFlag3 = arguments[i + 3]; testTextHelper(ID, aOffset, aBoundaryType, aText, aStartOffset, aEndOffset, toDoFlag1, toDoFlag2, toDoFlag3, acc.getTextBeforeOffset, "getTextBeforeOffset "); } } /** * Test word count for an element. * * @param aElement [in] element identifier * @param aCount [in] Expected word count * @param aToDoFlag [in] kTodo or kOk for returned text */ function testWordCount(aElement, aCount, aToDoFlag) { var isFunc = (aToDoFlag == kTodo) ? todo_is : is; var acc = getAccessible(aElement, nsIAccessibleText); var startOffsetObj = {}, endOffsetObj = {}; var length = acc.characterCount; var offset = 0; var wordCount = 0; while (true) { var text = acc.getTextAtOffset(offset, BOUNDARY_WORD_START, startOffsetObj, endOffsetObj); if (offset >= length) break; wordCount++; offset = endOffsetObj.value; } isFunc(wordCount, aCount, "wrong words count for '" + acc.getText(0, -1) + "': " + wordCount); } /** * Test word at a position for an element. * * @param aElement [in] element identifier * @param aWordIndex [in] index of the word to test * @param aText [in] expected text for that word * @param aToDoFlag [in] kTodo or kOk for returned text */ function testWordAt(aElement, aWordIndex, aText, aToDoFlag) { var isFunc = (aToDoFlag == kTodo) ? todo_is : is; var acc = getAccessible(aElement, nsIAccessibleText); var startOffsetObj = {}, endOffsetObj = {}; var length = acc.characterCount; var offset = 0; var wordIndex = -1; var wordFountAtOffset = -1; while (true) { var text = acc.getTextAtOffset(offset, BOUNDARY_WORD_START, startOffsetObj, endOffsetObj); if (offset >= length) break; wordIndex++; offset = endOffsetObj.value; if (wordIndex == aWordIndex) { wordFountAtOffset = startOffsetObj.value; break; } } if (wordFountAtOffset >= 0) { var text = acc.getTextAtOffset(wordFountAtOffset, BOUNDARY_WORD_END, startOffsetObj, endOffsetObj); if (endOffsetObj.value < wordFountAtOffset) { todo(false, "wrong start and end offset for word '" + aWordIndex + "': " + " of text '" + acc.getText(0, -1) + "'"); return; } text = acc.getText(wordFountAtOffset, endOffsetObj.value); isFunc(text, aText, "wrong text for word at pos '" + aWordIndex + "': " + " of text '" + acc.getText(0, -1) + "'"); } else { isFunc(false, "failed to find word " + aText + " at word pos " + aWordIndex + " of text '" + acc.getText(0, -1) + "'"); } } /** * Test words in a element. * * @param aElement [in] element identifier * @param aWords [in] array of expected words * @param aToDoFlag [in, optional] kTodo or kOk for returned text */ function testWords(aElement, aWords, aToDoFlag) { if (aToDoFlag == null) aToDoFlag = kOk; testWordCount(aElement, aWords.length, aToDoFlag); for (var i = 0; i < aWords.length; i++) { testWordAt(aElement, i, aWords[i], aToDoFlag); } } /** * Remove all selections. * * @param aID [in] Id, DOM node, or acc obj */ function cleanTextSelections(aID) { var acc = getAccessible(aID, [nsIAccessibleText]); while (acc.selectionCount > 0) acc.removeSelection(0); } /** * Test addSelection method. * * @param aID [in] Id, DOM node, or acc obj * @param aStartOffset [in] start offset for the new selection * @param aEndOffset [in] end offset for the new selection * @param aSelectionsCount [in] expected number of selections after addSelection */ function testTextAddSelection(aID, aStartOffset, aEndOffset, aSelectionsCount) { var acc = getAccessible(aID, [nsIAccessibleText]); var text = acc.getText(0, -1); acc.addSelection(aStartOffset, aEndOffset); ok(acc.selectionCount, aSelectionsCount, text + ": failed to add selection from offset '" + aStartOffset + "' to offset '" + aEndOffset + "': selectionCount after"); } /** * Test removeSelection method. * * @param aID [in] Id, DOM node, or acc obj * @param aSelectionIndex [in] index of the selection to be removed * @param aSelectionsCount [in] expected number of selections after * removeSelection */ function testTextRemoveSelection(aID, aSelectionIndex, aSelectionsCount) { var acc = getAccessible(aID, [nsIAccessibleText]); var text = acc.getText(0, -1); acc.removeSelection(aSelectionIndex); ok(acc.selectionCount, aSelectionsCount, text + ": failed to remove selection at index '" + aSelectionIndex + "': selectionCount after"); } /** * Test setSelectionBounds method. * * @param aID [in] Id, DOM node, or acc obj * @param aStartOffset [in] new start offset for the selection * @param aEndOffset [in] new end offset for the selection * @param aSelectionIndex [in] index of the selection to set * @param aSelectionsCount [in] expected number of selections after * setSelectionBounds */ function testTextSetSelection(aID, aStartOffset, aEndOffset, aSelectionIndex, aSelectionsCount) { var acc = getAccessible(aID, [nsIAccessibleText]); var text = acc.getText(0, -1); acc.setSelectionBounds(aSelectionIndex, aStartOffset, aEndOffset); is(acc.selectionCount, aSelectionsCount, text + ": failed to set selection at index '" + aSelectionIndex + "': selectionCount after"); } /** * Test selectionCount method. * * @param aID [in] Id, DOM node, or acc obj * @param aCount [in] expected selection count */ function testTextSelectionCount(aID, aCount) { var acc = getAccessible(aID, [nsIAccessibleText]); var text = acc.getText(0, -1); is(acc.selectionCount, aCount, text + ": wrong selectionCount: "); } /** * Test getSelectionBounds method. * * @param aID [in] Id, DOM node, or acc obj * @param aStartOffset [in] expected start offset for the selection * @param aEndOffset [in] expected end offset for the selection * @param aSelectionIndex [in] index of the selection to get */ function testTextGetSelection(aID, aStartOffset, aEndOffset, aSelectionIndex) { var acc = getAccessible(aID, [nsIAccessibleText]); var text = acc.getText(0, -1); var startObj = {}, endObj = {}; acc.getSelectionBounds(aSelectionIndex, startObj, endObj); is(startObj.value, aStartOffset, text + ": wrong start offset for index '" + aSelectionIndex + "'"); is(endObj.value, aEndOffset, text + ": wrong end offset for index '" + aSelectionIndex + "'"); } //////////////////////////////////////////////////////////////////////////////// // Private function testTextHelper(aID, aOffset, aBoundaryType, aText, aStartOffset, aEndOffset, aToDoFlag1, aToDoFlag2, aToDoFlag3, aTextFunc, aTextFuncName) { var exceptionFlag = aToDoFlag1 == undefined || aToDoFlag2 == undefined || aToDoFlag3 == undefined; try { var startOffsetObj = {}, endOffsetObj = {}; var text = aTextFunc(aOffset, aBoundaryType, startOffsetObj, endOffsetObj); var isFunc1 = (aToDoFlag1 == kTodo) ? todo_is : is; var isFunc2 = (aToDoFlag2 == kTodo) ? todo_is : is; var isFunc3 = (aToDoFlag3 == kTodo) ? todo_is : is; var startMsg = aTextFuncName + "(" + boundaryToString(aBoundaryType) + "): "; var endMsg = ", id: '" + prettyName(aID) + "';"; isFunc1(text, aText, startMsg + "wrong text, offset: " + aOffset + endMsg); isFunc2(startOffsetObj.value, aStartOffset, startMsg + "wrong start offset, offset: " + aOffset + endMsg); isFunc3(endOffsetObj.value, aEndOffset, startMsg + "wrong end offset, offset: " + aOffset + endMsg); } catch (e) { var okFunc = exceptionFlag ? todo : ok; okFunc(false, startMsg + "failed at offset " + aOffset + endMsg); } } function boundaryToString(aBoundaryType) { switch (aBoundaryType) { case BOUNDARY_CHAR: return "char"; case BOUNDARY_WORD_START: return "word start"; case BOUNDARY_WORD_END: return "word end"; case BOUNDARY_LINE_START: return "line start"; case BOUNDARY_LINE_END: return "line end"; case BOUNDARY_ATTRIBUTE_RANGE: return "attr range"; } }