diff options
Diffstat (limited to 'accessible/tests/mochitest/editabletext')
-rw-r--r-- | accessible/tests/mochitest/editabletext/a11y.ini | 7 | ||||
-rw-r--r-- | accessible/tests/mochitest/editabletext/editabletext.js | 353 | ||||
-rw-r--r-- | accessible/tests/mochitest/editabletext/test_1.html | 144 | ||||
-rw-r--r-- | accessible/tests/mochitest/editabletext/test_2.html | 63 |
4 files changed, 567 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/editabletext/a11y.ini b/accessible/tests/mochitest/editabletext/a11y.ini new file mode 100644 index 000000000..68466fdf2 --- /dev/null +++ b/accessible/tests/mochitest/editabletext/a11y.ini @@ -0,0 +1,7 @@ +[DEFAULT] +support-files = + editabletext.js + !/accessible/tests/mochitest/*.js + +[test_1.html] +[test_2.html] diff --git a/accessible/tests/mochitest/editabletext/editabletext.js b/accessible/tests/mochitest/editabletext/editabletext.js new file mode 100644 index 000000000..2fb1851bf --- /dev/null +++ b/accessible/tests/mochitest/editabletext/editabletext.js @@ -0,0 +1,353 @@ +/** + * Perform all editable text tests. + */ +function editableTextTestRun() +{ + this.add = function add(aTest) + { + this.seq.push(aTest); + } + + this.run = function run() + { + this.iterate(); + } + + this.index = 0; + this.seq = new Array(); + + this.iterate = function iterate() + { + if (this.index < this.seq.length) { + this.seq[this.index++].startTest(this); + return; + } + + this.seq = null; + SimpleTest.finish(); + } +} + +/** + * Used to test nsIEditableTextAccessible methods. + */ +function editableTextTest(aID) +{ + /** + * Schedule a test, the given function with its arguments will be executed + * when preceding test is complete. + */ + this.scheduleTest = function scheduleTest(aFunc) + { + // A data container acts like a dummy invoker, it's never invoked but + // it's used to generate real invoker when previous invoker was handled. + var dataContainer = { + func: aFunc, + funcArgs: Array.slice(arguments, 1) + }; + this.mEventQueue.push(dataContainer); + + if (!this.mEventQueueReady) { + this.unwrapNextTest(); + this.mEventQueueReady = true; + } + } + + /** + * setTextContents test. + */ + this.setTextContents = function setTextContents(aValue, aSkipStartOffset) + { + var testID = "setTextContents '" + aValue + "' for " + prettyName(aID); + + function setTextContentsInvoke() + { + dump(`\nsetTextContents '${aValue}'\n`); + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.setTextContents(aValue); + } + + aSkipStartOffset = aSkipStartOffset || 0; + var insertTripple = aValue ? + [ aSkipStartOffset, aSkipStartOffset + aValue.length, aValue ] : null; + var oldValue = getValue(aID); + var removeTripple = oldValue ? + [ aSkipStartOffset, aSkipStartOffset + oldValue.length, oldValue ] : null; + + this.generateTest(aID, removeTripple, insertTripple, setTextContentsInvoke, + getValueChecker(aID, aValue), testID); + } + + /** + * insertText test. + */ + this.insertText = function insertText(aStr, aPos, aResStr, aResPos) + { + var testID = "insertText '" + aStr + "' at " + aPos + " for " + + prettyName(aID); + + function insertTextInvoke() + { + dump(`\ninsertText '${aStr}' at ${aPos} pos\n`); + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.insertText(aStr, aPos); + } + + var resPos = (aResPos != undefined) ? aResPos : aPos; + this.generateTest(aID, null, [resPos, resPos + aStr.length, aStr], + insertTextInvoke, getValueChecker(aID, aResStr), testID); + } + + /** + * copyText test. + */ + this.copyText = function copyText(aStartPos, aEndPos, aClipboardStr) + { + var testID = "copyText from " + aStartPos + " to " + aEndPos + " for " + + prettyName(aID); + + function copyTextInvoke() + { + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.copyText(aStartPos, aEndPos); + } + + this.generateTest(aID, null, null, copyTextInvoke, + getClipboardChecker(aID, aClipboardStr), testID); + } + + /** + * copyText and pasteText test. + */ + this.copyNPasteText = function copyNPasteText(aStartPos, aEndPos, + aPos, aResStr) + { + var testID = "copyText from " + aStartPos + " to " + aEndPos + + "and pasteText at " + aPos + " for " + prettyName(aID); + + function copyNPasteTextInvoke() + { + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.copyText(aStartPos, aEndPos); + acc.pasteText(aPos); + } + + this.generateTest(aID, null, [aStartPos, aEndPos, getTextFromClipboard], + copyNPasteInvoke, getValueChecker(aID, aResStr), testID); + } + + /** + * cutText test. + */ + this.cutText = function cutText(aStartPos, aEndPos, aResStr, + aResStartPos, aResEndPos) + { + var testID = "cutText from " + aStartPos + " to " + aEndPos + " for " + + prettyName(aID); + + function cutTextInvoke() + { + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.cutText(aStartPos, aEndPos); + } + + var resStartPos = (aResStartPos != undefined) ? aResStartPos : aStartPos; + var resEndPos = (aResEndPos != undefined) ? aResEndPos : aEndPos; + this.generateTest(aID, [resStartPos, resEndPos, getTextFromClipboard], null, + cutTextInvoke, getValueChecker(aID, aResStr), testID); + } + + /** + * cutText and pasteText test. + */ + this.cutNPasteText = function copyNPasteText(aStartPos, aEndPos, + aPos, aResStr) + { + var testID = "cutText from " + aStartPos + " to " + aEndPos + + " and pasteText at " + aPos + " for " + prettyName(aID); + + function cutNPasteTextInvoke() + { + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.cutText(aStartPos, aEndPos); + acc.pasteText(aPos); + } + + this.generateTest(aID, [aStartPos, aEndPos, getTextFromClipboard], + [aPos, -1, getTextFromClipboard], + cutNPasteTextInvoke, getValueChecker(aID, aResStr), + testID); + } + + /** + * pasteText test. + */ + this.pasteText = function pasteText(aPos, aResStr) + { + var testID = "pasteText at " + aPos + " for " + prettyName(aID); + + function pasteTextInvoke() + { + var acc = getAccessible(aID, nsIAccessibleEditableText); + acc.pasteText(aPos); + } + + this.generateTest(aID, null, [aPos, -1, getTextFromClipboard], + pasteTextInvoke, getValueChecker(aID, aResStr), testID); + } + + /** + * deleteText test. + */ + this.deleteText = function deleteText(aStartPos, aEndPos, aResStr) + { + var testID = "deleteText from " + aStartPos + " to " + aEndPos + + " for " + prettyName(aID); + + var oldValue = getValue(aID).substring(aStartPos, aEndPos); + var removeTripple = oldValue ? [aStartPos, aEndPos, oldValue] : null; + + function deleteTextInvoke() + { + var acc = getAccessible(aID, [nsIAccessibleEditableText]); + acc.deleteText(aStartPos, aEndPos); + } + + this.generateTest(aID, removeTripple, null, deleteTextInvoke, + getValueChecker(aID, aResStr), testID); + } + + ////////////////////////////////////////////////////////////////////////////// + // Implementation details. + + function getValue(aID) + { + var value = ""; + var elm = getNode(aID); + if (elm instanceof Components.interfaces.nsIDOMNSEditableElement) + return elm.value; + + if (elm instanceof Components.interfaces.nsIDOMHTMLDocument) + return elm.body.textContent; + + return elm.textContent; + } + + /** + * Common checkers. + */ + function getValueChecker(aID, aValue) + { + var checker = { + check: function valueChecker_check() + { + is(getValue(aID), aValue, "Wrong value " + aValue); + } + }; + return checker; + } + + function getClipboardChecker(aID, aText) + { + var checker = { + check: function clipboardChecker_check() + { + is(getTextFromClipboard(), aText, "Wrong text in clipboard."); + } + }; + return checker; + } + + function getValueNClipboardChecker(aID, aValue, aText) + { + var valueChecker = getValueChecker(aID, aValue); + var clipboardChecker = getClipboardChecker(aID, aText); + + var checker = { + check: function() + { + valueChecker.check(); + clipboardChecker.check(); + } + }; + return checker; + } + + /** + * Process next scheduled test. + */ + this.unwrapNextTest = function unwrapNextTest() + { + var data = this.mEventQueue.mInvokers[this.mEventQueue.mIndex + 1]; + if (data) + data.func.apply(this, data.funcArgs); + } + + /** + * Used to generate an invoker object for the sheduled test. + */ + this.generateTest = function generateTest(aID, aRemoveTriple, aInsertTriple, + aInvokeFunc, aChecker, aInvokerID) + { + var et = this; + var invoker = { + eventSeq: [], + + invoke: aInvokeFunc, + finalCheck: function finalCheck() + { + //dumpTree(aID, `'${aID}' tree:`); + + aChecker.check(); + et.unwrapNextTest(); // replace dummy invoker on real invoker object. + }, + getID: function getID() { return aInvokerID; } + }; + + if (aRemoveTriple) { + var checker = new textChangeChecker(aID, aRemoveTriple[0], + aRemoveTriple[1], aRemoveTriple[2], + false); + invoker.eventSeq.push(checker); + } + + if (aInsertTriple) { + var checker = new textChangeChecker(aID, aInsertTriple[0], + aInsertTriple[1], aInsertTriple[2], + true); + invoker.eventSeq.push(checker); + } + + // Claim that we don't want to fail when no events are expected. + if (!aRemoveTriple && !aInsertTriple) + invoker.noEventsOnAction = true; + + this.mEventQueue.mInvokers[this.mEventQueue.mIndex + 1] = invoker; + } + + /** + * Run the tests. + */ + this.startTest = function startTest(aTestRun) + { + var testRunObj = aTestRun; + var thisObj = this; + this.mEventQueue.onFinish = function finishCallback() + { + // Notify textRun object that all tests were finished. + testRunObj.iterate(); + + // Help GC to avoid leaks (refer to aTestRun from local variable, drop + // onFinish function). + thisObj.mEventQueue.onFinish = null; + + return DO_NOT_FINISH_TEST; + } + + this.mEventQueue.invoke(); + } + + this.mEventQueue = new eventQueue(); + this.mEventQueueReady = false; +} + diff --git a/accessible/tests/mochitest/editabletext/test_1.html b/accessible/tests/mochitest/editabletext/test_1.html new file mode 100644 index 000000000..0c0b19696 --- /dev/null +++ b/accessible/tests/mochitest/editabletext/test_1.html @@ -0,0 +1,144 @@ +<!DOCTYPE html> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=452161 +--> +<head> + <title>nsIAccessibleEditableText chrome tests</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../events.js"></script> + <script type="application/javascript" + src="editabletext.js"></script> + + <script type="application/javascript"> + //gA11yEventDumpToConsole = true; + //enableLogging("tree,verbose"); // debug + + function addTestEditable(aID, aTestRun, aBeforeContent, aAfterContent) + { + var et = new editableTextTest(aID); + var startOffset = aBeforeContent ? aBeforeContent.length : 0; + // XXX afterContent currently is not used + + ////////////////////////////////////////////////////////////////////////// + // setTextContents + et.scheduleTest(et.setTextContents, "hello", startOffset); + et.scheduleTest(et.setTextContents, "olleh", startOffset); + et.scheduleTest(et.setTextContents, "", startOffset); + + ////////////////////////////////////////////////////////////////////////// + // insertText + et.scheduleTest(et.insertText, "hello", startOffset, "hello"); + et.scheduleTest(et.insertText, "ma ", startOffset, "ma hello"); + et.scheduleTest(et.insertText, "ma", startOffset + 2, "mama hello"); + et.scheduleTest(et.insertText, " hello", startOffset + 10, "mama hello hello"); + + // XXX: bug 452584 + + ////////////////////////////////////////////////////////////////////////// + // deleteText +// et.deleteText(0, 5, "hello hello"); +// et.deleteText(5, 6, "hellohello"); +// et.deleteText(5, 10, "hello"); +// et.deleteText(0, 5, ""); + + ////////////////////////////////////////////////////////////////////////// + // copyNPasteText +// et.copyNPasteText(0, 0, 0, ""); +// et.insertText("hello", 0, "hello"); +// et.copyNPasteText(0, 1, 0, "hhello"); +// et.copyNPasteText(5, 6, 6, "hhelloo"); +// et.copyNPasteText(3, 4, 1, "hehelloo"); + + ////////////////////////////////////////////////////////////////////////// +// // cutNPasteText +// et.cutNPasteText(0, 1, 1, "ehhelloo"); +// et.cutNPasteText(1, 2, 0, "hehelloo"); +// et.cutNPasteText(7, 8, 8, "hehelloo"); + + aTestRun.add(et); + } + + //gA11yEventDumpToConsole = true; // debug stuff + + function runTest() + { + var testRun = new editableTextTestRun(); + + addTestEditable("input", testRun); + addTestEditable("div", testRun); + addTestEditable("divb", testRun, "pseudo element", ""); + addTestEditable("diva", testRun, "", "pseudo element"); + addTestEditable("divba", testRun, "before", "after"); + addTestEditable(getNode("frame").contentDocument, testRun); + + testRun.run(); // Will call SimpleTest.finish(); + } + + function doTest() + { + // Prepare tested elements. + + // Design mode on/off triggers an editable state change event on + // the document accessible. + var frame = getNode("frame"); + waitForEvent(EVENT_STATE_CHANGE, frame.contentDocument, runTest); + frame.contentDocument.designMode = "on"; + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> + <style> + #divb::before, + #diva::after { + content: "pseudo element"; + } + #divba::before { + content: "before"; + } + #divba::after { + content: "after"; + } + </style> +</head> +<body> + + <a target="_blank" + title="nsIAccessibleEditableText chrome tests" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161"> + Bug 452161 + </a> + <a target="_blank" + title="Cache rendered text on a11y side" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660"> + Bug 626660 + </a> + <a target="_blank" + title="Pseudo element support test" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=1105611"> + Bug 1105611 + </a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <input id="input"/> + + <div id="div" contenteditable="true"></div> + <div id="divb" contenteditable="true"></div> + <div id="diva" contenteditable="true"></div> + <div id="divba" contenteditable="true"></div> + + <iframe id="frame"/> +</body> +</html> diff --git a/accessible/tests/mochitest/editabletext/test_2.html b/accessible/tests/mochitest/editabletext/test_2.html new file mode 100644 index 000000000..5d96ebf35 --- /dev/null +++ b/accessible/tests/mochitest/editabletext/test_2.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<html> +<head> + <title>nsIAccessibleEditableText chrome tests</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../events.js"></script> + <script type="application/javascript" + src="editabletext.js"></script> + + <script type="application/javascript"> + function doTest() + { + var et = new editableTextTest("input"); + + // 'ee' insertion/removal at 1 or 2 offset of 'hello'/'heeello' string + // reports 'ee' text was inserted/removed at 2 offset. + et.scheduleTest(et.insertText, "ee", 1, "heeello", 2); + et.scheduleTest(et.copyText, 1, 3, "ee"); + et.scheduleTest(et.cutText, 1, 3, "hello", 2, 4); + et.scheduleTest(et.insertText, "ee", 2, "heeello", 2); + et.scheduleTest(et.cutText, 2, 4, "hello", 2, 4); + + et.scheduleTest(et.deleteText, 1, 3, "hlo"); + et.scheduleTest(et.pasteText, 1, "heelo"); + + var testRun = new editableTextTestRun(); + testRun.add(et); + testRun.run(); // Will call SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> +<body> + + <a target="_blank" + title="HyperText accessible should get focus when the caret is positioned inside of it, text is changed or copied into clipboard by ATs" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=524115"> + Mozilla Bug 524115 + </a> + <a target="_blank" + title="Cache rendered text on a11y side" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=626660"> + Mozilla Bug 626660 + </a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <input id="input" value="hello"/> + +</body> +</html> |