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.js409
-rw-r--r--accessible/tests/mochitest/editabletext/test_1.html140
-rw-r--r--accessible/tests/mochitest/editabletext/test_2.html61
4 files changed, 617 insertions, 0 deletions
diff --git a/accessible/tests/mochitest/editabletext/a11y.ini b/accessible/tests/mochitest/editabletext/a11y.ini
new file mode 100644
index 0000000000..68466fdf23
--- /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 0000000000..ef305c7842
--- /dev/null
+++ b/accessible/tests/mochitest/editabletext/editabletext.js
@@ -0,0 +1,409 @@
+/* import-globals-from ../common.js */
+/* import-globals-from ../events.js */
+
+/**
+ * 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 = [];
+
+ 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, ...aFuncArgs) {
+ // 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: aFuncArgs,
+ };
+ 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();
+ var removeTripple = oldValue
+ ? [aSkipStartOffset, aSkipStartOffset + oldValue.length, oldValue]
+ : null;
+
+ this.generateTest(
+ removeTripple,
+ insertTripple,
+ setTextContentsInvoke,
+ getValueChecker(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(
+ null,
+ [resPos, resPos + aStr.length, aStr],
+ insertTextInvoke,
+ getValueChecker(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(
+ null,
+ null,
+ copyTextInvoke,
+ getClipboardChecker(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(
+ null,
+ [aStartPos, aEndPos, getTextFromClipboard],
+ copyNPasteTextInvoke,
+ getValueChecker(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(
+ [resStartPos, resEndPos, getTextFromClipboard],
+ null,
+ cutTextInvoke,
+ getValueChecker(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(
+ [aStartPos, aEndPos, getTextFromClipboard],
+ [aPos, -1, getTextFromClipboard],
+ cutNPasteTextInvoke,
+ getValueChecker(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(
+ null,
+ [aPos, -1, getTextFromClipboard],
+ pasteTextInvoke,
+ getValueChecker(aResStr),
+ testID
+ );
+ };
+
+ /**
+ * deleteText test.
+ */
+ this.deleteText = function deleteText(aStartPos, aEndPos, aResStr) {
+ var testID =
+ "deleteText from " +
+ aStartPos +
+ " to " +
+ aEndPos +
+ " for " +
+ prettyName(aID);
+
+ var oldValue = getValue().substring(aStartPos, aEndPos);
+ var removeTripple = oldValue ? [aStartPos, aEndPos, oldValue] : null;
+
+ function deleteTextInvoke() {
+ var acc = getAccessible(aID, [nsIAccessibleEditableText]);
+ acc.deleteText(aStartPos, aEndPos);
+ }
+
+ this.generateTest(
+ removeTripple,
+ null,
+ deleteTextInvoke,
+ getValueChecker(aResStr),
+ testID
+ );
+ };
+
+ // ////////////////////////////////////////////////////////////////////////////
+ // Implementation details.
+
+ function getValue() {
+ var elm = getNode(aID);
+ var elmClass = ChromeUtils.getClassName(elm);
+ if (elmClass === "HTMLTextAreaElement" || elmClass === "HTMLInputElement") {
+ return elm.value;
+ }
+
+ if (elmClass === "HTMLDocument") {
+ return elm.body.textContent;
+ }
+
+ return elm.textContent;
+ }
+
+ /**
+ * Common checkers.
+ */
+ function getValueChecker(aValue) {
+ var checker = {
+ check: function valueChecker_check() {
+ is(getValue(), aValue, "Wrong value " + aValue);
+ },
+ };
+ return checker;
+ }
+
+ function getClipboardChecker(aText) {
+ var checker = {
+ check: function clipboardChecker_check() {
+ is(getTextFromClipboard(), aText, "Wrong text in clipboard.");
+ },
+ };
+ 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(
+ 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) {
+ let checker = new textChangeChecker(
+ aID,
+ aRemoveTriple[0],
+ aRemoveTriple[1],
+ aRemoveTriple[2],
+ false
+ );
+ invoker.eventSeq.push(checker);
+ }
+
+ if (aInsertTriple) {
+ let 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 0000000000..693d4c8ee5
--- /dev/null
+++ b/accessible/tests/mochitest/editabletext/test_1.html
@@ -0,0 +1,140 @@
+<!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 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, "katze", 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 0000000000..1d252d836f
--- /dev/null
+++ b/accessible/tests/mochitest/editabletext/test_2.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>nsIAccessibleEditableText chrome tests</title>
+ <link rel="stylesheet" type="text/css"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+ <script 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>