зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1832353 - P2: Convert editable text tests to browser tests. r=Jamie
Differential Revision: https://phabricator.services.mozilla.com/D178715
This commit is contained in:
Родитель
e90263d66f
Коммит
6d1721c180
|
@ -8,6 +8,7 @@ support-files =
|
|||
prefs =
|
||||
javascript.options.asyncstack_capture_debuggee_only=false
|
||||
|
||||
[browser_editabletext.js]
|
||||
[browser_text.js]
|
||||
[browser_text_caret.js]
|
||||
[browser_text_paragraph_boundary.js]
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
async function testEditable(browser, acc, aBefore = "", aAfter = "") {
|
||||
async function resetInput() {
|
||||
if (acc.childCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let emptyInputEvent = waitForEvent(EVENT_TEXT_VALUE_CHANGE, "input");
|
||||
await invokeContentTask(browser, [], async () => {
|
||||
content.document.getElementById("input").innerHTML = "";
|
||||
});
|
||||
|
||||
await emptyInputEvent;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// insertText
|
||||
await testInsertText(acc, "hello", 0, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hello", aAfter]);
|
||||
await testInsertText(acc, "ma ", 0, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "ma hello", aAfter]);
|
||||
await testInsertText(acc, "ma", 2, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "mama hello", aAfter]);
|
||||
await testInsertText(acc, " hello", 10, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [
|
||||
aBefore,
|
||||
"mama hello hello",
|
||||
aAfter,
|
||||
]);
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// deleteText
|
||||
await testDeleteText(acc, 0, 5, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hello hello", aAfter]);
|
||||
await testDeleteText(acc, 5, 6, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hellohello", aAfter]);
|
||||
await testDeleteText(acc, 5, 10, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hello", aAfter]);
|
||||
await testDeleteText(acc, 0, 5, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "", aAfter]);
|
||||
|
||||
// XXX: clipboard operation tests don't work well with editable documents.
|
||||
if (acc.role == ROLE_DOCUMENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
await resetInput();
|
||||
|
||||
// copyText and pasteText
|
||||
await testInsertText(acc, "hello", 0, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hello", aAfter]);
|
||||
|
||||
await testCopyText(acc, 0, 1, aBefore.length, browser, "h");
|
||||
await testPasteText(acc, 1, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hhello", aAfter]);
|
||||
|
||||
await testCopyText(acc, 5, 6, aBefore.length, browser, "o");
|
||||
await testPasteText(acc, 6, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hhelloo", aAfter]);
|
||||
|
||||
await testCopyText(acc, 2, 3, aBefore.length, browser, "e");
|
||||
await testPasteText(acc, 1, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hehelloo", aAfter]);
|
||||
|
||||
// cut & paste
|
||||
await testCutText(acc, 0, 1, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "ehelloo", aAfter]);
|
||||
await testPasteText(acc, 2, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "ehhelloo", aAfter]);
|
||||
|
||||
await testCutText(acc, 3, 4, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "ehhlloo", aAfter]);
|
||||
await testPasteText(acc, 6, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "ehhlloeo", aAfter]);
|
||||
|
||||
await testCutText(acc, 0, 8, aBefore.length);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "", aAfter]);
|
||||
|
||||
await resetInput();
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// setTextContents
|
||||
await testSetTextContents(acc, "hello", aBefore.length, [
|
||||
EVENT_TEXT_INSERTED,
|
||||
]);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "hello", aAfter]);
|
||||
await testSetTextContents(acc, "katze", aBefore.length, [
|
||||
EVENT_TEXT_REMOVED,
|
||||
EVENT_TEXT_INSERTED,
|
||||
]);
|
||||
await isFinalValueCorrect(browser, acc, [aBefore, "katze", aAfter]);
|
||||
}
|
||||
|
||||
addAccessibleTask(
|
||||
`<input id="input"/>`,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(browser, findAccessibleChildByID(docAcc, "input"));
|
||||
},
|
||||
{ chrome: true, topLevel: true }
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
`<style>
|
||||
#input::after {
|
||||
content: "pseudo element";
|
||||
}
|
||||
</style>
|
||||
<div id="input" contenteditable="true" role="textbox"></div>`,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(
|
||||
browser,
|
||||
findAccessibleChildByID(docAcc, "input"),
|
||||
"",
|
||||
"pseudo element"
|
||||
);
|
||||
},
|
||||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
`<style>
|
||||
#input::before {
|
||||
content: "pseudo element";
|
||||
}
|
||||
</style>
|
||||
<div id="input" contenteditable="true" role="textbox"></div>`,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(
|
||||
browser,
|
||||
findAccessibleChildByID(docAcc, "input"),
|
||||
"pseudo element"
|
||||
);
|
||||
},
|
||||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
`<style>
|
||||
#input::before {
|
||||
content: "before";
|
||||
}
|
||||
#input::after {
|
||||
content: "after";
|
||||
}
|
||||
</style>
|
||||
<div id="input" contenteditable="true" role="textbox"></div>`,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(
|
||||
browser,
|
||||
findAccessibleChildByID(docAcc, "input"),
|
||||
"before",
|
||||
"after"
|
||||
);
|
||||
},
|
||||
{ chrome: true, topLevel: false /* bug 1834129 */ }
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
``,
|
||||
async function (browser, docAcc) {
|
||||
await testEditable(browser, docAcc);
|
||||
},
|
||||
{
|
||||
chrome: true,
|
||||
topLevel: true,
|
||||
contentDocBodyAttrs: { contentEditable: "true" },
|
||||
}
|
||||
);
|
|
@ -7,7 +7,9 @@
|
|||
/* exported createTextLeafPoint, DIRECTION_NEXT, DIRECTION_PREVIOUS,
|
||||
BOUNDARY_FLAG_DEFAULT, BOUNDARY_FLAG_INCLUDE_ORIGIN,
|
||||
BOUNDARY_FLAG_STOP_IN_EDITABLE, BOUNDARY_FLAG_SKIP_LIST_ITEM_MARKER,
|
||||
readablePoint, testPointEqual, textBoundaryGenerator, testBoundarySequence */
|
||||
readablePoint, testPointEqual, textBoundaryGenerator, testBoundarySequence,
|
||||
isFinalValueCorrect, isFinalValueCorrect, testInsertText, testDeleteText,
|
||||
testCopyText, testPasteText, testCutText, testSetTextContents */
|
||||
|
||||
// Load the shared-head file first.
|
||||
Services.scriptloader.loadSubScript(
|
||||
|
@ -17,9 +19,13 @@ Services.scriptloader.loadSubScript(
|
|||
|
||||
// Loading and common.js from accessible/tests/mochitest/ for all tests, as
|
||||
// well as promisified-events.js.
|
||||
|
||||
/* import-globals-from ../../mochitest/role.js */
|
||||
|
||||
loadScripts(
|
||||
{ name: "common.js", dir: MOCHITESTS_DIR },
|
||||
{ name: "text.js", dir: MOCHITESTS_DIR },
|
||||
{ name: "role.js", dir: MOCHITESTS_DIR },
|
||||
{ name: "promisified-events.js", dir: MOCHITESTS_DIR }
|
||||
);
|
||||
|
||||
|
@ -131,3 +137,140 @@ function testBoundarySequence(
|
|||
msg
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Editable text
|
||||
|
||||
async function waitForCopy(browser) {
|
||||
await BrowserTestUtils.waitForContentEvent(browser, "copy", false, evt => {
|
||||
return true;
|
||||
});
|
||||
|
||||
let clipboardData = await invokeContentTask(browser, [], async () => {
|
||||
let text = await content.navigator.clipboard.readText();
|
||||
return text;
|
||||
});
|
||||
|
||||
return clipboardData;
|
||||
}
|
||||
|
||||
async function isFinalValueCorrect(
|
||||
browser,
|
||||
acc,
|
||||
expectedTextLeafs,
|
||||
msg = "Value is correct"
|
||||
) {
|
||||
let value =
|
||||
acc.role == ROLE_ENTRY
|
||||
? acc.value
|
||||
: await invokeContentTask(browser, [], () => {
|
||||
return content.document.body.textContent;
|
||||
});
|
||||
|
||||
let [before, text, after] = expectedTextLeafs;
|
||||
let finalValue =
|
||||
before && after && !text
|
||||
? [before, after].join(" ")
|
||||
: [before, text, after].join("");
|
||||
|
||||
is(value.replace("\xa0", " "), finalValue, msg);
|
||||
}
|
||||
|
||||
function waitForTextChangeEvents(acc, eventSeq) {
|
||||
let events = eventSeq.map(eventType => {
|
||||
return [eventType, acc];
|
||||
});
|
||||
|
||||
if (acc.role == ROLE_ENTRY) {
|
||||
events.push([EVENT_TEXT_VALUE_CHANGE, acc]);
|
||||
}
|
||||
|
||||
return waitForEvents(events);
|
||||
}
|
||||
|
||||
async function testSetTextContents(acc, text, staticContentOffset, events) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
let evtPromise = waitForTextChangeEvents(acc, events);
|
||||
acc.setTextContents(text);
|
||||
let evt = (await evtPromise)[0];
|
||||
evt.QueryInterface(nsIAccessibleTextChangeEvent);
|
||||
is(evt.start, staticContentOffset);
|
||||
}
|
||||
|
||||
async function testInsertText(
|
||||
acc,
|
||||
textToInsert,
|
||||
insertOffset,
|
||||
staticContentOffset
|
||||
) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
|
||||
let evtPromise = waitForTextChangeEvents(acc, [EVENT_TEXT_INSERTED]);
|
||||
acc.insertText(textToInsert, staticContentOffset + insertOffset);
|
||||
let evt = (await evtPromise)[0];
|
||||
evt.QueryInterface(nsIAccessibleTextChangeEvent);
|
||||
is(evt.start, staticContentOffset + insertOffset);
|
||||
}
|
||||
|
||||
async function testDeleteText(
|
||||
acc,
|
||||
startOffset,
|
||||
endOffset,
|
||||
staticContentOffset
|
||||
) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
|
||||
let evtPromise = waitForTextChangeEvents(acc, [EVENT_TEXT_REMOVED]);
|
||||
acc.deleteText(
|
||||
staticContentOffset + startOffset,
|
||||
staticContentOffset + endOffset
|
||||
);
|
||||
let evt = (await evtPromise)[0];
|
||||
evt.QueryInterface(nsIAccessibleTextChangeEvent);
|
||||
is(evt.start, staticContentOffset + startOffset);
|
||||
}
|
||||
|
||||
async function testCopyText(
|
||||
acc,
|
||||
startOffset,
|
||||
endOffset,
|
||||
staticContentOffset,
|
||||
browser,
|
||||
aExpectedClipboard = null
|
||||
) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
let copied = waitForCopy(browser);
|
||||
acc.copyText(
|
||||
staticContentOffset + startOffset,
|
||||
staticContentOffset + endOffset
|
||||
);
|
||||
let clipboardText = await copied;
|
||||
if (aExpectedClipboard != null) {
|
||||
is(clipboardText, aExpectedClipboard, "Correct text in clipboard");
|
||||
}
|
||||
}
|
||||
|
||||
async function testPasteText(acc, insertOffset, staticContentOffset) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
let evtPromise = waitForTextChangeEvents(acc, [EVENT_TEXT_INSERTED]);
|
||||
acc.pasteText(staticContentOffset + insertOffset);
|
||||
|
||||
let evt = (await evtPromise)[0];
|
||||
evt.QueryInterface(nsIAccessibleTextChangeEvent);
|
||||
// XXX: In non-headless mode pasting text produces several text leaves
|
||||
// and the offset is not what we expect.
|
||||
// is(evt.start, staticContentOffset + insertOffset);
|
||||
}
|
||||
|
||||
async function testCutText(acc, startOffset, endOffset, staticContentOffset) {
|
||||
acc.QueryInterface(nsIAccessibleEditableText);
|
||||
let evtPromise = waitForTextChangeEvents(acc, [EVENT_TEXT_REMOVED]);
|
||||
acc.cutText(
|
||||
staticContentOffset + startOffset,
|
||||
staticContentOffset + endOffset
|
||||
);
|
||||
|
||||
let evt = (await evtPromise)[0];
|
||||
evt.QueryInterface(nsIAccessibleTextChangeEvent);
|
||||
is(evt.start, staticContentOffset + startOffset);
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
editabletext.js
|
||||
!/accessible/tests/mochitest/*.js
|
||||
|
||||
[test_1.html]
|
||||
[test_2.html]
|
|
@ -1,409 +0,0 @@
|
|||
/* 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;
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
<!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>
|
|
@ -1,61 +0,0 @@
|
|||
<!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>
|
|
@ -10,7 +10,6 @@ A11Y_MANIFESTS += [
|
|||
"aom/a11y.ini",
|
||||
"attributes/a11y.ini",
|
||||
"bounds/a11y.ini",
|
||||
"editabletext/a11y.ini",
|
||||
"elm/a11y.ini",
|
||||
"events/a11y.ini",
|
||||
"events/docload/a11y.ini",
|
||||
|
|
Загрузка…
Ссылка в новой задаче