mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-22 23:27:30 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
6
editor/libeditor/tests/browser.ini
Normal file
6
editor/libeditor/tests/browser.ini
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[browser_bug527935.js]
|
||||
skip-if = toolkit == 'android'
|
||||
support-files = bug527935.html
|
||||
[browser_bug629172.js]
|
||||
skip-if = toolkit == 'android'
|
||||
support-files = bug629172.html
|
||||
63
editor/libeditor/tests/browser_bug527935.js
Normal file
63
editor/libeditor/tests/browser_bug527935.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
add_task(function*() {
|
||||
yield new Promise(resolve => waitForFocus(resolve, window));
|
||||
|
||||
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug527935.html";
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: kPageURL
|
||||
}, function*(aBrowser) {
|
||||
var popupShown = false;
|
||||
function listener() {
|
||||
popupShown = true;
|
||||
}
|
||||
SpecialPowers.addAutoCompletePopupEventListener(window, "popupshowing", listener);
|
||||
|
||||
yield ContentTask.spawn(aBrowser, {}, function*() {
|
||||
var window = content.window.wrappedJSObject;
|
||||
var document = window.document;
|
||||
var formTarget = document.getElementById("formTarget");
|
||||
var initValue = document.getElementById("initValue");
|
||||
|
||||
window.loadPromise = new Promise(resolve => {
|
||||
formTarget.onload = resolve;
|
||||
});
|
||||
|
||||
initValue.focus();
|
||||
initValue.value = "foo";
|
||||
});
|
||||
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
|
||||
yield ContentTask.spawn(aBrowser, {}, function*() {
|
||||
var window = content.window.wrappedJSObject;
|
||||
var document = window.document;
|
||||
|
||||
yield window.loadPromise;
|
||||
|
||||
var newInput = document.createElement("input");
|
||||
newInput.setAttribute("name", "test");
|
||||
document.body.appendChild(newInput);
|
||||
|
||||
var event = document.createEvent("KeyboardEvent");
|
||||
|
||||
event.initKeyEvent("keypress", true, true, null, false, false,
|
||||
false, false, 0, "f".charCodeAt(0));
|
||||
newInput.value = "";
|
||||
newInput.focus();
|
||||
newInput.dispatchEvent(event);
|
||||
});
|
||||
|
||||
yield new Promise(resolve => hitEventLoop(resolve, 100));
|
||||
|
||||
ok(!popupShown, "Popup must not be opened");
|
||||
SpecialPowers.removeAutoCompletePopupEventListener(window, "popupshowing", listener);
|
||||
});
|
||||
});
|
||||
|
||||
function hitEventLoop(func, times) {
|
||||
if (times > 0) {
|
||||
setTimeout(hitEventLoop, 0, func, times - 1);
|
||||
} else {
|
||||
setTimeout(func, 0);
|
||||
}
|
||||
}
|
||||
106
editor/libeditor/tests/browser_bug629172.js
Normal file
106
editor/libeditor/tests/browser_bug629172.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
add_task(function*() {
|
||||
yield new Promise(resolve => waitForFocus(resolve, window));
|
||||
|
||||
const kPageURL = "http://example.org/browser/editor/libeditor/tests/bug629172.html";
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: kPageURL
|
||||
}, function*(aBrowser) {
|
||||
yield ContentTask.spawn(aBrowser, {}, function*() {
|
||||
var window = content.window.wrappedJSObject;
|
||||
var document = window.document;
|
||||
|
||||
// Note: Using the with keyword, we would have been able to write this as:
|
||||
//
|
||||
// with (window) {
|
||||
// Screenshots = {};
|
||||
// // so on
|
||||
// }
|
||||
//
|
||||
// However, browser-chrome tests are somehow forced to run in strict mode,
|
||||
// which doesn't permit the usage of the with keyword, turning the following
|
||||
// into the ugliest test you've ever seen. :(
|
||||
var LTRRef = document.getElementById("ltr-ref");
|
||||
var RTLRef = document.getElementById("rtl-ref");
|
||||
window.Screenshots = {};
|
||||
|
||||
// generate the reference screenshots
|
||||
LTRRef.style.display = "";
|
||||
document.body.clientWidth;
|
||||
window.Screenshots.ltr = window.snapshotWindow(window);
|
||||
LTRRef.parentNode.removeChild(LTRRef);
|
||||
RTLRef.style.display = "";
|
||||
document.body.clientWidth;
|
||||
window.Screenshots.rtl = window.snapshotWindow(window);
|
||||
RTLRef.parentNode.removeChild(RTLRef);
|
||||
window.Screenshots.get = function(dir, flip) {
|
||||
if (flip) {
|
||||
return this[dir == "rtl" ? "ltr" : "rtl"];
|
||||
} else {
|
||||
return this[dir];
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
function simulateCtrlShiftX(aBrowser) {
|
||||
// In e10s, the keypress event will be dispatched to the content process,
|
||||
// but in non-e10s it is handled by the browser UI code and hence won't
|
||||
// reach the web page. As a result, we need to observe the event in
|
||||
// the content process only in e10s mode.
|
||||
var waitForKeypressContent = BrowserTestUtils.waitForContentEvent(aBrowser, "keypress");
|
||||
EventUtils.synthesizeKey("x", {accelKey: true, shiftKey: true});
|
||||
if (gMultiProcessBrowser) {
|
||||
return waitForKeypressContent;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function* testDirection(initialDir, aBrowser) {
|
||||
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
|
||||
var window = content.window.wrappedJSObject;
|
||||
var document = window.document;
|
||||
|
||||
var t = window.t = document.createElement("textarea");
|
||||
t.setAttribute("dir", initialDir);
|
||||
t.value = "test.";
|
||||
window.inputEventCount = 0;
|
||||
t.oninput = function() { window.inputEventCount++; };
|
||||
document.getElementById("content").appendChild(t);
|
||||
document.body.clientWidth;
|
||||
var s1 = window.snapshotWindow(window);
|
||||
ok(window.compareSnapshots(s1, window.Screenshots.get(initialDir, false), true)[0],
|
||||
"Textarea should appear correctly before switching the direction (" + initialDir + ")");
|
||||
t.focus();
|
||||
is(window.inputEventCount, 0, "input event count must be 0 before");
|
||||
});
|
||||
yield simulateCtrlShiftX(aBrowser);
|
||||
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
|
||||
var window = content.window.wrappedJSObject;
|
||||
|
||||
is(window.t.getAttribute("dir"), initialDir == "ltr" ? "rtl" : "ltr", "The dir attribute must be correctly updated");
|
||||
is(window.inputEventCount, 1, "input event count must be 1 after");
|
||||
window.t.blur();
|
||||
var s2 = window.snapshotWindow(window);
|
||||
ok(window.compareSnapshots(s2, window.Screenshots.get(initialDir, true), true)[0],
|
||||
"Textarea should appear correctly after switching the direction (" + initialDir + ")");
|
||||
window.t.focus();
|
||||
is(window.inputEventCount, 1, "input event count must be 1 before");
|
||||
});
|
||||
yield simulateCtrlShiftX(aBrowser);
|
||||
yield ContentTask.spawn(aBrowser, {initialDir}, function({initialDir}) {
|
||||
var window = content.window.wrappedJSObject;
|
||||
|
||||
is(window.inputEventCount, 2, "input event count must be 2 after");
|
||||
is(window.t.getAttribute("dir"), initialDir == "ltr" ? "ltr" : "rtl", "The dir attribute must be correctly updated");
|
||||
window.t.blur();
|
||||
var s3 = window.snapshotWindow(window);
|
||||
ok(window.compareSnapshots(s3, window.Screenshots.get(initialDir, false), true)[0],
|
||||
"Textarea should appear correctly after switching back the direction (" + initialDir + ")");
|
||||
window.t.parentNode.removeChild(window.t);
|
||||
});
|
||||
}
|
||||
|
||||
yield testDirection("ltr", aBrowser);
|
||||
yield testDirection("rtl", aBrowser);
|
||||
});
|
||||
});
|
||||
202
editor/libeditor/tests/browserscope/lib/richtext/LICENSE
Normal file
202
editor/libeditor/tests/browserscope/lib/richtext/LICENSE
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
58
editor/libeditor/tests/browserscope/lib/richtext/README
Normal file
58
editor/libeditor/tests/browserscope/lib/richtext/README
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
README FOR BROWSERSCOPE
|
||||
-----------------------
|
||||
|
||||
Hey there - thanks for downloading the code. This file has instructions
|
||||
for getting setup so that you can run the codebase locally.
|
||||
|
||||
This project is built on Google App Engine using the
|
||||
Django web application framework and written in Python.
|
||||
|
||||
To get started, you'll need to first download the App Engine SDK at:
|
||||
http://code.google.com/appengine/downloads.html
|
||||
|
||||
For local development, just startup the server:
|
||||
./pathto/google_appengine/dev_appserver.py --port=8080 browserscope
|
||||
|
||||
You should then be able to access the local application at:
|
||||
http://localhost:8080/
|
||||
|
||||
Note: the first time you hit the homepage it may take a little
|
||||
while - that's because it's trying to read out median times for all
|
||||
of the tests from a nonexistent datastore and write to memcache.
|
||||
Just be a lil patient.
|
||||
|
||||
You can run the unit tests at:
|
||||
http://localhost:8080/test
|
||||
|
||||
|
||||
CONTRIBUTING
|
||||
------------------
|
||||
|
||||
Most likely you are interested in adding new tests or creating
|
||||
a new test category. If you are interested in adding tests to an existing
|
||||
"category" you may want to get in touch with the maintainer for that
|
||||
branch of the tree. We are really looking forward to receiving your
|
||||
code in patch format. Currently the category maintainers are:
|
||||
Network: Steve Souders <souders@gmail.com>
|
||||
Reflow: Lindsey Simon <elsigh@gmail.com>
|
||||
Security: Adam Barth <adam@adambarth.com> and Collin Jackson <collin@collinjackson.com>
|
||||
|
||||
|
||||
To create a completely new test category:
|
||||
* Copy one of the existing directories in categories/
|
||||
* Edit your test_set.py, handlers.py
|
||||
* Add your files in templates/ and static/
|
||||
* Update urls.py and settings.CATEGORIES
|
||||
* Follow the examples of other tests re:
|
||||
* beaconing using/testdriver_base
|
||||
* your GetScoreAndDisplayValue method
|
||||
* your GetRowScoreAndDisplayValue method
|
||||
|
||||
References:
|
||||
* App Engine Docs - http://code.google.com/appengine/docs/python/overview.html
|
||||
* App Engine Group - http://groups.google.com/group/google-appengine
|
||||
* Python Docs - http://www.python.org/doc/
|
||||
* Django - http://www.djangoproject.com/
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
The BrowserScope project provides a set of cross-browser HTML editor tests,
|
||||
which we import in our test suite in order to run them as part of our
|
||||
continuous integration system.
|
||||
|
||||
We pull tests occasionally from their Subversion repository using the pull
|
||||
script which can be found in this directory. We also record the revision ID
|
||||
which we've used in the current_revision file inside this directory.
|
||||
|
||||
Using the pull script is quite easy, just switch to this directory, and say:
|
||||
|
||||
sh update_from_upstream
|
||||
|
||||
There are tests which we're currently failing on, and there will probably be
|
||||
more of those in the future. We should maintain a list of the failing tests
|
||||
manually in currentStatus.js (which can also be found in this directory), to
|
||||
make sure that the suite passes entirely, with failing tests marked as todo
|
||||
items.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* This file lists the tests in the BrowserScope suite which we are currently
|
||||
* failing. We mark them as todo items to keep track of them.
|
||||
*/
|
||||
|
||||
var knownFailures = {
|
||||
// Dummy result items. There is one for each category.
|
||||
'apply' : {
|
||||
'0-undefined' : true
|
||||
},
|
||||
'unapply' : {
|
||||
'0-undefined' : true
|
||||
},
|
||||
'change' : {
|
||||
'0-undefined' : true
|
||||
},
|
||||
'query' : {
|
||||
'0-undefined' : true
|
||||
},
|
||||
'a' : {
|
||||
'createbookmark-0' : true,
|
||||
'fontsize-1' : true,
|
||||
'subscript-1' : true,
|
||||
'superscript-1' : true,
|
||||
},
|
||||
'u': {
|
||||
'removeformat-1' : true,
|
||||
'removeformat-2' : true,
|
||||
'strikethrough-2' : true,
|
||||
'subscript-1' : true,
|
||||
'superscript-1' : true,
|
||||
'unbookmark-0' : true,
|
||||
},
|
||||
'q': {
|
||||
'fontsize-1' : true,
|
||||
'fontsize-2' : true,
|
||||
},
|
||||
'c': {
|
||||
'fontsize-1' : true,
|
||||
'fontsize-2' : true,
|
||||
},
|
||||
};
|
||||
|
||||
function isKnownFailure(type, test, param) {
|
||||
return (type in knownFailures) && ((test + "-" + param) in knownFailures[type]);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
775
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
function load(){
|
||||
window.document.designMode = "On";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body contentEditable="true" onload="load()">
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
if test -d richtext; then
|
||||
rm -drf richtext;
|
||||
fi
|
||||
|
||||
svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext/static richtext | tail -1 | sed 's/[^0-9]//g' > current_revision
|
||||
|
||||
find richtext -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null
|
||||
|
||||
hg add current_revision richtext
|
||||
|
||||
hg stat .
|
||||
|
||||
202
editor/libeditor/tests/browserscope/lib/richtext2/LICENSE
Normal file
202
editor/libeditor/tests/browserscope/lib/richtext2/LICENSE
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
58
editor/libeditor/tests/browserscope/lib/richtext2/README
Normal file
58
editor/libeditor/tests/browserscope/lib/richtext2/README
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
README FOR BROWSERSCOPE
|
||||
-----------------------
|
||||
|
||||
Hey there - thanks for downloading the code. This file has instructions
|
||||
for getting setup so that you can run the codebase locally.
|
||||
|
||||
This project is built on Google App Engine using the
|
||||
Django web application framework and written in Python.
|
||||
|
||||
To get started, you'll need to first download the App Engine SDK at:
|
||||
http://code.google.com/appengine/downloads.html
|
||||
|
||||
For local development, just startup the server:
|
||||
./pathto/google_appengine/dev_appserver.py --port=8080 browserscope
|
||||
|
||||
You should then be able to access the local application at:
|
||||
http://localhost:8080/
|
||||
|
||||
Note: the first time you hit the homepage it may take a little
|
||||
while - that's because it's trying to read out median times for all
|
||||
of the tests from a nonexistent datastore and write to memcache.
|
||||
Just be a lil patient.
|
||||
|
||||
You can run the unit tests at:
|
||||
http://localhost:8080/test
|
||||
|
||||
|
||||
CONTRIBUTING
|
||||
------------------
|
||||
|
||||
Most likely you are interested in adding new tests or creating
|
||||
a new test category. If you are interested in adding tests to an existing
|
||||
"category" you may want to get in touch with the maintainer for that
|
||||
branch of the tree. We are really looking forward to receiving your
|
||||
code in patch format. Currently the category maintainers are:
|
||||
Network: Steve Souders <souders@gmail.com>
|
||||
Reflow: Lindsey Simon <elsigh@gmail.com>
|
||||
Security: Adam Barth <adam@adambarth.com> and Collin Jackson <collin@collinjackson.com>
|
||||
|
||||
|
||||
To create a completely new test category:
|
||||
* Copy one of the existing directories in categories/
|
||||
* Edit your test_set.py, handlers.py
|
||||
* Add your files in templates/ and static/
|
||||
* Update urls.py and settings.CATEGORIES
|
||||
* Follow the examples of other tests re:
|
||||
* beaconing using/testdriver_base
|
||||
* your GetScoreAndDisplayValue method
|
||||
* your GetRowScoreAndDisplayValue method
|
||||
|
||||
References:
|
||||
* App Engine Docs - http://code.google.com/appengine/docs/python/overview.html
|
||||
* App Engine Group - http://groups.google.com/group/google-appengine
|
||||
* Python Docs - http://www.python.org/doc/
|
||||
* Django - http://www.djangoproject.com/
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
The BrowserScope project provides a set of cross-browser HTML editor tests,
|
||||
which we import in our test suite in order to run them as part of our
|
||||
continuous integration system.
|
||||
|
||||
We pull tests occasionally from their Subversion repository using the pull
|
||||
script which can be found in this directory. We also record the revision ID
|
||||
which we've used in the current_revision file inside this directory.
|
||||
|
||||
Using the pull script is quite easy, just switch to this directory, and say:
|
||||
|
||||
sh update_from_upstream
|
||||
|
||||
There are tests which we're currently failing on, and there will probably be
|
||||
more of those in the future. We should maintain a list of the failing tests
|
||||
manually in currentStatus.js (which can also be found in this directory), to
|
||||
make sure that the suite passes entirely, with failing tests marked as todo
|
||||
items.
|
||||
|
||||
The current status of the test suite needs to be updated whenever an editor
|
||||
bug gets fixed, which makes us pass one of the tests. When that happens,
|
||||
you should set the UPDATE_TEST_RESULTS constant to true in test_richtext2.html,
|
||||
run the test suite, paste the result JSON string in a JSON beautifier (such
|
||||
as http://jsbeautifier.org/), and use the result to update currentStatus.js.
|
||||
1850
editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js
Normal file
1850
editor/libeditor/tests/browserscope/lib/richtext2/currentStatus.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1 @@
|
|||
805
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python2.5
|
||||
#
|
||||
# Copyright 2010 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Common constants"""
|
||||
|
||||
__author__ = 'rolandsteiner@google.com (Roland Steiner)'
|
||||
|
||||
CATEGORY = 'richtext2'
|
||||
|
||||
TEST_ID_PREFIX = 'RTE2'
|
||||
|
||||
CLASSES = ['Finalized', 'RFC', 'Proposed']
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/python2.5
|
||||
#
|
||||
# Copyright 2010 Google Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Handlers for New Rich Text Tests"""
|
||||
|
||||
__author__ = 'rolandsteiner@google.com (Roland Steiner)'
|
||||
|
||||
from google.appengine.api import users
|
||||
from google.appengine.ext import db
|
||||
from google.appengine.api import memcache
|
||||
from google.appengine.ext import webapp
|
||||
from google.appengine.ext.webapp import template
|
||||
|
||||
import django
|
||||
from django import http
|
||||
from django import shortcuts
|
||||
|
||||
from django.template import add_to_builtins
|
||||
add_to_builtins('base.custom_filters')
|
||||
|
||||
# Shared stuff
|
||||
from categories import all_test_sets
|
||||
from base import decorators
|
||||
from base import util
|
||||
|
||||
# common to the RichText2 suite
|
||||
from categories.richtext2 import common
|
||||
|
||||
# tests
|
||||
from categories.richtext2.tests.apply import APPLY_TESTS
|
||||
from categories.richtext2.tests.applyCSS import APPLY_TESTS_CSS
|
||||
from categories.richtext2.tests.change import CHANGE_TESTS
|
||||
from categories.richtext2.tests.changeCSS import CHANGE_TESTS_CSS
|
||||
from categories.richtext2.tests.delete import DELETE_TESTS
|
||||
from categories.richtext2.tests.forwarddelete import FORWARDDELETE_TESTS
|
||||
from categories.richtext2.tests.insert import INSERT_TESTS
|
||||
from categories.richtext2.tests.selection import SELECTION_TESTS
|
||||
from categories.richtext2.tests.unapply import UNAPPLY_TESTS
|
||||
from categories.richtext2.tests.unapplyCSS import UNAPPLY_TESTS_CSS
|
||||
|
||||
from categories.richtext2.tests.querySupported import QUERYSUPPORTED_TESTS
|
||||
from categories.richtext2.tests.queryEnabled import QUERYENABLED_TESTS
|
||||
from categories.richtext2.tests.queryIndeterm import QUERYINDETERM_TESTS
|
||||
from categories.richtext2.tests.queryState import QUERYSTATE_TESTS, QUERYSTATE_TESTS_CSS
|
||||
from categories.richtext2.tests.queryValue import QUERYVALUE_TESTS, QUERYVALUE_TESTS_CSS
|
||||
|
||||
|
||||
def About(request):
|
||||
"""About page."""
|
||||
overview = """These tests cover browers' implementations of
|
||||
<a href="http://blog.whatwg.org/the-road-to-html-5-contenteditable">contenteditable</a>
|
||||
for basic rich text formatting commands. Most browser implementations do very
|
||||
well at editing the HTML which is generated by their own execCommands. But a
|
||||
big problem happens when developers try to make cross-browser web
|
||||
applications using contenteditable - most browsers are not able to correctly
|
||||
change formatting generated by other browsers. On top of that, most browsers
|
||||
allow users to to paste arbitrary HTML from other webpages into a
|
||||
contenteditable region, which is even harder for browsers to properly
|
||||
format. These tests check how well the execCommand, queryCommandState,
|
||||
and queryCommandValue functions work with different types of HTML."""
|
||||
return util.About(request, common.CATEGORY, category_title='Rich Text',
|
||||
overview=overview, show_hidden=False)
|
||||
|
||||
|
||||
def RunRichText2Tests(request):
|
||||
params = {
|
||||
'classes': common.CLASSES,
|
||||
'commonIDPrefix': common.TEST_ID_PREFIX,
|
||||
'strict': False,
|
||||
'suites': [
|
||||
SELECTION_TESTS,
|
||||
APPLY_TESTS,
|
||||
APPLY_TESTS_CSS,
|
||||
CHANGE_TESTS,
|
||||
CHANGE_TESTS_CSS,
|
||||
UNAPPLY_TESTS,
|
||||
UNAPPLY_TESTS_CSS,
|
||||
DELETE_TESTS,
|
||||
FORWARDDELETE_TESTS,
|
||||
INSERT_TESTS,
|
||||
|
||||
QUERYSUPPORTED_TESTS,
|
||||
QUERYENABLED_TESTS,
|
||||
QUERYINDETERM_TESTS,
|
||||
QUERYSTATE_TESTS,
|
||||
QUERYSTATE_TESTS_CSS,
|
||||
QUERYVALUE_TESTS,
|
||||
QUERYVALUE_TESTS_CSS
|
||||
]
|
||||
}
|
||||
return shortcuts.render_to_response('%s/templates/richtext2.html' % common.CATEGORY, params)
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
.framed {
|
||||
vertical-align: top;
|
||||
margin: 8px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.legend {
|
||||
padding: 12px;
|
||||
background-color: #f8f8ff;
|
||||
}
|
||||
|
||||
.legendHdr {
|
||||
font-size: large;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
table.legend {
|
||||
display: inline-table;
|
||||
}
|
||||
|
||||
.suite-thead {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.lo {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
.hi {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.lo .grey {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
.lo .na {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
.lo .pass {
|
||||
background-color: #d4ffc0;
|
||||
}
|
||||
.lo .canary {
|
||||
background-color: #ffcccc;
|
||||
}
|
||||
.lo .fail {
|
||||
background-color: #ffcccc;
|
||||
}
|
||||
.lo .accept {
|
||||
background-color: #ffffc0;
|
||||
}
|
||||
.lo .exception {
|
||||
background-color: #f0d0f4;
|
||||
}
|
||||
.lo .unsupported {
|
||||
background-color: #f0d0f4;
|
||||
}
|
||||
|
||||
.hi .grey {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
.hi .na {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
.hi .pass {
|
||||
background-color: #e0ffdc;
|
||||
}
|
||||
.hi .canary {
|
||||
background-color: #ffd8d8;
|
||||
}
|
||||
.hi .fail {
|
||||
background-color: #ffd8d8;
|
||||
}
|
||||
.hi .accept {
|
||||
background-color: #ffffd8;
|
||||
}
|
||||
.hi .exception {
|
||||
background-color: #f4dcf8;
|
||||
}
|
||||
.hi .unsupported {
|
||||
background-color: #f4dcf8;
|
||||
}
|
||||
|
||||
|
||||
.sel {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.txt {
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
border: 1px solid #b0b0b0;
|
||||
}
|
||||
|
||||
.idLabel {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.fade {
|
||||
color: grey;
|
||||
}
|
||||
.accexp {
|
||||
color: #606070;
|
||||
}
|
||||
.comment {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.score {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.fatalerror {
|
||||
color: red;
|
||||
font-size: large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<link rel="stylesheet" href="editable.css" type="text/css">
|
||||
</head>
|
||||
<body contentEditable="true">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<link rel="stylesheet" href="editable.css" type="text/css">
|
||||
|
||||
<script>
|
||||
function setDesignMode() {
|
||||
window.document.designMode = "On";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="setDesignMode()">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<link rel="stylesheet" href="editable.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
.b, myb {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.i, myi {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.s, mys {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.u, myu {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sub, mysub {
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.sup, mysup {
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
.jc, myjc {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.jf, myjf {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
.jl, myjl {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.jr, myjr {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.red, myred {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.bcred, mybcred {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.large, mylarge {
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.fs18px, myfs18px {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.courier, mycourier {
|
||||
font-family: courier;
|
||||
}
|
||||
|
||||
gen::before {
|
||||
content: "[BEFORE]";
|
||||
}
|
||||
gen::after {
|
||||
content: "[AFTER]";
|
||||
}
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Canonicalization functions used in the RTE test suite.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* Canonicalize HTML entities to their actual character
|
||||
*
|
||||
* @param str {String} the HTML string to be canonicalized
|
||||
* @return {String} the canonicalized string
|
||||
*/
|
||||
|
||||
function canonicalizeEntities(str) {
|
||||
// TODO(rolandsteiner): this function is very much not optimized, but that shouldn't
|
||||
// theoretically matter too much - look into it at some point.
|
||||
var match;
|
||||
while (match = str.match(/&#x([0-9A-F]+);/i)) {
|
||||
str = str.replace('&#x' + match[1] + ';', String.fromCharCode(parseInt(match[1], 16)));
|
||||
}
|
||||
while (match = str.match(/&#([0-9]+);/)) {
|
||||
str = str.replace('&#' + match[1] + ';', String.fromCharCode(Number(match[1])));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize the contents of the HTML 'style' attribute.
|
||||
* I.e. sorts the CSS attributes alphabetically and canonicalizes the values
|
||||
* CSS attributes where necessary.
|
||||
*
|
||||
* If this would return an empty string, return null instead to suppress the
|
||||
* whole 'style' attribute.
|
||||
*
|
||||
* Avoid tests that contain {, } or : within CSS values!
|
||||
*
|
||||
* Note that this function relies on the spaces of the input string already
|
||||
* having been normalized by canonicalizeSpaces!
|
||||
*
|
||||
* FIXME: does not canonicalize the contents of compound attributes
|
||||
* (e.g., 'border').
|
||||
*
|
||||
* @param str {String} contents of the 'style' attribute
|
||||
* @param emitFlags {Object} flags used for this output
|
||||
* @return {String/null} canonicalized string, null instead of the empty string
|
||||
*/
|
||||
function canonicalizeStyle(str, emitFlags) {
|
||||
// Remove any enclosing curly brackets
|
||||
str = str.replace(/ ?[\{\}] ?/g, '');
|
||||
|
||||
var attributes = str.split(';');
|
||||
var count = attributes.length;
|
||||
var resultArr = [];
|
||||
|
||||
for (var a = 0; a < count; ++a) {
|
||||
// Retrieve "name: value" pair
|
||||
// Note: may expectedly fail if the last pair was terminated with ';'
|
||||
var avPair = attributes[a].match(/ ?([^ :]+) ?: ?(.+)/);
|
||||
if (!avPair)
|
||||
continue;
|
||||
|
||||
var name = avPair[1];
|
||||
var value = avPair[2].replace(/ $/, ''); // Remove any trailing space.
|
||||
|
||||
switch (name) {
|
||||
case 'color':
|
||||
case 'background-color':
|
||||
case 'border-color':
|
||||
if (emitFlags.canonicalizeUnits) {
|
||||
resultArr.push(name + ': #' + new Color(value).toHexString());
|
||||
} else {
|
||||
resultArr.push(name + ': ' + value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'font-family':
|
||||
if (emitFlags.canonicalizeUnits) {
|
||||
resultArr.push(name + ': ' + new FontName(value).toString());
|
||||
} else {
|
||||
resultArr.push(name + ': ' + value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'font-size':
|
||||
if (emitFlags.canonicalizeUnits) {
|
||||
resultArr.push(name + ': ' + new FontSize(value).toString());
|
||||
} else {
|
||||
resultArr.push(name + ': ' + value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
resultArr.push(name + ': ' + value);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by name, assuming no duplicate CSS attribute names.
|
||||
resultArr.sort();
|
||||
|
||||
return resultArr.join('; ') || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize a single attribute value.
|
||||
*
|
||||
* Note that this function relies on the spaces of the input string already
|
||||
* having been normalized by canonicalizeSpaces!
|
||||
*
|
||||
* @param elemName {String} the name of the element
|
||||
* @param attrName {String} the name of the attribute
|
||||
* @param attrValue {String} the value of the attribute
|
||||
* @param emitFlags {Object} flags used for this output
|
||||
* @return {String/null} the canonicalized value, or null if the attribute should be skipped.
|
||||
*/
|
||||
function canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags) {
|
||||
// We emit attributes as name="value", so change any contained apostrophes
|
||||
// to quote marks.
|
||||
attrValue = attrValue.replace(/\x22/, '\x27');
|
||||
|
||||
switch (attrName) {
|
||||
case 'class':
|
||||
return emitFlags.emitClass ? attrValue : null;
|
||||
|
||||
case 'id':
|
||||
if (!emitFlags.emitID) {
|
||||
return null;
|
||||
}
|
||||
if (attrValue && attrValue.substr(0, 7) == 'editor-') {
|
||||
return null;
|
||||
}
|
||||
return attrValue;
|
||||
|
||||
// Remove empty style attributes, canonicalize the contents otherwise,
|
||||
// provided the test cares for styles.
|
||||
case 'style':
|
||||
return (emitFlags.emitStyle && attrValue)
|
||||
? canonicalizeStyle(attrValue, emitFlags)
|
||||
: null;
|
||||
|
||||
// Never output onload handlers as they are set by the test environment.
|
||||
case 'onload':
|
||||
return null;
|
||||
|
||||
// Canonicalize colors.
|
||||
case 'bgcolor':
|
||||
case 'color':
|
||||
if (!attrValue) {
|
||||
return null;
|
||||
}
|
||||
return emitFlags.canonicalizeUnits ? new Color(attrValue).toString() : attrValue;
|
||||
|
||||
// Canonicalize font names.
|
||||
case 'face':
|
||||
return emitFlags.canonicalizeUnits ? new FontName(attrValue).toString() : attrValue;
|
||||
|
||||
// Canonicalize font sizes (leave other 'size' attributes as-is).
|
||||
case 'size':
|
||||
if (!attrValue) {
|
||||
return null;
|
||||
}
|
||||
switch (elemName) {
|
||||
case 'basefont':
|
||||
case 'font':
|
||||
return emitFlags.canonicalizeUnits ? new FontSize(attrValue).toString() : attrValue;
|
||||
}
|
||||
return attrValue;
|
||||
|
||||
// Remove spans with value 1. Retain spans with other values, even if
|
||||
// empty or with a value 0, since those indicate a flawed implementation.
|
||||
case 'colspan':
|
||||
case 'rowspan':
|
||||
case 'span':
|
||||
return (attrValue == '1' || attrValue === '') ? null : attrValue;
|
||||
|
||||
// Boolean attributes: presence equals true. If present, the value must be
|
||||
// the empty string or the attribute's canonical name.
|
||||
// (http://www.whatwg.org/specs/web-apps/current-work/#boolean-attributes)
|
||||
// Below we only normalize empty string to the canonical name for
|
||||
// comparison purposes. All other values are not touched and will therefore
|
||||
// in all likelihood result in a failed test (even if they may be accepted
|
||||
// by the UA).
|
||||
case 'async':
|
||||
case 'autofocus':
|
||||
case 'checked':
|
||||
case 'compact':
|
||||
case 'declare':
|
||||
case 'defer':
|
||||
case 'disabled':
|
||||
case 'formnovalidate':
|
||||
case 'frameborder':
|
||||
case 'ismap':
|
||||
case 'loop':
|
||||
case 'multiple':
|
||||
case 'nohref':
|
||||
case 'nosize':
|
||||
case 'noshade':
|
||||
case 'novalidate':
|
||||
case 'nowrap':
|
||||
case 'open':
|
||||
case 'readonly':
|
||||
case 'required':
|
||||
case 'reversed':
|
||||
case 'seamless':
|
||||
case 'selected':
|
||||
return attrValue ? attrValue : attrName;
|
||||
|
||||
default:
|
||||
return attrValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize the contents of an element tag.
|
||||
*
|
||||
* I.e. sorts the attributes alphabetically and canonicalizes their
|
||||
* values where necessary. Also removes attributes we're not interested in.
|
||||
*
|
||||
* Note that this function relies on the spaces of the input string already
|
||||
* having been normalized by canonicalizeSpaces!
|
||||
*
|
||||
* @param str {String} the contens of the element tag, excluding < and >.
|
||||
* @param emitFlags {Object} flags used for this output
|
||||
* @return {String} the canonicalized contents.
|
||||
*/
|
||||
function canonicalizeElementTag(str, emitFlags) {
|
||||
// FIXME: lowercase only if emitFlags.lowercase is set
|
||||
str = str.toLowerCase();
|
||||
|
||||
var pos = str.search(' ');
|
||||
|
||||
// element name only
|
||||
if (pos == -1) {
|
||||
return str;
|
||||
}
|
||||
|
||||
var elemName = str.substr(0, pos);
|
||||
str = str.substr(pos + 1);
|
||||
|
||||
// Even if emitFlags.emitAttrs is not set, we must iterate over the
|
||||
// attributes to catch the special selection attribute and/or selection
|
||||
// markers. :(
|
||||
|
||||
// Iterate over attributes, add them to an array, canonicalize their
|
||||
// contents, and finally output the (remaining) attributes in sorted order.
|
||||
// Note: We can't do a simple split on space here, because the value of,
|
||||
// e.g., 'style' attributes may also contain spaces.
|
||||
var attrs = [];
|
||||
var selStartInTag = false;
|
||||
var selEndInTag = false;
|
||||
|
||||
while (str) {
|
||||
var attrName;
|
||||
var attrValue = '';
|
||||
|
||||
pos = str.search(/[ =]/);
|
||||
if (pos >= 0) {
|
||||
attrName = str.substr(0, pos);
|
||||
if (str.charAt(pos) == ' ') {
|
||||
++pos;
|
||||
}
|
||||
if (str.charAt(pos) == '=') {
|
||||
++pos;
|
||||
if (str.charAt(pos) == ' ') {
|
||||
++pos;
|
||||
}
|
||||
str = str.substr(pos);
|
||||
switch (str.charAt(0)) {
|
||||
case '"':
|
||||
case "'":
|
||||
pos = str.indexOf(str.charAt(0), 1);
|
||||
pos = (pos < 0) ? str.length : pos;
|
||||
attrValue = str.substring(1, pos);
|
||||
++pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
pos = str.indexOf(' ', 0);
|
||||
pos = (pos < 0) ? str.length : pos;
|
||||
attrValue = (pos == -1) ? str : str.substr(0, pos);
|
||||
break;
|
||||
}
|
||||
attrValue = attrValue.replace(/^ /, '');
|
||||
attrValue = attrValue.replace(/ $/, '');
|
||||
}
|
||||
} else {
|
||||
attrName = str;
|
||||
}
|
||||
str = (pos == -1 || pos >= str.length) ? '' : str.substr(pos + 1);
|
||||
|
||||
// Remove special selection attributes.
|
||||
switch (attrName) {
|
||||
case ATTRNAME_SEL_START:
|
||||
selStartInTag = true;
|
||||
continue;
|
||||
|
||||
case ATTRNAME_SEL_END:
|
||||
selEndInTag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (attrName) {
|
||||
case '':
|
||||
case 'onload':
|
||||
case 'xmlns':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!emitFlags.emitAttrs) {
|
||||
break;
|
||||
}
|
||||
// >>> fall through >>>
|
||||
|
||||
case 'contenteditable':
|
||||
attrValue = canonicalizeEntities(attrValue);
|
||||
attrValue = canonicalizeSingleAttribute(elemName, attrName, attrValue, emitFlags);
|
||||
if (attrValue !== null) {
|
||||
attrs.push(attrName + '="' + attrValue + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var result = elemName;
|
||||
|
||||
// Sort alphabetically (on full string rather than just attribute value for
|
||||
// simplicity. Also, attribute names will differ when encountering the '=').
|
||||
if (attrs.length > 0) {
|
||||
attrs.sort();
|
||||
result += ' ' + attrs.join(' ');
|
||||
}
|
||||
|
||||
// Add intra-tag selection marker(s) or attribute(s), if any, at the end.
|
||||
if (selStartInTag && selEndInTag) {
|
||||
result += ' |';
|
||||
} else if (selStartInTag) {
|
||||
result += ' {';
|
||||
} else if (selEndInTag) {
|
||||
result += ' }';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize elements and attributes to facilitate comparison to the
|
||||
* expectation string: sort attributes, canonicalize values and remove chaff.
|
||||
*
|
||||
* Note that this function relies on the spaces of the input string already
|
||||
* having been normalized by canonicalizeSpaces!
|
||||
*
|
||||
* @param str {String} the HTML string to be canonicalized
|
||||
* @param emitFlags {Object} flags used for this output
|
||||
* @return {String} the canonicalized string
|
||||
*/
|
||||
function canonicalizeElementsAndAttributes(str, emitFlags) {
|
||||
var tagStart = str.indexOf('<');
|
||||
var tagEnd = 0;
|
||||
var result = '';
|
||||
|
||||
while (tagStart >= 0) {
|
||||
++tagStart;
|
||||
if (str.charAt(tagStart) == '/') {
|
||||
++tagStart;
|
||||
}
|
||||
result = result + canonicalizeEntities(str.substring(tagEnd, tagStart));
|
||||
tagEnd = str.indexOf('>', tagStart);
|
||||
if (tagEnd < 0) {
|
||||
tagEnd = str.length - 1;
|
||||
}
|
||||
if (str.charAt(tagEnd - 1) == '/') {
|
||||
--tagEnd;
|
||||
}
|
||||
var elemStr = str.substring(tagStart, tagEnd);
|
||||
elemStr = canonicalizeElementTag(elemStr, emitFlags);
|
||||
result = result + elemStr;
|
||||
tagStart = str.indexOf('<', tagEnd);
|
||||
}
|
||||
return result + canonicalizeEntities(str.substring(tagEnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize an innerHTML string to uniform single whitespaces.
|
||||
*
|
||||
* FIXME: running this prevents testing for pre-formatted content
|
||||
* and the CSS 'white-space' attribute.
|
||||
*
|
||||
* @param str {String} the HTML string to be canonicalized
|
||||
* @return {String} the canonicalized string
|
||||
*/
|
||||
function canonicalizeSpaces(str) {
|
||||
// Collapse sequential whitespace.
|
||||
str = str.replace(/\s+/g, ' ');
|
||||
|
||||
// Remove spaces immediately inside angle brackets <, >, </ and />.
|
||||
// While doing this also canonicalize <.../> to <...>.
|
||||
str = str.replace(/\< ?/g, '<');
|
||||
str = str.replace(/\<\/ ?/g, '</');
|
||||
str = str.replace(/ ?\/?\>/g, '>');
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Canonicalize an innerHTML string to uniform single whitespaces.
|
||||
* Also remove comments to retain only embedded selection markers, and
|
||||
* remove </br> and </hr> if present.
|
||||
*
|
||||
* FIXME: running this prevents testing for pre-formatted content
|
||||
* and the CSS 'white-space' attribute.
|
||||
*
|
||||
* @param str {String} the HTML string to be canonicalized
|
||||
* @return {String} the canonicalized string
|
||||
*/
|
||||
function initialCanonicalizationOf(str) {
|
||||
str = canonicalizeSpaces(str);
|
||||
str = str.replace(/ ?<!-- ?/g, '');
|
||||
str = str.replace(/ ?--> ?/g, '');
|
||||
str = str.replace(/<\/[bh]r>/g, '');
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
@ -0,0 +1,489 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Comparison functions used in the RTE test suite.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* constants used only in the compare functions.
|
||||
*/
|
||||
var RESULT_DIFF = 0; // actual result doesn't match expectation
|
||||
var RESULT_SEL = 1; // actual result matches expectation in HTML only
|
||||
var RESULT_EQUAL = 2; // actual result matches expectation in both HTML and selection
|
||||
|
||||
/**
|
||||
* Gets the test expectations as an array from the passed-in field.
|
||||
*
|
||||
* @param {Array|String} the test expectation(s) as string or array.
|
||||
* @return {Array} test expectations as an array.
|
||||
*/
|
||||
function getExpectationArray(expected) {
|
||||
if (expected === undefined) {
|
||||
return [];
|
||||
}
|
||||
if (expected === null) {
|
||||
return [null];
|
||||
}
|
||||
switch (typeof expected) {
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
return [expected];
|
||||
}
|
||||
// Assume it's already an array.
|
||||
return expected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a test result to a single expectation string.
|
||||
*
|
||||
* FIXME: add support for optional elements/attributes.
|
||||
*
|
||||
* @param expected {String} the already canonicalized (with the exception of selection marks) expectation string
|
||||
* @param actual {String} the already canonicalized (with the exception of selection marks) actual result
|
||||
* @return {Integer} one of the RESULT_... return values
|
||||
* @see variables.js for return values
|
||||
*/
|
||||
function compareHTMLToSingleExpectation(expected, actual) {
|
||||
// If the test checks the selection, then the actual string must match the
|
||||
// expectation exactly.
|
||||
if (expected == actual) {
|
||||
return RESULT_EQUAL;
|
||||
}
|
||||
|
||||
// Remove selection markers and see if strings match then.
|
||||
expected = expected.replace(/ [{}\|]>/g, '>'); // intra-tag
|
||||
expected = expected.replace(/[\[\]\^{}\|]/g, ''); // outside tag
|
||||
actual = actual.replace(/ [{}\|]>/g, '>'); // intra-tag
|
||||
actual = actual.replace(/[\[\]\^{}\|]/g, ''); // outside tag
|
||||
|
||||
return (expected == actual) ? RESULT_SEL : RESULT_DIFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the current HTMLtest result to the expectation string(s).
|
||||
*
|
||||
* @param actual {String/Boolean} actual value
|
||||
* @param expected {String/Array} expectation(s)
|
||||
* @param emitFlags {Object} flags to use for canonicalization
|
||||
* @return {Integer} one of the RESULT_... return values
|
||||
* @see variables.js for return values
|
||||
*/
|
||||
function compareHTMLToExpectation(actual, expected, emitFlags) {
|
||||
// Find the most favorable result among the possible expectation strings.
|
||||
var expectedArr = getExpectationArray(expected);
|
||||
var count = expectedArr ? expectedArr.length : 0;
|
||||
var best = RESULT_DIFF;
|
||||
|
||||
for (var idx = 0; idx < count && best < RESULT_EQUAL; ++idx) {
|
||||
var expected = expectedArr[idx];
|
||||
expected = canonicalizeSpaces(expected);
|
||||
expected = canonicalizeElementsAndAttributes(expected, emitFlags);
|
||||
|
||||
var singleResult = compareHTMLToSingleExpectation(expected, actual);
|
||||
|
||||
best = Math.max(best, singleResult);
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the current HTMLtest result to expected and acceptable results
|
||||
*
|
||||
* @param expected {String/Array} expected result(s)
|
||||
* @param accepted {String/Array} accepted result(s)
|
||||
* @param actual {String} actual result
|
||||
* @param emitFlags {Object} how to canonicalize the HTML strings
|
||||
* @param result {Object} [out] object recieving the result of the comparison.
|
||||
*/
|
||||
function compareHTMLTestResultTo(expected, accepted, actual, emitFlags, result) {
|
||||
actual = actual.replace(/[\x60\xb4]/g, '');
|
||||
actual = canonicalizeElementsAndAttributes(actual, emitFlags);
|
||||
|
||||
var bestExpected = compareHTMLToExpectation(actual, expected, emitFlags);
|
||||
|
||||
if (bestExpected == RESULT_EQUAL) {
|
||||
// Shortcut - it doesn't get any better
|
||||
result.valresult = VALRESULT_EQUAL;
|
||||
result.selresult = SELRESULT_EQUAL;
|
||||
return;
|
||||
}
|
||||
|
||||
var bestAccepted = compareHTMLToExpectation(actual, accepted, emitFlags);
|
||||
|
||||
switch (bestExpected) {
|
||||
case RESULT_SEL:
|
||||
switch (bestAccepted) {
|
||||
case RESULT_EQUAL:
|
||||
// The HTML was equal to the/an expected HTML result as well
|
||||
// (just not the selection there), therefore the difference
|
||||
// between expected and accepted can only lie in the selection.
|
||||
result.valresult = VALRESULT_EQUAL;
|
||||
result.selresult = SELRESULT_ACCEPT;
|
||||
return;
|
||||
|
||||
case RESULT_SEL:
|
||||
case RESULT_DIFF:
|
||||
// The acceptable expectations did not yield a better result
|
||||
// -> stay with the original (i.e., comparison to 'expected') result.
|
||||
result.valresult = VALRESULT_EQUAL;
|
||||
result.selresult = SELRESULT_DIFF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case RESULT_DIFF:
|
||||
switch (bestAccepted) {
|
||||
case RESULT_EQUAL:
|
||||
result.valresult = VALRESULT_ACCEPT;
|
||||
result.selresult = SELRESULT_EQUAL;
|
||||
return;
|
||||
|
||||
case RESULT_SEL:
|
||||
result.valresult = VALRESULT_ACCEPT;
|
||||
result.selresult = SELRESULT_DIFF;
|
||||
return;
|
||||
|
||||
case RESULT_DIFF:
|
||||
result.valresult = VALRESULT_DIFF;
|
||||
result.selresult = SELRESULT_NA;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
throw INTERNAL_ERR + HTML_COMPARISON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the canaries are unviolated.
|
||||
*
|
||||
* @param container {Object} the test container descriptor as object reference
|
||||
* @param result {Object} object reference that contains the result data
|
||||
* @return {Boolean} whether the canaries' HTML is OK (selection flagged, but not fatal)
|
||||
*/
|
||||
function verifyCanaries(container, result) {
|
||||
if (!container.canary) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var str = canonicalizeElementsAndAttributes(result.bodyInnerHTML, emitFlagsForCanary);
|
||||
|
||||
if (str.length < 2 * container.canary.length) {
|
||||
result.valresult = VALRESULT_CANARY;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = result.bodyOuterHTML;
|
||||
return false;
|
||||
}
|
||||
|
||||
var strBefore = str.substr(0, container.canary.length);
|
||||
var strAfter = str.substr(str.length - container.canary.length);
|
||||
|
||||
// Verify that the canary stretch doesn't contain any selection markers
|
||||
if (SELECTION_MARKERS.test(strBefore) || SELECTION_MARKERS.test(strAfter)) {
|
||||
str = str.replace(SELECTION_MARKERS, '');
|
||||
if (str.length < 2 * container.canary.length) {
|
||||
result.valresult = VALRESULT_CANARY;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = result.bodyOuterHTML;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Selection escaped contentEditable element, but HTML may still be ok.
|
||||
result.selresult = SELRESULT_CANARY;
|
||||
strBefore = str.substr(0, container.canary.length);
|
||||
strAfter = str.substr(str.length - container.canary.length);
|
||||
}
|
||||
|
||||
if (strBefore !== container.canary || strAfter !== container.canary) {
|
||||
result.valresult = VALRESULT_CANARY;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = result.bodyOuterHTML;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the current HTMLtest result to the expectation string(s).
|
||||
* Sets the global result variables.
|
||||
*
|
||||
* @param suite {Object} the test suite as object reference
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} the test as object reference
|
||||
* @param container {Object} the test container description
|
||||
* @param result {Object} [in/out] the result description, incl. HTML strings
|
||||
* @see variables.js for result values
|
||||
*/
|
||||
function compareHTMLTestResult(suite, group, test, container, result) {
|
||||
if (!verifyCanaries(container, result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var emitFlags = {
|
||||
emitAttrs: getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES),
|
||||
emitStyle: getTestParameter(suite, group, test, PARAM_CHECK_STYLE),
|
||||
emitClass: getTestParameter(suite, group, test, PARAM_CHECK_CLASS),
|
||||
emitID: getTestParameter(suite, group, test, PARAM_CHECK_ID),
|
||||
lowercase: true,
|
||||
canonicalizeUnits: true
|
||||
};
|
||||
|
||||
// 2a.) Compare opening tag -
|
||||
// decide whether to compare vs. outer or inner HTML based on this.
|
||||
var openingTagEnd = result.outerHTML.indexOf('>') + 1;
|
||||
var openingTag = result.outerHTML.substr(0, openingTagEnd);
|
||||
|
||||
openingTag = canonicalizeElementsAndAttributes(openingTag, emitFlags);
|
||||
var tagCmp = compareHTMLToExpectation(openingTag, container.tagOpen, emitFlags);
|
||||
|
||||
if (tagCmp == RESULT_EQUAL) {
|
||||
result.output = result.innerHTML;
|
||||
compareHTMLTestResultTo(
|
||||
getTestParameter(suite, group, test, PARAM_EXPECTED),
|
||||
getTestParameter(suite, group, test, PARAM_ACCEPT),
|
||||
result.innerHTML,
|
||||
emitFlags,
|
||||
result)
|
||||
} else {
|
||||
result.output = result.outerHTML;
|
||||
compareHTMLTestResultTo(
|
||||
getContainerParameter(suite, group, test, container, PARAM_EXPECTED_OUTER),
|
||||
getContainerParameter(suite, group, test, container, PARAM_ACCEPT_OUTER),
|
||||
result.outerHTML,
|
||||
emitFlags,
|
||||
result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a selection position indicator.
|
||||
*
|
||||
* @param node {DOMNode} the node where to insert the selection indicator
|
||||
* @param offs {Integer} the offset of the selection indicator
|
||||
* @param textInd {String} the indicator to use if the node is a text node
|
||||
* @param elemInd {String} the indicator to use if the node is an element node
|
||||
*/
|
||||
function insertSelectionIndicator(node, offs, textInd, elemInd) {
|
||||
switch (node.nodeType) {
|
||||
case DOM_NODE_TYPE_TEXT:
|
||||
// Insert selection marker for text node into text content.
|
||||
var text = node.data;
|
||||
node.data = text.substring(0, offs) + textInd + text.substring(offs);
|
||||
break;
|
||||
|
||||
case DOM_NODE_TYPE_ELEMENT:
|
||||
var child = node.firstChild;
|
||||
try {
|
||||
// node has other children: insert marker as comment node
|
||||
var comment = document.createComment(elemInd);
|
||||
while (child && offs) {
|
||||
--offs;
|
||||
child = child.nextSibling;
|
||||
}
|
||||
if (child) {
|
||||
node.insertBefore(comment, child);
|
||||
} else {
|
||||
node.appendChild(comment);
|
||||
}
|
||||
} catch (ex) {
|
||||
// can't append child comment -> insert as special attribute(s)
|
||||
switch (elemInd) {
|
||||
case '|':
|
||||
node.setAttribute(ATTRNAME_SEL_START, '1');
|
||||
node.setAttribute(ATTRNAME_SEL_END, '1');
|
||||
break;
|
||||
|
||||
case '{':
|
||||
node.setAttribute(ATTRNAME_SEL_START, '1');
|
||||
break;
|
||||
|
||||
case '}':
|
||||
node.setAttribute(ATTRNAME_SEL_END, '1');
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds quotes around all text nodes to show cases with non-normalized
|
||||
* text nodes. Those are not a bug, but may still be usefil in helping to
|
||||
* debug erroneous cases.
|
||||
*
|
||||
* @param node {DOMNode} root node from which to descend
|
||||
*/
|
||||
function encloseTextNodesWithQuotes(node) {
|
||||
switch (node.nodeType) {
|
||||
case DOM_NODE_TYPE_ELEMENT:
|
||||
for (var i = 0; i < node.childNodes.length; ++i) {
|
||||
encloseTextNodesWithQuotes(node.childNodes[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_TYPE_TEXT:
|
||||
node.data = '\x60' + node.data + '\xb4';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the result of a test run and do some preliminary canonicalization.
|
||||
*
|
||||
* @param container {Object} the container where to retrieve the result from as object reference
|
||||
* @param result {Object} object reference that contains the result data
|
||||
* @return {String} a preliminarily canonicalized innerHTML with selection markers
|
||||
*/
|
||||
function prepareHTMLTestResult(container, result) {
|
||||
// Start with empty strings in case any of the below throws.
|
||||
result.innerHTML = '';
|
||||
result.outerHTML = '';
|
||||
|
||||
// 1.) insert selection markers
|
||||
var selRange = createFromWindow(container.win);
|
||||
if (selRange) {
|
||||
// save values, since range object gets auto-modified
|
||||
var node1 = selRange.getAnchorNode();
|
||||
var offs1 = selRange.getAnchorOffset();
|
||||
var node2 = selRange.getFocusNode();
|
||||
var offs2 = selRange.getFocusOffset();
|
||||
|
||||
// add markers
|
||||
if (node1 && node1 == node2 && offs1 == offs2) {
|
||||
// collapsed selection
|
||||
insertSelectionIndicator(node1, offs1, '^', '|');
|
||||
} else {
|
||||
// Start point and end point are different
|
||||
if (node1) {
|
||||
insertSelectionIndicator(node1, offs1, '[', '{');
|
||||
}
|
||||
|
||||
if (node2) {
|
||||
if (node1 == node2 && offs1 < offs2) {
|
||||
// Anchor indicator was inserted under the same node, so we need
|
||||
// to shift the offset by 1
|
||||
++offs2;
|
||||
}
|
||||
insertSelectionIndicator(node2, offs2, ']', '}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2.) insert markers for text node boundaries;
|
||||
encloseTextNodesWithQuotes(container.editor);
|
||||
|
||||
// 3.) retrieve inner and outer HTML
|
||||
result.innerHTML = initialCanonicalizationOf(container.editor.innerHTML);
|
||||
result.bodyInnerHTML = initialCanonicalizationOf(container.body.innerHTML);
|
||||
if (goog.userAgent.IE) {
|
||||
result.outerHTML = initialCanonicalizationOf(container.editor.outerHTML);
|
||||
result.bodyOuterHTML = initialCanonicalizationOf(container.body.outerHTML);
|
||||
result.outerHTML = result.outerHTML.replace(/^\s+/, '');
|
||||
result.outerHTML = result.outerHTML.replace(/\s+$/, '');
|
||||
result.bodyOuterHTML = result.bodyOuterHTML.replace(/^\s+/, '');
|
||||
result.bodyOuterHTML = result.bodyOuterHTML.replace(/\s+$/, '');
|
||||
} else {
|
||||
result.outerHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.editor));
|
||||
result.bodyOuterHTML = initialCanonicalizationOf(new XMLSerializer().serializeToString(container.body));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare a text test result to the expectation string(s).
|
||||
*
|
||||
* @param suite {Object} the test suite as object reference
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} the test as object reference
|
||||
* @param actual {String/Boolean} actual value
|
||||
* @param expected {String/Array} expectation(s)
|
||||
* @return {Boolean} whether we found a match
|
||||
*/
|
||||
function compareTextTestResultWith(suite, group, test, actual, expected) {
|
||||
var expectedArr = getExpectationArray(expected);
|
||||
// Find the most favorable result among the possible expectation strings.
|
||||
var count = expectedArr.length;
|
||||
|
||||
// If the value matches the expectation exactly, then we're fine.
|
||||
for (var idx = 0; idx < count; ++idx) {
|
||||
if (actual === expectedArr[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise see if we should canonicalize specific value types.
|
||||
//
|
||||
// We only need to look at font name, color and size units if the originating
|
||||
// test was both a) queryCommandValue and b) querying a font name/color/size
|
||||
// specific criterion.
|
||||
//
|
||||
// TODO(rolandsteiner): This is ugly! Refactor!
|
||||
switch (getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
|
||||
case 'backcolor':
|
||||
case 'forecolor':
|
||||
case 'hilitecolor':
|
||||
for (var idx = 0; idx < count; ++idx) {
|
||||
if (new Color(actual).compare(new Color(expectedArr[idx])))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case 'fontname':
|
||||
for (var idx = 0; idx < count; ++idx) {
|
||||
if (new FontName(actual).compare(new FontName(expectedArr[idx])))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case 'fontsize':
|
||||
for (var idx = 0; idx < count; ++idx) {
|
||||
if (new FontSize(actual).compare(new FontSize(expectedArr[idx])))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the passed-in text test result to the expectation string(s).
|
||||
* Sets the global result variables.
|
||||
*
|
||||
* @param suite {Object} the test suite as object reference
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} the test as object reference
|
||||
* @param actual {String/Boolean} actual value
|
||||
* @return {Integer} a RESUTLHTML... result value
|
||||
* @see variables.js for result values
|
||||
*/
|
||||
function compareTextTestResult(suite, group, test, result) {
|
||||
var expected = getTestParameter(suite, group, test, PARAM_EXPECTED);
|
||||
if (compareTextTestResultWith(suite, group, test, result.output, expected)) {
|
||||
result.valresult = VALRESULT_EQUAL;
|
||||
return;
|
||||
}
|
||||
var accepted = getTestParameter(suite, group, test, PARAM_ACCEPT);
|
||||
if (accepted && compareTextTestResultWith(suite, group, test, result.output, accepted)) {
|
||||
result.valresult = VALRESULT_ACCEPT;
|
||||
return;
|
||||
}
|
||||
result.valresult = VALRESULT_DIFF;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,456 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Functions used to format the test result output.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* Writes a fatal error to the output (replaces alert box)
|
||||
*
|
||||
* @param text {String} text to output
|
||||
*/
|
||||
function writeFatalError(text) {
|
||||
var errorsStart = document.getElementById('errors');
|
||||
var divider = document.getElementById('divider');
|
||||
if (!errorsStart) {
|
||||
errorsStart = document.createElement('hr');
|
||||
errorsStart.id = 'errors';
|
||||
divider.parentNode.insertBefore(errorsStart, divider);
|
||||
}
|
||||
var error = document.createElement('div');
|
||||
error.className = 'fatalerror';
|
||||
error.innerHTML = 'FATAL ERROR: ' + escapeOutput(text);
|
||||
errorsStart.parentNode.insertBefore(error, divider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique ID for a given single test out of the suite ID and
|
||||
* test ID.
|
||||
*
|
||||
* @param suiteID {string} ID string of the suite
|
||||
* @param testID {string} ID string of the individual tests
|
||||
* @return {string} globally unique ID
|
||||
*/
|
||||
function generateOutputID(suiteID, testID) {
|
||||
return commonIDPrefix + '-' + suiteID + '_' + testID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to highlight the selection markers
|
||||
*
|
||||
* @param str {String} a HTML string containing selection markers
|
||||
* @return {String} the HTML string with highlighting tags around the markers
|
||||
*/
|
||||
function highlightSelectionMarkers(str) {
|
||||
str = str.replace(/\[/g, '<span class="sel">[</span>');
|
||||
str = str.replace(/\]/g, '<span class="sel">]</span>');
|
||||
str = str.replace(/\^/g, '<span class="sel">^</span>');
|
||||
str = str.replace(/{/g, '<span class="sel">{</span>');
|
||||
str = str.replace(/}/g, '<span class="sel">}</span>');
|
||||
str = str.replace(/\|/g, '<b class="sel">|</b>');
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to highlight the selection markers
|
||||
*
|
||||
* @param str {String} a HTML string containing selection markers
|
||||
* @return {String} the HTML string with highlighting tags around the markers
|
||||
*/
|
||||
function highlightSelectionMarkersAndTextNodes(str) {
|
||||
str = highlightSelectionMarkers(str);
|
||||
str = str.replace(/\x60/g, '<span class="txt">');
|
||||
str = str.replace(/\xb4/g, '</span>');
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to format output according to type
|
||||
*
|
||||
* @param value {String/Boolean} string or value to format
|
||||
* @return {String} HTML-formatted string
|
||||
*/
|
||||
function formatValueOrString(value) {
|
||||
if (value === undefined)
|
||||
return '<i>undefined</i>';
|
||||
if (value === null)
|
||||
return '<i>null</i>';
|
||||
|
||||
switch (typeof value) {
|
||||
case 'boolean':
|
||||
return '<i>' + value.toString() + '</i>';
|
||||
|
||||
case 'number':
|
||||
return value.toString();
|
||||
|
||||
case 'string':
|
||||
return "'" + escapeOutput(value) + "'";
|
||||
|
||||
default:
|
||||
return '<i>(' + escapeOutput(value.toString()) + ')</i>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to highlight text nodes
|
||||
*
|
||||
* @param suite {Object} the suite the test belongs to
|
||||
* @param group {Object} the group within the suite the test belongs to
|
||||
* @param test {Object} the test description as object reference
|
||||
* @param actual {String} a HTML string containing text nodes with markers
|
||||
* @return {String} string with highlighting tags around the text node parts
|
||||
*/
|
||||
function formatActualResult(suite, group, test, actual) {
|
||||
if (typeof actual != 'string')
|
||||
return formatValueOrString(actual);
|
||||
|
||||
actual = escapeOutput(actual);
|
||||
|
||||
// Fade attributes (or just style) if not actually tested for
|
||||
if (!getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES)) {
|
||||
actual = actual.replace(/([^ =]+)=\x22([^\x22]*)\x22/g, '<span class="fade">$1="$2"</span>');
|
||||
} else {
|
||||
// NOTE: convert 'class="..."' first, before adding other <span class="fade">...</span> !!!
|
||||
if (!getTestParameter(suite, group, test, PARAM_CHECK_CLASS)) {
|
||||
actual = actual.replace(/class=\x22([^\x22]*)\x22/g, '<span class="fade">class="$1"</span>');
|
||||
}
|
||||
if (!getTestParameter(suite, group, test, PARAM_CHECK_STYLE)) {
|
||||
actual = actual.replace(/style=\x22([^\x22]*)\x22/g, '<span class="fade">style="$1"</span>');
|
||||
}
|
||||
if (!getTestParameter(suite, group, test, PARAM_CHECK_ID)) {
|
||||
actual = actual.replace(/id=\x22([^\x22]*)\x22/g, '<span class="fade">id="$1"</span>');
|
||||
} else {
|
||||
// fade out contenteditable host element's 'editor-<xyz>' ID.
|
||||
actual = actual.replace(/id=\x22editor-([^\x22]*)\x22/g, '<span class="fade">id="editor-$1"</span>');
|
||||
}
|
||||
// grey out 'xmlns'
|
||||
actual = actual.replace(/xmlns=\x22([^\x22]*)\x22/g, '<span class="fade">xmlns="$1"</span>');
|
||||
// remove 'onload'
|
||||
actual = actual.replace(/onload=\x22[^\x22]*\x22 ?/g, '');
|
||||
}
|
||||
// Highlight selection markers and text nodes.
|
||||
actual = highlightSelectionMarkersAndTextNodes(actual);
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape text content for use with .innerHTML.
|
||||
*
|
||||
* @param str {String} HTML text to displayed
|
||||
* @return {String} the escaped HTML
|
||||
*/
|
||||
function escapeOutput(str) {
|
||||
return str ? str.replace(/\</g, '<').replace(/\>/g, '>') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in a single output table cell
|
||||
*
|
||||
* @param id {String} ID of the table cell
|
||||
* @param val {String} inner HTML to set
|
||||
* @param ttl {String, optional} value of the 'title' attribute
|
||||
* @param cls {String, optional} class name for the cell
|
||||
*/
|
||||
function setTD(id, val, ttl, cls) {
|
||||
var td = document.getElementById(id);
|
||||
if (td) {
|
||||
td.innerHTML = val;
|
||||
if (ttl) {
|
||||
td.title = ttl;
|
||||
}
|
||||
if (cls) {
|
||||
td.className = cls;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the results of a single test suite
|
||||
*
|
||||
* @param suite {Object} test suite as object reference
|
||||
* @param clsID {String} test class ID ('Proposed', 'RFC', 'Final')
|
||||
* @param group {Object} the group of tests within the suite the test belongs to
|
||||
* @param testIdx {Object} the test as object reference
|
||||
*/
|
||||
function outputTestResults(suite, clsID, group, test) {
|
||||
var suiteID = suite.id;
|
||||
var cls = suite[clsID];
|
||||
var trID = generateOutputID(suiteID, test.id);
|
||||
var testResult = results[suiteID][clsID][test.id];
|
||||
var testValOut = VALOUTPUT[testResult.valresult];
|
||||
var testSelOut = SELOUTPUT[testResult.selresult];
|
||||
|
||||
var suiteChecksSelOnly = !suiteChecksHTMLOrText(suite);
|
||||
var testUsesHTML = !!getTestParameter(suite, group, test, PARAM_EXECCOMMAND) ||
|
||||
!!getTestParameter(suite, group, test, PARAM_FUNCTION);
|
||||
|
||||
// Set background color for test ID
|
||||
var td = document.getElementById(trID + IDOUT_TESTID);
|
||||
if (td) {
|
||||
td.className = (suiteChecksSelOnly && testResult.selresult != SELRESULT_NA) ? testSelOut.css : testValOut.css;
|
||||
}
|
||||
|
||||
// Fill in "Command" and "Value" cells
|
||||
var cmd;
|
||||
var cmdOutput = ' ';
|
||||
var valOutput = ' ';
|
||||
|
||||
if (cmd = getTestParameter(suite, group, test, PARAM_EXECCOMMAND)) {
|
||||
cmdOutput = escapeOutput(cmd);
|
||||
var val = getTestParameter(suite, group, test, PARAM_VALUE);
|
||||
if (val !== undefined) {
|
||||
valOutput = formatValueOrString(val);
|
||||
}
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_FUNCTION)) {
|
||||
cmdOutput = '<i>' + escapeOutput(cmd) + '</i>';
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSUPPORTED)) {
|
||||
cmdOutput = '<i>queryCommandSupported</i>';
|
||||
valOutput = escapeOutput(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDENABLED)) {
|
||||
cmdOutput = '<i>queryCommandEnabled</i>';
|
||||
valOutput = escapeOutput(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDINDETERM)) {
|
||||
cmdOutput = '<i>queryCommandIndeterm</i>';
|
||||
valOutput = escapeOutput(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSTATE)) {
|
||||
cmdOutput = '<i>queryCommandState</i>';
|
||||
valOutput = escapeOutput(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
|
||||
cmdOutput = '<i>queryCommandValue</i>';
|
||||
valOutput = escapeOutput(cmd);
|
||||
} else {
|
||||
cmdOutput = '<i>(none)</i>';
|
||||
}
|
||||
setTD(trID + IDOUT_COMMAND, cmdOutput);
|
||||
setTD(trID + IDOUT_VALUE, valOutput);
|
||||
|
||||
// Fill in "Attribute checked?" and "Style checked?" cells
|
||||
if (testUsesHTML) {
|
||||
var checkAttrs = getTestParameter(suite, group, test, PARAM_CHECK_ATTRIBUTES);
|
||||
var checkStyle = getTestParameter(suite, group, test, PARAM_CHECK_STYLE);
|
||||
|
||||
setTD(trID + IDOUT_CHECKATTRS,
|
||||
checkAttrs ? OUTSTR_YES : OUTSTR_NO,
|
||||
checkAttrs ? 'attributes must match' : 'attributes are ignored');
|
||||
|
||||
if (checkAttrs && checkStyle) {
|
||||
setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_YES, 'style attribute contents must match');
|
||||
} else if (checkAttrs) {
|
||||
setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'style attribute contents is ignored');
|
||||
} else {
|
||||
setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NO, 'all attributes (incl. style) are ignored');
|
||||
}
|
||||
} else {
|
||||
setTD(trID + IDOUT_CHECKATTRS, OUTSTR_NA, 'attributes not applicable');
|
||||
setTD(trID + IDOUT_CHECKSTYLE, OUTSTR_NA, 'style not applicable');
|
||||
}
|
||||
|
||||
// Fill in test pad specification cell (initial HTML + selection markers)
|
||||
setTD(trID + IDOUT_PAD, highlightSelectionMarkers(escapeOutput(getTestParameter(suite, group, test, PARAM_PAD))));
|
||||
|
||||
// Fill in expected result(s) cell
|
||||
var expectedOutput = '';
|
||||
var expectedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_EXPECTED));
|
||||
for (var idx = 0; idx < expectedArr.length; ++idx) {
|
||||
if (expectedOutput) {
|
||||
expectedOutput += '\xA0\xA0\xA0<i>or</i><br>';
|
||||
}
|
||||
expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx]))
|
||||
: formatValueOrString(expectedArr[idx]);
|
||||
}
|
||||
var acceptedArr = getExpectationArray(getTestParameter(suite, group, test, PARAM_ACCEPT));
|
||||
for (var idx = 0; idx < acceptedArr.length; ++idx) {
|
||||
expectedOutput += '<span class="accexp">\xA0\xA0\xA0<i>or</i></span><br><span class="accexp">';
|
||||
expectedOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx]))
|
||||
: formatValueOrString(acceptedArr[idx]);
|
||||
expectedOutput += '</span>';
|
||||
}
|
||||
// TODO(rolandsteiner): THIS IS UGLY, relying on 'div' container being index 2,
|
||||
// AND not allowing other containers to have 'outer' results - change!!!
|
||||
var outerOutput = '';
|
||||
expectedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_EXPECTED_OUTER));
|
||||
for (var idx = 0; idx < expectedArr.length; ++idx) {
|
||||
if (outerOutput) {
|
||||
outerOutput += '\xA0\xA0\xA0<i>or</i><br>';
|
||||
}
|
||||
outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(expectedArr[idx]))
|
||||
: formatValueOrString(expectedArr[idx]);
|
||||
}
|
||||
acceptedArr = getExpectationArray(getContainerParameter(suite, group, test, containers[2], PARAM_ACCEPT_OUTER));
|
||||
for (var idx = 0; idx < acceptedArr.length; ++idx) {
|
||||
if (outerOutput) {
|
||||
outerOutput += '<span class="accexp">\xA0\xA0\xA0<i>or</i></span><br>';
|
||||
}
|
||||
outerOutput += '<span class="accexp">';
|
||||
outerOutput += testUsesHTML ? highlightSelectionMarkers(escapeOutput(acceptedArr[idx]))
|
||||
: formatValueOrString(acceptedArr[idx]);
|
||||
outerOutput += '</span>';
|
||||
}
|
||||
if (outerOutput) {
|
||||
expectedOutput += '<hr>' + outerOutput;
|
||||
}
|
||||
setTD(trID + IDOUT_EXPECTED, expectedOutput);
|
||||
|
||||
// Iterate over the individual container results
|
||||
for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
|
||||
var cntID = containers[cntIdx].id;
|
||||
var cntTD = document.getElementById(trID + IDOUT_CONTAINER + cntID);
|
||||
var cntResult = testResult[cntID];
|
||||
var cntValOut = VALOUTPUT[cntResult.valresult];
|
||||
var cntSelOut = SELOUTPUT[cntResult.selresult];
|
||||
var cssVal = cntValOut.css;
|
||||
var cssSel = (!suiteChecksSelOnly || cntResult.selresult != SELRESULT_NA) ? cntSelOut.css : cssVal;
|
||||
var cssCnt = cssVal;
|
||||
|
||||
// Fill in result status cell ("PASS", "ACC.", "FAIL", "EXC.", etc.)
|
||||
setTD(trID + IDOUT_STATUSVAL + cntID, cntValOut.output, cntValOut.title, cssVal);
|
||||
|
||||
// Fill in selection status cell ("PASS", "ACC.", "FAIL", "N/A")
|
||||
setTD(trID + IDOUT_STATUSSEL + cntID, cntSelOut.output, cntSelOut.title, cssSel);
|
||||
|
||||
// Fill in actual result
|
||||
switch (cntResult.valresult) {
|
||||
case VALRESULT_SETUP_EXCEPTION:
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
SETUP_EXCEPTION + '(mouseover)',
|
||||
escapeOutput(cntResult.output),
|
||||
cssVal);
|
||||
break;
|
||||
|
||||
case VALRESULT_EXECUTION_EXCEPTION:
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
EXECUTION_EXCEPTION + '(mouseover)',
|
||||
escapeOutput(cntResult.output.toString()),
|
||||
cssVal);
|
||||
break;
|
||||
|
||||
case VALRESULT_VERIFICATION_EXCEPTION:
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
VERIFICATION_EXCEPTION + '(mouseover)',
|
||||
escapeOutput(cntResult.output.toString()),
|
||||
cssVal);
|
||||
break;
|
||||
|
||||
case VALRESULT_UNSUPPORTED:
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
escapeOutput(cntResult.output),
|
||||
'',
|
||||
cssVal);
|
||||
break;
|
||||
|
||||
case VALRESULT_CANARY:
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)),
|
||||
'',
|
||||
cssVal);
|
||||
break;
|
||||
|
||||
case VALRESULT_DIFF:
|
||||
case VALRESULT_ACCEPT:
|
||||
case VALRESULT_EQUAL:
|
||||
if (!testUsesHTML) {
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
formatValueOrString(cntResult.output),
|
||||
'',
|
||||
cssVal);
|
||||
} else if (cntResult.selresult == SELRESULT_CANARY) {
|
||||
cssCnt = suiteChecksSelOnly ? cssSel : cssVal;
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
highlightSelectionMarkersAndTextNodes(escapeOutput(cntResult.output)),
|
||||
'',
|
||||
cssCnt);
|
||||
} else {
|
||||
cssCnt = suiteChecksSelOnly ? cssSel : cssVal;
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
formatActualResult(suite, group, test, cntResult.output),
|
||||
'',
|
||||
cssCnt);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cssCnt = 'exception';
|
||||
setTD(trID + IDOUT_ACTUAL + cntID,
|
||||
INTERNAL_ERR + 'UNKNOWN RESULT VALUE',
|
||||
'',
|
||||
cssCnt);
|
||||
}
|
||||
|
||||
if (cntTD) {
|
||||
cntTD.className = cssCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the results of a single test suite
|
||||
*
|
||||
* @param {Object} suite as object reference
|
||||
*/
|
||||
function outputTestSuiteResults(suite) {
|
||||
var suiteID = suite.id;
|
||||
var span;
|
||||
|
||||
span = document.getElementById(suiteID + '-score');
|
||||
if (span) {
|
||||
span.innerHTML = results[suiteID].valscore + '/' + results[suiteID].count;
|
||||
}
|
||||
span = document.getElementById(suiteID + '-selscore');
|
||||
if (span) {
|
||||
span.innerHTML = results[suiteID].selscore + '/' + results[suiteID].count;
|
||||
}
|
||||
span = document.getElementById(suiteID + '-time');
|
||||
if (span) {
|
||||
span.innerHTML = results[suiteID].time;
|
||||
}
|
||||
span = document.getElementById(suiteID + '-progress');
|
||||
if (span) {
|
||||
span.style.color = 'green';
|
||||
}
|
||||
|
||||
for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
|
||||
var clsID = testClassIDs[clsIdx];
|
||||
var cls = suite[clsID];
|
||||
if (!cls)
|
||||
continue;
|
||||
|
||||
span = document.getElementById(suiteID + '-' + clsID + '-score');
|
||||
if (span) {
|
||||
span.innerHTML = results[suiteID][clsID].valscore + '/' + results[suiteID][clsID].count;
|
||||
}
|
||||
span = document.getElementById(suiteID + '-' + clsID + '-selscore');
|
||||
if (span) {
|
||||
span.innerHTML = results[suiteID][clsID].selscore + '/' + results[suiteID][clsID].count;
|
||||
}
|
||||
|
||||
var groupCount = cls.length;
|
||||
|
||||
for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
|
||||
var group = cls[groupIdx];
|
||||
var testCount = group.tests.length;
|
||||
|
||||
for (var testIdx = 0; testIdx < testCount; ++testIdx) {
|
||||
var test = group.tests[testIdx];
|
||||
|
||||
outputTestResults(suite, clsID, group, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Functions used to handle test and expectation strings.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalize text selection indicators and convert inter-element selection
|
||||
* indicators to comments.
|
||||
*
|
||||
* Note that this function relies on the spaces of the input string already
|
||||
* having been normalized by canonicalizeSpaces!
|
||||
*
|
||||
* @param pad {String} HTML string that includes selection marker characters
|
||||
* @return {String} the HTML string with the selection markers converted
|
||||
*/
|
||||
function convertSelectionIndicators(pad) {
|
||||
// Sanity check: Markers { } | only directly before or after an element,
|
||||
// or just before a closing > (i.e., not within a text node).
|
||||
// Note that intra-tag selection markers have already been converted to the
|
||||
// special selection attribute(s) above.
|
||||
if (/[^>][{}\|][^<>]/.test(pad) ||
|
||||
/^[{}\|][^<]/.test(pad) ||
|
||||
/[^>][{}\|]$/.test(pad) ||
|
||||
/^[{}\|]*$/.test(pad)) {
|
||||
throw SETUP_BAD_SELECTION_SPEC;
|
||||
}
|
||||
|
||||
// Convert intra-tag selection markers to special attributes.
|
||||
pad = pad.replace(/\{\>/g, ATTRNAME_SEL_START + '="1">');
|
||||
pad = pad.replace(/\}\>/g, ATTRNAME_SEL_END + '="1">');
|
||||
pad = pad.replace(/\|\>/g, ATTRNAME_SEL_START + '="1" ' +
|
||||
ATTRNAME_SEL_END + '="1">');
|
||||
|
||||
// Convert remaining {, }, | to comments with '[' and ']' data.
|
||||
pad = pad.replace('{', '<!--[-->');
|
||||
pad = pad.replace('}', '<!--]-->');
|
||||
pad = pad.replace('|', '<!--[--><!--]-->');
|
||||
|
||||
// Convert caret indicator ^ to empty selection indicator []
|
||||
// (this simplifies further processing).
|
||||
pad = pad.replace(/\^/, '[]');
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives one point of the selection from the indicators with the HTML tree:
|
||||
* '[' or ']' within a text or comment node, or the special selection
|
||||
* attributes within an element node.
|
||||
*
|
||||
* @param root {DOMNode} root node of the recursive search
|
||||
* @param marker {String} which marker to look for: '[' or ']'
|
||||
* @return {Object} a pair object: {node: {DOMNode}/null, offset: {Integer}}
|
||||
*/
|
||||
function deriveSelectionPoint(root, marker) {
|
||||
switch (root.nodeType) {
|
||||
case DOM_NODE_TYPE_ELEMENT:
|
||||
if (root.attributes) {
|
||||
// Note: getAttribute() is necessary for this to work on all browsers!
|
||||
if (marker == '[' && root.getAttribute(ATTRNAME_SEL_START)) {
|
||||
root.removeAttribute(ATTRNAME_SEL_START);
|
||||
return {node: root, offs: 0};
|
||||
}
|
||||
if (marker == ']' && root.getAttribute(ATTRNAME_SEL_END)) {
|
||||
root.removeAttribute(ATTRNAME_SEL_END);
|
||||
return {node: root, offs: 0};
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < root.childNodes.length; ++i) {
|
||||
var pair = deriveSelectionPoint(root.childNodes[i], marker);
|
||||
if (pair.node) {
|
||||
return pair;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_TYPE_TEXT:
|
||||
var pos = root.data.indexOf(marker);
|
||||
if (pos != -1) {
|
||||
// Remove selection marker from text.
|
||||
var nodeText = root.data;
|
||||
root.data = nodeText.substr(0, pos) + nodeText.substr(pos + 1);
|
||||
return {node: root, offs: pos };
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM_NODE_TYPE_COMMENT:
|
||||
var pos = root.data.indexOf(marker);
|
||||
if (pos != -1) {
|
||||
// Remove comment node from parent.
|
||||
var helper = root.previousSibling;
|
||||
|
||||
for (pos = 0; helper; ++pos ) {
|
||||
helper = helper.previousSibling;
|
||||
}
|
||||
helper = root;
|
||||
root = root.parentNode;
|
||||
root.removeChild(helper);
|
||||
return {node: root, offs: pos };
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return {node: null, offs: 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the test HTML with the starting state specified in the test.
|
||||
*
|
||||
* The selection is specified "inline", using special characters:
|
||||
* ^ a collapsed text caret selection (same as [])
|
||||
* [ the selection start within a text node
|
||||
* ] the selection end within a text node
|
||||
* | collapsed selection between elements (same as {})
|
||||
* { selection starting with the following element
|
||||
* } selection ending with the preceding element
|
||||
* {, } and | can also be used within an element tag, just before the closing
|
||||
* angle bracket > to specify a selection [element, 0] where the element
|
||||
* doesn't otherwise have any children. Ex.: <hr {>foobarbaz<hr }>
|
||||
*
|
||||
* Explicit and implicit specification can also be mixed between the 2 points.
|
||||
*
|
||||
* A pad string must only contain at most ONE of the above that is suitable for
|
||||
* that start or end point, respectively, and must contain either both or none.
|
||||
*
|
||||
* @param suite {Object} suite that test originates in as object reference
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} test to be run as object reference
|
||||
* @param container {Object} container descriptor as object reference
|
||||
*/
|
||||
function initContainer(suite, group, test, container) {
|
||||
var pad = getTestParameter(suite, group, test, PARAM_PAD);
|
||||
pad = canonicalizeSpaces(pad);
|
||||
pad = convertSelectionIndicators(pad);
|
||||
|
||||
if (container.editorID) {
|
||||
container.body.innerHTML = container.canary + container.tagOpen + pad + container.tagClose + container.canary;
|
||||
container.editor = container.doc.getElementById(container.editorID);
|
||||
} else {
|
||||
container.body.innerHTML = pad;
|
||||
container.editor = container.body;
|
||||
}
|
||||
|
||||
win = container.win;
|
||||
doc = container.doc;
|
||||
body = container.body;
|
||||
editor = container.editor;
|
||||
sel = null;
|
||||
|
||||
if (!editor) {
|
||||
throw SETUP_CONTAINER;
|
||||
}
|
||||
|
||||
if (getTestParameter(suite, group, test, PARAM_STYLE_WITH_CSS)) {
|
||||
try {
|
||||
container.doc.execCommand('styleWithCSS', false, true);
|
||||
} catch (ex) {
|
||||
// ignore exception if unsupported
|
||||
}
|
||||
}
|
||||
|
||||
var selAnchor = deriveSelectionPoint(editor, '[');
|
||||
var selFocus = deriveSelectionPoint(editor, ']');
|
||||
|
||||
// sanity check
|
||||
if (!selAnchor || !selFocus) {
|
||||
throw SETUP_SELECTION;
|
||||
}
|
||||
|
||||
if (!selAnchor.node || !selFocus.node) {
|
||||
if (selAnchor.node || selFocus.node) {
|
||||
// Broken test: only one selection point was specified
|
||||
throw SETUP_BAD_SELECTION_SPEC;
|
||||
}
|
||||
sel = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (selAnchor.node === selFocus.node) {
|
||||
if (selAnchor.offs > selFocus.offs) {
|
||||
// Both selection points are within the same node, the selection was
|
||||
// specified inline (thus the end indicator element or character was
|
||||
// removed), and the end point is before the start (reversed selection).
|
||||
// Start offset that was derived is now off by 1 and needs adjustment.
|
||||
--selAnchor.offs;
|
||||
}
|
||||
|
||||
if (selAnchor.offs === selFocus.offs) {
|
||||
createCaret(selAnchor.node, selAnchor.offs).select();
|
||||
try {
|
||||
sel = win.getSelection();
|
||||
} catch (ex) {
|
||||
sel = undefined;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
createFromNodes(selAnchor.node, selAnchor.offs, selFocus.node, selFocus.offs).select();
|
||||
|
||||
try {
|
||||
sel = win.getSelection();
|
||||
} catch (ex) {
|
||||
sel = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the editor element after a test is run.
|
||||
*
|
||||
* @param container {Object} container descriptor as object reference
|
||||
*/
|
||||
function resetContainer(container) {
|
||||
// Remove errant styles and attributes that may have been set on the <body>.
|
||||
container.body.removeAttribute('style');
|
||||
container.body.removeAttribute('color');
|
||||
container.body.removeAttribute('bgcolor');
|
||||
|
||||
try {
|
||||
container.doc.execCommand('styleWithCSS', false, false);
|
||||
} catch (ex) {
|
||||
// Ignore exception if unsupported.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the editor document.
|
||||
*/
|
||||
function initEditorDocs() {
|
||||
for (var c = 0; c < containers.length; ++c) {
|
||||
var container = containers[c];
|
||||
|
||||
container.iframe = document.getElementById('iframe-' + container.id);
|
||||
container.win = container.iframe.contentWindow;
|
||||
container.doc = container.win.document;
|
||||
container.body = container.doc.body;
|
||||
// container.editor is set per test (changes on embedded editor elements).
|
||||
|
||||
// Some browsers require a selection to go with their 'styleWithCSS'.
|
||||
try {
|
||||
container.win.getSelection().selectAllChildren(editor);
|
||||
} catch (ex) {
|
||||
// ignore exception if unsupported
|
||||
}
|
||||
// Default styleWithCSS to false.
|
||||
try {
|
||||
container.doc.execCommand('styleWithCSS', false, false);
|
||||
} catch (ex) {
|
||||
// ignore exception if unsupported
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
goog.require('goog.dom.Range');
|
||||
|
||||
window.createFromWindow = goog.dom.Range.createFromWindow;
|
||||
window.createFromNodes = goog.dom.Range.createFromNodes;
|
||||
window.createCaret = goog.dom.Range.createCaret;
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,383 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Main functions used in running the RTE test suite.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
/**
|
||||
* Info function: returns true if the suite (mainly) tests the result HTML/Text.
|
||||
*
|
||||
* @param suite {String} the test suite
|
||||
* @return {boolean} Whether the suite main focus is the output HTML/Text
|
||||
*/
|
||||
function suiteChecksHTMLOrText(suite) {
|
||||
return suite.id[0] != 'S';
|
||||
}
|
||||
|
||||
/**
|
||||
* Info function: returns true if the suite checks the result selection.
|
||||
*
|
||||
* @param suite {String} the test suite
|
||||
* @return {boolean} Whether the suite checks the selection
|
||||
*/
|
||||
function suiteChecksSelection(suite) {
|
||||
return suite.id[0] != 'Q';
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function returning the effective value of a test parameter.
|
||||
*
|
||||
* @param suite {Object} the test suite
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} the test
|
||||
* @param param {String} the test parameter to be checked
|
||||
* @return {Any} the effective value of the parameter (can be undefined)
|
||||
*/
|
||||
function getTestParameter(suite, group, test, param) {
|
||||
var val = test[param];
|
||||
if (val === undefined) {
|
||||
val = group[param];
|
||||
}
|
||||
if (val === undefined) {
|
||||
val = suite[param];
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function returning the effective value of a container/test parameter.
|
||||
*
|
||||
* @param suite {Object} the test suite
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} the test
|
||||
* @param container {Object} the container descriptor object
|
||||
* @param param {String} the test parameter to be checked
|
||||
* @return {Any} the effective value of the parameter (can be undefined)
|
||||
*/
|
||||
function getContainerParameter(suite, group, test, container, param) {
|
||||
var val = undefined;
|
||||
if (test[container.id]) {
|
||||
val = test[container.id][param];
|
||||
}
|
||||
if (val === undefined) {
|
||||
val = test[param];
|
||||
}
|
||||
if (val === undefined) {
|
||||
val = group[param];
|
||||
}
|
||||
if (val === undefined) {
|
||||
val = suite[param];
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the global variables before any tests are run.
|
||||
*/
|
||||
function initVariables() {
|
||||
results = {
|
||||
count: 0,
|
||||
valscore: 0,
|
||||
selscore: 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a single test - outputs and sets the result variables.
|
||||
*
|
||||
* @param suite {Object} suite that test originates in as object reference
|
||||
* @param group {Object} group of tests within the suite the test belongs to
|
||||
* @param test {Object} test to be run as object reference
|
||||
* @param container {Object} container descriptor as object reference
|
||||
* @see variables.js for RESULT... values
|
||||
*/
|
||||
function runSingleTest(suite, group, test, container) {
|
||||
var result = {
|
||||
valscore: 0,
|
||||
selscore: 0,
|
||||
valresult: VALRESULT_NOT_RUN,
|
||||
selresult: SELRESULT_NOT_RUN,
|
||||
output: ''
|
||||
};
|
||||
|
||||
// 1.) Populate the editor element with the initial test setup HTML.
|
||||
try {
|
||||
initContainer(suite, group, test, container);
|
||||
} catch(ex) {
|
||||
result.valresult = VALRESULT_SETUP_EXCEPTION;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = SETUP_EXCEPTION + ex.toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2.) Run the test command, general function or query function.
|
||||
var isHTMLTest = false;
|
||||
|
||||
try {
|
||||
var cmd = undefined;
|
||||
|
||||
if (cmd = getTestParameter(suite, group, test, PARAM_EXECCOMMAND)) {
|
||||
isHTMLTest = true;
|
||||
// Note: "getTestParameter(suite, group, test, PARAM_VALUE) || null"
|
||||
// doesn't work, since value might be the empty string, e.g., for 'insertText'!
|
||||
var value = getTestParameter(suite, group, test, PARAM_VALUE);
|
||||
if (value === undefined) {
|
||||
value = null;
|
||||
}
|
||||
container.doc.execCommand(cmd, false, value);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_FUNCTION)) {
|
||||
isHTMLTest = true;
|
||||
eval(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSUPPORTED)) {
|
||||
result.output = container.doc.queryCommandSupported(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDENABLED)) {
|
||||
result.output = container.doc.queryCommandEnabled(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDINDETERM)) {
|
||||
result.output = container.doc.queryCommandIndeterm(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDSTATE)) {
|
||||
result.output = container.doc.queryCommandState(cmd);
|
||||
} else if (cmd = getTestParameter(suite, group, test, PARAM_QUERYCOMMANDVALUE)) {
|
||||
result.output = container.doc.queryCommandValue(cmd);
|
||||
if (result.output === false) {
|
||||
// A return value of boolean 'false' for queryCommandValue means 'not supported'.
|
||||
result.valresult = VALRESULT_UNSUPPORTED;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = UNSUPPORTED;
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result.valresult = VALRESULT_SETUP_EXCEPTION;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = SETUP_EXCEPTION + SETUP_NOCOMMAND;
|
||||
return result;
|
||||
}
|
||||
} catch (ex) {
|
||||
result.valresult = VALRESULT_EXECUTION_EXCEPTION;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = EXECUTION_EXCEPTION + ex.toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
// 4.) Verify test result
|
||||
try {
|
||||
if (isHTMLTest) {
|
||||
// First, retrieve HTML from container
|
||||
prepareHTMLTestResult(container, result);
|
||||
|
||||
// Compare result to expectations
|
||||
compareHTMLTestResult(suite, group, test, container, result);
|
||||
|
||||
result.valscore = (result.valresult === VALRESULT_EQUAL) ? 1 : 0;
|
||||
result.selscore = (result.selresult === SELRESULT_EQUAL) ? 1 : 0;
|
||||
} else {
|
||||
compareTextTestResult(suite, group, test, result);
|
||||
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.valscore = (result.valresult === VALRESULT_EQUAL) ? 1 : 0;
|
||||
}
|
||||
} catch (ex) {
|
||||
result.valresult = VALRESULT_VERIFICATION_EXCEPTION;
|
||||
result.selresult = SELRESULT_NA;
|
||||
result.output = VERIFICATION_EXCEPTION + ex.toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the results dictionary for a given test suite.
|
||||
* (for all classes -> tests -> containers)
|
||||
*
|
||||
* @param {Object} suite as object reference
|
||||
*/
|
||||
function initTestSuiteResults(suite) {
|
||||
var suiteID = suite.id;
|
||||
|
||||
// Initialize results entries for this suite
|
||||
results[suiteID] = {
|
||||
count: 0,
|
||||
valscore: 0,
|
||||
selscore: 0,
|
||||
time: 0
|
||||
};
|
||||
var totalTestCount = 0;
|
||||
|
||||
for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
|
||||
var clsID = testClassIDs[clsIdx];
|
||||
var cls = suite[clsID];
|
||||
if (!cls)
|
||||
continue;
|
||||
|
||||
results[suiteID][clsID] = {
|
||||
count: 0,
|
||||
valscore: 0,
|
||||
selscore: 0
|
||||
};
|
||||
var clsTestCount = 0;
|
||||
|
||||
var groupCount = cls.length;
|
||||
for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
|
||||
var group = cls[groupIdx];
|
||||
var testCount = group.tests.length;
|
||||
|
||||
clsTestCount += testCount;
|
||||
totalTestCount += testCount;
|
||||
|
||||
for (var testIdx = 0; testIdx < testCount; ++testIdx) {
|
||||
var test = group.tests[testIdx];
|
||||
|
||||
results[suiteID][clsID ][test.id] = {
|
||||
valscore: 0,
|
||||
selscore: 0,
|
||||
valresult: VALRESULT_NOT_RUN,
|
||||
selresult: SELRESULT_NOT_RUN
|
||||
};
|
||||
for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
|
||||
var cntID = containers[cntIdx].id;
|
||||
|
||||
results[suiteID][clsID][test.id][cntID] = {
|
||||
valscore: 0,
|
||||
selscore: 0,
|
||||
valresult: VALRESULT_NOT_RUN,
|
||||
selresult: SELRESULT_NOT_RUN,
|
||||
output: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
results[suiteID][clsID].count = clsTestCount;
|
||||
}
|
||||
results[suiteID].count = totalTestCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a single test suite (such as DELETE tests or INSERT tests).
|
||||
*
|
||||
* @param suite {Object} suite as object reference
|
||||
*/
|
||||
function runTestSuite(suite) {
|
||||
var suiteID = suite.id;
|
||||
var suiteStartTime = new Date().getTime();
|
||||
|
||||
initTestSuiteResults(suite);
|
||||
|
||||
for (var clsIdx = 0; clsIdx < testClassCount; ++clsIdx) {
|
||||
var clsID = testClassIDs[clsIdx];
|
||||
var cls = suite[clsID];
|
||||
if (!cls)
|
||||
continue;
|
||||
|
||||
var groupCount = cls.length;
|
||||
|
||||
for (var groupIdx = 0; groupIdx < groupCount; ++groupIdx) {
|
||||
var group = cls[groupIdx];
|
||||
var testCount = group.tests.length;
|
||||
|
||||
for (var testIdx = 0; testIdx < testCount; ++testIdx) {
|
||||
var test = group.tests[testIdx];
|
||||
|
||||
var valscore = 1;
|
||||
var selscore = 1;
|
||||
var valresult = VALRESULT_EQUAL;
|
||||
var selresult = SELRESULT_EQUAL;
|
||||
|
||||
for (var cntIdx = 0; cntIdx < containers.length; ++cntIdx) {
|
||||
var container = containers[cntIdx];
|
||||
var cntID = container.id;
|
||||
|
||||
var result = runSingleTest(suite, group, test, container);
|
||||
|
||||
results[suiteID][clsID][test.id][cntID] = result;
|
||||
|
||||
valscore = Math.min(valscore, result.valscore);
|
||||
selscore = Math.min(selscore, result.selscore);
|
||||
valresult = Math.min(valresult, result.valresult);
|
||||
selresult = Math.min(selresult, result.selresult);
|
||||
|
||||
resetContainer(container);
|
||||
}
|
||||
|
||||
results[suiteID][clsID][test.id].valscore = valscore;
|
||||
results[suiteID][clsID][test.id].selscore = selscore;
|
||||
results[suiteID][clsID][test.id].valresult = valresult;
|
||||
results[suiteID][clsID][test.id].selresult = selresult;
|
||||
|
||||
results[suiteID][clsID].valscore += valscore;
|
||||
results[suiteID][clsID].selscore += selscore;
|
||||
results[suiteID].valscore += valscore;
|
||||
results[suiteID].selscore += selscore;
|
||||
results.valscore += valscore;
|
||||
results.selscore += selscore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results[suiteID].time = new Date().getTime() - suiteStartTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a single test suite (such as DELETE tests or INSERT tests)
|
||||
* and updates the output HTML.
|
||||
*
|
||||
* @param {Object} suite as object reference
|
||||
*/
|
||||
function runAndOutputTestSuite(suite) {
|
||||
runTestSuite(suite);
|
||||
outputTestSuiteResults(suite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the beacon with the test results.
|
||||
*/
|
||||
function fillResults() {
|
||||
// Result totals of the individual categories
|
||||
categoryTotals = [
|
||||
'selection=' + results['S'].selscore,
|
||||
'apply=' + results['A'].valscore,
|
||||
'applyCSS=' + results['AC'].valscore,
|
||||
'change=' + results['C'].valscore,
|
||||
'changeCSS=' + results['CC'].valscore,
|
||||
'unapply=' + results['U'].valscore,
|
||||
'unapplyCSS=' + results['UC'].valscore,
|
||||
'delete=' + results['D'].valscore,
|
||||
'forwarddelete=' + results['FD'].valscore,
|
||||
'insert=' + results['I'].valscore,
|
||||
'selectionResult=' + (results['A'].selscore +
|
||||
results['AC'].selscore +
|
||||
results['C'].selscore +
|
||||
results['CC'].selscore +
|
||||
results['U'].selscore +
|
||||
results['UC'].selscore +
|
||||
results['D'].selscore +
|
||||
results['FD'].selscore +
|
||||
results['I'].selscore),
|
||||
'querySupported=' + results['Q'].valscore,
|
||||
'queryEnabled=' + results['QE'].valscore,
|
||||
'queryIndeterm=' + results['QI'].valscore,
|
||||
'queryState=' + results['QS'].valscore,
|
||||
'queryStateCSS=' + results['QSC'].valscore,
|
||||
'queryValue=' + results['QV'].valscore,
|
||||
'queryValueCSS=' + results['QVC'].valscore
|
||||
];
|
||||
|
||||
// Beacon copies category results
|
||||
beacon = categoryTotals.slice(0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Common constants and variables used in the RTE test suite.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
// All colors defined in CSS3.
|
||||
var colorChart = {
|
||||
'aliceblue': {red: 0xF0, green: 0xF8, blue: 0xFF},
|
||||
'antiquewhite': {red: 0xFA, green: 0xEB, blue: 0xD7},
|
||||
'aqua': {red: 0x00, green: 0xFF, blue: 0xFF},
|
||||
'aquamarine': {red: 0x7F, green: 0xFF, blue: 0xD4},
|
||||
'azure': {red: 0xF0, green: 0xFF, blue: 0xFF},
|
||||
'beige': {red: 0xF5, green: 0xF5, blue: 0xDC},
|
||||
'bisque': {red: 0xFF, green: 0xE4, blue: 0xC4},
|
||||
'black': {red: 0x00, green: 0x00, blue: 0x00},
|
||||
'blanchedalmond': {red: 0xFF, green: 0xEB, blue: 0xCD},
|
||||
'blue': {red: 0x00, green: 0x00, blue: 0xFF},
|
||||
'blueviolet': {red: 0x8A, green: 0x2B, blue: 0xE2},
|
||||
'brown': {red: 0xA5, green: 0x2A, blue: 0x2A},
|
||||
'burlywood': {red: 0xDE, green: 0xB8, blue: 0x87},
|
||||
'cadetblue': {red: 0x5F, green: 0x9E, blue: 0xA0},
|
||||
'chartreuse': {red: 0x7F, green: 0xFF, blue: 0x00},
|
||||
'chocolate': {red: 0xD2, green: 0x69, blue: 0x1E},
|
||||
'coral': {red: 0xFF, green: 0x7F, blue: 0x50},
|
||||
'cornflowerblue': {red: 0x64, green: 0x95, blue: 0xED},
|
||||
'cornsilk': {red: 0xFF, green: 0xF8, blue: 0xDC},
|
||||
'crimson': {red: 0xDC, green: 0x14, blue: 0x3C},
|
||||
'cyan': {red: 0x00, green: 0xFF, blue: 0xFF},
|
||||
'darkblue': {red: 0x00, green: 0x00, blue: 0x8B},
|
||||
'darkcyan': {red: 0x00, green: 0x8B, blue: 0x8B},
|
||||
'darkgoldenrod': {red: 0xB8, green: 0x86, blue: 0x0B},
|
||||
'darkgray': {red: 0xA9, green: 0xA9, blue: 0xA9},
|
||||
'darkgreen': {red: 0x00, green: 0x64, blue: 0x00},
|
||||
'darkgrey': {red: 0xA9, green: 0xA9, blue: 0xA9},
|
||||
'darkkhaki': {red: 0xBD, green: 0xB7, blue: 0x6B},
|
||||
'darkmagenta': {red: 0x8B, green: 0x00, blue: 0x8B},
|
||||
'darkolivegreen': {red: 0x55, green: 0x6B, blue: 0x2F},
|
||||
'darkorange': {red: 0xFF, green: 0x8C, blue: 0x00},
|
||||
'darkorchid': {red: 0x99, green: 0x32, blue: 0xCC},
|
||||
'darkred': {red: 0x8B, green: 0x00, blue: 0x00},
|
||||
'darksalmon': {red: 0xE9, green: 0x96, blue: 0x7A},
|
||||
'darkseagreen': {red: 0x8F, green: 0xBC, blue: 0x8F},
|
||||
'darkslateblue': {red: 0x48, green: 0x3D, blue: 0x8B},
|
||||
'darkslategray': {red: 0x2F, green: 0x4F, blue: 0x4F},
|
||||
'darkslategrey': {red: 0x2F, green: 0x4F, blue: 0x4F},
|
||||
'darkturquoise': {red: 0x00, green: 0xCE, blue: 0xD1},
|
||||
'darkviolet': {red: 0x94, green: 0x00, blue: 0xD3},
|
||||
'deeppink': {red: 0xFF, green: 0x14, blue: 0x93},
|
||||
'deepskyblue': {red: 0x00, green: 0xBF, blue: 0xFF},
|
||||
'dimgray': {red: 0x69, green: 0x69, blue: 0x69},
|
||||
'dimgrey': {red: 0x69, green: 0x69, blue: 0x69},
|
||||
'dodgerblue': {red: 0x1E, green: 0x90, blue: 0xFF},
|
||||
'firebrick': {red: 0xB2, green: 0x22, blue: 0x22},
|
||||
'floralwhite': {red: 0xFF, green: 0xFA, blue: 0xF0},
|
||||
'forestgreen': {red: 0x22, green: 0x8B, blue: 0x22},
|
||||
'fuchsia': {red: 0xFF, green: 0x00, blue: 0xFF},
|
||||
'gainsboro': {red: 0xDC, green: 0xDC, blue: 0xDC},
|
||||
'ghostwhite': {red: 0xF8, green: 0xF8, blue: 0xFF},
|
||||
'gold': {red: 0xFF, green: 0xD7, blue: 0x00},
|
||||
'goldenrod': {red: 0xDA, green: 0xA5, blue: 0x20},
|
||||
'gray': {red: 0x80, green: 0x80, blue: 0x80},
|
||||
'green': {red: 0x00, green: 0x80, blue: 0x00},
|
||||
'greenyellow': {red: 0xAD, green: 0xFF, blue: 0x2F},
|
||||
'grey': {red: 0x80, green: 0x80, blue: 0x80},
|
||||
'honeydew': {red: 0xF0, green: 0xFF, blue: 0xF0},
|
||||
'hotpink': {red: 0xFF, green: 0x69, blue: 0xB4},
|
||||
'indianred': {red: 0xCD, green: 0x5C, blue: 0x5C},
|
||||
'indigo': {red: 0x4B, green: 0x00, blue: 0x82},
|
||||
'ivory': {red: 0xFF, green: 0xFF, blue: 0xF0},
|
||||
'khaki': {red: 0xF0, green: 0xE6, blue: 0x8C},
|
||||
'lavender': {red: 0xE6, green: 0xE6, blue: 0xFA},
|
||||
'lavenderblush': {red: 0xFF, green: 0xF0, blue: 0xF5},
|
||||
'lawngreen': {red: 0x7C, green: 0xFC, blue: 0x00},
|
||||
'lemonchiffon': {red: 0xFF, green: 0xFA, blue: 0xCD},
|
||||
'lightblue': {red: 0xAD, green: 0xD8, blue: 0xE6},
|
||||
'lightcoral': {red: 0xF0, green: 0x80, blue: 0x80},
|
||||
'lightcyan': {red: 0xE0, green: 0xFF, blue: 0xFF},
|
||||
'lightgoldenrodyellow': {red: 0xFA, green: 0xFA, blue: 0xD2},
|
||||
'lightgray': {red: 0xD3, green: 0xD3, blue: 0xD3},
|
||||
'lightgreen': {red: 0x90, green: 0xEE, blue: 0x90},
|
||||
'lightgrey': {red: 0xD3, green: 0xD3, blue: 0xD3},
|
||||
'lightpink': {red: 0xFF, green: 0xB6, blue: 0xC1},
|
||||
'lightsalmon': {red: 0xFF, green: 0xA0, blue: 0x7A},
|
||||
'lightseagreen': {red: 0x20, green: 0xB2, blue: 0xAA},
|
||||
'lightskyblue': {red: 0x87, green: 0xCE, blue: 0xFA},
|
||||
'lightslategray': {red: 0x77, green: 0x88, blue: 0x99},
|
||||
'lightslategrey': {red: 0x77, green: 0x88, blue: 0x99},
|
||||
'lightsteelblue': {red: 0xB0, green: 0xC4, blue: 0xDE},
|
||||
'lightyellow': {red: 0xFF, green: 0xFF, blue: 0xE0},
|
||||
'lime': {red: 0x00, green: 0xFF, blue: 0x00},
|
||||
'limegreen': {red: 0x32, green: 0xCD, blue: 0x32},
|
||||
'linen': {red: 0xFA, green: 0xF0, blue: 0xE6},
|
||||
'magenta': {red: 0xFF, green: 0x00, blue: 0xFF},
|
||||
'maroon': {red: 0x80, green: 0x00, blue: 0x00},
|
||||
'mediumaquamarine': {red: 0x66, green: 0xCD, blue: 0xAA},
|
||||
'mediumblue': {red: 0x00, green: 0x00, blue: 0xCD},
|
||||
'mediumorchid': {red: 0xBA, green: 0x55, blue: 0xD3},
|
||||
'mediumpurple': {red: 0x93, green: 0x70, blue: 0xDB},
|
||||
'mediumseagreen': {red: 0x3C, green: 0xB3, blue: 0x71},
|
||||
'mediumslateblue': {red: 0x7B, green: 0x68, blue: 0xEE},
|
||||
'mediumspringgreen': {red: 0x00, green: 0xFA, blue: 0x9A},
|
||||
'mediumturquoise': {red: 0x48, green: 0xD1, blue: 0xCC},
|
||||
'mediumvioletred': {red: 0xC7, green: 0x15, blue: 0x85},
|
||||
'midnightblue': {red: 0x19, green: 0x19, blue: 0x70},
|
||||
'mintcream': {red: 0xF5, green: 0xFF, blue: 0xFA},
|
||||
'mistyrose': {red: 0xFF, green: 0xE4, blue: 0xE1},
|
||||
'moccasin': {red: 0xFF, green: 0xE4, blue: 0xB5},
|
||||
'navajowhite': {red: 0xFF, green: 0xDE, blue: 0xAD},
|
||||
'navy': {red: 0x00, green: 0x00, blue: 0x80},
|
||||
'oldlace': {red: 0xFD, green: 0xF5, blue: 0xE6},
|
||||
'olive': {red: 0x80, green: 0x80, blue: 0x00},
|
||||
'olivedrab': {red: 0x6B, green: 0x8E, blue: 0x23},
|
||||
'orange': {red: 0xFF, green: 0xA5, blue: 0x00},
|
||||
'orangered': {red: 0xFF, green: 0x45, blue: 0x00},
|
||||
'orchid': {red: 0xDA, green: 0x70, blue: 0xD6},
|
||||
'palegoldenrod': {red: 0xEE, green: 0xE8, blue: 0xAA},
|
||||
'palegreen': {red: 0x98, green: 0xFB, blue: 0x98},
|
||||
'paleturquoise': {red: 0xAF, green: 0xEE, blue: 0xEE},
|
||||
'palevioletred': {red: 0xDB, green: 0x70, blue: 0x93},
|
||||
'papayawhip': {red: 0xFF, green: 0xEF, blue: 0xD5},
|
||||
'peachpuff': {red: 0xFF, green: 0xDA, blue: 0xB9},
|
||||
'peru': {red: 0xCD, green: 0x85, blue: 0x3F},
|
||||
'pink': {red: 0xFF, green: 0xC0, blue: 0xCB},
|
||||
'plum': {red: 0xDD, green: 0xA0, blue: 0xDD},
|
||||
'powderblue': {red: 0xB0, green: 0xE0, blue: 0xE6},
|
||||
'purple': {red: 0x80, green: 0x00, blue: 0x80},
|
||||
'red': {red: 0xFF, green: 0x00, blue: 0x00},
|
||||
'rosybrown': {red: 0xBC, green: 0x8F, blue: 0x8F},
|
||||
'royalblue': {red: 0x41, green: 0x69, blue: 0xE1},
|
||||
'saddlebrown': {red: 0x8B, green: 0x45, blue: 0x13},
|
||||
'salmon': {red: 0xFA, green: 0x80, blue: 0x72},
|
||||
'sandybrown': {red: 0xF4, green: 0xA4, blue: 0x60},
|
||||
'seagreen': {red: 0x2E, green: 0x8B, blue: 0x57},
|
||||
'seashell': {red: 0xFF, green: 0xF5, blue: 0xEE},
|
||||
'sienna': {red: 0xA0, green: 0x52, blue: 0x2D},
|
||||
'silver': {red: 0xC0, green: 0xC0, blue: 0xC0},
|
||||
'skyblue': {red: 0x87, green: 0xCE, blue: 0xEB},
|
||||
'slateblue': {red: 0x6A, green: 0x5A, blue: 0xCD},
|
||||
'slategray': {red: 0x70, green: 0x80, blue: 0x90},
|
||||
'slategrey': {red: 0x70, green: 0x80, blue: 0x90},
|
||||
'snow': {red: 0xFF, green: 0xFA, blue: 0xFA},
|
||||
'springgreen': {red: 0x00, green: 0xFF, blue: 0x7F},
|
||||
'steelblue': {red: 0x46, green: 0x82, blue: 0xB4},
|
||||
'tan': {red: 0xD2, green: 0xB4, blue: 0x8C},
|
||||
'teal': {red: 0x00, green: 0x80, blue: 0x80},
|
||||
'thistle': {red: 0xD8, green: 0xBF, blue: 0xD8},
|
||||
'tomato': {red: 0xFF, green: 0x63, blue: 0x47},
|
||||
'turquoise': {red: 0x40, green: 0xE0, blue: 0xD0},
|
||||
'violet': {red: 0xEE, green: 0x82, blue: 0xEE},
|
||||
'wheat': {red: 0xF5, green: 0xDE, blue: 0xB3},
|
||||
'white': {red: 0xFF, green: 0xFF, blue: 0xFF},
|
||||
'whitesmoke': {red: 0xF5, green: 0xF5, blue: 0xF5},
|
||||
'yellow': {red: 0xFF, green: 0xFF, blue: 0x00},
|
||||
'yellowgreen': {red: 0x9A, green: 0xCD, blue: 0x32},
|
||||
|
||||
'transparent': {red: 0x00, green: 0x00, blue: 0x00, alpha: 0.0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Color class allows cross-browser comparison of values, which can
|
||||
* be returned from queryCommandValue in several formats:
|
||||
* #ff00ff
|
||||
* #f0f
|
||||
* rgb(255, 0, 0)
|
||||
* rgb(100%, 0%, 28%) // disabled for the time being (see below)
|
||||
* rgba(127, 0, 64, 0.25)
|
||||
* rgba(50%, 0%, 10%, 0.65) // disabled for the time being (see below)
|
||||
* palegoldenrod
|
||||
* transparent
|
||||
*
|
||||
* @constructor
|
||||
* @param value {String} original value
|
||||
*/
|
||||
function Color(value) {
|
||||
this.compare = function(other) {
|
||||
if (!this.valid || !other.valid) {
|
||||
return false;
|
||||
}
|
||||
if (this.alpha != other.alpha) {
|
||||
return false;
|
||||
}
|
||||
if (this.alpha == 0.0) {
|
||||
// both are fully transparent -> ignore the specific color information
|
||||
return true;
|
||||
}
|
||||
// TODO(rolandsteiner): handle hsl/hsla values
|
||||
return this.red == other.red && this.green == other.green && this.blue == other.blue;
|
||||
}
|
||||
this.parse = function(value) {
|
||||
if (!value)
|
||||
return false;
|
||||
value = String(value).toLowerCase();
|
||||
var match;
|
||||
// '#' + 6 hex digits, e.g., #ff3300
|
||||
match = value.match(/#([0-9a-f]{6})/i);
|
||||
if (match) {
|
||||
this.red = parseInt(match[1].substring(0, 2), 16);
|
||||
this.green = parseInt(match[1].substring(2, 4), 16);
|
||||
this.blue = parseInt(match[1].substring(4, 6), 16);
|
||||
this.alpha = 1.0;
|
||||
return true;
|
||||
}
|
||||
// '#' + 3 hex digits, e.g., #f30
|
||||
match = value.match(/#([0-9a-f]{3})/i);
|
||||
if (match) {
|
||||
this.red = parseInt(match[1].substring(0, 1), 16) * 16;
|
||||
this.green = parseInt(match[1].substring(1, 2), 16) * 16;
|
||||
this.blue = parseInt(match[1].substring(2, 3), 16) * 16;
|
||||
this.alpha = 1.0;
|
||||
return true;
|
||||
}
|
||||
// a color name, e.g., springgreen
|
||||
match = colorChart[value];
|
||||
if (match) {
|
||||
this.red = match.red;
|
||||
this.green = match.green;
|
||||
this.blue = match.blue;
|
||||
this.alpha = (match.alpha === undefined) ? 1.0 : match.alpha;
|
||||
return true;
|
||||
}
|
||||
// rgb(r, g, b), e.g., rgb(128, 12, 217)
|
||||
match = value.match(/rgb\(([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/i);
|
||||
if (match) {
|
||||
this.red = Number(match[1]);
|
||||
this.green = Number(match[2]);
|
||||
this.blue = Number(match[3]);
|
||||
this.alpha = 1.0;
|
||||
return true;
|
||||
}
|
||||
// rgb(r%, g%, b%), e.g., rgb(100%, 0%, 50%)
|
||||
// Commented out for the time being, since it seems likely that the resulting
|
||||
// decimal values will create false negatives when compared with non-% values.
|
||||
//
|
||||
// => store as separate percent values and do exact matching when compared with % values
|
||||
// and fuzzy matching when compared with non-% values?
|
||||
//
|
||||
// match = value.match(/rgb\(([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*\)/i);
|
||||
// if (match) {
|
||||
// this.red = Number(match[1]) * 255 / 100;
|
||||
// this.green = Number(match[2]) * 255 / 100;
|
||||
// this.blue = Number(match[3]) * 255 / 100;
|
||||
// this.alpha = 1.0;
|
||||
// return true;
|
||||
// }
|
||||
// rgba(r, g, b, a), e.g., rgb(128, 12, 217, 0.2)
|
||||
match = value.match(/rgba\(([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/i);
|
||||
if (match) {
|
||||
this.red = Number(match[1]);
|
||||
this.green = Number(match[2]);
|
||||
this.blue = Number(match[3]);
|
||||
this.alpha = Number(match[4]);
|
||||
return true;
|
||||
}
|
||||
// rgba(r%, g%, b%, a), e.g., rgb(100%, 0%, 50%, 0.3)
|
||||
// Commented out for the time being (cf. rgb() matching above)
|
||||
// match = value.match(/rgba\(([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%\s*,\s*([0-9]{0,3}(?:\.[0-9]+)?)%,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/i);
|
||||
// if (match) {
|
||||
// this.red = Number(match[1]) * 255 / 100;
|
||||
// this.green = Number(match[2]) * 255 / 100;
|
||||
// this.blue = Number(match[3]) * 255 / 100;
|
||||
// this.alpha = Number(match[4]);
|
||||
// return true;
|
||||
// }
|
||||
// TODO(rolandsteiner): handle "hsl(h, s, l)" and "hsla(h, s, l, a)" notation
|
||||
return false;
|
||||
}
|
||||
this.toString = function() {
|
||||
return this.valid ? this.red + ',' + this.green + ',' + this.blue : '(invalid)';
|
||||
}
|
||||
this.toHexString = function() {
|
||||
if (!this.valid)
|
||||
return '(invalid)';
|
||||
return ((this.red < 16) ? '0' : '') + this.red.toString(16) +
|
||||
((this.green < 16) ? '0' : '') + this.green.toString(16) +
|
||||
((this.blue < 16) ? '0' : '') + this.blue.toString(16);
|
||||
}
|
||||
this.valid = this.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class for converting font sizes to the size
|
||||
* attribute in a font tag. Currently only converts px because
|
||||
* only the sizes and px ever come from queryCommandValue.
|
||||
*
|
||||
* @constructor
|
||||
* @param value {String} original value
|
||||
*/
|
||||
function FontSize(value) {
|
||||
this.parse = function(str) {
|
||||
if (!str)
|
||||
this.valid = false;
|
||||
var match;
|
||||
if (match = String(str).match(/([0-9]+)px/)) {
|
||||
var px = Number(match[1]);
|
||||
if (px <= 0 || px > 47)
|
||||
return false;
|
||||
if (px <= 10) {
|
||||
this.size = '1';
|
||||
} else if (px <= 13) {
|
||||
this.size = '2';
|
||||
} else if (px <= 16) {
|
||||
this.size = '3';
|
||||
} else if (px <= 18) {
|
||||
this.size = '4';
|
||||
} else if (px <= 24) {
|
||||
this.size = '5';
|
||||
} else if (px <= 32) {
|
||||
this.size = '6';
|
||||
} else {
|
||||
this.size = '7';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (match = String(str).match(/([+-][0-9]+)/)) {
|
||||
this.size = match[1];
|
||||
return this.size >= 1 && this.size <= 7;
|
||||
}
|
||||
if (Number(str)) {
|
||||
this.size = String(Number(str));
|
||||
return this.size >= 1 && this.size <= 7;
|
||||
}
|
||||
switch (str) {
|
||||
case 'x-small':
|
||||
this.size = '1';
|
||||
return true;
|
||||
case 'small':
|
||||
this.size = '2';
|
||||
return true;
|
||||
case 'medium':
|
||||
this.size = '3';
|
||||
return true;
|
||||
case 'large':
|
||||
this.size = '4';
|
||||
return true;
|
||||
case 'x-large':
|
||||
this.size = '5';
|
||||
return true;
|
||||
case 'xx-large':
|
||||
this.size = '6';
|
||||
return true;
|
||||
case 'xxx-large':
|
||||
this.size = '7';
|
||||
return true;
|
||||
case '-webkit-xxx-large':
|
||||
this.size = '7';
|
||||
return true;
|
||||
case 'larger':
|
||||
this.size = '+1';
|
||||
return true;
|
||||
case 'smaller':
|
||||
this.size = '-1';
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
this.compare = function(other) {
|
||||
return this.valid && other.valid && this.size === other.size;
|
||||
}
|
||||
this.toString = function() {
|
||||
return this.valid ? this.size : '(invalid)';
|
||||
}
|
||||
this.valid = this.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class for converting & canonicalizing font names.
|
||||
*
|
||||
* @constructor
|
||||
* @param value {String} original value
|
||||
*/
|
||||
function FontName(value) {
|
||||
this.parse = function(str) {
|
||||
if (!str)
|
||||
return false;
|
||||
str = String(str).toLowerCase();
|
||||
switch (str) {
|
||||
case 'arial new':
|
||||
this.fontname = 'arial';
|
||||
return true;
|
||||
case 'courier new':
|
||||
this.fontname = 'courier';
|
||||
return true;
|
||||
case 'times new':
|
||||
case 'times roman':
|
||||
case 'times new roman':
|
||||
this.fontname = 'times';
|
||||
return true;
|
||||
}
|
||||
this.fontname = value;
|
||||
return true;
|
||||
}
|
||||
this.compare = function(other) {
|
||||
return this.valid && other.valid && this.fontname === other.fontname;
|
||||
}
|
||||
this.toString = function() {
|
||||
return this.valid ? this.fontname : '(invalid)';
|
||||
}
|
||||
this.valid = this.parse(value);
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
* @fileoverview
|
||||
* Common constants and variables used in the RTE test suite.
|
||||
*
|
||||
* Copyright 2010 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License')
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @version 0.1
|
||||
* @author rolandsteiner@google.com
|
||||
*/
|
||||
|
||||
// Constant for indicating a test setup is unsupported or incorrect
|
||||
// (threw exception).
|
||||
var INTERNAL_ERR = 'INTERNAL ERROR: ';
|
||||
var SETUP_EXCEPTION = 'SETUP EXCEPTION: ';
|
||||
var EXECUTION_EXCEPTION = 'EXECUTION EXCEPTION: ';
|
||||
var VERIFICATION_EXCEPTION = 'VERIFICATION EXCEPTION: ';
|
||||
|
||||
var SETUP_CONTAINER = 'WHEN INITIALIZING TEST CONTAINER';
|
||||
var SETUP_BAD_SELECTION_SPEC = 'BAD SELECTION SPECIFICATION IN TEST OR EXPECTATION STRING';
|
||||
var SETUP_HTML = 'WHEN SETTING TEST HTML';
|
||||
var SETUP_SELECTION = 'WHEN SETTING SELECTION';
|
||||
var SETUP_NOCOMMAND = 'NO COMMAND, GENERAL FUNCTION OR QUERY FUNCTION GIVEN';
|
||||
var HTML_COMPARISON = 'WHEN COMPARING OUTPUT HTML';
|
||||
|
||||
// Exceptiona to be thrown on unsupported selection operations
|
||||
var SELMODIFY_UNSUPPORTED = 'UNSUPPORTED selection.modify()';
|
||||
var SELALLCHILDREN_UNSUPPORTED = 'UNSUPPORTED selection.selectAllChildren()';
|
||||
|
||||
// Output string for unsupported functions
|
||||
// (returning bool 'false' as opposed to throwing an exception)
|
||||
var UNSUPPORTED = '<i>false</i> (UNSUPPORTED)';
|
||||
|
||||
// HTML comparison result contants.
|
||||
var VALRESULT_NOT_RUN = 0; // test hasn't been run yet
|
||||
var VALRESULT_SETUP_EXCEPTION = 1;
|
||||
var VALRESULT_EXECUTION_EXCEPTION = 2;
|
||||
var VALRESULT_VERIFICATION_EXCEPTION = 3;
|
||||
var VALRESULT_UNSUPPORTED = 4;
|
||||
var VALRESULT_CANARY = 5; // HTML changes bled into the canary.
|
||||
var VALRESULT_DIFF = 6;
|
||||
var VALRESULT_ACCEPT = 7; // HTML technically correct, but not ideal.
|
||||
var VALRESULT_EQUAL = 8;
|
||||
|
||||
var VALOUTPUT = [ // IMPORTANT: this array MUST be coordinated with the values above!!
|
||||
{css: 'grey', output: '???', title: 'The test has not been run yet.'}, // VALRESULT_NOT_RUN
|
||||
{css: 'exception', output: 'EXC.', title: 'Exception was thrown during setup.'}, // VALRESULT_SETUP_EXCEPTION
|
||||
{css: 'exception', output: 'EXC.', title: 'Exception was thrown during execution.'}, // VALRESULT_EXECUTION_EXCEPTION
|
||||
{css: 'exception', output: 'EXC.', title: 'Exception was thrown during result verification.'}, // VALRESULT_VERIFICATION_EXCEPTION
|
||||
{css: 'unsupported', output: 'UNS.', title: 'Unsupported command or value'}, // VALRESULT_UNSUPPORTED
|
||||
{css: 'canary', output: 'CANARY', title: 'The command affected the contentEditable root element, or outside HTML.'}, // VALRESULT_CANARY
|
||||
{css: 'fail', output: 'FAIL', title: 'The result differs from the expectation(s).'}, // VALRESULT_DIFF
|
||||
{css: 'accept', output: 'ACC.', title: 'The result is technically correct, but sub-optimal.'}, // VALRESULT_ACCEPT
|
||||
{css: 'pass', output: 'PASS', title: 'The test result matches the expectation.'} // VALRESULT_EQUAL
|
||||
]
|
||||
|
||||
// Selection comparison result contants.
|
||||
var SELRESULT_NOT_RUN = 0; // test hasn't been run yet
|
||||
var SELRESULT_CANARY = 1; // selection escapes the contentEditable element
|
||||
var SELRESULT_DIFF = 2;
|
||||
var SELRESULT_NA = 3;
|
||||
var SELRESULT_ACCEPT = 4; // Selection is acceptable, but not ideal.
|
||||
var SELRESULT_EQUAL = 5;
|
||||
|
||||
var SELOUTPUT = [ // IMPORTANT: this array MUST be coordinated with the values above!!
|
||||
{css: 'grey', output: 'grey', title: 'The test has not been run yet.'}, // SELRESULT_NOT_RUN
|
||||
{css: 'canary', output: 'CANARY', title: 'The selection escaped the contentEditable boundary!'}, // SELRESULT_CANARY
|
||||
{css: 'fail', output: 'FAIL', title: 'The selection differs from the expectation(s).'}, // SELRESULT_DIFF
|
||||
{css: 'na', output: 'N/A', title: 'The correctness of the selection could not be verified.'}, // SELRESULT_NA
|
||||
{css: 'accept', output: 'ACC.', title: 'The selection is technically correct, but sub-optimal.'}, // SELRESULT_ACCEPT
|
||||
{css: 'pass', output: 'PASS', title: 'The selection matches the expectation.'} // SELRESULT_EQUAL
|
||||
];
|
||||
|
||||
// RegExp for selection markers
|
||||
var SELECTION_MARKERS = /[\[\]\{\}\|\^]/;
|
||||
|
||||
// Special attributes used to mark selections within elements that otherwise
|
||||
// have no children. Important: attribute name MUST be lower case!
|
||||
var ATTRNAME_SEL_START = 'bsselstart';
|
||||
var ATTRNAME_SEL_END = 'bsselend';
|
||||
|
||||
// DOM node type constants.
|
||||
var DOM_NODE_TYPE_ELEMENT = 1;
|
||||
var DOM_NODE_TYPE_TEXT = 3;
|
||||
var DOM_NODE_TYPE_COMMENT = 8;
|
||||
|
||||
// Test parameter names
|
||||
var PARAM_DESCRIPTION = 'desc';
|
||||
var PARAM_PAD = 'pad';
|
||||
var PARAM_EXECCOMMAND = 'command';
|
||||
var PARAM_FUNCTION = 'function';
|
||||
var PARAM_QUERYCOMMANDSUPPORTED = 'qcsupported';
|
||||
var PARAM_QUERYCOMMANDENABLED = 'qcenabled';
|
||||
var PARAM_QUERYCOMMANDINDETERM = 'qcindeterm';
|
||||
var PARAM_QUERYCOMMANDSTATE = 'qcstate';
|
||||
var PARAM_QUERYCOMMANDVALUE = 'qcvalue';
|
||||
var PARAM_VALUE = 'value';
|
||||
var PARAM_EXPECTED = 'expected';
|
||||
var PARAM_EXPECTED_OUTER = 'expOuter';
|
||||
var PARAM_ACCEPT = 'accept';
|
||||
var PARAM_ACCEPT_OUTER = 'accOuter';
|
||||
var PARAM_CHECK_ATTRIBUTES = 'checkAttrs';
|
||||
var PARAM_CHECK_STYLE = 'checkStyle';
|
||||
var PARAM_CHECK_CLASS = 'checkClass';
|
||||
var PARAM_CHECK_ID = 'checkID';
|
||||
var PARAM_STYLE_WITH_CSS = 'styleWithCSS';
|
||||
|
||||
// ID suffixes for the output columns
|
||||
var IDOUT_TR = '_:TR:'; // per container
|
||||
var IDOUT_TESTID = '_:tid'; // per test
|
||||
var IDOUT_COMMAND = '_:cmd'; // per test
|
||||
var IDOUT_VALUE = '_:val'; // per test
|
||||
var IDOUT_CHECKATTRS = '_:att'; // per test
|
||||
var IDOUT_CHECKSTYLE = '_:sty'; // per test
|
||||
var IDOUT_CONTAINER = '_:cnt:'; // per container
|
||||
var IDOUT_STATUSVAL = '_:sta:'; // per container
|
||||
var IDOUT_STATUSSEL = '_:sel:'; // per container
|
||||
var IDOUT_PAD = '_:pad'; // per test
|
||||
var IDOUT_EXPECTED = '_:exp'; // per test
|
||||
var IDOUT_ACTUAL = '_:act:'; // per container
|
||||
|
||||
// Output strings to use for yes/no/NA
|
||||
var OUTSTR_YES = '●';
|
||||
var OUTSTR_NO = '○';
|
||||
var OUTSTR_NA = '-';
|
||||
|
||||
// Tags at the start of HTML strings where they were taken from
|
||||
var HTMLTAG_BODY = 'B:';
|
||||
var HTMLTAG_OUTER = 'O:';
|
||||
var HTMLTAG_INNER = 'I:';
|
||||
|
||||
// What to use for the canary
|
||||
var CANARY = 'CAN<br>ARY';
|
||||
|
||||
// Containers for tests, and their associated DOM elements:
|
||||
// iframe, win, doc, body, elem
|
||||
var containers = [
|
||||
{ id: 'dM',
|
||||
iframe: null,
|
||||
win: null,
|
||||
doc: null,
|
||||
body: null,
|
||||
editor: null,
|
||||
tagOpen: '<body>',
|
||||
tagClose: '</body>',
|
||||
editorID: null,
|
||||
canary: '',
|
||||
},
|
||||
{ id: 'body',
|
||||
iframe: null,
|
||||
win: null,
|
||||
doc: null,
|
||||
body: null,
|
||||
editor: null,
|
||||
tagOpen: '<body contenteditable="true">',
|
||||
tagClose: '</body>',
|
||||
editorID: null,
|
||||
canary: ''
|
||||
},
|
||||
{ id: 'div',
|
||||
iframe: null,
|
||||
win: null,
|
||||
doc: null,
|
||||
body: null,
|
||||
editor: null,
|
||||
tagOpen: '<div contenteditable="true" id="editor-div">',
|
||||
tagClose: '</div>',
|
||||
editorID: 'editor-div',
|
||||
canary: CANARY
|
||||
}
|
||||
];
|
||||
|
||||
// Helper variables to use in test functions
|
||||
var win = null; // window object to use for test functions
|
||||
var doc = null; // document object to use for test functions
|
||||
var body = null; // The <body> element of the current document
|
||||
var editor = null; // The contentEditable element (i.e., the <body> or <div>)
|
||||
var sel = null; // The current selection after the pad is set up
|
||||
|
||||
// Canonicalization emit flags for various purposes
|
||||
var emitFlagsForCanary = {
|
||||
emitAttrs: true,
|
||||
emitStyle: true,
|
||||
emitClass: true,
|
||||
emitID: true,
|
||||
lowercase: true,
|
||||
canonicalizeUnits: true
|
||||
};
|
||||
var emitFlagsForOutput = {
|
||||
emitAttrs: true,
|
||||
emitStyle: true,
|
||||
emitClass: true,
|
||||
emitID: true,
|
||||
lowercase: false,
|
||||
canonicalizeUnits: false
|
||||
};
|
||||
|
||||
// Shades of output colors
|
||||
var colorShades = ['Lo', 'Hi'];
|
||||
|
||||
// Classes of tests
|
||||
var testClassIDs = ['Finalized', 'RFC', 'Proposed'];
|
||||
var testClassCount = testClassIDs.length;
|
||||
|
||||
// Dictionary storing the detailed test results.
|
||||
var results = {
|
||||
count: 0,
|
||||
score: 0
|
||||
};
|
||||
|
||||
// Results - populated by the fillResults() function.
|
||||
var beacon = [];
|
||||
|
||||
// "compatibility" between Python and JS for test quines
|
||||
var True = true;
|
||||
var False = false;
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
<!-- Legend -->
|
||||
<TABLE CLASS="legend framed">
|
||||
<THEAD>
|
||||
<TR><TH COLSPAN=3 CLASS="legendHdr">Result Description</TH></TR>
|
||||
<TR><TH>Status</TH><TH ALIGN="LEFT">Meaning</TH><TH ALIGN="LEFT">Explanation</TH><TH>Scoring</TH></TR>
|
||||
</THEAD>
|
||||
<TBODY>
|
||||
<TR CLASS="lo"><TD CLASS="pass" ALIGN="CENTER"> PASS </TD><TD CLASS="legend" ROWSPAN=2>Passed</TD><TD CLASS="legend" ROWSPAN=2>The result matches the expectation.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="pass">PASS (+1)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="pass" ALIGN="CENTER"> PASS </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="accept" ALIGN="CENTER"> ACC. </TD><TD CLASS="legend" ROWSPAN=2>Acceptable</TD><TD CLASS="legend" ROWSPAN=2>The result is technically correct, but not ideal (too verbose, deprecated usage, etc.) - for informative purposes only.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="accept" ALIGN="CENTER"> ACC. </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="fail" ALIGN="CENTER"> FAIL </TD><TD CLASS="legend" ROWSPAN=2>Failure</TD><TD CLASS="legend" ROWSPAN=2>The result does not match any given expectation.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="fail" ALIGN="CENTER"> FAIL </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="canary" ALIGN="CENTER"> CANARY </TD><TD CLASS="legend" ROWSPAN=2>Canary</TD><TD CLASS="legend" ROWSPAN=2>The result changes HTML other than children of the contentEditable element.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="canary" ALIGN="CENTER"> CANARY </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="unsupported" ALIGN="CENTER"> UNS. </TD><TD CLASS="legend" ROWSPAN=2>Unsupported</TD><TD CLASS="legend" ROWSPAN=2>The specific function or value is unsupported (returned boolean 'false').</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="unsupported" ALIGN="CENTER"> UNS. </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="exception" ALIGN="CENTER"> EXC. </TD><TD CLASS="legend" ROWSPAN=2>Exception</TD><TD CLASS="legend" ROWSPAN=2>An unexpected exception was thrown during the execution of the test.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="exception" ALIGN="CENTER"> EXC. </TD></TR>
|
||||
<TR CLASS="lo"><TD CLASS="na" ALIGN="CENTER"> N/A </TD><TD CLASS="legend" ROWSPAN=2>Not Applicable</TD><TD CLASS="legend" ROWSPAN=2>The selection could not be tested, because the tested function failed to return a known result.</TD><TD ROWSPAN=2 ALIGN="CENTER" CLASS="fail">FAIL (+0)</TD></TR>
|
||||
<TR CLASS="hi"><TD CLASS="na" ALIGN="CENTER"> N/A </TD></TR>
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
<TABLE CLASS="legend framed">
|
||||
<THEAD>
|
||||
<TR><TH COLSPAN=2 CLASS="legendHdr">Selection and Result Display</TH></TR>
|
||||
<TR><TH>Character</TH><TH ALIGN="LEFT">Explanation</TH></TR>
|
||||
</THEAD>
|
||||
<TBODY>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">[</TD><TD>Start of selection - selection point is within a text node.</TD></TR>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">]</TD><TD>End of selection - selection point is within a text node.</TD></TR>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">^</TD><TD>Collapsed selection - selection point is within a text node.</TD></TR>
|
||||
<TR><TD COLSPAN=2> </TD></TR>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">{</TD><TD>Start of selection - selection point is within an element node.</TD></TR>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">}</TD><TD>End of selection - selection point is within an element node.</TD></TR>
|
||||
<TR><TD CLASS="sel" ALIGN="CENTER">|</TD><TD>Collapsed selection - selection point is within an element node.</TD></TR>
|
||||
<TR><TD COLSPAN=2> </TD></TR>
|
||||
<TR><TD ALIGN="CENTER"><SPAN CLASS="fade">foo</SPAN></TD><TD>Greyed text indicates parts of the output that are ignored for the purposes of checking the result.</TD></TR>
|
||||
<TR><TD ALIGN="CENTER"><SPAN CLASS="txt">foo</SPAN></TD><TD>Grey border indicates extent of text nodes in the result.</TD></TR>
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
<!-- progress meter -->
|
||||
<HR ID="divider">
|
||||
<H1>Running Test Suites: {% for s in suites %}<A HREF="#{{ s.id }}" ID="{{ s.id }}-progress" STYLE="color: #eeeeee">{{ s.id }}</A> {% endfor %}<SPAN ID="done"> </SPAN></H1>
|
||||
<HR>
|
||||
<!-- main output -->
|
||||
{% for s in suites %}
|
||||
<H1 ID="{{ s.id }}"><A NAME="{{ s.id }}" HREF="#{{ s.id }}">{{ s.id }}</A> - {{ s.caption }}:
|
||||
<SPAN ID="{{ s.id }}-{% ifequal s.id.0 'S' %}sel{% endifequal %}score">?/?</SPAN>
|
||||
{% ifnotequal s.id.0 "Q" %}{% ifnotequal s.id.0 "S" %}
|
||||
(Selection: <SPAN ID="{{ s.id }}-selscore">?/?</SPAN>)
|
||||
{% endifnotequal %}{% endifnotequal %}
|
||||
(time: <SPAN ID="{{ s.id }}-time">?</SPAN> ms)
|
||||
</H1>
|
||||
{% if s.comment %}
|
||||
<DIV CLASS="comment">{{ s.comment|safe }}</DIV>
|
||||
{% endif %}
|
||||
{% for cls in classes %}{% for pk, pv in s.items %}{% ifequal pk cls %}
|
||||
<H2 ID="{{ s.id }}-{{ cls }}"><A NAME="{{ s.id }}-{{ cls }}" HREF="#{{ s.id }}-{{ cls }}">{{ cls }} Tests</A>:
|
||||
<SPAN ID="{{ s.id }}-{{ cls }}-{% ifequal s.id.0 'S' %}sel{% endifequal %}score">?/?</SPAN>
|
||||
{% ifnotequal s.id.0 "Q" %}{% ifnotequal s.id.0 "S" %}
|
||||
(Selection: <SPAN ID="{{ s.id }}-{{ cls }}-selscore">?/?</SPAN>)
|
||||
{% endifnotequal %}{% endifnotequal %}
|
||||
</H2>
|
||||
<TABLE WIDTH=100%>
|
||||
<THEAD>
|
||||
<TR>
|
||||
<TH TITLE="Unique ID of the test" ALIGN="LEFT">ID</TH>
|
||||
<TH TITLE="Command or function used in the test" ALIGN="LEFT">Command</TH>
|
||||
<TH TITLE="Value field for commands" ALIGN="LEFT">Value</TH>
|
||||
{% ifnotequal s.id.0 "S" %}{% ifnotequal s.id.0 "Q" %}{% comment %} Don't output attribute and style columns for selection and "queryCommand..." tests. {% endcomment %}
|
||||
<TH TITLE="check Atributes?">A</TH>
|
||||
<TH TITLE="check Style">S</TH>
|
||||
{% endifnotequal %}{% endifnotequal %}
|
||||
<TH TITLE="Testing HTML Element">Env.</TH>
|
||||
{% ifnotequal s.id.0 "S" %}{% comment %} Don't output HTML status column for selection tests. {% endcomment %}
|
||||
<TH TITLE="State of the test">Status</TH>
|
||||
{% endifnotequal %}
|
||||
{% ifnotequal s.id.0 "Q" %}{% comment %} Don't output selection result column for "queryCommand..." tests. {% endcomment %}
|
||||
<TH TITLE="State of the test regarding the selection">Selection</TH>
|
||||
{% endifnotequal %}
|
||||
<TH TITLE="Initial HTML and selection" ALIGN="LEFT">Initial</TH>
|
||||
<TH TITLE="Expected HTML and selection" ALIGN="LEFT">Expected</TH>
|
||||
<TH TITLE="Actual result HTML and selection" ALIGN="LEFT">Actual (lower case, canonicalized, selection marks)</TH>
|
||||
<TH TITLE="Short description of the test" ALIGN="LEFT">Description</TH>
|
||||
</TR>
|
||||
</THEAD>
|
||||
<TBODY>
|
||||
{% for g in pv %}{% for t in g.tests %}
|
||||
<TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:dM" CLASS="{% cycle 'lo' 'lo' 'lo' 'hi' 'hi' 'hi' as shade %}">
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:tid"><A CLASS="idLabel" NAME="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}" HREF="#{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}">{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}</A></TD>
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cmd"> </TD>
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:val"> </TD>
|
||||
{% ifnotequal s.id.0 "S" %}{% ifnotequal s.id.0 "Q" %}{% comment %} Don't output attribute and style columns for selection and "queryCommand..." tests. {% endcomment %}
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:att" ALIGN="CENTER"> </TD>
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sty" ALIGN="CENTER"> </TD>
|
||||
{% endifnotequal %}{% endifnotequal %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:dM" TITLE="designMode="on"" ALIGN="CENTER">dM</TD>
|
||||
{% ifnotequal s.id.0 "S" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:dM" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
{% ifnotequal s.id.0 "Q" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:dM" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:pad"> </TD>
|
||||
<TD ROWSPAN=3 ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:exp"> </TD>
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:dM"><I>Processing...</I></TD>
|
||||
<TD ROWSPAN=3>{{ t.desc|default:" " }}</TD>
|
||||
</TR>
|
||||
<TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:body" CLASS="{% cycle shade %}">
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:body" TITLE="<body contentEditable="true">" ALIGN="CENTER">body</TD>
|
||||
{% ifnotequal s.id.0 "S" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:body" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
{% ifnotequal s.id.0 "Q" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:body" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:body"><I>Processing...</I></TD>
|
||||
</TR>
|
||||
<TR ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:TR:div" CLASS="{% cycle shade %}">
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:cnt:div" TITLE="<div contentEditable="true">" ALIGN="CENTER">div</TD>
|
||||
{% ifnotequal s.id.0 "S" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sta:div" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
{% ifnotequal s.id.0 "Q" %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:sel:div" ALIGN="CENTER">NONE</TD>
|
||||
{% endifnotequal %}
|
||||
<TD ID="{{ commonIDPrefix }}-{{ s.id }}_{{ t.id }}_:act:div"><I>Processing...</I></TD>
|
||||
</TR>
|
||||
{% endfor %}{% endfor %}
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
{% endifequal %}{% endfor %}{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>New Rich Text Tests</title>
|
||||
|
||||
<link rel="stylesheet" href="static/common.css" type="text/css">
|
||||
<link rel="stylesheet" href="static/editable.css" type="text/css">
|
||||
|
||||
<!-- utility scripts -->
|
||||
<script src="static/js/variables.js"></script>
|
||||
|
||||
<script src="static/js/canonicalize.js"></script>
|
||||
<script src="static/js/compare.js"></script>
|
||||
<script src="static/js/output.js"></script>
|
||||
<script src="static/js/pad.js"></script>
|
||||
<script src="static/js/range.js"></script>
|
||||
<script src="static/js/units.js"></script>
|
||||
|
||||
<script src="static/js/run.js"></script>
|
||||
|
||||
<!-- new tests -->
|
||||
<script type="text/javascript">
|
||||
{% autoescape off %}
|
||||
|
||||
var commonIDPrefix = '{{ commonIDPrefix }}';
|
||||
{% for s in suites %}
|
||||
var {{ s.id }}_TESTS = {{ s }};
|
||||
{% endfor %}
|
||||
|
||||
/**
|
||||
* Stuff to do after all tests are run:
|
||||
* - write a nice "DONE!" at the end of the progress meter
|
||||
* - beacon the results
|
||||
* - remove the testing <iframe>s
|
||||
*/
|
||||
function finish() {
|
||||
var span = document.getElementById('done');
|
||||
if (span)
|
||||
span.innerHTML = ' ... DONE!';
|
||||
|
||||
fillResults();
|
||||
parent.sendScore(beacon, categoryTotals);
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run every individual suite, with a a brief timeout in between
|
||||
* to allow for screen updates.
|
||||
*/
|
||||
{% for s in suites %}
|
||||
{% if not forloop.first %}
|
||||
setTimeout("runSuite{{ s.id }}()", 100);
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
function runSuite{{ s.id }}() {
|
||||
runAndOutputTestSuite({{ s.id }}_TESTS);
|
||||
{% endfor %}
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all tests in all suites.
|
||||
*/
|
||||
function doRunTests() {
|
||||
initVariables();
|
||||
initEditorDocs();
|
||||
|
||||
// Start with the first test suite
|
||||
runSuite{{ suites.0.id }}();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs after allowing for some time to have everything loaded
|
||||
* (aka. horrible IE9 kludge)
|
||||
*/
|
||||
function runTests() {
|
||||
setTimeout("doRunTests()", 1500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the <iframe>s after all tests are finished
|
||||
*/
|
||||
function cleanUp() {
|
||||
var e = document.getElementById('iframe-dM');
|
||||
e.parentNode.removeChild(e);
|
||||
e = document.getElementById('iframe-body');
|
||||
e.parentNode.removeChild(e);
|
||||
e = document.getElementById('iframe-div');
|
||||
e.parentNode.removeChild(e);
|
||||
}
|
||||
{% endautoescape %}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="runTests()">
|
||||
{% include "richtext2/templates/output.html" %}
|
||||
<hr>
|
||||
<iframe name="iframe-dM" id="iframe-dM" src="static/editable-dM.html"></iframe>
|
||||
<iframe name="iframe-body" id="iframe-body" src="static/editable-body.html"></iframe>
|
||||
<iframe name="iframe-div" id="iframe-div" src="static/editable-div.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
__all__ = [
|
||||
'apply',
|
||||
'applyCSS',
|
||||
'change',
|
||||
'changeCSS',
|
||||
'delete',
|
||||
'forwarddelete',
|
||||
'insert',
|
||||
'queryEnabled',
|
||||
'queryIndeterm',
|
||||
'queryState',
|
||||
'querySupported',
|
||||
'queryValue',
|
||||
'selection',
|
||||
'unapply',
|
||||
'unapplyCSS'
|
||||
]
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
|
||||
APPLY_TESTS = {
|
||||
'id': 'A',
|
||||
'caption': 'Apply Formatting Tests',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] bold',
|
||||
'command': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_TEXT-1_SI',
|
||||
'rte1-id': 'a-bold-0',
|
||||
'desc': 'Bold selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<b>[bar]</b>baz',
|
||||
'foo<strong>[bar]</strong>baz' ] },
|
||||
|
||||
{ 'id': 'B_TEXT-1_SIR',
|
||||
'desc': 'Bold reversed selection',
|
||||
'pad': 'foo]bar[baz',
|
||||
'expected': [ 'foo<b>[bar]</b>baz',
|
||||
'foo<strong>[bar]</strong>baz' ] },
|
||||
|
||||
{ 'id': 'B_I-1_SL',
|
||||
'desc': 'Bold selection, partially including italic',
|
||||
'pad': 'foo[bar<i>baz]qoz</i>quz',
|
||||
'expected': [ 'foo<b>[bar</b><i><b>baz]</b>qoz</i>quz',
|
||||
'foo<b>[bar<i>baz]</i></b><i>qoz</i>quz',
|
||||
'foo<strong>[bar</strong><i><strong>baz]</strong>qoz</i>quz',
|
||||
'foo<strong>[bar<i>baz]</i></strong><i>qoz</i>quz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_TEXT-1_SI',
|
||||
'rte1-id': 'a-italic-0',
|
||||
'desc': 'Italicize selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<i>[bar]</i>baz',
|
||||
'foo<em>[bar]</em>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] underline',
|
||||
'command': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_TEXT-1_SI',
|
||||
'rte1-id': 'a-underline-0',
|
||||
'desc': 'Underline selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<u>[bar]</u>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] strikethrough',
|
||||
'command': 'strikethrough',
|
||||
'tests': [
|
||||
{ 'id': 'S_TEXT-1_SI',
|
||||
'rte1-id': 'a-strikethrough-0',
|
||||
'desc': 'Strike-through selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<s>[bar]</s>baz',
|
||||
'foo<strike>[bar]</strike>baz',
|
||||
'foo<del>[bar]</del>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] subscript',
|
||||
'command': 'subscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUB_TEXT-1_SI',
|
||||
'rte1-id': 'a-subscript-0',
|
||||
'desc': 'Change selection to subscript',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<sub>[bar]</sub>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] superscript',
|
||||
'command': 'superscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUP_TEXT-1_SI',
|
||||
'rte1-id': 'a-superscript-0',
|
||||
'desc': 'Change selection to superscript',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<sup>[bar]</sup>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] createlink',
|
||||
'command': 'createlink',
|
||||
'tests': [
|
||||
{ 'id': 'CL:url_TEXT-1_SI',
|
||||
'rte1-id': 'a-createlink-0',
|
||||
'desc': 'create a link around the selection',
|
||||
'value': '#foo',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<a href="#foo">[bar]</a>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] formatBlock',
|
||||
'command': 'formatblock',
|
||||
'tests': [
|
||||
{ 'id': 'FB:H1_TEXT-1_SI',
|
||||
'rte1-id': 'a-formatblock-0',
|
||||
'desc': 'format the selection into a block: use <h1>',
|
||||
'value': 'h1',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<h1>foo[bar]baz</h1>' },
|
||||
|
||||
{ 'id': 'FB:P_TEXT-1_SI',
|
||||
'desc': 'format the selection into a block: use <p>',
|
||||
'value': 'p',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<p>foo[bar]baz</p>' },
|
||||
|
||||
{ 'id': 'FB:PRE_TEXT-1_SI',
|
||||
'desc': 'format the selection into a block: use <pre>',
|
||||
'value': 'pre',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<pre>foo[bar]baz</pre>' },
|
||||
|
||||
{ 'id': 'FB:ADDRESS_TEXT-1_SI',
|
||||
'desc': 'format the selection into a block: use <address>',
|
||||
'value': 'address',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<address>foo[bar]baz</address>' },
|
||||
|
||||
{ 'id': 'FB:BQ_TEXT-1_SI',
|
||||
'desc': 'format the selection into a block: use <blockquote>',
|
||||
'value': 'blockquote',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<blockquote>foo[bar]baz</blockquote>' },
|
||||
|
||||
{ 'id': 'FB:BQ_BR.BR-1_SM',
|
||||
'desc': 'format a multi-line selection into a block: use <blockquote>',
|
||||
'command': 'formatblock',
|
||||
'value': 'blockquote',
|
||||
'pad': 'fo[o<br>bar<br>b]az',
|
||||
'expected': '<blockquote>fo[o<br>bar<br>b]az</blockquote>' }
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{ 'desc': '[MIDAS] backcolor',
|
||||
'command': 'backcolor',
|
||||
'tests': [
|
||||
{ 'id': 'BC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-backcolor-0',
|
||||
'desc': 'Change background color (note: no non-CSS variant available)',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
|
||||
'foo<font style="background-color: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] forecolor',
|
||||
'command': 'forecolor',
|
||||
'tests': [
|
||||
{ 'id': 'FC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-forecolor-0',
|
||||
'desc': 'Change the text color',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<font color="blue">[bar]</font>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] hilitecolor',
|
||||
'command': 'hilitecolor',
|
||||
'tests': [
|
||||
{ 'id': 'HC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-hilitecolor-0',
|
||||
'desc': 'Change the hilite color',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
|
||||
'foo<font style="background-color: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontname',
|
||||
'command': 'fontname',
|
||||
'tests': [
|
||||
{ 'id': 'FN:a_TEXT-1_SI',
|
||||
'rte1-id': 'a-fontname-0',
|
||||
'desc': 'Change the font name',
|
||||
'value': 'arial',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<font face="arial">[bar]</font>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontsize',
|
||||
'command': 'fontsize',
|
||||
'tests': [
|
||||
{ 'id': 'FS:2_TEXT-1_SI',
|
||||
'rte1-id': 'a-fontsize-0',
|
||||
'desc': 'Change the font size to "2"',
|
||||
'value': '2',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<font size="2">[bar]</font>baz' },
|
||||
|
||||
{ 'id': 'FS:18px_TEXT-1_SI',
|
||||
'desc': 'Change the font size to "18px"',
|
||||
'value': '18px',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<font size="18px">[bar]</font>baz' },
|
||||
|
||||
{ 'id': 'FS:large_TEXT-1_SI',
|
||||
'desc': 'Change the font size to "large"',
|
||||
'value': 'large',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<font size="large">[bar]</font>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] increasefontsize',
|
||||
'command': 'increasefontsize',
|
||||
'tests': [
|
||||
{ 'id': 'INCFS:2_TEXT-1_SI',
|
||||
'desc': 'Decrease the font size (to small)',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<font size="4">[bar]</font>baz',
|
||||
'foo<font size="+1">[bar]</font>baz',
|
||||
'foo<big>[bar]</big>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] decreasefontsize',
|
||||
'command': 'decreasefontsize',
|
||||
'tests': [
|
||||
{ 'id': 'DECFS:2_TEXT-1_SI',
|
||||
'rte1-id': 'a-decreasefontsize-0',
|
||||
'desc': 'Decrease the font size (to small)',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<font size="2">[bar]</font>baz',
|
||||
'foo<font size="-1">[bar]</font>baz',
|
||||
'foo<small>[bar]</small>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] indent (note: accept the de-facto standard indent of 40px)',
|
||||
'command': 'indent',
|
||||
'tests': [
|
||||
{ 'id': 'IND_TEXT-1_SI',
|
||||
'rte1-id': 'a-indent-0',
|
||||
'desc': 'Indent the text (accept the de-facto standard of 40px indent)',
|
||||
'pad': 'foo[bar]baz',
|
||||
'checkAttrs': False,
|
||||
'expected': [ '<blockquote>foo[bar]baz</blockquote>',
|
||||
'<div style="margin-left: 40px">foo[bar]baz</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div contenteditable="true" style="margin-left: 40px">foo[bar]baz</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] outdent (-> unapply tests)',
|
||||
'command': 'outdent',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifycenter',
|
||||
'command': 'justifycenter',
|
||||
'tests': [
|
||||
{ 'id': 'JC_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifycenter-0',
|
||||
'desc': 'justify the text centrally',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<center>foo^bar</center>',
|
||||
'<p align="center">foo^bar</p>',
|
||||
'<p align="middle">foo^bar</p>',
|
||||
'<div align="center">foo^bar</div>',
|
||||
'<div align="middle">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': [ '<div align="center" contenteditable="true">foo^bar</div>',
|
||||
'<div align="middle" contenteditable="true">foo^bar</div>' ] } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyfull',
|
||||
'command': 'justifyfull',
|
||||
'tests': [
|
||||
{ 'id': 'JF_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyfull-0',
|
||||
'desc': 'justify the text fully',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p align="justify">foo^bar</p>',
|
||||
'<div align="justify">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div align="justify" contenteditable="true">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyleft',
|
||||
'command': 'justifyleft',
|
||||
'tests': [
|
||||
{ 'id': 'JL_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyleft-0',
|
||||
'desc': 'justify the text left',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p align="left">foo^bar</p>',
|
||||
'<div align="left">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div align="left" contenteditable="true">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyright',
|
||||
'command': 'justifyright',
|
||||
'tests': [
|
||||
{ 'id': 'JR_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyright-0',
|
||||
'desc': 'justify the text right',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p align="right">foo^bar</p>',
|
||||
'<div align="right">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div align="right" contenteditable="true">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] heading',
|
||||
'command': 'heading',
|
||||
'tests': [
|
||||
{ 'id': 'H:H1_TEXT-1_SC',
|
||||
'desc': 'create a heading from the paragraph that contains the selection',
|
||||
'value': 'h1',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<h1>foo[bar]baz</h1>' }
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{ 'desc': '[Other] createbookmark',
|
||||
'command': 'createbookmark',
|
||||
'tests': [
|
||||
{ 'id': 'CB:name_TEXT-1_SI',
|
||||
'rte1-id': 'a-createbookmark-0',
|
||||
'desc': 'create a bookmark (named link) around selection',
|
||||
'value': 'created',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<a name="created">[bar]</a>baz' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
|
||||
APPLY_TESTS_CSS = {
|
||||
'id': 'AC',
|
||||
'caption': 'Apply Formatting Tests, using styleWithCSS',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': True,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] bold',
|
||||
'command': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_TEXT-1_SI',
|
||||
'rte1-id': 'a-bold-1',
|
||||
'desc': 'Bold selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="font-weight: bold">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_TEXT-1_SI',
|
||||
'rte1-id': 'a-italic-1',
|
||||
'desc': 'Italicize selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="font-style: italic">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] underline',
|
||||
'command': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_TEXT-1_SI',
|
||||
'rte1-id': 'a-underline-1',
|
||||
'desc': 'Underline selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="text-decoration: underline">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] strikethrough',
|
||||
'command': 'strikethrough',
|
||||
'tests': [
|
||||
{ 'id': 'S_TEXT-1_SI',
|
||||
'rte1-id': 'a-strikethrough-1',
|
||||
'desc': 'Strike-through selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="text-decoration: line-through">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] subscript',
|
||||
'command': 'subscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUB_TEXT-1_SI',
|
||||
'rte1-id': 'a-subscript-1',
|
||||
'desc': 'Change selection to subscript',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="vertical-align: sub">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] superscript',
|
||||
'command': 'superscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUP_TEXT-1_SI',
|
||||
'rte1-id': 'a-superscript-1',
|
||||
'desc': 'Change selection to superscript',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span style="vertical-align: super">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{ 'desc': '[MIDAS] backcolor',
|
||||
'command': 'backcolor',
|
||||
'tests': [
|
||||
{ 'id': 'BC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-backcolor-1',
|
||||
'desc': 'Change background color',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
|
||||
'foo<font style="background-color: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] forecolor',
|
||||
'command': 'forecolor',
|
||||
'tests': [
|
||||
{ 'id': 'FC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-forecolor-1',
|
||||
'desc': 'Change the text color',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="color: blue">[bar]</span>baz',
|
||||
'foo<font style="color: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] hilitecolor',
|
||||
'command': 'hilitecolor',
|
||||
'tests': [
|
||||
{ 'id': 'HC:blue_TEXT-1_SI',
|
||||
'rte1-id': 'a-hilitecolor-1',
|
||||
'desc': 'Change the hilite color',
|
||||
'value': 'blue',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="background-color: blue">[bar]</span>baz',
|
||||
'foo<font style="background-color: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontname',
|
||||
'command': 'fontname',
|
||||
'tests': [
|
||||
{ 'id': 'FN:a_TEXT-1_SI',
|
||||
'rte1-id': 'a-fontname-1',
|
||||
'desc': 'Change the font name',
|
||||
'value': 'arial',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="font-family: arial">[bar]</span>baz',
|
||||
'foo<font style="font-family: blue">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontsize',
|
||||
'command': 'fontsize',
|
||||
'tests': [
|
||||
{ 'id': 'FS:2_TEXT-1_SI',
|
||||
'rte1-id': 'a-fontsize-1',
|
||||
'desc': 'Change the font size to "2"',
|
||||
'value': '2',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="font-size: small">[bar]</span>baz',
|
||||
'foo<font style="font-size: small">[bar]</font>baz' ] },
|
||||
|
||||
{ 'id': 'FS:18px_TEXT-1_SI',
|
||||
'desc': 'Change the font size to "18px"',
|
||||
'value': '18px',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="font-size: 18px">[bar]</span>baz',
|
||||
'foo<font style="font-size: 18px">[bar]</font>baz' ] },
|
||||
|
||||
{ 'id': 'FS:large_TEXT-1_SI',
|
||||
'desc': 'Change the font size to "large"',
|
||||
'value': 'large',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<span style="font-size: large">[bar]</span>baz',
|
||||
'foo<font style="font-size: large">[bar]</font>baz' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] indent',
|
||||
'command': 'indent',
|
||||
'tests': [
|
||||
{ 'id': 'IND_TEXT-1_SI',
|
||||
'rte1-id': 'a-indent-1',
|
||||
'desc': 'Indent the text (assume "standard" 40px)',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ '<div style="margin-left: 40px">foo[bar]baz</div>',
|
||||
'<div style="margin: 0 0 0 40px">foo[bar]baz</div>',
|
||||
'<blockquote style="margin-left: 40px">foo[bar]baz</blockquote>',
|
||||
'<blockquote style="margin: 0 0 0 40px">foo[bar]baz</blockquote>' ],
|
||||
'div': {
|
||||
'accOuter': [ '<div contenteditable="true" style="margin-left: 40px">foo[bar]baz</div>',
|
||||
'<div contenteditable="true" style="margin: 0 0 0 40px">foo[bar]baz</div>' ] } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] outdent (-> unapply tests)',
|
||||
'command': 'outdent',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifycenter',
|
||||
'command': 'justifycenter',
|
||||
'tests': [
|
||||
{ 'id': 'JC_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifycenter-1',
|
||||
'desc': 'justify the text centrally',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p style="text-align: center">foo^bar</p>',
|
||||
'<div style="text-align: center">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div contenteditable="true" style="text-align: center">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyfull',
|
||||
'command': 'justifyfull',
|
||||
'tests': [
|
||||
{ 'id': 'JF_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyfull-1',
|
||||
'desc': 'justify the text fully',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p style="text-align: justify">foo^bar</p>',
|
||||
'<div style="text-align: justify">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div contenteditable="true" style="text-align: justify">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyleft',
|
||||
'command': 'justifyleft',
|
||||
'tests': [
|
||||
{ 'id': 'JL_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyleft-1',
|
||||
'desc': 'justify the text left',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p style="text-align: left">foo^bar</p>',
|
||||
'<div style="text-align: left">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div contenteditable="true" style="text-align: left">foo^bar</div>' } }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] justifyright',
|
||||
'command': 'justifyright',
|
||||
'tests': [
|
||||
{ 'id': 'JR_TEXT-1_SC',
|
||||
'rte1-id': 'a-justifyright-1',
|
||||
'desc': 'justify the text right',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ '<p style="text-align: right">foo^bar</p>',
|
||||
'<div style="text-align: right">foo^bar</div>' ],
|
||||
'div': {
|
||||
'accOuter': '<div contenteditable="true" style="text-align: right">foo^bar</div>' } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
CHANGE_TESTS = {
|
||||
'id': 'C',
|
||||
'caption': 'Change Existing Format to Different Format Tests',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_I-1_SL',
|
||||
'desc': 'Italicize partially italicized text',
|
||||
'pad': 'foo[bar<i>baz]</i>qoz',
|
||||
'expected': 'foo<i>[barbaz]</i>qoz' },
|
||||
|
||||
{ 'id': 'I_B-I-1_SO',
|
||||
'desc': 'Italicize partially italicized text in bold context',
|
||||
'pad': '<b>foo[bar<i>baz</i>}</b>',
|
||||
'expected': '<b>foo<i>[barbaz]</i></b>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] underline',
|
||||
'command': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_U-1_SO',
|
||||
'desc': 'Underline partially underlined text',
|
||||
'pad': 'foo[bar<u>baz</u>qoz]quz',
|
||||
'expected': 'foo<u>[barbazqoz]</u>quz' },
|
||||
|
||||
{ 'id': 'U_U-1_SL',
|
||||
'desc': 'Underline partially underlined text',
|
||||
'pad': 'foo[bar<u>baz]qoz</u>quz',
|
||||
'expected': 'foo<u>[barbaz]qoz</u>quz' },
|
||||
|
||||
{ 'id': 'U_S-U-1_SO',
|
||||
'desc': 'Underline partially underlined text in striked context',
|
||||
'pad': '<s>foo[bar<u>baz</u>}</s>',
|
||||
'expected': '<s>foo<u>[barbaz]</u></s>' }
|
||||
]
|
||||
},
|
||||
|
||||
|
||||
{ 'desc': '[MIDAS] backcolor',
|
||||
'command': 'backcolor',
|
||||
'tests': [
|
||||
{ 'id': 'BC:842_FONTs:bc:fca-1_SW',
|
||||
'rte1-id': 'c-backcolor-0',
|
||||
'desc': 'Change background color to new color',
|
||||
'value': '#884422',
|
||||
'pad': '<font style="background-color: #ffccaa">[foobarbaz]</font>',
|
||||
'expected': [ '<font style="background-color: #884422">[foobarbaz]</font>',
|
||||
'<span style="background-color: #884422">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'BC:00f_SPANs:bc:f00-1_SW',
|
||||
'rte1-id': 'c-backcolor-2',
|
||||
'desc': 'Change background color to new color',
|
||||
'value': '#0000ff',
|
||||
'pad': '<span style="background-color: #ff0000">[foobarbaz]</span>',
|
||||
'expected': [ '<font style="background-color: #0000ff">[foobarbaz]</font>',
|
||||
'<span style="background-color: #0000ff">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'BC:ace_FONT.ass.s:bc:rgb-1_SW',
|
||||
'rte1-id': 'c-backcolor-1',
|
||||
'desc': 'Change background color in styled span to new color',
|
||||
'value': '#aaccee',
|
||||
'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">[foobarbaz]</span>',
|
||||
'expected': [ '<font style="background-color: #aaccee">[foobarbaz]</font>',
|
||||
'<span style="background-color: #aaccee">[foobarbaz]</span>' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] forecolor',
|
||||
'command': 'forecolor',
|
||||
'tests': [
|
||||
{ 'id': 'FC:g_FONTc:b-1_SW',
|
||||
'rte1-id': 'c-forecolor-0',
|
||||
'desc': 'Change the text color (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<font color="blue">[foobarbaz]</font>',
|
||||
'expected': '<font color="green">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FC:g_SPANs:c:g-1_SW',
|
||||
'rte1-id': 'c-forecolor-1',
|
||||
'desc': 'Change the text color from a styled span (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<span style="color: blue">[foobarbaz]</span>',
|
||||
'expected': '<font color="green">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FC:g_FONTc:b.s:c:r-1_SW',
|
||||
'rte1-id': 'c-forecolor-2',
|
||||
'desc': 'Change the text color from conflicting color and style (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<font color="blue" style="color: red">[foobarbaz]</font>',
|
||||
'expected': '<font color="green">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FC:g_FONTc:b.sz:6-1_SI',
|
||||
'desc': 'Change the font color in content with a different font size and font color',
|
||||
'value': 'green',
|
||||
'pad': '<font color="blue" size="6">foo[bar]baz</font>',
|
||||
'expected': [ '<font color="blue" size="6">foo<font color="green">[bar]</font>baz</font>',
|
||||
'<font size="6"><font color="blue">foo<font color="green">[bar]</font><font color="blue">baz</font></font>' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] hilitecolor',
|
||||
'command': 'hilitecolor',
|
||||
'tests': [
|
||||
{ 'id': 'HC:g_FONTs:c:b-1_SW',
|
||||
'rte1-id': 'c-hilitecolor-0',
|
||||
'desc': 'Change the hilite color (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<font style="background-color: blue">[foobarbaz]</font>',
|
||||
'expected': [ '<font style="background-color: green">[foobarbaz]</font>',
|
||||
'<span style="background-color: green">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'HC:g_SPANs:c:g-1_SW',
|
||||
'rte1-id': 'c-hilitecolor-2',
|
||||
'desc': 'Change the hilite color from a styled span (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<span style="background-color: blue">[foobarbaz]</span>',
|
||||
'expected': '<span style="background-color: green">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'HC:g_SPAN.ass.s:c:rgb-1_SW',
|
||||
'rte1-id': 'c-hilitecolor-1',
|
||||
'desc': 'Change the hilite color from a styled span (without CSS)',
|
||||
'value': 'green',
|
||||
'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0);">[foobarbaz]</span>',
|
||||
'expected': '<span style="background-color: green">[foobarbaz]</span>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontname',
|
||||
'command': 'fontname',
|
||||
'tests': [
|
||||
{ 'id': 'FN:c_FONTf:a-1_SW',
|
||||
'rte1-id': 'c-fontname-0',
|
||||
'desc': 'Change existing font name to new font name (without CSS)',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="arial">[foobarbaz]</font>',
|
||||
'expected': '<font face="courier">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FN:c_SPANs:ff:a-1_SW',
|
||||
'rte1-id': 'c-fontname-1',
|
||||
'desc': 'Change existing font name from style to new font name (without CSS)',
|
||||
'value': 'courier',
|
||||
'pad': '<span style="font-family: arial">[foobarbaz]</span>',
|
||||
'expected': '<font face="courier">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a.s:ff:v-1_SW',
|
||||
'rte1-id': 'c-fontname-2',
|
||||
'desc': 'Change existing font name with conflicting face and style to new font name (without CSS)',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="arial" style="font-family: verdana">[foobarbaz]</font>',
|
||||
'expected': '<font face="courier">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a-1_SI',
|
||||
'desc': 'Change existing font name to new font name, text partially selected',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="arial">foo[bar]baz</font>',
|
||||
'expected': '<font face="arial">foo</font><font face="courier">[bar]</font><font face="arial">baz</font>',
|
||||
'accept': '<font face="arial">foo<font face="courier">[bar]</font>baz</font>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a-2_SL',
|
||||
'desc': 'Change existing font name to new font name, using CSS styling',
|
||||
'value': 'courier',
|
||||
'pad': 'foo[bar<font face="arial">baz]qoz</font>',
|
||||
'expected': 'foo<font face="courier">[barbaz]</font><font face="arial">qoz</font>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:v-FONTf:a-1_SW',
|
||||
'rte1-id': 'c-fontname-3',
|
||||
'desc': 'Change existing font name in nested <font> tags to new font name (without CSS)',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="verdana"><font face="arial">[foobarbaz]</font></font>',
|
||||
'expected': '<font face="courier">[foobarbaz]</font>',
|
||||
'accept': '<font face="verdana"><font face="courier">[foobarbaz]</font></font>' },
|
||||
|
||||
{ 'id': 'FN:c_SPANs:ff:v-FONTf:a-1_SW',
|
||||
'rte1-id': 'c-fontname-4',
|
||||
'desc': 'Change existing font name in nested mixed tags to new font name (without CSS)',
|
||||
'value': 'courier',
|
||||
'pad': '<span style="font-family: verdana"><font face="arial">[foobarbaz]</font></span>',
|
||||
'expected': '<font face="courier">[foobarbaz]</font>',
|
||||
'accept': '<span style="font-family: verdana"><font face="courier">[foobarbaz]</font></span>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontsize',
|
||||
'command': 'fontsize',
|
||||
'tests': [
|
||||
{ 'id': 'FS:1_FONTsz:4-1_SW',
|
||||
'rte1-id': 'c-fontsize-0',
|
||||
'desc': 'Change existing font size to new size (without CSS)',
|
||||
'value': '1',
|
||||
'pad': '<font size="4">[foobarbaz]</font>',
|
||||
'expected': '<font size="1">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FS:1_SPAN.ass.s:fs:large-1_SW',
|
||||
'rte1-id': 'c-fontsize-1',
|
||||
'desc': 'Change existing font size from styled span to new size (without CSS)',
|
||||
'value': '1',
|
||||
'pad': '<span class="Apple-style-span" style="font-size: large">[foobarbaz]</span>',
|
||||
'expected': '<font size="1">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FS:5_FONTsz:1.s:fs:xs-1_SW',
|
||||
'rte1-id': 'c-fontsize-2',
|
||||
'desc': 'Change existing font size from tag with conflicting size and style to new size (without CSS)',
|
||||
'value': '5',
|
||||
'pad': '<font size="1" style="font-size:x-small">[foobarbaz]</font>',
|
||||
'expected': '<font size="5">[foobarbaz]</font>' },
|
||||
|
||||
{ 'id': 'FS:2_FONTc:b.sz:6-1_SI',
|
||||
'desc': 'Change the font size in content with a different font size and font color',
|
||||
'value': '2',
|
||||
'pad': '<font color="blue" size="6">foo[bar]baz</font>',
|
||||
'expected': [ '<font color="blue" size="6">foo<font size="2">[bar]</font>baz</font>',
|
||||
'<font color="blue"><font size="6">foo</font><font size="2">[bar]</font><font size="6">baz</font></font>' ] },
|
||||
|
||||
{ 'id': 'FS:larger_FONTsz:4',
|
||||
'desc': 'Change selection to use next larger font',
|
||||
'value': 'larger',
|
||||
'pad': '<font size="4">foo[bar]baz</font>',
|
||||
'expected': '<font size="4">foo<font size="larger">[bar]</font>baz</font>',
|
||||
'accept': '<font size="4">foo</font><font size="5">[bar]</font><font size="4">baz</font>' },
|
||||
|
||||
{ 'id': 'FS:smaller_FONTsz:4',
|
||||
'desc': 'Change selection to use next smaller font',
|
||||
'value': 'smaller',
|
||||
'pad': '<font size="4">foo[bar]baz</font>',
|
||||
'expected': '<font size="4">foo<font size="smaller">[bar]</font>baz</font>',
|
||||
'accept': '<font size="4">foo</font><font size="3">[bar]</font><font size="4">baz</font>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] formatblock',
|
||||
'command': 'formatblock',
|
||||
'tests': [
|
||||
{ 'id': 'FB:h1_ADDRESS-1_SW',
|
||||
'desc': 'change block from <address> to <h1>',
|
||||
'value': 'h1',
|
||||
'pad': '<address>foo [bar] baz</address>',
|
||||
'expected': '<h1>foo [bar] baz</h1>' },
|
||||
|
||||
{ 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SO',
|
||||
'desc': 'change block from <address> with partially formatted content to <h1>',
|
||||
'value': 'h1',
|
||||
'pad': '<address>foo [<font size="4">bar</font>] baz</address>',
|
||||
'expected': '<h1>foo [bar] baz</h1>' },
|
||||
|
||||
{ 'id': 'FB:h1_ADDRESS-FONTsz:4-1_SW',
|
||||
'desc': 'change block from <address> with partially formatted content to <h1>',
|
||||
'value': 'h1',
|
||||
'pad': '<address>foo <font size="4">[bar]</font> baz</address>',
|
||||
'expected': '<h1>foo [bar] baz</h1>' },
|
||||
|
||||
{ 'id': 'FB:h1_ADDRESS-FONT.ass.sz:4-1_SW',
|
||||
'desc': 'change block from <address> with partially formatted content to <h1>',
|
||||
'value': 'h1',
|
||||
'pad': '<address>foo <font class="Apple-style-span" size="4">[bar]</font> baz</address>',
|
||||
'expected': '<h1>foo [bar] baz</h1>' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
|
||||
CHANGE_TESTS_CSS = {
|
||||
'id': 'CC',
|
||||
'caption': 'Change Existing Format to Different Format Tests, using styleWithCSS',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': True,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_I-1_SL',
|
||||
'desc': 'Italicize partially italicized text',
|
||||
'pad': 'foo[bar<i>baz]</i>qoz',
|
||||
'expected': 'foo<span style="font-style: italic">[barbaz]</span>qoz' },
|
||||
|
||||
{ 'id': 'I_B-1_SL',
|
||||
'desc': 'Italicize partially bolded text',
|
||||
'pad': 'foo[bar<b>baz]</b>qoz',
|
||||
'expected': 'foo<span style="font-style: italic">[bar<b>baz]</b></span>qoz',
|
||||
'accept': 'foo<span style="font-style: italic">[bar<b>baz</b>}</span>qoz' },
|
||||
|
||||
{ 'id': 'I_B-1_SW',
|
||||
'desc': 'Italicize bold text, ideally combining both',
|
||||
'pad': 'foobar<b>[baz]</b>qoz',
|
||||
'expected': 'foobar<span style="font-style: italic; font-weight: bold">[baz]</span>qoz',
|
||||
'accept': 'foobar<b><span style="font-style: italic">[baz]</span></b>qoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] backcolor',
|
||||
'command': 'backcolor',
|
||||
'tests': [
|
||||
{ 'id': 'BC:gray_SPANs:bc:b-1_SW',
|
||||
'desc': 'Change background color from blue to gray',
|
||||
'value': 'gray',
|
||||
'pad': '<span style="background-color: blue">[foobarbaz]</span>',
|
||||
'expected': '<span style="background-color: gray">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'BC:gray_SPANs:bc:b-1_SO',
|
||||
'desc': 'Change background color from blue to gray',
|
||||
'value': 'gray',
|
||||
'pad': '{<span style="background-color: blue">foobarbaz</span>}',
|
||||
'expected': [ '{<span style="background-color: gray">foobarbaz</span>}',
|
||||
'<span style="background-color: gray">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'BC:gray_SPANs:bc:b-1_SI',
|
||||
'desc': 'Change background color from blue to gray',
|
||||
'value': 'gray',
|
||||
'pad': '<span style="background-color: blue">foo[bar]baz</span>',
|
||||
'expected': '<span style="background-color: blue">foo</span><span style="background-color: gray">[bar]</span><span style="background-color: blue">baz</span>',
|
||||
'accept': '<span style="background-color: blue">foo<span style="background-color: gray">[bar]</span>baz</span>' },
|
||||
|
||||
{ 'id': 'BC:gray_P-SPANs:bc:b-1_SW',
|
||||
'desc': 'Change background color within a paragraph from blue to gray',
|
||||
'value': 'gray',
|
||||
'pad': '<p><span style="background-color: blue">[foobarbaz]</span></p>',
|
||||
'expected': [ '<p><span style="background-color: gray">[foobarbaz]</span></p>',
|
||||
'<p style="background-color: gray">[foobarbaz]</p>' ] },
|
||||
|
||||
{ 'id': 'BC:gray_P-SPANs:bc:b-2_SW',
|
||||
'desc': 'Change background color within a paragraph from blue to gray',
|
||||
'value': 'gray',
|
||||
'pad': '<p>foo<span style="background-color: blue">[bar]</span>baz</p>',
|
||||
'expected': '<p>foo<span style="background-color: gray">[bar]</span>baz</p>' },
|
||||
|
||||
{ 'id': 'BC:gray_P-SPANs:bc:b-3_SO',
|
||||
'desc': 'Change background color within a paragraph from blue to gray (selection encloses more than previous span)',
|
||||
'value': 'gray',
|
||||
'pad': '<p>[foo<span style="background-color: blue">barbaz</span>qoz]quz</p>',
|
||||
'expected': '<p><span style="background-color: gray">[foobarbazqoz]</span>quz</p>' },
|
||||
|
||||
{ 'id': 'BC:gray_P-SPANs:bc:b-3_SL',
|
||||
'desc': 'Change background color within a paragraph from blue to gray (previous span partially selected)',
|
||||
'value': 'gray',
|
||||
'pad': '<p>[foo<span style="background-color: blue">bar]baz</span>qozquz</p>',
|
||||
'expected': '<p><span style="background-color: gray">[foobar]</span><span style="background-color: blue">baz</span>qozquz</p>' },
|
||||
|
||||
{ 'id': 'BC:gray_SPANs:bc:b-2_SL',
|
||||
'desc': 'Change background color from blue to gray on partially covered span, selection extends left',
|
||||
'value': 'gray',
|
||||
'pad': 'foo [bar <span style="background-color: blue">baz] qoz</span> quz sic',
|
||||
'expected': 'foo <span style="background-color: gray">[bar baz]</span><span style="background-color: blue"> qoz</span> quz sic' },
|
||||
|
||||
{ 'id': 'BC:gray_SPANs:bc:b-2_SR',
|
||||
'desc': 'Change background color from blue to gray on partially covered span, selection extends right',
|
||||
'value': 'gray',
|
||||
'pad': 'foo bar <span style="background-color: blue">baz [qoz</span> quz] sic',
|
||||
'expected': 'foo bar <span style="background-color: blue">baz </span><span style="background-color: gray">[qoz quz]</span> sic' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontname',
|
||||
'command': 'fontname',
|
||||
'tests': [
|
||||
{ 'id': 'FN:c_SPANs:ff:a-1_SW',
|
||||
'desc': 'Change existing font name to new font name, using CSS styling',
|
||||
'value': 'courier',
|
||||
'pad': '<span style="font-family: arial">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-family: courier">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a-1_SW',
|
||||
'desc': 'Change existing font name to new font name, using CSS styling',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="arial">[foobarbaz]</font>',
|
||||
'expected': [ '<font style="font-family: courier">[foobarbaz]</font>',
|
||||
'<span style="font-family: courier">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a-1_SI',
|
||||
'desc': 'Change existing font name to new font name, using CSS styling',
|
||||
'value': 'courier',
|
||||
'pad': '<font face="arial">foo[bar]baz</font>',
|
||||
'expected': '<font face="arial">foo</font><span style="font-family: courier">[bar]</span><font face="arial">baz</font>' },
|
||||
|
||||
{ 'id': 'FN:a_FONTf:a-1_SI',
|
||||
'desc': 'Change existing font name to same font name, using CSS styling (should be noop)',
|
||||
'value': 'arial',
|
||||
'pad': '<font face="arial">foo[bar]baz</font>',
|
||||
'expected': '<font face="arial">foo[bar]baz</font>' },
|
||||
|
||||
{ 'id': 'FN:a_FONTf:a-1_SW',
|
||||
'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)',
|
||||
'value': 'arial',
|
||||
'pad': '<font face="arial">[foobarbaz]</font>',
|
||||
'expected': [ '<font face="arial">[foobarbaz]</font>',
|
||||
'<span style="font-family: arial">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'FN:a_FONTf:a-1_SO',
|
||||
'desc': 'Change existing font name to same font name, using CSS styling (should be noop or perhaps change tag)',
|
||||
'value': 'arial',
|
||||
'pad': '{<font face="arial">foobarbaz</font>}',
|
||||
'expected': [ '{<font face="arial">foobarbaz</font>}',
|
||||
'<font face="arial">[foobarbaz]</font>',
|
||||
'{<span style="font-family: arial">foobarbaz</span>}',
|
||||
'<span style="font-family: arial">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'FN:a_SPANs:ff:a-1_SI',
|
||||
'desc': 'Change existing font name to same font name, using CSS styling (should be noop)',
|
||||
'value': 'arial',
|
||||
'pad': '<span style="font-family: arial">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-family: arial">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FN:c_FONTf:a-2_SL',
|
||||
'desc': 'Change existing font name to new font name, using CSS styling',
|
||||
'value': 'courier',
|
||||
'pad': 'foo[bar<font face="arial">baz]qoz</font>',
|
||||
'expected': 'foo<span style="font-family: courier">[barbaz]</span><font face="arial">qoz</font>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] fontsize',
|
||||
'command': 'fontsize',
|
||||
'tests': [
|
||||
{ 'id': 'FS:1_SPANs:fs:l-1_SW',
|
||||
'desc': 'Change existing font size to new size, using CSS styling',
|
||||
'value': '1',
|
||||
'pad': '<span style="font-size: large">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-size: x-small">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FS:large_SPANs:fs:l-1_SW',
|
||||
'desc': 'Change existing font size to same size (should be noop)',
|
||||
'value': 'large',
|
||||
'pad': '<span style="font-size: large">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-size: large">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FS:18px_SPANs:fs:l-1_SW',
|
||||
'desc': 'Change existing font size to equivalent px size (should be noop, or change unit)',
|
||||
'value': '18px',
|
||||
'pad': '<span style="font-size: large">[foobarbaz]</span>',
|
||||
'expected': [ '<span style="font-size: 18px">[foobarbaz]</span>',
|
||||
'<span style="font-size: large">[foobarbaz]</span>' ] },
|
||||
|
||||
{ 'id': 'FS:4_SPANs:fs:l-1_SW',
|
||||
'desc': 'Change existing font size to equivalent numeric size (should be noop)',
|
||||
'value': '4',
|
||||
'pad': '<span style="font-size: large">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-size: large">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FS:4_SPANs:fs:18px-1_SW',
|
||||
'desc': 'Change existing font size to equivalent numeric size (should be noop)',
|
||||
'value': '4',
|
||||
'pad': '<span style="font-size: 18px">[foobarbaz]</span>',
|
||||
'expected': '<span style="font-size: 18px">[foobarbaz]</span>' },
|
||||
|
||||
{ 'id': 'FS:larger_SPANs:fs:l-1_SI',
|
||||
'desc': 'Change selection to use next larger font',
|
||||
'value': 'larger',
|
||||
'pad': '<span style="font-size: large">foo[bar]baz</span>',
|
||||
'expected': [ '<span style="font-size: large">foo<span style="font-size: x-large">[bar]</span>baz</span>',
|
||||
'<span style="font-size: large">foo</span><span style="font-size: x-large">[bar]</span><span style="font-size: large">baz</span>' ],
|
||||
'accept': '<span style="font-size: large">foo<font size="larger">[bar]</font>baz</span>' },
|
||||
|
||||
{ 'id': 'FS:smaller_SPANs:fs:l-1_SI',
|
||||
'desc': 'Change selection to use next smaller font',
|
||||
'value': 'smaller',
|
||||
'pad': '<span style="font-size: large">foo[bar]baz</span>',
|
||||
'expected': [ '<span style="font-size: large">foo<span style="font-size: medium">[bar]</span>baz</span>',
|
||||
'<span style="font-size: large">foo</span><span style="font-size: medium">[bar]</span><span style="font-size: large">baz</span>' ],
|
||||
'accept': '<span style="font-size: large">foo<font size="smaller">[bar]</font>baz</span>' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,330 @@
|
|||
|
||||
DELETE_TESTS = {
|
||||
'id': 'D',
|
||||
'caption': 'Delete Tests',
|
||||
'command': 'delete',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete single characters',
|
||||
'tests': [
|
||||
{ 'id': 'CHAR-1_SC',
|
||||
'desc': 'Delete 1 character',
|
||||
'pad': 'foo^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-2_SC',
|
||||
'desc': 'Delete 1 pre-composed character o with diaeresis',
|
||||
'pad': 'foö^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-3_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis above',
|
||||
'pad': 'foö^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-4_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis below',
|
||||
'pad': 'foo̤^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-5_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis above and below',
|
||||
'pad': 'foö̤^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-5_SI-1',
|
||||
'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis above',
|
||||
'pad': 'foo[̈]̤barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-5_SI-2',
|
||||
'desc': 'Delete 1 character with combining diaeresis above and below, selection on diaeresis below',
|
||||
'pad': 'foö[̤]barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-5_SR',
|
||||
'desc': 'Delete 1 character with combining diaeresis above and below, selection oblique on diaeresis and following text',
|
||||
'pad': 'foö[̤bar]baz',
|
||||
'expected': 'fo^baz' },
|
||||
|
||||
{ 'id': 'CHAR-6_SC',
|
||||
'desc': 'Delete 1 character with enclosing square',
|
||||
'pad': 'foo⃞^barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-7_SC',
|
||||
'desc': 'Delete 1 character with combining long solidus overlay',
|
||||
'pad': 'foo̸^barbaz',
|
||||
'expected': 'fo^barbaz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete text selection',
|
||||
'tests': [
|
||||
{ 'id': 'TEXT-1_SI',
|
||||
'desc': 'Delete text selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SS',
|
||||
'desc': 'Delete at start of span',
|
||||
'pad': 'foo<b>^bar</b>baz',
|
||||
'expected': 'fo^<b>bar</b>baz' },
|
||||
|
||||
{ 'id': 'B-1_SA',
|
||||
'desc': 'Delete from position after span',
|
||||
'pad': 'foo<b>bar</b>^baz',
|
||||
'expected': 'foo<b>ba^</b>baz' },
|
||||
|
||||
{ 'id': 'B-1_SW',
|
||||
'desc': 'Delete selection that wraps the whole span content',
|
||||
'pad': 'foo<b>[bar]</b>baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SO',
|
||||
'desc': 'Delete selection that wraps the whole span',
|
||||
'pad': 'foo[<b>bar</b>]baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SL',
|
||||
'desc': 'Delete oblique selection that starts before span',
|
||||
'pad': 'foo[bar<b>baz]quoz</b>quuz',
|
||||
'expected': 'foo^<b>quoz</b>quuz' },
|
||||
|
||||
{ 'id': 'B-1_SR',
|
||||
'desc': 'Delete oblique selection that ends after span',
|
||||
'pad': 'foo<b>bar[baz</b>quoz]quuz',
|
||||
'expected': 'foo<b>bar^</b>quuz' },
|
||||
|
||||
{ 'id': 'B.I-1_SM',
|
||||
'desc': 'Delete oblique selection that starts and ends in different spans',
|
||||
'pad': 'foo<b>bar[baz</b><i>qoz]quuz</i>quuuz',
|
||||
'expected': 'foo<b>bar^</b><i>quuz</i>quuuz' },
|
||||
|
||||
{ 'id': 'GEN-1_SS',
|
||||
'desc': 'Delete at start of span with generated content',
|
||||
'pad': 'foo<gen>^bar</gen>baz',
|
||||
'expected': 'fo^<gen>bar</gen>baz' },
|
||||
|
||||
{ 'id': 'GEN-1_SA',
|
||||
'desc': 'Delete from position after span with generated content',
|
||||
'pad': 'foo<gen>bar</gen>^baz',
|
||||
'expected': 'foo<gen>ba^</gen>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete paragraphs',
|
||||
'tests': [
|
||||
{ 'id': 'P2-1_SS2',
|
||||
'desc': 'Delete from collapsed selection at start of paragraph - should merge with previous',
|
||||
'pad': '<p>foobar</p><p>^bazqoz</p>',
|
||||
'expected': '<p>foobar^bazqoz</p>' },
|
||||
|
||||
{ 'id': 'P2-1_SI2',
|
||||
'desc': 'Delete non-collapsed selection at start of paragraph - should not merge with previous',
|
||||
'pad': '<p>foobar</p><p>[baz]qoz</p>',
|
||||
'expected': '<p>foobar</p><p>^qoz</p>' },
|
||||
|
||||
{ 'id': 'P2-1_SM',
|
||||
'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them',
|
||||
'pad': '<p>foo[bar</p><p>baz]qoz</p>',
|
||||
'expected': '<p>foo^qoz</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete lists and list items',
|
||||
'tests': [
|
||||
{ 'id': 'OL-LI2-1_SO1',
|
||||
'desc': 'Delete fully wrapped list item',
|
||||
'pad': 'foo<ol>{<li>bar</li>}<li>baz</li></ol>qoz',
|
||||
'expected': ['foo<ol>|<li>baz</li></ol>qoz',
|
||||
'foo<ol><li>^baz</li></ol>qoz'] },
|
||||
|
||||
{ 'id': 'OL-LI2-1_SM',
|
||||
'desc': 'Delete oblique range between list items within same list',
|
||||
'pad': 'foo<ol><li>ba[r</li><li>b]az</li></ol>qoz',
|
||||
'expected': 'foo<ol><li>ba^az</li></ol>qoz' },
|
||||
|
||||
{ 'id': 'OL-LI-1_SW',
|
||||
'desc': 'Delete contents of last list item (list should remain)',
|
||||
'pad': 'foo<ol><li>[foo]</li></ol>qoz',
|
||||
'expected': ['foo<ol><li>|</li></ol>qoz',
|
||||
'foo<ol><li>^</li></ol>qoz'] },
|
||||
|
||||
{ 'id': 'OL-LI-1_SO',
|
||||
'desc': 'Delete last list item of list (should remove entire list)',
|
||||
'pad': 'foo<ol>{<li>foo</li>}</ol>qoz',
|
||||
'expected': 'foo^qoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete with strange selections',
|
||||
'tests': [
|
||||
{ 'id': 'HR.BR-1_SM',
|
||||
'desc': 'Delete selection that starts and ends within nodes that don\'t have children',
|
||||
'pad': 'foo<hr {>bar<br }>baz',
|
||||
'expected': 'foo<hr>|<br>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete after table',
|
||||
'tests': [
|
||||
{ 'id': 'TABLE-1_SA',
|
||||
'desc': 'Delete from position immediately after table (should have no effect)',
|
||||
'pad': 'foo<table><tbody><tr><td>bar</td></tr></tbody></table>^baz',
|
||||
'expected': 'foo<table><tbody><tr><td>bar</td></tr></tbody></table>^baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete within table cells',
|
||||
'tests': [
|
||||
{ 'id': 'TD-1_SS',
|
||||
'desc': 'Delete from start of first cell (should have no effect)',
|
||||
'pad': 'foo<table><tbody><tr><td>^bar</td></tr></tbody></table>baz',
|
||||
'expected': 'foo<table><tbody><tr><td>^bar</td></tr></tbody></table>baz' },
|
||||
|
||||
{ 'id': 'TD2-1_SS2',
|
||||
'desc': 'Delete from start of inner cell (should have no effect)',
|
||||
'pad': 'foo<table><tbody><tr><td>bar</td><td>^baz</td></tr></tbody></table>quoz',
|
||||
'expected': 'foo<table><tbody><tr><td>bar</td><td>^baz</td></tr></tbody></table>quoz' },
|
||||
|
||||
{ 'id': 'TD2-1_SM',
|
||||
'desc': 'Delete with selection spanning 2 cells',
|
||||
'pad': 'foo<table><tbody><tr><td>ba[r</td><td>b]az</td></tr></tbody></table>quoz',
|
||||
'expected': 'foo<table><tbody><tr><td>ba^</td><td>az</td></tr></tbody></table>quoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete table rows',
|
||||
'tests': [
|
||||
{ 'id': 'TR3-1_SO1',
|
||||
'desc': 'Delete first table row',
|
||||
'pad': '<table><tbody>{<tr><td>A</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^B</td></tr><tr><td>C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3-1_SO2',
|
||||
'desc': 'Delete middle table row',
|
||||
'pad': '<table><tbody><tr><td>A</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td></tr>|<tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>A</td></tr><tr><td>^C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3-1_SO3',
|
||||
'desc': 'Delete last table row',
|
||||
'pad': '<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td></tr><tr><td>B^</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR2rs:2-1_SO1',
|
||||
'desc': 'Delete first table row where a cell has rowspan 2',
|
||||
'pad': '<table><tbody>{<tr><td>A</td><td rowspan=2>R</td></tr>}<tr><td>B</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>B</td><td>R</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^B</td><td>R</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR2rs:2-1_SO2',
|
||||
'desc': 'Delete second table row where a cell has rowspan 2',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=2>R</td></tr>{<tr><td>B</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td><td>R</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td><td>R^</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO1',
|
||||
'desc': 'Delete first table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody>{<tr><td>A</td><td rowspan=3>R</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO2',
|
||||
'desc': 'Delete middle table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr>|<tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr><tr><td>^C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO3',
|
||||
'desc': 'Delete last table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B^</td></tr></tbody></table>'] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete with non-editable nested content',
|
||||
'tests': [
|
||||
{ 'id': 'DIV:ce:false-1_SO',
|
||||
'desc': 'Delete nested non-editable <div>',
|
||||
'pad': 'foo[bar<div contenteditable="false">NESTED</div>baz]qoz',
|
||||
'expected': 'foo^qoz' },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SB',
|
||||
'desc': 'Delete from immediately after a nested non-editable <div> (should be no-op)',
|
||||
'pad': 'foobar<div contenteditable="false">NESTED</div>^bazqoz',
|
||||
'expected': 'foobar<div contenteditable="false">NESTED</div>^bazqoz' },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SL',
|
||||
'desc': 'Delete nested non-editable <div> with oblique selection',
|
||||
'pad': 'foo[bar<div contenteditable="false">NES]TED</div>bazqoz',
|
||||
'expected': [ 'foo^<div contenteditable="false">NESTED</div>bazqoz',
|
||||
'foo<div contenteditable="false">[NES]TED</div>bazqoz' ] },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SR',
|
||||
'desc': 'Delete nested non-editable <div> with oblique selection',
|
||||
'pad': 'foobar<div contenteditable="false">NES[TED</div>baz]qoz',
|
||||
'expected': [ 'foobar<div contenteditable="false">NESTED</div>^qoz',
|
||||
'foobar<div contenteditable="false">NES[TED]</div>qoz' ] },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SI',
|
||||
'desc': 'Delete inside nested non-editable <div> (should be no-op)',
|
||||
'pad': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz',
|
||||
'expected': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'Delete with display:inline-block',
|
||||
'checkStyle': True,
|
||||
'tests': [
|
||||
{ 'id': 'SPAN:d:ib-1_SC',
|
||||
'desc': 'Delete inside an inline-block <span>',
|
||||
'pad': 'foo<span style="display: inline-block">bar^baz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">ba^baz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-1_SA',
|
||||
'desc': 'Delete from immediately after an inline-block <span>',
|
||||
'pad': 'foo<span style="display: inline-block">barbaz</span>^qoz',
|
||||
'expected': 'foo<span style="display: inline-block">barba^</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-2_SL',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo[DEL<span style="display: inline-block">ETE]bar</span>baz',
|
||||
'expected': 'foo^<span style="display: inline-block">bar</span>baz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-3_SR',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">bar[DEL</span>ETE]baz',
|
||||
'expected': 'foo<span style="display: inline-block">bar^</span>baz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4i_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">bar[DELETE]baz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">bar^baz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4l_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">[DELETE]barbaz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">^barbaz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4r_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">barbaz[DELETE]</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">barbaz^</span>qoz' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
|
||||
FORWARDDELETE_TESTS = {
|
||||
'id': 'FD',
|
||||
'caption': 'Forward-Delete Tests',
|
||||
'command': 'forwardDelete',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete single characters',
|
||||
'tests': [
|
||||
{ 'id': 'CHAR-1_SC',
|
||||
'desc': 'Delete 1 character',
|
||||
'pad': 'foo^barbaz',
|
||||
'expected': 'foo^arbaz' },
|
||||
|
||||
{ 'id': 'CHAR-2_SC',
|
||||
'desc': 'Delete 1 pre-composed character o with diaeresis',
|
||||
'pad': 'fo^öbarbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-3_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis above',
|
||||
'pad': 'fo^öbarbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-4_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis below',
|
||||
'pad': 'fo^o̤barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-5_SC',
|
||||
'desc': 'Delete 1 character with combining diaeresis above and below',
|
||||
'pad': 'fo^ö̤barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-6_SC',
|
||||
'desc': 'Delete 1 character with enclosing square',
|
||||
'pad': 'fo^o⃞barbaz',
|
||||
'expected': 'fo^barbaz' },
|
||||
|
||||
{ 'id': 'CHAR-7_SC',
|
||||
'desc': 'Delete 1 character with combining long solidus overlay',
|
||||
'pad': 'fo^o̸barbaz',
|
||||
'expected': 'fo^barbaz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete text selections',
|
||||
'tests': [
|
||||
{ 'id': 'TEXT-1_SI',
|
||||
'desc': 'Delete text selection',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SE',
|
||||
'desc': 'Forward-delete at end of span',
|
||||
'pad': 'foo<b>bar^</b>baz',
|
||||
'expected': 'foo<b>bar^</b>az' },
|
||||
|
||||
{ 'id': 'B-1_SB',
|
||||
'desc': 'Forward-delete from position before span',
|
||||
'pad': 'foo^<b>bar</b>baz',
|
||||
'expected': 'foo^<b>ar</b>baz' },
|
||||
|
||||
{ 'id': 'B-1_SW',
|
||||
'desc': 'Delete selection that wraps the whole span content',
|
||||
'pad': 'foo<b>[bar]</b>baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SO',
|
||||
'desc': 'Delete selection that wraps the whole span',
|
||||
'pad': 'foo[<b>bar</b>]baz',
|
||||
'expected': 'foo^baz' },
|
||||
|
||||
{ 'id': 'B-1_SL',
|
||||
'desc': 'Delete oblique selection that starts before span',
|
||||
'pad': 'foo[bar<b>baz]quoz</b>quuz',
|
||||
'expected': 'foo^<b>quoz</b>quuz' },
|
||||
|
||||
{ 'id': 'B-1_SR',
|
||||
'desc': 'Delete oblique selection that ends after span',
|
||||
'pad': 'foo<b>bar[baz</b>quoz]quuz',
|
||||
'expected': 'foo<b>bar^</b>quuz' },
|
||||
|
||||
{ 'id': 'B.I-1_SM',
|
||||
'desc': 'Delete oblique selection that starts and ends in different spans',
|
||||
'pad': 'foo<b>bar[baz</b><i>qoz]quuz</i>quuuz',
|
||||
'expected': 'foo<b>bar^</b><i>quuz</i>quuuz' },
|
||||
|
||||
{ 'id': 'GEN-1_SE',
|
||||
'desc': 'Delete at end of span with generated content',
|
||||
'pad': 'foo<gen>bar^</gen>baz',
|
||||
'expected': 'foo<gen>bar^</gen>az' },
|
||||
|
||||
{ 'id': 'GEN-1_SB',
|
||||
'desc': 'Delete from position before span with generated content',
|
||||
'pad': 'foo^<gen>bar</gen>baz',
|
||||
'expected': 'foo^<gen>ar</gen>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete paragraphs',
|
||||
'tests': [
|
||||
{ 'id': 'P2-1_SE1',
|
||||
'desc': 'Delete from collapsed selection at end of paragraph - should merge with next',
|
||||
'pad': '<p>foobar^</p><p>bazqoz</p>',
|
||||
'expected': '<p>foobar^bazqoz</p>' },
|
||||
|
||||
{ 'id': 'P2-1_SI1',
|
||||
'desc': 'Delete non-collapsed selection at end of paragraph - should not merge with next',
|
||||
'pad': '<p>foo[bar]</p><p>bazqoz</p>',
|
||||
'expected': '<p>foo^</p><p>bazqoz</p>' },
|
||||
|
||||
{ 'id': 'P2-1_SM',
|
||||
'desc': 'Delete non-collapsed selection spanning 2 paragraphs - should merge them',
|
||||
'pad': '<p>foo[bar</p><p>baz]qoz</p>',
|
||||
'expected': '<p>foo^qoz</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete lists and list items',
|
||||
'tests': [
|
||||
{ 'id': 'OL-LI2-1_SO1',
|
||||
'desc': 'Delete fully wrapped list item',
|
||||
'pad': 'foo<ol>{<li>bar</li>}<li>baz</li></ol>qoz',
|
||||
'expected': ['foo<ol>|<li>baz</li></ol>qoz',
|
||||
'foo<ol><li>^baz</li></ol>qoz'] },
|
||||
|
||||
{ 'id': 'OL-LI2-1_SM',
|
||||
'desc': 'Delete oblique range between list items within same list',
|
||||
'pad': 'foo<ol><li>ba[r</li><li>b]az</li></ol>qoz',
|
||||
'expected': 'foo<ol><li>ba^az</li></ol>qoz' },
|
||||
|
||||
{ 'id': 'OL-LI-1_SW',
|
||||
'desc': 'Delete contents of last list item (list should remain)',
|
||||
'pad': 'foo<ol><li>[foo]</li></ol>qoz',
|
||||
'expected': ['foo<ol><li>|</li></ol>qoz',
|
||||
'foo<ol><li>^</li></ol>qoz'] },
|
||||
|
||||
{ 'id': 'OL-LI-1_SO',
|
||||
'desc': 'Delete last list item of list (should remove entire list)',
|
||||
'pad': 'foo<ol>{<li>foo</li>}</ol>qoz',
|
||||
'expected': 'foo^qoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete with strange selections',
|
||||
'tests': [
|
||||
{ 'id': 'HR.BR-1_SM',
|
||||
'desc': 'Delete selection that starts and ends within nodes that don\'t have children',
|
||||
'pad': 'foo<hr {>bar<br }>baz',
|
||||
'expected': 'foo<hr>|<br>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete from immediately before a table',
|
||||
'tests': [
|
||||
{ 'id': 'TABLE-1_SB',
|
||||
'desc': 'Delete from position immediately before table (should have no effect)',
|
||||
'pad': 'foo^<table><tbody><tr><td>bar</td></tr></tbody></table>baz',
|
||||
'expected': 'foo^<table><tbody><tr><td>bar</td></tr></tbody></table>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete within table cells',
|
||||
'tests': [
|
||||
{ 'id': 'TD-1_SE',
|
||||
'desc': 'Delete from end of last cell (should have no effect)',
|
||||
'pad': 'foo<table><tbody><tr><td>bar^</td></tr></tbody></table>baz',
|
||||
'expected': 'foo<table><tbody><tr><td>bar^</td></tr></tbody></table>baz' },
|
||||
|
||||
{ 'id': 'TD2-1_SE1',
|
||||
'desc': 'Delete from end of inner cell (should have no effect)',
|
||||
'pad': 'foo<table><tbody><tr><td>bar^</td><td>baz</td></tr></tbody></table>quoz',
|
||||
'expected': 'foo<table><tbody><tr><td>bar^</td><td>baz</td></tr></tbody></table>quoz' },
|
||||
|
||||
{ 'id': 'TD2-1_SM',
|
||||
'desc': 'Delete with selection spanning 2 cells',
|
||||
'pad': 'foo<table><tbody><tr><td>ba[r</td><td>b]az</td></tr></tbody></table>quoz',
|
||||
'expected': 'foo<table><tbody><tr><td>ba^</td><td>az</td></tr></tbody></table>quoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'forward-delete table rows',
|
||||
'tests': [
|
||||
{ 'id': 'TR3-1_SO1',
|
||||
'desc': 'Delete first table row',
|
||||
'pad': '<table><tbody>{<tr><td>A</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^B</td></tr><tr><td>C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3-1_SO2',
|
||||
'desc': 'Delete middle table row',
|
||||
'pad': '<table><tbody><tr><td>A</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td></tr>|<tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>A</td></tr><tr><td>^C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3-1_SO3',
|
||||
'desc': 'Delete last table row',
|
||||
'pad': '<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td></tr><tr><td>B</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td></tr><tr><td>B^</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR2rs:2-1_SO1',
|
||||
'desc': 'Delete first table row where a cell has rowspan 2',
|
||||
'pad': '<table><tbody>{<tr><td>A</td><td rowspan=2>R</td></tr>}<tr><td>B</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>B</td><td>R</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^B</td><td>R</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR2rs:2-1_SO2',
|
||||
'desc': 'Delete second table row where a cell has rowspan 2',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=2>R</td></tr>{<tr><td>B</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td><td>R</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td><td>R^</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO1',
|
||||
'desc': 'Delete first table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody>{<tr><td>A</td><td rowspan=3>R</td></tr>}<tr><td>B</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody>|<tr><td>A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>^A</td><td rowspan="2">R</td></tr><tr><td>C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO2',
|
||||
'desc': 'Delete middle table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr>{<tr><td>B</td></tr>}<tr><td>C</td></tr></tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr>|<tr><td>C</td></tr></tbody></table>',
|
||||
'<table><tbody><tr><td>B</td><td rowspan="2">R</td></tr><tr><td>^C</td></tr></tbody></table>'] },
|
||||
|
||||
{ 'id': 'TR3rs:3-1_SO3',
|
||||
'desc': 'Delete last table row where a cell has rowspan 3',
|
||||
'pad': '<table><tbody><tr><td>A</td><td rowspan=3>R</td></tr><tr><td>B</td></tr>{<tr><td>C</td></tr>}</tbody></table>',
|
||||
'expected': ['<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B</td></tr>|</tbody></table>',
|
||||
'<table><tbody><tr><td>A</td><td rowspan="2">R</td></tr><tr><td>B^</td></tr></tbody></table>'] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'delete with non-editable nested content',
|
||||
'tests': [
|
||||
{ 'id': 'DIV:ce:false-1_SO',
|
||||
'desc': 'Delete nested non-editable <div>',
|
||||
'pad': 'foo[bar<div contenteditable="false">NESTED</div>baz]qoz',
|
||||
'expected': 'foo^qoz' },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SB',
|
||||
'desc': 'Delete from immediately before a nested non-editable <div> (should be no-op)',
|
||||
'pad': 'foobar^<div contenteditable="false">NESTED</div>bazqoz',
|
||||
'expected': 'foobar^<div contenteditable="false">NESTED</div>bazqoz' },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SL',
|
||||
'desc': 'Delete nested non-editable <div> with oblique selection',
|
||||
'pad': 'foo[bar<div contenteditable="false">NES]TED</div>bazqoz',
|
||||
'expected': [ 'foo^<div contenteditable="false">NESTED</div>bazqoz',
|
||||
'foo<div contenteditable="false">[NES]TED</div>bazqoz' ] },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SR',
|
||||
'desc': 'Delete nested non-editable <div> with oblique selection',
|
||||
'pad': 'foobar<div contenteditable="false">NES[TED</div>baz]qoz',
|
||||
'expected': [ 'foobar<div contenteditable="false">NESTED</div>^qoz',
|
||||
'foobar<div contenteditable="false">NES[TED]</div>qoz' ] },
|
||||
|
||||
{ 'id': 'DIV:ce:false-1_SI',
|
||||
'desc': 'Delete inside nested non-editable <div> (should be no-op)',
|
||||
'pad': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz',
|
||||
'expected': 'foobar<div contenteditable="false">NE[ST]ED</div>bazqoz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'Delete with display:inline-block',
|
||||
'checkStyle': True,
|
||||
'tests': [
|
||||
{ 'id': 'SPAN:d:ib-1_SC',
|
||||
'desc': 'Delete inside an inline-block <span>',
|
||||
'pad': 'foo<span style="display: inline-block">bar^baz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">bar^az</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-1_SA',
|
||||
'desc': 'Delete from immediately before an inline-block <span>',
|
||||
'pad': 'foo^<span style="display: inline-block">barbaz</span>qoz',
|
||||
'expected': 'foo^<span style="display: inline-block">arbaz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-2_SL',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo[DEL<span style="display: inline-block">ETE]bar</span>baz',
|
||||
'expected': 'foo^<span style="display: inline-block">bar</span>baz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-3_SR',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">bar[DEL</span>ETE]baz',
|
||||
'expected': 'foo<span style="display: inline-block">bar^</span>baz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4i_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">bar[DELETE]baz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">bar^baz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4l_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">[DELETE]barbaz</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">^barbaz</span>qoz' },
|
||||
|
||||
{ 'id': 'SPAN:d:ib-4r_SI',
|
||||
'desc': 'Delete with nested inline-block <span>, oblique selection',
|
||||
'pad': 'foo<span style="display: inline-block">barbaz[DELETE]</span>qoz',
|
||||
'expected': 'foo<span style="display: inline-block">barbaz^</span>qoz' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
|
||||
INSERT_TESTS = {
|
||||
'id': 'I',
|
||||
'caption': 'Insert Tests',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <hr>',
|
||||
'command': 'inserthorizontalrule',
|
||||
'tests': [
|
||||
{ 'id': 'IHR_TEXT-1_SC',
|
||||
'rte1-id': 'a-inserthorizontalrule-0',
|
||||
'desc': 'Insert <hr> into text',
|
||||
'pad': 'foo^bar',
|
||||
'expected': 'foo<hr>^bar',
|
||||
'accept': 'foo<hr>|bar' },
|
||||
|
||||
{ 'id': 'IHR_TEXT-1_SI',
|
||||
'desc': 'Insert <hr>, replacing selected text',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<hr>^baz',
|
||||
'accept': 'foo<hr>|baz' },
|
||||
|
||||
{ 'id': 'IHR_DIV-B-1_SX',
|
||||
'desc': 'Insert <hr> between elements',
|
||||
'pad': '<div><b>foo</b>|<b>bar</b></div>',
|
||||
'expected': '<div><b>foo</b><hr>|<b>bar</b></div>' },
|
||||
|
||||
{ 'id': 'IHR_DIV-B-2_SO',
|
||||
'desc': 'Insert <hr>, replacing a fully wrapped element',
|
||||
'pad': '<div><b>foo</b>{<b>bar</b>}<b>baz</b></div>',
|
||||
'expected': '<div><b>foo</b><hr>|<b>baz</b></div>' },
|
||||
|
||||
{ 'id': 'IHR_B-1_SC',
|
||||
'desc': 'Insert <hr> into a span, splitting it',
|
||||
'pad': '<b>foo^bar</b>',
|
||||
'expected': '<b>foo</b><hr><b>^bar</b>' },
|
||||
|
||||
{ 'id': 'IHR_B-1_SS',
|
||||
'desc': 'Insert <hr> into a span at the start (should not create an empty span)',
|
||||
'pad': '<b>^foobar</b>',
|
||||
'expected': '<hr><b>^foobar</b>' },
|
||||
|
||||
{ 'id': 'IHR_B-1_SE',
|
||||
'desc': 'Insert <hr> into a span at the end',
|
||||
'pad': '<b>foobar^</b>',
|
||||
'expected': [ '<b>foobar</b><hr>|',
|
||||
'<b>foobar</b><hr><b>^</b>' ] },
|
||||
|
||||
{ 'id': 'IHR_B-2_SL',
|
||||
'desc': 'Insert <hr> with oblique selection starting outside of span',
|
||||
'pad': 'foo[bar<b>baz]qoz</b>',
|
||||
'expected': 'foo<hr>|<b>qoz</b>' },
|
||||
|
||||
{ 'id': 'IHR_B-2_SLR',
|
||||
'desc': 'Insert <hr> with oblique reversed selection starting outside of span',
|
||||
'pad': 'foo]bar<b>baz[qoz</b>',
|
||||
'expected': [ 'foo<hr>|<b>qoz</b>',
|
||||
'foo<hr><b>^qoz</b>' ] },
|
||||
|
||||
{ 'id': 'IHR_B-3_SR',
|
||||
'desc': 'Insert <hr> with oblique selection ending outside of span',
|
||||
'pad': '<b>foo[bar</b>baz]quoz',
|
||||
'expected': [ '<b>foo</b><hr>|quoz',
|
||||
'<b>foo</b><hr><b>^</b>quoz' ] },
|
||||
|
||||
{ 'id': 'IHR_B-3_SRR',
|
||||
'desc': 'Insert <hr> with oblique reversed selection starting outside of span',
|
||||
'pad': '<b>foo]bar</b>baz[quoz',
|
||||
'expected': '<b>foo</b><hr>|quoz' },
|
||||
|
||||
{ 'id': 'IHR_B-I-1_SM',
|
||||
'desc': 'Insert <hr> with oblique selection between different spans',
|
||||
'pad': '<b>foo[bar</b><i>baz]quoz</i>',
|
||||
'expected': [ '<b>foo</b><hr>|<i>quoz</i>',
|
||||
'<b>foo</b><hr><b>^</b><i>quoz</i>' ] },
|
||||
|
||||
{ 'id': 'IHR_B-I-1_SMR',
|
||||
'desc': 'Insert <hr> with reversed oblique selection between different spans',
|
||||
'pad': '<b>foo]bar</b><i>baz[quoz</i>',
|
||||
'expected': '<b>foo</b><hr><i>^quoz</i>' },
|
||||
|
||||
{ 'id': 'IHR_P-1_SC',
|
||||
'desc': 'Insert <hr> into a paragraph, splitting it',
|
||||
'pad': '<p>foo^bar</p>',
|
||||
'expected': [ '<p>foo</p><hr>|<p>bar</p>',
|
||||
'<p>foo</p><hr><p>^bar</p>' ] },
|
||||
|
||||
{ 'id': 'IHR_P-1_SS',
|
||||
'desc': 'Insert <hr> into a paragraph at the start (should not create an empty span)',
|
||||
'pad': '<p>^foobar</p>',
|
||||
'expected': [ '<hr>|<p>foobar</p>',
|
||||
'<hr><p>^foobar</p>' ] },
|
||||
|
||||
{ 'id': 'IHR_P-1_SE',
|
||||
'desc': 'Insert <hr> into a paragraph at the end (should not create an empty span)',
|
||||
'pad': '<p>foobar^</p>',
|
||||
'expected': '<p>foobar</p><hr>|' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <p>',
|
||||
'command': 'insertparagraph',
|
||||
'tests': [
|
||||
{ 'id': 'IP_P-1_SC',
|
||||
'desc': 'Split paragraph',
|
||||
'pad': '<p>foo^bar</p>',
|
||||
'expected': '<p>foo</p><p>^bar</p>' },
|
||||
|
||||
{ 'id': 'IP_UL-LI-1_SC',
|
||||
'desc': 'Split list item',
|
||||
'pad': '<ul><li>foo^bar</li></ul>',
|
||||
'expected': '<ul><li>foo</li><li>^bar</li></ul>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert text',
|
||||
'command': 'inserttext',
|
||||
'tests': [
|
||||
{ 'id': 'ITEXT:text_TEXT-1_SC',
|
||||
'desc': 'Insert text',
|
||||
'value': 'text',
|
||||
'pad': 'foo^bar',
|
||||
'expected': 'footext^bar' },
|
||||
|
||||
{ 'id': 'ITEXT:text_TEXT-1_SI',
|
||||
'desc': 'Insert text, replacing selected text',
|
||||
'value': 'text',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'footext^baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <br>',
|
||||
'command': 'insertlinebreak',
|
||||
'tests': [
|
||||
{ 'id': 'IBR_TEXT-1_SC',
|
||||
'desc': 'Insert <br> into text',
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ 'foo<br>|bar',
|
||||
'foo<br>^bar' ] },
|
||||
|
||||
{ 'id': 'IBR_TEXT-1_SI',
|
||||
'desc': 'Insert <br>, replacing selected text',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': [ 'foo<br>|baz',
|
||||
'foo<br>^baz' ] },
|
||||
|
||||
{ 'id': 'IBR_LI-1_SC',
|
||||
'desc': 'Insert <br> within list item',
|
||||
'pad': '<ul><li>foo^bar</li></ul>',
|
||||
'expected': '<ul><li>foo<br>^bar</li></ul>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <img>',
|
||||
'command': 'insertimage',
|
||||
'tests': [
|
||||
{ 'id': 'IIMG:url_TEXT-1_SC',
|
||||
'rte1-id': 'a-insertimage-0',
|
||||
'desc': 'Insert image with URL "bar.png"',
|
||||
'value': 'bar.png',
|
||||
'checkAttrs': True,
|
||||
'pad': 'foo^bar',
|
||||
'expected': [ 'foo<img src="bar.png">|bar',
|
||||
'foo<img src="bar.png">^bar' ] },
|
||||
|
||||
{ 'id': 'IIMG:url_IMG-1_SO',
|
||||
'desc': 'Change existing image to new URL, selection on <img>',
|
||||
'value': 'quz.png',
|
||||
'checkAttrs': True,
|
||||
'pad': '<span>foo{<img src="bar.png">}bar</span>',
|
||||
'expected': [ '<span>foo<img src="quz.png"/>|bar</span>',
|
||||
'<span>foo<img src="quz.png"/>^bar</span>' ] },
|
||||
|
||||
{ 'id': 'IIMG:url_SPAN-IMG-1_SO',
|
||||
'desc': 'Change existing image to new URL, selection in text surrounding <img>',
|
||||
'value': 'quz.png',
|
||||
'checkAttrs': True,
|
||||
'pad': 'foo[<img src="bar.png">]bar',
|
||||
'expected': [ 'foo<img src="quz.png"/>|bar',
|
||||
'foo<img src="quz.png"/>^bar' ] },
|
||||
|
||||
{ 'id': 'IIMG:._SPAN-IMG-1_SO',
|
||||
'desc': 'Remove existing image or URL, selection on <img>',
|
||||
'value': '',
|
||||
'checkAttrs': True,
|
||||
'pad': '<span>foo{<img src="bar.png">}bar</span>',
|
||||
'expected': [ '<span>foo^bar</span>',
|
||||
'<span>foo<img>|bar</span>',
|
||||
'<span>foo<img>^bar</span>',
|
||||
'<span>foo<img src="">|bar</span>',
|
||||
'<span>foo<img src="">^bar</span>' ] },
|
||||
|
||||
{ 'id': 'IIMG:._IMG-1_SO',
|
||||
'desc': 'Remove existing image or URL, selection in text surrounding <img>',
|
||||
'value': '',
|
||||
'checkAttrs': True,
|
||||
'pad': 'foo[<img src="bar.png">]bar',
|
||||
'expected': [ 'foo^bar',
|
||||
'foo<img>|bar',
|
||||
'foo<img>^bar',
|
||||
'foo<img src="">|bar',
|
||||
'foo<img src="">^bar' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <ol>',
|
||||
'command': 'insertorderedlist',
|
||||
'tests': [
|
||||
{ 'id': 'IOL_TEXT-1_SC',
|
||||
'rte1-id': 'a-insertorderedlist-0',
|
||||
'desc': 'Insert ordered list on collapsed selection',
|
||||
'pad': 'foo^bar',
|
||||
'expected': '<ol><li>foo^bar</li></ol>' },
|
||||
|
||||
{ 'id': 'IOL_TEXT-1_SI',
|
||||
'desc': 'Insert ordered list on selected text',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<ol><li>foo[bar]baz</li></ol>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert <ul>',
|
||||
'command': 'insertunorderedlist',
|
||||
'tests': [
|
||||
{ 'id': 'IUL_TEXT-1_SC',
|
||||
'desc': 'Insert unordered list on collapsed selection',
|
||||
'pad': 'foo^bar',
|
||||
'expected': '<ul><li>foo^bar</li></ul>' },
|
||||
|
||||
{ 'id': 'IUL_TEXT-1_SI',
|
||||
'rte1-id': 'a-insertunorderedlist-0',
|
||||
'desc': 'Insert unordered list on selected text',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': '<ul><li>foo[bar]baz</li></ul>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'insert arbitrary HTML',
|
||||
'command': 'inserthtml',
|
||||
'tests': [
|
||||
{ 'id': 'IHTML:BR_TEXT-1_SC',
|
||||
'rte1-id': 'a-inserthtml-0',
|
||||
'desc': 'InsertHTML: <br>',
|
||||
'value': '<br>',
|
||||
'pad': 'foo^barbaz',
|
||||
'expected': 'foo<br>^barbaz' },
|
||||
|
||||
{ 'id': 'IHTML:text_TEXT-1_SI',
|
||||
'desc': 'InsertHTML: "NEW"',
|
||||
'value': 'NEW',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'fooNEW^baz' },
|
||||
|
||||
{ 'id': 'IHTML:S_TEXT-1_SI',
|
||||
'desc': 'InsertHTML: "<span>NEW<span>"',
|
||||
'value': '<span>NEW</span>',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<span>NEW</span>^baz' },
|
||||
|
||||
{ 'id': 'IHTML:H1.H2_TEXT-1_SI',
|
||||
'desc': 'InsertHTML: "<h1>NEW</h1><h2>HTML</h2>"',
|
||||
'value': '<h1>NEW</h1><h2>HTML</h2>',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<h1>NEW</h1><h2>HTML</h2>^baz' },
|
||||
|
||||
{ 'id': 'IHTML:P-B_TEXT-1_SI',
|
||||
'desc': 'InsertHTML: "<p>NEW<b>HTML</b>!</p>"',
|
||||
'value': '<p>NEW<b>HTML</b>!</p>',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'foo<p>NEW<b>HTML</b>!</p>^baz' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
|
||||
QUERYENABLED_TESTS = {
|
||||
'id': 'QE',
|
||||
'caption': 'queryCommandEnabled Tests',
|
||||
'pad': 'foo[bar]baz',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': False,
|
||||
'expected': True,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'HTML5 commands',
|
||||
'tests': [
|
||||
{ 'id': 'SELECTALL_TEXT-1',
|
||||
'desc': 'check whether the "selectall" command is enabled',
|
||||
'qcenabled': 'selectall' },
|
||||
|
||||
{ 'id': 'UNSELECT_TEXT-1',
|
||||
'desc': 'check whether the "unselect" command is enabled',
|
||||
'qcenabled': 'unselect' },
|
||||
|
||||
{ 'id': 'UNDO_TEXT-1',
|
||||
'desc': 'check whether the "undo" command is enabled',
|
||||
'qcenabled': 'undo' },
|
||||
|
||||
{ 'id': 'REDO_TEXT-1',
|
||||
'desc': 'check whether the "redo" command is enabled',
|
||||
'qcenabled': 'redo' },
|
||||
|
||||
{ 'id': 'BOLD_TEXT-1',
|
||||
'desc': 'check whether the "bold" command is enabled',
|
||||
'qcenabled': 'bold' },
|
||||
|
||||
{ 'id': 'ITALIC_TEXT-1',
|
||||
'desc': 'check whether the "italic" command is enabled',
|
||||
'qcenabled': 'italic' },
|
||||
|
||||
{ 'id': 'UNDERLINE_TEXT-1',
|
||||
'desc': 'check whether the "underline" command is enabled',
|
||||
'qcenabled': 'underline' },
|
||||
|
||||
{ 'id': 'STRIKETHROUGH_TEXT-1',
|
||||
'desc': 'check whether the "strikethrough" command is enabled',
|
||||
'qcenabled': 'strikethrough' },
|
||||
|
||||
{ 'id': 'SUBSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "subscript" command is enabled',
|
||||
'qcenabled': 'subscript' },
|
||||
|
||||
{ 'id': 'SUPERSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "superscript" command is enabled',
|
||||
'qcenabled': 'superscript' },
|
||||
|
||||
{ 'id': 'FORMATBLOCK_TEXT-1',
|
||||
'desc': 'check whether the "formatblock" command is enabled',
|
||||
'qcenabled': 'formatblock' },
|
||||
|
||||
{ 'id': 'CREATELINK_TEXT-1',
|
||||
'desc': 'check whether the "createlink" command is enabled',
|
||||
'qcenabled': 'createlink' },
|
||||
|
||||
{ 'id': 'UNLINK_TEXT-1',
|
||||
'desc': 'check whether the "unlink" command is enabled',
|
||||
'qcenabled': 'unlink' },
|
||||
|
||||
{ 'id': 'INSERTHTML_TEXT-1',
|
||||
'desc': 'check whether the "inserthtml" command is enabled',
|
||||
'qcenabled': 'inserthtml' },
|
||||
|
||||
{ 'id': 'INSERTHORIZONTALRULE_TEXT-1',
|
||||
'desc': 'check whether the "inserthorizontalrule" command is enabled',
|
||||
'qcenabled': 'inserthorizontalrule' },
|
||||
|
||||
{ 'id': 'INSERTIMAGE_TEXT-1',
|
||||
'desc': 'check whether the "insertimage" command is enabled',
|
||||
'qcenabled': 'insertimage' },
|
||||
|
||||
{ 'id': 'INSERTLINEBREAK_TEXT-1',
|
||||
'desc': 'check whether the "insertlinebreak" command is enabled',
|
||||
'qcenabled': 'insertlinebreak' },
|
||||
|
||||
{ 'id': 'INSERTPARAGRAPH_TEXT-1',
|
||||
'desc': 'check whether the "insertparagraph" command is enabled',
|
||||
'qcenabled': 'insertparagraph' },
|
||||
|
||||
{ 'id': 'INSERTORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertorderedlist" command is enabled',
|
||||
'qcenabled': 'insertorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTUNORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertunorderedlist" command is enabled',
|
||||
'qcenabled': 'insertunorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTTEXT_TEXT-1',
|
||||
'desc': 'check whether the "inserttext" command is enabled',
|
||||
'qcenabled': 'inserttext' },
|
||||
|
||||
{ 'id': 'DELETE_TEXT-1',
|
||||
'desc': 'check whether the "delete" command is enabled',
|
||||
'qcenabled': 'delete' },
|
||||
|
||||
{ 'id': 'FORWARDDELETE_TEXT-1',
|
||||
'desc': 'check whether the "forwarddelete" command is enabled',
|
||||
'qcenabled': 'forwarddelete' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'MIDAS commands',
|
||||
'tests': [
|
||||
{ 'id': 'STYLEWITHCSS_TEXT-1',
|
||||
'desc': 'check whether the "styleWithCSS" command is enabled',
|
||||
'qcenabled': 'styleWithCSS' },
|
||||
|
||||
{ 'id': 'CONTENTREADONLY_TEXT-1',
|
||||
'desc': 'check whether the "contentreadonly" command is enabled',
|
||||
'qcenabled': 'contentreadonly' },
|
||||
|
||||
{ 'id': 'BACKCOLOR_TEXT-1',
|
||||
'desc': 'check whether the "backcolor" command is enabled',
|
||||
'qcenabled': 'backcolor' },
|
||||
|
||||
{ 'id': 'FORECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "forecolor" command is enabled',
|
||||
'qcenabled': 'forecolor' },
|
||||
|
||||
{ 'id': 'HILITECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "hilitecolor" command is enabled',
|
||||
'qcenabled': 'hilitecolor' },
|
||||
|
||||
{ 'id': 'FONTNAME_TEXT-1',
|
||||
'desc': 'check whether the "fontname" command is enabled',
|
||||
'qcenabled': 'fontname' },
|
||||
|
||||
{ 'id': 'FONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "fontsize" command is enabled',
|
||||
'qcenabled': 'fontsize' },
|
||||
|
||||
{ 'id': 'INCREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "increasefontsize" command is enabled',
|
||||
'qcenabled': 'increasefontsize' },
|
||||
|
||||
{ 'id': 'DECREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "decreasefontsize" command is enabled',
|
||||
'qcenabled': 'decreasefontsize' },
|
||||
|
||||
{ 'id': 'HEADING_TEXT-1',
|
||||
'desc': 'check whether the "heading" command is enabled',
|
||||
'qcenabled': 'heading' },
|
||||
|
||||
{ 'id': 'INDENT_TEXT-1',
|
||||
'desc': 'check whether the "indent" command is enabled',
|
||||
'qcenabled': 'indent' },
|
||||
|
||||
{ 'id': 'OUTDENT_TEXT-1',
|
||||
'desc': 'check whether the "outdent" command is enabled',
|
||||
'qcenabled': 'outdent' },
|
||||
|
||||
{ 'id': 'CREATEBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "createbookmark" command is enabled',
|
||||
'qcenabled': 'createbookmark' },
|
||||
|
||||
{ 'id': 'UNBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "unbookmark" command is enabled',
|
||||
'qcenabled': 'unbookmark' },
|
||||
|
||||
{ 'id': 'JUSTIFYCENTER_TEXT-1',
|
||||
'desc': 'check whether the "justifycenter" command is enabled',
|
||||
'qcenabled': 'justifycenter' },
|
||||
|
||||
{ 'id': 'JUSTIFYFULL_TEXT-1',
|
||||
'desc': 'check whether the "justifyfull" command is enabled',
|
||||
'qcenabled': 'justifyfull' },
|
||||
|
||||
{ 'id': 'JUSTIFYLEFT_TEXT-1',
|
||||
'desc': 'check whether the "justifyleft" command is enabled',
|
||||
'qcenabled': 'justifyleft' },
|
||||
|
||||
{ 'id': 'JUSTIFYRIGHT_TEXT-1',
|
||||
'desc': 'check whether the "justifyright" command is enabled',
|
||||
'qcenabled': 'justifyright' },
|
||||
|
||||
{ 'id': 'REMOVEFORMAT_TEXT-1',
|
||||
'desc': 'check whether the "removeformat" command is enabled',
|
||||
'qcenabled': 'removeformat' },
|
||||
|
||||
{ 'id': 'COPY_TEXT-1',
|
||||
'desc': 'check whether the "copy" command is enabled',
|
||||
'qcenabled': 'copy' },
|
||||
|
||||
{ 'id': 'CUT_TEXT-1',
|
||||
'desc': 'check whether the "cut" command is enabled',
|
||||
'qcenabled': 'cut' },
|
||||
|
||||
{ 'id': 'PASTE_TEXT-1',
|
||||
'desc': 'check whether the "paste" command is enabled',
|
||||
'qcenabled': 'paste' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'Other tests',
|
||||
'tests': [
|
||||
{ 'id': 'garbage-1_TEXT-1',
|
||||
'desc': 'check correct return value with garbage input',
|
||||
'qcenabled': '#!#@7',
|
||||
'expected': False }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
|
||||
QUERYINDETERM_TESTS = {
|
||||
'id': 'QI',
|
||||
'caption': 'queryCommandIndeterm Tests',
|
||||
'pad': 'foo[bar]baz',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': False,
|
||||
'expected': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'HTML5 commands',
|
||||
'tests': [
|
||||
{ 'id': 'SELECTALL_TEXT-1',
|
||||
'desc': 'check whether the "selectall" command is indeterminate',
|
||||
'qcindeterm': 'selectall' },
|
||||
|
||||
{ 'id': 'UNSELECT_TEXT-1',
|
||||
'desc': 'check whether the "unselect" command is indeterminate',
|
||||
'qcindeterm': 'unselect' },
|
||||
|
||||
{ 'id': 'UNDO_TEXT-1',
|
||||
'desc': 'check whether the "undo" command is indeterminate',
|
||||
'qcindeterm': 'undo' },
|
||||
|
||||
{ 'id': 'REDO_TEXT-1',
|
||||
'desc': 'check whether the "redo" command is indeterminate',
|
||||
'qcindeterm': 'redo' },
|
||||
|
||||
{ 'id': 'BOLD_TEXT-1',
|
||||
'desc': 'check whether the "bold" command is indeterminate',
|
||||
'qcindeterm': 'bold' },
|
||||
|
||||
{ 'id': 'ITALIC_TEXT-1',
|
||||
'desc': 'check whether the "italic" command is indeterminate',
|
||||
'qcindeterm': 'italic' },
|
||||
|
||||
{ 'id': 'UNDERLINE_TEXT-1',
|
||||
'desc': 'check whether the "underline" command is indeterminate',
|
||||
'qcindeterm': 'underline' },
|
||||
|
||||
{ 'id': 'STRIKETHROUGH_TEXT-1',
|
||||
'desc': 'check whether the "strikethrough" command is indeterminate',
|
||||
'qcindeterm': 'strikethrough' },
|
||||
|
||||
{ 'id': 'SUBSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "subscript" command is indeterminate',
|
||||
'qcindeterm': 'subscript' },
|
||||
|
||||
{ 'id': 'SUPERSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "superscript" command is indeterminate',
|
||||
'qcindeterm': 'superscript' },
|
||||
|
||||
{ 'id': 'FORMATBLOCK_TEXT-1',
|
||||
'desc': 'check whether the "formatblock" command is indeterminate',
|
||||
'qcindeterm': 'formatblock' },
|
||||
|
||||
{ 'id': 'CREATELINK_TEXT-1',
|
||||
'desc': 'check whether the "createlink" command is indeterminate',
|
||||
'qcindeterm': 'createlink' },
|
||||
|
||||
{ 'id': 'UNLINK_TEXT-1',
|
||||
'desc': 'check whether the "unlink" command is indeterminate',
|
||||
'qcindeterm': 'unlink' },
|
||||
|
||||
{ 'id': 'INSERTHTML_TEXT-1',
|
||||
'desc': 'check whether the "inserthtml" command is indeterminate',
|
||||
'qcindeterm': 'inserthtml' },
|
||||
|
||||
{ 'id': 'INSERTHORIZONTALRULE_TEXT-1',
|
||||
'desc': 'check whether the "inserthorizontalrule" command is indeterminate',
|
||||
'qcindeterm': 'inserthorizontalrule' },
|
||||
|
||||
{ 'id': 'INSERTIMAGE_TEXT-1',
|
||||
'desc': 'check whether the "insertimage" command is indeterminate',
|
||||
'qcindeterm': 'insertimage' },
|
||||
|
||||
{ 'id': 'INSERTLINEBREAK_TEXT-1',
|
||||
'desc': 'check whether the "insertlinebreak" command is indeterminate',
|
||||
'qcindeterm': 'insertlinebreak' },
|
||||
|
||||
{ 'id': 'INSERTPARAGRAPH_TEXT-1',
|
||||
'desc': 'check whether the "insertparagraph" command is indeterminate',
|
||||
'qcindeterm': 'insertparagraph' },
|
||||
|
||||
{ 'id': 'INSERTORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertorderedlist" command is indeterminate',
|
||||
'qcindeterm': 'insertorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTUNORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertunorderedlist" command is indeterminate',
|
||||
'qcindeterm': 'insertunorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTTEXT_TEXT-1',
|
||||
'desc': 'check whether the "inserttext" command is indeterminate',
|
||||
'qcindeterm': 'inserttext' },
|
||||
|
||||
{ 'id': 'DELETE_TEXT-1',
|
||||
'desc': 'check whether the "delete" command is indeterminate',
|
||||
'qcindeterm': 'delete' },
|
||||
|
||||
{ 'id': 'FORWARDDELETE_TEXT-1',
|
||||
'desc': 'check whether the "forwarddelete" command is indeterminate',
|
||||
'qcindeterm': 'forwarddelete' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'MIDAS commands',
|
||||
'tests': [
|
||||
{ 'id': 'STYLEWITHCSS_TEXT-1',
|
||||
'desc': 'check whether the "styleWithCSS" command is indeterminate',
|
||||
'qcindeterm': 'styleWithCSS' },
|
||||
|
||||
{ 'id': 'CONTENTREADONLY_TEXT-1',
|
||||
'desc': 'check whether the "contentreadonly" command is indeterminate',
|
||||
'qcindeterm': 'contentreadonly' },
|
||||
|
||||
{ 'id': 'BACKCOLOR_TEXT-1',
|
||||
'desc': 'check whether the "backcolor" command is indeterminate',
|
||||
'qcindeterm': 'backcolor' },
|
||||
|
||||
{ 'id': 'FORECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "forecolor" command is indeterminate',
|
||||
'qcindeterm': 'forecolor' },
|
||||
|
||||
{ 'id': 'HILITECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "hilitecolor" command is indeterminate',
|
||||
'qcindeterm': 'hilitecolor' },
|
||||
|
||||
{ 'id': 'FONTNAME_TEXT-1',
|
||||
'desc': 'check whether the "fontname" command is indeterminate',
|
||||
'qcindeterm': 'fontname' },
|
||||
|
||||
{ 'id': 'FONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "fontsize" command is indeterminate',
|
||||
'qcindeterm': 'fontsize' },
|
||||
|
||||
{ 'id': 'INCREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "increasefontsize" command is indeterminate',
|
||||
'qcindeterm': 'increasefontsize' },
|
||||
|
||||
{ 'id': 'DECREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "decreasefontsize" command is indeterminate',
|
||||
'qcindeterm': 'decreasefontsize' },
|
||||
|
||||
{ 'id': 'HEADING_TEXT-1',
|
||||
'desc': 'check whether the "heading" command is indeterminate',
|
||||
'qcindeterm': 'heading' },
|
||||
|
||||
{ 'id': 'INDENT_TEXT-1',
|
||||
'desc': 'check whether the "indent" command is indeterminate',
|
||||
'qcindeterm': 'indent' },
|
||||
|
||||
{ 'id': 'OUTDENT_TEXT-1',
|
||||
'desc': 'check whether the "outdent" command is indeterminate',
|
||||
'qcindeterm': 'outdent' },
|
||||
|
||||
{ 'id': 'CREATEBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "createbookmark" command is indeterminate',
|
||||
'qcindeterm': 'createbookmark' },
|
||||
|
||||
{ 'id': 'UNBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "unbookmark" command is indeterminate',
|
||||
'qcindeterm': 'unbookmark' },
|
||||
|
||||
{ 'id': 'JUSTIFYCENTER_TEXT-1',
|
||||
'desc': 'check whether the "justifycenter" command is indeterminate',
|
||||
'qcindeterm': 'justifycenter' },
|
||||
|
||||
{ 'id': 'JUSTIFYFULL_TEXT-1',
|
||||
'desc': 'check whether the "justifyfull" command is indeterminate',
|
||||
'qcindeterm': 'justifyfull' },
|
||||
|
||||
{ 'id': 'JUSTIFYLEFT_TEXT-1',
|
||||
'desc': 'check whether the "justifyleft" command is indeterminate',
|
||||
'qcindeterm': 'justifyleft' },
|
||||
|
||||
{ 'id': 'JUSTIFYRIGHT_TEXT-1',
|
||||
'desc': 'check whether the "justifyright" command is indeterminate',
|
||||
'qcindeterm': 'justifyright' },
|
||||
|
||||
{ 'id': 'REMOVEFORMAT_TEXT-1',
|
||||
'desc': 'check whether the "removeformat" command is indeterminate',
|
||||
'qcindeterm': 'removeformat' },
|
||||
|
||||
{ 'id': 'COPY_TEXT-1',
|
||||
'desc': 'check whether the "copy" command is indeterminate',
|
||||
'qcindeterm': 'copy' },
|
||||
|
||||
{ 'id': 'CUT_TEXT-1',
|
||||
'desc': 'check whether the "cut" command is indeterminate',
|
||||
'qcindeterm': 'cut' },
|
||||
|
||||
{ 'id': 'PASTE_TEXT-1',
|
||||
'desc': 'check whether the "paste" command is indeterminate',
|
||||
'qcindeterm': 'paste' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'Other tests',
|
||||
'tests': [
|
||||
{ 'id': 'garbage-1_TEXT-1',
|
||||
'desc': 'check correct return value with garbage input',
|
||||
'qcindeterm': '#!#@7' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,575 @@
|
|||
|
||||
QUERYSTATE_TESTS = {
|
||||
'id': 'QS',
|
||||
'caption': 'queryCommandState Tests',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'qcstate': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query bold state',
|
||||
'qcstate': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_TEXT_SI',
|
||||
'rte1-id': 'q-bold-0',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_B-1_SI',
|
||||
'rte1-id': 'q-bold-1',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<b>foo[bar]baz</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SI',
|
||||
'rte1-id': 'q-bold-2',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<strong>foo[bar]baz</strong>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SI',
|
||||
'rte1-id': 'q-bold-3',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<span style="font-weight: bold">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:n-1_SI',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_Bs:fw:n-1_SI',
|
||||
'rte1-id': 'q-bold-4',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_B-SPANs:fw:n-1_SI',
|
||||
'rte1-id': 'q-bold-5',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<b><span style="font-weight: normal">foo[bar]baz</span></b>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_SPAN.b-1-SI',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<span class="b">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_MYB-1-SI',
|
||||
'desc': 'query the "bold" state',
|
||||
'pad': '<myb>foo[bar]baz</myb>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B-I-1_SC',
|
||||
'desc': 'query the "bold" state, bold tag not immediate parent',
|
||||
'pad': '<b>foo<i>ba^r</i>baz</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B-I-1_SL',
|
||||
'desc': 'query the "bold" state, selection partially in child element',
|
||||
'pad': '<b>fo[o<i>b]ar</i>baz</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B-I-1_SR',
|
||||
'desc': 'query the "bold" state, selection partially in child element',
|
||||
'pad': '<b>foo<i>ba[r</i>b]az</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_STRONG-I-1_SC',
|
||||
'desc': 'query the "bold" state, bold tag not immediate parent',
|
||||
'pad': '<strong>foo<i>ba^r</i>baz</strong>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B-I-U-1_SC',
|
||||
'desc': 'query the "bold" state, bold tag not immediate parent',
|
||||
'pad': '<b>foo<i>bar<u>b^az</u></i></strong>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B-I-U-1_SM',
|
||||
'desc': 'query the "bold" state, bold tag not immediate parent',
|
||||
'pad': '<b>foo<i>ba[r<u>b]az</u></i></strong>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_TEXT-B-1_SO-1',
|
||||
'desc': 'query the "bold" state, selection wrapping the bold tag',
|
||||
'pad': 'foo[<b>bar</b>]baz',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_TEXT-B-1_SO-2',
|
||||
'desc': 'query the "bold" state, selection wrapping the bold tag',
|
||||
'pad': 'foo{<b>bar</b>}baz',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_TEXT-B-1_SL',
|
||||
'desc': 'query the "bold" state, selection containing non-bold text',
|
||||
'pad': 'fo[o<b>ba]r</b>baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_TEXT-B-1_SR',
|
||||
'desc': 'query the "bold" state, selection containing non-bold text',
|
||||
'pad': 'foo<b>b[ar</b>b]az',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_TEXT-B-1_SO-3',
|
||||
'desc': 'query the "bold" state, selection containing non-bold text',
|
||||
'pad': 'fo[o<b>bar</b>b]az',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_B.TEXT.B-1_SM',
|
||||
'desc': 'query the "bold" state, selection including non-bold text',
|
||||
'pad': '<b>fo[o</b>bar<b>b]az</b>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'B_B.B.B-1_SM',
|
||||
'desc': 'query the "bold" state, selection mixed, but all bold',
|
||||
'pad': '<b>fo[o</b><b>bar</b><b>b]az</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_B.STRONG.B-1_SM',
|
||||
'desc': 'query the "bold" state, selection mixed, but all bold',
|
||||
'pad': '<b>fo[o</b><strong>bar</strong><b>b]az</b>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'B_SPAN.b.MYB.SPANs:fw:b-1_SM',
|
||||
'desc': 'query the "bold" state, selection mixed, but all bold',
|
||||
'pad': '<span class="b">fo[o</span><myb>bar</myb><span style="font-weight: bold">b]az</span>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query italic state',
|
||||
'qcstate': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_TEXT_SI',
|
||||
'rte1-id': 'q-italic-0',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'I_I-1_SI',
|
||||
'rte1-id': 'q-italic-1',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<i>foo[bar]baz</i>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'I_EM-1_SI',
|
||||
'rte1-id': 'q-italic-2',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<em>foo[bar]baz</em>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SI',
|
||||
'rte1-id': 'q-italic-3',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<span style="font-style: italic">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:n-1_SI',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<span style="font-style: normal">foo[bar]baz</span>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'I_I-SPANs:fs:n-1_SI',
|
||||
'rte1-id': 'q-italic-4',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<i><span style="font-style: normal">foo[bar]baz</span></i>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'I_SPAN.i-1-SI',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<span class="i">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'I_MYI-1-SI',
|
||||
'desc': 'query the "italic" state',
|
||||
'pad': '<myi>foo[bar]baz</myi>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query underline state',
|
||||
'qcstate': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_TEXT_SI',
|
||||
'rte1-id': 'q-underline-0',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'U_U-1_SI',
|
||||
'rte1-id': 'q-underline-1',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<u>foo[bar]baz</u>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'U_Us:td:n-1_SI',
|
||||
'rte1-id': 'q-underline-4',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<u style="text-decoration: none">foo[bar]baz</u>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'U_Ah:url-1_SI',
|
||||
'rte1-id': 'q-underline-2',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<a href="http://www.goo.gl">foo[bar]baz</a>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'U_Ah:url.s:td:n-1_SI',
|
||||
'rte1-id': 'q-underline-5',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<a href="http://www.goo.gl" style="text-decoration: none">foo[bar]baz</a>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SI',
|
||||
'rte1-id': 'q-underline-3',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<span style="text-decoration: underline">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'U_SPAN.u-1-SI',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<span class="u">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'U_MYU-1-SI',
|
||||
'desc': 'query the "underline" state',
|
||||
'pad': '<myu>foo[bar]baz</myu>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query strike-through state',
|
||||
'qcstate': 'strikethrough',
|
||||
'tests': [
|
||||
{ 'id': 'S_TEXT_SI',
|
||||
'rte1-id': 'q-strikethrough-0',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'S_S-1_SI',
|
||||
'rte1-id': 'q-strikethrough-3',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<s>foo[bar]baz</s>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SI',
|
||||
'rte1-id': 'q-strikethrough-1',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<strike>foo[bar]baz</strike>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_STRIKEs:td:n-1_SI',
|
||||
'rte1-id': 'q-strikethrough-2',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<strike style="text-decoration: none">foo[bar]baz</strike>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'S_DEL-1_SI',
|
||||
'rte1-id': 'q-strikethrough-4',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<del>foo[bar]baz</del>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SI',
|
||||
'rte1-id': 'q-strikethrough-5',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<span style="text-decoration: line-through">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_SPAN.s-1-SI',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<span class="s">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_MYS-1-SI',
|
||||
'desc': 'query the "strikethrough" state',
|
||||
'pad': '<mys>foo[bar]baz</mys>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'S_S.STRIKE.DEL-1_SM',
|
||||
'desc': 'query the "strikethrough" state, selection mixed, but all struck',
|
||||
'pad': '<s>fo[o</s><strike>bar</strike><del>b]az</del>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query subscript state',
|
||||
'qcstate': 'subscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUB_TEXT_SI',
|
||||
'rte1-id': 'q-subscript-0',
|
||||
'desc': 'query the "subscript" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'SUB_SUB-1_SI',
|
||||
'rte1-id': 'q-subscript-1',
|
||||
'desc': 'query the "subscript" state',
|
||||
'pad': '<sub>foo[bar]baz</sub>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'SUB_SPAN.sub-1-SI',
|
||||
'desc': 'query the "subscript" state',
|
||||
'pad': '<span class="sub">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'SUB_MYSUB-1-SI',
|
||||
'desc': 'query the "subscript" state',
|
||||
'pad': '<mysub>foo[bar]baz</mysub>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query superscript state',
|
||||
'qcstate': 'superscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUP_TEXT_SI',
|
||||
'rte1-id': 'q-superscript-0',
|
||||
'desc': 'query the "superscript" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'SUP_SUP-1_SI',
|
||||
'rte1-id': 'q-superscript-1',
|
||||
'desc': 'query the "superscript" state',
|
||||
'pad': '<sup>foo[bar]baz</sup>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'IOL_TEXT_SI',
|
||||
'desc': 'query the "insertorderedlist" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'SUP_SPAN.sup-1-SI',
|
||||
'desc': 'query the "superscript" state',
|
||||
'pad': '<span class="sup">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'SUP_MYSUP-1-SI',
|
||||
'desc': 'query the "superscript" state',
|
||||
'pad': '<mysup>foo[bar]baz</mysup>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the selection is in an ordered list',
|
||||
'qcstate': 'insertorderedlist',
|
||||
'tests': [
|
||||
{ 'id': 'IOL_TEXT-1_SI',
|
||||
'rte1-id': 'q-insertorderedlist-0',
|
||||
'desc': 'query the "insertorderedlist" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'IOL_OL-LI-1_SI',
|
||||
'rte1-id': 'q-insertorderedlist-1',
|
||||
'desc': 'query the "insertorderedlist" state',
|
||||
'pad': '<ol><li>foo[bar]baz</li></ol>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'IOL_UL_LI-1_SI',
|
||||
'rte1-id': 'q-insertorderedlist-2',
|
||||
'desc': 'query the "insertorderedlist" state',
|
||||
'pad': '<ul><li>foo[bar]baz</li></ul>',
|
||||
'expected': False }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the selection is in an unordered list',
|
||||
'qcstate': 'insertunorderedlist',
|
||||
'tests': [
|
||||
{ 'id': 'IUL_TEXT_SI',
|
||||
'rte1-id': 'q-insertunorderedlist-0',
|
||||
'desc': 'query the "insertunorderedlist" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'IUL_OL-LI-1_SI',
|
||||
'rte1-id': 'q-insertunorderedlist-1',
|
||||
'desc': 'query the "insertunorderedlist" state',
|
||||
'pad': '<ol><li>foo[bar]baz</li></ol>',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'IUL_UL-LI-1_SI',
|
||||
'rte1-id': 'q-insertunorderedlist-2',
|
||||
'desc': 'query the "insertunorderedlist" state',
|
||||
'pad': '<ul><li>foo[bar]baz</li></ul>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the paragraph is centered',
|
||||
'qcstate': 'justifycenter',
|
||||
'tests': [
|
||||
{ 'id': 'JC_TEXT_SI',
|
||||
'rte1-id': 'q-justifycenter-0',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'JC_DIVa:c-1_SI',
|
||||
'rte1-id': 'q-justifycenter-1',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': '<div align="center">foo[bar]baz</div>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JC_Pa:c-1_SI',
|
||||
'rte1-id': 'q-justifycenter-2',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': '<p align="center">foo[bar]baz</p>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JC_SPANs:ta:c-1_SI',
|
||||
'rte1-id': 'q-justifycenter-3',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': '<div style="text-align: center">foo[bar]baz</div>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JC_SPAN.jc-1-SI',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': '<span class="jc">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JC_MYJC-1-SI',
|
||||
'desc': 'query the "justifycenter" state',
|
||||
'pad': '<myjc>foo[bar]baz</myjc>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the paragraph is justified',
|
||||
'qcstate': 'justifyfull',
|
||||
'tests': [
|
||||
{ 'id': 'JF_TEXT_SI',
|
||||
'rte1-id': 'q-justifyfull-0',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'JF_DIVa:j-1_SI',
|
||||
'rte1-id': 'q-justifyfull-1',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': '<div align="justify">foo[bar]baz</div>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JF_Pa:j-1_SI',
|
||||
'rte1-id': 'q-justifyfull-2',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': '<p align="justify">foo[bar]baz</p>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JF_SPANs:ta:j-1_SI',
|
||||
'rte1-id': 'q-justifyfull-3',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': '<span style="text-align: justify">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JF_SPAN.jf-1-SI',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': '<span class="jf">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JF_MYJF-1-SI',
|
||||
'desc': 'query the "justifyfull" state',
|
||||
'pad': '<myjf>foo[bar]baz</myjf>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the paragraph is aligned left',
|
||||
'qcstate': 'justifyleft',
|
||||
'tests': [
|
||||
{ 'id': 'JL_TEXT_SI',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'JL_DIVa:l-1_SI',
|
||||
'rte1-id': 'q-justifyleft-0',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': '<div align="left">foo[bar]baz</div>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JL_Pa:l-1_SI',
|
||||
'rte1-id': 'q-justifyleft-1',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': '<p align="left">foo[bar]baz</p>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JL_SPANs:ta:l-1_SI',
|
||||
'rte1-id': 'q-justifyleft-2',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': '<span style="text-align: left">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JL_SPAN.jl-1-SI',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': '<span class="jl">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JL_MYJL-1-SI',
|
||||
'desc': 'query the "justifyleft" state',
|
||||
'pad': '<myjl>foo[bar]baz</myjl>',
|
||||
'expected': True }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'query whether the paragraph is aligned right',
|
||||
'qcstate': 'justifyright',
|
||||
'tests': [
|
||||
{ 'id': 'JR_TEXT_SI',
|
||||
'rte1-id': 'q-justifyright-0',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': False },
|
||||
|
||||
{ 'id': 'JR_DIVa:r-1_SI',
|
||||
'rte1-id': 'q-justifyright-1',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': '<div align="right">foo[bar]baz</div>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JR_Pa:r-1_SI',
|
||||
'rte1-id': 'q-justifyright-2',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': '<p align="right">foo[bar]baz</p>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JR_SPANs:ta:r-1_SI',
|
||||
'rte1-id': 'q-justifyright-3',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': '<span style="text-align: right">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JR_SPAN.jr-1-SI',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': '<span class="jr">foo[bar]baz</span>',
|
||||
'expected': True },
|
||||
|
||||
{ 'id': 'JR_MYJR-1-SI',
|
||||
'desc': 'query the "justifyright" state',
|
||||
'pad': '<myjr>foo[bar]baz</myjr>',
|
||||
'expected': True }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
QUERYSTATE_TESTS_CSS = {
|
||||
'id': 'QSC',
|
||||
'caption': 'queryCommandState Tests, using styleWithCSS',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': True,
|
||||
|
||||
'Proposed': QUERYSTATE_TESTS['Proposed']
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
|
||||
QUERYSUPPORTED_TESTS = {
|
||||
'id': 'Q',
|
||||
'caption': 'queryCommandSupported Tests',
|
||||
'pad': 'foo[bar]baz',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': False,
|
||||
'expected': True,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'HTML5 commands',
|
||||
'tests': [
|
||||
{ 'id': 'SELECTALL_TEXT-1',
|
||||
'desc': 'check whether the "selectall" command is supported',
|
||||
'qcsupported': 'selectall' },
|
||||
|
||||
{ 'id': 'UNSELECT_TEXT-1',
|
||||
'desc': 'check whether the "unselect" command is supported',
|
||||
'qcsupported': 'unselect' },
|
||||
|
||||
{ 'id': 'UNDO_TEXT-1',
|
||||
'desc': 'check whether the "undo" command is supported',
|
||||
'qcsupported': 'undo' },
|
||||
|
||||
{ 'id': 'REDO_TEXT-1',
|
||||
'desc': 'check whether the "redo" command is supported',
|
||||
'qcsupported': 'redo' },
|
||||
|
||||
{ 'id': 'BOLD_TEXT-1',
|
||||
'desc': 'check whether the "bold" command is supported',
|
||||
'qcsupported': 'bold' },
|
||||
|
||||
{ 'id': 'BOLD_B',
|
||||
'desc': 'check whether the "bold" command is supported',
|
||||
'qcsupported': 'bold',
|
||||
'pad': '<b>foo[bar]baz</b>' },
|
||||
|
||||
{ 'id': 'ITALIC_TEXT-1',
|
||||
'desc': 'check whether the "italic" command is supported',
|
||||
'qcsupported': 'italic' },
|
||||
|
||||
{ 'id': 'ITALIC_I',
|
||||
'desc': 'check whether the "italic" command is supported',
|
||||
'qcsupported': 'italic',
|
||||
'pad': '<i>foo[bar]baz</i>' },
|
||||
|
||||
{ 'id': 'UNDERLINE_TEXT-1',
|
||||
'desc': 'check whether the "underline" command is supported',
|
||||
'qcsupported': 'underline' },
|
||||
|
||||
{ 'id': 'STRIKETHROUGH_TEXT-1',
|
||||
'desc': 'check whether the "strikethrough" command is supported',
|
||||
'qcsupported': 'strikethrough' },
|
||||
|
||||
{ 'id': 'SUBSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "subscript" command is supported',
|
||||
'qcsupported': 'subscript' },
|
||||
|
||||
{ 'id': 'SUPERSCRIPT_TEXT-1',
|
||||
'desc': 'check whether the "superscript" command is supported',
|
||||
'qcsupported': 'superscript' },
|
||||
|
||||
{ 'id': 'FORMATBLOCK_TEXT-1',
|
||||
'desc': 'check whether the "formatblock" command is supported',
|
||||
'qcsupported': 'formatblock' },
|
||||
|
||||
{ 'id': 'CREATELINK_TEXT-1',
|
||||
'desc': 'check whether the "createlink" command is supported',
|
||||
'qcsupported': 'createlink' },
|
||||
|
||||
{ 'id': 'UNLINK_TEXT-1',
|
||||
'desc': 'check whether the "unlink" command is supported',
|
||||
'qcsupported': 'unlink' },
|
||||
|
||||
{ 'id': 'INSERTHTML_TEXT-1',
|
||||
'desc': 'check whether the "inserthtml" command is supported',
|
||||
'qcsupported': 'inserthtml' },
|
||||
|
||||
{ 'id': 'INSERTHORIZONTALRULE_TEXT-1',
|
||||
'desc': 'check whether the "inserthorizontalrule" command is supported',
|
||||
'qcsupported': 'inserthorizontalrule' },
|
||||
|
||||
{ 'id': 'INSERTIMAGE_TEXT-1',
|
||||
'desc': 'check whether the "insertimage" command is supported',
|
||||
'qcsupported': 'insertimage' },
|
||||
|
||||
{ 'id': 'INSERTLINEBREAK_TEXT-1',
|
||||
'desc': 'check whether the "insertlinebreak" command is supported',
|
||||
'qcsupported': 'insertlinebreak' },
|
||||
|
||||
{ 'id': 'INSERTPARAGRAPH_TEXT-1',
|
||||
'desc': 'check whether the "insertparagraph" command is supported',
|
||||
'qcsupported': 'insertparagraph' },
|
||||
|
||||
{ 'id': 'INSERTORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertorderedlist" command is supported',
|
||||
'qcsupported': 'insertorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTUNORDEREDLIST_TEXT-1',
|
||||
'desc': 'check whether the "insertunorderedlist" command is supported',
|
||||
'qcsupported': 'insertunorderedlist' },
|
||||
|
||||
{ 'id': 'INSERTTEXT_TEXT-1',
|
||||
'desc': 'check whether the "inserttext" command is supported',
|
||||
'qcsupported': 'inserttext' },
|
||||
|
||||
{ 'id': 'DELETE_TEXT-1',
|
||||
'desc': 'check whether the "delete" command is supported',
|
||||
'qcsupported': 'delete' },
|
||||
|
||||
{ 'id': 'FORWARDDELETE_TEXT-1',
|
||||
'desc': 'check whether the "forwarddelete" command is supported',
|
||||
'qcsupported': 'forwarddelete' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'MIDAS commands',
|
||||
'tests': [
|
||||
{ 'id': 'STYLEWITHCSS_TEXT-1',
|
||||
'desc': 'check whether the "styleWithCSS" command is supported',
|
||||
'qcsupported': 'styleWithCSS' },
|
||||
|
||||
{ 'id': 'CONTENTREADONLY_TEXT-1',
|
||||
'desc': 'check whether the "contentreadonly" command is supported',
|
||||
'qcsupported': 'contentreadonly' },
|
||||
|
||||
{ 'id': 'BACKCOLOR_TEXT-1',
|
||||
'desc': 'check whether the "backcolor" command is supported',
|
||||
'qcsupported': 'backcolor' },
|
||||
|
||||
{ 'id': 'FORECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "forecolor" command is supported',
|
||||
'qcsupported': 'forecolor' },
|
||||
|
||||
{ 'id': 'HILITECOLOR_TEXT-1',
|
||||
'desc': 'check whether the "hilitecolor" command is supported',
|
||||
'qcsupported': 'hilitecolor' },
|
||||
|
||||
{ 'id': 'FONTNAME_TEXT-1',
|
||||
'desc': 'check whether the "fontname" command is supported',
|
||||
'qcsupported': 'fontname' },
|
||||
|
||||
{ 'id': 'FONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "fontsize" command is supported',
|
||||
'qcsupported': 'fontsize' },
|
||||
|
||||
{ 'id': 'INCREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "increasefontsize" command is supported',
|
||||
'qcsupported': 'increasefontsize' },
|
||||
|
||||
{ 'id': 'DECREASEFONTSIZE_TEXT-1',
|
||||
'desc': 'check whether the "decreasefontsize" command is supported',
|
||||
'qcsupported': 'decreasefontsize' },
|
||||
|
||||
{ 'id': 'HEADING_TEXT-1',
|
||||
'desc': 'check whether the "heading" command is supported',
|
||||
'qcsupported': 'heading' },
|
||||
|
||||
{ 'id': 'INDENT_TEXT-1',
|
||||
'desc': 'check whether the "indent" command is supported',
|
||||
'qcsupported': 'indent' },
|
||||
|
||||
{ 'id': 'OUTDENT_TEXT-1',
|
||||
'desc': 'check whether the "outdent" command is supported',
|
||||
'qcsupported': 'outdent' },
|
||||
|
||||
{ 'id': 'CREATEBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "createbookmark" command is supported',
|
||||
'qcsupported': 'createbookmark' },
|
||||
|
||||
{ 'id': 'UNBOOKMARK_TEXT-1',
|
||||
'desc': 'check whether the "unbookmark" command is supported',
|
||||
'qcsupported': 'unbookmark' },
|
||||
|
||||
{ 'id': 'JUSTIFYCENTER_TEXT-1',
|
||||
'desc': 'check whether the "justifycenter" command is supported',
|
||||
'qcsupported': 'justifycenter' },
|
||||
|
||||
{ 'id': 'JUSTIFYFULL_TEXT-1',
|
||||
'desc': 'check whether the "justifyfull" command is supported',
|
||||
'qcsupported': 'justifyfull' },
|
||||
|
||||
{ 'id': 'JUSTIFYLEFT_TEXT-1',
|
||||
'desc': 'check whether the "justifyleft" command is supported',
|
||||
'qcsupported': 'justifyleft' },
|
||||
|
||||
{ 'id': 'JUSTIFYRIGHT_TEXT-1',
|
||||
'desc': 'check whether the "justifyright" command is supported',
|
||||
'qcsupported': 'justifyright' },
|
||||
|
||||
{ 'id': 'REMOVEFORMAT_TEXT-1',
|
||||
'desc': 'check whether the "removeformat" command is supported',
|
||||
'qcsupported': 'removeformat' },
|
||||
|
||||
{ 'id': 'COPY_TEXT-1',
|
||||
'desc': 'check whether the "copy" command is supported',
|
||||
'qcsupported': 'copy' },
|
||||
|
||||
{ 'id': 'CUT_TEXT-1',
|
||||
'desc': 'check whether the "cut" command is supported',
|
||||
'qcsupported': 'cut' },
|
||||
|
||||
{ 'id': 'PASTE_TEXT-1',
|
||||
'desc': 'check whether the "paste" command is supported',
|
||||
'qcsupported': 'paste' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'Other tests',
|
||||
'tests': [
|
||||
{ 'id': 'garbage-1_TEXT-1',
|
||||
'desc': 'check correct return value with garbage input',
|
||||
'qcsupported': '#!#@7',
|
||||
'expected': False }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,429 @@
|
|||
|
||||
QUERYVALUE_TESTS = {
|
||||
'id': 'QV',
|
||||
'caption': 'queryCommandValue Tests',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] query bold value',
|
||||
'qcvalue': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_TEXT_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'B_B-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<b>foo[bar]baz</b>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<strong>foo[bar]baz</strong>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<span style="font-weight: bold">foo[bar]baz</span>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:n-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<span style="font-weight: normal">foo[bar]baz</span>',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'B_Bs:fw:n-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<b><span style="font-weight: normal">foo[bar]baz</span></b>',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'B_SPAN.b-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<span class="b">foo[bar]baz</span>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'B_MYB-1-SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<myb>foo[bar]baz</myb>',
|
||||
'expected': 'true' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] query italic value',
|
||||
'qcvalue': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_TEXT_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': 'foo[bar]baz',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'I_I-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<i>foo[bar]baz</i>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'I_EM-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<em>foo[bar]baz</em>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<span style="font-style: italic">foo[bar]baz</span>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:n-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<span style="font-style: normal">foo[bar]baz</span>',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'I_I-SPANs:fs:n-1_SI',
|
||||
'desc': 'query the "bold" value',
|
||||
'pad': '<i><span style="font-style: normal">foo[bar]baz</span></i>',
|
||||
'expected': 'false' },
|
||||
|
||||
{ 'id': 'I_SPAN.i-1_SI',
|
||||
'desc': 'query the "italic" value',
|
||||
'pad': '<span class="i">foo[bar]baz</span>',
|
||||
'expected': 'true' },
|
||||
|
||||
{ 'id': 'I_MYI-1-SI',
|
||||
'desc': 'query the "italic" value',
|
||||
'pad': '<myi>foo[bar]baz</myi>',
|
||||
'expected': 'true' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[HTML5] query block formatting value',
|
||||
'qcvalue': 'formatblock',
|
||||
'tests': [
|
||||
{ 'id': 'FB_TEXT-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': 'foobar^baz',
|
||||
'expected': '',
|
||||
'accept': 'normal' },
|
||||
|
||||
{ 'id': 'FB_H1-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': '<h1>foobar^baz</h1>',
|
||||
'expected': 'h1' },
|
||||
|
||||
{ 'id': 'FB_PRE-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': '<pre>foobar^baz</pre>',
|
||||
'expected': 'pre' },
|
||||
|
||||
{ 'id': 'FB_BQ-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': '<blockquote>foobar^baz</blockquote>',
|
||||
'expected': 'blockquote' },
|
||||
|
||||
{ 'id': 'FB_ADDRESS-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': '<address>foobar^baz</address>',
|
||||
'expected': 'address' },
|
||||
|
||||
{ 'id': 'FB_H1-H2-1_SC',
|
||||
'desc': 'query the "formatBlock" value',
|
||||
'pad': '<h1>foo<h2>ba^r</h2>baz</h1>',
|
||||
'expected': 'h2' },
|
||||
|
||||
{ 'id': 'FB_H1-H2-1_SL',
|
||||
'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
|
||||
'pad': '<h1>fo[o<h2>ba]r</h2>baz</h1>',
|
||||
'expected': 'h1' },
|
||||
|
||||
{ 'id': 'FB_H1-H2-1_SR',
|
||||
'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
|
||||
'pad': '<h1>foo<h2>b[ar</h2>ba]z</h1>',
|
||||
'expected': 'h1' },
|
||||
|
||||
{ 'id': 'FB_TEXT-ADDRESS-1_SL',
|
||||
'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
|
||||
'pad': 'fo[o<ADDRESS>ba]r</ADDRESS>baz',
|
||||
'expected': '',
|
||||
'accept': 'normal' },
|
||||
|
||||
{ 'id': 'FB_TEXT-ADDRESS-1_SR',
|
||||
'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
|
||||
'pad': 'foo<ADDRESS>b[ar</ADDRESS>ba]z',
|
||||
'expected': '',
|
||||
'accept': 'normal' },
|
||||
|
||||
{ 'id': 'FB_H1-H2.TEXT.H2-1_SM',
|
||||
'desc': 'query the "formatBlock" value on oblique selection (outermost formatting expected)',
|
||||
'pad': '<h1><h2>fo[o</h2>bar<h2>b]az</h2></h1>',
|
||||
'expected': 'h1' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query heading type',
|
||||
'qcvalue': 'heading',
|
||||
'tests': [
|
||||
{ 'id': 'H_H1-1_SC',
|
||||
'desc': 'query the "heading" type',
|
||||
'pad': '<h1>foobar^baz</h1>',
|
||||
'expected': 'h1',
|
||||
'accept': '<h1>' },
|
||||
|
||||
{ 'id': 'H_H3-1_SC',
|
||||
'desc': 'query the "heading" type',
|
||||
'pad': '<h3>foobar^baz</h3>',
|
||||
'expected': 'h3',
|
||||
'accept': '<h3>' },
|
||||
|
||||
{ 'id': 'H_H1-H2-H3-H4-1_SC',
|
||||
'desc': 'query the "heading" type within nested heading tags',
|
||||
'pad': '<h1><h2><h3><h4>foobar^baz</h4></h3></h2></h1>',
|
||||
'expected': 'h4',
|
||||
'accept': '<h4>' },
|
||||
|
||||
{ 'id': 'H_P-1_SC',
|
||||
'desc': 'query the "heading" type outside of a heading',
|
||||
'pad': '<p>foobar^baz</p>',
|
||||
'expected': '' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query font name',
|
||||
'qcvalue': 'fontname',
|
||||
'tests': [
|
||||
{ 'id': 'FN_FONTf:a-1_SI',
|
||||
'rte1-id': 'q-fontname-0',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<font face="arial">foo[bar]baz</font>',
|
||||
'expected': 'arial' },
|
||||
|
||||
{ 'id': 'FN_SPANs:ff:a-1_SI',
|
||||
'rte1-id': 'q-fontname-1',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<span style="font-family: arial">foo[bar]baz</span>',
|
||||
'expected': 'arial' },
|
||||
|
||||
{ 'id': 'FN_FONTf:a.s:ff:c-1_SI',
|
||||
'rte1-id': 'q-fontname-2',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<font face="arial" style="font-family: courier">foo[bar]baz</font>',
|
||||
'expected': 'courier' },
|
||||
|
||||
{ 'id': 'FN_FONTf:a-FONTf:c-1_SI',
|
||||
'rte1-id': 'q-fontname-3',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<font face="arial"><font face="courier">foo[bar]baz</font></font>',
|
||||
'expected': 'courier' },
|
||||
|
||||
{ 'id': 'FN_SPANs:ff:c-FONTf:a-1_SI',
|
||||
'rte1-id': 'q-fontname-4',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<span style="font-family: courier"><font face="arial">foo[bar]baz</font></span>',
|
||||
'expected': 'arial' },
|
||||
|
||||
{ 'id': 'FN_SPAN.fs18px-1_SI',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<span class="courier">foo[bar]baz</span>',
|
||||
'expected': 'courier' },
|
||||
|
||||
{ 'id': 'FN_MYCOURIER-1-SI',
|
||||
'desc': 'query the "fontname" value',
|
||||
'pad': '<mycourier>foo[bar]baz</mycourier>',
|
||||
'expected': 'courier' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query font size',
|
||||
'qcvalue': 'fontsize',
|
||||
'tests': [
|
||||
{ 'id': 'FS_FONTsz:4-1_SI',
|
||||
'rte1-id': 'q-fontsize-0',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<font size=4>foo[bar]baz</font>',
|
||||
'expected': '18px' },
|
||||
|
||||
{ 'id': 'FS_FONTs:fs:l-1_SI',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<font style="font-size: large">foo[bar]baz</font>',
|
||||
'expected': '18px' },
|
||||
|
||||
{ 'id': 'FS_FONT.ass.s:fs:l-1_SI',
|
||||
'rte1-id': 'q-fontsize-1',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<font class="Apple-style-span" style="font-size: large">foo[bar]baz</font>',
|
||||
'expected': '18px' },
|
||||
|
||||
{ 'id': 'FS_FONTsz:1.s:fs:xl-1_SI',
|
||||
'rte1-id': 'q-fontsize-2',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<font size=1 style="font-size: x-large">foo[bar]baz</font>',
|
||||
'expected': '24px' },
|
||||
|
||||
{ 'id': 'FS_SPAN.large-1_SI',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<span class="large">foo[bar]baz</span>',
|
||||
'expected': 'large' },
|
||||
|
||||
{ 'id': 'FS_SPAN.fs18px-1_SI',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<span class="fs18px">foo[bar]baz</span>',
|
||||
'expected': '18px' },
|
||||
|
||||
{ 'id': 'FA_MYLARGE-1-SI',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<mylarge>foo[bar]baz</mylarge>',
|
||||
'expected': 'large' },
|
||||
|
||||
{ 'id': 'FA_MYFS18PX-1-SI',
|
||||
'desc': 'query the "fontsize" value',
|
||||
'pad': '<myfs18px>foo[bar]baz</myfs18px>',
|
||||
'expected': '18px' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query background color',
|
||||
'qcvalue': 'backcolor',
|
||||
'tests': [
|
||||
{ 'id': 'BC_FONTs:bc:fca-1_SI',
|
||||
'rte1-id': 'q-backcolor-0',
|
||||
'desc': 'query the "backcolor" value',
|
||||
'pad': '<font style="background-color: #ffccaa">foo[bar]baz</font>',
|
||||
'expected': '#ffccaa' },
|
||||
|
||||
{ 'id': 'BC_SPANs:bc:abc-1_SI',
|
||||
'rte1-id': 'q-backcolor-2',
|
||||
'desc': 'query the "backcolor" value',
|
||||
'pad': '<span style="background-color: #aabbcc">foo[bar]baz</span>',
|
||||
'expected': '#aabbcc' },
|
||||
|
||||
{ 'id': 'BC_FONTs:bc:084-SPAN-1_SI',
|
||||
'desc': 'query the "backcolor" value, where the color was set on an ancestor',
|
||||
'pad': '<font style="background-color: #008844"><span>foo[bar]baz</span></font>',
|
||||
'expected': '#008844' },
|
||||
|
||||
{ 'id': 'BC_SPANs:bc:cde-SPAN-1_SI',
|
||||
'desc': 'query the "backcolor" value, where the color was set on an ancestor',
|
||||
'pad': '<span style="background-color: #ccddee"><span>foo[bar]baz</span></span>',
|
||||
'expected': '#ccddee' },
|
||||
|
||||
{ 'id': 'BC_SPAN.ass.s:bc:rgb-1_SI',
|
||||
'rte1-id': 'q-backcolor-1',
|
||||
'desc': 'query the "backcolor" value',
|
||||
'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">foo[bar]baz</span>',
|
||||
'expected': '#ff0000' },
|
||||
|
||||
{ 'id': 'BC_SPAN.bcred-1_SI',
|
||||
'desc': 'query the "backcolor" value',
|
||||
'pad': '<span class="bcred">foo[bar]baz</span>',
|
||||
'expected': 'red' },
|
||||
|
||||
{ 'id': 'BC_MYBCRED-1-SI',
|
||||
'desc': 'query the "backcolor" value',
|
||||
'pad': '<mybcred>foo[bar]baz</mybcred>',
|
||||
'expected': 'red' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query text color',
|
||||
'qcvalue': 'forecolor',
|
||||
'tests': [
|
||||
{ 'id': 'FC_FONTc:f00-1_SI',
|
||||
'rte1-id': 'q-forecolor-0',
|
||||
'desc': 'query the "forecolor" value',
|
||||
'pad': '<font color="#ff0000">foo[bar]baz</font>',
|
||||
'expected': '#ff0000' },
|
||||
|
||||
{ 'id': 'FC_SPANs:c:0f0-1_SI',
|
||||
'rte1-id': 'q-forecolor-1',
|
||||
'desc': 'query the "forecolor" value',
|
||||
'pad': '<span style="color: #00ff00">foo[bar]baz</span>',
|
||||
'expected': '#00ff00' },
|
||||
|
||||
{ 'id': 'FC_FONTc:333.s:c:999-1_SI',
|
||||
'rte1-id': 'q-forecolor-2',
|
||||
'desc': 'query the "forecolor" value',
|
||||
'pad': '<font color="#333333" style="color: #999999">foo[bar]baz</font>',
|
||||
'expected': '#999999' },
|
||||
|
||||
{ 'id': 'FC_FONTc:641-SPAN-1_SI',
|
||||
'desc': 'query the "forecolor" value, where the color was set on an ancestor',
|
||||
'pad': '<font color="#664411"><span>foo[bar]baz</span></font>',
|
||||
'expected': '#664411' },
|
||||
|
||||
{ 'id': 'FC_SPANs:c:d95-SPAN-1_SI',
|
||||
'desc': 'query the "forecolor" value, where the color was set on an ancestor',
|
||||
'pad': '<span style="color: #dd9955"><span>foo[bar]baz</span></span>',
|
||||
'expected': '#dd9955' },
|
||||
|
||||
{ 'id': 'FC_SPAN.red-1_SI',
|
||||
'desc': 'query the "forecolor" value',
|
||||
'pad': '<span class="red">foo[bar]baz</span>',
|
||||
'expected': 'red' },
|
||||
|
||||
{ 'id': 'FC_MYRED-1-SI',
|
||||
'desc': 'query the "forecolor" value',
|
||||
'pad': '<myred>foo[bar]baz</myred>',
|
||||
'expected': 'red' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': '[MIDAS] query hilight color (same as background color)',
|
||||
'qcvalue': 'hilitecolor',
|
||||
'tests': [
|
||||
{ 'id': 'HC_FONTs:bc:fc0-1_SI',
|
||||
'rte1-id': 'q-hilitecolor-0',
|
||||
'desc': 'query the "hilitecolor" value',
|
||||
'pad': '<font style="background-color: #ffcc00">foo[bar]baz</font>',
|
||||
'expected': '#ffcc00' },
|
||||
|
||||
{ 'id': 'HC_SPANs:bc:a0c-1_SI',
|
||||
'rte1-id': 'q-hilitecolor-2',
|
||||
'desc': 'query the "hilitecolor" value',
|
||||
'pad': '<span style="background-color: #aa00cc">foo[bar]baz</span>',
|
||||
'expected': '#aa00cc' },
|
||||
|
||||
{ 'id': 'HC_SPAN.ass.s:bc:rgb-1_SI',
|
||||
'rte1-id': 'q-hilitecolor-1',
|
||||
'desc': 'query the "hilitecolor" value',
|
||||
'pad': '<span class="Apple-style-span" style="background-color: rgb(255, 0, 0)">foo[bar]baz</span>',
|
||||
'expected': '#ff0000' },
|
||||
|
||||
{ 'id': 'HC_FONTs:bc:83e-SPAN-1_SI',
|
||||
'desc': 'query the "hilitecolor" value, where the color was set on an ancestor',
|
||||
'pad': '<font style="background-color: #8833ee"><span>foo[bar]baz</span></font>',
|
||||
'expected': '#8833ee' },
|
||||
|
||||
{ 'id': 'HC_SPANs:bc:b12-SPAN-1_SI',
|
||||
'desc': 'query the "hilitecolor" value, where the color was set on an ancestor',
|
||||
'pad': '<span style="background-color: #bb1122"><span>foo[bar]baz</span></span>',
|
||||
'expected': '#bb1122' },
|
||||
|
||||
{ 'id': 'HC_SPAN.bcred-1_SI',
|
||||
'desc': 'query the "hilitecolor" value',
|
||||
'pad': '<span class="bcred">foo[bar]baz</span>',
|
||||
'expected': 'red' },
|
||||
|
||||
{ 'id': 'HC_MYBCRED-1-SI',
|
||||
'desc': 'query the "hilitecolor" value',
|
||||
'pad': '<mybcred>foo[bar]baz</mybcred>',
|
||||
'expected': 'red' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
QUERYVALUE_TESTS_CSS = {
|
||||
'id': 'QVC',
|
||||
'caption': 'queryCommandValue Tests, using styleWithCSS',
|
||||
'checkAttrs': False,
|
||||
'checkStyle': False,
|
||||
'styleWithCSS': True,
|
||||
|
||||
'Proposed': QUERYVALUE_TESTS['Proposed']
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,772 @@
|
|||
|
||||
SELECTION_TESTS = {
|
||||
'id': 'S',
|
||||
'caption': 'Selection Tests',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': False,
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'selectall',
|
||||
'command': 'selectall',
|
||||
'tests': [
|
||||
{ 'id': 'SELALL_TEXT-1_SI',
|
||||
'desc': 'select all, text only',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': [ '[foo bar baz]',
|
||||
'{foo bar baz}' ] },
|
||||
|
||||
{ 'id': 'SELALL_I-1_SI',
|
||||
'desc': 'select all, with outer tags',
|
||||
'pad': '<i>foo [bar] baz</i>',
|
||||
'expected': '{<i>foo bar baz</i>}' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'unselect',
|
||||
'command': 'unselect',
|
||||
'tests': [
|
||||
{ 'id': 'UNSEL_TEXT-1_SI',
|
||||
'desc': 'unselect',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo bar baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify (generic)',
|
||||
'tests': [
|
||||
{ 'id': 'SM:m.f.c_TEXT-1_SC-1',
|
||||
'desc': 'move caret 1 character forward',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foo b^ar baz',
|
||||
'expected': 'foo ba^r baz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXT-1_SC-1',
|
||||
'desc': 'move caret 1 character backward',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo b^ar baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXT-1_SI-1',
|
||||
'desc': 'move caret forward (sollapse selection)',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo bar^ baz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXT-1_SI-1',
|
||||
'desc': 'move caret backward (collapse selection)',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-1_SC-1',
|
||||
'desc': 'move caret 1 word forward',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': 'foo b^ar baz',
|
||||
'expected': 'foo bar^ baz' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-1_SC-2',
|
||||
'desc': 'move caret 1 word forward',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': 'foo^ bar baz',
|
||||
'expected': 'foo bar^ baz' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-1_SI-1',
|
||||
'desc': 'move caret 1 word forward from non-collapsed selection',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo bar baz^' },
|
||||
|
||||
{ 'id': 'SM:m.b.w_TEXT-1_SC-1',
|
||||
'desc': 'move caret 1 word backward',
|
||||
'function': 'sel.modify("move", "backward", "word");',
|
||||
'pad': 'foo b^ar baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:m.b.w_TEXT-1_SC-3',
|
||||
'desc': 'move caret 1 word backward',
|
||||
'function': 'sel.modify("move", "backward", "word");',
|
||||
'pad': 'foo bar ^baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:m.b.w_TEXT-1_SI-1',
|
||||
'desc': 'move caret 1 word backward from non-collapsed selection',
|
||||
'function': 'sel.modify("move", "backward", "word");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': '^foo bar baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: move forward over combining diacritics, etc.',
|
||||
'tests': [
|
||||
{ 'id': 'SM:m.f.c_CHAR-2_SC-1',
|
||||
'desc': 'move 1 character forward over combined o with diaeresis',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^öbarbaz',
|
||||
'expected': 'foö^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-3_SC-1',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^öbarbaz',
|
||||
'expected': 'foö^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-4_SC-1',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis below',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^o̤barbaz',
|
||||
'expected': 'foo̤^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-5_SC-1',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above and below',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^ö̤barbaz',
|
||||
'expected': 'foö̤^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-5_SI-1',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis above',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foo[̈]̤barbaz',
|
||||
'expected': 'foö̤^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-5_SI-2',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above and below, selection on diaeresis below',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foö[̤]barbaz',
|
||||
'expected': 'foö̤^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-5_SL',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo[ö]̤barbaz',
|
||||
'expected': 'foö̤^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-5_SR',
|
||||
'desc': 'move 1 character forward over character with combining diaeresis above and below, selection oblique on diaeresis and following text',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foö[̤bar]baz',
|
||||
'expected': 'foö̤bar^baz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-6_SC-1',
|
||||
'desc': 'move 1 character forward over character with enclosing square',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^o⃞barbaz',
|
||||
'expected': 'foo⃞^barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_CHAR-7_SC-1',
|
||||
'desc': 'move 1 character forward over character with combining long solidus overlay',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'fo^o̸barbaz',
|
||||
'expected': 'foo̸^barbaz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: move backward over combining diacritics, etc.',
|
||||
'tests': [
|
||||
{ 'id': 'SM:m.b.c_CHAR-2_SC-1',
|
||||
'desc': 'move 1 character backward over combined o with diaeresis',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foö^barbaz',
|
||||
'expected': 'fo^öbarbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-3_SC-1',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foö^barbaz',
|
||||
'expected': 'fo^öbarbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-4_SC-1',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis below',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo̤^barbaz',
|
||||
'expected': 'fo^o̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-5_SC-1',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above and below',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foö̤^barbaz',
|
||||
'expected': 'fo^ö̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-5_SI-1',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis above',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo[̈]̤barbaz',
|
||||
'expected': 'fo^ö̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-5_SI-2',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above and below, selection on diaeresis below',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foö[̤]barbaz',
|
||||
'expected': 'fo^ö̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-5_SL',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and preceding text',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'fo[ö]̤barbaz',
|
||||
'expected': 'fo^ö̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-5_SR',
|
||||
'desc': 'move 1 character backward over character with combining diaeresis above and below, selection oblique on diaeresis and following text',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foö[̤bar]baz',
|
||||
'expected': 'fo^ö̤barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-6_SC-1',
|
||||
'desc': 'move 1 character backward over character with enclosing square',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo⃞^barbaz',
|
||||
'expected': 'fo^o⃞barbaz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_CHAR-7_SC-1',
|
||||
'desc': 'move 1 character backward over character with combining long solidus overlay',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo̸^barbaz',
|
||||
'expected': 'fo^o̸barbaz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: move forward/backward/left/right in RTL text',
|
||||
'tests': [
|
||||
{ 'id': 'SM:m.f.c_Pdir:rtl-1_SC-1',
|
||||
'desc': 'move caret forward 1 character in right-to-left text',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': '<p dir="rtl">foo b^ar baz</p>',
|
||||
'expected': '<p dir="rtl">foo ba^r baz</p>' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_Pdir:rtl-1_SC-1',
|
||||
'desc': 'move caret backward 1 character in right-to-left text',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': '<p dir="rtl">foo ba^r baz</p>',
|
||||
'expected': '<p dir="rtl">foo b^ar baz</p>' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_Pdir:rtl-1_SC-1',
|
||||
'desc': 'move caret 1 character to the right in LTR text within RTL context',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': '<p dir="rtl">foo b^ar baz</p>',
|
||||
'expected': '<p dir="rtl">foo ba^r baz</p>' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_Pdir:rtl-1_SC-1',
|
||||
'desc': 'move caret 1 character to the left in LTR text within RTL context',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': '<p dir="rtl">foo ba^r baz</p>',
|
||||
'expected': '<p dir="rtl">foo b^ar baz</p>' },
|
||||
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXT:ar-1_SC-1',
|
||||
'desc': 'move caret forward 1 character in Arabic text',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'مرح^با العالم',
|
||||
'expected': 'مرحب^ا العالم' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXT:ar-1_SC-1',
|
||||
'desc': 'move caret backward 1 character in Arabic text',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'مرح^با العالم',
|
||||
'expected': 'مر^حبا العالم' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXT:he-1_SC-1',
|
||||
'desc': 'move caret forward 1 character in Hebrew text',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'של^ום עולם',
|
||||
'expected': 'שלו^ם עולם' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXT:he-1_SC-1',
|
||||
'desc': 'move caret backward 1 character in Hebrew text',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'של^ום עולם',
|
||||
'expected': 'ש^לום עולם' },
|
||||
|
||||
|
||||
{ 'id': 'SM:m.f.c_BDOdir:rtl-1_SC-1',
|
||||
'desc': 'move caret forward 1 character inside <bdo>',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'foo <bdo dir="rtl">b^ar</bdo> baz',
|
||||
'expected': 'foo <bdo dir="rtl">ba^r</bdo> baz' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_BDOdir:rtl-1_SC-1',
|
||||
'desc': 'move caret backward 1 character inside <bdo>',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'foo <bdo dir="rtl">ba^r</bdo> baz',
|
||||
'expected': 'foo <bdo dir="rtl">b^ar</bdo> baz' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_BDOdir:rtl-1_SC-1',
|
||||
'desc': 'move caret 1 character to the right inside <bdo>',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'foo <bdo dir="rtl">ba^r</bdo> baz',
|
||||
'expected': 'foo <bdo dir="rtl">b^ar</bdo> baz' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_BDOdir:rtl-1_SC-1',
|
||||
'desc': 'move caret 1 character to the left inside <bdo>',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'foo <bdo dir="rtl">b^ar</bdo> baz',
|
||||
'expected': 'foo <bdo dir="rtl">ba^r</bdo> baz' },
|
||||
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXTrle-1_SC-rtl-1',
|
||||
'desc': 'move caret forward in RTL text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫car يعني سيا^رة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXTrle-1_SC-rtl-1',
|
||||
'desc': 'move caret backward in RTL text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫car يعني س^يارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_TEXTrle-1_SC-rtl-1',
|
||||
'desc': 'move caret 1 character to the right in RTL text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫car يعني س^يارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_TEXTrle-1_SC-rtl-1',
|
||||
'desc': 'move caret 1 character to the left in RTL text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'I said, "(RLE)‫car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫car يعني سيا^رة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXTrle-1_SC-ltr-1',
|
||||
'desc': 'move caret forward in LTR text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXTrle-1_SC-ltr-1',
|
||||
'desc': 'move caret backward in LTR text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_TEXTrle-1_SC-ltr-1',
|
||||
'desc': 'move caret 1 character to the right in LTR text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_TEXTrle-1_SC-ltr-1',
|
||||
'desc': 'move caret 1 character to the left in LTR text within RLE-PDF marks',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'I said, "(RLE)‫ca^r يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLE)‫c^ar يعني سيارة‬(PDF)".' },
|
||||
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXTrlo-1_SC-rtl-1',
|
||||
'desc': 'move caret forward in RTL text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮car يعني سيا^رة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXTrlo-1_SC-rtl-1',
|
||||
'desc': 'move caret backward in RTL text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮car يعني س^يارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_TEXTrlo-1_SC-rtl-1',
|
||||
'desc': 'move caret 1 character to the right in RTL text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮car يعني س^يارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_TEXTrlo-1_SC-rtl-1',
|
||||
'desc': 'move caret 1 character to the left in RTL text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'I said, "(RLO)‮car يعني سي^ارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮car يعني سيا^رة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXTrlo-1_SC-ltr-1',
|
||||
'desc': 'move caret forward in Latin text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXTrlo-1_SC-ltr-1',
|
||||
'desc': 'move caret backward in Latin text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_TEXTrlo-1_SC-ltr-1',
|
||||
'desc': 'move caret 1 character to the right in Latin text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_TEXTrlo-1_SC-ltr-1',
|
||||
'desc': 'move caret 1 character to the left in Latin text within RLO-PDF marks',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'I said, "(RLO)‮c^ar يعني سيارة‬(PDF)".',
|
||||
'expected': 'I said, "(RLO)‮ca^r يعني سيارة‬(PDF)".' },
|
||||
|
||||
|
||||
{ 'id': 'SM:m.f.c_TEXTrlm-1_SC-1',
|
||||
'desc': 'move caret forward in RTL text within neutral characters followed by RLM',
|
||||
'function': 'sel.modify("move", "forward", "character");',
|
||||
'pad': 'I said, "يعني سيارة!^?!‏(RLM)".',
|
||||
'expected': 'I said, "يعني سيارة!?^!‏(RLM)".' },
|
||||
|
||||
{ 'id': 'SM:m.b.c_TEXTrlm-1_SC-1',
|
||||
'desc': 'move caret backward in RTL text within neutral characters followed by RLM',
|
||||
'function': 'sel.modify("move", "backward", "character");',
|
||||
'pad': 'I said, "يعني سيارة!?^!‏(RLM)".',
|
||||
'expected': 'I said, "يعني سيارة!^?!‏(RLM)".' },
|
||||
|
||||
{ 'id': 'SM:m.r.c_TEXTrlm-1_SC-1',
|
||||
'desc': 'move caret 1 character to the right in RTL text within neutral characters followed by RLM',
|
||||
'function': 'sel.modify("move", "right", "character");',
|
||||
'pad': 'I said, "يعني سيارة!?^!‏(RLM)".',
|
||||
'expected': 'I said, "يعني سيارة!^?!‏(RLM)".' },
|
||||
|
||||
{ 'id': 'SM:m.l.c_TEXTrlm-1_SC-1',
|
||||
'desc': 'move caret 1 character to the left in RTL text within neutral characters followed by RLM',
|
||||
'function': 'sel.modify("move", "left", "character");',
|
||||
'pad': 'I said, "يعني سيارة!^?!‏(RLM)".',
|
||||
'expected': 'I said, "يعني سيارة!?^!‏(RLM)".' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: move forward/backward over words in Japanese text',
|
||||
'tests': [
|
||||
{ 'id': 'SM:m.f.w_TEXT-jp_SC-1',
|
||||
'desc': 'move caret forward 1 word in Japanese text (adjective)',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': '^面白い例文をテストしましょう。',
|
||||
'expected': '面白い^例文をテストしましょう。' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-jp_SC-2',
|
||||
'desc': 'move caret forward 1 word in Japanese text (in the middle of a word)',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': '面^白い例文をテストしましょう。',
|
||||
'expected': '面白い^例文をテストしましょう。' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-jp_SC-3',
|
||||
'desc': 'move caret forward 1 word in Japanese text (noun)',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': '面白い^例文をテストしましょう。',
|
||||
'expected': [ '面白い例文^をテストしましょう。',
|
||||
'面白い例文を^テストしましょう。' ] },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-jp_SC-4',
|
||||
'desc': 'move caret forward 1 word in Japanese text (Katakana)',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': '面白い例文を^テストしましょう。',
|
||||
'expected': '面白い例文をテスト^しましょう。' },
|
||||
|
||||
{ 'id': 'SM:m.f.w_TEXT-jp_SC-5',
|
||||
'desc': 'move caret forward 1 word in Japanese text (verb)',
|
||||
'function': 'sel.modify("move", "forward", "word");',
|
||||
'pad': '面白い例文をテスト^しましょう。',
|
||||
'expected': '面白い例文をテストしましょう^。' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection forward',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.f.c_TEXT-1_SC-1',
|
||||
'desc': 'extend selection 1 character forward',
|
||||
'function': 'sel.modify("extend", "forward", "character");',
|
||||
'pad': 'foo ^bar baz',
|
||||
'expected': 'foo [b]ar baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.c_TEXT-1_SI-1',
|
||||
'desc': 'extend selection 1 character forward',
|
||||
'function': 'sel.modify("extend", "forward", "character");',
|
||||
'pad': 'foo [b]ar baz',
|
||||
'expected': 'foo [ba]r baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.w_TEXT-1_SC-1',
|
||||
'desc': 'extend selection 1 word forward',
|
||||
'function': 'sel.modify("extend", "forward", "word");',
|
||||
'pad': 'foo ^bar baz',
|
||||
'expected': 'foo [bar] baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.w_TEXT-1_SI-1',
|
||||
'desc': 'extend selection 1 word forward',
|
||||
'function': 'sel.modify("extend", "forward", "word");',
|
||||
'pad': 'foo [b]ar baz',
|
||||
'expected': 'foo [bar] baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.w_TEXT-1_SI-2',
|
||||
'desc': 'extend selection 1 word forward',
|
||||
'function': 'sel.modify("extend", "forward", "word");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo [bar baz]' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection backward, shrinking it',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.b.c_TEXT-1_SI-2',
|
||||
'desc': 'extend selection 1 character backward',
|
||||
'function': 'sel.modify("extend", "backward", "character");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo [ba]r baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.c_TEXT-1_SI-1',
|
||||
'desc': 'extend selection 1 character backward',
|
||||
'function': 'sel.modify("extend", "backward", "character");',
|
||||
'pad': 'foo [b]ar baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SI-3',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo [bar baz]',
|
||||
'expected': 'foo [bar] baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SI-2',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo [bar] baz',
|
||||
'expected': 'foo ^bar baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SI-4',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo b[ar baz]',
|
||||
'expected': 'foo b[ar] baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SI-5',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo b[ar] baz',
|
||||
'expected': 'foo b^ar baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection backward, creating or extending a reverse selections',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.b.c_TEXT-1_SC-1',
|
||||
'desc': 'extend selection 1 character backward',
|
||||
'function': 'sel.modify("extend", "backward", "character");',
|
||||
'pad': 'foo b^ar baz',
|
||||
'expected': 'foo ]b[ar baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.c_TEXT-1_SIR-1',
|
||||
'desc': 'extend selection 1 character backward',
|
||||
'function': 'sel.modify("extend", "backward", "character");',
|
||||
'pad': 'foo b]a[r baz',
|
||||
'expected': 'foo ]ba[r baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SIR-1',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo b]a[r baz',
|
||||
'expected': 'foo ]ba[r baz' },
|
||||
|
||||
{ 'id': 'SM:e.b.w_TEXT-1_SIR-2',
|
||||
'desc': 'extend selection 1 word backward',
|
||||
'function': 'sel.modify("extend", "backward", "word");',
|
||||
'pad': 'foo ]ba[r baz',
|
||||
'expected': ']foo ba[r baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection forward, shrinking a reverse selections',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.f.c_TEXT-1_SIR-1',
|
||||
'desc': 'extend selection 1 character forward',
|
||||
'function': 'sel.modify("extend", "forward", "character");',
|
||||
'pad': 'foo b]a[r baz',
|
||||
'expected': 'foo ba^r baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.c_TEXT-1_SIR-2',
|
||||
'desc': 'extend selection 1 character forward',
|
||||
'function': 'sel.modify("extend", "forward", "character");',
|
||||
'pad': 'foo ]ba[r baz',
|
||||
'expected': 'foo b]a[r baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.w_TEXT-1_SIR-1',
|
||||
'desc': 'extend selection 1 word forward',
|
||||
'function': 'sel.modify("extend", "forward", "word");',
|
||||
'pad': 'foo ]ba[r baz',
|
||||
'expected': 'foo ba^r baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.w_TEXT-1_SIR-3',
|
||||
'desc': 'extend selection 1 word forward',
|
||||
'function': 'sel.modify("extend", "forward", "word");',
|
||||
'pad': ']foo ba[r baz',
|
||||
'expected': 'foo ]ba[r baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection forward to line boundary',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.f.lb_BR.BR-1_SC-1',
|
||||
'desc': 'extend selection forward to line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': 'fo^o<br>bar<br>baz',
|
||||
'expected': 'fo[o]<br>bar<br>baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_BR.BR-1_SI-1',
|
||||
'desc': 'extend selection forward to next line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': 'fo[o]<br>bar<br>baz',
|
||||
'expected': 'fo[o<br>bar]<br>baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_BR.BR-1_SM-1',
|
||||
'desc': 'extend selection forward to line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': 'fo[o<br>b]ar<br>baz',
|
||||
'expected': 'fo[o<br>bar]<br>baz' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_P.P.P-1_SC-1',
|
||||
'desc': 'extend selection forward to line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': '<p>fo^o</p><p>bar</p><p>baz</p>',
|
||||
'expected': '<p>fo[o]</p><p>bar</p><p>baz</p>' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_P.P.P-1_SI-1',
|
||||
'desc': 'extend selection forward to next line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': '<p>fo[o]</p><p>bar</p><p>baz</p>',
|
||||
'expected': '<p>fo[o</p><p>bar]</p><p>baz</p>' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_P.P.P-1_SM-1',
|
||||
'desc': 'extend selection forward to line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': '<p>fo[o</p><p>b]ar</p><p>baz</p>',
|
||||
'expected': '<p>fo[o</p><p>bar]</p><p>baz</p>' },
|
||||
|
||||
{ 'id': 'SM:e.f.lb_P.P.P-1_SMR-1',
|
||||
'desc': 'extend selection forward to line boundary',
|
||||
'function': 'sel.modify("extend", "forward", "lineboundary");',
|
||||
'pad': '<p>foo</p><p>b]a[r</p><p>baz</p>',
|
||||
'expected': '<p>foo</p><p>ba[r]</p><p>baz</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection backward to line boundary',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.b.lb_BR.BR-1_SC-2',
|
||||
'desc': 'extend selection backward to line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': 'foo<br>bar<br>b^az',
|
||||
'expected': 'foo<br>bar<br>]b[az' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_BR.BR-1_SIR-2',
|
||||
'desc': 'extend selection backward to previous line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': 'foo<br>bar<br>]b[az',
|
||||
'expected': 'foo<br>]bar<br>b[az' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_BR.BR-1_SMR-2',
|
||||
'desc': 'extend selection backward to line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': 'foo<br>ba]r<br>b[az',
|
||||
'expected': 'foo<br>]bar<br>b[az' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_P.P.P-1_SC-2',
|
||||
'desc': 'extend selection backward to line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': '<p>foo</p><p>bar</p><p>b^az</p>',
|
||||
'expected': '<p>foo</p><p>bar</p><p>]b[az</p>' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_P.P.P-1_SIR-2',
|
||||
'desc': 'extend selection backward to previous line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': '<p>foo</p><p>bar</p><p>]b[az</p>',
|
||||
'expected': '<p>foo</p><p>]bar</p><p>b[az</p>' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_P.P.P-1_SMR-2',
|
||||
'desc': 'extend selection backward to line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': '<p>foo</p><p>ba]r</p><p>b[az</p>',
|
||||
'expected': '<p>foo</p><p>]bar</p><p>b[az</p>' },
|
||||
|
||||
{ 'id': 'SM:e.b.lb_P.P.P-1_SM-2',
|
||||
'desc': 'extend selection backward to line boundary',
|
||||
'function': 'sel.modify("extend", "backward", "lineboundary");',
|
||||
'pad': '<p>foo</p><p>b[a]r</p><p>baz</p>',
|
||||
'expected': '<p>foo</p><p>]b[ar</p><p>baz</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection forward to next line (NOTE: use identical text in every line!)',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.f.l_BR.BR-2_SC-1',
|
||||
'desc': 'extend selection forward to next line',
|
||||
'function': 'sel.modify("extend", "forward", "line");',
|
||||
'pad': 'fo^o<br>foo<br>foo',
|
||||
'expected': 'fo[o<br>fo]o<br>foo' },
|
||||
|
||||
{ 'id': 'SM:e.f.l_BR.BR-2_SI-1',
|
||||
'desc': 'extend selection forward to next line',
|
||||
'function': 'sel.modify("extend", "forward", "line");',
|
||||
'pad': 'fo[o]<br>foo<br>foo',
|
||||
'expected': 'fo[o<br>foo]<br>foo' },
|
||||
|
||||
{ 'id': 'SM:e.f.l_BR.BR-2_SM-1',
|
||||
'desc': 'extend selection forward to next line',
|
||||
'function': 'sel.modify("extend", "forward", "line");',
|
||||
'pad': 'fo[o<br>f]oo<br>foo',
|
||||
'expected': 'fo[o<br>foo<br>f]oo' },
|
||||
|
||||
{ 'id': 'SM:e.f.l_P.P-1_SC-1',
|
||||
'desc': 'extend selection forward to next line over paragraph boundaries',
|
||||
'function': 'sel.modify("extend", "forward", "line");',
|
||||
'pad': '<p>foo^bar</p><p>foobar</p>',
|
||||
'expected': '<p>foo[bar</p><p>foo]bar</p>' },
|
||||
|
||||
{ 'id': 'SM:e.f.l_P.P-1_SMR-1',
|
||||
'desc': 'extend selection forward to next line over paragraph boundaries',
|
||||
'function': 'sel.modify("extend", "forward", "line");',
|
||||
'pad': '<p>fo]obar</p><p>foob[ar</p>',
|
||||
'expected': '<p>foobar</p><p>fo]ob[ar</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.modify: extend selection backward to previous line (NOTE: use identical text in every line!)',
|
||||
'tests': [
|
||||
{ 'id': 'SM:e.b.l_BR.BR-2_SC-2',
|
||||
'desc': 'extend selection backward to previous line',
|
||||
'function': 'sel.modify("extend", "backward", "line");',
|
||||
'pad': 'foo<br>foo<br>f^oo',
|
||||
'expected': 'foo<br>f]oo<br>f[oo' },
|
||||
|
||||
{ 'id': 'SM:e.b.l_BR.BR-2_SIR-2',
|
||||
'desc': 'extend selection backward to previous line',
|
||||
'function': 'sel.modify("extend", "backward", "line");',
|
||||
'pad': 'foo<br>foo<br>]f[oo',
|
||||
'expected': 'foo<br>]foo<br>f[oo' },
|
||||
|
||||
{ 'id': 'SM:e.b.l_BR.BR-2_SMR-2',
|
||||
'desc': 'extend selection backward to previous line',
|
||||
'function': 'sel.modify("extend", "backward", "line");',
|
||||
'pad': 'foo<br>fo]o<br>f[oo',
|
||||
'expected': 'fo]o<br>foo<br>f[oo' },
|
||||
|
||||
{ 'id': 'SM:e.b.l_P.P-1_SC-2',
|
||||
'desc': 'extend selection backward to next line over paragraph boundaries',
|
||||
'function': 'sel.modify("extend", "backward", "line");',
|
||||
'pad': '<p>foobar</p><p>foo^bar</p>',
|
||||
'expected': '<p>foo]bar</p><p>foo[bar</p>' },
|
||||
|
||||
{ 'id': 'SM:e.b.l_P.P-1_SM-1',
|
||||
'desc': 'extend selection backward to next line over paragraph boundaries',
|
||||
'function': 'sel.modify("extend", "backward", "line");',
|
||||
'pad': '<p>fo[obar</p><p>foob]ar</p>',
|
||||
'expected': '<p>fo[ob]ar</p><p>foobar</p>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'sel.selectAllChildren(<element>)',
|
||||
'function': 'sel.selectAllChildren(doc.getElementById("div"));',
|
||||
'tests': [
|
||||
{ 'id': 'SAC:div_DIV-1_SC-1',
|
||||
'desc': 'selectAllChildren(<div>)',
|
||||
'pad': 'foo<div id="div">bar <span>ba^z</span></div>qoz',
|
||||
'expected': [ 'foo<div id="div">[bar <span>baz</span>}</div>qoz',
|
||||
'foo<div id="div">{bar <span>baz</span>}</div>qoz' ] },
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,462 @@
|
|||
|
||||
UNAPPLY_TESTS = {
|
||||
'id': 'U',
|
||||
'caption': 'Unapply Existing Formatting Tests',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': False,
|
||||
'expected': 'foo[bar]baz',
|
||||
|
||||
'RFC': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove link',
|
||||
'command': 'unlink',
|
||||
'tests': [
|
||||
{ 'id': 'UNLINK_A-1_SO',
|
||||
'desc': 'unlink wrapped <a> element',
|
||||
'pad': 'foo[<a>bar</a>]baz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-1_SW',
|
||||
'desc': 'unlink <a> element where the selection wraps the full content',
|
||||
'pad': 'foo<a>[bar]</a>baz' },
|
||||
|
||||
{ 'id': 'UNLINK_An:a.h:id-1_SO',
|
||||
'desc': 'unlink wrapped <a> element that has a name and href attribute',
|
||||
'pad': 'foo[<a name="A" href="#UNLINK:An:a.h:id-1_SO">bar</a>]baz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-2_SO',
|
||||
'desc': 'unlink contained <a> element',
|
||||
'pad': 'foo[b<a>a</a>r]baz' },
|
||||
|
||||
{ 'id': 'UNLINK_A2-1_SO',
|
||||
'desc': 'unlink 2 contained <a> elements',
|
||||
'pad': 'foo[<a>b</a>a<a>r</a>]baz' }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove bold',
|
||||
'command': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_B-1_SW',
|
||||
'rte1-id': 'u-bold-0',
|
||||
'desc': 'Selection within tags; remove <b> tags',
|
||||
'pad': 'foo<b>[bar]</b>baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <b> tags',
|
||||
'pad': 'foo[<b>bar</b>]baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SL',
|
||||
'desc': 'Selection oblique left; remove <b> tags',
|
||||
'pad': 'foo[<b>bar]</b>baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SR',
|
||||
'desc': 'Selection oblique right; remove <b> tags',
|
||||
'pad': 'foo<b>[bar</b>]baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SW',
|
||||
'rte1-id': 'u-bold-1',
|
||||
'desc': 'Selection within tags; remove <strong> tags',
|
||||
'pad': 'foo<strong>[bar]</strong>baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <strong> tags',
|
||||
'pad': 'foo[<strong>bar</strong>]baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SL',
|
||||
'desc': 'Selection oblique left; remove <strong> tags',
|
||||
'pad': 'foo[<strong>bar]</strong>baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SR',
|
||||
'desc': 'Selection oblique right; remove <strong> tags',
|
||||
'pad': 'foo<strong>[bar</strong>]baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SW',
|
||||
'rte1-id': 'u-bold-2',
|
||||
'desc': 'Selection within tags; remove "font-weight: bold"',
|
||||
'pad': 'foo<span style="font-weight: bold">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SO',
|
||||
'desc': 'Selection outside of tags; remove "font-weight: bold"',
|
||||
'pad': 'foo[<span style="font-weight: bold">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SL',
|
||||
'desc': 'Selection oblique left; remove "font-weight: bold"',
|
||||
'pad': 'foo[<span style="font-weight: bold">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SR',
|
||||
'desc': 'Selection oblique right; remove "font-weight: bold"',
|
||||
'pad': 'foo<span style="font-weight: bold">[bar</span>]baz' },
|
||||
|
||||
{ 'id': 'B_B-P3-1_SO12',
|
||||
'desc': 'Unbolding multiple paragraphs in inside bolded content with content-model violation',
|
||||
'pad': '<b>{<p>foo</p><p>bar</p>}<p>baz</p></b>',
|
||||
'expected': [ '<p>[foo</p><p>bar]</p><p><b>baz</b></p>',
|
||||
'<p>[foo</p><p>bar]</p><b><p>baz</p></b>' ] },
|
||||
|
||||
{ 'id': 'B_B-P-I..P-1_SO-I',
|
||||
'desc': 'Unbolding italicized content inside bolded content with content-model violation',
|
||||
'pad': '<b><p>foo[<i>bar</i>]</p><p>baz</p></b>',
|
||||
'expected': [ '<p><b>foo</b><i>[bar]</i></p><p><b>baz</b></p>',
|
||||
'<b><p>foo</p></b><p><i>[bar]</i></p><b><p>baz</p></b>' ] },
|
||||
|
||||
{ 'id': 'B_B-2_SL',
|
||||
'desc': 'Remove partially covered bold, selection extends left',
|
||||
'pad': 'foo [bar <b>baz] qoz</b> quz sic',
|
||||
'expected': 'foo [bar baz]<b> qoz</b> quz sic' },
|
||||
|
||||
{ 'id': 'B_B-2_SR',
|
||||
'desc': 'Remove partially covered bold, selection extends right',
|
||||
'pad': 'foo bar <b>baz [qoz</b> quz] sic',
|
||||
'expected': 'foo bar <b>baz </b>[qoz quz] sic' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_I-1_SW',
|
||||
'rte1-id': 'u-italic-0',
|
||||
'desc': 'Selection within tags; remove <i> tags',
|
||||
'pad': 'foo<i>[bar]</i>baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <i> tags',
|
||||
'pad': 'foo[<i>bar</i>]baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SL',
|
||||
'desc': 'Selection oblique left; remove <i> tags',
|
||||
'pad': 'foo[<i>bar]</i>baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SR',
|
||||
'desc': 'Selection oblique right; remove <i> tags',
|
||||
'pad': 'foo<i>[bar</i>]baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SW',
|
||||
'rte1-id': 'u-italic-1',
|
||||
'desc': 'Selection within tags; remove <em> tags',
|
||||
'pad': 'foo<em>[bar]</em>baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <em> tags',
|
||||
'pad': 'foo[<em>bar</em>]baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SL',
|
||||
'desc': 'Selection oblique left; remove <em> tags',
|
||||
'pad': 'foo[<em>bar]</em>baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SR',
|
||||
'desc': 'Selection oblique right; remove <em> tags',
|
||||
'pad': 'foo<em>[bar</em>]baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SW',
|
||||
'rte1-id': 'u-italic-2',
|
||||
'desc': 'Selection within tags; remove "font-style: italic"',
|
||||
'pad': 'foo<span style="font-style: italic">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SO',
|
||||
'desc': 'Selection outside of tags; Italicize "font-style: italic"',
|
||||
'pad': 'foo[<span style="font-style: italic">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SL',
|
||||
'desc': 'Selection oblique left; Italicize "font-style: italic"',
|
||||
'pad': 'foo[<span style="font-style: italic">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SR',
|
||||
'desc': 'Selection oblique right; Italicize "font-style: italic"',
|
||||
'pad': 'foo<span style="font-style: italic">[bar</span>]baz' },
|
||||
|
||||
{ 'id': 'I_I-P3-1_SO2',
|
||||
'desc': 'Unitalicize content with content-model violation',
|
||||
'pad': '<i><p>foo</p>{<p>bar</p>}<p>baz</p></i>',
|
||||
'expected': [ '<p><i>foo</i></p><p>[bar]</p><p><i>baz</i></p>',
|
||||
'<i><p>foo</p></i><p>[bar]</p><i><p>baz</p></i>' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove underline',
|
||||
'command': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_U-1_SW',
|
||||
'rte1-id': 'u-underline-0',
|
||||
'desc': 'Selection within tags; remove <u> tags',
|
||||
'pad': 'foo<u>[bar]</u>baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <u> tags',
|
||||
'pad': 'foo[<u>bar</u>]baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SL',
|
||||
'desc': 'Selection oblique left; remove <u> tags',
|
||||
'pad': 'foo[<u>bar]</u>baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SR',
|
||||
'desc': 'Selection oblique right; remove <u> tags',
|
||||
'pad': 'foo<u>[bar</u>]baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SW',
|
||||
'rte1-id': 'u-underline-1',
|
||||
'desc': 'Selection within tags; remove "text-decoration: underline"',
|
||||
'pad': 'foo<span style="text-decoration: underline">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SO',
|
||||
'desc': 'Selection outside of tags; remove "text-decoration: underline"',
|
||||
'pad': 'foo[<span style="text-decoration: underline">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SL',
|
||||
'desc': 'Selection oblique left; remove "text-decoration: underline"',
|
||||
'pad': 'foo[<span style="text-decoration: underline">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SR',
|
||||
'desc': 'Selection oblique right; remove "text-decoration: underline"',
|
||||
'pad': 'foo<span style="text-decoration: underline">[bar</span>]baz' },
|
||||
|
||||
{ 'id': 'U_U-S-1_SO',
|
||||
'desc': 'Removing underline from underlined content with striked content',
|
||||
'pad': '<u>foo[bar<s>baz</s>quoz]</u>',
|
||||
'expected': '<u>foo</u>[bar<s>baz</s>quoz]' },
|
||||
|
||||
{ 'id': 'U_U-S-2_SI',
|
||||
'desc': 'Removing underline from striked content inside underlined content',
|
||||
'pad': '<u><s>foo[bar]baz</s>quoz</u>',
|
||||
'expected': '<s><u>foo</u>[bar]<u>baz</u>quoz</s>' },
|
||||
|
||||
{ 'id': 'U_U-P3-1_SO',
|
||||
'desc': 'Removing underline from underlined content with content-model violation',
|
||||
'pad': '<u><p>foo</p>{<p>bar</p>}<p>baz</p></u>',
|
||||
'expected': [ '<p><u>foo</u></p><p>[bar]</p><p><u>baz</u></p>',
|
||||
'<u><p>foo</p></u><p>[bar]</p><u><p>baz</p></u>' ] }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove strike through',
|
||||
'command': 'strikethrough',
|
||||
'tests': [
|
||||
{ 'id': 'S_S-1_SW',
|
||||
'rte1-id': 'u-strikethrough-1',
|
||||
'desc': 'Selection within tags; remove <s> tags',
|
||||
'pad': 'foo<s>[bar]</s>baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <s> tags',
|
||||
'pad': 'foo[<s>bar</s>]baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SL',
|
||||
'desc': 'Selection oblique left; remove <s> tags',
|
||||
'pad': 'foo[<s>bar]</s>baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SR',
|
||||
'desc': 'Selection oblique right; remove <s> tags',
|
||||
'pad': 'foo<s>[bar</s>]baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SW',
|
||||
'rte1-id': 'u-strikethrough-0',
|
||||
'desc': 'Selection within tags; remove <strike> tags',
|
||||
'pad': 'foo<strike>[bar]</strike>baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <strike> tags',
|
||||
'pad': 'foo[<strike>bar</strike>]baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SL',
|
||||
'desc': 'Selection oblique left; remove <strike> tags',
|
||||
'pad': 'foo[<strike>bar]</strike>baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-2_SR',
|
||||
'desc': 'Selection oblique right; remove <strike> tags',
|
||||
'pad': 'foo<strike>[bar</strike>]baz' },
|
||||
|
||||
{ 'id': 'S_DEL-1_SW',
|
||||
'rte1-id': 'u-strikethrough-2',
|
||||
'desc': 'Selection within tags; remove <del> tags',
|
||||
'pad': 'foo<del>[bar]</del>baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SW',
|
||||
'rte1-id': 'u-strikethrough-3',
|
||||
'desc': 'Selection within tags; remove "text-decoration:line-through"',
|
||||
'pad': 'foo<span style="text-decoration:line-through">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SO',
|
||||
'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo[<span style="text-decoration:line-through">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SL',
|
||||
'desc': 'Selection oblique left; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo[<span style="text-decoration:line-through">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SR',
|
||||
'desc': 'Selection oblique right; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo<span style="text-decoration:line-through">[bar</span>]baz' },
|
||||
|
||||
{ 'id': 'S_S-U-1_SI',
|
||||
'desc': 'Removing underline from underlined content inside striked content',
|
||||
'pad': '<s><u>foo[bar]baz</u>quoz</s>',
|
||||
'expected': '<s><u>foo</u></s><u>[bar]</u><s><u>baz</u>quoz</s>' },
|
||||
|
||||
{ 'id': 'S_U-S-1_SI',
|
||||
'desc': 'Removing underline from striked content inside underlined content',
|
||||
'pad': '<u><s>foo[bar]baz</s>quoz</u>',
|
||||
'expected': '<u><s>foo</s>[bar]<s>baz</s>quoz</u>' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove subscript',
|
||||
'command': 'subscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUB_SUB-1_SW',
|
||||
'rte1-id': 'u-subscript-0',
|
||||
'desc': 'remove subscript',
|
||||
'pad': 'foo<sub>[bar]</sub>baz' },
|
||||
|
||||
{ 'id': 'SUB_SPANs:va:sub-1_SW',
|
||||
'rte1-id': 'u-subscript-1',
|
||||
'desc': 'remove subscript',
|
||||
'pad': 'foo<span style="vertical-align: sub">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove superscript',
|
||||
'command': 'superscript',
|
||||
'tests': [
|
||||
{ 'id': 'SUP_SUP-1_SW',
|
||||
'rte1-id': 'u-superscript-0',
|
||||
'desc': 'remove superscript',
|
||||
'pad': 'foo<sup>[bar]</sup>baz' },
|
||||
|
||||
{ 'id': 'SUP_SPANs:va:super-1_SW',
|
||||
'rte1-id': 'u-superscript-1',
|
||||
'desc': 'remove superscript',
|
||||
'pad': 'foo<span style="vertical-align: super">[bar]</span>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove links',
|
||||
'command': 'unlink',
|
||||
'tests': [
|
||||
{ 'id': 'UNLINK_Ahref:url-1_SW',
|
||||
'rte1-id': 'u-unlink-0',
|
||||
'desc': 'unlink an <a> element with href attribute where all children are selected',
|
||||
'pad': 'foo<a href="http://www.goo.gl">[bar]</a>baz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-1_SC',
|
||||
'desc': 'unlink an <a> element that contains the collapsed selection',
|
||||
'pad': 'foo<a>ba^r</a>baz',
|
||||
'expected': 'fooba^rbaz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-1_SI',
|
||||
'desc': 'unlink an <a> element that contains the whole selection',
|
||||
'pad': 'foo<a>b[a]r</a>baz',
|
||||
'expected': 'foob[a]rbaz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-2_SL',
|
||||
'desc': 'unlink a partially contained <a> element',
|
||||
'pad': 'foo[ba<a>r]ba</a>z' },
|
||||
|
||||
{ 'id': 'UNLINK_A-3_SR',
|
||||
'desc': 'unlink a partially contained <a> element',
|
||||
'pad': 'fo<a>o[ba</a>r]baz' },
|
||||
|
||||
{ 'id': 'UNLINK_As:d:b.fw:b-1_SW',
|
||||
'desc': 'unlink, preserving styles',
|
||||
'pad': 'foo<a href="#" style="display: block; font-weight: bold">[bar]</a>baz',
|
||||
'expected': 'foo<span style="display: block; font-weight: bold">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'UNLINK_A-IMG-1_SO',
|
||||
'desc': 'unlink a linked image at the start of the content',
|
||||
'pad': '{<a href="#"><img src="pic.jpg" align="right" height="140" width="200"></a>abc]',
|
||||
'expected': '{<img src="pic.jpg" align="right" height="140" width="200">abc]' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'outdent',
|
||||
'command': 'outdent',
|
||||
'tests': [
|
||||
{ 'id': 'OUTDENT_BQ-1_SW',
|
||||
'rte1-id': 'u-outdent-0',
|
||||
'desc': 'outdent (remove) a <blockquote>',
|
||||
'pad': 'foo<blockquote>[bar]</blockquote>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' },
|
||||
|
||||
{ 'id': 'OUTDENT_BQ.wibq.s:m:00040.b:n.p:0-1_SW',
|
||||
'rte1-id': 'u-outdent-1',
|
||||
'desc': 'outdent (remove) a styled <blockquote>',
|
||||
'pad': 'foo<blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px">[bar]</blockquote>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' },
|
||||
|
||||
{ 'id': 'OUTDENT_OL-LI-1_SW',
|
||||
'rte1-id': 'u-outdent-3',
|
||||
'desc': 'outdent (remove) an ordered list',
|
||||
'pad': 'foo<ol><li>[bar]</li></ol>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' },
|
||||
|
||||
{ 'id': 'OUTDENT_UL-LI-1_SW',
|
||||
'rte1-id': 'u-outdent-2',
|
||||
'desc': 'outdent (remove) an unordered list',
|
||||
'pad': 'foo<ul><li>[bar]</li></ul>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' },
|
||||
|
||||
{ 'id': 'OUTDENT_DIV-1_SW',
|
||||
'rte1-id': 'u-outdent-4',
|
||||
'desc': 'outdent (remove) a styled <div> with margin',
|
||||
'pad': 'foo<div style="margin-left: 40px;">[bar]</div>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove all formatting',
|
||||
'command': 'removeformat',
|
||||
'tests': [
|
||||
{ 'id': 'REMOVEFORMAT_B-1_SW',
|
||||
'rte1-id': 'u-removeformat-0',
|
||||
'desc': 'remove a <b> tag using "removeformat"',
|
||||
'pad': 'foo<b>[bar]</b>baz' },
|
||||
|
||||
{ 'id': 'REMOVEFORMAT_Ahref:url-1_SW',
|
||||
'rte1-id': 'u-removeformat-0',
|
||||
'desc': 'remove a link using "removeformat"',
|
||||
'pad': 'foo<a href="http://www.goo.gl">[bar]</a>baz' },
|
||||
|
||||
{ 'id': 'REMOVEFORMAT_TABLE-TBODY-TR-TD-1_SW',
|
||||
'rte1-id': 'u-removeformat-2',
|
||||
'desc': 'remove a table using "removeformat"',
|
||||
'pad': 'foo<table><tbody><tr><td>[bar]</td></tr></tbody></table>baz',
|
||||
'expected': [ 'foo<p>[bar]</p>baz',
|
||||
'foo<div>[bar]</div>baz' ],
|
||||
'accept': 'foo<br>[bar]<br>baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove bookmark',
|
||||
'command': 'unbookmark',
|
||||
'tests': [
|
||||
{ 'id': 'UNBOOKMARK_An:name-1_SW',
|
||||
'rte1-id': 'u-unbookmark-0',
|
||||
'desc': 'unlink a bookmark (a named <a> element) where all children are selected',
|
||||
'pad': 'foo<a name="bookmark">[bar]</a>baz' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
|
||||
UNAPPLY_TESTS_CSS = {
|
||||
'id': 'UC',
|
||||
'caption': 'Unapply Existing Formatting Tests, using styleWithCSS',
|
||||
'checkAttrs': True,
|
||||
'checkStyle': True,
|
||||
'styleWithCSS': True,
|
||||
'expected': 'foo[bar]baz',
|
||||
|
||||
'Proposed': [
|
||||
{ 'desc': '',
|
||||
'id': '',
|
||||
'command': '',
|
||||
'tests': [
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove bold',
|
||||
'command': 'bold',
|
||||
'tests': [
|
||||
{ 'id': 'B_B-1_SW',
|
||||
'desc': 'Selection within tags; remove <b> tags',
|
||||
'pad': 'foo<b>[bar]</b>baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <b> tags',
|
||||
'pad': 'foo[<b>bar</b>]baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SL',
|
||||
'desc': 'Selection oblique left; remove <b> tags',
|
||||
'pad': 'foo[<b>bar]</b>baz' },
|
||||
|
||||
{ 'id': 'B_B-1_SR',
|
||||
'desc': 'Selection oblique right; remove <b> tags',
|
||||
'pad': 'foo<b>[bar</b>]baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SW',
|
||||
'desc': 'Selection within tags; remove <strong> tags',
|
||||
'pad': 'foo<strong>[bar]</strong>baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <strong> tags',
|
||||
'pad': 'foo[<strong>bar</strong>]baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SL',
|
||||
'desc': 'Selection oblique left; remove <strong> tags',
|
||||
'pad': 'foo[<strong>bar]</strong>baz' },
|
||||
|
||||
{ 'id': 'B_STRONG-1_SR',
|
||||
'desc': 'Selection oblique right; remove <strong> tags',
|
||||
'pad': 'foo<strong>[bar</strong>]baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SW',
|
||||
'desc': 'Selection within tags; remove "font-weight: bold"',
|
||||
'pad': 'foo<span style="font-weight: bold">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SO',
|
||||
'desc': 'Selection outside of tags; remove "font-weight: bold"',
|
||||
'pad': 'foo[<span style="font-weight: bold">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SL',
|
||||
'desc': 'Selection oblique left; remove "font-weight: bold"',
|
||||
'pad': 'foo[<span style="font-weight: bold">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'B_SPANs:fw:b-1_SR',
|
||||
'desc': 'Selection oblique right; remove "font-weight: bold"',
|
||||
'pad': 'foo<span style="font-weight: bold">[bar</span>]baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove italic',
|
||||
'command': 'italic',
|
||||
'tests': [
|
||||
{ 'id': 'I_I-1_SW',
|
||||
'desc': 'Selection within tags; remove <i> tags',
|
||||
'pad': 'foo<i>[bar]</i>baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <i> tags',
|
||||
'pad': 'foo[<i>bar</i>]baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SL',
|
||||
'desc': 'Selection oblique left; remove <i> tags',
|
||||
'pad': 'foo[<i>bar]</i>baz' },
|
||||
|
||||
{ 'id': 'I_I-1_SR',
|
||||
'desc': 'Selection oblique right; remove <i> tags',
|
||||
'pad': 'foo<i>[bar</i>]baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SW',
|
||||
'desc': 'Selection within tags; remove <em> tags',
|
||||
'pad': 'foo<em>[bar]</em>baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <em> tags',
|
||||
'pad': 'foo[<em>bar</em>]baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SL',
|
||||
'desc': 'Selection oblique left; remove <em> tags',
|
||||
'pad': 'foo[<em>bar]</em>baz' },
|
||||
|
||||
{ 'id': 'I_EM-1_SR',
|
||||
'desc': 'Selection oblique right; remove <em> tags',
|
||||
'pad': 'foo<em>[bar</em>]baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SW',
|
||||
'desc': 'Selection within tags; remove "font-style: italic"',
|
||||
'pad': 'foo<span style="font-style: italic">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SO',
|
||||
'desc': 'Selection outside of tags; Italicize "font-style: italic"',
|
||||
'pad': 'foo[<span style="font-style: italic">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SL',
|
||||
'desc': 'Selection oblique left; Italicize "font-style: italic"',
|
||||
'pad': 'foo[<span style="font-style: italic">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'I_SPANs:fs:i-1_SR',
|
||||
'desc': 'Selection oblique right; Italicize "font-style: italic"',
|
||||
'pad': 'foo<span style="font-style: italic">[bar</span>]baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove underline',
|
||||
'command': 'underline',
|
||||
'tests': [
|
||||
{ 'id': 'U_U-1_SW',
|
||||
'desc': 'Selection within tags; remove <u> tags',
|
||||
'pad': 'foo<u>[bar]</u>baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <u> tags',
|
||||
'pad': 'foo[<u>bar</u>]baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SL',
|
||||
'desc': 'Selection oblique left; remove <u> tags',
|
||||
'pad': 'foo[<u>bar]</u>baz' },
|
||||
|
||||
{ 'id': 'U_U-1_SR',
|
||||
'desc': 'Selection oblique right; remove <u> tags',
|
||||
'pad': 'foo<u>[bar</u>]baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SW',
|
||||
'desc': 'Selection within tags; remove "text-decoration: underline"',
|
||||
'pad': 'foo<span style="text-decoration: underline">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SO',
|
||||
'desc': 'Selection outside of tags; remove "text-decoration: underline"',
|
||||
'pad': 'foo[<span style="text-decoration: underline">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SL',
|
||||
'desc': 'Selection oblique left; remove "text-decoration: underline"',
|
||||
'pad': 'foo[<span style="text-decoration: underline">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'U_SPANs:td:u-1_SR',
|
||||
'desc': 'Selection oblique right; remove "text-decoration: underline"',
|
||||
'pad': 'foo<span style="text-decoration: underline">[bar</span>]baz' }
|
||||
]
|
||||
},
|
||||
|
||||
{ 'desc': 'remove strike-through',
|
||||
'command': 'strikethrough',
|
||||
'tests': [
|
||||
{ 'id': 'S_S-1_SW',
|
||||
'desc': 'Selection within tags; remove <s> tags',
|
||||
'pad': 'foo<s>[bar]</s>baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <s> tags',
|
||||
'pad': 'foo[<s>bar</s>]baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SL',
|
||||
'desc': 'Selection oblique left; remove <s> tags',
|
||||
'pad': 'foo[<s>bar]</s>baz' },
|
||||
|
||||
{ 'id': 'S_S-1_SR',
|
||||
'desc': 'Selection oblique right; remove <s> tags',
|
||||
'pad': 'foo<s>[bar</s>]baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SW',
|
||||
'desc': 'Selection within tags; remove <strike> tags',
|
||||
'pad': 'foo<strike>[bar]</strike>baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SO',
|
||||
'desc': 'Selection outside of tags; remove <strike> tags',
|
||||
'pad': 'foo[<strike>bar</strike>]baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SL',
|
||||
'desc': 'Selection oblique left; remove <strike> tags',
|
||||
'pad': 'foo[<strike>bar]</strike>baz' },
|
||||
|
||||
{ 'id': 'S_STRIKE-1_SR',
|
||||
'desc': 'Selection oblique right; remove <strike> tags',
|
||||
'pad': 'foo<strike>[bar</strike>]baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SW',
|
||||
'desc': 'Selection within tags; remove "text-decoration:line-through"',
|
||||
'pad': 'foo<span style="text-decoration:line-through">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SO',
|
||||
'desc': 'Selection outside of tags; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo[<span style="text-decoration:line-through">bar</span>]baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SL',
|
||||
'desc': 'Selection oblique left; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo[<span style="text-decoration:line-through">bar]</span>baz' },
|
||||
|
||||
{ 'id': 'S_SPANs:td:lt-1_SR',
|
||||
'desc': 'Selection oblique right; Italicize "text-decoration:line-through"',
|
||||
'pad': 'foo<span style="text-decoration:line-through">[bar</span>]baz' },
|
||||
|
||||
{ 'id': 'S_SPANc:s-1_SW',
|
||||
'desc': 'Unapply "strike-through" on interited CSS style',
|
||||
'checkClass': True,
|
||||
'pad': 'foo<span class="s">[bar]</span>baz' },
|
||||
|
||||
{ 'id': 'S_SPANc:s-2_SI',
|
||||
'desc': 'Unapply "strike-through" on interited CSS style',
|
||||
'pad': '<span class="s">foo[bar]baz</span>',
|
||||
'checkClass': True,
|
||||
'expected': '<span class="s">foo</span>[bar]<span class="s">baz</span>' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>Rich Text 2 Unit Test Example</title>
|
||||
|
||||
<!-- utility scripts -->
|
||||
<script type="text/javascript" src="static/js/variables.js"></script>
|
||||
<script type="text/javascript" src="static/js/canonicalize.js"></script>
|
||||
<script type="text/javascript" src="static/js/compare.js"></script>
|
||||
<script type="text/javascript" src="static/js/pad.js"></script>
|
||||
<script type="text/javascript" src="static/js/range.js"></script>
|
||||
<script type="text/javascript" src="static/js/units.js"></script>
|
||||
<script type="text/javascript" src="static/js/run.js"></script>
|
||||
<!-- you do not need static/js/output.js -->
|
||||
|
||||
<!--
|
||||
Tests - note that those have the extensions .py,
|
||||
but can be used as JS files directly.
|
||||
-->
|
||||
<script type="text/javascript" src="tests/selection.py"></script>
|
||||
<script type="text/javascript" src="tests/apply.py"></script>
|
||||
<script type="text/javascript" src="tests/applyCSS.py"></script>
|
||||
<script type="text/javascript" src="tests/change.py"></script>
|
||||
<script type="text/javascript" src="tests/changeCSS.py"></script>
|
||||
<script type="text/javascript" src="tests/unapply.py"></script>
|
||||
<script type="text/javascript" src="tests/unapplyCSS.py"></script>
|
||||
<script type="text/javascript" src="tests/delete.py"></script>
|
||||
<script type="text/javascript" src="tests/forwarddelete.py"></script>
|
||||
<script type="text/javascript" src="tests/insert.py"></script>
|
||||
<script type="text/javascript" src="tests/querySupported.py"></script>
|
||||
<script type="text/javascript" src="tests/queryEnabled.py"></script>
|
||||
<script type="text/javascript" src="tests/queryIndeterm.py"></script>
|
||||
<script type="text/javascript" src="tests/queryState.py"></script>
|
||||
<script type="text/javascript" src="tests/queryValue.py"></script>
|
||||
|
||||
<!-- Do something -->
|
||||
<script type="text/javascript">
|
||||
function runTest() {
|
||||
initVariables();
|
||||
initEditorDocs();
|
||||
|
||||
runTestSuite(UNAPPLY_TESTS);
|
||||
|
||||
// Below alert is just a simple demonstration on how to access the test results.
|
||||
// Note that we only ran UNAPPLY tests above, so we have only results from that test set.
|
||||
//
|
||||
// The 'results' structure is as follows:
|
||||
//
|
||||
// results structure containing all results
|
||||
// [<suite ID>] structure containing the results for the given suite *)
|
||||
// .count number of tests in the given suite
|
||||
// .valscore sum of all test value results (HTML or query value)
|
||||
// .selscore sum of all selection results (HTML tests only)
|
||||
// [<class ID>] structure containing the results for the given class **)
|
||||
// .count number of tests in the given suite
|
||||
// .valscore sum of all test value results (HTML or query value)
|
||||
// .selscore sum of all selection results (HTML tests only)
|
||||
// [<test ID>] structure containing the reults for a given test ***)
|
||||
// .valscore value score (0 or 1), minimum over all containers
|
||||
// .selscore selection score (0 or 1), minimum over all containers (HTML tests only)
|
||||
// .valresult worst test value result (integer, see variables.js)
|
||||
// .selresult worst selection result (integer, see variables.js)
|
||||
// [<cont. ID>] structure containing the results of the test for a given container ****)
|
||||
// .valscore value score (0 or 1)
|
||||
// .selscore selection score (0 or 1)
|
||||
// .valresult value result (integer, see variables.js)
|
||||
// .selresult selection result (integer, see variables.js)
|
||||
// .output output string (mainly for use by the online version)
|
||||
// .innerHTML inner HTML of the testing container (<div> or <body>) after the test
|
||||
// .outerHTML outer HTML of the testing container (<div> or <body>) after the test
|
||||
// .bodyInnerHTML inner HTML of the <body> after the test
|
||||
// .bodyOuterHTML outer HTML of the <body> after the test
|
||||
//
|
||||
// *) <suite ID>: a 1-3 character ID, e.g. UNAPPLY_TESTS.id, or 'U' (both referring the same suite)
|
||||
// **) <class ID>: one of 'Proposed', 'RFC' or 'Finalized'
|
||||
// ***) <test ID>: the ID of the test, without the leading 'RTE2-<suite ID>_' part
|
||||
// ****) <container ID>: one of 'div' (test within a <div contenteditable="true">)
|
||||
// 'dM' (test with designMode = 'on')
|
||||
// 'body' (test within a <body contenteditable="true">)
|
||||
|
||||
alert("Result of 'Apply' tests:\nOut of " +
|
||||
results[UNAPPLY_TESTS.id].count + " tests\n" +
|
||||
results[UNAPPLY_TESTS.id].valscore + " had correct HTML, and\n" +
|
||||
results[UNAPPLY_TESTS.id].selscore + " had a correct result selection\n(in all testing containers)." +
|
||||
"\n\n" +
|
||||
"Test RTE2-U_B_B-1_SW results with a contenteditable <body>:\n" +
|
||||
results['U']['Proposed']['B_B-1_SW']['body'].valscore + " points for the value result, and\n" +
|
||||
results['U']['Proposed']['B_B-1_SW']['body'].selscore + " points for the selection" +
|
||||
""
|
||||
);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="runTest()">
|
||||
<iframe name="iframe-dM" id="iframe-dM" src="static/editable-dM.html"></iframe>
|
||||
<iframe name="iframe-body" id="iframe-body" src="static/editable-body.html"></iframe>
|
||||
<iframe name="iframe-div" id="iframe-div" src="static/editable-div.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
if test -d richtext2; then
|
||||
rm -drf richtext2;
|
||||
fi
|
||||
|
||||
svn checkout http://browserscope.googlecode.com/svn/trunk/categories/richtext2 richtext2 | tail -1 | sed 's/[^0-9]//g' > current_revision
|
||||
|
||||
find richtext2 -type d -name .svn -exec rm -drf \{\} \; 2> /dev/null
|
||||
|
||||
# Remove test_set.py and other similarly named files because they confuse our mochitest runner
|
||||
find richtext2 =type f -name test_\* -exec rm -rf \{\} \; 2> /dev/null
|
||||
|
||||
hg add current_revision richtext2
|
||||
|
||||
hg stat .
|
||||
|
||||
59
editor/libeditor/tests/browserscope/mochitest.ini
Normal file
59
editor/libeditor/tests/browserscope/mochitest.ini
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
[default]
|
||||
support-files =
|
||||
lib/richtext2/current_revision
|
||||
lib/richtext2/richtext2/common.py
|
||||
lib/richtext2/richtext2/unittestexample.html
|
||||
lib/richtext2/richtext2/static/editable-dM.html
|
||||
lib/richtext2/richtext2/static/editable.css
|
||||
lib/richtext2/richtext2/static/editable-body.html
|
||||
lib/richtext2/richtext2/static/editable-div.html
|
||||
lib/richtext2/richtext2/static/js/variables.js
|
||||
lib/richtext2/richtext2/static/js/range-bootstrap.js
|
||||
lib/richtext2/richtext2/static/js/range.js
|
||||
lib/richtext2/richtext2/static/js/output.js
|
||||
lib/richtext2/richtext2/static/js/compare.js
|
||||
lib/richtext2/richtext2/static/js/canonicalize.js
|
||||
lib/richtext2/richtext2/static/js/pad.js
|
||||
lib/richtext2/richtext2/static/js/run.js
|
||||
lib/richtext2/richtext2/static/js/units.js
|
||||
lib/richtext2/richtext2/static/common.css
|
||||
lib/richtext2/richtext2/__init__.py
|
||||
lib/richtext2/richtext2/handlers.py
|
||||
lib/richtext2/richtext2/templates/output.html
|
||||
lib/richtext2/richtext2/templates/richtext2.html
|
||||
lib/richtext2/richtext2/tests/forwarddelete.py
|
||||
lib/richtext2/richtext2/tests/selection.py
|
||||
lib/richtext2/richtext2/tests/queryIndeterm.py
|
||||
lib/richtext2/richtext2/tests/unapplyCSS.py
|
||||
lib/richtext2/richtext2/tests/apply.py
|
||||
lib/richtext2/richtext2/tests/unapply.py
|
||||
lib/richtext2/richtext2/tests/change.py
|
||||
lib/richtext2/richtext2/tests/queryState.py
|
||||
lib/richtext2/richtext2/tests/queryValue.py
|
||||
lib/richtext2/richtext2/tests/__init__.py
|
||||
lib/richtext2/richtext2/tests/insert.py
|
||||
lib/richtext2/richtext2/tests/queryEnabled.py
|
||||
lib/richtext2/richtext2/tests/applyCSS.py
|
||||
lib/richtext2/richtext2/tests/changeCSS.py
|
||||
lib/richtext2/richtext2/tests/delete.py
|
||||
lib/richtext2/richtext2/tests/querySupported.py
|
||||
lib/richtext2/README
|
||||
lib/richtext2/update_from_upstream
|
||||
lib/richtext2/LICENSE
|
||||
lib/richtext2/README.Mozilla
|
||||
lib/richtext2/currentStatus.js
|
||||
lib/richtext/current_revision
|
||||
lib/richtext/README
|
||||
lib/richtext/update_from_upstream
|
||||
lib/richtext/LICENSE
|
||||
lib/richtext/README.Mozilla
|
||||
lib/richtext/richtext/editable.html
|
||||
lib/richtext/richtext/richtext.html
|
||||
lib/richtext/richtext/js/range.js
|
||||
lib/richtext/currentStatus.js
|
||||
|
||||
[test_richtext2.html]
|
||||
subsuite = clipboard
|
||||
skip-if = os == 'android' && debug # Bug 1202045
|
||||
[test_richtext.html]
|
||||
|
||||
48
editor/libeditor/tests/browserscope/test_richtext.html
Normal file
48
editor/libeditor/tests/browserscope/test_richtext.html
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
BrowserScope richtext category tests
|
||||
-->
|
||||
<head>
|
||||
<title>BrowserScope Richtext Tests</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext/currentStatus.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=550569">Mozilla Bug 550569</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe src="lib/richtext/richtext/richtext.html"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Running all of the tests can take a long time, try to account for it
|
||||
SimpleTest.requestLongerTimeout(5);
|
||||
|
||||
function sendScore(results, continueParams) {
|
||||
ok(results.length > 1, "At least one test should have been run");
|
||||
for (var i = 1; i < results.length; ++i) {
|
||||
var result = results[i];
|
||||
[type, command, param, success] = result.split(/[\-=]/);
|
||||
var comp = is;
|
||||
if (isKnownFailure(type, command, param)) {
|
||||
comp = todo_is;
|
||||
}
|
||||
comp(success, "1", "Browserscope richtext category=" + type +
|
||||
" test=" + command +
|
||||
" param=" + param);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementsByTagName("iframe")[0].addEventListener("load", function() {
|
||||
SimpleTest.finish();
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
233
editor/libeditor/tests/browserscope/test_richtext2.html
Normal file
233
editor/libeditor/tests/browserscope/test_richtext2.html
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!--
|
||||
BrowserScope richtext2 category tests
|
||||
|
||||
This test is originally based on the unit test example available as part of the
|
||||
RichText2 suite:
|
||||
http://code.google.com/p/browserscope/source/browse/trunk/categories/richtext2/unittestexample.html
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>BrowserScope Richtext2 Tests</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<!-- utility scripts -->
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/variables.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/canonicalize.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/compare.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/pad.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/range.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/units.js"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/static/js/run.js"></script>
|
||||
<!-- you do not need static/js/output.js -->
|
||||
|
||||
<!--
|
||||
Tests - note that those have the extensions .py,
|
||||
but can be used as JS files directly.
|
||||
-->
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/selection.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/apply.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/applyCSS.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/change.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/changeCSS.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/unapply.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/unapplyCSS.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/delete.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/forwarddelete.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/insert.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/querySupported.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/queryEnabled.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/queryIndeterm.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/queryState.py"></script>
|
||||
<script type="text/javascript" src="lib/richtext2/richtext2/tests/queryValue.py"></script>
|
||||
|
||||
<script type="text/javascript" src="lib/richtext2/currentStatus.js"></script>
|
||||
|
||||
<!-- Do something -->
|
||||
<script type="text/javascript">
|
||||
// Set this constant to true in order to get the current status of the test suite.
|
||||
// This is useful for updating the currentStatus.js file when an editor bug is fixed.
|
||||
const UPDATE_TEST_RESULTS = false;
|
||||
|
||||
// some tests (at least RTE2-QE_PASTE_TEXT-1) require clipboard data
|
||||
function startTest() {
|
||||
SimpleTest.waitForClipboard("foo",
|
||||
function() {
|
||||
SpecialPowers.clipboardCopyString("foo");
|
||||
},
|
||||
runTest,
|
||||
function() {
|
||||
ok(false, "Failed to copy a string to the clipboard");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
initVariables();
|
||||
initEditorDocs();
|
||||
|
||||
const tests = [
|
||||
SELECTION_TESTS,
|
||||
APPLY_TESTS,
|
||||
APPLY_TESTS_CSS,
|
||||
CHANGE_TESTS,
|
||||
CHANGE_TESTS_CSS,
|
||||
UNAPPLY_TESTS,
|
||||
UNAPPLY_TESTS_CSS,
|
||||
DELETE_TESTS,
|
||||
FORWARDDELETE_TESTS,
|
||||
INSERT_TESTS,
|
||||
QUERYSUPPORTED_TESTS,
|
||||
QUERYENABLED_TESTS,
|
||||
QUERYINDETERM_TESTS,
|
||||
QUERYSTATE_TESTS,
|
||||
QUERYVALUE_TESTS,
|
||||
];
|
||||
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
runTestSuite(tests[i]);
|
||||
}
|
||||
|
||||
// Below alert is just a simple demonstration on how to access the test results.
|
||||
// Note that we only ran UNAPPLY tests above, so we have only results from that test set.
|
||||
//
|
||||
// The 'results' structure is as follows:
|
||||
//
|
||||
// results structure containing all results
|
||||
// [<suite ID>] structure containing the results for the given suite *)
|
||||
// .count number of tests in the given suite
|
||||
// .valscore sum of all test value results (HTML or query value)
|
||||
// .selscore sum of all selection results (HTML tests only)
|
||||
// [<class ID>] structure containing the results for the given class **)
|
||||
// .count number of tests in the given suite
|
||||
// .valscore sum of all test value results (HTML or query value)
|
||||
// .selscore sum of all selection results (HTML tests only)
|
||||
// [<test ID>] structure containing the reults for a given test ***)
|
||||
// .valscore value score (0 or 1), minimum over all containers
|
||||
// .selscore selection score (0 or 1), minimum over all containers (HTML tests only)
|
||||
// .valresult worst test value result (integer, see variables.js)
|
||||
// .selresult worst selection result (integer, see variables.js)
|
||||
// [<cont. ID>] structure containing the results of the test for a given container ****)
|
||||
// .valscore value score (0 or 1)
|
||||
// .selscore selection score (0 or 1)
|
||||
// .valresult value result (integer, see variables.js)
|
||||
// .selresult selection result (integer, see variables.js)
|
||||
// .output output string (mainly for use by the online version)
|
||||
// .innerHTML inner HTML of the testing container (<div> or <body>) after the test
|
||||
// .outerHTML outer HTML of the testing container (<div> or <body>) after the test
|
||||
// .bodyInnerHTML inner HTML of the <body> after the test
|
||||
// .bodyOuterHTML outer HTML of the <body> after the test
|
||||
//
|
||||
// *) <suite ID>: a 1-3 character ID, e.g. UNAPPLY_TESTS.id, or 'U' (both referring the same suite)
|
||||
// **) <class ID>: one of 'Proposed', 'RFC' or 'Finalized'
|
||||
// ***) <test ID>: the ID of the test, without the leading 'RTE2-<suite ID>_' part
|
||||
// ****) <container ID>: one of 'div' (test within a <div contenteditable="true">)
|
||||
// 'dM' (test with designMode = 'on')
|
||||
// 'body' (test within a <body contenteditable="true">)
|
||||
|
||||
if (UPDATE_TEST_RESULTS) {
|
||||
var newKnownFailures = {value: {}, select: {}};
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var category = tests[i];
|
||||
for (var group in results[category.id]) {
|
||||
switch (group) {
|
||||
// Skip the known properties
|
||||
case "count":
|
||||
case "valscore":
|
||||
case "selscore":
|
||||
case "time":
|
||||
break;
|
||||
default:
|
||||
for (var test_id in results[category.id][group]) {
|
||||
switch (test_id) {
|
||||
// Skip the known properties
|
||||
case "count":
|
||||
case "valscore":
|
||||
case "selscore":
|
||||
break;
|
||||
default:
|
||||
for (var structure in results[category.id][group][test_id]) {
|
||||
switch (structure) {
|
||||
// Only look at each test structure
|
||||
case "dM":
|
||||
case "body":
|
||||
case "div":
|
||||
if (!results[category.id][group][test_id][structure].valscore) {
|
||||
newKnownFailures.value[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
|
||||
}
|
||||
if (!results[category.id][group][test_id][structure].selscore) {
|
||||
newKnownFailures.select[category.id + "-" + group + "-" + test_id + "-" + structure] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var resultContainer = document.getElementById("results");
|
||||
resultContainer.style.display = "";
|
||||
resultContainer.textContent = JSON.stringify(newKnownFailures);
|
||||
} else {
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var category = tests[i];
|
||||
for (var group in results[category.id]) {
|
||||
switch (group) {
|
||||
// Skip the known properties
|
||||
case "count":
|
||||
case "valscore":
|
||||
case "selscore":
|
||||
case "time":
|
||||
break;
|
||||
default:
|
||||
for (var test_id in results[category.id][group]) {
|
||||
switch (test_id) {
|
||||
// Skip the known properties
|
||||
case "count":
|
||||
case "valscore":
|
||||
case "selscore":
|
||||
break;
|
||||
default:
|
||||
for (var structure in results[category.id][group][test_id]) {
|
||||
switch (structure) {
|
||||
// Only look at each test structure
|
||||
case "dM":
|
||||
case "body":
|
||||
case "div":
|
||||
var row = results[category.id][group][test_id][structure];
|
||||
var testName = [category.id, group, test_id, structure].join("-");
|
||||
(testName in knownFailures.value ? todo_is : is)(
|
||||
row.valscore, 1, "Browserscope richtext2 value: " + testName);
|
||||
(testName in knownFailures.select ? todo_is : is)(
|
||||
row.selscore, 1, "Browserscope richtext2 selection: " + testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Running all of the tests can take a long time, try to account for it
|
||||
SimpleTest.requestLongerTimeout(5);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="startTest()">
|
||||
<iframe name="iframe-dM" id="iframe-dM" src="lib/richtext2/richtext2/static/editable-dM.html"></iframe>
|
||||
<iframe name="iframe-body" id="iframe-body" src="lib/richtext2/richtext2/static/editable-body.html"></iframe>
|
||||
<iframe name="iframe-div" id="iframe-div" src="lib/richtext2/richtext2/static/editable-div.html"></iframe>
|
||||
<pre id="results" style="display: none"></pre>
|
||||
</body>
|
||||
</html>
|
||||
11
editor/libeditor/tests/bug527935.html
Normal file
11
editor/libeditor/tests/bug527935.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<body>
|
||||
<div id="content">
|
||||
<iframe id="formTarget" name="formTarget"></iframe>
|
||||
<form action="data:text/html," target="formTarget">
|
||||
<input name="test" id="initValue"><input type="submit">
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html
|
||||
15
editor/libeditor/tests/bug629172.html
Normal file
15
editor/libeditor/tests/bug629172.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<style>
|
||||
textarea { resize: none }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<textarea id="ltr-ref" style="display: none">test.</textarea>
|
||||
<textarea id="rtl-ref" style="display: none; direction: rtl">test.</textarea>
|
||||
</div
|
||||
</body>
|
||||
</html>
|
||||
14
editor/libeditor/tests/chrome.ini
Normal file
14
editor/libeditor/tests/chrome.ini
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[DEFAULT]
|
||||
skip-if = os == 'android'
|
||||
support-files = green.png
|
||||
|
||||
[test_bug489202.xul]
|
||||
[test_bug599983.xul]
|
||||
[test_bug607584.xul]
|
||||
[test_bug616590.xul]
|
||||
[test_bug780908.xul]
|
||||
[test_contenteditable_text_input_handling.html]
|
||||
[test_htmleditor_keyevent_handling.html]
|
||||
[test_set_document_title_transaction.html]
|
||||
[test_texteditor_keyevent_handling.html]
|
||||
skip-if = (debug && os=='win') || (os == 'linux') # Bug 1116205, leaks on windows debug, fails delete key on linux
|
||||
BIN
editor/libeditor/tests/data/cfhtml-chromium.txt
Normal file
BIN
editor/libeditor/tests/data/cfhtml-chromium.txt
Normal file
Binary file not shown.
BIN
editor/libeditor/tests/data/cfhtml-firefox.txt
Normal file
BIN
editor/libeditor/tests/data/cfhtml-firefox.txt
Normal file
Binary file not shown.
BIN
editor/libeditor/tests/data/cfhtml-ie.txt
Normal file
BIN
editor/libeditor/tests/data/cfhtml-ie.txt
Normal file
Binary file not shown.
18
editor/libeditor/tests/data/cfhtml-nocontext.txt
Normal file
18
editor/libeditor/tests/data/cfhtml-nocontext.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
Version:0.9
|
||||
StartHTML:-1
|
||||
EndHTML:-1
|
||||
StartFragment:0000000111
|
||||
EndFragment:0000000246
|
||||
<!--StartFragment-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Test</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
3.<b>1415926535897932</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
<!--EndFragment-->
|
||||
BIN
editor/libeditor/tests/data/cfhtml-ooo.txt
Normal file
BIN
editor/libeditor/tests/data/cfhtml-ooo.txt
Normal file
Binary file not shown.
8
editor/libeditor/tests/file_bug549262.html
Normal file
8
editor/libeditor/tests/file_bug549262.html
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<a href="">test</a>
|
||||
<div id="editor" contenteditable="true">abc</div>
|
||||
<div style="height: 20000px;"></div>
|
||||
</body>
|
||||
</html>
|
||||
7
editor/libeditor/tests/file_bug586662.html
Normal file
7
editor/libeditor/tests/file_bug586662.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<div style="height: 20000px;"></div>
|
||||
<textarea id="editor"></textarea>
|
||||
</body>
|
||||
</html>
|
||||
5
editor/libeditor/tests/file_bug674770-1.html
Normal file
5
editor/libeditor/tests/file_bug674770-1.html
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE>
|
||||
<script>
|
||||
localStorage["clicked"] = "true";
|
||||
close();
|
||||
</script>
|
||||
13
editor/libeditor/tests/file_bug915962.html
Normal file
13
editor/libeditor/tests/file_bug915962.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<button>Button</button>
|
||||
<img src="green.png" usemap="#map">
|
||||
<map name="map">
|
||||
<!-- This URL ensures that the link doesn't get clicked, since
|
||||
mochitests cannot access the outside network. -->
|
||||
<area shape="rect" coords="0,0,10,10" href="https://youtube.com/">
|
||||
</map>
|
||||
<div style="height: 20000px;" tabindex="-1"><hr></div>
|
||||
</body>
|
||||
</html>
|
||||
41
editor/libeditor/tests/file_select_all_without_body.html
Normal file
41
editor/libeditor/tests/file_select_all_without_body.html
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function is(aLeft, aRight, aMessage)
|
||||
{
|
||||
window.opener.SimpleTest.is(aLeft, aRight, aMessage);
|
||||
}
|
||||
|
||||
function unload()
|
||||
{
|
||||
window.opener.SimpleTest.finish();
|
||||
}
|
||||
|
||||
function boom()
|
||||
{
|
||||
var root = document.documentElement;
|
||||
while(root.firstChild) {
|
||||
root.removeChild(root.firstChild);
|
||||
}
|
||||
root.appendChild(document.createTextNode("Mozilla"));
|
||||
root.focus();
|
||||
cespan = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
|
||||
cespan.setAttributeNS(null, "contenteditable", "true");
|
||||
root.appendChild(cespan);
|
||||
try {
|
||||
document.execCommand("selectAll", false, null);
|
||||
} catch(e) { }
|
||||
|
||||
is(window.getSelection().toString(), "Mozilla",
|
||||
"The nodes are not selected");
|
||||
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.opener.SimpleTest.waitForFocus(boom, window);
|
||||
|
||||
</script></head>
|
||||
|
||||
<body onunload="unload();"></body>
|
||||
</html>
|
||||
BIN
editor/libeditor/tests/green.png
Normal file
BIN
editor/libeditor/tests/green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 334 B |
245
editor/libeditor/tests/mochitest.ini
Normal file
245
editor/libeditor/tests/mochitest.ini
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
data/cfhtml-chromium.txt
|
||||
data/cfhtml-firefox.txt
|
||||
data/cfhtml-ie.txt
|
||||
data/cfhtml-ooo.txt
|
||||
data/cfhtml-nocontext.txt
|
||||
file_bug549262.html
|
||||
file_bug586662.html
|
||||
file_bug674770-1.html
|
||||
file_bug915962.html
|
||||
file_select_all_without_body.html
|
||||
green.png
|
||||
spellcheck.js
|
||||
|
||||
[test_bug46555.html]
|
||||
[test_bug200416.html]
|
||||
[test_bug289384.html]
|
||||
skip-if = os != "mac"
|
||||
[test_bug290026.html]
|
||||
[test_bug291780.html]
|
||||
[test_bug309731.html]
|
||||
[test_bug316447.html]
|
||||
[test_bug318065.html]
|
||||
[test_bug332636.html]
|
||||
support-files = test_bug332636.html^headers^
|
||||
[test_bug366682.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug372345.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug404320.html]
|
||||
[test_bug408231.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug410986.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug414526.html]
|
||||
[test_bug417418.html]
|
||||
skip-if = android_version == '18' # bug 1147989
|
||||
[test_bug432225.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug439808.html]
|
||||
[test_bug442186.html]
|
||||
[test_bug449243.html]
|
||||
[test_bug455992.html]
|
||||
[test_bug456244.html]
|
||||
[test_bug460740.html]
|
||||
[test_bug468353.html]
|
||||
[test_bug471319.html]
|
||||
[test_bug471722.html]
|
||||
[test_bug478725.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug480647.html]
|
||||
[test_bug480972.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug483651.html]
|
||||
[test_bug484181.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug487524.html]
|
||||
[test_bug490879.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android' # bug 1299578
|
||||
[test_bug502673.html]
|
||||
[test_bug514156.html]
|
||||
[test_bug520189.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug525389.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug537046.html]
|
||||
[test_bug549262.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug550434.html]
|
||||
skip-if = android_version == '18' # bug 1147989
|
||||
[test_bug551704.html]
|
||||
subsuite = clipboard
|
||||
[test_bug552782.html]
|
||||
[test_bug567213.html]
|
||||
[test_bug569988.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug570144.html]
|
||||
[test_bug578771.html]
|
||||
skip-if = android_version == '18' # bug 1147989
|
||||
[test_bug586662.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug587461.html]
|
||||
[test_bug590554.html]
|
||||
[test_bug592592.html]
|
||||
[test_bug596001.html]
|
||||
subsuite = clipboard
|
||||
[test_bug596333.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug596506.html]
|
||||
[test_bug597331.html]
|
||||
skip-if = toolkit == 'android' || asan || (os == "win" && os_version != "5.1") # Bug 718316, Bug 1211213
|
||||
[test_bug597784.html]
|
||||
[test_bug599322.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug599983.html]
|
||||
[test_bug600570.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android' || (os == "win" && os_version != "5.1") # Bug 718316
|
||||
[test_bug602130.html]
|
||||
[test_bug603556.html]
|
||||
subsuite = clipboard
|
||||
[test_bug604532.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug607584.html]
|
||||
[test_bug611182.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug612128.html]
|
||||
[test_bug612447.html]
|
||||
[test_bug620906.html]
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_bug622371.html]
|
||||
skip-if = toolkit == 'android' #bug 957797
|
||||
[test_bug625452.html]
|
||||
[test_bug629845.html]
|
||||
[test_bug635636.html]
|
||||
skip-if = e10s || os == 'android'
|
||||
[test_bug636465.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug638596.html]
|
||||
[test_bug640321.html]
|
||||
skip-if = android_version == '18' # bug 1147989
|
||||
[test_bug641466.html]
|
||||
[test_bug645914.html]
|
||||
[test_bug646194.html]
|
||||
[test_bug668599.html]
|
||||
[test_bug674770-1.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug674770-2.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug674861.html]
|
||||
[test_bug676401.html]
|
||||
[test_bug677752.html]
|
||||
[test_bug681229.html]
|
||||
subsuite = clipboard
|
||||
[test_bug686203.html]
|
||||
[test_bug692520.html]
|
||||
[test_bug697842.html]
|
||||
[test_bug725069.html]
|
||||
[test_bug735059.html]
|
||||
[test_bug738366.html]
|
||||
[test_bug740784.html]
|
||||
[test_bug742261.html]
|
||||
[test_bug757371.html]
|
||||
[test_bug757771.html]
|
||||
[test_bug767684.html]
|
||||
[test_bug772796.html]
|
||||
skip-if = toolkit == 'android' # bug 1309431
|
||||
[test_bug773262.html]
|
||||
[test_bug780035.html]
|
||||
[test_bug787432.html]
|
||||
[test_bug790475.html]
|
||||
[test_bug795418.html]
|
||||
[test_bug795418-2.html]
|
||||
[test_bug795418-3.html]
|
||||
[test_bug795418-4.html]
|
||||
[test_bug795418-5.html]
|
||||
[test_bug795418-6.html]
|
||||
[test_bug795785.html]
|
||||
[test_bug796839.html]
|
||||
[test_bug830600.html]
|
||||
subsuite = clipboard
|
||||
skip-if = e10s
|
||||
[test_bug832025.html]
|
||||
[test_bug850043.html]
|
||||
[test_bug857487.html]
|
||||
[test_bug858918.html]
|
||||
[test_bug915962.html]
|
||||
[test_bug974309.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug966155.html]
|
||||
skip-if = os != "win"
|
||||
[test_bug966552.html]
|
||||
skip-if = os != "win"
|
||||
[test_bug998188.html]
|
||||
[test_bug1026397.html]
|
||||
[test_bug1053048.html]
|
||||
[test_bug1067255.html]
|
||||
[test_bug1068979.html]
|
||||
subsuite = clipboard
|
||||
[test_bug1094000.html]
|
||||
[test_bug1100966.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug1102906.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug1101392.html]
|
||||
subsuite = clipboard
|
||||
[test_bug1109465.html]
|
||||
[test_bug1140105.html]
|
||||
[test_bug1140617.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android' # bug 1299578
|
||||
[test_bug1153237.html]
|
||||
[test_bug1154791.html]
|
||||
skip-if = os == 'android'
|
||||
[test_bug1162952.html]
|
||||
[test_bug1181130-1.html]
|
||||
[test_bug1181130-2.html]
|
||||
[test_bug1186799.html]
|
||||
[test_bug1230473.html]
|
||||
[test_bug1247483.html]
|
||||
subsuite = clipboard
|
||||
skip-if = toolkit == 'android'
|
||||
[test_bug1248128.html]
|
||||
[test_bug1250010.html]
|
||||
[test_bug1257363.html]
|
||||
[test_bug1248185.html]
|
||||
[test_bug1258085.html]
|
||||
[test_bug1268736.html]
|
||||
[test_bug1270235.html]
|
||||
[test_bug1310912.html]
|
||||
skip-if = toolkit == 'android' # bug 1315898
|
||||
[test_bug1314790.html]
|
||||
[test_bug1315065.html]
|
||||
[test_bug1328023.html]
|
||||
[test_bug1330796.html]
|
||||
[test_bug1332876.html]
|
||||
|
||||
[test_CF_HTML_clipboard.html]
|
||||
subsuite = clipboard
|
||||
[test_composition_event_created_in_chrome.html]
|
||||
[test_contenteditable_focus.html]
|
||||
[test_dom_input_event_on_htmleditor.html]
|
||||
skip-if = toolkit == 'android' # bug 1054087
|
||||
[test_dom_input_event_on_texteditor.html]
|
||||
[test_dragdrop.html]
|
||||
skip-if = os == 'android'
|
||||
[test_keypress_untrusted_event.html]
|
||||
[test_root_element_replacement.html]
|
||||
[test_select_all_without_body.html]
|
||||
[test_spellcheck_pref.html]
|
||||
skip-if = toolkit == 'android'
|
||||
[test_backspace_vs.html]
|
||||
[test_css_chrome_load_access.html]
|
||||
skip-if = toolkit == 'android' # chrome urls not available due to packaging
|
||||
[test_selection_move_commands.html]
|
||||
20
editor/libeditor/tests/spellcheck.js
Normal file
20
editor/libeditor/tests/spellcheck.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
function isSpellingCheckOk(aEditor, aMisspelledWords) {
|
||||
var selcon = aEditor.selectionController;
|
||||
var sel = selcon.getSelection(selcon.SELECTION_SPELLCHECK);
|
||||
var numWords = sel.rangeCount;
|
||||
|
||||
is(numWords, aMisspelledWords.length, "Correct number of misspellings and words.");
|
||||
|
||||
if (numWords !== aMisspelledWords.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < numWords; ++i) {
|
||||
var word = String(sel.getRangeAt(i));
|
||||
is(word, aMisspelledWords[i], "Misspelling is what we think it is.");
|
||||
if (word !== aMisspelledWords[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
159
editor/libeditor/tests/test_CF_HTML_clipboard.html
Normal file
159
editor/libeditor/tests/test_CF_HTML_clipboard.html
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=572642
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 572642</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=572642">Mozilla Bug 572642</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="editor1" contenteditable="true"></div>
|
||||
<iframe id="editor2"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 572642 **/
|
||||
|
||||
function copyCF_HTML(cfhtml, success, failure) {
|
||||
const Cc = SpecialPowers.Cc;
|
||||
const Ci = SpecialPowers.Ci;
|
||||
const CF_HTML = "application/x-moz-nativehtml";
|
||||
|
||||
function getLoadContext() {
|
||||
return SpecialPowers.wrap(window).QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
}
|
||||
|
||||
var cb = Cc["@mozilla.org/widget/clipboard;1"].
|
||||
getService(Ci.nsIClipboard);
|
||||
|
||||
var counter = 0;
|
||||
function copyCF_HTML_worker(success, failure) {
|
||||
if (++counter > 50) {
|
||||
ok(false, "Timed out while polling clipboard for pasted data");
|
||||
failure();
|
||||
return;
|
||||
}
|
||||
|
||||
var flavors = [CF_HTML];
|
||||
if (!cb.hasDataMatchingFlavors(flavors, flavors.length, cb.kGlobalClipboard)) {
|
||||
setTimeout(function() { copyCF_HTML_worker(success, failure); }, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
var trans = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
trans.addDataFlavor(CF_HTML);
|
||||
cb.getData(trans, cb.kGlobalClipboard);
|
||||
var data = SpecialPowers.createBlankObject();
|
||||
try {
|
||||
trans.getTransferData(CF_HTML, data, {});
|
||||
data = SpecialPowers.wrap(data).value.QueryInterface(Ci.nsISupportsCString).data;
|
||||
} catch (e) {
|
||||
setTimeout(function() { copyCF_HTML_worker(success, failure); }, 100);
|
||||
return;
|
||||
}
|
||||
success();
|
||||
}
|
||||
|
||||
var trans = Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
trans.addDataFlavor(CF_HTML);
|
||||
var data = Cc["@mozilla.org/supports-cstring;1"].
|
||||
createInstance(Ci.nsISupportsCString);
|
||||
data.data = cfhtml;
|
||||
trans.setTransferData(CF_HTML, data, cfhtml.length);
|
||||
cb.setData(trans, null, cb.kGlobalClipboard);
|
||||
copyCF_HTML_worker(success, failure);
|
||||
}
|
||||
|
||||
function loadCF_HTMLdata(filename) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", filename, false);
|
||||
req.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
req.send(null);
|
||||
ok(req.status, 200, "Could not read the binary file " + filename);
|
||||
return req.responseText;
|
||||
}
|
||||
|
||||
var gTests = [
|
||||
// Copied from Firefox
|
||||
{fileName: "cfhtml-firefox.txt", expected: "Firefox"},
|
||||
// Copied from OpenOffice.org
|
||||
{fileName: "cfhtml-ooo.txt", expected: "hello"},
|
||||
// Copied from IE
|
||||
{fileName: "cfhtml-ie.txt", expected: "browser"},
|
||||
// Copied from Chromium
|
||||
{fileName: "cfhtml-chromium.txt", expected: "Pacific"},
|
||||
// CF_HTML with no context specified (StartHTML and EndHTML set to -1)
|
||||
{fileName: "cfhtml-nocontext.txt", expected: "3.1415926535897932"},
|
||||
];
|
||||
var gTestIndex = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
for (var i = 0; i < gTests.length; ++i) {
|
||||
gTests[i].data = loadCF_HTMLdata("data/" + gTests[i].fileName);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
var test = gTests[gTestIndex++];
|
||||
|
||||
copyCF_HTML(test.data, function() {
|
||||
// contenteditable
|
||||
var contentEditable = document.getElementById("editor1");
|
||||
contentEditable.innerHTML = "";
|
||||
contentEditable.focus();
|
||||
synthesizeKey("v", {accelKey: true});
|
||||
isnot(contentEditable.textContent.indexOf(test.expected), -1,
|
||||
"Paste operation for " + test.fileName + " should be successful in contenteditable");
|
||||
|
||||
// designMode
|
||||
var iframe = document.getElementById("editor2");
|
||||
iframe.addEventListener("load", function() {
|
||||
iframe.removeEventListener("load", arguments.callee, false);
|
||||
var doc = iframe.contentDocument;
|
||||
var win = doc.defaultView;
|
||||
setTimeout(function() {
|
||||
win.addEventListener("focus", function() {
|
||||
win.removeEventListener("focus", arguments.callee, false);
|
||||
doc.designMode = "on";
|
||||
synthesizeKey("v", {accelKey: true}, win);
|
||||
isnot(doc.body.textContent.indexOf(test.expected), -1,
|
||||
"Paste operation for " + test.fileName + " should be successful in designMode");
|
||||
|
||||
if (gTestIndex == gTests.length)
|
||||
SimpleTest.finish();
|
||||
else
|
||||
runTest();
|
||||
}, false);
|
||||
win.focus();
|
||||
}, 0);
|
||||
}, false);
|
||||
iframe.src = "data:text/html,";
|
||||
}, SimpleTest.finish);
|
||||
}
|
||||
|
||||
var isMac = ("nsILocalFileMac" in SpecialPowers.Ci);
|
||||
if (isMac)
|
||||
SimpleTest.waitForFocus(runTest);
|
||||
else {
|
||||
// This test is not yet supported on non-Mac platforms, see bug 574005.
|
||||
todo(false, "Test not supported on this platform");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
130
editor/libeditor/tests/test_backspace_vs.html
Normal file
130
editor/libeditor/tests/test_backspace_vs.html
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1216427
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1216427</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1216427">Mozilla Bug 1216427</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="edit1" contenteditable="true">a☺️b</div><!-- BMP symbol with VS16 -->
|
||||
<div id="edit2" contenteditable="true">a🌐︎b</div><!-- plane 1 symbol with VS15 -->
|
||||
<div id="edit3" contenteditable="true">a㐂󠄀b</div><!-- BMP ideograph with VS17 -->
|
||||
<div id="edit4" contenteditable="true">a𠀀󠄁b</div><!-- SMP ideograph with VS18 -->
|
||||
<div id="edit5" contenteditable="true">a☺︁︂︃b</div><!-- BMP symbol with extra VSes -->
|
||||
<div id="edit6" contenteditable="true">a𠀀󠄀󠄁󠄂b</div><!-- SMP symbol with extra VSes -->
|
||||
<!-- The Regional Indicator combinations here were supported by Apple Color Emoji
|
||||
even prior to the major extension of coverage in the 10.10.5 timeframe. -->
|
||||
<div id="edit7" contenteditable="true">a🇨🇳b</div><!-- Regional Indicator flag: CN -->
|
||||
<div id="edit8" contenteditable="true">a🇨🇳🇩🇪b</div><!-- two RI flags: CN, DE -->
|
||||
<div id="edit9" contenteditable="true">a🇨🇳🇩🇪🇪🇸b</div><!-- three RI flags: CN, DE, ES -->
|
||||
<div id="edit10" contenteditable="true">a🇨🇳🇩🇪🇪🇸🇫🇷b</div><!-- four RI flags: CN, DE, ES, FR -->
|
||||
<div id="edit11" contenteditable="true">a🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧b</div><!-- five RI flags: CN, DE, ES, FR, GB -->
|
||||
|
||||
<div id="edit1b" contenteditable="true">a☺️b</div><!-- BMP symbol with VS16 -->
|
||||
<div id="edit2b" contenteditable="true">a🌐︎b</div><!-- plane 1 symbol with VS15 -->
|
||||
<div id="edit3b" contenteditable="true">a㐂󠄀b</div><!-- BMP ideograph with VS17 -->
|
||||
<div id="edit4b" contenteditable="true">a𠀀󠄁b</div><!-- SMP ideograph with VS18 -->
|
||||
<div id="edit5b" contenteditable="true">a☺︁︂︃b</div><!-- BMP symbol with extra VSes -->
|
||||
<div id="edit6b" contenteditable="true">a𠀀󠄀󠄁󠄂b</div><!-- SMP symbol with extra VSes -->
|
||||
<div id="edit7b" contenteditable="true">a🇨🇳b</div><!-- Regional Indicator flag: CN -->
|
||||
<div id="edit8b" contenteditable="true">a🇨🇳🇩🇪b</div><!-- two RI flags: CN, DE -->
|
||||
<div id="edit9b" contenteditable="true">a🇨🇳🇩🇪🇪🇸b</div><!-- three RI flags: CN, DE, ES -->
|
||||
<div id="edit10b" contenteditable="true">a🇨🇳🇩🇪🇪🇸🇫🇷b</div><!-- four RI flags: CN, DE, ES, FR -->
|
||||
<div id="edit11b" contenteditable="true">a🇨🇳🇩🇪🇪🇸🇫🇷🇬🇧b</div><!-- five RI flags: CN, DE, ES, FR, GB -->
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1216427 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(runTest);
|
||||
|
||||
function test(edit, bsCount) {
|
||||
edit.focus();
|
||||
var sel = window.getSelection();
|
||||
sel.collapse(edit.childNodes[0], edit.textContent.length - 1);
|
||||
for (i = 0; i < bsCount; ++i) {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
}
|
||||
is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
}
|
||||
|
||||
function testWithMove(edit, offset, bsCount) {
|
||||
edit.focus();
|
||||
var sel = window.getSelection();
|
||||
sel.collapse(edit.childNodes[0], 0);
|
||||
var i;
|
||||
for (i = 0; i < offset; ++i) {
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
}
|
||||
for (i = 0; i < bsCount; ++i) {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
}
|
||||
is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
/* test backspace-deletion of the middle character(s) */
|
||||
test(document.getElementById("edit1"), 1);
|
||||
test(document.getElementById("edit2"), 1);
|
||||
test(document.getElementById("edit3"), 1);
|
||||
test(document.getElementById("edit4"), 1);
|
||||
test(document.getElementById("edit5"), 1);
|
||||
test(document.getElementById("edit6"), 1);
|
||||
|
||||
/*
|
||||
* Tests with Regional Indicator flags: these behave differently depending
|
||||
* whether an emoji font is present, as ligated flags are edited as single
|
||||
* characters whereas non-ligated RI characters act individually.
|
||||
*
|
||||
* For now, only rely on such an emoji font on OS X 10.7+. (Note that the
|
||||
* Segoe UI Emoji font on Win8.1 and Win10 does not implement Regional
|
||||
* Indicator flags.)
|
||||
*
|
||||
* Once the Firefox Emoji font is ready, we can load that via @font-face
|
||||
* and expect these tests to work across all platforms.
|
||||
*/
|
||||
hasEmojiFont =
|
||||
(navigator.platform.indexOf("Mac") == 0 &&
|
||||
/10\.([7-9]|[1-9][0-9])/.test(navigator.oscpu));
|
||||
|
||||
if (hasEmojiFont) {
|
||||
test(document.getElementById("edit7"), 1);
|
||||
test(document.getElementById("edit8"), 2);
|
||||
test(document.getElementById("edit9"), 3);
|
||||
test(document.getElementById("edit10"), 4);
|
||||
test(document.getElementById("edit11"), 5);
|
||||
}
|
||||
|
||||
/* extra tests with the use of RIGHT and LEFT to get to the right place */
|
||||
testWithMove(document.getElementById("edit1b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit2b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit3b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit4b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit5b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit6b"), 2, 1);
|
||||
if (hasEmojiFont) {
|
||||
testWithMove(document.getElementById("edit7b"), 2, 1);
|
||||
testWithMove(document.getElementById("edit8b"), 3, 2);
|
||||
testWithMove(document.getElementById("edit9b"), 4, 3);
|
||||
testWithMove(document.getElementById("edit10b"), 5, 4);
|
||||
testWithMove(document.getElementById("edit11b"), 6, 5);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
103
editor/libeditor/tests/test_bug1026397.html
Normal file
103
editor/libeditor/tests/test_bug1026397.html
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1026397
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1026397</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1026397">Mozilla Bug 1026397</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input id="input">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1026397 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var input = document.getElementById("input");
|
||||
input.focus();
|
||||
|
||||
function doTest(aMaxLength, aInitialValue, aCaretOffset,
|
||||
aInsertString, aExpectedValueDuringComposition,
|
||||
aExpectedValueAfterCompositionEnd, aAdditionalExplanation)
|
||||
{
|
||||
input.value = aInitialValue;
|
||||
var maxLengthStr = "";
|
||||
if (aMaxLength >= 0) {
|
||||
input.maxLength = aMaxLength;
|
||||
maxLengthStr = aMaxLength.toString();
|
||||
} else {
|
||||
input.removeAttribute("maxlength");
|
||||
maxLengthStr = "not specified";
|
||||
}
|
||||
input.selectionStart = input.selectionEnd = aCaretOffset;
|
||||
if (aAdditionalExplanation) {
|
||||
aAdditionalExplanation = " " + aAdditionalExplanation;
|
||||
} else {
|
||||
aAdditionalExplanation = "";
|
||||
}
|
||||
|
||||
synthesizeCompositionChange(
|
||||
{ "composition":
|
||||
{ "string": aInsertString,
|
||||
"clauses":
|
||||
[
|
||||
{ "length": aInsertString.length, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
|
||||
]
|
||||
},
|
||||
"caret": { "start": aInsertString.length, "length": 0 }
|
||||
});
|
||||
is(input.value, aExpectedValueDuringComposition,
|
||||
"The value of input whose maxlength is " + maxLengthStr + " should be "
|
||||
+ aExpectedValueDuringComposition + " during composition" + aAdditionalExplanation);
|
||||
synthesizeComposition({ type: "compositioncommitasis" });
|
||||
is(input.value, aExpectedValueAfterCompositionEnd,
|
||||
"The value of input whose maxlength is " + maxLengthStr + " should be "
|
||||
+ aExpectedValueAfterCompositionEnd + " after compositionend" + aAdditionalExplanation);
|
||||
}
|
||||
|
||||
// maxlength hasn't been specified yet.
|
||||
doTest(-1, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6");
|
||||
|
||||
// maxlength="1"
|
||||
doTest(1, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "");
|
||||
|
||||
// maxlength="2"
|
||||
doTest(2, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7");
|
||||
doTest(2, "X", 1, "\uD842\uDFB7\u91CE\u5BB6", "X\uD842\uDFB7\u91CE\u5BB6", "X");
|
||||
doTest(2, "Y", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6Y", "Y");
|
||||
|
||||
// maxlength="3"
|
||||
doTest(3, "", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE");
|
||||
doTest(3, "A", 1, "\uD842\uDFB7\u91CE\u5BB6", "A\uD842\uDFB7\u91CE\u5BB6", "A\uD842\uDFB7");
|
||||
doTest(3, "B", 0, "\uD842\uDFB7\u91CE\u5BB6", "\uD842\uDFB7\u91CE\u5BB6B", "\uD842\uDFB7B");
|
||||
doTest(3, "CD", 1, "\uD842\uDFB7\u91CE\u5BB6", "C\uD842\uDFB7\u91CE\u5BB6D", "CD");
|
||||
|
||||
// maxlength="4"
|
||||
doTest(4, "EF", 1, "\uD842\uDFB7\u91CE\u5BB6", "E\uD842\uDFB7\u91CE\u5BB6F", "E\uD842\uDFB7F");
|
||||
doTest(4, "GHI", 1, "\uD842\uDFB7\u91CE\u5BB6", "G\uD842\uDFB7\u91CE\u5BB6HI", "GHI");
|
||||
|
||||
// maxlength="1", inputting only high surrogate
|
||||
doTest(1, "", 0, "\uD842", "\uD842", "\uD842", "even if input string is only a high surrogate");
|
||||
|
||||
// maxlength="1", inputting only low surrogate
|
||||
doTest(1, "", 0, "\uDFB7", "\uDFB7", "\uDFB7", "even if input string is only a low surrogate");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
73
editor/libeditor/tests/test_bug1053048.html
Normal file
73
editor/libeditor/tests/test_bug1053048.html
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1053048
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1053048</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1053048 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
const nsISelectionPrivate = SpecialPowers.Ci.nsISelectionPrivate;
|
||||
const nsISelectionListener = SpecialPowers.Ci.nsISelectionListener;
|
||||
const nsIDOMNSEditableElement = SpecialPowers.Ci.nsIDOMNSEditableElement;
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var textarea = SpecialPowers.wrap(document.getElementById("textarea"));
|
||||
textarea.focus();
|
||||
|
||||
var editor = textarea.QueryInterface(nsIDOMNSEditableElement).editor;
|
||||
var selectionPrivate = editor.selection.QueryInterface(nsISelectionPrivate);
|
||||
|
||||
var selectionListener = {
|
||||
count: 0,
|
||||
notifySelectionChanged: function (aDocument, aSelection, aReason)
|
||||
{
|
||||
ok(true, "selectionStart: " + textarea.selectionStart);
|
||||
ok(true, "selectionEnd: " + textarea.selectionEnd);
|
||||
this.count++;
|
||||
}
|
||||
};
|
||||
|
||||
// Move caret to the end of the textarea
|
||||
synthesizeMouse(textarea, 290, 10, {});
|
||||
is(textarea.selectionStart, 3, "selectionStart should be 3 (after \"foo\")");
|
||||
is(textarea.selectionEnd, 3, "selectionEnd should be 3 (after \"foo\")");
|
||||
|
||||
selectionPrivate.addSelectionListener(selectionListener);
|
||||
|
||||
sendKey("RETURN");
|
||||
is(selectionListener.count, 1, "nsISelectionListener.notifySelectionChanged() should be called");
|
||||
is(textarea.selectionStart, 4, "selectionStart should be 4");
|
||||
is(textarea.selectionEnd, 4, "selectionEnd should be 4");
|
||||
is(textarea.value, "foo\n", "The line break should be appended");
|
||||
|
||||
selectionPrivate.removeSelectionListener(selectionListener);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1053048">Mozilla Bug 1053048</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
|
||||
<textarea id="textarea"
|
||||
style="height: 100px; width: 300px; -moz-appearance: none"
|
||||
spellcheck="false"
|
||||
onkeydown="this.style.display='block'; this.style.height='200px';">foo</textarea>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
57
editor/libeditor/tests/test_bug1067255.html
Normal file
57
editor/libeditor/tests/test_bug1067255.html
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!-- 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/. -->
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1067255
|
||||
-->
|
||||
|
||||
<head>
|
||||
<title>Test for Bug 1067255</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
|
||||
<body onload="doTest();">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1067255">Mozilla Bug 1067255</a>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1067255 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function doTest() {
|
||||
var text = $("text-field");
|
||||
var password = $("password-field");
|
||||
|
||||
var editor1 = SpecialPowers.wrap(text).editor;
|
||||
var editor2 = SpecialPowers.wrap(password).editor;
|
||||
|
||||
text.focus();
|
||||
text.select();
|
||||
|
||||
ok(editor1.canCopy(), "can copy, text");
|
||||
ok(editor1.canCut(), "can cut, text");
|
||||
ok(editor1.canDelete(), "can delete, text");
|
||||
|
||||
password.focus();
|
||||
password.select();
|
||||
|
||||
// Copy and cut commands don't do anything on passoword fields by default,
|
||||
// but webpages can hook up event handlers to the event, and thus, we have to
|
||||
// always keep the cut and copy event enabled in HTML/XHTML documents.
|
||||
ok(editor2.canCopy(), "can copy, password");
|
||||
ok(editor2.canCut(), "can cut, password");
|
||||
ok(editor2.canDelete(), "can delete, password");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
<input type="text" value="Gonzo says hi" id="text-field" />
|
||||
<input type="password" value="Jan also" id="password-field" />
|
||||
</body>
|
||||
</html>
|
||||
72
editor/libeditor/tests/test_bug1068979.html
Normal file
72
editor/libeditor/tests/test_bug1068979.html
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1068979
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1068979</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1068979">Mozilla Bug 1068979</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="editor1" contenteditable="true">𝐀</div>
|
||||
<div id="editor2" contenteditable="true">a<u>𝐁</u>b</div>
|
||||
<div id="editor3" contenteditable="true">a𝐂<u>b</u></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1068979 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Test backspacing over SMP characters pasted-in to a contentEditable
|
||||
getSelection().selectAllChildren(document.getElementById("editor1"));
|
||||
var ed1 = document.getElementById("editor1");
|
||||
var ch1 = ed1.textContent;
|
||||
ed1.focus();
|
||||
synthesizeKey("C", {accelKey: true});
|
||||
synthesizeKey("V", {accelKey: true});
|
||||
synthesizeKey("V", {accelKey: true});
|
||||
synthesizeKey("V", {accelKey: true});
|
||||
synthesizeKey("V", {accelKey: true});
|
||||
is(ed1.textContent, ch1 + ch1 + ch1 + ch1, "Should have four SMP characters");
|
||||
sendKey("back_space");
|
||||
is(ed1.textContent, ch1 + ch1 + ch1, "Three complete characters should remain");
|
||||
sendKey("back_space");
|
||||
is(ed1.textContent, ch1 + ch1, "Two complete characters should remain");
|
||||
sendKey("back_space");
|
||||
is(ed1.textContent, ch1, "Only one complete SMP character should remain");
|
||||
ed1.blur();
|
||||
|
||||
// Test backspacing across an SMP character in a sub-element
|
||||
getSelection().selectAllChildren(document.getElementById("editor2"));
|
||||
var ed2 = document.getElementById("editor2");
|
||||
ed2.focus();
|
||||
sendKey("right");
|
||||
sendKey("back_space");
|
||||
sendKey("back_space");
|
||||
is(ed2.textContent, "a", "Only the 'a' should remain");
|
||||
ed2.blur();
|
||||
|
||||
// Test backspacing across an SMP character from a following sub-element
|
||||
getSelection().selectAllChildren(document.getElementById("editor3"));
|
||||
var ed3 = document.getElementById("editor3");
|
||||
ed3.focus();
|
||||
sendKey("right");
|
||||
sendKey("left");
|
||||
sendKey("back_space");
|
||||
is(ed3.textContent, "ab", "The letters 'ab' should remain");
|
||||
ed3.blur();
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
104
editor/libeditor/tests/test_bug1094000.html
Normal file
104
editor/libeditor/tests/test_bug1094000.html
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1094000
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1094000</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094000">Mozilla Bug 1094000</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="editor0" contenteditable></div>
|
||||
<div id="editor1" contenteditable><br></div>
|
||||
<div id="editor2" contenteditable>a</div>
|
||||
<div id="editor3" contenteditable>b</div>
|
||||
<div id="editor4" contenteditable>c</div>
|
||||
<div id="editor5" contenteditable>d</div>
|
||||
<div id="editor6" contenteditable>e</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1094000 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const kIsLinux = navigator.platform.indexOf("Linux") == 0;
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var editor0 = document.getElementById("editor0");
|
||||
var editor1 = document.getElementById("editor1");
|
||||
var editor2 = document.getElementById("editor2");
|
||||
var editor3 = document.getElementById("editor3");
|
||||
var editor4 = document.getElementById("editor4");
|
||||
var editor5 = document.getElementById("editor5");
|
||||
var editor6 = document.getElementById("editor6");
|
||||
|
||||
ok(editor1.getBoundingClientRect().height - editor0.getBoundingClientRect().height > 1,
|
||||
"an editor having a <br> element and an empty editor shouldn't be same height");
|
||||
ok(Math.abs(editor1.getBoundingClientRect().height - editor2.getBoundingClientRect().height) <= 1,
|
||||
"an editor having only a <br> element and an editor having \"a\" should be same height");
|
||||
|
||||
editor2.focus();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
is(editor2.innerHTML, "<br>",
|
||||
"an editor which had \"a\" should have only <br> element after Backspace keypress");
|
||||
ok(Math.abs(editor2.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
|
||||
"an editor whose content was removed by Backspace key should have a place to put a caret");
|
||||
|
||||
editor3.focus();
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
is(editor3.innerHTML, "<br>",
|
||||
"an editor which had \"b\" should have only <br> element after Delete keypress");
|
||||
ok(Math.abs(editor3.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
|
||||
"an editor whose content was removed by Delete key should have a place to put a caret");
|
||||
|
||||
editor4.focus();
|
||||
window.getSelection().selectAllChildren(editor4);
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
is(editor4.innerHTML, "<br>",
|
||||
"an editor which had \"c\" should have only <br> element after removing selected text with Backspace key");
|
||||
ok(Math.abs(editor4.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
|
||||
"an editor whose content was selected and removed by Backspace key should have a place to put a caret");
|
||||
|
||||
editor5.focus();
|
||||
window.getSelection().selectAllChildren(editor5);
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
is(editor5.innerHTML, "<br>",
|
||||
"an editor which had \"d\" should have only <br> element after removing selected text with Delete key");
|
||||
ok(Math.abs(editor5.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
|
||||
"an editor whose content was selected and removed by Delete key should have a place to put a caret");
|
||||
|
||||
editor6.focus();
|
||||
window.getSelection().selectAllChildren(editor6);
|
||||
synthesizeKey("x", { accelKey: true });
|
||||
is(editor6.innerHTML, "<br>",
|
||||
"an editor which had \"e\" should have only <br> element after removing selected text by \"Cut\"");
|
||||
ok(Math.abs(editor6.getBoundingClientRect().height - editor1.getBoundingClientRect().height) <= 1,
|
||||
"an editor whose content was selected and removed by \"Cut\" should have a place to put a caret");
|
||||
|
||||
editor0.focus();
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
is(editor0.innerHTML, "",
|
||||
"an empty editor should keep being empty even if Backspace key is pressed");
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
is(editor0.innerHTML, "",
|
||||
"an empty editor should keep being empty even if Delete key is pressed");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
65
editor/libeditor/tests/test_bug1100966.html
Normal file
65
editor/libeditor/tests/test_bug1100966.html
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1100966
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1100966</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
</div>
|
||||
<div id="content" contenteditable>
|
||||
=====<br>
|
||||
correct<br>
|
||||
fivee sixx<br>
|
||||
====
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test for Bug 1100966 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var div = document.getElementById("content");
|
||||
div.focus();
|
||||
synthesizeMouseAtCenter(div, {});
|
||||
|
||||
synthesizeKey(" ", {});
|
||||
setTimeout(function() {
|
||||
synthesizeKey("a", {});
|
||||
setTimeout(function() {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
|
||||
var sel = getSpellCheckSelection();
|
||||
is(sel.rangeCount, 2, "We should have two misspelled words");
|
||||
is(String(sel.getRangeAt(0)), "fivee", "Correct misspelled word");
|
||||
is(String(sel.getRangeAt(1)), "sixx", "Correct misspelled word");
|
||||
|
||||
SimpleTest.finish();
|
||||
},0);
|
||||
},0);
|
||||
|
||||
});
|
||||
|
||||
function getSpellCheckSelection() {
|
||||
var Ci = SpecialPowers.Ci;
|
||||
var editingSession = SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
var editor = editingSession.getEditorForWindow(window);
|
||||
var selcon = editor.selectionController;
|
||||
return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
78
editor/libeditor/tests/test_bug1101392.html
Normal file
78
editor/libeditor/tests/test_bug1101392.html
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1101392
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1101392</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1101392 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTests);
|
||||
|
||||
function runCopyCommand(element, compareText, nextTest)
|
||||
{
|
||||
element.focus();
|
||||
var expectedEndpoint, sel;
|
||||
if (element.localName == "textarea") {
|
||||
element.select();
|
||||
expectedEndpoint = element.selectionEnd;
|
||||
} else {
|
||||
sel = getSelection();
|
||||
sel.selectAllChildren(element.parentNode);
|
||||
expectedEndpoint = [sel.getRangeAt(0).endContainer,
|
||||
sel.getRangeAt(0).endOffset];
|
||||
}
|
||||
|
||||
function checkCollapse() {
|
||||
var desc = " after cmd_copyAndCollapseToEnd for " +
|
||||
element.localName;
|
||||
if (element.localName == "textarea") {
|
||||
is(element.selectionStart, expectedEndpoint, "start offset" + desc);
|
||||
is(element.selectionEnd, expectedEndpoint, "end offset" + desc);
|
||||
} else {
|
||||
is(sel.isCollapsed, true, "collapsed" + desc);
|
||||
is(sel.anchorNode, expectedEndpoint[0], "node" + desc);
|
||||
is(sel.anchorOffset, expectedEndpoint[1], "offset" + desc);
|
||||
}
|
||||
|
||||
nextTest();
|
||||
}
|
||||
|
||||
SimpleTest.waitForClipboard(compareText,
|
||||
() => SpecialPowers.doCommand(window, "cmd_copyAndCollapseToEnd"),
|
||||
checkCollapse, checkCollapse);
|
||||
}
|
||||
|
||||
function testDiv()
|
||||
{
|
||||
var content = document.getElementById("content");
|
||||
runCopyCommand(content, 'abc', testTextarea);
|
||||
}
|
||||
|
||||
function testTextarea()
|
||||
{
|
||||
var textarea = document.getElementById("textarea");
|
||||
runCopyCommand(textarea, 'def', SimpleTest.finish);
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
testDiv();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1101392">Mozilla Bug 1101392</a>
|
||||
<div><div id="content">abc</div></div>
|
||||
|
||||
<textarea id="textarea">def</textarea>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
51
editor/libeditor/tests/test_bug1102906.html
Normal file
51
editor/libeditor/tests/test_bug1102906.html
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1102906
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1102906</title>
|
||||
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
/* Test for Bug 1102906 */
|
||||
/* The caret should be movable by using keyboard after drag-and-drop. */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus( () => {
|
||||
let content = document.getElementById("content");
|
||||
let drag = document.getElementById("drag")
|
||||
let selection = window.getSelection();
|
||||
|
||||
/* Perform drag-and-drop for an arbitrary content. The caret should be at
|
||||
the end of the contenteditable. */
|
||||
selection.selectAllChildren(drag);
|
||||
synthesizeDrop(drag, content, {}, "copy");
|
||||
|
||||
let textContentAfterDrop = content.textContent;
|
||||
|
||||
/* Move the caret to the front of the contenteditable by using keyboard. */
|
||||
for (let i = 0; i < content.textContent.length; ++i) {
|
||||
sendKey("LEFT");
|
||||
}
|
||||
sendChar("!");
|
||||
|
||||
is(content.textContent, "!" + textContentAfterDrop,
|
||||
"The exclamation mark should be inserted at the front.");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1102906">Mozilla Bug 1102906</a>
|
||||
<div id="content" contenteditable="true"><span id="drag">Drag</span></div>
|
||||
</body>
|
||||
</html>
|
||||
69
editor/libeditor/tests/test_bug1109465.html
Normal file
69
editor/libeditor/tests/test_bug1109465.html
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1109465
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1109465</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test for Bug 1109465 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var t = document.querySelector("textarea");
|
||||
t.focus();
|
||||
|
||||
// Type foo\nbar and place the caret at the end of the last line
|
||||
synthesizeKey("f", {});
|
||||
synthesizeKey("o", {});
|
||||
synthesizeKey("o", {});
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("b", {});
|
||||
synthesizeKey("a", {});
|
||||
synthesizeKey("r", {});
|
||||
synthesizeKey("VK_UP", {});
|
||||
is(t.selectionStart, 3, "Correct start of selection");
|
||||
is(t.selectionEnd, 3, "Correct end of selection");
|
||||
|
||||
// Compose an IME string
|
||||
synthesizeComposition({ type: "compositionstart" });
|
||||
var composingString = "\u306B";
|
||||
synthesizeCompositionChange(
|
||||
{ "composition":
|
||||
{ "string": composingString,
|
||||
"clauses":
|
||||
[
|
||||
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
|
||||
]
|
||||
},
|
||||
"caret": { "start": 1, "length": 0 }
|
||||
});
|
||||
synthesizeComposition({ type: "compositioncommitasis" });
|
||||
is(t.value, "foo\u306B\nbar", "Correct value after composition");
|
||||
|
||||
// Now undo to test that the transaction merger has correctly detected the
|
||||
// IMETextTxn.
|
||||
synthesizeKey("Z", {accelKey: true});
|
||||
is(t.value, "foo\nbar", "Correct value after undo");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
71
editor/libeditor/tests/test_bug1140105.html
Normal file
71
editor/libeditor/tests/test_bug1140105.html
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1140105
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1140105</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
</div>
|
||||
|
||||
<div id="content" contenteditable><font face="Arial">1234567890</font></div>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test for Bug 1140105 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var div = document.getElementById("content");
|
||||
div.focus();
|
||||
synthesizeMouseAtCenter(div, {});
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
|
||||
var sel = window.getSelection();
|
||||
var selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be in text node");
|
||||
is(selRange.endOffset, 9, "offset should be 9");
|
||||
|
||||
var firstHas = {};
|
||||
var anyHas = {};
|
||||
var allHas = {};
|
||||
var editor = getEditor();
|
||||
|
||||
var atomService = SpecialPowers.Cc["@mozilla.org/atom-service;1"].getService(SpecialPowers.Ci.nsIAtomService);
|
||||
var propAtom = atomService.getAtom("font");
|
||||
editor.getInlineProperty(propAtom, "face", "Arial", firstHas, anyHas, allHas);
|
||||
is(firstHas.value, true, "Test for Arial: firstHas: true expected");
|
||||
is(anyHas.value, true, "Test for Arial: anyHas: true expected");
|
||||
is(allHas.value, true, "Test for Arial: allHas: true expected");
|
||||
editor.getInlineProperty(propAtom, "face", "Courier", firstHas, anyHas, allHas);
|
||||
is(firstHas.value, false, "Test for Courier: firstHas: false expected");
|
||||
is(anyHas.value, false, "Test for Courier: anyHas: false expected");
|
||||
is(allHas.value, false, "Test for Courier: allHas: false expected");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
function getEditor() {
|
||||
var Ci = SpecialPowers.Ci;
|
||||
var editingSession = SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
var editor = editingSession.getEditorForWindow(window);
|
||||
editor.QueryInterface(Ci.nsIHTMLEditor);
|
||||
return editor;
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
37
editor/libeditor/tests/test_bug1140617.html
Normal file
37
editor/libeditor/tests/test_bug1140617.html
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<!doctype html>
|
||||
<title>Mozilla Bug 1140617</title>
|
||||
<link rel=stylesheet href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1140617"
|
||||
target="_blank">Mozilla Bug 1140617</a>
|
||||
<iframe id="i1" width="200" height="100" src="about:blank"></iframe>
|
||||
<img id="i" src="green.png">
|
||||
<script>
|
||||
function runTest() {
|
||||
SpecialPowers.setCommandNode(window, document.getElementById("i"));
|
||||
SpecialPowers.doCommand(window, "cmd_copyImageContents");
|
||||
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
doc.designMode = "on";
|
||||
doc.defaultView.focus();
|
||||
var selection = doc.defaultView.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.selectAllChildren(doc.body);
|
||||
selection.collapseToEnd();
|
||||
|
||||
doc.execCommand("fontname", false, "Arial");
|
||||
doc.execCommand("bold", false, null);
|
||||
doc.execCommand("insertText", false, "12345");
|
||||
doc.execCommand("paste", false, null);
|
||||
doc.execCommand("insertText", false, "a");
|
||||
|
||||
is(doc.queryCommandValue("fontname"), "Arial", "Arial expected");
|
||||
is(doc.queryCommandState("bold"), true, "Bold expected");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(runTest);
|
||||
</script>
|
||||
49
editor/libeditor/tests/test_bug1153237.html
Normal file
49
editor/libeditor/tests/test_bug1153237.html
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1153237
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1153237</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Avoid platform selection differences
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["layout.word_select.eat_space_to_next_word", true]]
|
||||
}, runTests);
|
||||
});
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var element = document.getElementById("editor");
|
||||
var sel = window.getSelection();
|
||||
|
||||
element.focus();
|
||||
is(sel.getRangeAt(0).startOffset, 0, "offset is zero");
|
||||
|
||||
SpecialPowers.doCommand(window, "cmd_selectRight2");
|
||||
is(sel.toString(), "Some ",
|
||||
"first word + space is selected: got '" + sel.toString() + "'");
|
||||
|
||||
SpecialPowers.doCommand(window, "cmd_selectRight2");
|
||||
is(sel.toString(), "Some text",
|
||||
"both words are selected: got '" + sel.toString() + "'");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1153237">Mozilla Bug 1153237</a>
|
||||
<div id="editor" contenteditable>Some text</div><span></span>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
67
editor/libeditor/tests/test_bug1154791.html
Normal file
67
editor/libeditor/tests/test_bug1154791.html
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1154791
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1154791</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
</div>
|
||||
|
||||
<div id="content" contenteditable>
|
||||
<tt>thiss onee is stilll a</tt>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test for Bug 1154791 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var div = document.getElementById("content");
|
||||
div.focus();
|
||||
synthesizeMouseAtCenter(div, {});
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
|
||||
setTimeout(function() {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
setTimeout(function() {
|
||||
synthesizeKey(" ", {});
|
||||
|
||||
setTimeout(function() {
|
||||
var sel = getSpellCheckSelection();
|
||||
is(sel.rangeCount, 2, "We should have two misspelled words");
|
||||
is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word");
|
||||
is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word");
|
||||
|
||||
SimpleTest.finish();
|
||||
},0);
|
||||
},0);
|
||||
},0);
|
||||
|
||||
});
|
||||
|
||||
function getSpellCheckSelection() {
|
||||
var Ci = SpecialPowers.Ci;
|
||||
var editingSession = SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
var editor = editingSession.getEditorForWindow(window);
|
||||
var selcon = editor.selectionController;
|
||||
return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
43
editor/libeditor/tests/test_bug1162952.html
Normal file
43
editor/libeditor/tests/test_bug1162952.html
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1162952
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1162952</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1162952">Mozilla Bug 1162952</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 1162952 **/
|
||||
var userCallbackRun = false;
|
||||
|
||||
document.addEventListener('keydown', function() {
|
||||
// During a user callback, the commands should be enabled
|
||||
userCallbackRun = true;
|
||||
is(true, document.queryCommandEnabled('cut'));
|
||||
is(true, document.queryCommandEnabled('copy'));
|
||||
});
|
||||
|
||||
// Otherwise, they should be disabled
|
||||
is(false, document.queryCommandEnabled('cut'));
|
||||
is(false, document.queryCommandEnabled('copy'));
|
||||
|
||||
// Fire a user callback
|
||||
synthesizeKey('A', {});
|
||||
|
||||
ok(userCallbackRun, "User callback should've been run");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
50
editor/libeditor/tests/test_bug1181130-1.html
Normal file
50
editor/libeditor/tests/test_bug1181130-1.html
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1181130
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1181130</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1181130">Mozilla Bug 1181130</a>
|
||||
<p id="display"></p>
|
||||
<div id="container" contenteditable="true">
|
||||
editable div
|
||||
<div id="noneditable" contenteditable="false">
|
||||
non-editable div
|
||||
<div id="editable" contenteditable="true">nested editable div</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1181130 **/
|
||||
var container = document.getElementById("container");
|
||||
var noneditable = document.getElementById("noneditable");
|
||||
var editable = document.getElementById("editable");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
synthesizeMouseAtCenter(noneditable, {});
|
||||
ok(!document.getSelection().toString().includes("nested editable div"),
|
||||
"Selection should not include non-editable content");
|
||||
|
||||
synthesizeMouseAtCenter(container, {});
|
||||
ok(!document.getSelection().toString().includes("nested editable div"),
|
||||
"Selection should not include non-editable content");
|
||||
|
||||
synthesizeMouseAtCenter(editable, {});
|
||||
ok(!document.getSelection().toString().includes("nested editable div"),
|
||||
"Selection should not include non-editable content");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
44
editor/libeditor/tests/test_bug1181130-2.html
Normal file
44
editor/libeditor/tests/test_bug1181130-2.html
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1181130
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1181130</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1181130">Mozilla Bug 1181130</a>
|
||||
<p id="display"></p>
|
||||
<div id="container" contenteditable="true">
|
||||
editable div
|
||||
<div id="noneditable" contenteditable="false">
|
||||
non-editable div
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1181130 **/
|
||||
var container = document.getElementById("container");
|
||||
var noneditable = document.getElementById("noneditable");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var nonHTMLElement = document.createElementNS("http://www.example.com", "element");
|
||||
nonHTMLElement.innerHTML = '<div contenteditable="true">nested editable div</div>';
|
||||
noneditable.appendChild(nonHTMLElement);
|
||||
|
||||
synthesizeMouseAtCenter(noneditable, {});
|
||||
ok(!document.getSelection().toString().includes("nested editable div"),
|
||||
"Selection should not include non-editable content");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
81
editor/libeditor/tests/test_bug1186799.html
Normal file
81
editor/libeditor/tests/test_bug1186799.html
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1186799
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1186799</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1186799">Mozilla Bug 1186799</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<span id="span">span</span>
|
||||
<div id="editor" contenteditable></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 1186799 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var span = document.getElementById("span");
|
||||
var editor = document.getElementById("editor");
|
||||
editor.focus();
|
||||
|
||||
synthesizeCompositionChange(
|
||||
{ "composition":
|
||||
{ "string": "\u3042",
|
||||
"clauses":
|
||||
[
|
||||
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
|
||||
]
|
||||
},
|
||||
"caret": { "start": 1, "length": 0 }
|
||||
});
|
||||
|
||||
ok(isThereIMESelection(), "There should be IME selection");
|
||||
|
||||
var compositionEnd = false;
|
||||
editor.addEventListener("compositionend", function () { compositionEnd = true; }, true);
|
||||
|
||||
synthesizeMouseAtCenter(span, {});
|
||||
|
||||
ok(compositionEnd, "composition end should be fired at clicking outside of the editor");
|
||||
ok(!isThereIMESelection(), "There should be no IME selection");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
function isThereIMESelection()
|
||||
{
|
||||
var selCon = SpecialPowers.wrap(window).
|
||||
QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
|
||||
getInterface(SpecialPowers.Ci.nsIWebNavigation).
|
||||
QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor).
|
||||
getInterface(SpecialPowers.Ci.nsIEditingSession).
|
||||
getEditorForWindow(window).
|
||||
selectionController;
|
||||
const kIMESelections = [
|
||||
SpecialPowers.Ci.nsISelectionController.SELECTION_IME_RAWINPUT,
|
||||
SpecialPowers.Ci.nsISelectionController.SELECTION_IME_SELECTEDRAWTEXT,
|
||||
SpecialPowers.Ci.nsISelectionController.SELECTION_IME_CONVERTEDTEXT,
|
||||
SpecialPowers.Ci.nsISelectionController.SELECTION_IME_SELECTEDCONVERTEDTEXT
|
||||
];
|
||||
for (var i = 0; i < kIMESelections.length; i++) {
|
||||
var sel = selCon.getSelection(kIMESelections[i]);
|
||||
if (sel && sel.rangeCount) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
124
editor/libeditor/tests/test_bug1230473.html
Normal file
124
editor/libeditor/tests/test_bug1230473.html
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1230473
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1230473</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230473">Mozilla Bug 1230473</a>
|
||||
<input id="input">
|
||||
<textarea id="textarea"></textarea>
|
||||
<div id="div" contenteditable></div>
|
||||
<script type="application/javascript">
|
||||
/** Test for Bug 1230473 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(()=>{
|
||||
function runTest(aEditor) {
|
||||
function committer() {
|
||||
aEditor.blur();
|
||||
aEditor.focus();
|
||||
}
|
||||
function isNSEditableElement() {
|
||||
return aEditor.tagName.toLowerCase() == "input" || aEditor.tagName.toLowerCase() == "textarea";
|
||||
}
|
||||
function value() {
|
||||
return isNSEditableElement() ? aEditor.value : aEditor.textContent;
|
||||
}
|
||||
function isComposing() {
|
||||
return isNSEditableElement() ? SpecialPowers.wrap(aEditor)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDOMNSEditableElement)
|
||||
.editor
|
||||
.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
|
||||
.composing :
|
||||
SpecialPowers.wrap(window)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDocShell)
|
||||
.editor
|
||||
.QueryInterface(SpecialPowers.Ci.nsIEditorIMESupport)
|
||||
.composing;
|
||||
}
|
||||
function clear() {
|
||||
if (isNSEditableElement()) {
|
||||
aEditor.value = "";
|
||||
} else {
|
||||
aEditor.textContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
// Committing at compositionstart
|
||||
aEditor.focus();
|
||||
aEditor.addEventListener("compositionstart", committer, true);
|
||||
synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 1, length: 0 }});
|
||||
aEditor.removeEventListener("compositionstart", committer, true);
|
||||
ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionstart event handler");
|
||||
is(value(), "", "composition in " + aEditor.id + " shouldn't insert any text since it's committed at compositionstart");
|
||||
clear();
|
||||
|
||||
// Committing at first compositionupdate
|
||||
aEditor.focus();
|
||||
aEditor.addEventListener("compositionupdate", committer, true);
|
||||
synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 1, length: 0 }});
|
||||
aEditor.removeEventListener("compositionupdate", committer, true);
|
||||
ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
|
||||
is(value(), "", "composition in " + aEditor.id + " shouldn't have inserted any text since it's committed at first compositionupdate");
|
||||
clear();
|
||||
|
||||
// Committing at first text (eCompositionChange)
|
||||
aEditor.focus();
|
||||
aEditor.addEventListener("text", committer, true);
|
||||
synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 1, length: 0 }});
|
||||
aEditor.removeEventListener("text", committer, true);
|
||||
ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
|
||||
is(value(), "", "composition in " + aEditor.id + " should have inserted any text since it's committed at first text");
|
||||
clear();
|
||||
|
||||
// Committing at second compositionupdate
|
||||
aEditor.focus();
|
||||
synthesizeComposition({ type: "compositionstart" });
|
||||
synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 1, length: 0 }});
|
||||
ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second compositionupdate");
|
||||
is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second compositionupdate");
|
||||
aEditor.addEventListener("compositionupdate", committer, true);
|
||||
synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 2, length: 0 }});
|
||||
aEditor.removeEventListener("compositionupdate", committer, true);
|
||||
ok(!isComposing(), "composition in " + aEditor.id + " should be committed by compositionupdate event handler");
|
||||
todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second compositionupdate");
|
||||
clear();
|
||||
|
||||
// Committing at second text (eCompositionChange)
|
||||
aEditor.focus();
|
||||
synthesizeComposition({ type: "compositionstart" });
|
||||
synthesizeCompositionChange({ composition: { string: "a", clauses: [{length: 1, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 1, length: 0 }});
|
||||
ok(isComposing(), "composition should be in " + aEditor.id + " before dispatching second text");
|
||||
is(value(), "a", "composition in " + aEditor.id + " should be 'a' before dispatching second text");
|
||||
aEditor.addEventListener("text", committer, true);
|
||||
synthesizeCompositionChange({ composition: { string: "ab", clauses: [{length: 2, attr: COMPOSITION_ATTR_RAW_CLAUSE }] },
|
||||
caret: { start: 2, length: 0 }});
|
||||
aEditor.removeEventListener("text", committer, true);
|
||||
ok(!isComposing(), "composition in " + aEditor.id + " should be committed by text event handler");
|
||||
todo_is(value(), "a", "composition in " + aEditor.id + " shouldn't have been modified since it's committed at second text");
|
||||
clear();
|
||||
}
|
||||
runTest(document.getElementById("input"));
|
||||
runTest(document.getElementById("textarea"));
|
||||
runTest(document.getElementById("div"));
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
61
editor/libeditor/tests/test_bug1247483.html
Normal file
61
editor/libeditor/tests/test_bug1247483.html
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html><head>
|
||||
<title>Test for bug 1247483</title>
|
||||
<style src="/tests/SimpleTest/test.css" type="text/css"></style>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
// Copy content from table.
|
||||
var selection = getSelection();
|
||||
var startRange = document.createRange();
|
||||
startRange.setStart(document.getElementById("start"), 0);
|
||||
startRange.setEnd(document.getElementById("end"), 2);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(startRange);
|
||||
SpecialPowers.wrap(document).execCommand("copy", false, null);
|
||||
|
||||
// Paste content into "pastecontainer"
|
||||
var pasteContainer = document.getElementById("pastecontainer");
|
||||
var pasteRange = document.createRange();
|
||||
pasteRange.selectNodeContents(pasteContainer);
|
||||
pasteRange.collapse(false);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(pasteRange);
|
||||
SpecialPowers.wrap(document).execCommand("paste", false, null);
|
||||
|
||||
is(pasteContainer.querySelectorAll("td").length, 4, "4 <td> should be pasted.");
|
||||
|
||||
document.execCommand("undo", false, null);
|
||||
|
||||
is(pasteContainer.querySelectorAll("td").length, 0, "Undo should have remove the 4 pasted <td>.");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(runTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1247483">Mozilla Bug 1247483</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="container" contenteditable="true">
|
||||
<table>
|
||||
<tr id="start"><td>1 1</td><td>1 2</td></tr>
|
||||
<tr id="end"><td>2 1</td><td>2 2</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="pastecontainer" contenteditable="true">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
52
editor/libeditor/tests/test_bug1248128.html
Normal file
52
editor/libeditor/tests/test_bug1248128.html
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1248128
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1248128</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
var outer = document.querySelector("html");
|
||||
ok(outer.scrollTop == 0, "scrollTop is zero: got " + outer.scrollTop);
|
||||
|
||||
var input = document.getElementById("testInput");
|
||||
input.focus();
|
||||
|
||||
var scroll = outer.scrollTop;
|
||||
ok(scroll > 0, "element has scrolled: new value " + scroll);
|
||||
|
||||
try {
|
||||
SpecialPowers.doCommand(window, "cmd_moveLeft");
|
||||
ok(false, "should not be able to do kMoveLeft");
|
||||
} catch (e) {
|
||||
ok(true, "unable to perform kMoveLeft");
|
||||
}
|
||||
|
||||
ok(outer.scrollTop == scroll,
|
||||
"scroll is unchanged: got " + outer.scrollTop + ", expected " + scroll);
|
||||
|
||||
// Make sure cmd_moveLeft isn't failing for some unrelated reason
|
||||
synthesizeKey("a", {});
|
||||
is(input.selectionStart, 1, "selectionStart after typing");
|
||||
SpecialPowers.doCommand(window, "cmd_moveLeft");
|
||||
is(input.selectionStart, 0, "selectionStart after move left");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248128">Mozilla Bug 1248128</a>
|
||||
<div style="height: 2000px;"></div>
|
||||
<input type="text" id="testInput"></input>
|
||||
<div style="height: 200px;"></div>
|
||||
</body>
|
||||
</html>
|
||||
57
editor/libeditor/tests/test_bug1248185.html
Normal file
57
editor/libeditor/tests/test_bug1248185.html
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1248185
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1248185</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Avoid platform selection differences
|
||||
SimpleTest.waitForFocus(function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [["layout.word_select.eat_space_to_next_word", true]]
|
||||
}, runTests);
|
||||
});
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var editor = document.querySelector("#test");
|
||||
editor.focus();
|
||||
|
||||
var sel = window.getSelection();
|
||||
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
SpecialPowers.doCommand(window, "cmd_selectRight2");
|
||||
ok(sel.toString() == "three ", "expected 'three ' to be selected");
|
||||
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
SpecialPowers.doCommand(window, "cmd_moveRight2");
|
||||
ok(sel.toString() == "", "expected empty selection");
|
||||
|
||||
SpecialPowers.doCommand(window, "cmd_selectLeft2");
|
||||
ok(sel.toString() == "five", "expected 'five' to be selected");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248185">Mozilla Bug 1248185</a>
|
||||
<body>
|
||||
<div style="font: 12px monospace; width: 45ch;">
|
||||
<span contenteditable="" id="test">blablablablablablablablablablablablablabla one two three four five</span>
|
||||
<div>
|
||||
<span>foo</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
93
editor/libeditor/tests/test_bug1250010.html
Normal file
93
editor/libeditor/tests/test_bug1250010.html
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1250010
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1250010</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
</div>
|
||||
|
||||
<div id="test1" contenteditable><p><b><font color="red">1234567890</font></b></p></div>
|
||||
<div id="test2" contenteditable><p><tt>xyz</tt></p><p><tt><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAIAAABvrngfAAAAFklEQVQImWMwjWhCQwxECoW3oCHihAB0LyYv5/oAHwAAAABJRU5ErkJggg=="></tt></p></div>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
function getImageDataURI()
|
||||
{
|
||||
return document.getElementsByTagName("img")[0].getAttribute("src");
|
||||
}
|
||||
|
||||
/** Test for Bug 1250010 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
|
||||
// First test: Empty paragraph is split correctly.
|
||||
var div = document.getElementById("test1");
|
||||
div.focus();
|
||||
synthesizeMouseAtCenter(div, {});
|
||||
|
||||
var sel = window.getSelection();
|
||||
var selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 10, "offset should be 10");
|
||||
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("b", {});
|
||||
synthesizeKey("VK_UP", {});
|
||||
synthesizeKey("a", {});
|
||||
|
||||
is(div.innerHTML, "<p><b><font color=\"red\">1234567890</font></b></p>" +
|
||||
"<p><b><font color=\"red\">a<br></font></b></p>" +
|
||||
"<p><b><font color=\"red\">b<br></font></b></p>",
|
||||
"unexpected HTML");
|
||||
|
||||
// Second test: Since we modified the code path that splits non-text nodes,
|
||||
// test that this works, if the split node is not empty.
|
||||
div = document.getElementById("test2");
|
||||
div.focus();
|
||||
synthesizeMouseAtCenter(div, {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 3, "offset should be 3");
|
||||
|
||||
// Move behind the image and press enter, insert an "A".
|
||||
// That should insert a new empty paragraph with the "A" after what we have.
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("A", {});
|
||||
|
||||
// The resulting HTML is sadly less than optimal:
|
||||
// A <br> gets inserted after the image and the "A" is followed by an empty <tt></tt>.
|
||||
var newHTML = div.innerHTML;
|
||||
var expectedHTML;
|
||||
// Existing part with additional <br> inserted.
|
||||
expectedHTML = "<p><tt>xyz</tt></p><p><tt><img src=\"" + getImageDataURI() + "\"><br></tt></p>" +
|
||||
// New part caused by pressing enter after the image and typing an "A".
|
||||
"<p><tt>A</tt><br><tt></tt></p>";
|
||||
is(newHTML, expectedHTML, "unexpected HTML");
|
||||
|
||||
// In case the empty tag gets deleted some day, let them know that something improved.
|
||||
expectedHTML = "<p><tt>xyz</tt></p><p><tt><img src=\"" + getImageDataURI() + "\"><br></tt></p>" +
|
||||
"<p><tt>A</tt><br></p>";
|
||||
todo_is(newHTML, expectedHTML, "unexpected HTML");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
182
editor/libeditor/tests/test_bug1257363.html
Normal file
182
editor/libeditor/tests/test_bug1257363.html
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
<!DOCTYPE>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1257363
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1257363</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="display">
|
||||
</div>
|
||||
|
||||
<div id="backspaceCSS" contenteditable><p style="color:red;">12345</p>67</div>
|
||||
<div id="backspace" contenteditable><p><font color="red">12345</font></p>67</div>
|
||||
<div id="deleteCSS" contenteditable><p style="color:red;">x</p></div>
|
||||
<div id="delete" contenteditable><p><font color="red">y</font></p></div>
|
||||
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
/** Test for Bug 1257363 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
|
||||
// ***** Backspace test *****
|
||||
var div = document.getElementById("backspaceCSS");
|
||||
div.focus();
|
||||
synthesizeMouse(div, 100, 2, {}); /* click behind and down */
|
||||
|
||||
var sel = window.getSelection();
|
||||
var selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 5, "offset should be 5");
|
||||
|
||||
// Return and backspace should take us to where we started.
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 5, "offset should be 5");
|
||||
|
||||
// Add an "a" to the end of the paragraph.
|
||||
synthesizeKey("a", {});
|
||||
|
||||
// Return and forward delete should take us to the following line.
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
|
||||
// Add a "b" to the start.
|
||||
synthesizeKey("b", {});
|
||||
|
||||
is(div.innerHTML, "<p style=\"color:red;\">12345a</p>b67",
|
||||
"unexpected HTML");
|
||||
|
||||
// Let's repeat the whole thing, but a font tag instead of CSS.
|
||||
// The behaviour is different since the font is carried over.
|
||||
div = document.getElementById("backspace");
|
||||
div.focus();
|
||||
synthesizeMouse(div, 100, 2, {}); /* click behind and down */
|
||||
|
||||
sel = window.getSelection();
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 5, "offset should be 5");
|
||||
|
||||
// Return and backspace should take us to where we started.
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 5, "offset should be 5");
|
||||
|
||||
// Add an "a" to the end of the paragraph.
|
||||
synthesizeKey("a", {});
|
||||
|
||||
// Return and forward delete should take us to the following line.
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
|
||||
// Add a "b" to the start.
|
||||
synthesizeKey("b", {});
|
||||
|
||||
// Here we get a somewhat ugly result since the red sticks.
|
||||
is(div.innerHTML, "<p><font color=\"red\">12345a</font></p><font color=\"red\">b</font>67",
|
||||
"unexpected HTML");
|
||||
|
||||
// ***** Delete test *****
|
||||
div = document.getElementById("deleteCSS");
|
||||
div.focus();
|
||||
synthesizeMouse(div, 100, 2, {}); /* click behind and down */
|
||||
|
||||
var sel = window.getSelection();
|
||||
var selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 1, "offset should be 1");
|
||||
|
||||
// left, enter should create a new empty paragraph before
|
||||
// but leave the selection at the start of the existing paragraph.
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
is(selRange.endContainer.nodeValue, "x", "we should be in the text node with the x");
|
||||
|
||||
// Now moving up into the new empty paragraph.
|
||||
synthesizeKey("VK_UP", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "P", "selection should be the new empty paragraph");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
|
||||
// Forward delete should now take us to where we started.
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
|
||||
// Add an "a" to the start of the paragraph.
|
||||
synthesizeKey("a", {});
|
||||
|
||||
is(div.innerHTML, "<p style=\"color:red;\">ax</p>",
|
||||
"unexpected HTML");
|
||||
|
||||
// Let's repeat the whole thing, but a font tag instead of CSS.
|
||||
div = document.getElementById("delete");
|
||||
div.focus();
|
||||
synthesizeMouse(div, 100, 2, {}); /* click behind and down */
|
||||
|
||||
var sel = window.getSelection();
|
||||
var selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the end of text node");
|
||||
is(selRange.endOffset, 1, "offset should be 1");
|
||||
|
||||
// left, enter should create a new empty paragraph before
|
||||
// but leave the selection at the start of the existing paragraph.
|
||||
synthesizeKey("VK_LEFT", {});
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
is(selRange.endContainer.nodeValue, "y", "we should be in the text node with the y");
|
||||
|
||||
// Now moving up into the new empty paragraph.
|
||||
synthesizeKey("VK_UP", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "FONT", "selection should be the font tag");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
is(selRange.endContainer.parentNode.nodeName, "P", "the parent of the font should be a paragraph");
|
||||
|
||||
// Forward delete should now take us to where we started.
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
|
||||
selRange = sel.getRangeAt(0);
|
||||
is(selRange.endContainer.nodeName, "#text", "selection should be at the start of text node");
|
||||
is(selRange.endOffset, 0, "offset should be 0");
|
||||
|
||||
// Add an "a" to the start of the paragraph.
|
||||
synthesizeKey("a", {});
|
||||
|
||||
is(div.innerHTML, "<p><font color=\"red\">ay</font></p>",
|
||||
"unexpected HTML");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
66
editor/libeditor/tests/test_bug1258085.html
Normal file
66
editor/libeditor/tests/test_bug1258085.html
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test for Bug 1186799</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||
<div contenteditable></div>
|
||||
<script>
|
||||
var div = document.querySelector("div");
|
||||
|
||||
function reset() {
|
||||
div.innerHTML = "x<br> y";
|
||||
div.focus();
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
}
|
||||
|
||||
function checks(msg) {
|
||||
is(div.innerHTML, "x<br><br>",
|
||||
msg + ": Should add a second <br> to prevent collapse of first");
|
||||
is(div.childNodes.length, 3, msg + ": No empty text nodes allowed");
|
||||
ok(getSelection().isCollapsed, msg + ": Selection must be collapsed");
|
||||
is(getSelection().focusNode, div, msg + ": Focus must be in div");
|
||||
is(getSelection().focusOffset, 2,
|
||||
msg + ": Focus must be between the two <br>s");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function() {
|
||||
// Put selection after the "y" and backspace
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Collapsed backspace");
|
||||
|
||||
// Now do the same with delete
|
||||
reset();
|
||||
synthesizeKey("VK_DELETE", {});
|
||||
checks("Collapsed delete");
|
||||
|
||||
// Forward selection
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {shiftKey: true});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Forward-selected backspace");
|
||||
|
||||
// Backward selection
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_LEFT", {shiftKey: true});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
checks("Backward-selected backspace");
|
||||
|
||||
// Make sure we're not deleting if the whitespace isn't actually collapsed
|
||||
div.style.whiteSpace = "pre-wrap";
|
||||
reset();
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_RIGHT", {});
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
if (div.innerHTML, "x<br> ", "pre-wrap: Don't delete uncollapsed space");
|
||||
ok(getSelection().isCollapsed, "pre-wrap: Selection must be collapsed");
|
||||
is(getSelection().focusNode, div.lastChild,
|
||||
"pre-wrap: Focus must be in final text node");
|
||||
is(getSelection().focusOffset, 1, "pre-wrap: Focus must be at end of node");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
</script>
|
||||
64
editor/libeditor/tests/test_bug1268736.html
Normal file
64
editor/libeditor/tests/test_bug1268736.html
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1268736
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1268736</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268736">Mozilla Bug 1268736</a>
|
||||
<table id="table" border="1" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>a</td>
|
||||
<td>b</td>
|
||||
<td>c</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>d</td>
|
||||
<td id="cell_readonly">e</td>
|
||||
<td contenteditable="true" id="cell_writable">f</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
/**
|
||||
* Test for Bug 1268736
|
||||
*
|
||||
* Tests for editing a table cell's contents when the table cell is or isn't a child of a contenteditable node.
|
||||
*
|
||||
*/
|
||||
|
||||
function getEditor() {
|
||||
const Ci = SpecialPowers.Ci;
|
||||
var editingSession = SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
return editingSession.getEditorForWindow(window).QueryInterface(Ci.nsITableEditor);
|
||||
}
|
||||
|
||||
var table = document.getElementById("table");
|
||||
var tableHTML = table.innerHTML;
|
||||
var editor = getEditor();
|
||||
|
||||
var cell = document.getElementById("cell_readonly");
|
||||
cell.focus();
|
||||
editor.deleteTableCellContents();
|
||||
is(table.innerHTML == tableHTML, true, "editor should not modify non-editable table cell" );
|
||||
|
||||
cell = document.getElementById("cell_writable");
|
||||
cell.focus();
|
||||
editor.deleteTableCellContents();
|
||||
is(cell.innerHTML == "<br>", true, "editor can modify editable table cells" );
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue