summaryrefslogtreecommitdiffstats
path: root/accessible/tests/mochitest/editabletext
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/tests/mochitest/editabletext')
-rw-r--r--accessible/tests/mochitest/editabletext/a11y.ini7
-rw-r--r--accessible/tests/mochitest/editabletext/editabletext.js353
-rw-r--r--accessible/tests/mochitest/editabletext/test_1.html144
-rw-r--r--accessible/tests/mochitest/editabletext/test_2.html63
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>