Incorporate the TinyMCE tests into our JS tests:

- Modified the original tests so TinyMCE can be loaded from /src/wp-includes/js/tinymce.
- Added "WP" option to the UI to select only tests relevant to our integration (excludes most of the default plugins tests).
- Added tests for obsolete HTML elements and attributes (html4 back-compat).
See #27014.

git-svn-id: https://develop.svn.wordpress.org/trunk@27155 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz 2014-02-10 01:11:25 +00:00
parent 4951bdc964
commit ce2dcccf86
144 changed files with 27501 additions and 3 deletions

View File

@ -160,7 +160,8 @@ module.exports = function(grunt) {
tests: {
src: [
'tests/qunit/**/*.js',
'!tests/qunit/vendor/qunit.js'
'!tests/qunit/vendor/qunit.js',
'!tests/qunit/editor/**'
],
options: grunt.file.readJSON('tests/qunit/.jshintrc')
},
@ -228,7 +229,10 @@ module.exports = function(grunt) {
}
},
qunit: {
files: ['tests/qunit/**/*.html']
files: [
'tests/qunit/**/*.html',
'!tests/qunit/editor/**'
]
},
phpunit: {
'default': {
@ -340,7 +344,10 @@ module.exports = function(grunt) {
}
},
test: {
files: ['tests/qunit/**'],
files: [
'tests/qunit/**',
'!tests/qunit/editor/**'
],
tasks: ['qunit']
}
}

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Code Coverage</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<!-- coverage -->
<link rel="stylesheet" href="js/reporter.css" type="text/css" />
<script src="js/underscore-min.js"></script>
<script src="js/backbone-min.js"></script>
<script src="js/reporter.js"></script>
<script src="js/JSCovReporter.js"></script>
</head>
<body>
<div id="coverage"></div>
<div id="menu"></div>
<script>
if (top != window && top.TestRunner) {
new JSCovReporter({ coverObject: top.TestRunner.getCoverObject() });
//onsole.info(top.TestRunner.getCoverObject());
}
</script>
</body>
</html>

View File

@ -0,0 +1,194 @@
JSCovFileReporter = Backbone.View.extend({
initialize: function () {
_.bindAll(this);
this.open = '<tr class="{class}"><td class="line">{line_number}</td><td class="hits">{count}</td><td class="source">';
this.close = '</td></tr>';
this.coverObject = this.options.coverObject;
this.error = 0;
this.pass = 0;
this.total = 0;
},
// substitute credits: MooTools
substitute: function(string, object){
return string.replace(/\\?\{([^{}]+)\}/g, function(match, name){
if (match.charAt(0) == '\\') return match.slice(1);
return (object[name] !== null) ? object[name] : '';
});
},
generateClose: function(count){
return this.substitute(this.close, {
count: count
});
},
generateOpen: function(hit_count, line_number){
return this.substitute(this.open, {
'count': hit_count,
'line_number': line_number,
'class': hit_count ? 'hit' : 'miss'
});
},
report: function () {
var thisview = this;
var i, l, k;
var code = this.coverObject.__code;
// generate array of all tokens
var codez = [];
for (i = 0, l = code.length; i < l; i++){
codez.push({
pos: i,
value: code.slice(i, i + 1)
});
}
// CoverObject has keys like "12:200" which means from char 12 to 200
// This orders all first gaps in a list of dictionaries to ease drawing table lines
var gaps = Object.keys(this.coverObject);
gaps = _.without(gaps, '__code');
var first_gaps = _.map(gaps, function ( gap ) {
return {
gap: parseInt(gap.split(':')[0], 10),
hit_count: thisview.coverObject[gap]
};
}).sort(function (a, b) {
if (a['gap'] > b['gap']) return 1;
if (b['gap'] > a['gap']) return -1;
return 0;
});
var second_gaps = _.map(gaps, function ( gap ) {
return {
gap: parseInt(gap.split(':')[1], 10),
hit_count: thisview.coverObject[gap]
};
}).sort(function (a, b) {
if (a['gap'] > b['gap']) return 1;
if (b['gap'] > a['gap']) return -1;
return 0;
});
// If it doesn't start from 0 it's because there are comments in the beginning
// We add a initial gap with one hit
if (first_gaps[0] !== 0) {
first_gaps.splice(0, 0, {gap: 0, hit_count: 1});
}
var result = '';
var number_trailing_whitespaces = 0;
var trailing_whitespaces = '';
// We will go from one gap to the next wrapping them in table lines
for (i=0, l = first_gaps.length; i < l; i++){
var hit_count = first_gaps[i]['hit_count'];
this.total++;
if (hit_count) this.pass++;
else this.error++;
var limit = null;
if (i+1 >= l) {
limit = codez.length;
}
else {
limit = first_gaps[i+1]['gap'];
}
// Table line opening
result += this.generateOpen(hit_count, this.total);
// Add trailing white space if it existed from previous line without carriage returns
if (number_trailing_whitespaces > 0 ) {
result += trailing_whitespaces.replace(/(\r\n|\n|\r)/gm,"");
}
// Add lines of code without initial white spaces, and replacing conflictive chars
result += _.map(codez.slice(first_gaps[i]['gap'], limit), function (loc) {
return loc['value'];
}).join('').trimLeft().replace(/</g, '&lt;').replace(/>/g, '&gt;');
// Count trailing white spaces for future line, then remove them
var matches = result.match(/(\s+)$/);
result = result.trimRight();
if (matches !== null) {
number_trailing_whitespaces = matches[0].length;
trailing_whitespaces = matches[0];
}
else {
number_trailing_whitespaces = 0;
}
// Generate table line closing
result += this.generateClose(hit_count);
}
return result;
}
});
JSCovReporter = Backbone.View.extend({
initialize: function () {
this.coverObject = this.options.coverObject;
// Generate the report
this.report();
// Activate reporter.js scrolling UX
onload();
},
report: function () {
var result = '';
var index = '';
for (var file in this.coverObject) {
var fileReporter = new JSCovFileReporter({ coverObject: this.coverObject[file] });
var fileReport = fileReporter.report();
var percentage = Math.round(fileReporter.pass / fileReporter.total * 100);
this.error += fileReporter.error;
this.pass += fileReporter.pass;
this.total += fileReporter.total;
var type_coverage = "high";
if (percentage < 75 && percentage >= 50) {
type_coverage = 'medium';
}
else if (percentage < 50 && percentage >= 25) {
type_coverage = 'low';
}
else if (percentage < 25) {
type_coverage = 'terrible';
}
// Title
result += '<h2 id="' + file + '" class="file-title">' + file + '</h2>';
// Stats
result += '<div class="stats ' + type_coverage + '"><div class="percentage">'+ percentage + '%</div>';
result += '<div class="sloc">' + fileReporter.total + '</div><div class="hits">' + fileReporter.pass + '</div>';
result += '<div class="misses">' + fileReporter.error + '</div></div>';
// Report
result += '<div class="file-report">';
result += '<table id="source"><tbody>' + fileReport + '</tbody></table>';
result += '</div>';
// Menu index
index += '<li><span class="cov ' + type_coverage + '">' + percentage + '</span><a href="#' + file+ '">' + file + '</a></li>';
}
$('#coverage').html(result);
$('#menu').html('<ul id="toc">' + index + '</ul>');
}
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,31 @@
headings = [];
onload = function(){
headings = document.querySelectorAll('h2');
};
onscroll = function(e){
var heading = find(window.scrollY);
if (!heading) return;
var links = document.querySelectorAll('#menu a')
, link;
for (var i = 0, len = links.length; i < len; ++i) {
link = links[i];
link.className = link.getAttribute('href') == '#' + heading.id
? 'active'
: '';
}
};
function find(y) {
var i = headings.length
, heading;
while (i--) {
heading = headings[i];
if (y > heading.offsetTop) {
return heading;
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,539 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint loopfunc:true */
/*global tinymce:true */
tinymce.PluginManager.add('noneditable', function(editor) {
var TreeWalker = tinymce.dom.TreeWalker;
var externalName = 'contenteditable', internalName = 'data-mce-' + externalName;
var VK = tinymce.util.VK;
// Returns the content editable state of a node "true/false" or null
function getContentEditable(node) {
var contentEditable;
// Ignore non elements
if (node.nodeType === 1) {
// Check for fake content editable
contentEditable = node.getAttribute(internalName);
if (contentEditable && contentEditable !== "inherit") {
return contentEditable;
}
// Check for real content editable
contentEditable = node.contentEditable;
if (contentEditable !== "inherit") {
return contentEditable;
}
}
return null;
}
// Returns the noneditable parent or null if there is a editable before it or if it wasn't found
function getNonEditableParent(node) {
var state;
while (node) {
state = getContentEditable(node);
if (state) {
return state === "false" ? node : null;
}
node = node.parentNode;
}
}
function handleContentEditableSelection() {
var dom = editor.dom, selection = editor.selection, caretContainerId = 'mce_noneditablecaret', invisibleChar = '\uFEFF';
// Get caret container parent for the specified node
function getParentCaretContainer(node) {
while (node) {
if (node.id === caretContainerId) {
return node;
}
node = node.parentNode;
}
}
// Finds the first text node in the specified node
function findFirstTextNode(node) {
var walker;
if (node) {
walker = new TreeWalker(node, node);
for (node = walker.current(); node; node = walker.next()) {
if (node.nodeType === 3) {
return node;
}
}
}
}
// Insert caret container before/after target or expand selection to include block
function insertCaretContainerOrExpandToBlock(target, before) {
var caretContainer, rng;
// Select block
if (getContentEditable(target) === "false") {
if (dom.isBlock(target)) {
selection.select(target);
return;
}
}
rng = dom.createRng();
if (getContentEditable(target) === "true") {
if (!target.firstChild) {
target.appendChild(editor.getDoc().createTextNode('\u00a0'));
}
target = target.firstChild;
before = true;
}
/*
caretContainer = dom.create('span', {
id: caretContainerId,
'data-mce-bogus': true,
style:'border: 1px solid red'
}, invisibleChar);
*/
caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true}, invisibleChar);
if (before) {
target.parentNode.insertBefore(caretContainer, target);
} else {
dom.insertAfter(caretContainer, target);
}
rng.setStart(caretContainer.firstChild, 1);
rng.collapse(true);
selection.setRng(rng);
return caretContainer;
}
// Removes any caret container except the one we might be in
function removeCaretContainer(caretContainer) {
var rng, child, currentCaretContainer, lastContainer;
if (caretContainer) {
rng = selection.getRng(true);
rng.setStartBefore(caretContainer);
rng.setEndBefore(caretContainer);
child = findFirstTextNode(caretContainer);
if (child && child.nodeValue.charAt(0) == invisibleChar) {
child = child.deleteData(0, 1);
}
dom.remove(caretContainer, true);
selection.setRng(rng);
} else {
currentCaretContainer = getParentCaretContainer(selection.getStart());
while ((caretContainer = dom.get(caretContainerId)) && caretContainer !== lastContainer) {
if (currentCaretContainer !== caretContainer) {
child = findFirstTextNode(caretContainer);
if (child && child.nodeValue.charAt(0) == invisibleChar) {
child = child.deleteData(0, 1);
}
dom.remove(caretContainer, true);
}
lastContainer = caretContainer;
}
}
}
// Modifies the selection to include contentEditable false elements or insert caret containers
function moveSelection() {
var nonEditableStart, nonEditableEnd, isCollapsed, rng, element;
// Checks if there is any contents to the left/right side of caret returns the noneditable element or
// any editable element if it finds one inside
function hasSideContent(element, left) {
var container, offset, walker, node, len;
container = rng.startContainer;
offset = rng.startOffset;
// If endpoint is in middle of text node then expand to beginning/end of element
if (container.nodeType == 3) {
len = container.nodeValue.length;
if ((offset > 0 && offset < len) || (left ? offset == len : offset === 0)) {
return;
}
} else {
// Can we resolve the node by index
if (offset < container.childNodes.length) {
// Browser represents caret position as the offset at the start of an element. When moving right
// this is the element we are moving into so we consider our container to be child node at offset-1
var pos = !left && offset > 0 ? offset-1 : offset;
container = container.childNodes[pos];
if (container.hasChildNodes()) {
container = container.firstChild;
}
} else {
// If not then the caret is at the last position in it's container and the caret container
// should be inserted after the noneditable element
return !left ? element : null;
}
}
// Walk left/right to look for contents
walker = new TreeWalker(container, element);
while ((node = walker[left ? 'prev' : 'next']())) {
if (node.nodeType === 3 && node.nodeValue.length > 0) {
return;
} else if (getContentEditable(node) === "true") {
// Found contentEditable=true element return this one to we can move the caret inside it
return node;
}
}
return element;
}
// Remove any existing caret containers
removeCaretContainer();
// Get noneditable start/end elements
isCollapsed = selection.isCollapsed();
nonEditableStart = getNonEditableParent(selection.getStart());
nonEditableEnd = getNonEditableParent(selection.getEnd());
// Is any fo the range endpoints noneditable
if (nonEditableStart || nonEditableEnd) {
rng = selection.getRng(true);
// If it's a caret selection then look left/right to see if we need to move the caret out side or expand
if (isCollapsed) {
nonEditableStart = nonEditableStart || nonEditableEnd;
if ((element = hasSideContent(nonEditableStart, true))) {
// We have no contents to the left of the caret then insert a caret container before the noneditable element
insertCaretContainerOrExpandToBlock(element, true);
} else if ((element = hasSideContent(nonEditableStart, false))) {
// We have no contents to the right of the caret then insert a caret container after the noneditable element
insertCaretContainerOrExpandToBlock(element, false);
} else {
// We are in the middle of a noneditable so expand to select it
selection.select(nonEditableStart);
}
} else {
rng = selection.getRng(true);
// Expand selection to include start non editable element
if (nonEditableStart) {
rng.setStartBefore(nonEditableStart);
}
// Expand selection to include end non editable element
if (nonEditableEnd) {
rng.setEndAfter(nonEditableEnd);
}
selection.setRng(rng);
}
}
}
function handleKey(e) {
var keyCode = e.keyCode, nonEditableParent, caretContainer, startElement, endElement;
function getNonEmptyTextNodeSibling(node, prev) {
while ((node = node[prev ? 'previousSibling' : 'nextSibling'])) {
if (node.nodeType !== 3 || node.nodeValue.length > 0) {
return node;
}
}
}
function positionCaretOnElement(element, start) {
selection.select(element);
selection.collapse(start);
}
function canDelete(backspace) {
var rng, container, offset, nonEditableParent;
function removeNodeIfNotParent(node) {
var parent = container;
while (parent) {
if (parent === node) {
return;
}
parent = parent.parentNode;
}
dom.remove(node);
moveSelection();
}
function isNextPrevTreeNodeNonEditable() {
var node, walker, nonEmptyElements = editor.schema.getNonEmptyElements();
walker = new tinymce.dom.TreeWalker(container, editor.getBody());
while ((node = (backspace ? walker.prev() : walker.next()))) {
// Found IMG/INPUT etc
if (nonEmptyElements[node.nodeName.toLowerCase()]) {
break;
}
// Found text node with contents
if (node.nodeType === 3 && tinymce.trim(node.nodeValue).length > 0) {
break;
}
// Found non editable node
if (getContentEditable(node) === "false") {
removeNodeIfNotParent(node);
return true;
}
}
// Check if the content node is within a non editable parent
if (getNonEditableParent(node)) {
return true;
}
return false;
}
if (selection.isCollapsed()) {
rng = selection.getRng(true);
container = rng.startContainer;
offset = rng.startOffset;
container = getParentCaretContainer(container) || container;
// Is in noneditable parent
if ((nonEditableParent = getNonEditableParent(container))) {
removeNodeIfNotParent(nonEditableParent);
return false;
}
// Check if the caret is in the middle of a text node
if (container.nodeType == 3 && (backspace ? offset > 0 : offset < container.nodeValue.length)) {
return true;
}
// Resolve container index
if (container.nodeType == 1) {
container = container.childNodes[offset] || container;
}
// Check if previous or next tree node is non editable then block the event
if (isNextPrevTreeNodeNonEditable()) {
return false;
}
}
return true;
}
startElement = selection.getStart();
endElement = selection.getEnd();
// Disable all key presses in contentEditable=false except delete or backspace
nonEditableParent = getNonEditableParent(startElement) || getNonEditableParent(endElement);
if (nonEditableParent && (keyCode < 112 || keyCode > 124) && keyCode != VK.DELETE && keyCode != VK.BACKSPACE) {
// Is Ctrl+c, Ctrl+v or Ctrl+x then use default browser behavior
if ((tinymce.isMac ? e.metaKey : e.ctrlKey) && (keyCode == 67 || keyCode == 88 || keyCode == 86)) {
return;
}
e.preventDefault();
// Arrow left/right select the element and collapse left/right
if (keyCode == VK.LEFT || keyCode == VK.RIGHT) {
var left = keyCode == VK.LEFT;
// If a block element find previous or next element to position the caret
if (editor.dom.isBlock(nonEditableParent)) {
var targetElement = left ? nonEditableParent.previousSibling : nonEditableParent.nextSibling;
var walker = new TreeWalker(targetElement, targetElement);
var caretElement = left ? walker.prev() : walker.next();
positionCaretOnElement(caretElement, !left);
} else {
positionCaretOnElement(nonEditableParent, left);
}
}
} else {
// Is arrow left/right, backspace or delete
if (keyCode == VK.LEFT || keyCode == VK.RIGHT || keyCode == VK.BACKSPACE || keyCode == VK.DELETE) {
caretContainer = getParentCaretContainer(startElement);
if (caretContainer) {
// Arrow left or backspace
if (keyCode == VK.LEFT || keyCode == VK.BACKSPACE) {
nonEditableParent = getNonEmptyTextNodeSibling(caretContainer, true);
if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
e.preventDefault();
if (keyCode == VK.LEFT) {
positionCaretOnElement(nonEditableParent, true);
} else {
dom.remove(nonEditableParent);
return;
}
} else {
removeCaretContainer(caretContainer);
}
}
// Arrow right or delete
if (keyCode == VK.RIGHT || keyCode == VK.DELETE) {
nonEditableParent = getNonEmptyTextNodeSibling(caretContainer);
if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
e.preventDefault();
if (keyCode == VK.RIGHT) {
positionCaretOnElement(nonEditableParent, false);
} else {
dom.remove(nonEditableParent);
return;
}
} else {
removeCaretContainer(caretContainer);
}
}
}
if ((keyCode == VK.BACKSPACE || keyCode == VK.DELETE) && !canDelete(keyCode == VK.BACKSPACE)) {
e.preventDefault();
return false;
}
}
}
}
editor.on('mousedown', function(e) {
var node = editor.selection.getNode();
if (getContentEditable(node) === "false" && node == e.target) {
// Expand selection on mouse down we can't block the default event since it's used for drag/drop
moveSelection();
}
});
editor.on('mouseup keyup', moveSelection);
editor.on('keydown', handleKey);
}
var editClass, nonEditClass, nonEditableRegExps;
// Converts configured regexps to noneditable span items
function convertRegExpsToNonEditable(e) {
var i = nonEditableRegExps.length, content = e.content, cls = tinymce.trim(nonEditClass);
// Don't replace the variables when raw is used for example on undo/redo
if (e.format == "raw") {
return;
}
while (i--) {
content = content.replace(nonEditableRegExps[i], function(match) {
var args = arguments, index = args[args.length - 2];
// Is value inside an attribute then don't replace
if (index > 0 && content.charAt(index - 1) == '"') {
return match;
}
return (
'<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' +
editor.dom.encode(typeof(args[1]) === "string" ? args[1] : args[0]) + '</span>'
);
});
}
e.content = content;
}
editClass = " " + tinymce.trim(editor.getParam("noneditable_editable_class", "mceEditable")) + " ";
nonEditClass = " " + tinymce.trim(editor.getParam("noneditable_noneditable_class", "mceNonEditable")) + " ";
// Setup noneditable regexps array
nonEditableRegExps = editor.getParam("noneditable_regexp");
if (nonEditableRegExps && !nonEditableRegExps.length) {
nonEditableRegExps = [nonEditableRegExps];
}
editor.on('PreInit', function() {
handleContentEditableSelection();
if (nonEditableRegExps) {
editor.on('BeforeSetContent', convertRegExpsToNonEditable);
}
// Apply contentEditable true/false on elements with the noneditable/editable classes
editor.parser.addAttributeFilter('class', function(nodes) {
var i = nodes.length, className, node;
while (i--) {
node = nodes[i];
className = " " + node.attr("class") + " ";
if (className.indexOf(editClass) !== -1) {
node.attr(internalName, "true");
} else if (className.indexOf(nonEditClass) !== -1) {
node.attr(internalName, "false");
}
}
});
// Remove internal name
editor.serializer.addAttributeFilter(internalName, function(nodes) {
var i = nodes.length, node;
while (i--) {
node = nodes[i];
if (nonEditableRegExps && node.attr('data-mce-content')) {
node.name = "#text";
node.type = 3;
node.raw = true;
node.value = node.attr('data-mce-content');
} else {
node.attr(externalName, null);
node.attr(internalName, null);
}
}
});
// Convert external name into internal name
editor.parser.addAttributeFilter(externalName, function(nodes) {
var i = nodes.length, node;
while (i--) {
node = nodes[i];
node.attr(internalName, node.attr(externalName));
node.attr(externalName, null);
}
});
});
editor.on('drop', function(e) {
if (getNonEditableParent(e.target)) {
e.preventDefault();
}
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("noneditable",function(e){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(u),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function r(){function r(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function a(e){var t;if(e)for(t=new f(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function i(n,r){var a,i;return"false"===t(n)&&u.isBlock(n)?void s.select(n):(i=u.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,r=!0),a=u.create("span",{id:g,"data-mce-bogus":!0},m),r?n.parentNode.insertBefore(a,n):u.insertAfter(a,n),i.setStart(a.firstChild,1),i.collapse(!0),s.setRng(i),a)}function o(e){var t,n,i,o;if(e)t=s.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0),s.setRng(t);else for(i=r(s.getStart());(e=u.get(g))&&e!==o;)i!==e&&(n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0)),o=e}function l(){function e(e,n){var r,a,i,o,l;if(r=d.startContainer,a=d.startOffset,3==r.nodeType){if(l=r.nodeValue.length,a>0&&l>a||(n?a==l:0===a))return}else{if(!(a<r.childNodes.length))return n?null:e;var u=!n&&a>0?a-1:a;r=r.childNodes[u],r.hasChildNodes()&&(r=r.firstChild)}for(i=new f(r,e);o=i[n?"prev":"next"]();){if(3===o.nodeType&&o.nodeValue.length>0)return;if("true"===t(o))return o}return e}var r,a,l,d,u;o(),l=s.isCollapsed(),r=n(s.getStart()),a=n(s.getEnd()),(r||a)&&(d=s.getRng(!0),l?(r=r||a,(u=e(r,!0))?i(u,!0):(u=e(r,!1))?i(u,!1):s.select(r)):(d=s.getRng(!0),r&&d.setStartBefore(r),a&&d.setEndAfter(a),s.setRng(d)))}function d(a){function i(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function d(e,t){s.select(e),s.collapse(t)}function g(a){function i(e){for(var t=d;t;){if(t===e)return;t=t.parentNode}u.remove(e),l()}function o(){var r,o,l=e.schema.getNonEmptyElements();for(o=new tinymce.dom.TreeWalker(d,e.getBody());(r=a?o.prev():o.next())&&!l[r.nodeName.toLowerCase()]&&!(3===r.nodeType&&tinymce.trim(r.nodeValue).length>0);)if("false"===t(r))return i(r),!0;return n(r)?!0:!1}var f,d,c,g;if(s.isCollapsed()){if(f=s.getRng(!0),d=f.startContainer,c=f.startOffset,d=r(d)||d,g=n(d))return i(g),!1;if(3==d.nodeType&&(a?c>0:c<d.nodeValue.length))return!0;if(1==d.nodeType&&(d=d.childNodes[c]||d),o())return!1}return!0}var m,p,v,E,h=a.keyCode;if(v=s.getStart(),E=s.getEnd(),m=n(v)||n(E),m&&(112>h||h>124)&&h!=c.DELETE&&h!=c.BACKSPACE){if((tinymce.isMac?a.metaKey:a.ctrlKey)&&(67==h||88==h||86==h))return;if(a.preventDefault(),h==c.LEFT||h==c.RIGHT){var y=h==c.LEFT;if(e.dom.isBlock(m)){var T=y?m.previousSibling:m.nextSibling,C=new f(T,T),b=y?C.prev():C.next();d(b,!y)}else d(m,y)}}else if(h==c.LEFT||h==c.RIGHT||h==c.BACKSPACE||h==c.DELETE){if(p=r(v)){if(h==c.LEFT||h==c.BACKSPACE)if(m=i(p,!0),m&&"false"===t(m)){if(a.preventDefault(),h!=c.LEFT)return void u.remove(m);d(m,!0)}else o(p);if(h==c.RIGHT||h==c.DELETE)if(m=i(p),m&&"false"===t(m)){if(a.preventDefault(),h!=c.RIGHT)return void u.remove(m);d(m,!1)}else o(p)}if((h==c.BACKSPACE||h==c.DELETE)&&!g(h==c.BACKSPACE))return a.preventDefault(),!1}}var u=e.dom,s=e.selection,g="mce_noneditablecaret",m="";e.on("mousedown",function(n){var r=e.selection.getNode();"false"===t(r)&&r==n.target&&l()}),e.on("mouseup keyup",l),e.on("keydown",d)}function a(t){var n=l.length,r=t.content,a=tinymce.trim(o);if("raw"!=t.format){for(;n--;)r=r.replace(l[n],function(t){var n=arguments,i=n[n.length-2];return i>0&&'"'==r.charAt(i-1)?t:'<span class="'+a+'" data-mce-content="'+e.dom.encode(n[0])+'">'+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+"</span>"});t.content=r}}var i,o,l,f=tinymce.dom.TreeWalker,d="contenteditable",u="data-mce-"+d,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",l=e.getParam("noneditable_regexp"),l&&!l.length&&(l=[l]),e.on("PreInit",function(){r(),l&&e.on("BeforeSetContent",a),e.parser.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)n=e[r],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(u,"true"):-1!==t.indexOf(o)&&n.attr(u,"false")}),e.serializer.addAttributeFilter(u,function(e){for(var t,n=e.length;n--;)t=e[n],l&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(d,null),t.attr(u,null))}),e.parser.addAttributeFilter(d,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(u,t.attr(d)),t.attr(d,null)})}),e.on("drop",function(e){n(e.target)&&e.preventDefault()})});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Test Runner</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="js/qunit/testrunner.css" type="text/css" />
<script src="js/qunit/testrunner.js"></script>
<script>
TestRunner.addSuites([
"tinymce/tests.js",
"tinymce/dom/tests.js",
"tinymce/html/tests.js",
"tinymce/ui/tests.js",
"tinymce/util/tests.js",
"plugins/tests.js"
]);
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,20 @@
Copyright (c) 2010 John Resig, http://jquery.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,119 @@
ol#qunit-tests {
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
margin:0;
padding:0;
list-style-position:inside;
font-size: smaller;
}
ol#qunit-tests li{
padding:0.4em 0.5em 0.4em 2.5em;
border-bottom:1px solid #fff;
font-size:small;
list-style-position:inside;
}
ol#qunit-tests li ol{
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
margin-top:0.5em;
margin-left:0;
padding:0.5em;
background-color:#fff;
border-radius:15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
}
ol#qunit-tests li li{
border-bottom:none;
margin:0.5em;
background-color:#fff;
list-style-position: inside;
padding:0.4em 0.5em 0.4em 0.5em;
}
ol#qunit-tests li li.pass{
border-left:26px solid #C6E746;
background-color:#fff;
color:#5E740B;
}
ol#qunit-tests li li.fail{
border-left:26px solid #EE5757;
background-color:#fff;
color:#710909;
}
ol#qunit-tests li.pass{
background-color:#D2E0E6;
color:#528CE0;
}
ol#qunit-tests li.fail{
background-color:#EE5757;
color:#000;
}
ol#qunit-tests li strong {
cursor:pointer;
}
h1#qunit-header{
background-color:#0d3349;
margin:0;
padding:0.5em 0 0.5em 1em;
color:#fff;
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
border-top-right-radius:15px;
border-top-left-radius:15px;
-moz-border-radius-topright:15px;
-moz-border-radius-topleft:15px;
-webkit-border-top-right-radius:15px;
-webkit-border-top-left-radius:15px;
text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px;
}
h2#qunit-banner{
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
height:5px;
margin:0;
padding:0;
}
h2#qunit-banner.qunit-pass{
background-color:#C6E746;
}
h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar {
background-color:#EE5757;
}
#qunit-testrunner-toolbar {
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
padding:0;
/*width:80%;*/
padding:0em 0 0.5em 2em;
font-size: small;
}
h2#qunit-userAgent {
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
background-color:#2b81af;
margin:0;
padding:0;
color:#fff;
font-size: small;
padding:0.5em 0 0.5em 2.5em;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
p#qunit-testresult{
font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
margin:0;
font-size: small;
color:#2b81af;
border-bottom-right-radius:15px;
border-bottom-left-radius:15px;
-moz-border-radius-bottomright:15px;
-moz-border-radius-bottomleft:15px;
-webkit-border-bottom-right-radius:15px;
-webkit-border-bottom-left-radius:15px;
background-color:#D2E0E6;
padding:0.5em 0.5em 0.5em 2.5em;
}
strong b.fail{
color:#710909;
}
strong b.pass{
color:#5E740B;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
(function() {
if (parent != window && window.QUnit) {
QUnit.done = function(data) {
if (window.__$coverObject) {
parent.TestRunner.addCoverObject(window.__$coverObject);
}
if (parent.TestRunner) {
parent.TestRunner.done(data.failed, data.total, document.title);
}
};
}
})();

View File

@ -0,0 +1,151 @@
body, html {
margin: 0; padding: 0;
overflow: hidden;
width: 100%; height: 100%;
position: absolute;
top: 0; left: 0;
font-size: 12px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #111;
background: #EEE;
}
a {
color: #111;
}
.runner, .sidebar, .controls, .tests {
position: absolute;
top: 0; left: 0;
}
.sidebar {
background: #DDD;
}
.controls {
background: #BBB;
}
.controls div {
padding: 2px;
}
.tests {
overflow: auto;
}
.suite {
padding: 10px;
}
.suite .selection {
float: right;
font-weight: normal;
}
.stats {
display: none;
float: right;
margin-right: 3px;
font-size: 10px;
line-height: 16px;
}
.test {
margin: 5px;
background: #EEE;
line-height: 16px;
}
.passed a {
color: #888;
}
span.passed {
color: green;
}
div.failed {
background: #EE5757;
}
span.failed {
color: red;
}
.failed span.failed {
color: black;
}
.running .stats, .failed .stats, .passed .stats, .skipped .stats {
display: inline;
font-weight: bold;
}
.suite-title {
font-weight: bold;
}
.gstatus {
float: right;
}
iframe {
position: absolute;
top: 0; left: 0;
border: 0;
padding: 0;
}
*[unselectable] {
-moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
user-select: none;
}
button#coverage {
float: right;
}
#coverview {
display: none;
position: fixed;
background: #fff;
z-index: 9;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
#coverview iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#coverview .close {
position: absolute;
right: -14px;
top: -18px;
color: #000;
font-size: 14px;
display: block;
z-index: 11;
text-decoration: none;
font-family: Verdana;
font-weight: bold;
text-shadow: 0 0 2px #fff;
}
#overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #ccc;
background: rgba(0,0,0,0.3);
}

View File

@ -0,0 +1,540 @@
// Quick and dirty testrunner hack, it's ugly but it works
(function() {
function TestRunner() {
var suites = [], suiteUrls = [], actions = {};
var started, currentTest, testUrls = [], globalStats = {};
var coverObjects = [];
function get(id) {
return document.getElementById(id);
}
function addClass(elm, cls) {
if (cls && !hasClass(elm, cls)) {
elm.className += elm.className ? ' ' + cls : cls;
}
}
function removeClass(elm, cls) {
if (hasClass(elm, cls)) {
elm.className = elm.className.replace(new RegExp("(^|\\s+)" + cls + "(\\s+|$)", "g"), ' ');
}
}
function hasClass(elm, cls) {
return elm && cls && (' ' + elm.className + ' ').indexOf(' ' + cls + ' ') !== -1;
}
function init() {
function loadNext() {
var url = suiteUrls.shift();
if (url) {
loadSuite(url, function(json, url) {
json.baseURL = url.substring(0, url.lastIndexOf('/'));
if (json.baseURL) {
json.baseURL += '/';
}
suites.push(json);
loadNext();
});
} else {
render();
reflow();
hashToStates();
// WP
wpTests();
}
}
loadNext();
}
function getHashData() {
var pos, hash = location.hash, items, item, data = {}, i;
pos = hash.indexOf('!');
if (pos > 0) {
items = hash.substring(pos + 1).split('&');
for (i = 0; i < items.length; i++) {
item = items[i].split('=');
data[item[0]] = item[1];
}
}
return data;
}
function setHashData(data) {
var name, hashItems = [];
for (name in data) {
if (data[name] !== null) {
hashItems.push(name + '=' + data[name]);
}
}
location.hash = '!' + hashItems.join('&');
}
function statesToHash() {
var i, checkboxes, states = [], hasDisabled;
checkboxes = get('tests').getElementsByTagName("input");
for (i = 0; i < checkboxes.length; i++) {
states[i] = checkboxes[i].checked ? '1' : '0';
hasDisabled = hasDisabled || states[i] === '0';
}
setHashData({
min: get('min').checked,
jsrobot: get('jsrobot').checked,
tests: hasDisabled ? states.join('') : null
});
}
function hashToStates() {
var i, data = getHashData(location.hash), checkboxes;
if (typeof(data.min) != "undefined") {
get('min').checked = data.min === "true";
}
if (typeof(data.jsrobot) != "undefined") {
get('jsrobot').checked = data.jsrobot === "true";
}
if (typeof(data.tests) != "undefined") {
checkboxes = get('tests').getElementsByTagName("input");
for (i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = data.tests.substr(i, 1) === '1';
}
}
}
function addAction(name, action) {
actions[name] = action;
}
function toggleCheckboxes(elm, state) {
var checkboxes = (elm || get('tests')).getElementsByTagName("input"), i;
for (i = 0; i < checkboxes.length; i++) {
checkboxes[i].checked = state;
}
}
function start() {
var si, ti, tests;
testUrls = [];
for (si = 0; si < suites.length; si++) {
tests = suites[si].tests;
for (ti = 0; ti < tests.length; ti++) {
if (get('c' + si + '-' + ti).checked) {
testUrls.push(tests[ti]);
}
removeClass(get('t' + si + '-' + ti), "passed");
removeClass(get('t' + si + '-' + ti), "failed");
}
}
globalStats = {
total: 0,
failed: 0
};
// Start first test
currentTest = testUrls.shift();
if (currentTest) {
get('testview').src = currentTest.url + "?min=" + get('min').checked;
}
get('coverage').disabled = true;
}
function stop() {
started = false;
get('testview').src = 'javascript:""';
get('start').innerHTML = 'start';
if (coverObjects.length) {
get('coverage').disabled = false;
}
}
addAction("start", function(elm) {
started = !started;
if (started) {
start();
} else {
stop();
reset();
}
elm.innerHTML = started ? 'stop' : 'start';
});
addAction("select-none", function(elm) {
toggleCheckboxes(get('s' + elm.getAttribute("data-suite")), false);
reset();
});
addAction("select-all", function(elm) {
toggleCheckboxes(get('s' + elm.getAttribute("data-suite")), true);
reset();
});
addAction("select-failed", function(elm) {
toggleCheckboxes(get('s' + elm.getAttribute("data-suite")), false);
reset();
var targetIndex = elm.getAttribute("data-suite");
for (si = 0; si < suites.length; si++) {
if (targetIndex !== null && targetIndex != si) {
continue;
}
tests = suites[si].tests;
for (ti = 0; ti < tests.length; ti++) {
if (tests[ti].failed) {
get('c' + si + '-' + ti).checked = true;
}
}
}
});
// WP
function wpTests( element ) {
var si, ti, tests, targetIndex = null;
if ( element ) {
targetIndex = element.getAttribute("data-suite");
}
toggleCheckboxes( get( 's' + targetIndex ), false );
reset();
for ( si = 0; si < suites.length; si++ ) {
if ( targetIndex !== null && targetIndex != si ) {
continue;
}
tests = suites[si].tests;
if ( si === 0 || si === 2 || si === 3 || si === 4 ) {
for ( ti in tests ) {
get( 'c' + si + '-' + ti ).checked = true;
}
} else if ( si === 1 ) {
for ( ti in tests ) {
if ( ti !== '1' ) {
// No jQuery integration
get( 'c' + si + '-' + ti ).checked = true;
}
}
} else if ( si === 5 ) {
for ( ti in tests ) {
// Only the media and paste plugins
if ( ti === '0' || ti === '2' ) {
get( 'c' + si + '-' + ti ).checked = true;
}
}
}
}
}
// WP
addAction("select-wordpress", wpTests );
addAction("coverage", function(elm) {
if (elm.disabled) {
return;
}
showCoverage();
});
function render() {
var si, ti, tests, html = '';
var div = document.createElement('div');
addClass(div, "runner");
html += '<div id="sidebar" class="sidebar" unselectable="true">';
html += '<div id="controls" class="controls">';
html += '<div>';
html += '<button id="start" data-action="start">Start</button>';
html += '<label><input id="min" type="checkbox" checked>Minified</label>';
html += '<label style="display:none"><input id="jsrobot" type="checkbox">JSRobot</label>';
html += '<button id="coverage" data-action="coverage" disabled>Coverage</button>';
html += '</div>';
html += '<div>';
html += '<span id="gstatus" class="gstatus"></span>';
html += 'Select: ';
html += '<a data-action="select-wordpress" href="javascript:;">WP</a> ';
html += '<a data-action="select-all" href="javascript:;">[All]</a> ';
html += '<a data-action="select-none" href="javascript:;">[None]</a> ';
html += '<a data-action="select-failed" href="javascript:;">[Failed]</a>';
html += '</div>';
html += '</div>';
html += '<div id="tests" class="tests">';
for (si = 0; si < suites.length; si++) {
tests = suites[si].tests;
html += '<div id="s' + si + '" class="suite"><div class="suite-title">';
html += '<div class="selection">';
html += '<a data-action="select-wordpress" data-suite="' + si + '" href="javascript:;">WP</a> ';
html += '<a data-action="select-all" data-suite="' + si + '" href="javascript:;">[All]</a> ';
html += '<a data-action="select-none" data-suite="' + si + '" href="javascript:;">[None]</a> ';
html += '<a data-action="select-failed" data-suite="' + si + '" href="javascript:;">[Failed]</a>';
html += '</div>' + suites[si].title;
html += '</div>';
for (ti = 0; ti < tests.length; ti++) {
tests[ti].suiteIndex = si;
tests[ti].testIndex = ti;
tests[ti].url = suites[si].baseURL + tests[ti].url;
html += (
'<div id="t' + si + '-' + ti + '" class="test">' +
'<span id="s' + si + '-' + ti + '" class="stats">Running</span>' +
'<input id="c' + si + '-' + ti + '" type="checkbox" checked />' +
'<a href="' + tests[ti].url + '" target="testview">' + tests[ti].title + '</a>' +
'</div>'
);
}
html += '</div>';
}
html += '</div>';
html += '</div>';
html += '<iframe id="testview" name="testview" src="javascript:\'\'"></iframe>';
// coverage
html += '<div id="overlay"></div>';
html += '<div id="coverview">';
html += '<a class="close" href="javascript:TestRunner.hideCoverage();" title="Close">x</a>';
html += '<iframe frameborder="0" src="javascript:\'\'"></iframe>';
html += '</div>';
div.innerHTML = html;
document.body.appendChild(div);
get('sidebar').onclick = function(e) {
var target;
e = e || event;
target = e.target || e.srcElement;
if ((action = actions[target.getAttribute("data-action")])) {
action(target);
}
statesToHash();
};
}
function addSuites(urls) {
suiteUrls.push.apply(suiteUrls, urls);
}
function loadSuite(url, callback) {
var xhr;
function ready() {
if (xhr.readyState == 4) {
callback(eval("(" + xhr.responseText + ")"), url);
xhr = null;
} else {
setTimeout(ready, 10);
}
}
xhr = new XMLHttpRequest();
if (xhr) {
xhr.open('GET', url, true);
xhr.send();
setTimeout(ready, 10);
}
}
function reflow() {
var viewPortW, viewPortH, sideBarWidth, controlsHeight;
function rect(id, x, y, w, h) {
var style, elm;
if ((elm = get(id))) {
style = elm.style;
style.left = x + "px";
style.top = y + "px";
style.width = w + "px";
style.height = h + "px";
}
}
viewPortW = window.innerWidth || document.documentElement.clientWidth;
viewPortH = window.innerHeight || document.documentElement.clientHeight;
sideBarWidth = 300;
controlsHeight = 60;
rect('testview', sideBarWidth, 0, viewPortW - sideBarWidth, viewPortH);
rect('sidebar', 0, 0, sideBarWidth, viewPortH);
rect('controls', 0, 0, sideBarWidth, controlsHeight);
rect('tests', 0, controlsHeight, sideBarWidth, viewPortH - controlsHeight);
}
function reset() {
var si, tests, ti;
stop();
get('gstatus').innerHTML = '';
removeClass(get("controls"), "failed");
for (si = 0; si < suites.length; si++) {
tests = suites[si].tests;
for (ti = 0; ti < tests.length; ti++) {
removeClass(get('t' + si + '-' + ti), "passed");
removeClass(get('t' + si + '-' + ti), "failed");
removeClass(get('t' + si + '-' + ti), "running");
}
}
}
function updateGlobalStatus() {
get('gstatus').innerHTML = 'Total: ' + globalStats.total + ", Failed: " + globalStats.failed;
addClass(get("controls"), globalStats.failed > 0 ? "failed" : "");
}
function done(failed, total) {
var nextTest, currentTestElm;
function runNextTest() {
if ((nextTest = testUrls.shift())) {
currentTest = nextTest;
currentTestElm = get('t' + currentTest.suiteIndex + '-' + currentTest.testIndex);
currentTestElm.scrollIntoView(false);
if (nextTest.jsrobot === true && !get('jsrobot').checked) {
get('s' + currentTest.suiteIndex + '-' + currentTest.testIndex).innerHTML = 'Skipped';
addClass(currentTestElm, "skipped");
runNextTest();
} else {
addClass(currentTestElm, "running");
get('testview').src = nextTest.url + "?min=" + get('min').checked;
}
} else {
stop();
}
}
if (started) {
currentTest.failed = failed;
currentTest.total = total;
globalStats.total += total;
globalStats.failed += failed;
updateGlobalStatus();
get('s' + currentTest.suiteIndex + '-' + currentTest.testIndex).innerHTML = (
'(<span class="failed">' + failed + '</span>, ' +
'<span class="passed">' + (total - failed) + '</span>, ' +
'<span class="total">' + total + '</span>)'
);
addClass(get('t' + currentTest.suiteIndex + '-' + currentTest.testIndex), failed > 0 ? 'failed' : 'passed');
removeClass(currentTestElm, "running");
runNextTest();
}
}
function addCoverObject(coverObject) {
coverObjects.push(coverObject);
}
// this is going to be called from the coverage iframe
function getCoverObject() {
var coverObject = {}, fileName, gaps, gap, count;
for (var i = 0, length = coverObjects.length; i < length; i++) {
for (fileName in coverObjects[i]) {
gaps = coverObjects[i][fileName];
if (!coverObject.hasOwnProperty(fileName)) {
coverObject[fileName] = gaps;
} else {
for (gap in gaps) {
if (gap === '__code') {
continue;
}
count = gaps[gap];
if (!coverObject[fileName].hasOwnProperty(gap)) {
coverObject[fileName][gap] = count;
} else {
coverObject[fileName][gap] += count;
}
}
}
}
}
return coverObject;
}
function showCoverage() {
var overlay, coverView, viewPortW, viewPortH;
viewPortW = window.innerWidth || document.documentElement.clientWidth;
viewPortH = window.innerHeight || document.documentElement.clientHeight;
overlay = get('overlay');
overlay.style.display = 'block';
coverView = get('coverview');
coverView.style.left = '30px';
coverView.style.top = '30px';
coverView.style.width = (viewPortW - 60) + 'px';
coverView.style.height = (viewPortH - 60) + 'px';
coverView.style.display = 'block';
coverView.getElementsByTagName('iframe')[0].src = 'coverage/index.html';
}
function hideCoverage() {
get('overlay').style.display = 'none';
get('coverview').style.display = 'none';
}
return {
init: init,
addSuites: addSuites,
reflow: reflow,
done: done,
addCoverObject: addCoverObject,
getCoverObject: getCoverObject,
showCoverage: showCoverage,
hideCoverage: hideCoverage
};
}
var testRunner = new TestRunner();
self.onload = function() {
testRunner.init();
};
self.onresize = function() {
testRunner.reflow();
};
self.TestRunner = testRunner;
})();

View File

@ -0,0 +1,17 @@
// Edited for WordPress
(function() {
var baseURL;
// Get base where the tinymce script is located
var scripts = document.getElementsByTagName('script');
for ( var i = 0; i < scripts.length; i++ ) {
var src = scripts[i].src;
if ( /tinymce_loader\.js/.test( src ) ) {
baseURL = src.substring( 0, src.indexOf('/tests/qunit/') );
break;
}
}
document.write('<script src="' + baseURL + '/src/wp-includes/js/tinymce/tinymce.min.js"></script>');
})();

View File

@ -0,0 +1,299 @@
function fontFace(face) {
if (tinymce.isOpera) {
return "'" + face + "'";
} else {
return face;
}
}
function findContainer(selector) {
var container;
if (tinymce.is(selector, 'string')) {
container = editor.dom.select(selector)[0];
} else {
container = selector;
}
if (container.firstChild) {
container = container.firstChild;
}
return container;
}
function setSelection(startSelector, startOffset, endSelector, endOffset) {
if (!endSelector) {
endSelector = startSelector;
endOffset = startOffset;
}
var startContainer = findContainer(startSelector);
var endContainer = findContainer(endSelector);
var rng = editor.dom.createRng();
function setRange(container, offset, start) {
offset = offset || 0;
if (offset === 'after') {
if (start) {
rng.setStartAfter(container);
} else {
rng.setEndAfter(container);
}
return;
} else if (offset === 'afterNextCharacter') {
container = container.nextSibling;
offset = 1;
}
if (start) {
rng.setStart(container, offset);
} else {
rng.setEnd(container, offset);
}
}
setRange(startContainer, startOffset, true);
setRange(endContainer, endOffset, false);
editor.selection.setRng(rng);
}
function initWhenTinyAndRobotAreReady(initTinyFunction) {
function loaded() {
QUnit.start();
}
tinymce.on('AddEditor', function(e) {
e.editor.on('Init', function() {
loaded();
});
});
window.robot.onload(initTinyFunction);
}
function trimContent(content) {
return content.replace(/^<p>&nbsp;<\/p>\n?/, '').replace(/\n?<p>&nbsp;<\/p>$/, '');
}
/**
* Fakes a key event.
*
* @param {Element/String} e DOM element object or element id to send fake event to.
* @param {String} na Event name to fake like "keydown".
* @param {Object} o Optional object with data to send with the event like keyCode and charCode.
*/
function fakeKeyEvent(e, na, o) {
var ev;
o = tinymce.extend({
keyCode : 13,
charCode : 0
}, o);
e = tinymce.DOM.get(e);
if (e.fireEvent) {
ev = document.createEventObject();
tinymce.extend(ev, o);
e.fireEvent('on' + na, ev);
return;
}
if (document.createEvent) {
try {
// Fails in Safari
ev = document.createEvent('KeyEvents');
ev.initKeyEvent(na, true, true, window, false, false, false, false, o.keyCode, o.charCode);
} catch (ex) {
ev = document.createEvent('Events');
ev.initEvent(na, true, true);
ev.keyCode = o.keyCode;
ev.charCode = o.charCode;
}
} else {
ev = document.createEvent('UIEvents');
if (ev.initUIEvent)
ev.initUIEvent(na, true, true, window, 1);
ev.keyCode = o.keyCode;
ev.charCode = o.charCode;
}
e.dispatchEvent(ev);
}
function normalizeRng(rng) {
if (rng.startContainer.nodeType == 3) {
if (rng.startOffset == 0)
rng.setStartBefore(rng.startContainer);
else if (rng.startOffset >= rng.startContainer.nodeValue.length - 1)
rng.setStartAfter(rng.startContainer);
}
if (rng.endContainer.nodeType == 3) {
if (rng.endOffset == 0)
rng.setEndBefore(rng.endContainer);
else if (rng.endOffset >= rng.endContainer.nodeValue.length - 1)
rng.setEndAfter(rng.endContainer);
}
return rng;
}
// TODO: Replace this with the new event logic in 3.5
function type(chr) {
var editor = tinymce.activeEditor, keyCode, charCode, event = tinymce.dom.Event, evt, startElm, rng;
function fakeEvent(target, type, evt) {
editor.dom.fire(target, type, evt);
}
// Numeric keyCode
if (typeof(chr) == "number") {
charCode = keyCode = chr;
} else if (typeof(chr) == "string") {
// String value
if (chr == '\b') {
keyCode = 8;
charCode = chr.charCodeAt(0);
} else if (chr == '\n') {
keyCode = 13;
charCode = chr.charCodeAt(0);
} else {
charCode = chr.charCodeAt(0);
keyCode = charCode;
}
} else {
evt = chr;
}
evt = evt || {keyCode: keyCode, charCode: charCode};
startElm = editor.selection.getStart();
fakeEvent(startElm, 'keydown', evt);
fakeEvent(startElm, 'keypress', evt);
if (!evt.isDefaultPrevented()) {
if (keyCode == 8) {
if (editor.getDoc().selection) {
rng = editor.getDoc().selection.createRange();
if (rng.text.length === 0) {
rng.moveStart('character', -1);
rng.select();
}
rng.execCommand('Delete', false, null);
} else {
rng = editor.selection.getRng();
if (rng.startContainer.nodeType == 1 && rng.collapsed) {
var nodes = rng.startContainer.childNodes, lastNode = nodes[nodes.length - 1];
// If caret is at <p>abc|</p> and after the abc text node then move it to the end of the text node
// Expand the range to include the last char <p>ab[c]</p> since IE 11 doesn't delete otherwise
if (rng.startOffset >= nodes.length - 1 && lastNode && lastNode.nodeType == 3 && lastNode.data.length > 0) {
rng.setStart(lastNode, lastNode.data.length - 1);
rng.setEnd(lastNode, lastNode.data.length);
editor.selection.setRng(rng);
}
}
editor.getDoc().execCommand('Delete', false, null);
}
} else if (typeof(chr) == 'string') {
rng = editor.selection.getRng(true);
if (rng.startContainer.nodeType == 3 && rng.collapsed) {
rng.startContainer.insertData(rng.startOffset, chr);
rng.setStart(rng.startContainer, rng.startOffset + 1);
rng.collapse(true);
editor.selection.setRng(rng);
} else {
rng.insertNode(editor.getDoc().createTextNode(chr));
}
}
}
fakeEvent(startElm, 'keyup', evt);
}
function cleanHtml(html) {
html = html.toLowerCase().replace(/[\r\n]+/gi, '');
html = html.replace(/ (sizcache[0-9]+|sizcache|nodeindex|sizset[0-9]+|sizset|data\-mce\-expando|data\-mce\-selected)="[^"]*"/gi, '');
html = html.replace(/<span[^>]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>|<div[^>]+data-mce-bogus[^>]+><\/div>/gi, '');
return html;
}
function normalizeHtml(html) {
var writer = new tinymce.html.Writer();
new tinymce.html.SaxParser({
validate: false,
comment: writer.comment,
cdata: writer.cdata,
text: writer.text,
end: writer.end,
pi: writer.pi,
doctype: writer.doctype,
start: function(name, attrs, empty) {
attrs.sort(function(a, b) {
if (a.name === b.name) {
return 0;
}
return a.name > b.name ? 1 : -1;
});
writer.start(name, attrs, empty);
}
}).parse(html);
return writer.getContent();
}
/**
* Measures the x, y, w, h of the specified element/control relative to the view element.
*/
function rect(ctrl) {
var outerRect, innerRect;
if (ctrl.nodeType) {
innerRect = ctrl.getBoundingClientRect();
} else {
innerRect = ctrl.getEl().getBoundingClientRect();
}
outerRect = document.getElementById('view').getBoundingClientRect();
return [
Math.round(innerRect.left - outerRect.left),
Math.round(innerRect.top - outerRect.top),
Math.round(innerRect.right - innerRect.left),
Math.round(innerRect.bottom - innerRect.top)
];
}
function size(ctrl) {
return rect(ctrl).slice(2);
}
function resetScroll(elm) {
elm.scrollTop = 0;
elm.scrollLeft = 0;
}
// Needed since fonts render differently on different platforms
function nearlyEqualRects(rect1, rect2, diff) {
diff = diff || 1;
for (var i = 0; i < 4; i++) {
if (Math.abs(rect1[i] - rect2[i]) > diff) {
deepEqual(rect1, rect2);
return;
}
}
ok(true);
}

View File

@ -0,0 +1,170 @@
<!DOCTYPE html>
<html>
<head>
<title>Automatic link tests</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="js/dsl.js"></script>
<script src="js/autolink.actions.js"></script>
<script src="js/states.js"></script>
<script><!--
window.robotUsesSymbols = true;
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Automatic Links", {
autostart: false,
setup: function() {
window.queue = new dsl.Queue();
}
});
if (!tinymce.isIE) {
asyncTest('Typing a HTTP URL', function() {
TypingHTTPURL.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPURL.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPURL.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPURL.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPURL.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</h1>$'));
TypingHTTPURL.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingHTTPURL.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.ephox.com">http://www.ephox.com</a>(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingEclipsedHTTPURL.inA(NonEmptyParagraph).gives(new RegExp('^<p>\\(<a href="http://www.ephox.com">http://www.ephox.com</a>\\)(\\s|&nbsp;)Test</p>$'));
TypingHTTPURLAndNewline.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="http://www.ephox.com">http://www.ephox.com</a></p><p>(Test|<a href=\"http://www.ephox.com\"></a>Test)</p>$'));
queue.done();
});
asyncTest('Typing a HTTPS URL', function() {
TypingHTTPSURL.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPSURL.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPSURL.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPSURL.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingHTTPSURL.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</h1>$'));
TypingHTTPSURL.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingHTTPSURL.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="https://www.ephox.com">https://www.ephox.com</a>(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingEclipsedHTTPSURL.inA(NonEmptyParagraph).gives(new RegExp('^<p>\\(<a href="https://www.ephox.com">https://www.ephox.com</a>\\)(\\s|&nbsp;)Test</p>$'));
TypingHTTPSURLAndNewline.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="https://www.ephox.com">https://www.ephox.com</a></p><p>(Test|<a href=\"https://www.ephox.com\"></a>Test)</p>$'));
queue.done();
});
asyncTest('Typing a SSH URL', function() {
TypingSSHURL.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingSSHURL.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingSSHURL.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingSSHURL.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingSSHURL.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</h1>$'));
TypingSSHURL.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingSSHURL.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="ssh://www.ephox.com">ssh://www.ephox.com</a>(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingEclipsedSSHURL.inA(NonEmptyParagraph).gives(new RegExp('^<p>\\(<a href="ssh://www.ephox.com">ssh://www.ephox.com</a>\\)(\\s|&nbsp;)Test</p>$'));
TypingSSHURLAndNewline.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="ssh://www.ephox.com">ssh://www.ephox.com</a></p><p>(Test|<a href=\"ssh://www.ephox.com\"></a>Test)</p>$'));
queue.done();
});
asyncTest('Typing a FTP URL', function() {
TypingFTPURL.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingFTPURL.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingFTPURL.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingFTPURL.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingFTPURL.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</h1>$'));
TypingFTPURL.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingFTPURL.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="ftp://www.ephox.com">ftp://www.ephox.com</a>(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingEclipsedFTPURL.inA(NonEmptyParagraph).gives(new RegExp('^<p>\\(<a href="ftp://www.ephox.com">ftp://www.ephox.com</a>\\)(\\s|&nbsp;)Test</p>$'));
TypingFTPURLAndNewline.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="ftp://www.ephox.com">ftp://www.ephox.com</a></p><p>(Test|<a href=\"ftp://www.ephox.com\"></a>Test)</p>$'));
queue.done();
});
asyncTest('Typing a WWW URL', function() {
TypingWWWURL.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingWWWURL.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingWWWURL.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingWWWURL.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</p>$'));
TypingWWWURL.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</h1>$'));
TypingWWWURL.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingWWWURL.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.ephox.com">www.ephox.com</a>(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingEclipsedWWWURL.inA(NonEmptyParagraph).gives(new RegExp('^<p>\\(<a href="http://www.ephox.com">www.ephox.com</a>\\)(\\s|&nbsp;)Test</p>$'));
TypingWWWURLAndNewline.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="http://www.ephox.com">www.ephox.com</a></p><p>(Test|<a href=\"http://www.ephox.com\"></a>Test)</p>$'));
queue.done();
});
asyncTest('Typing a WWW URL with end dot', function() {
TypingWWWURLWithEndDot.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</p>$'));
TypingWWWURLWithEndDot.inA(ParagraphWithMarginLeft).gives(new RegExp('^<p style="margin-left: 60px;"><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</p>$'));
TypingWWWURLWithEndDot.inA(ParagraphWithPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px;"><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</p>$'));
TypingWWWURLWithEndDot.inA(ParagraphWithMarginAndPaddingLeft).gives(new RegExp('^<p style="padding-left: 60px; margin-left: 60px;"><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</p>$'));
TypingWWWURLWithEndDot.inA(NonEmptyHeading).gives(new RegExp('^<h1><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</h1>$'));
TypingWWWURLWithEndDot.inA(TableCellWithoutBrs2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test</td><td>&nbsp;</td></tr></tbody></table>$'));
TypingWWWURLWithEndDot.inA(TableCellWithBrsFirstLine2).gives(new RegExp('^<table><tbody><tr><td><a href="http://www.site.com">www.site.com</a>.(\\s|&nbsp;)Test<br />Line 2</td><td>&nbsp;</td></tr></tbody></table>$'));
queue.done();
});
asyncTest('Typing a mail address', function() {
TypingMailAddr.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="mailto:user@domain.com">user@domain.com</a>(\\s|&nbsp;)Test</p>$'));
TypingDashedMailAddr.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="mailto:first-last@domain.com">first-last@domain.com</a>(\\s|&nbsp;)Test</p>$'));
queue.done();
});
asyncTest('Typing a mail address with protocol', function() {
TypingMailAddrWithProtocol.inA(NonEmptyParagraph).gives(new RegExp('^<p><a href="mailto:user@domain.com">mailto:user@domain.com</a>(\\s|&nbsp;)Test</p>$'));
queue.done();
});
} else {
test("IE has built in support", function() {
ok(true, "Skipped");
});
}
var initTinyFunction = function(){
tinymce.init({
mode : "exact",
elements : "elm1",
plugins : "autolink",
add_unload_trigger : false,
webkit_fake_resize: false,
theme_advanced_styles : 'test1=test1;test2=test2',
valid_styles : {
'*' : 'text-align,padding-left,color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
indent : 0,
init_instance_callback : function(ed) {
editor = ed;
}
});
}
--></script>
</head>
<body>
<h1 id="qunit-header">Automatic link tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
</div>
<script src="../js/jsrobot/robot.js"></script>
<script>
initWhenTinyAndRobotAreReady(initTinyFunction);
</script>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for the Autosave plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Autosave plugin", {
autostart: false
});
test("isEmpty true", function() {
ok(editor.plugins.autosave.isEmpty(''));
ok(editor.plugins.autosave.isEmpty(' '));
ok(editor.plugins.autosave.isEmpty('\t\t\t'));
ok(editor.plugins.autosave.isEmpty('<p id="x"></p>'));
ok(editor.plugins.autosave.isEmpty('<p></p>'));
ok(editor.plugins.autosave.isEmpty('<p> </p>'));
ok(editor.plugins.autosave.isEmpty('<p>\t</p>'));
ok(editor.plugins.autosave.isEmpty('<p><br></p>'));
ok(editor.plugins.autosave.isEmpty('<p><br /></p>'));
ok(editor.plugins.autosave.isEmpty('<p><br data-mce-bogus="true" /></p>'));
ok(editor.plugins.autosave.isEmpty('<p><br><br></p>'));
ok(editor.plugins.autosave.isEmpty('<p><br /><br /></p>'));
ok(editor.plugins.autosave.isEmpty('<p><br data-mce-bogus="true" /><br data-mce-bogus="true" /></p>'));
});
test("isEmpty false", function() {
ok(!editor.plugins.autosave.isEmpty('X'));
ok(!editor.plugins.autosave.isEmpty(' X'));
ok(!editor.plugins.autosave.isEmpty('\t\t\tX'));
ok(!editor.plugins.autosave.isEmpty('<p>X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p> X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p>\tX</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br>X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br />X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br data-mce-bogus="true" />X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br><br>X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br /><br />X</p>'));
ok(!editor.plugins.autosave.isEmpty('<p><br data-mce-bogus="true" /><br data-mce-bogus="true" />X</p>'));
ok(!editor.plugins.autosave.isEmpty('<h1></h1>'));
ok(!editor.plugins.autosave.isEmpty('<img src="x" />'));
});
test("hasDraft/storeDraft/restoreDraft", function() {
ok(!editor.plugins.autosave.hasDraft());
editor.setContent('X');
editor.undoManager.add();
editor.plugins.autosave.storeDraft();
ok(editor.plugins.autosave.hasDraft());
editor.setContent('Y');
editor.undoManager.add();
editor.plugins.autosave.restoreDraft();
equal(editor.getContent(), '<p>X</p>');
});
tinymce.init({
selector: "textarea",
add_unload_trigger: false,
plugins: 'autosave',
autosave_ask_before_unload: false,
init_instance_callback: function(ed) {
editor = ed;
editor.plugins.autosave.removeDraft();
QUnit.start();
}
});
</script>
<h1 id="qunit-header">Unit tests for the Table plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,154 @@
<!DOCTYPE html>
<html>
<head>
<title>Fullpage plugin tests</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Fullpage plugin", {
autostart: false,
teardown: function() {
editor.getBody().dir = 'ltr';
}
});
function normalizeHTML(html) {
return html.replace(/\s/g, '');
}
function hasLink(href) {
var links = editor.getDoc().getElementsByTagName('link');
for (var i = 0; i < links.length; i++) {
if (links[i].href.indexOf('/' + href) != -1) {
return true;
}
}
}
test('Keep header/footer intact', function() {
expect(2);
editor.setContent('<html><body><p>Test</p>');
equal(normalizeHTML(editor.getContent()), '<html><body><p>Test</p>', 'Invalid HTML content is still editable.');
editor.setContent('<html><body><p>Test</p></body></html>');
equal(normalizeHTML(editor.getContent()), '<html><body><p>Test</p></body></html>', 'Header/footer is intact.');
});
test('Default header/footer', function() {
expect(1);
editor.setContent('<p>Test</p>');
equal(editor.getContent(), '<!DOCTYPE html>\n<html>\n<head>\n</head>\n<body>\n<p>Test</p>\n</body>\n</html>', 'Invalid HTML content is still editable.');
});
test('Parse body attributes', function() {
expect(9);
editor.setContent('<html><body><p>Test</p></body></html>');
equal(editor.getBody().style.color, '', 'No color on body.');
equal(editor.getBody().dir, '', 'No dir on body.');
equal(editor.dom.getStyle(editor.getBody().firstChild, 'display', true), 'block', 'No styles added to iframe document');
editor.setContent('<html><body style="color:#FF0000"><p>Test</p></body></html>');
ok(editor.getBody().style.color.length > 0, 'Color added to body');
editor.setContent('<html><body dir="rtl"><p>Test</p></body></html>');
equal(editor.getBody().dir, 'rtl', 'Dir added to body');
editor.setContent('<html><head><style>p {text-align:right}</style></head><body dir="rtl"><p>Test</p></body></html>');
equal(editor.dom.getStyle(editor.getBody().firstChild, 'text-align', true), 'right', 'Styles added to iframe document');
editor.setContent('<html><body><p>Test</p></body></html>');
equal(editor.getBody().style.color, '', 'No color on body.');
equal(editor.getBody().dir, '', 'No dir on body.');
equal(editor.dom.getStyle(editor.getBody().firstChild, 'display', true), 'block', 'No styles added to iframe document');
});
test('fullpage_hide_in_source_view: false', function() {
editor.settings.fullpage_hide_in_source_view = false;
editor.setContent('<html><body><p>1</p></body></html>');
equal(editor.getContent({source_view: true}), '<html><body>\n<p>1</p>\n</body></html>');
});
test('fullpage_hide_in_source_view: false', function() {
editor.settings.fullpage_hide_in_source_view = true;
editor.setContent('<html><body><p>1</p></body></html>');
equal(editor.getContent({source_view: true}), '<p>1</p>');
});
test('fullpage link elements', function() {
editor.setContent('<html><head><link rel="stylesheet" href="a.css"><link rel="something"></head><body><p>c</p></body></html>');
equal(editor.getContent(), '<html><head><link rel="stylesheet" href="a.css"><link rel="something"></head><body>\n<p>c</p>\n</body></html>');
});
test('fullpage add/remove stylesheets', function() {
editor.setContent('<html><head><link rel="stylesheet" href="a.css"></head><body><p>c</p></body></html>');
ok(hasLink("a.css"));
ok(!hasLink("b.css"));
ok(!hasLink("c.css"));
editor.setContent('<html><head><link rel="stylesheet" href="a.css"><link rel="stylesheet" href="b.css"></head><body><p>c</p></body></html>');
ok(hasLink("a.css"));
ok(hasLink("b.css"));
ok(!hasLink("c.css"));
editor.setContent('<html><head><link rel="stylesheet" href="a.css"><link rel="stylesheet" href="b.css"><link rel="stylesheet" href="c.css"></head><body><p>c</p></body></html>');
ok(hasLink("a.css"));
ok(hasLink("b.css"));
ok(hasLink("c.css"));
editor.setContent('<html><head><link rel="stylesheet" href="a.css"></head><body><p>c</p></body></html>');
ok(hasLink("a.css"));
ok(!hasLink("b.css"));
ok(!hasLink("c.css"));
editor.setContent('<html><head></head><body><p>c</p></body></html>');
ok(!hasLink("a.css"));
ok(!hasLink("b.css"));
ok(!hasLink("c.css"));
});
tinymce.init({
mode : "exact",
elements : "elm1",
plugins : "fullpage",
add_unload_trigger : false,
valid_styles : {
'*' : 'text-align,padding-left,color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
indent : 0,
setup: function(ed) {
ed.on('NodeChange', false);
},
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Fullpage plugin tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,126 @@
<!DOCTYPE html>
<html>
<head>
<title>jQuery Plugin tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="http://www.google.com/jsapi"></script>
<script>
google.load("jquery", "1");
</script>
<script src="../../js/tinymce/classes/jquery.tinymce.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("jQuery plugin", {
autostart: false
});
test("Get contents using jQuery", function() {
expect(4);
tinymce.get('elm1').setContent('<p>Editor 1</p>');
equal($('#elm1').html(), '<p>Editor 1</p>');
equal($('#elm1').val(), '<p>Editor 1</p>');
equal($('#elm1').attr('value'), '<p>Editor 1</p>');
equal($('#elm1').text(), 'Editor 1');
});
test("Set contents using jQuery", function() {
expect(4);
$('#elm1').html('Test 1');
equal($('#elm1').html(), '<p>Test 1</p>');
$('#elm1').val('Test 2');
equal($('#elm1').html(), '<p>Test 2</p>');
$('#elm1').text('Test 3');
equal($('#elm1').html(), '<p>Test 3</p>');
$('#elm1').attr('value', 'Test 4');
equal($('#elm1').html(), '<p>Test 4</p>');
});
test("append/prepend contents using jQuery", function() {
expect(2);
tinymce.get('elm1').setContent('<p>Editor 1</p>');
$('#elm1').append('<p>Test 1</p>');
equal($('#elm1').html(), '<p>Editor 1</p>\n<p>Test 1</p>');
$('#elm1').prepend('<p>Test 2</p>');
equal($('#elm1').html(), '<p>Test 2</p>\n<p>Editor 1</p>\n<p>Test 1</p>');
});
test("Find using :tinymce selector", function() {
expect(1);
equal($('textarea:tinymce').length, 2);
});
test("Set contents using :tinymce selector", function() {
expect(3);
$('textarea:tinymce').val('Test 1');
equal($('#elm1').val(), '<p>Test 1</p>');
equal($('#elm2').val(), '<p>Test 1</p>');
equal($('#elm3').val(), 'Textarea');
});
test("Get contents using :tinymce selector", function() {
expect(1);
$('textarea:tinymce').val('Test get');
equal($('textarea:tinymce').val(), '<p>Test get</p>');
});
QUnit.stop();
$(function() {
$('textarea.tinymce').tinymce({
// Location of TinyMCE script
script_url : location.search.indexOf('min=true') > 0 ? '../../js/tinymce/tinymce.min.js' : '../../js/tinymce/tinymce.js',
// General options
plugins : "pagebreak,layer,table,save,emoticons,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,template",
// Theme options
theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect",
theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emoticons,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : true,
init_instance_callback : function(ed) {
var ed1 = tinymce.get('elm1'), ed2 = tinymce.get('elm2');
// When both editors are initialized
if (ed1 && ed1.initialized && ed2 && ed2.initialized)
QUnit.start();
}
});
});
</script>
</head>
<body>
<h1 id="qunit-header">TinyMCE jQuery plugin tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1" class="tinymce">Editor 1</textarea>
<textarea id="elm2" name="elm2" class="tinymce">Editor 2</textarea>
<textarea id="elm3" name="elm3">Textarea</textarea>
</div>
</body>
</html>

View File

@ -0,0 +1,52 @@
function fakeTypeAURL(url) {
return function(callback) {
// type the URL and then press the space bar
tinymce.execCommand('mceInsertContent', false, url);
window.robot.type(32, false, callback, editor.selection.getNode());
};
}
function fakeTypeAnEclipsedURL(url) {
return function(callback) {
// type the URL and then type ')'
tinymce.execCommand('mceInsertContent', false, '(' + url);
window.robot.typeSymbol(")", function() {
window.robot.type(32, false, callback, editor.selection.getNode());
}, editor.selection.getNode());
};
}
function fakeTypeANewlineURL(url) {
return function(callback) {
// type the URL and then press the enter key
tinymce.execCommand('mceInsertContent', false, url);
window.robot.type('\n', false, callback, editor.selection.getNode());
};
}
createAction('Typing HTTP URL', fakeTypeAURL('http://www.ephox.com'));
createAction('Typing HTTPS URL', fakeTypeAURL('https://www.ephox.com'));
createAction('Typing SSH URL', fakeTypeAURL('ssh://www.ephox.com'));
createAction('Typing FTP URL', fakeTypeAURL('ftp://www.ephox.com'));
createAction('Typing WWW URL', fakeTypeAURL('www.ephox.com'));
createAction('Typing WWW URL With End Dot', fakeTypeAURL('www.site.com.'));
createAction('Typing Mail Addr', fakeTypeAURL('user@domain.com'));
createAction('Typing Mail Addr With Protocol', fakeTypeAURL('mailto:user@domain.com'));
createAction('Typing Dashed Mail Addr', fakeTypeAURL('first-last@domain.com'));
createAction('Typing Eclipsed HTTP URL', fakeTypeAnEclipsedURL('http://www.ephox.com'));
createAction('Typing Eclipsed HTTPS URL', fakeTypeAnEclipsedURL('https://www.ephox.com'));
createAction('Typing Eclipsed SSH URL', fakeTypeAnEclipsedURL('ssh://www.ephox.com'));
createAction('Typing Eclipsed FTP URL', fakeTypeAnEclipsedURL('ftp://www.ephox.com'));
createAction('Typing Eclipsed WWW URL', fakeTypeAnEclipsedURL('www.ephox.com'));
createAction('Typing HTTP URL And Newline', fakeTypeANewlineURL('http://www.ephox.com'));
createAction('Typing HTTPS URL And Newline', fakeTypeANewlineURL('https://www.ephox.com'));
createAction('Typing SSH URL And Newline', fakeTypeANewlineURL('ssh://www.ephox.com'));
createAction('Typing FTP URL And Newline', fakeTypeANewlineURL('ftp://www.ephox.com'));
createAction('Typing WWW URL And Newline', fakeTypeANewlineURL('www.ephox.com'));
createAction('Applying OL', 'InsertOrderedList');
createAction('Applying UL', 'InsertUnorderedList');
createAction('Indenting', 'Indent');
createAction('Outdenting', 'Outdent');
createAction('Typing Enter', fakeKeyPressAction('\n'));
createAction('Typing Tab', fakeKeyPressAction('\t'));
createAction('Typing Shift Tab', fakeKeyPressAction('\t', true));

View File

@ -0,0 +1,138 @@
var editor;
function getFunctionName(func) {
if (func.name && func.name != "") {
return func.name;
} else if (typeof func == "function" || typeof func == "object") {
var fName = ("" + func).match(/function\s*([\w\$]+)\s*\(/);
if (fName !== null && fName != "") {
return fName[1];
} else {
for (var v in window) {
if (window[v] === func) {
func.name = v;
return v;
}
}
}
}
}
function assertState(expected, message) {
var content = editor.getContent().replace(/[\n\r]/g, '');
if (expected && expected.replace) expected = expected.replace(/[\n\r]/g, '');
// Safari reports "function", while Firefox and IE report "object"
if (typeof expected == "function" || typeof expected == "object") {
if (expected.test(content))
equal(content, content, message);
else
equal(content, expected.toString(), message);
} else {
equal(content, expected, message);
}
}
tinymce.create('dsl.Queue', {
Queue: function() {
this.queue = [];
},
add: function(task) {
this.queue.push(task);
},
next: function() {
if (this.queue.length > 0) {
var task = this.queue.shift();
task();
return true;
} else {
QUnit.start();
return false;
}
},
done: function() {
expect(this.queue.length);
this.next();
}
});
tinymce.create('dsl.Action', {
Action: function(name, action) {
this.name = name;
this.a = this.curryPreposition('a');
this.inA = this.curryPreposition('in a');
this.to = this.curryPreposition('to');
if (tinymce.is(action, 'string')) {
this.action = function(callback) {
editor.execCommand(action);
callback();
};
} else {
this.action = action;
}
},
curryPreposition: function(preposition) {
return function(state) {
return this.go(state, preposition);
};
},
go: function(state, preposition) {
var message = this.name + " " + preposition + " " + getFunctionName(state);
var action = this.action;
var actionPerformed = false;
function defer(callback) {
return function() {
var args = arguments;
queue.add(function() {
if (actionPerformed) {
callback.apply(undefined, args);
queue.next();
return;
}
editor.focus();
state();
action(function() {
actionPerformed = true;
callback.apply(undefined, args);
queue.next();
});
});
return this;
};
}
var dslState = {
gives: defer(function(expected) {
assertState(expected, message);
}),
enablesState: defer(function(state) {
ok(editor.queryCommandState(state), message + " enables " + state + " command");
}),
disablesState: defer(function(state) {
ok(!editor.queryCommandState(state), message + " disables " + state + " command");
})
};
dslState.andGives = dslState.gives;
return dslState;
}
});
// Action Utilities
function fakeKeyPressAction(keyCode, shiftKey) {
return function(callback) {
setTimeout(function() {
window.robot.type(keyCode, shiftKey, callback, editor.selection.getNode());
}, 1);
};
}
function createAction(name, action) {
window[name.replace(/\s+/g, '')] = new dsl.Action(name, action);
}

View File

@ -0,0 +1,176 @@
function createState(content, startSelector, startOffset, endSelector, endOffset) {
return function() {
editor.setContent(content);
setSelection(startSelector, startOffset, endSelector, endOffset);
};
}
/** Collapsed Selection States **/
function EmptyParagraph() {
var body = editor.getBody();
while (body.firstChild) {
editor.dom.remove(body.firstChild);
}
var p = body.ownerDocument.createElement('p');
p.appendChild(body.ownerDocument.createTextNode(''));
body.appendChild(p, body);
setSelection(p.firstChild, 0);
}
function EmptyHeading() {
EmptyParagraph();
editor.dom.rename(editor.getBody().firstChild, 'h1');
setSelection(editor.getBody().firstChild.firstChild, 0);
}
function TextAfterUL() {
editor.setContent('<ul><li>Item</li></ul>Test');
setSelection(editor.dom.getRoot().lastChild, 2);
}
function TextAfterOL() {
editor.setContent('<ol><li>Item</li></ol>Test');
setSelection(editor.dom.getRoot().lastChild, 2);
}
EmptyContent = createState('', 'body', 0);
PlainText = createState('Test', 'body', 0);
NonEmptyParagraph = createState('<p>Test</p>', 'p', 0);
ParagraphWithMarginLeft = createState('<p style="margin-left: 60px;">Test</p>', 'p', 0);
ParagraphWithPaddingLeft = createState('<p style="padding-left: 60px;">Test</p>', 'p', 0);
ParagraphWithMarginAndPaddingLeft = createState('<p style="margin-left: 60px; padding-left: 60px;">Test</p>', 'p', 0);
CenteredListItem = createState('<ul><li style="text-align: center;">Item1</li><li>Item2</li></ul>', 'li:nth-child(1)', 2);
ItemInCenteredList = createState('<ul style="text-align: center;"><li>Item1</li><li>Item2</li></ul>', 'li:nth-child(1)', 2);
RightAlignedListItem = createState('<ul><li style="text-align: right;">Item1</li><li>Item2</li></ul>', 'li:nth-child(1)', 2);
ItemInRightAlignedList = createState('<ul style="text-align: right;"><li>Item1</li><li>Item2</li></ul>', 'li:nth-child(1)', 2);
ParagraphBetweenOrderedLists = createState('<ol><li>Item1</li></ol><p>Test</p><ol><li>Item2</li></ol>', 'p', 2);
ParagraphBetweenUnorderedLists = createState('<ul><li>Item1</li></ul><p>Test</p><ul><li>Item2</li></ul>', 'p', 2);
ParagraphBetweenMixedLists = createState('<ol><li>Item1</li></ol><p>Test</p><ul><li>Item2</li></ul>', 'p', 2);
NonEmptyHeading = createState('<h1>Test</h1>', 'h1', 0);
TableCellWithoutBrs = createState('<table><tbody><tr><td>Test</td><td>&nbsp;</td></tr></tbody></table>', 'td', 4);
TableCellWithoutBrs2 = createState('<table><tbody><tr><td>Test</td><td>&nbsp;</td></tr></tbody></table>', 'td', 0);
TableCellWithBrsFirstLine = createState('<table><tbody><tr><td>Test<br>Line 2</td><td>&nbsp;</td></tr></tbody></table>', 'td', 1);
TableCellWithBrsFirstLine2 = createState('<table><tbody><tr><td>Test<br>Line 2</td><td>&nbsp;</td></tr></tbody></table>', 'td', 0);
TableCellWithBrsMiddleLine = createState('<table><tbody><tr><td>Test<br/>Line 2<br/>Line 3</td><td>&nbsp;</td></tr></tbody></table>', 'td br:nth-child(1)', 'afterNextCharacter');
TableCellWithBrsLastLine = createState('<table><tbody><tr><td>Test<br>Line 2</td><td>&nbsp;</td></tr></tbody></table>', 'td br:nth-child(1)', 'afterNextCharacter');
TableCellWithAdjacentBrsFirstLine = createState('<table><tbody><tr><td>Test<br><br>Line 2</td><td>&nbsp;</td></tr></tbody></table>', 'td', 1);
HeadingInOrderedList = createState('<ol><li><h2>Test</h2></li></ol>', 'h2', '2');
HeadingInUnorderedList = createState('<ul><li><h2>Test</h2></li></ul>', 'h2', '2');
HeadingInOrderedListBeforeParagraph = createState('<ol><li><h2>Test</h2></li></ol><p>Content<br />After</p>', 'h2', '2');
DefinitionListDescription = createState('<dl><dt>Term</dt><dd>Description</dd></dl>', 'dd', 2);
DefinitionListTerm = createState('<dl><dt>Term</dt><dd>Description</dd></dl>', 'dt', 2);
EndOfParagraphBeforeOL = createState('<p>Test</p><ol><li>Item</li></ol>', 'p', 4);
EndOfParagraphBeforeOLWithListType = createState('<p>Test</p><ol style="list-style-type: lower-alpha;"><li>Item</li></ol>', 'p', 4);
EndOfParagraphBeforeUL = createState('<p>Test</p><ul><li>Item</li></ul>', 'p', 4);
StartOfParagraphAfterOL = createState('<ol><li>Item</li></ol><p>Test</p>', 'p', 1);
StartOfParagraphAfterUL = createState('<ul><li>Item</li></ul><p>Test</p>', 'p', 1);
StartOfParagraphAfterOLWithListType = createState('<ol style="list-style-type: lower-alpha;"><li>Item</li></ol><p>Test</p>', 'p', 1);
EmptyOrderedListItem = createState('<ol><li>Before</li><li>&nbsp;</li><li>After</li></ol>', 'li:nth-child(2)', 0);
EmptyUnorderedListItem = createState('<ul><li>Before</li><li>&nbsp;</li><li>After</li></ul>', 'li:nth-child(2)', 0);
NonEmptyOrderedListItem = createState('<ol><li>Before</li><li>Test</li><li>After</li></ol>', 'li:nth-child(2)', 0);
NonEmptyUnorderedListItem = createState('<ul><li>Before</li><li>Test</li><li>After</li></ul>', 'li:nth-child(2)', 0);
NestedEmptyOrderedListItem = createState('<ol><li>Before<ol><li>&nbsp;</li></ol></li><li>After</li></ol>', 'li ol li', 0);
NestedEmptyUnorderedListItem = createState('<ul><li>Before<ul><li>&nbsp;</li></ul></li><li>After</li></ul>', 'li ul li', 0);
NestedNonEmptyOrderedListItem = createState('<ol><li>Before<ol><li>Test</li></ol></li><li>After</li></ol>', 'li ol li', 0);
NestedNonEmptyUnorderedListItem = createState('<ul><li>Before<ul><li>Test</li></ul></li><li>After</li></ul>', 'li ul li', 0);
NestedOrderedListWithMultipleItems = createState('<ol><li>Before<ol><li>Item1</li><li>Item2</li></ol></li></ol>', 'li ol li', 0);
NestedUnorderedListWithMultipleItems = createState('<ul><li>Before<ul><li>Item1</li><li>Item2</li></ul></li></ul>', 'li ul li', 0);
OrderedLowerAlphaListItem = createState('<ol style="list-style-type: lower-alpha;"><li>Item 1</li><li>Item 2</li></ol>', 'li:nth-child(2)', 0);
UnorderedSquareListItem = createState('<ul style="list-style-type: square;"><li>Item 1</li><li>Item 2</li></ul>', 'li:nth-child(2)', 0);
OrderedListItemWithNestedChild = createState('<ol><li>Item1<ol><li>Nested</li></ol></li></ol>', 'li:nth-child(1)', 2);
UnorderedListItemWithNestedChild = createState('<ul><li>Item1<ul><li>Nested</li></ul></li></ul>', 'li:nth-child(1)', 2);
OrderedListWithAdjacentNestedLists = createState('<ol><li style="list-style-type: none;"><ol><li>Item 1</li></ol></li><li>Item 2</li><li style="list-style-type: none;"><ol><li>Item 3</li></ol></li></ol>', 'li:nth-child(2)', 4);
UnorderedListWithAdjacentNestedLists = createState('<ul><li style="list-style-type: none;"><ul><li>Item 1</li></ul></li><li>Item 2</li><li style="list-style-type: none;"><ul><li>Item 3</li></ul></li></ul>', 'li:nth-child(2)', 4);
OrderedListItemWithMargin = createState('<ol><li style="margin-left: 60px;">Test</li></ol>', 'li', 0);
UnorderedListItemWithMargin = createState('<ul><li style="margin-left: 60px;">Test</li></ul>', 'li', 0);
OrderedListItemWithNestedAlphaList = createState('<ol><li>Item<ol style="list-style-type: lower-alpha;"><li>Nested</li></ol></li></ol>', 'li', 2);
/** Collapsed DIV Tests **/
OrderedListItemInsideDiv = createState('<div id="div"><ol>\n<li>Item1</li><li>Item2</li></ol></div>', 'li:nth-child(1)', 2);
UnorderedListItemInsideDiv = createState('<div id="div"><ul>\n<li>Item1</li><li>Item2</li></ul></div>', 'li:nth-child(1)', 2);
ParagraphInDiv = createState('<div><p>Item</p></div>', 'p', 2);
TextInDiv = createState('<div>Item</div>', 'div', 2);
TextWithBrsInDivFirstLine = createState('<div>Item1<br />Item2</div>', 'div', 2);
TextWithBrsInDivMiddleLine = createState('<div>Item1<br />Item2<br />Item3</div>', 'br:nth-child(1)', 'afterNextCharacter');
TextWithBrsInDivLastLine = createState('<div>Item1<br />Item2</div>', 'br:nth-child(1)', 'afterNextCharacter');
TextWithBrsInFormattingInDiv = function() {
var rng;
editor.setContent('<div><strong>Before<br /></strong>Item1<br />Item2<br />Item3</div>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('div')[0].childNodes[1], 0);
rng.setEnd(editor.dom.select('div')[0], 6);
editor.selection.setRng(rng);
};
TextWithBrInsideFormatting = function() {
var rng;
editor.setContent('<div><em><strong>Before<br /><span class="foo">Item1</span></strong></em>Item2<br />Item3</div>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].childNodes[0], 2);
rng.setEnd(editor.dom.select('div')[0], 4);
editor.selection.setRng(rng);
};
/** Expanded Selection States **/
SingleParagraphSelection = createState('<p>This is a test</p>', 'p', 5, 'p', 7);
MultipleParagraphSelection = createState('<p>This is a test</p><p>Second paragraph</p>', 'p:nth-child(1)', 5, 'p:nth-child(2)', 6);
SingleHeadingSelection = createState('<h1>This is a test</h1>', 'h1', 5, 'h1', 7);
MultipleHeadingSelection = createState('<h1>This is a test</h1><h1>Second paragraph</h1>', 'h1:nth-child(1)', 5, 'h1:nth-child(2)', 6);
SingleBlockSelection = createState('<div>This is a test</div>', 'div', 5, 'div', 7);
MultipleBlockSelection = createState('<div>This is a test</div><div>Second paragraph</div>', 'div:nth-child(1)', 5, 'div:nth-child(2)', 6);
SingleBlockWithBrSelection = createState('<div>Item1<br />Item2</div>', 'div', 3, 'br', 'afterNextCharacter');
MultipleBlockWithBrSelection = createState('<div>Item1<br />Item2</div><div>Item3</div>', 'div:nth-child(1)', 2, 'div:nth-child(2)', 3);
MultipleBlockWithBrPartialSelection = createState('<div>Item1<br />Item2</div><div>Item3<br />Item4</div>', 'div:nth-child(1)', 2, 'div:nth-child(2)', 3);
MultipleBlockWithBrPartialSelectionAtEnd = createState('<div>Item1<br />Item2</div><div>Item3<br />Item4</div>', 'div:nth-child(1) br', 'afterNextCharacter', 'div:nth-child(2) br', 'afterNextCharacter');
MultipleBlockWithEmptyDivsAllSelected = createState('<div id="start">&nbsp;</div><div>a</div><div></div><div>b</div><div></div><div id="end">&nbsp;</div>', '#start', 0, '#end', 0);
CellWithoutBrSelection = createState('<table><tbody><tr><td>Cell 1</td></tr></tbody></table>', 'td', 1, 'td', 1); //selection is a single point so it will avoid table selection bugs in ie9.
CellWithBrSingleLineSelection = createState('<table><tbody><tr><td>Cell 1<br>Line 2</td></tr></tbody></table>', 'td', 1, 'td', 4);
CellWithBrMultipleLineSelection = createState('<table><tbody><tr><td>Cell 1<br>Line 2</td></tr></tbody></table>', 'td', 1, 'td', 4);
TableCellWithTextAfterUL = createState('<table><tbody><tr><td><ul><li>Existing</li></ul><span id="start">Line1</span><br />Line2<br id="end" />Line3<br />Line4</td></tr></tbody></table>', '#start', 1, '#end', 'afterNextCharacter');
ParagraphToHeadingSelection = createState('<p>This is a test</p><h1>Second paragraph</h1>', 'p', 5, 'h1', 6);
ParagraphToBlockSelection = createState('<p>This is a test</p><div>Second paragraph</div>', 'p', 5, 'div', 6);
HeadingToParagraphSelection = createState('<h1>This is a test</h1><p>Second paragraph</p>', 'h1', 5, 'p', 6);
BlockToParagraphSelection = createState('<div>This is a test</div><p>Second paragraph</p>', 'div', 5, 'p', 6);
MultipleParagraphAndHeadingSelection = createState('<p>This is a test</p><h1>Second paragraph</h1><div>Third paragraph</div>', 'p', 5, 'div', 5);
ThreeBoldDivsWithBrSelection = createState('<div><strong>One</strong></div><div><strong>Two</strong></div><div><strong>Three<br></strong></div>', 'div:nth-child(1) strong', 2, 'div:nth-child(3) strong', 2);
SingleLiOlSelection = createState('<ol><li>Item 1</li></ol>', 'li', 1, 'li', 4);
MultiLiOlSelection = createState('<ol><li>Item 1</li><li>Item 2</li></ol>', 'li:nth-child(1)', 1, 'li:nth-child(2)', 4);
SingleLiUlSelection = createState('<ul><li>Item 1</li></ul>', 'li', 1, 'li', 4);
MultiLiUlSelection = createState('<ul><li>Item 1</li><li>Item 2</li></ul>', 'li:nth-child(1)', 1, 'li:nth-child(2)', 4);
MultiNestedLiUlSelection = createState('<ul><li style="list-style-type: none;"><ul><li>Item 1</li><li>Item 2</li></ul></li></ul>', 'li li:nth-child(1)', 1, 'li li:nth-child(2)', 4);
MultiNestedLiOlSelection = createState('<ol><li style="list-style-type: none;"><ol><li>Item 1</li><li>Item 2</li></ol></li></ol>', 'li li:nth-child(1)', 1, 'li li:nth-child(2)', 4);
IndentedOlInOlCorrectSelection = createState('<ol><li>Item 1<ol><li>Indented</li></ol></li></ol>', 'li', 1, 'li li', 4);
IndentedUlInUlCorrectSelection = createState('<ul><li>Item 1<ul><li>Indented</li></ul></li></ul>', 'li', 1, 'li li', 4);
IndentedOlInOlIncorrectSelection = createState('<ol><li>Item 1</li><ol><li>Indented</li></ol></ol>', 'li', 1, 'ol ol li', 4);
IndentedUlInUlIncorrectSelection = createState('<ul><li>Item 1</li><ul><li>Indented</li></ul></ul>', 'li', 1, 'ul ul li', 4);
IndentedOlInUlCorrectSelection = createState('<ul><li>Item 1<ol><li>Indented</li></ol></li></ul>', 'li', 1, 'li li', 4);
IndentedUlInOlCorrectSelection = createState('<ol><li>Item 1<ul><li>Indented</li></ul></li></ol>', 'li', 1, 'li li', 4);
IndentedOlInUlIncorrectSelection = createState('<ul><li>Item 1</li><ol><li>Indented</li></ol></ul>', 'li', 1, 'ul ol li', 4);
IndentedUlInOlIncorrectSelection = createState('<ol><li>Item 1</li><ul><li>Indented</li></ul></ol>', 'li', 1, 'ol ul li', 4);
// TODO: Paragraph/heading to list combinations.
ParagraphBeforeOlSelection = createState('<p>Before</p><ol><li>Item 1</li></ol>', 'p', 3, 'li', 4);
ParagraphBeforeUlSelection = createState('<p>Before</p><ul><li>Item 1</li></ul>', 'p', 3, 'li', 4);
ParagraphAfterOlSelection = createState('<ol><li>Item 1</li></ol><p>After</p>', 'li', 4, 'p', 3);
ParagraphAfterUlSelection = createState('<ul><li>Item 1</li></ul><p>After</p>', 'li', 4, 'p', 3);
ParagraphBeforeAndAfterOlSelection = createState('<p>Before</p><ol><li>Item 1</li></ol><p id="after">After</p>', 'p', 4, '#after', 3);
ParagraphBeforeAndAfterUlSelection = createState('<p>Before</p><ul><li>Item 1</li></ul><p id="after">After</p>', 'p', 4, '#after', 3);
SelectionEndingAtBr = createState('<p>Item<br>After</p>', 'p', 2, 'br', 'after');
SelectionStartingAtBr = createState('<p>Before<br>Item</p>', 'p', 'after', 'br', 'afterNextCharacter');

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for Media Plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="../js/utils.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Legacyoutput plugin", {
autostart: false
});
test("Font color", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('forecolor', false, '#FF0000');
equal(editor.getContent().toLowerCase(), '<p><font color="#ff0000">text</font></p>');
});
test("Font size", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('fontsize', false, 7);
equal(editor.getContent(), '<p><font size="7">text</font></p>');
});
test("Font face", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('fontname', false, "times");
equal(editor.getContent(), '<p><font face="times">text</font></p>');
});
test("Bold", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('bold');
equal(editor.getContent(), '<p><b>text</b></p>');
});
test("Italic", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('italic');
equal(editor.getContent(), '<p><i>text</i></p>');
});
test("Underline", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('underline');
equal(editor.getContent(), '<p><u>text</u></p>');
});
test("Strikethrough", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('strikethrough');
equal(editor.getContent(), '<p><strike>text</strike></p>');
});
test("Justifyleft", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('justifyleft');
equal(editor.getContent(), '<p align="left">text</p>');
});
test("Justifycenter", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('justifycenter');
equal(editor.getContent(), '<p align="center">text</p>');
});
test("Justifyright", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('justifyright');
equal(editor.getContent(), '<p align="right">text</p>');
});
test("Justifyfull", function() {
editor.setContent('<p>text</p>');
setSelection('p', 0, 'p', 4);
editor.execCommand('justifyfull');
equal(editor.getContent(), '<p align="justify">text</p>');
});
function initTiny(settings, load) {
var default_settings = {
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
document_base_url : '/tinymce/tinymce/trunk/tests/',
plugins : 'legacyoutput',
init_instance_callback : function(ed) {
editor = ed;
load();
}
};
var settings = tinymce.extend(default_settings, settings);
tinymce.init(settings);
}
initTiny({}, QUnit.start);
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for Legacyoutput Plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for Media Plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Media plugin", {
autostart: false
});
test("Object retain as is", function() {
editor.setContent(
'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355">' +
'<param name="movie" value="someurl">' +
'<param name="wmode" value="transparent">' +
'<embed src="someurl" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355" />' +
'</object>'
);
equal(editor.getContent(),
'<p><object width="425" height="355" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">' +
'<param name="movie" value="someurl">' +
'<param name="wmode" value="transparent">' +
'<embed src="someurl" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355" />' +
'</object></p>'
);
});
test("Embed retain as is", function() {
editor.setContent(
'<video src="320x240.ogg" autoplay loop controls>text<a href="#">link</a></video>'
);
equal(editor.getContent(),
// IE produces a different attribute order for some odd reason, I love IE
tinymce.isIE ?
'<p><video width="300" height="150" controls="controls" loop="loop" autoplay="autoplay" src="320x240.ogg">text<a href="#">link</a></video></p>' :
'<p><video width="300" height="150" src="320x240.ogg" autoplay="autoplay" loop="loop" controls="controls">text<a href="#">link</a></video></p>'
);
});
test("Video retain as is", function() {
editor.setContent(
'<video src="320x240.ogg" autoplay loop controls>text<a href="#">link</a></video>'
);
equal(editor.getContent(),
// IE produces a different attribute order for some odd reason, I love IE
tinymce.isIE ?
'<p><video width="300" height="150" controls="controls" loop="loop" autoplay="autoplay" src="320x240.ogg">text<a href="#">link</a></video></p>' :
'<p><video width="300" height="150" src="320x240.ogg" autoplay="autoplay" loop="loop" controls="controls">text<a href="#">link</a></video></p>'
);
});
test("Iframe retain as is", function() {
editor.setContent(
'<iframe src="320x240.ogg" allowfullscreen>text<a href="#">link</a></iframe>'
);
equal(editor.getContent(),
'<p><iframe src="320x240.ogg" width="300" height="150" allowfullscreen="allowfullscreen">text<a href="#">link</a></iframe></p>'
);
});
test("Audio retain as is", function() {
editor.setContent(
'<audio src="sound.mp3">' +
'<track kind="captions" src="foo.en.vtt" srclang="en" label="English">' +
'<track kind="captions" src="foo.sv.vtt" srclang="sv" label="Svenska">' +
'text<a href="#">link</a>' +
'</audio>'
);
equal(editor.getContent(),
'<p>' +
'<audio src="sound.mp3">' +
'<track kind="captions" src="foo.en.vtt" srclang="en" label="English">' +
'<track kind="captions" src="foo.sv.vtt" srclang="sv" label="Svenska">' +
'text<a href="#">link</a>' +
'</audio>' +
'</p>'
);
});
test("Resize complex object", function() {
editor.setContent(
'<video width="300" height="150" controls="controls">' +
'<source src="s" />' +
'<object type="application/x-shockwave-flash" data="../../js/tinymce/plugins/media/moxieplayer.swf" width="300" height="150">' +
'<param name="allowfullscreen" value="true" />' +
'<param name="allowscriptaccess" value="always" />' +
'<param name="flashvars" value="video_src=s" />' +
'<!--[if IE]><param name="movie" value="../../js/tinymce/plugins/media/moxieplayer.swf" /><![endif]-->' +
'</object>' +
'</video>'
);
var placeholderElm = editor.getBody().firstChild.firstChild;
placeholderElm.width = 100;
placeholderElm.height = 200;
editor.fire('objectResized', {target: placeholderElm, width: placeholderElm.width, height: placeholderElm.height});
equal(editor.getContent(),
'<p>' +
'<video width="100" height="200" controls="controls">' +
'<source src="s" />' +
'<object type="application/x-shockwave-flash" data="../../js/tinymce/plugins/media/moxieplayer.swf" width="100" height="200">' +
'<param name="allowfullscreen" value="true" />' +
'<param name="allowscriptaccess" value="always" />' +
'<param name="flashvars" value="video_src=s" />' +
'<!--[if IE]>' +
'<param name="movie" value="../../js/tinymce/plugins/media/moxieplayer.swf" />' +
'<![endif]-->' +
'</object>' +
'</video>' +
'</p>'
);
});
test("Media script elements", function() {
editor.setContent(
'<script src="http://media1.tinymce.com/123456"></sc'+'ript>' +
'<script src="http://media2.tinymce.com/123456"></sc'+'ript>'
);
equal(editor.getBody().getElementsByTagName('img')[0].className, 'mce-object mce-object-script');
equal(editor.getBody().getElementsByTagName('img')[0].width, 300);
equal(editor.getBody().getElementsByTagName('img')[0].height, 150);
equal(editor.getBody().getElementsByTagName('img')[1].className, 'mce-object mce-object-script');
equal(editor.getBody().getElementsByTagName('img')[1].width, 100);
equal(editor.getBody().getElementsByTagName('img')[1].height, 200);
equal(editor.getContent(),
'<p>\n' +
'<script src="http://media1.tinymce.com/123456" type="text/javascript"></sc'+'ript>\n' +
'<script src="http://media2.tinymce.com/123456" type="text/javascript"></sc'+'ript>\n' +
'</p>'
);
});
tinymce.init({
mode: "exact",
elements: "elm1",
add_unload_trigger: false,
document_base_url: '/tinymce/tinymce/trunk/tests/',
plugins: 'media',
media_scripts: [
{filter: 'http://media1.tinymce.com'},
{filter: 'http://media2.tinymce.com', width: 100, height: 200}
],
init_instance_callback: function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for Media Plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,237 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for noneditable</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor, rng;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Noneditable plugin", {
autostart: false
});
test('expand to noneditable (start)', function() {
editor.setContent('<p><span class="mceNonEditable">no</span>yes</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild.firstChild, 1);
rng.setEnd(editor.getBody().firstChild.lastChild, 1);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 0);
equal(rng.endContainer.nodeName, '#text');
equal(rng.endOffset, 1);
});
test('expand to noneditable (end)', function() {
editor.setContent('<p>yes<span class="mceNonEditable">no</span></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().firstChild.lastChild.firstChild, 1);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, '#text');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 2);
});
test('expand to noneditable (start/end)', function() {
editor.setContent('<p>yes<span class="mceNonEditable">noedit</span>yes</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 1);
rng.setEnd(editor.dom.select('span')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 2);
});
test('type after non editable', function() {
editor.setContent('<p><span class="mceNonEditable">no</span>yes</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 2);
rng.setEnd(editor.dom.select('span')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
type('X');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.getAttribute('data-mce-bogus'), 'true');
equal(rng.startContainer.nodeName, 'SPAN');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'SPAN');
equal(rng.endOffset, 1);
equal(editor.getContent(), '<p><span class="mceNonEditable">no</span>Xyes</p>');
});
test('type between non editable', function() {
editor.setContent('<p><span class="mceNonEditable">no</span><span class="mceNonEditable">no</span></p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 2);
rng.setEnd(editor.dom.select('span')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
type('X');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.getAttribute('data-mce-bogus'), 'true');
equal(rng.startContainer.nodeName, 'SPAN');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'SPAN');
equal(rng.endOffset, 1);
equal(editor.getContent(), '<p><span class="mceNonEditable">no</span>X<span class="mceNonEditable">no</span></p>');
});
test('type after last non editable', function() {
editor.setContent('<p><span class="mceNonEditable">no</span></p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 2);
rng.setEnd(editor.dom.select('span')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.dom.fire(editor.getBody(), 'mouseup');
type('X');
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.getAttribute('data-mce-bogus'), 'true');
equal(rng.startContainer.nodeName, 'SPAN');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'SPAN');
equal(rng.endOffset, 1);
equal(editor.getContent(), '<p><span class="mceNonEditable">no</span>X</p>');
});
test('escape noneditable inline element (left)', function() {
editor.setContent('<p>no <span class="mceNonEditable">yes</span> no</p><p class="mceNonEditable">no</p>');
var container = editor.dom.select('p')[0];
rng = editor.dom.createRng();
rng.selectNode(editor.dom.select('span')[0]);
editor.selection.setRng(rng);
type({keyCode: 37});
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, 'SPAN');
equal(rng.startContainer.parentNode.nodeName, 'P');
equal(editor.dom.nodeIndex(rng.startContainer), 1);
equal(rng.collapsed, true);
});
test('escape noneditable inline element (right)', function() {
editor.setContent('<p>no <span class="mceNonEditable">yes</span> no</p><p class="mceNonEditable">no</p>');
var container = editor.dom.select('p')[0];
rng = editor.dom.createRng();
rng.selectNode(editor.dom.select('span')[0]);
editor.selection.setRng(rng);
type({keyCode: 39});
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, 'SPAN');
equal(rng.startContainer.parentNode.nodeName, 'P');
equal(editor.dom.nodeIndex(rng.startContainer), 2);
equal(rng.collapsed, true);
});
test('escape noneditable block element (left)', function(){
editor.setContent('<p>yes</p><p class="mceNonEditable">no</p><p>yes</p>');
rng = editor.dom.createRng();
rng.selectNode(editor.dom.select('p')[1]);
editor.selection.setRng(rng);
type({keyCode: 37});
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, "P");
equal(editor.dom.nodeIndex(rng.startContainer), 0);
equal(rng.startOffset, 1);
equal(rng.collapsed, true);
});
test('escape noneditable block element (right)', function(){
editor.setContent('<p>yes</p><p class="mceNonEditable">no</p><p>yes</p>');
rng = editor.dom.createRng();
rng.selectNode(editor.dom.select('p')[1]);
editor.selection.setRng(rng);
type({keyCode: 39});
rng = normalizeRng(editor.selection.getRng(true));
equal(rng.startContainer.nodeName, "P");
equal(editor.dom.nodeIndex(rng.startContainer), 2);
equal(rng.startOffset, 0);
equal(rng.collapsed, true);
});
test('noneditable regexp', function() {
editor.setContent('<p>{test1}{test2}</p>');
equal(editor.dom.select('span').length, 2);
equal(editor.getContent(), '<p>{test1}{test2}</p>');
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
indent : false,
theme_advanced_styles : 'test1=test1;test2=test2',
noneditable_regexp : [/\{[^\}]+\}/g],
valid_elements : '@[contenteditable|id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong,b,em,i,strike,u,#p,-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value|tabindex|accesskey],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
plugins: 'noneditable',
forced_root_block : '',
convert_fonts_to_spans : false,
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests noneditable plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic editor functionality tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
function check_plugin_loaded(name){
var pluginManager = tinymce.PluginManager;
var depPlugin = pluginManager.get(name);
ok(depPlugin, name + " plugin should have loaded");
}
test('Dependency Chain Legacy style test', function() {
expect(3);
check_plugin_loaded("example");
check_plugin_loaded("example_dependency");
check_plugin_loaded("depend_chain");
});
tinymce.create('tinymce.plugins.DependencyChain', {});
// Register plugin
tinymce.PluginManager.add('depend_chain', tinymce.plugins.DependencyChain, ["example_dependency"]);
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
plugins: "depend_chain",
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugin Dependency Functional tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
function check_plugin_loaded(name){
var pluginManager = tinymce.PluginManager;
var depPlugin = pluginManager.get(name);
ok(depPlugin, name + " plugin should have loaded");
}
test('Dependency Chain Legacy style test', function() {
expect(3);
check_plugin_loaded("example");
check_plugin_loaded("example_dependency");
check_plugin_loaded("depend_chain");
});
tinymce.create('tinymce.plugins.DependencyChain', {});
// Register plugin
tinymce.PluginManager.add('depend_chain', tinymce.plugins.DependencyChain, ["example_dependency"]);
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
plugins: "-depend_chain",
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic editor functionality tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
function check_plugin_order(order){
deepEqual(plugin_load_order, order, "Load order for plugins");
}
test('PluginDependencyIsLoaded', function() {
expect(1);
check_plugin_order(["one", "two", "three", "four"]);
});
var plugin_load_order =[];
tinymce.create('tinymce.plugins.One', {
init: function(ed, url) {plugin_load_order.push("one");}
});
tinymce.create('tinymce.plugins.Two', {
init: function(ed, url) {plugin_load_order.push("two");}
});
tinymce.create('tinymce.plugins.Three', {
init: function(ed, url) {plugin_load_order.push("three");}
});
tinymce.create('tinymce.plugins.Four', {
init: function(ed, url) {plugin_load_order.push("four");}
});
// Register plugin
tinymce.PluginManager.add('two', tinymce.plugins.Two, ["one"]);
tinymce.PluginManager.add('three', tinymce.plugins.Three, ["two"]);
tinymce.PluginManager.add('one', tinymce.plugins.One);
tinymce.PluginManager.add('four', tinymce.plugins.Four, ["one", "two"]);
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
plugins: "-three,-four",
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic editor functionality tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
test('PluginDependencyIsLoaded', function() {
expect(2);
var pluginManager = tinymce.PluginManager;
var depPlugin = pluginManager.get("example_dependency");
ok(depPlugin, "Example Dependent plugin should have loaded");
var examplePlugin = pluginManager.get("example");
ok(examplePlugin, "Example plugin should have loaded via dependencies");
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
plugins: "example_dependency",
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,58 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic editor functionality tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
function check_plugin_loaded(name){
var pluginManager = tinymce.PluginManager;
var depPlugin = pluginManager.get(name);
ok(depPlugin, name + " plugin should have loaded");
}
test('Plugin Dependency Loaded from a Specific location', function() {
expect(2);
check_plugin_loaded("specific_location");
check_plugin_loaded("autolink");
});
tinymce.create('tinymce.plugins.SpecificLocation', {});
// Register plugin
tinymce.PluginManager.add('specific_location', tinymce.plugins.SpecificLocation, [{prefix: "plugins/", resource:"autolink", suffix:'/plugin' + tinymce.suffix + '.js'}]);
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
plugins: "-specific_location",
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for searchreplace plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor, rng;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.SearchReplace", {
autostart: false
});
test('Find no match', function() {
editor.getBody().innerHTML = 'a';
equal(0, editor.plugins.searchreplace.find('x'));
});
test('Find single match', function() {
editor.getBody().innerHTML = 'a';
equal(1, editor.plugins.searchreplace.find('a'));
});
test('Find single match in multiple elements', function() {
editor.getBody().innerHTML = 't<b>e</b><em>xt</em>';
equal(1, editor.plugins.searchreplace.find('text'));
});
test('Find single match, match case: true', function() {
editor.getBody().innerHTML = 'a A';
equal(1, editor.plugins.searchreplace.find('A', true));
});
test('Find single match, whole words: true', function() {
editor.getBody().innerHTML = 'a Ax';
equal(1, editor.plugins.searchreplace.find('a', false, true));
});
test('Find multiple matches', function() {
editor.getBody().innerHTML = 'a b A';
equal(2, editor.plugins.searchreplace.find('a'));
});
test('Find and replace single match', function() {
editor.getBody().innerHTML = 'a';
editor.plugins.searchreplace.find('a');
ok(!editor.plugins.searchreplace.replace('x'));
equal("<p>x</p>", editor.getContent());
});
test('Find and replace first in multiple matches', function() {
editor.getBody().innerHTML = 'a b a';
editor.plugins.searchreplace.find('a');
ok(editor.plugins.searchreplace.replace('x'));
equal("<p>x b a</p>", editor.getContent());
});
test('Find and replace all in multiple matches', function() {
editor.getBody().innerHTML = 'a b a';
editor.plugins.searchreplace.find('a');
ok(!editor.plugins.searchreplace.replace('x', true, true));
equal("<p>x b x</p>", editor.getContent());
});
test('Find multiple matches, move to next and replace', function() {
editor.getBody().innerHTML = 'a a';
equal(2, editor.plugins.searchreplace.find('a'));
editor.plugins.searchreplace.next();
ok(!editor.plugins.searchreplace.replace('x'));
equal("<p>a x</p>", editor.getContent());
});
test('Find multiple matches, move to next and replace backwards', function() {
editor.getBody().innerHTML = 'a a';
equal(2, editor.plugins.searchreplace.find('a'));
editor.plugins.searchreplace.next();
ok(editor.plugins.searchreplace.replace('x', false));
ok(!editor.plugins.searchreplace.replace('y', false));
equal("<p>y x</p>", editor.getContent());
});
test('Find multiple matches and unmark them', function() {
editor.getBody().innerHTML = 'a b a';
equal(2, editor.plugins.searchreplace.find('a'));
editor.plugins.searchreplace.done();
equal('a', editor.selection.getContent());
equal(0, editor.getBody().getElementsByTagName('span').length);
});
test('Find multiple matches with pre blocks', function() {
editor.getBody().innerHTML = 'abc<pre> abc </pre>abc';
equal(3, editor.plugins.searchreplace.find('b'));
equal(normalizeHtml(editor.getBody().innerHTML), (
'a<span class="mce-match-marker mce-match-marker-selected" data-mce-bogus="1" data-mce-index="0">b</span>c' +
'<pre> a<span class="mce-match-marker" data-mce-bogus="1" data-mce-index="1">b</span>c </pre>' +
'a<span class="mce-match-marker" data-mce-bogus="1" data-mce-index="2">b</span>c'
));
});
tinymce.init({
mode: "exact",
plugins: "searchreplace",
elements: "elm1",
add_unload_trigger: false,
indent: false,
disable_nodechange: true,
init_instance_callback : function(ed) {
editor = ed;
window.setTimeout(function() {
QUnit.start();
}, 0);
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for lists plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<a href="javascript:;" onclick="alert(tinymce.get('elm1').getContent({format: 'raw'}));return false;">[Get raw]</a>
</body>
</html>

View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for spellchecker plugin</title>
<meta http-eqiv="X-UA-Compatible" content="IE-edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editors = {}, awaitingInit=2;
initTinyMCE({
instance_name: 'no_lang'
});
initTinyMCE({
instance_name: 'one_lang',
spellchecker_languages: 'English=en'
});
initTinyMCE({
instance_name: 'many_lang',
spellchecker_languages: 'English=en,French=fr,German=de'
});
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.Spellchecker", {
autostart: false
});
// Default spellchecker language should match editor language
test('Check default language', function() {
var mainLanguage = editors.no_lang.settings.language || 'en';
equal(editors.no_lang.settings.spellchecker_language, mainLanguage);
});
// Spellchecker button may include a language menu
// When no languages are specified, the default list of languages should be
// used, matching the list in the old TinyMCE 3 spellchecker plugin.
test('Check spellcheck button is a splitbutton (no languages)', function() {
var spellcheckButton = editors.no_lang.buttons.spellchecker;
equal(spellcheckButton.type, 'splitbutton');
});
// When exactly one spellchecker language is specified, there's no need to
// display a selection menu.
test('Check spellcheck button is a normal button (one language)', function() {
var spellcheckButton = editors.one_lang.buttons.spellchecker;
equal(spellcheckButton.type, 'button');
});
// When more than one spellchecker language is specified, a selection menu
// should be provided to choose between them.
test('Check spellcheck button is a splitbutton (many languages)', function() {
var spellcheckButton = editors.many_lang.buttons.spellchecker;
equal(spellcheckButton.type, 'splitbutton');
});
function initTinyMCE(args) {
var instance_name = args.instance_name;
var init_args = {
mode: "exact",
plugins: "spellchecker",
selector: '#' + instance_name,
add_unload_trigger: false,
disable_nodechange: true,
toolbar1: "spellchecker",
init_instance_callback: function(ed) {
editors[instance_name] = ed;
checkEditorsReady();
}
};
if (args.spellchecker_languages) {
init_args.spellchecker_languages = args.spellchecker_languages;
}
tinymce.init(init_args);
}
function checkEditorsReady() {
awaitingInit--;
if (awaitingInit == 0) {
window.setTimeout(function() {
QUnit.start();
}, 0);
}
}
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for spellchecker plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="no_lang"></textarea>
<a href="javascript:;" onclick="alert(tinymce.get('no_lang').getContent({format: 'raw'}));return false;">[Get raw]</a>
<textarea id="one_lang"></textarea>
<a href="javascript:;" onclick="alert(tinymce.get('one_lang').getContent({format: 'raw'}));return false;">[Get raw]</a>
<textarea id="many_lang"></textarea>
<a href="javascript:;" onclick="alert(tinymce.get('many_lang').getContent({format: 'raw'}));return false;">[Get raw]</a>
</body>
</html>

View File

@ -0,0 +1,348 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for the Table plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Table plugin", {
autostart: false
});
function getFontmostWindow() {
return editor.windowManager.windows[editor.windowManager.windows.length - 1];
}
function fillAndSubmitWindowForm(data) {
var win = getFontmostWindow();
win.fromJSON(data);
win.find('form')[0].submit();
win.close();
}
function cleanTableHtml(html) {
return cleanHtml(html).replace(/<p>(&nbsp;|<br[^>]+>)<\/p>$/, '');
}
test("Table properties dialog (get data from plain table)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
deepEqual(getFontmostWindow().toJSON(), {
"align": false,
"border": "",
"caption": false,
"cellpadding": "",
"cellspacing": "",
"height": "",
"width": ""
});
getFontmostWindow().close();
});
test("Table properties dialog (get data from full table)", function() {
editor.setContent(
'<table style="width: 100px; height: 101px;" border="4" cellspacing="2" cellpadding="3">' +
'<caption>&nbsp;</caption>' +
'<tbody>' +
'<tr>' +
'<td>&nbsp;</td>' +
'</tr>' +
'</tbody>' +
'</table>'
);
setSelection('td', 0);
editor.execCommand('mceInsertTable');
deepEqual(getFontmostWindow().toJSON(), {
"align": false,
"border": "4",
"caption": true,
"cellpadding": "3",
"cellspacing": "2",
"height": "101",
"width": "100"
});
getFontmostWindow().close();
});
test("Table properties dialog (add caption)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
fillAndSubmitWindowForm({
caption: true
});
equal(
cleanTableHtml(editor.getContent()),
'<table><caption>&nbsp;</caption><tbody><tr><td>x</td></tr></tbody></table>'
);
});
test("Table properties dialog (remove caption)", function() {
editor.setContent('<table><caption>&nbsp;</caption><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
fillAndSubmitWindowForm({
caption: false
});
equal(
cleanTableHtml(editor.getContent()),
'<table><tbody><tr><td>x</td></tr></tbody></table>'
);
});
test("Table properties dialog (change size in pixels)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
fillAndSubmitWindowForm({
width: 100,
height: 101
});
equal(
cleanTableHtml(editor.getContent()),
'<table style="width: 100px; height: 101px;"><tbody><tr><td>x</td></tr></tbody></table>'
);
});
test("Table properties dialog (change size in %)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
fillAndSubmitWindowForm({
width: "100%",
height: "101%"
});
equal(
cleanTableHtml(editor.getContent()),
'<table style="width: 100%; height: 101%;"><tbody><tr><td>x</td></tr></tbody></table>'
);
});
test("Table properties dialog (change: border,cellpadding,cellspacing,align)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceInsertTable');
fillAndSubmitWindowForm({
border: "1",
cellpadding: "2",
cellspacing: "3",
align: "right"
});
equal(
cleanTableHtml(editor.getContent()),
'<table style="float: right;" border="1" cellspacing="3" cellpadding="2"><tbody><tr><td>x</td></tr></tbody></table>'
);
});
test("Table cell properties dialog (get data from plain cell)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableCellProps');
deepEqual(getFontmostWindow().toJSON(), {
"align": false,
"height": "",
"scope": "",
"type": "td",
"width": ""
});
getFontmostWindow().close();
});
test("Table cell properties dialog (get data from complex cell)", function() {
editor.setContent('<table><tr><th style="text-align: right; width: 10px; height: 11px" scope="row">X</th></tr></table>');
setSelection('th', 0);
editor.execCommand('mceTableCellProps');
deepEqual(getFontmostWindow().toJSON(), {
"align": "right",
"height": "11",
"scope": "row",
"type": "th",
"width": "10"
});
getFontmostWindow().close();
});
test("Table cell properties dialog (update all)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableCellProps');
fillAndSubmitWindowForm({
"align": "right",
"height": "11",
"scope": "row",
"type": "th",
"width": "10"
});
equal(
cleanTableHtml(editor.getContent()),
'<table><tbody><tr><th style="width: 10px; height: 11px; text-align: right;" scope="row">x</th></tr></tbody></table>'
);
});
test("Table row properties dialog (get data from plain cell)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableRowProps');
deepEqual(getFontmostWindow().toJSON(), {
"align": false,
"height": "",
"type": "tbody"
});
getFontmostWindow().close();
});
test("Table row properties dialog (get data from complex cell)", function() {
editor.setContent('<table><thead><tr style="height: 10px; text-align: right"><td>X</td></tr></thead></table>');
setSelection('td', 0);
editor.execCommand('mceTableRowProps');
deepEqual(getFontmostWindow().toJSON(), {
"align": "right",
"height": "10",
"type": "thead"
});
getFontmostWindow().close();
});
test("Table row properties dialog (update all)", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableRowProps');
fillAndSubmitWindowForm({
"align": "right",
"height": "10",
"type": "thead"
});
equal(
cleanTableHtml(editor.getContent()),
'<table><thead><tr style="height: 10px; text-align: right;"><td>x</td></tr></thead></table>'
);
});
test("mceTableDelete command", function() {
editor.setContent('<table><tr><td>X</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableDelete');
equal(cleanTableHtml(editor.getContent()), '');
});
test("mceTableDeleteCol command", function() {
editor.setContent('<table><tr><td>1</td><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableDeleteCol');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>2</td></tr></tbody></table>');
});
test("mceTableDeleteRow command", function() {
editor.setContent('<table><tr><td>1</td></tr><tr><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableDeleteRow');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>2</td></tr></tbody></table>');
});
test("mceTableInsertColAfter command", function() {
editor.setContent('<table><tr><td>1</td></tr><tr><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableInsertColAfter');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>1</td><td>&nbsp;</td></tr><tr><td>2</td><td>&nbsp;</td></tr></tbody></table>');
});
test("mceTableInsertColBefore command", function() {
editor.setContent('<table><tr><td>1</td></tr><tr><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableInsertColBefore');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>&nbsp;</td><td>1</td></tr><tr><td>&nbsp;</td><td>2</td></tr></tbody></table>');
});
test("mceTableInsertRowAfter command", function() {
editor.setContent('<table><tr><td>1</td><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableInsertRowAfter');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>1</td><td>2</td></tr><tr><td>&nbsp;</td><td>&nbsp;</td></tr></tbody></table>');
});
test("mceTableInsertRowBefore command", function() {
editor.setContent('<table><tr><td>1</td><td>2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableInsertRowBefore');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>1</td><td>2</td></tr></tbody></table>');
});
test("mceTableMergeCells command with cell selection", function() {
editor.setContent('<table><tr><td class="mce-item-selected">1</td><td class="mce-item-selected">2</td></tr></table>');
setSelection('td', 0);
editor.execCommand('mceTableMergeCells');
equal(cleanTableHtml(editor.getContent()), '<table><tbody><tr><td colspan="2">12</td></tr></tbody></table>');
});
test("mceTableSplitCells command", function() {
editor.setContent('<table><tbody><tr><td colspan="2">12</td></tr></tbody></table>');
setSelection('td', 0);
editor.execCommand('mceTableSplitCells');
equal(
cleanTableHtml(editor.getContent()),
'<table><tbody><tr><td>12</td><td>&nbsp;</td></tr></tbody></table>'
);
});
tinymce.init({
selector: "textarea",
add_unload_trigger: false,
plugins: 'table',
valid_styles: {
'*' : 'width,height,text-align,float'
},
init_instance_callback: function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
<h1 id="qunit-header">Unit tests for the Table plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html>
<head>
<title>Table plugin tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="../js/jsrobot/robot.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module('Table plugin', {
autostart: false
});
var VK;
var UP_ARROW = 0x26;
var DOWN_ARROW = 0x28;
var ENTER = 0xA;
if (tinymce.isWebKit) {
asyncTest('Selecting Cell and typing should update cell correctly in WebKit', function() {
editor.setContent('<table><tr><td><p>first cell</p></td><td><p>second cell</p></td></tr></table>');
// in order for the robot to work well, we need to focus the editor before performing selection on it.
editor.focus();
// in order to simulate the section on tables as per the plugin we do a select then call out to the fix table selection
// (which is called by selection events).
editor.selection.select(editor.dom.select('td')[0]);
editor.fire('keydown');
robot.type('g',false, function(){
var expected = '<table><tbody><tr><td><p>g</p></td><td><p>second cell</p></td></tr></tbody></table>';
var actual = editor.getContent();
equal(actual, expected);
start();
}, editor.getBody());
});
} else {
asyncTest('Empty stub', function() {
start();
ok(true, "Dummy");
});
}
function testCursorKey(html, nodeToSelect, keyCode, expected) {
editor.setContent(html);
editor.focus();
setSelection(nodeToSelect, 0);
editor.focus();
robot.type(keyCode, false, function() {
var node = editor.selection.getNode();
var actual = node.firstChild.nodeValue;
equal(actual, expected);
start();
}, editor.getBody());
}
asyncTest('space key does not nuke content in th cells', 1, function() {
editor.setContent('<table><tbody><tr><th id="a">abcdef</th></tr></tbody></table>');
editor.focus();
setSelection('#a', 3);
editor.focus();
robot.type(VK.SPACEBAR, false, function() {
var actual = editor.dom.get('a').innerHTML;
var expected = 'abc def';
equal(actual, expected);
start()
}, editor.getBody());
});
asyncTest('arrow up key moves to row above', function() {
var html = '<table><tr><td>0</td><td>1</td></tr><tr><td>0</td><td id="b">2</td></tr></table>';
testCursorKey(html, '#b', UP_ARROW, '1');
});
asyncTest('arrow up key moves to row above for heading cells', function() {
var html = '<table><tr><td>0</td><td>1</td></tr><tr><td>0</td><th id="b">2</th></tr></table>';
testCursorKey(html, '#b', UP_ARROW, '1');
});
asyncTest('arrow down key moves to row below', function() {
var html = '<table><tr><td id="a"></td></tr><tr><td>2</td></tr></table>';
testCursorKey(html, '#a', DOWN_ARROW, '2');
});
asyncTest('arrow up key in cell with colspan moves to row above', function() {
var html = '<table><tr><td>1</td><td></td></tr><tr><td id="b" colspan="2"></td></tr></table>';
testCursorKey(html, '#b', UP_ARROW, '1');
});
asyncTest('arrow down key in cell with colspan moves to row below', function() {
var html = '<table><tr><td id="a" colspan="2"></td></tr><tr><td>2</td><td></td></tr></table>';
testCursorKey(html, '#a', DOWN_ARROW, '2');
});
asyncTest('arrow key up in top row escapes table', function() {
var html = '<p>outside</p><table><tr><td id="a"></td></tr><tr><td></td></tr></table>';
testCursorKey(html, '#a', UP_ARROW, 'outside');
});
asyncTest('arrow key down in bottom row escapes table', function() {
var html = '<table><tr><td></td></tr><tr><td id="b"></td></tr></table><p>outside</p>';
testCursorKey(html, '#b', DOWN_ARROW, 'outside');
});
asyncTest('arrow key up in bottom row to last p in above tr', 1, function() {
var html = "<table><tr><td><p id='a'>a</p><p id='b'>b</p></td></tr><tr><td><p id='c'>c</p><p>d</p></td></tr></table>";
testCursorKey(html, '#c', UP_ARROW, 'b');
});
asyncTest('arrow key down in top row to first p in below tr', 1, function() {
var html = "<table><tr><td><p id='a'>a</p><p id='b'>b</p></td></tr><tr><td><p id='c'>c</p><p>d</p></td></tr></table>";
testCursorKey(html, '#b', DOWN_ARROW, 'c');
});
asyncTest('arrow key down into table cell with br', 1, function() {
var html = "<table><tr><td id='a'></td></tr><tr><td>something<br></td></tr></table>";
testCursorKey(html, '#a', DOWN_ARROW, 'something');
});
asyncTest('shift-enter in table cell ending with BR places caret on new line', function() {
editor.setContent('<table><tr><td>d <strong>e</strong><br></td></tr></table>');
setSelection('strong', 1);
robot.type(ENTER, true, function(){
var expected = '<table><tbody><tr><td>d <strong>e<br /></strong></td></tr></tbody></table>';
var actual = editor.getContent();
var range = editor.selection.getRng(true);
equal(cleanHtml(actual), expected);
equal(range.startContainer.nodeName, 'STRONG');
equal(range.startOffset, 2);
equal(range.collapsed, true);
start();
}, editor.getBody());
});
// Only run on Gecko since WebKit and IE can place a caret after a table
if (tinymce.Env.gecko) {
test("Insert table and remove caret placeholder", function() {
editor.setContent('<table><tbody><tr><td>x</td></tr></tbody></table>');
equal(editor.getBody().firstChild.nodeName, "TABLE");
equal(editor.getBody().lastChild.nodeName, "P");
equal(editor.getContent(), '<table><tbody><tr><td>x</td></tr></tbody></table>');
});
} else {
test("Skipped since it works in this browser", function() {
ok(true, "Dummy assert");
});
}
var initTinyFunction = function(){
tinymce.init({
mode : "exact",
elements : "elm1",
cleanup: true,
indent: false,
add_unload_trigger : false,
webkit_fake_resize: false,
plugins: "table",
init_instance_callback : function(ed) {
editor = ed;
VK = tinymce.util.VK;
}
});
};
</script>
</head>
<body>
<h1 id="qunit-header">Table plugin tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
<script>
initWhenTinyAndRobotAreReady(initTinyFunction);
</script>
</body>
</html>

View File

@ -0,0 +1,24 @@
{
"title": "Plugins tests",
"tests": [
{"title": "Media", "url": "media.html"},
{"title": "Noneditable", "url": "noneditable.html"},
{"title": "Paste", "url": "paste.html"},
{"title": "Table", "url": "table.html"},
{"title": "Table (robot)", "url": "table_robot.html", "jsrobot": true},
{"title": "jQuery", "url": "jquery_plugin.html"},
{"title": "Autolink (robot)", "url": "autolink.html", "jsrobot": true},
{"title": "Autosave", "url": "autosave.html"},
{"title": "Wordcount", "url": "wordcount.html"},
{"title": "Fullpage", "url": "fullpage.html"},
{"title": "Legacyoutput", "url": "legacyoutput.html"},
{"title": "Plugin Dependencies", "url": "plugin_dependency_simple.html"},
{"title": "Plugin Dependency Chain", "url": "plugin_dependency_chain.html"},
{"title": "Plugin Dependency Chain Legacy", "url": "plugin_dependency_chain_legacy.html"},
{"title": "Dependency Chain Init Call Order", "url": "plugin_dependency_init_call_order.html"},
{"title": "Dependency With Specific Location", "url": "plugin_dependency_specific_location.html"},
{"title": "Lists", "url": "lists.html"},
{"title": "Searchreplace", "url": "searchreplace.html"},
{"title": "Spellchecker", "url": "spellchecker.html"}
]
}

View File

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for the Wordcount plugin</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.plugins.Wordcount", {
autostart: false
});
test("Blank document has 0 words", function() {
expect(1);
editor.setContent('');
var result = editor.plugins.wordcount.getCount();
equal(result, 0);
});
test("Simple word count", function() {
expect(1);
editor.setContent('<p>My sentence is this.</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 4);
});
test("Does not count dashes", function() {
expect(1);
editor.setContent('<p>Something -- ok</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 2);
});
test("Does not count asterisks, non-word characters", function() {
expect(1);
editor.setContent('<p>* something\n· something else</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 3);
});
test("Does not count htmlentities", function() {
expect(1);
editor.setContent('<p>It&rsquo;s my life &ndash; don\'t you forget.</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 6);
});
test("Counts hyphenated words as one word", function() {
expect(1);
editor.setContent('<p>Hello some-word here.</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 3);
});
test("Counts words between blocks as two words", function() {
expect(1);
editor.setContent('<p>Hello</p><p>world</p>');
var result = editor.plugins.wordcount.getCount();
equal(result, 2);
});
/*
The blocking functionality in the wordcount plugin prevents this code from
being tested correctly.
I'm of the opinion that the blocking code isn't really doing
anything crucial, and should be ripped out, so this module can be tested.
---------
test("should set the word count in the target html element", function() {
expect(1);
editor.setContent('<p>Hey, it\'s me!</p>');
equal(parseInt(document.getElementById('elm1-word-count').innerHTML), 3);
});
*/
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
wordcount_target_id: 'current-count',
plugins : 'wordcount',
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
<h1 id="qunit-header">Unit tests for the Wordcount plugin</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="word-count">
Current Count: <span id="current-count"></span>
</div>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

BIN
tests/qunit/editor/test.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@ -0,0 +1,221 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.Editor</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.Editor", {
autostart: false
});
test('Event: change', function() {
var level, lastLevel;
editor.on('change', function(e) {
level = e.level;
lastLevel = e.lastLevel;
});
editor.setContent('');
editor.insertContent('a');
equal(level.content.toLowerCase(), '<p>a</p>');
equal(lastLevel.content, editor.undoManager.data[0].content);
editor.off('change');
});
test('Event: beforeExecCommand', function() {
var level, lastLevel, cmd, ui, value;
editor.on('BeforeExecCommand', function(e) {
cmd = e.command;
ui = e.ui;
value = e.value;
e.preventDefault();
});
editor.setContent('');
editor.insertContent('a');
equal(editor.getContent(), '');
equal(cmd, 'mceInsertContent');
equal(ui, false);
equal(value, 'a');
editor.off('BeforeExecCommand');
editor.setContent('');
editor.insertContent('a');
equal(editor.getContent(), '<p>a</p>');
});
test('urls - relativeURLs', function() {
editor.settings.relative_urls = true;
editor.documentBaseURI = new tinymce.util.URI('http://www.site.com/dirA/dirB/dirC/');
editor.setContent('<a href="test.html">test</a>');
equal(editor.getContent(), '<p><a href="test.html">test</a></p>');
editor.setContent('<a href="../test.html">test</a>');
equal(editor.getContent(), '<p><a href="../test.html">test</a></p>');
editor.setContent('<a href="test/test.html">test</a>');
equal(editor.getContent(), '<p><a href="test/test.html">test</a></p>');
editor.setContent('<a href="/test.html">test</a>');
equal(editor.getContent(), '<p><a href="../../../test.html">test</a></p>');
editor.setContent('<a href="http://www.somesite.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="http://www.somesite.com/test/file.htm">test</a></p>');
editor.setContent('<a href="//www.site.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="../../../test/file.htm">test</a></p>');
editor.setContent('<a href="//www.somesite.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="//www.somesite.com/test/file.htm">test</a></p>');
});
test('urls - absoluteURLs', function() {
editor.settings.relative_urls = false;
editor.settings.remove_script_host = true;
editor.documentBaseURI = new tinymce.util.URI('http://www.site.com/dirA/dirB/dirC/');
editor.setContent('<a href="test.html">test</a>');
equal(editor.getContent(), '<p><a href="/dirA/dirB/dirC/test.html">test</a></p>');
editor.setContent('<a href="../test.html">test</a>');
equal(editor.getContent(), '<p><a href="/dirA/dirB/test.html">test</a></p>');
editor.setContent('<a href="test/test.html">test</a>');
equal(editor.getContent(), '<p><a href="/dirA/dirB/dirC/test/test.html">test</a></p>');
editor.setContent('<a href="http://www.somesite.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="http://www.somesite.com/test/file.htm">test</a></p>');
editor.settings.relative_urls = false;
editor.settings.remove_script_host = false;
editor.setContent('<a href="test.html">test</a>');
equal(editor.getContent(), '<p><a href="http://www.site.com/dirA/dirB/dirC/test.html">test</a></p>');
editor.setContent('<a href="../test.html">test</a>');
equal(editor.getContent(), '<p><a href="http://www.site.com/dirA/dirB/test.html">test</a></p>');
editor.setContent('<a href="test/test.html">test</a>');
equal(editor.getContent(), '<p><a href="http://www.site.com/dirA/dirB/dirC/test/test.html">test</a></p>');
editor.setContent('<a href="http://www.somesite.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="http://www.somesite.com/test/file.htm">test</a></p>');
editor.setContent('<a href="//www.site.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="//www.site.com/test/file.htm">test</a></p>');
editor.setContent('<a href="//www.somesite.com/test/file.htm">test</a>');
equal(editor.getContent(), '<p><a href="//www.somesite.com/test/file.htm">test</a></p>');
});
test('WebKit Serialization range bug', function() {
expect(1);
if (tinymce.isIE) {
ok(true, "Skip IE");
} else {
// Note that if we create the P with this invalid content directly, Chrome cleans it up differently to other browsers so we don't
// wind up testing the serialization functionality we were aiming for and the test fails.
var p = editor.dom.create('p', {}, '123<table><tbody><tr><td>X</td></tr></tbody></table>456');
editor.dom.replace(p, editor.getBody().firstChild);
equal(editor.getContent(), '<p>123</p>\n<table>\n<tbody>\n<tr>\n<td>X</td>\n</tr>\n</tbody>\n</table>\n<p>456</p>');
}
});
test('editor_methods - getParam', function() {
expect(5);
editor.settings.test = 'a,b,c';
equal(editor.getParam('test', '', 'hash')['c'], 'c');
editor.settings.test = 'a';
equal(editor.getParam('test', '', 'hash')['a'], 'a');
editor.settings.test = 'a=b';
equal(editor.getParam('test', '', 'hash')['a'], 'b');
editor.settings.test = 'a=b;c=d,e';
equal(editor.getParam('test', '', 'hash')['c'], 'd,e');
editor.settings.test = 'a=b,c=d';
equal(editor.getParam('test', '', 'hash')['c'], 'd');
});
test('setContent', function() {
var count;
expect(4);
function callback(e) {
e.content = e.content.replace(/test/, 'X');
count++;
};
editor.on('SetContent', callback);
editor.on('BeforeSetContent', callback);
count = 0;
editor.setContent('<p>test</p>');
equal(editor.getContent(), "<p>X</p>");
equal(count, 2);
editor.off('SetContent', callback);
editor.off('BeforeSetContent', callback);
count = 0;
editor.setContent('<p>test</p>');
equal(editor.getContent(), "<p>test</p>");
equal(count, 0);
});
test('custom elements', function() {
expect(1);
editor.setContent('<custom1>c1</custom1><custom2>c1</custom2>');
equal(editor.getContent().replace(/[\r\n]/g, ''), '<custom1>c1</custom1><p><custom2>c1</custom2></p>');
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
custom_elements: 'custom1,~custom2',
extended_valid_elements: 'custom1,custom2',
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for tinymce.Editor</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,765 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.EditorCommands</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.EditorCommands", {
autostart: false
});
function getContent() {
return editor.getContent({format:'raw'}).toLowerCase().replace(/[\r\n]+/g, '');
};
test('mceInsertContent - p inside text of p', function() {
var rng;
expect(7);
editor.setContent('<p>1234</p>');
editor.focus();
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 1);
rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<p>abc</p>');
equal(getContent(), '<p>1</p><p>abc</p><p>4</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - p inside whole p', function() {
var rng;
expect(7);
editor.setContent('<p>1234</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<p>abc</p>');
equal(getContent(), '<p>abc</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - pre in text of pre', function() {
var rng;
expect(7);
editor.setContent('<pre>1234</pre>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('pre')[0].firstChild, 1);
rng.setEnd(editor.dom.select('pre')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<pre>abc</pre>');
equal(getContent(), '<pre>1</pre><pre>abc</pre><pre>4</pre>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'PRE');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'PRE');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - h1 in text of h1', function() {
var rng;
expect(7);
editor.setContent('<h1>1234</h1>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('h1')[0].firstChild, 1);
rng.setEnd(editor.dom.select('h1')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<h1>abc</h1>');
equal(getContent(), '<h1>1</h1><h1>abc</h1><h1>4</h1>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'H1');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'H1');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - li inside li', function() {
var rng;
expect(7);
editor.setContent('<ul><li>1234</li></ul>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('li')[0].firstChild, 1);
rng.setEnd(editor.dom.select('li')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<li>abc</li>');
equal(getContent(), '<ul><li>1</li><li>abc</li><li>4</li></ul>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'LI');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'LI');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - p inside empty editor', function() {
var rng;
expect(7);
editor.setContent('');
editor.execCommand('mceInsertContent', false, '<p>abc</p>');
equal(getContent(), '<p>abc</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - text inside empty p', function() {
var rng;
expect(7);
editor.getBody().innerHTML = '<p></p>';
setSelection('p', 0);
editor.execCommand('mceInsertContent', false, 'abc');
equal(editor.getBody().innerHTML.toLowerCase().replace(/^<br>/, ''), '<p>abc</p>'); // Opera inserts a BR at the beginning of contents if the P is empty
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - text inside empty p with br caret node', function() {
var rng;
expect(7);
editor.getBody().innerHTML = '<p><br></p>';
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 0);
rng.setEnd(editor.getBody().firstChild, 0);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, 'abc');
equal(editor.getBody().innerHTML.toLowerCase(), '<p>abc</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
equal(rng.startContainer.innerHTML, 'abc');
});
test('mceInsertContent - image inside p', function() {
var rng;
expect(6);
editor.setContent('<p>1</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 1);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<img src="about:blank" />');
equal(editor.getContent(), '<p><img src="about:blank" alt="" /></p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 1);
});
test('mceInsertContent - legacy content', function() {
var rng;
expect(1);
// Convert legacy content
editor.setContent('<p>1</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 1);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<u>u</u><strike>strike</strike><font size="7">font</font>');
equal(editor.getContent(), '<p><span style="text-decoration: underline;">u</span><span style="text-decoration: line-through;">strike</span><span style="font-size: 300%;">font</span></p>');
});
test('mceInsertContent - hr', function() {
var rng;
expect(7);
editor.setContent('<p>123</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 1);
rng.setEnd(editor.dom.select('p')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, '<hr />');
equal(editor.getContent(), '<p>1</p><hr /><p>3</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer, editor.getBody().lastChild);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 0);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 0);
});
test('mceInsertContent - forced root block', function() {
var rng;
expect(1);
// Forced root block
editor.getBody().innerHTML = '';
editor.execCommand('mceInsertContent', false, 'test<b>123</b><!-- a -->');
// Opera adds an extra paragraph since it adds a BR at the end of the contents pass though this for now since it's an minority browser
equal(editor.getContent().replace(/<p>\u00a0<\/p>/g, ''), '<p>test<strong>123</strong></p><!-- a -->');
});
test('mceInsertContent - mixed inline content inside td', function() {
var rng;
expect(1);
// Forced root block
editor.getBody().innerHTML = '<table><tr><td>X</td></tr></table>';
setSelection('td', 0, 'td', 0);
editor.execCommand('mceInsertContent', false, 'test<b>123</b><!-- a -->');
equal(editor.getContent(), '<table><tbody><tr><td>test<strong>123</strong><!-- a -->X</td></tr></tbody></table>');
});
test('mceInsertContent - invalid insertion with spans on page', function(){
var startingContent = '<p>123 testing <em>span later in document</em></p>',
insertedContent = '<ul><li>u</li><li>l</li></ul>';
editor.setContent(startingContent);
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 0);
editor.selection.setRng(rng);
editor.execCommand('mceInsertContent', false, insertedContent);
equal(editor.getContent(), insertedContent + startingContent);
});
test('mceInsertContent - text with space before at start of block', function() {
editor.getBody().innerHTML = '<p>a</p>';
setSelection('p', 0);
editor.execCommand('mceInsertContent', false, ' b');
equal(editor.getContent(), '<p>\u00a0ba</p>');
});
test('mceInsertContent - text with space after at end of block', function() {
editor.getBody().innerHTML = '<p>a</p>';
setSelection('p', 1);
editor.execCommand('mceInsertContent', false, 'b ');
equal(editor.getContent(), '<p>ab\u00a0</p>');
});
test('mceInsertContent - text with space before/after at middle of block', function() {
editor.getBody().innerHTML = '<p>ac</p>';
setSelection('p', 1);
editor.execCommand('mceInsertContent', false, ' b ');
equal(editor.getContent(), '<p>a b c</p>');
});
test('mceInsertContent - inline element with space before/after at middle of block', function() {
editor.getBody().innerHTML = '<p>ac</p>';
setSelection('p', 1);
editor.execCommand('mceInsertContent', false, ' <em>b</em> ');
equal(editor.getContent(), '<p>a <em>b</em> c</p>');
});
test('mceInsertContent - block element with space before/after at middle of block', function() {
editor.getBody().innerHTML = '<p>ac</p>';
setSelection('p', 1);
editor.execCommand('mceInsertContent', false, ' <p>b</p> ');
equal(editor.getContent(), '<p>a</p><p>b</p><p>c</p>');
});
test('InsertHorizontalRule', function() {
var rng;
expect(7);
editor.setContent('<p>123</p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 1);
rng.setEnd(editor.dom.select('p')[0].firstChild, 2);
editor.selection.setRng(rng);
editor.execCommand('InsertHorizontalRule');
equal(editor.getContent(), '<p>1</p><hr /><p>3</p>');
rng = normalizeRng(editor.selection.getRng(true));
ok(rng.collapsed);
equal(rng.startContainer, editor.getBody().lastChild);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 0);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 0);
});
test('Justify - multiple block elements selected - queryCommandState', function() {
editor.setContent('<div style="text-align: left;"><div id="a" style="text-align: right;">one</div><div id="b" style="text-align: right;">two</div></div>');
setSelection('#a', 0, '#b', 3);
equal(editor.queryCommandState('JustifyLeft'), false);
ok(editor.queryCommandState('JustifyRight'));
});
test('Formatting commands (xhtmlTextStyles)', function() {
var c;
expect(19);
editor.focus();
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('Bold');
equal(editor.getContent(), "<p><strong>test 123</strong></p>");
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('Italic');
equal(editor.getContent(), "<p><em>test 123</em></p>");
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('Underline');
equal(editor.getContent(), '<p><span style="text-decoration: underline;">test 123</span></p>');
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('Strikethrough');
equal(editor.getContent(), '<p><span style="text-decoration: line-through;">test 123</span></p>');
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('FontName',false,'Arial');
equal(editor.getContent(), '<p><span style="font-family: ' + fontFace('Arial') + ';">test 123</span></p>');
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('FontSize',false,'7');
equal(editor.getContent(), '<p><span style="font-size: xx-large;">test 123</span></p>');
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('ForeColor', false, '#FF0000');
equal(editor.getContent(), '<p><span style="color: #ff0000;">test 123</span></p>');
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('HiliteColor', false, '#FF0000');
equal(editor.getContent(), '<p><span style="background-color: #ff0000;">test 123</span></p>');
editor.setContent('<p><span style="text-decoration: underline;">test 123</span></p>');
equal(editor.getContent(), '<p><span style="text-decoration: underline;">test 123</span></p>');
editor.setContent('<p><span style="text-decoration: line-through;">test 123</span></p>');
equal(editor.getContent(), '<p><span style="text-decoration: line-through;">test 123</span></p>');
editor.setContent('<p><span style="font-family: Arial;">test 123</span></p>');
equal(editor.getContent(), '<p><span style="font-family: Arial;">test 123</span></p>');
editor.setContent('<p><span style="font-size: xx-large;">test 123</span></p>');
equal(editor.getContent(), '<p><span style="font-size: xx-large;">test 123</span></p>');
editor.setContent('<p><u>test 123</u></p>');
equal(editor.getContent(), '<p><span style="text-decoration: underline;">test 123</span></p>');
editor.setContent('<p><strike>test 123</strike></p>');
equal(editor.getContent(), '<p><span style="text-decoration: line-through;">test 123</span></p>');
editor.setContent('<p><font face="Arial">test 123</font></p>');
equal(editor.getContent(), '<p><span style="font-family: ' + fontFace('Arial') + ';">test 123</span></p>');
editor.setContent('<p><font size="7">test 123</font></p>');
equal(editor.getContent(), '<p><span style="font-size: 300%;">test 123</span></p>');
editor.setContent('<p><font face="Arial" size="7">test 123</font></p>');
equal(editor.getContent(), '<p><span style="font-size: 300%; font-family: ' + fontFace('Arial') + ';">test 123</span></p>');
editor.setContent('<font style="background-color: #ff0000" color="#ff0000">test</font><font face="Arial">test</font>');
equal(editor.getContent(), '<p><span style="color: #ff0000; background-color: #ff0000;">test</span><span style="font-family: ' + fontFace('Arial') + ';">test</span></p>');
editor.setContent('<p><font face="Arial" style="color: #ff0000">test 123</font></p>');
equal(editor.getContent(), '<p><span style="color: #ff0000; font-family: ' + fontFace('Arial') + ';">test 123</span></p>');
});
test('Formatting commands (alignInline)', function() {
expect(7);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('JustifyLeft');
equal(editor.getContent(), '<p style="text-align: left;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('JustifyCenter');
equal(editor.getContent(), '<p style="text-align: center;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('JustifyRight');
equal(editor.getContent(), '<p style="text-align: right;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('JustifyFull');
equal(editor.getContent(), '<p style="text-align: justify;">test 123</p>');
editor.setContent('<img src="../media/logo.jpg" />');
editor.selection.select(editor.dom.select('img')[0]);
editor.execCommand('JustifyLeft');
equal(editor.getContent(), '<p><img style="float: left;" src="../media/logo.jpg" alt="" /></p>');
editor.setContent('<img src="../media/logo.jpg" />');
editor.selection.select(editor.dom.select('img')[0]);
editor.execCommand('JustifyCenter');
equal(editor.getContent(), '<p><img style="margin-right: auto; margin-left: auto; display: block;" src="../media/logo.jpg" alt="" /></p>');
editor.setContent('<img src="../media/logo.jpg" />');
editor.selection.select(editor.dom.select('img')[0]);
editor.execCommand('JustifyRight');
equal(editor.getContent(), '<p><img style="float: right;" src="../media/logo.jpg" alt="" /></p>');
});
test('mceBlockQuote', function() {
expect(2);
editor.focus();
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceBlockQuote');
equal(editor.getContent().replace(/\s+/g, ''), '<blockquote><p>test123</p></blockquote>');
editor.setContent('<p>test 123</p><p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceBlockQuote');
equal(editor.getContent().replace(/\s+/g, ''), '<blockquote><p>test123</p><p>test123</p></blockquote>');
});
test('FormatBlock', function() {
expect(9);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h1');
equal(editor.getContent(), '<h1>test 123</h1>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h2');
equal(editor.getContent(), '<h2>test 123</h2>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h3');
equal(editor.getContent(), '<h3>test 123</h3>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h4');
equal(editor.getContent(), '<h4>test 123</h4>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h5');
equal(editor.getContent(), '<h5>test 123</h5>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'h6');
equal(editor.getContent(), '<h6>test 123</h6>');
editor.execCommand('SelectAll');
try {
editor.execCommand('FormatBlock', false, 'div');
} catch (ex) {
//t.log('Failed: ' + ex.message);
}
equal(editor.getContent(), '<div>test 123</div>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'address');
equal(editor.getContent(), '<address>test 123</address>');
editor.execCommand('SelectAll');
editor.execCommand('FormatBlock', false, 'pre');
equal(editor.getContent(), '<pre>test 123</pre>');
});
test('mceInsertLink (relative)', function() {
expect(1);
editor.setContent('test 123');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'test');
equal(editor.getContent(), '<p><a href="test">test 123</a></p>');
});
test('mceInsertLink (link absolute)', function() {
expect(1);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'http://www.site.com');
equal(editor.getContent(), '<p><a href="http://www.site.com">test 123</a></p>');
});
test('mceInsertLink (link encoded)', function() {
expect(1);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, '"&<>');
equal(editor.getContent(), '<p><a href="&quot;&amp;&lt;&gt;">test 123</a></p>');
});
test('mceInsertLink (link encoded and with class)', function() {
expect(1);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, {href : '"&<>', 'class' : 'test'});
equal(editor.getContent(), '<p><a class="test" href="&quot;&amp;&lt;&gt;">test 123</a></p>');
});
test('mceInsertLink (link with space)', function() {
expect(1);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, {href : 'foo bar'});
equal(editor.getContent(), '<p><a href="foo%20bar">test 123</a></p>');
});
test('mceInsertLink (link floated img)', function() {
expect(1);
editor.setContent('<p><img style="float: right;" src="about:blank" /></p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link"><img style="float: right;" src="about:blank" alt="" /></a></p>');
});
test('mceInsertLink (link adjacent text)', function() {
var rng;
expect(1);
editor.setContent('<p><a href="#">a</a>b</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.lastChild, 0);
rng.setEnd(editor.getBody().firstChild.lastChild, 1);
editor.selection.setRng(rng);
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="#">a</a><a href="link">b</a></p>');
});
test('mceInsertLink (link text inside text)', function() {
var rng;
expect(1);
editor.setContent('<p><a href="#"><em>abc</em></a></p>');
setSelection('em', 1, 'em', 2);
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link"><em>abc</em></a></p>');
});
test('mceInsertLink (link around existing links)', function() {
var rng;
expect(1);
editor.setContent('<p><a href="#1">1</a><a href="#2">2</a></p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link">12</a></p>');
});
test('mceInsertLink (link around existing links with different attrs)', function() {
var rng;
expect(1);
editor.setContent('<p><a id="a" href="#1">1</a><a id="b" href="#2">2</a></p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link">12</a></p>');
});
test('mceInsertLink (link around existing complex contents with links)', function() {
var rng;
expect(1);
editor.setContent('<p><span id="s1"><strong><a id="a" href="#1"><em>1</em></a></strong></span><span id="s2"><em><a id="b" href="#2"><strong>2</strong></a></em></span></p>');
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link"><span id="s1"><strong><em>1</em></strong></span><span id="s2"><em><strong>2</strong></em></span></a></p>');
});
test('mceInsertLink (link text inside link)', function() {
var rng;
expect(1);
editor.setContent('<p><a href="#">test</a></p>');
setSelection('p', 0, 'p', 1);
editor.execCommand('SelectAll');
editor.execCommand('mceInsertLink', false, 'link');
equal(editor.getContent(), '<p><a href="link">test</a></p>');
});
test('unlink', function() {
expect(1);
editor.setContent('<p><a href="test">test</a> <a href="test">123</a></p>');
editor.execCommand('SelectAll');
editor.execCommand('unlink');
equal(editor.getContent(), '<p>test 123</p>');
});
test('subscript/superscript', function() {
expect(4);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('subscript');
equal(editor.getContent(), '<p><sub>test 123</sub></p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('superscript');
equal(editor.getContent(), '<p><sup>test 123</sup></p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('subscript');
editor.execCommand('subscript');
equal(editor.getContent(), '<p>test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('superscript');
editor.execCommand('superscript');
equal(editor.getContent(), '<p>test 123</p>');
});
test('indent/outdent', function() {
expect(4);
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('Indent');
equal(editor.getContent(), '<p style="padding-left: 30px;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('Indent');
editor.execCommand('Indent');
equal(editor.getContent(), '<p style="padding-left: 60px;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('Indent');
editor.execCommand('Indent');
editor.execCommand('Outdent');
equal(editor.getContent(), '<p style="padding-left: 30px;">test 123</p>');
editor.setContent('<p>test 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('Outdent');
equal(editor.getContent(), '<p>test 123</p>');
});
test('RemoveFormat', function() {
var t = this;
expect(3);
editor.setContent('<p><em>test</em> <strong>123</strong> <a href="123">123</a> 123</p>');
editor.execCommand('SelectAll');
editor.execCommand('RemoveFormat');
equal(editor.getContent(), '<p>test 123 <a href="123">123</a> 123</p>');
editor.setContent('<p><em><em>test</em> <strong>123</strong> <a href="123">123</a> 123</em></p>');
editor.execCommand('SelectAll');
editor.execCommand('RemoveFormat');
equal(editor.getContent(), '<p>test 123 <a href="123">123</a> 123</p>');
editor.setContent('<p><em>test<span id="x">test <strong>123</strong></span><a href="123">123</a> 123</em></p>');
editor.selection.select(editor.dom.get('x'));
editor.execCommand('RemoveFormat');
equal(editor.getContent(), '<p><em>test</em><span id="x">test 123</span><em><a href="123">123</a> 123</em></p>');
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
indent : false,
entities : 'raw',
convert_urls : false,
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,padding-left,text-align,display'
},
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for tinymce.EditorCommands</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.ForceBlocks</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.ForceBlocks", {
autostart: false,
setup: function() {
editor.settings.forced_root_block = 'p';
editor.settings.forced_root_block_attrs = null;
}
});
function pressArrowKey(evt) {
var dom = editor.dom, target = editor.selection.getNode();
evt = tinymce.extend({keyCode: 37}, evt);
dom.fire(target, 'keydown', evt);
dom.fire(target, 'keypress', evt);
dom.fire(target, 'keyup', evt);
}
test('Wrap single root text node in P', function() {
editor.getBody().innerHTML = 'abcd';
setSelection('body', 2);
pressArrowKey();
equal(cleanHtml(editor.getBody().innerHTML), '<p>abcd</p>');
equal(editor.selection.getNode().nodeName, 'P');
});
test('Wrap single root text node in P with attrs', function() {
editor.settings.forced_root_block_attrs = {"class": "class1"};
editor.getBody().innerHTML = 'abcd';
setSelection('body', 2);
pressArrowKey();
equal(editor.getContent(), '<p class="class1">abcd</p>');
equal(editor.selection.getNode().nodeName, 'P');
});
test('Wrap single root text node in P but not table sibling', function() {
editor.getBody().innerHTML = 'abcd<table><tr><td>x</td></tr></table>';
setSelection('body', 2);
pressArrowKey();
equal(cleanHtml(editor.getBody().innerHTML), '<p>abcd</p><table><tbody><tr><td>x</td></tr></tbody></table>');
equal(editor.selection.getNode().nodeName, 'P');
});
test('Wrap root em in P but not table sibling', function() {
editor.getBody().innerHTML = '<em>abcd</em><table><tr><td>x</td></tr></table>';
setSelection('em', 2);
pressArrowKey();
equal(cleanHtml(editor.getBody().innerHTML), '<p><em>abcd</em></p><table><tbody><tr><td>x</td></tr></tbody></table>');
equal(editor.selection.getNode().nodeName, 'EM');
});
test('Wrap single root text node in DIV', function() {
editor.settings.forced_root_block = 'div';
editor.getBody().innerHTML = 'abcd';
setSelection('body', 2);
pressArrowKey();
equal(cleanHtml(editor.getBody().innerHTML), '<div>abcd</div>');
equal(editor.selection.getNode().nodeName, 'DIV');
});
test('Remove empty root text nodes', function() {
var body = editor.getBody();
editor.settings.forced_root_block = 'div';
editor.getBody().innerHTML = 'abcd<div>abcd</div>';
setSelection('body', 2);
body.insertBefore(editor.getDoc().createTextNode(''), body.firstChild);
body.appendChild(editor.getDoc().createTextNode(''));
pressArrowKey();
equal(cleanHtml(body.innerHTML), '<div>abcd</div><div>abcd</div>');
equal(editor.selection.getNode().nodeName, 'DIV');
equal(body.childNodes.length, 2);
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
indent : false,
schema: 'html5',
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for tinymce.ForceBlocks</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for check formatting</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="../js/utils.js"></script>
<script>
var editor, inlineEditor, rng, format;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Check formatting", {
autostart: false
});
function getContent() {
return editor.getContent().toLowerCase().replace(/[\r\n]+/g, '');
};
test('Selected style element text', function() {
editor.formatter.register('bold', {inline : 'b'});
editor.getBody().innerHTML = '<p><b>1234</b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
rng.setEnd(editor.dom.select('b')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('bold'), 'Selected style element text');
});
test('Selected style element with css styles', function() {
editor.formatter.register('color', {inline : 'span', styles : {color : '#ff0000'}});
editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 0);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('color'), 'Selected style element with css styles');
});
test('Selected style element with attributes', function() {
editor.formatter.register('fontsize', {inline : 'font', attributes : {size : '7'}});
editor.getBody().innerHTML = '<p><font size="7">1234</font></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('font')[0].firstChild, 0);
rng.setEnd(editor.dom.select('font')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('fontsize'), 'Selected style element with attributes');
});
test('Selected style element text multiple formats', function() {
editor.formatter.register('multiple', [
{inline : 'b'},
{inline : 'strong'}
]);
editor.getBody().innerHTML = '<p><strong>1234</strong></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('strong')[0].firstChild, 0);
rng.setEnd(editor.dom.select('strong')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('multiple'), 'Selected style element text multiple formats');
});
test('Selected complex style element', function() {
editor.formatter.register('complex', {inline : 'span', styles : {fontWeight : 'bold'}});
editor.getBody().innerHTML = '<p><span style="color:#ff0000; font-weight:bold">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 0);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('complex'), 'Selected complex style element');
});
test('Selected non style element text', function() {
editor.formatter.register('bold', {inline : 'b'});
editor.getBody().innerHTML = '<p>1234</p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(!editor.formatter.match('bold'), 'Selected non style element text');
});
test('Selected partial style element (start)', function() {
editor.formatter.register('bold', {inline : 'b'});
editor.getBody().innerHTML = '<p><b>1234</b>5678</p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].lastChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('bold'), 'Selected partial style element (start)');
});
test('Selected partial style element (end)', function() {
editor.formatter.register('bold', {inline : 'b'});
editor.getBody().innerHTML = '<p>1234<b>5678</b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('b')[0].lastChild, 4);
editor.selection.setRng(rng);
ok(!editor.formatter.match('bold'), 'Selected partial style element (end)');
});
test('Selected element text with parent inline element', function() {
editor.formatter.register('bold', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em><span>1234</span></em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 0);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('bold'), 'Selected element text with parent inline element');
});
test('Selected element match with variable', function() {
editor.formatter.register('complex', {inline : 'span', styles : {color : '%color'}});
editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 0);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('complex', {color : '#ff0000'}), 'Selected element match with variable');
});
test('Selected element match with variable and function', function() {
editor.formatter.register('complex', {
inline : 'span',
styles : {
color : function(vars) {
return vars.color + '00';
}
}
});
editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 0);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
ok(editor.formatter.match('complex', {color : '#ff00'}), 'Selected element match with variable and function');
});
test('formatChanged simple format', function() {
var newState, newArgs;
editor.formatter.formatChanged('bold', function(state, args) {
newState = state;
newArgs = args;
});
editor.getBody().innerHTML = '<p>text</p>';
setSelection('p', 0, 'p', 4);
// Check apply
editor.formatter.apply('bold');
editor.nodeChanged();
ok(newState);
equal(newArgs.format, 'bold');
equal(newArgs.node, editor.getBody().firstChild.firstChild);
equal(newArgs.parents.length, 2);
// Check remove
editor.formatter.remove('bold');
editor.nodeChanged();
ok(!newState);
equal(newArgs.format, 'bold');
equal(newArgs.node, editor.getBody().firstChild);
equal(newArgs.parents.length, 1);
});
test('formatChanged complex format', function() {
var newState, newArgs;
editor.formatter.register('complex', {inline : 'span', styles : {color : '%color'}});
editor.formatter.formatChanged('complex', function(state, args) {
newState = state;
newArgs = args;
}, true);
editor.getBody().innerHTML = '<p>text</p>';
setSelection('p', 0, 'p', 4);
// Check apply
editor.formatter.apply('complex', {color: '#FF0000'});
editor.nodeChanged();
ok(newState);
equal(newArgs.format, 'complex');
equal(newArgs.node, editor.getBody().firstChild.firstChild);
equal(newArgs.parents.length, 2);
// Check remove
editor.formatter.remove('complex', {color: '#FF0000'});
editor.nodeChanged();
ok(!newState);
equal(newArgs.format, 'complex');
equal(newArgs.node, editor.getBody().firstChild);
equal(newArgs.parents.length, 1);
});
test('Match format on div block in inline mode', function() {
inlineEditor.setContent('<p>a</p><p>b</p>');
inlineEditor.execCommand('SelectAll');
ok(!inlineEditor.formatter.match('div'), 'Formatter.match on div says true');
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
theme_advanced_styles : 'test1=test1;test2=test2',
valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong,b,em,i,strike,u,#p,-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value|tabindex|accesskey],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
fix_list_elements : 0,
fix_table_elements : 0,
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
init_instance_callback : function(ed) {
editor = ed;
if (inlineEditor) {
QUnit.start();
}
}
});
var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
tinymce.init({
selector: "#elm2",
inline: true,
external_plugins: {
noneditable: url + 'external-plugins/noneditable/plugin.js'
},
add_unload_trigger: false,
indent: false,
theme_advanced_styles: 'test1=test1;test2=test2',
forced_root_block: '',
convert_fonts_to_spans: false,
disable_nodechange: true,
entities: 'raw',
valid_styles: {
'*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
init_instance_callback: function(ed) {
inlineEditor = ed;
if (editor) {
QUnit.start();
}
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for text formatting</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
<div id="elm2"></div>
</body>
</html>

View File

@ -0,0 +1,401 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for remove formatting</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor, rng, format;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Remove formatting", {
autostart: false
});
function getContent() {
return editor.getContent().toLowerCase().replace(/[\r]+/g, '');
};
test('Inline element on selected text', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b>1234</b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
rng.setEnd(editor.dom.select('b')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p>1234</p>', 'Inline element on selected text');
});
test('Inline element on selected text with remove=all', function() {
editor.formatter.register('format', {selector : 'b', remove : 'all'});
editor.getBody().innerHTML = '<p><b title="text">1234</b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
rng.setEnd(editor.dom.select('b')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p>1234</p>', 'Inline element on selected text with remove=all');
});
test('Inline element on selected text with remove=none', function() {
editor.formatter.register('format', {selector : 'span', styles : {fontWeight : 'bold'}, remove : 'none'});
editor.getBody().innerHTML = '<p><span style="font-weight:bold">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('p')[0], 1);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><span>1234</span></p>', 'Inline element on selected text with remove=none');
});
test('Inline element style where element is format root', function() {
editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
editor.getBody().innerHTML = '<p><span style="font-weight:bold; color:#FF0000"><em>1234</em></span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('em')[0].firstChild, 1);
rng.setEnd(editor.dom.select('em')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(),
'<p><span style="color: #ff0000; font-weight: bold;">' +
'<em>1</em></span><span style="color: #ff0000;"><em>23</em></span>' +
'<span style=\"color: #ff0000; font-weight: bold;\"><em>4' +
'</em></span></p>',
'Inline element style where element is format root');
});
test('Partially selected inline element text', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b>1234</b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 2);
rng.setEnd(editor.dom.select('b')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><b>12</b>34</p>', 'Partially selected inline element text');
});
test('Partially selected inline element text with children', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em><span>1234</span></em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[0].firstChild, 2);
rng.setEnd(editor.dom.select('span')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><b><em><span>12</span></em></b><em><span>34</span></em></p>', 'Partially selected inline element text with children');
});
test('Partially selected inline element text with complex children', function() {
editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
editor.getBody().innerHTML = '<p><span style="font-weight:bold"><em><span style="color:#ff0000;font-weight:bold">1234</span></em></span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('span')[1].firstChild, 2);
rng.setEnd(editor.dom.select('span')[1].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><span style="font-weight: bold;"><em><span style="color: #ff0000; font-weight: bold;">12</span></em></span><em><span style="color: #ff0000;">34</span></em></p>', 'Partially selected inline element text with complex children');
});
test('Inline elements with exact flag', function() {
editor.formatter.register('format', {inline : 'span', styles : {color : '#ff0000'}, exact : true});
editor.getBody().innerHTML = '<p><span style="font-size:10px;color:#ff0000">1234</span><span style="font-size:10px;color:#00ff00">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('p')[0], 2);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><span style="font-size: 10px;">1234</span><span style="color: #00ff00; font-size: 10px;">1234</span></p>', 'Inline elements with exact flag');
});
test('Inline elements with variables', function() {
editor.formatter.register('format', {inline : 'span', styles : {color : '%color'}, exact : true});
editor.getBody().innerHTML = '<p><span style="font-size:10px;color:#ff0000">1234</span><span style="font-size:10px;color:#00ff00">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('p')[0], 2);
editor.selection.setRng(rng);
editor.formatter.remove('format', {color : '#ff0000'});
equal(getContent(), '<p><span style="font-size: 10px;">1234</span><span style="color: #00ff00; font-size: 10px;">1234</span></p>', 'Inline elements on selected text with variables');
});
test('Inline elements with functions and variables', function() {
editor.formatter.register('format', {
inline : 'span',
styles : {
color : function(vars) {
return vars.color + "00";
}
},
exact : true
});
editor.getBody().innerHTML = '<p><span style="font-size:10px;color:#ff0000">1234</span><span style="font-size:10px;color:#00ff00">1234</span></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('p')[0], 2);
editor.selection.setRng(rng);
editor.formatter.remove('format', {
color : '#ff00'
});
equal(getContent(), '<p><span style="font-size: 10px;">1234</span><span style="color: #00ff00; font-size: 10px;">1234</span></p>', 'Inline elements with functions and variables');
});
test('End within start element', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b>1234<b>5678</b></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('b')[0], 2);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p>12345678</p>', 'End within start element');
});
test('Start and end within similar format 1', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em><b>1234<b>5678</b></b></em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('em')[0], 0);
rng.setEnd(editor.dom.select('b')[1], 2);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><em>12345678</em></p>', 'Start and end within similar format 1');
});
test('Start and end within similar format 2', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em><b>1234</b><b>5678</b></em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('em')[0], 0);
rng.setEnd(editor.dom.select('em')[0], 1);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><em>1234</em><b><em><b>5678</b></em></b></p>', 'Start and end within similar format 2');
});
test('Start and end within similar format 3', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em><b>1234</b></em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('em')[0], 0);
rng.setEnd(editor.dom.select('em')[0], 1);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><em>1234</em></p>', 'Start and end within similar format 3');
});
test('End within start', function() {
editor.formatter.register('format', {inline : 'b'});
editor.getBody().innerHTML = '<p><b><em>x<b>abc</b>y</em></b></p>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0], 0);
rng.setEnd(editor.dom.select('b')[1].firstChild, 3);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><em>x</em><em>abc</em><b><em>y</em></b></p>', 'End within start');
});
test('Remove block format', function() {
editor.formatter.register('format', {block : 'h1'});
editor.getBody().innerHTML = '<h1>text</h1>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
rng.setEnd(editor.dom.select('h1')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p>text</p>', 'Remove block format');
});
test('Remove wrapper block format', function() {
editor.formatter.register('format', {block : 'blockquote', wrapper : true});
editor.getBody().innerHTML = '<blockquote><p>text</p></blockquote>';
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p>text</p>', 'Remove wrapper block format');
});
test('Remove span format within block with style', function() {
editor.formatter.register('format', {selector : 'span', attributes : ['style', 'class'], remove : 'empty', split : true, expand : false, deep : true});
rng = editor.dom.createRng();
editor.getBody().innerHTML = '<p style="color:#ff0000"><span style="color:#00ff00">text</span></p>';
rng.setStart(editor.dom.select('span')[0].firstChild, 1);
rng.setEnd(editor.dom.select('span')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p style="color: #ff0000;"><span style="color: #00ff00;">t</span>ex<span style="color: #00ff00;">t</span></p>', 'Remove span format within block with style');
});
test('Remove and verify start element', function() {
editor.formatter.register('format', {inline : 'b'});
rng = editor.dom.createRng();
editor.getBody().innerHTML = '<p><b>text</b></p>';
rng.setStart(editor.dom.select('b')[0].firstChild, 1);
rng.setEnd(editor.dom.select('b')[0].firstChild, 3);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), '<p><b>t</b>ex<b>t</b></p>');
equal(editor.selection.getStart().nodeName, 'P');
});
test('Remove with selection collapsed ensure correct caret position', function() {
var content = '<p>test</p><p>testing</p>';
editor.formatter.register('format', {block : 'p'});
rng = editor.dom.createRng();
editor.getBody().innerHTML = content;
rng.setStart(editor.dom.select('p')[0].firstChild, 4);
rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(getContent(), content);
equal(editor.selection.getStart(), editor.dom.select('p')[0]);
});
test('Caret format at middle of text', function() {
editor.setContent('<p><b>abc</b></p>');
editor.formatter.register('format', {inline: 'b'});
setSelection('b', 1, 'b', 1);
editor.formatter.remove('format');
equal(editor.getContent(), '<p>abc</p>');
});
test('Caret format at end of text', function() {
editor.setContent('<p><b>abc</b></p>');
editor.formatter.register('format', {inline: 'b'});
setSelection('b', 3, 'b', 3);
editor.formatter.remove('format');
type('d');
equal(editor.getContent(), '<p><b>abc</b>d</p>');
});
test('Caret format at end of text inside other format', function() {
editor.setContent('<p><em><b>abc</b></em></p>');
editor.formatter.register('format', {inline: 'b'});
setSelection('b', 3, 'b', 3);
editor.formatter.remove('format');
type('d');
equal(editor.getContent(), '<p><em><b>abc</b>d</em></p>');
});
test('Caret format at end of text inside other format with text after 1', function() {
editor.setContent('<p><em><b>abc</b></em>e</p>');
editor.formatter.register('format', {inline: 'b'});
setSelection('b', 3, 'b', 3);
editor.formatter.remove('format');
type('d');
equal(editor.getContent(), '<p><em><b>abc</b>d</em>e</p>');
});
test('Caret format at end of text inside other format with text after 2', function() {
editor.setContent('<p><em><b>abc</b></em>e</p>');
editor.formatter.register('format', {inline: 'em'});
setSelection('b', 3, 'b', 3);
editor.formatter.remove('format');
type('d');
equal(editor.getContent(), '<p><em><b>abc</b></em><b>d</b>e</p>');
});
test('Caret format on second word in table cell', function() {
editor.setContent('<table><tbody><tr><td>one <b>two</b></td></tr></tbody></table>');
editor.formatter.register('format', {inline: 'b'});
setSelection('b', 2, 'b', 2);
editor.formatter.remove('format');
equal(editor.getContent(), '<table><tbody><tr><td>one two</td></tr></tbody></table>');
});
test('contentEditable: false on start and contentEditable: true on end', function() {
var rng;
editor.formatter.register('format', {inline: 'b'});
editor.setContent('<p>abc</p><p contenteditable="false"><b>def</b></p><p><b>ghj</b></p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('b')[0].firstChild, 0);
rng.setEnd(editor.dom.select('b')[1].firstChild, 3);
editor.selection.setRng(rng);
editor.formatter.remove('format');
equal(editor.getContent(), '<p>abc</p><p><b>def</b></p><p>ghj</p>', 'Text in last paragraph is not bold');
});
test('contentEditable: true on start and contentEditable: false on end', function() {
editor.formatter.register('format', {inline: 'b'});
editor.setContent('<p>abc</p><p><b>def</b></p><p contenteditable="false"><b>ghj</b></p>');
setSelection('p:nth-child(2) b', 0, 'p:last b', 3);
editor.formatter.remove('format');
equal(editor.getContent(), '<p>abc</p><p>def</p><p><b>ghj</b></p>', 'Text in first paragraph is not bold');
});
test('contentEditable: true inside contentEditable: false', function() {
editor.formatter.register('format', {inline: 'b'});
editor.setContent('<p>abc</p><p contenteditable="false"><span contenteditable="true"><b>def</b></span></p>');
setSelection('b', 0, 'b', 3);
editor.formatter.remove('format');
equal(editor.getContent(), '<p>abc</p><p><span>def</span></p>', 'Text is not bold');
});
test('remove format block on contentEditable: false block', function() {
editor.formatter.register('format', {block: 'h1'});
editor.setContent('<p>abc</p><h1 contenteditable="false">def</h1>');
setSelection('h1:nth-child(2)', 0, 'h1:nth-child(2)', 3);
editor.formatter.remove('format');
equal(editor.getContent(), '<p>abc</p><h1>def</h1>', 'H1 is still not h1');
});
/*
test('Remove format bug 1', function() {
editor.setContent('<p><b>ab<em>cde</em>fgh</b></p>');
editor.formatter.register('format', {inline: 'b'});
setSelection('em', 0, 'em', 2);
editor.formatter.remove('format');
equal(editor.getContent(), '<p><b>ab</b><em>cd</em><b><em>e</em>fgh</b></p>');
});
*/
var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
tinymce.init({
mode : "exact",
elements : "elm1",
external_plugins: {
noneditable: url + 'external-plugins/noneditable/plugin.js'
},
indent : false,
add_unload_trigger : false,
theme_advanced_styles : 'test1=test1;test2=test2',
valid_elements : '@[contenteditable|id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong,b,em,i,strike,u,#p,-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value|tabindex|accesskey],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
fix_list_elements : 0,
fix_table_elements : 0,
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
disable_nodechange: true,
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for text formatting</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>Basic editor functionality tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="../js/jsrobot/robot.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module('Formatting - Robot Tests', {
autostart: false
});
function checkExpectedAfterNewParagraph(expected) {
robot.type('\n', false, function() {
robot.type('g', false, function() {
var actual = editor.getContent();
var cleaned = actual.replace("<br />","");
equal(cleaned, expected);
start();
}, editor.getBody())
}, editor.getBody());
}
asyncTest('Should not be bold after turning off bold and going to a new paragraph', function() {
editor.setContent('<p><strong>text</strong></p>');
// in order for the robot to work well, we need to focus the editor before performing selection on it.
editor.focus();
setSelection("strong",4);
editor.execCommand("Bold");
var expected = '<p><strong>text</strong></p>\n<p>g</p>';
checkExpectedAfterNewParagraph(expected);
});
asyncTest('Format with nested formatting turned off handled correctly', function(){
editor.setContent('<p><strong>bold<em>italic<span style="text-decoration: underline;">under</span></em></strong></p>');
editor.focus();
setSelection("span",5);
editor.execCommand("Italic");
var expected ='<p><strong>bold<em>italic<span style="text-decoration: underline;">under</span></em></strong></p>\n<p><strong><span style="text-decoration: underline;">g</span></strong></p>';
checkExpectedAfterNewParagraph(expected);
});
asyncTest('Format selection over two lines', function(){
editor.setContent("<div id='a'>one</div><div id='b'>two</div>");
editor.focus();
setSelection('#a', 0, '#b', 0);
editor.execCommand('formatBlock', false, 'h1');
equal(editor.dom.select('#a')[0].tagName, 'H1');
equal(editor.dom.select('#b')[0].tagName, 'DIV');
start();
});
var initTinyFunction = function(){
tinymce.init({
mode : "exact",
elements : "elm1",
cleanup: true,
add_unload_trigger : false,
plugins: "table",
init_instance_callback : function(ed) {
editor = ed;
}
});
};
</script>
</head>
<body>
<h1 id="qunit-header">Plugin Dependency Functional tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</div>
<script>
initWhenTinyAndRobotAreReady(initTinyFunction);
</script>
</body>
</html>

View File

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.UndoManager tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.UndoManager", {
autostart: false
});
test('Initial states', function() {
expect(3);
ok(!editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('One undo level', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.focus();
editor.execCommand('SelectAll');
editor.execCommand('Bold');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('Two undo levels', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.execCommand('SelectAll');
editor.execCommand('Italic');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('No undo levels and one redo', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.undoManager.undo();
ok(!editor.undoManager.hasUndo());
ok(editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('One undo levels and one redo', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.execCommand('SelectAll');
editor.execCommand('Italic');
editor.undoManager.undo();
ok(editor.undoManager.hasUndo());
ok(editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('Typing state', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(2);
editor.dom.fire(editor.getBody(), 'keydown', {keyCode : 65});
ok(editor.undoManager.typing)
editor.dom.fire(editor.getBody(), 'keyup', {keyCode : 13});
ok(!editor.undoManager.typing)
});
test('Undo and add new level', function() {
editor.undoManager.clear();
editor.setContent('test');
expect(3);
editor.execCommand('SelectAll');
editor.execCommand('Bold');
editor.undoManager.undo();
editor.execCommand('SelectAll');
editor.execCommand('Italic');
ok(editor.undoManager.hasUndo());
ok(!editor.undoManager.hasRedo());
ok(!editor.undoManager.typing)
});
test('Events', function() {
var add, undo, redo;
editor.undoManager.clear();
editor.setContent('test');
expect(6);
editor.on('AddUndo', function(e) {
add = e.level;
});
editor.on('Undo', function(e) {
undo = e.level;
});
editor.on('Redo', function(e) {
redo = e.level;
});
editor.execCommand('SelectAll');
editor.execCommand('Bold');
ok(add.content);
ok(add.bookmark);
editor.undoManager.undo();
ok(undo.content);
ok(undo.bookmark);
editor.undoManager.redo();
ok(redo.content);
ok(redo.bookmark);
});
test('Undo added when typing and losing focus', function() {
editor.focus();
editor.undoManager.clear();
editor.setContent("<p>some text</p>");
setSelection('p', 4, 'p', 9);
type('\b');
window.focus();
editor.dom.fire(editor.getBody(), 'focusout');
editor.execCommand('FormatBlock', false, 'h1');
editor.undoManager.undo();
equal(editor.getContent(), "<p>some</p>");
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
theme_advanced_styles : 'test1=test1;test2=test2',
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.UndoManager tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"><textarea id="elm1" name="elm1"></textarea></div>
</body>
</html>

View File

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<title>Undo Tests</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../js/qunit/reporter.js"></script>
<script src="../js/utils.js"></script>
<script src="../js/tinymce_loader.js"></script>
<script src="../js/jsrobot/robot.js"></script>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
var BACKSPACE = 0x8;
module('Undo', {
autostart: false
});
function isUndoEnabled() {
return editor.undoManager.hasUndo();
}
// The following code never made it into the main codebase -- but it might be useful one day.
// If you're seeing this in August 2011 or later, please delete.
// in webkit the iframe window needs to be given focus before selection
// will behave correctly. This code assigns focus to the tinymce window, giving it back to the
// main window if it started with it.
// if (tinymce.isWebKit) {
// var hadFocus = document.hasFocus();
// t.getWin().focus();
// if (hadFocus) {
// window.focus();
// }
// }
function assertUndoEnabledWhenTyping(c, expectedContent) {
editor.setContent('<p>Content</p>');
editor.undoManager.clear();
editor.undoManager.add();
editor.execCommand('mceRepaint');
// Need to focus the editor before setting selection in order to get the editor typing working correctly.
// All evidence points to the normal APIs not needing an editor.focus() call
editor.focus();
setSelection('p', 4);
ok(!isUndoEnabled(), 'Undo starts disabled.');
robot.type(c, false, function() {
equal(editor.getContent(), expectedContent);
ok(isUndoEnabled(), 'Undo is enabled.');
QUnit.start();
}, editor.selection.getNode());
}
asyncTest('Undo added when typing character', function() {
assertUndoEnabledWhenTyping('b', '<p>Contbent</p>');
});
asyncTest('Undo added when typing enter', function() {
assertUndoEnabledWhenTyping('\n', '<p>Cont</p><p>ent</p>');
});
asyncTest('Forward delete triggers undo in IE', function() {
editor.setContent('<p>Test1 Test2</p>');
editor.undoManager.clear();
editor.execCommand('mceRepaint');
ok(!isUndoEnabled(), 'Undo is disabled.');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('p')[0].firstChild, 0);
rng.setEnd(editor.dom.select('p')[0].firstChild, 6);
editor.selection.setRng(rng);
robot.forwardDelete(function() {
equal(editor.getContent(), '<p>Test2</p>', 'First word has been deleted');
ok(isUndoEnabled(), 'Undo is enabled.');
editor.undoManager.undo();
equal(editor.getContent(), '<p>Test1 Test2</p>', 'First word has been restored');
QUnit.start();
}, editor.selection.getNode());
});
var initTinyFunction = function(){
tinymce.init({
mode : "exact",
elements : "elm1",
cleanup: true,
add_unload_trigger : false,
indent : 0,
init_instance_callback : function(ed) {
editor = ed;
}
});
}
</script>
</head>
<body>
<h1 id="qunit-header">Undo Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1">Content
</textarea>
</div>
<script>
initWhenTinyAndRobotAreReady(initTinyFunction);
</script>
</body>
</html>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.dom.DOMUtils</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
</head>
<body>
<script>
QUnit.config.reorder = false;
module("tinymce.dom.DOMUtils", {
});
</script>
<script src="DOMUtils.js"></script>
<h1 id="qunit-header">Unit tests for tinymce.dom.DOMUtils</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,680 @@
(function() {
var DOM = new tinymce.dom.DOMUtils(document, {keep_values : true, schema : new tinymce.html.Schema()});
test('parseStyle', 11, function() {
var dom;
DOM.add(document.body, 'div', {id : 'test'});
dom = new tinymce.dom.DOMUtils(document, {hex_colors : true, keep_values : true, url_converter : function(u, n, e) {
return 'X' + u + 'Y';
}});
equal(
dom.serializeStyle(dom.parseStyle('border: 1px solid red; color: green')),
'border: 1px solid red; color: green;'
);
equal(
dom.serializeStyle(dom.parseStyle('border: 1px solid rgb(0, 255, 255); color: green')),
'border: 1px solid #00ffff; color: green;'
);
equal(
dom.serializeStyle(dom.parseStyle('border-top: 1px solid red; border-left: 1px solid red; border-bottom: 1px solid red; border-right: 1px solid red;')),
'border: 1px solid red;'
);
equal(
dom.serializeStyle(dom.parseStyle('border-width: 1pt 1pt 1pt 1pt; border-style: none none none none; border-color: black black black black;')),
'border: 1pt none black;'
);
equal(
dom.serializeStyle(dom.parseStyle('border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;')),
'border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;'
);
equal(
dom.serializeStyle(dom.parseStyle('background: transparent url(test.gif);')),
'background: transparent url(\'Xtest.gifY\');'
);
equal(
dom.serializeStyle(dom.parseStyle('background: transparent url(http://www.site.com/test.gif?a=1&b=2);')),
'background: transparent url(\'Xhttp://www.site.com/test.gif?a=1&b=2Y\');'
);
dom.setHTML('test', '<span id="test2" style=" margin-left: 1px; margin-top: 1px; margin-right: 1px; margin-bottom: 1px "></span>');
equal(dom.getAttrib('test2', 'style'), 'margin: 1px;');
dom.setHTML('test', '<span id="test2" style="background-image: url(test.gif);"></span>');
equal(dom.getAttrib('test2', 'style'), 'background-image: url(\'Xtest.gifY\');');
dom.get('test').innerHTML = '<span id="test2" style="border: 1px solid #00ff00"></span>';
equal(dom.getAttrib('test2', 'style'), tinymce.isIE && !window.getSelection ? 'border: #00ff00 1px solid;' : 'border: 1px solid #00ff00;'); // IE has a separate output
dom.get('test').innerHTML = '<span id="test2" style="background-image: url(http://www.site.com/test.gif);"></span>';
equal(dom.getAttrib('test2', 'style'), 'background-image: url(\'Xhttp://www.site.com/test.gifY\');');
DOM.remove('test');
});
test('addClass', 10, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').className = '';
DOM.addClass('test', 'abc');
equal(DOM.get('test').className, 'abc');
DOM.get('test').className = '';
equal(DOM.addClass('test', 'abc'), 'abc');
equal(DOM.addClass(null, 'abc'), false);
DOM.addClass('test', '123');
equal(DOM.get('test').className, 'abc 123');
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.addClass(DOM.select('span', 'test'), 'abc');
equal(DOM.get('test2').className, 'abc');
equal(DOM.get('test3').className, 'abc');
equal(DOM.get('test4').className, 'abc');
DOM.get('test').innerHTML = '';
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.addClass(['test2', 'test3', 'test4'], 'abc');
equal(DOM.get('test2').className, 'abc');
equal(DOM.get('test3').className, 'abc');
equal(DOM.get('test4').className, 'abc');
DOM.get('test').innerHTML = '';
DOM.remove('test');
});
test('removeClass', 4, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').className = 'abc 123 xyz';
DOM.removeClass('test', '123');
equal(DOM.get('test').className, 'abc xyz');
DOM.get('test').innerHTML = '<span id="test2" class="test1"></span><span id="test3" class="test test1 test"></span><span id="test4" class="test1 test"></span>';
DOM.removeClass(DOM.select('span', 'test'), 'test1');
equal(DOM.get('test2').className, '');
equal(DOM.get('test3').className, 'test test');
equal(DOM.get('test4').className, 'test');
DOM.get('test').innerHTML = '';
DOM.remove('test');
});
test('hasClass', 7, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').className = 'abc 123 xyz';
ok(DOM.hasClass('test', 'abc'));
ok(DOM.hasClass('test', '123'));
ok(DOM.hasClass('test', 'xyz'));
ok(!DOM.hasClass('test', 'aaa'));
DOM.get('test').className = 'abc';
ok(DOM.hasClass('test', 'abc'));
DOM.get('test').className = 'aaa abc';
ok(DOM.hasClass('test', 'abc'));
DOM.get('test').className = 'abc aaa';
ok(DOM.hasClass('test', 'abc'));
DOM.remove('test');
});
test('add', 5, function() {
var e;
DOM.add(document.body, 'div', {id : 'test'});
DOM.add('test', 'span', {'class' : 'abc 123'}, 'content <b>abc</b>');
e = DOM.get('test').getElementsByTagName('span')[0];
equal(e.className, 'abc 123');
equal(e.innerHTML.toLowerCase(), 'content <b>abc</b>');
DOM.remove(e);
DOM.add('test', 'span', {'class' : 'abc 123'});
e = DOM.get('test').getElementsByTagName('span')[0];
equal(e.className, 'abc 123');
DOM.remove(e);
DOM.add('test', 'span');
e = DOM.get('test').getElementsByTagName('span')[0];
equal(e.nodeName, 'SPAN');
DOM.remove(e);
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.add(['test2', 'test3', 'test4'], 'span', {'class' : 'abc 123'});
equal(DOM.select('span', 'test').length, 6);
DOM.remove('test');
});
test('create', 3, function() {
var e;
e = DOM.create('span', {'class' : 'abc 123'}, 'content <b>abc</b>');
equal(e.nodeName, 'SPAN');
equal(e.className, 'abc 123');
equal(e.innerHTML.toLowerCase(), 'content <b>abc</b>');
});
test('createHTML', 4, function() {
equal(DOM.createHTML('span', {'id' : 'id1', 'class' : 'abc 123'}, 'content <b>abc</b>'), '<span id="id1" class="abc 123">content <b>abc</b></span>');
equal(DOM.createHTML('span', {'id' : 'id1', 'class' : 'abc 123'}), '<span id="id1" class="abc 123" />');
equal(DOM.createHTML('span'), '<span />');
equal(DOM.createHTML('span', null, 'content <b>abc</b>'), '<span>content <b>abc</b></span>');
});
test('uniqueId', 3, function() {
DOM.counter = 0;
equal(DOM.uniqueId(), 'mce_0');
equal(DOM.uniqueId(), 'mce_1');
equal(DOM.uniqueId(), 'mce_2');
});
test('showHide', 10, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.show('test');
equal(DOM.get('test').style.display, 'block');
ok(!DOM.isHidden('test'));
DOM.hide('test');
equal(DOM.get('test').style.display, 'none');
ok(DOM.isHidden('test'));
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.hide(['test2', 'test3', 'test4'], 'test');
equal(DOM.get('test2').style.display, 'none');
equal(DOM.get('test3').style.display, 'none');
equal(DOM.get('test4').style.display, 'none');
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.show(['test2', 'test3', 'test4'], 'test');
equal(DOM.get('test2').style.display, 'block');
equal(DOM.get('test3').style.display, 'block');
equal(DOM.get('test4').style.display, 'block');
// Cleanup
DOM.setAttrib('test', 'style', '');
DOM.remove('test');
});
test('select', 4, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<div>test 1</div><div>test 2 <div>test 3</div></div><div>test 4</div>');
equal(DOM.select('div', 'test').length, 4);
ok(DOM.select('div', 'test').reverse);
DOM.setHTML('test', '<div class="test1 test2 test3">test 1</div><div class="test2">test 2 <div>test 3</div></div><div>test 4</div>')
equal(DOM.select('div.test2', 'test').length, 2);
DOM.setHTML('test', '<div class="test1 test2 test3">test 1</div><div class="test2">test 2 <div>test 3</div></div><div>test 4</div>')
equal(DOM.select('div div', 'test').length, 1, null, tinymce.isWebKit); // Issue: http://bugs.webkit.org/show_bug.cgi?id=17461
//alert(DOM.select('div div', 'test').length +","+DOM.get('test').querySelectorAll('div div').length);
DOM.remove('test');
});
test('is', 3, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<div id="textX" class="test">test 1</div>');
ok(DOM.is(DOM.get('textX'), 'div'));
ok(DOM.is(DOM.get('textX'), 'div#textX.test'));
ok(!DOM.is(DOM.get('textX'), 'div#textX2'));
DOM.remove('test');
});
test('encode', 1, function() {
equal(DOM.encode('abc<>"&\'\u00e5\u00e4\u00f6'), 'abc&lt;&gt;&quot;&amp;&#39;\u00e5\u00e4\u00f6');
});
test('setGetAttrib', 16, function() {
var dom;
DOM.add(document.body, 'div', {id : 'test'});
DOM.setAttrib('test', 'class', 'test 123');
equal(DOM.getAttrib('test', 'class'), 'test 123');
DOM.setAttrib('test', 'src', 'url');
equal(DOM.getAttrib('test', 'src'), 'url');
equal(DOM.getAttrib('test', 'data-mce-src'), 'url');
equal(DOM.getAttrib('test', 'abc'), '');
DOM.setAttribs('test', {'class' : '123', title : 'abc'});
equal(DOM.getAttrib('test', 'class'), '123');
equal(DOM.getAttrib('test', 'title'), 'abc');
DOM.setAttribs('test');
equal(DOM.getAttrib('test', 'class'), '123');
equal(DOM.getAttrib('test', 'title'), 'abc');
dom = new tinymce.dom.DOMUtils(document, {keep_values : true, url_converter : function(u, n, e) {
return '&<>"' + u + '&<>"' + n;
}});
dom.setAttribs('test', {src : '123', href : 'abc'});
equal(DOM.getAttrib('test', 'src'), '&<>"123&<>"src');
equal(DOM.getAttrib('test', 'href'), '&<>"abc&<>"href');
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.setAttribs(['test2', 'test3', 'test4'], {test1 : "1", test2 : "2"});
equal(DOM.getAttrib('test2', 'test1'), '1');
equal(DOM.getAttrib('test3', 'test2'), '2');
equal(DOM.getAttrib('test4', 'test1'), '1');
equal(DOM.getAttrib(document, 'test'), false);
equal(DOM.getAttrib(document, 'test', ''), '');
equal(DOM.getAttrib(document, 'test', 'x'), 'x');
DOM.remove('test');
});
test('getAttribs', 2, function() {
var dom;
function check(obj, val) {
var count = 0;
val = val.split(',');
tinymce.each(obj, function(o) {
if (tinymce.inArray(val, o.nodeName.toLowerCase()) != -1 && o.specified)
count++;
});
return count == obj.length;
};
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<span id="test2" class="test"></span>';
ok(check(DOM.getAttribs('test2'), 'id,class'));
DOM.get('test').innerHTML = '<input id="test2" type="checkbox" name="test" value="1" disabled readonly checked></span>';
ok(check(DOM.getAttribs('test2'), 'id,type,name,value,disabled,readonly,checked'), 'Expected attributed: type,name,disabled,readonly,checked');
DOM.remove('test');
});
test('setGetStyles', 7, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setStyle('test', 'font-size', '20px');
equal(DOM.getStyle('test', 'font-size'), '20px', null, tinymce.isWebKit);
DOM.setStyle('test', 'fontSize', '21px');
equal(DOM.getStyle('test', 'fontSize'), '21px', null, tinymce.isWebKit);
DOM.setStyles('test', {fontSize : '22px', display : 'inline'});
equal(DOM.getStyle('test', 'fontSize'), '22px', null, tinymce.isWebKit);
equal(DOM.getStyle('test', 'display'), 'inline', null, tinymce.isWebKit);
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.setStyles(['test2', 'test3', 'test4'], {fontSize : "22px"});
equal(DOM.getStyle('test2', 'fontSize'), '22px');
equal(DOM.getStyle('test3', 'fontSize'), '22px');
equal(DOM.getStyle('test4', 'fontSize'), '22px');
DOM.setAttrib('test', 'style', '');
DOM.remove('test');
});
test('getPos', 2, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setStyles('test', {position : 'absolute', left : 100, top : 110});
equal(DOM.getPos('test').x, 100);
equal(DOM.getPos('test').y, 110);
DOM.setAttrib('test', 'style', '');
DOM.remove('test');
});
test('getParent', 6, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<div><span>ab<a id="test2" href="">abc</a>c</span></div>';
equal(DOM.getParent('test2', function(n) {return n.nodeName == 'SPAN';}).nodeName, 'SPAN');
equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}).nodeName, 'BODY');
equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}, document.body), null);
equal(DOM.getParent('test2', function(n) {return false;}), null);
equal(DOM.getParent('test2', 'SPAN').nodeName, 'SPAN');
equal(DOM.getParent('test2', 'body', DOM.get('test')), null);
DOM.get('test').innerHTML = '';
DOM.remove('test');
});
test('getParents', 4, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<div><span class="test">ab<span><a id="test2" href="">abc</a>c</span></span></div>';
equal(DOM.getParents('test2', function(n) {return n.nodeName == 'SPAN';}).length, 2);
equal(DOM.getParents('test2', 'span').length, 2);
equal(DOM.getParents('test2', 'span.test').length, 1);
equal(DOM.getParents('test2', 'body', DOM.get('test')).length, 0);
DOM.remove('test');
});
test('is', 2, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<div><span class="test">ab<span><a id="test2" href="">abc</a>c</span></span></div>';
ok(DOM.is(DOM.select('span', 'test'), 'span'));
ok(DOM.is(DOM.select('#test2', 'test'), '#test2'));
DOM.remove('test');
});
test('getViewPort', 4, function() {
var wp;
wp = DOM.getViewPort();
equal(wp.x, 0);
equal(wp.y, 0);
ok(wp.w > 0);
ok(wp.h > 0);
});
test('getRect', 5, function() {
var r;
DOM.add(document.body, 'div', {id : 'test'});
DOM.setStyles('test', {position : 'absolute', left : 100, top : 110, width : 320, height : 240});
r = DOM.getRect('test');
equal(r.x, 100);
equal(r.y, 110);
equal(r.w, 320);
equal(r.h, 240);
DOM.setAttrib('test', 'style', '');
DOM.get('test').innerHTML = '<div style="width:320px;height:240px"><div id="test2" style="width:50%;height:240px"></div></div>';
r = DOM.getRect('test2');
equal(r.w, 160);
DOM.remove('test');
});
test('getSize', 2, function() {
var r;
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<div style="width:320px;height:240px"><div id="test2" style="width:50%;height:240px"></div></div>';
r = DOM.getSize('test2');
equal(r.w, 160);
DOM.get('test').innerHTML = '<div style="width:320px;height:240px"><div id="test2" style="width:100px;height:240px"></div></div>';
r = DOM.getSize('test2');
equal(r.w, 100);
DOM.remove('test');
});
test('getNext', 5, function() {
var r;
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<strong>A</strong><span>B</span><em>C</em>';
equal(DOM.getNext(DOM.get('test').firstChild, '*').nodeName, 'SPAN');
equal(DOM.getNext(DOM.get('test').firstChild, 'em').nodeName, 'EM');
equal(DOM.getNext(DOM.get('test').firstChild, 'div'), null);
equal(DOM.getNext(null, 'div'), null);
equal(DOM.getNext(DOM.get('test').firstChild, function(n) {return n.nodeName == 'EM'}).nodeName, 'EM');
DOM.remove('test');
});
test('getPrev', 5, function() {
var r;
DOM.add(document.body, 'div', {id : 'test'});
DOM.get('test').innerHTML = '<strong>A</strong><span>B</span><em>C</em>';
equal(DOM.getPrev(DOM.get('test').lastChild, '*').nodeName, 'SPAN');
equal(DOM.getPrev(DOM.get('test').lastChild, 'strong').nodeName, 'STRONG');
equal(DOM.getPrev(DOM.get('test').lastChild, 'div'), null);
equal(DOM.getPrev(null, 'div'), null);
equal(DOM.getPrev(DOM.get('test').lastChild, function(n) {return n.nodeName == 'STRONG'}).nodeName, 'STRONG');
DOM.remove('test');
});
test('loadCSS', 1, function() {
var c = 0;
DOM.loadCSS('css/test.css?a=1,css/test.css?a=2,css/test.css?a=3');
tinymce.each(document.getElementsByTagName('link'), function(n) {
if (n.href.indexOf('test.css?a=') != -1)
c++;
});
equal(c, 3, null, tinymce.isOpera);
});
test('insertAfter', 2, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<span id="test2"></span>');
DOM.insertAfter(DOM.create('br'), 'test2');
equal(DOM.get('test2').nextSibling.nodeName, 'BR');
DOM.setHTML('test', '<span>test</span><span id="test2"></span><span>test</span>');
DOM.insertAfter(DOM.create('br'), 'test2');
equal(DOM.get('test2').nextSibling.nodeName, 'BR');
DOM.remove('test');
});
test('isBlock', 4, function() {
ok(DOM.isBlock(DOM.create('div')));
ok(DOM.isBlock('DIV'));
ok(!DOM.isBlock('SPAN'));
ok(DOM.isBlock('div'));
});
test('remove', 3, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
DOM.remove('test2', 1);
equal(DOM.get('test').innerHTML.toLowerCase(), '<span>test</span><span>test2</span>');
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
equal(DOM.remove('test2').nodeName, 'SPAN');
DOM.get('test').innerHTML = '<span id="test2"></span><span id="test3"></span><span id="test4"></span>';
DOM.remove(['test2', 'test4']);
equal(DOM.select('span', 'test').length, 1);
DOM.remove('test');
});
test('replace', 2, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
DOM.replace(DOM.create('div', {id : 'test2'}), 'test2', 1);
equal(DOM.get('test2').innerHTML.toLowerCase(), '<span>test</span><span>test2</span>');
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
DOM.replace(DOM.create('div', {id : 'test2'}), 'test2');
equal(DOM.get('test2').innerHTML, '');
DOM.remove('test');
});
test('toHex', 5, function() {
equal(DOM.toHex('rgb(0, 255, 255)'), '#00ffff');
equal(DOM.toHex('rgb(255, 0, 0)'), '#ff0000');
equal(DOM.toHex('rgb(0, 0, 255)'), '#0000ff');
equal(DOM.toHex('rgb ( 0 , 0 , 255 ) '), '#0000ff');
equal(DOM.toHex(' RGB ( 0 , 0 , 255 ) '), '#0000ff');
});
test('getOuterHTML', 4, function() {
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
equal(DOM.getOuterHTML('test2').toLowerCase().replace(/\"/g, ''), '<span id=test2><span>test</span><span>test2</span></span>');
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
DOM.setOuterHTML('test2', '<div id="test2">123</div>');
equal(tinymce.trim(DOM.getOuterHTML('test2') || '').toLowerCase().replace(/\"/g, ''), '<div id=test2>123</div>');
DOM.setHTML('test', '<span id="test2"><span>test</span><span>test2</span></span>');
DOM.setOuterHTML('test2', '<div id="test2">123</div><div id="test3">abc</div>');
equal(tinymce.trim(DOM.get('test').innerHTML).toLowerCase().replace(/>\s+</g, '><').replace(/\"/g, ''), '<div id=test2>123</div><div id=test3>abc</div>');
DOM.setHTML('test', 'test');
equal(tinymce.trim(DOM.getOuterHTML(DOM.get('test').firstChild)), 'test');
DOM.remove('test');
});
test('encodeDecode', 2, function() {
equal(DOM.encode('\u00e5\u00e4\u00f6&<>"'), '\u00e5\u00e4\u00f6&amp;&lt;&gt;&quot;');
equal(DOM.decode('&aring;&auml;&ouml;&amp;&lt;&gt;&quot;'), '\u00e5\u00e4\u00f6&<>"');
});
test('split', 2, function() {
var point, parent;
DOM.add(document.body, 'div', {id : 'test'});
DOM.setHTML('test', '<p><b>text1<span>inner</span>text2</b></p>');
parent = DOM.select('p', DOM.get('test'))[0];
point = DOM.select('span', DOM.get('test'))[0];
DOM.split(parent, point);
equal(DOM.get('test').innerHTML.toLowerCase().replace(/\s+/g, ''), '<p><b>text1</b></p><span>inner</span><p><b>text2</b></p>');
DOM.setHTML('test', '<ul><li>first line<br><ul><li><span>second</span> <span>line</span></li><li>third line<br></li></ul></li></ul>');
parent = DOM.select('li:nth-child(1)', DOM.get('test'))[0];
point = DOM.select('ul li:nth-child(2)', DOM.get('test'))[0];
DOM.split(parent, point);
equal(cleanHtml(DOM.get('test').innerHTML), '<ul><li>first line<br><ul><li><span>second</span> <span>line</span></li></ul></li><li>third line<br></li></ul>');
DOM.remove('test');
});
test('nodeIndex', 5, function() {
DOM.add(document.body, 'div', {id : 'test'}, 'abc<b>abc</b>abc');
equal(DOM.nodeIndex(DOM.get('test').childNodes[0]), 0, 'Index of first child.');
equal(DOM.nodeIndex(DOM.get('test').childNodes[1]), 1, 'Index of second child.');
equal(DOM.nodeIndex(DOM.get('test').childNodes[2]), 2, 'Index of third child.');
DOM.get('test').insertBefore(DOM.doc.createTextNode('a'), DOM.get('test').firstChild);
DOM.get('test').insertBefore(DOM.doc.createTextNode('b'), DOM.get('test').firstChild);
equal(DOM.nodeIndex(DOM.get('test').lastChild), 4, 'Index of last child with fragmented DOM.');
equal(DOM.nodeIndex(DOM.get('test').lastChild, true), 2, 'Normalized index of last child with fragmented DOM.');
DOM.remove('test');
});
test('isEmpty', 14, function() {
DOM.schema = new tinymce.html.Schema(); // A schema will be added when used within a editor instance
DOM.add(document.body, 'div', {id : 'test'}, '');
ok(DOM.isEmpty(DOM.get('test')), 'No children');
DOM.setHTML('test', '<br />');
ok(DOM.isEmpty(DOM.get('test')), 'Br child');
DOM.setHTML('test', '<br /><br />');
ok(!DOM.isEmpty(DOM.get('test')), 'Br children');
DOM.setHTML('test', 'text');
ok(!DOM.isEmpty(DOM.get('test')), 'Text child');
DOM.setHTML('test', '<span>text</span>');
ok(!DOM.isEmpty(DOM.get('test')), 'Text child in span');
DOM.setHTML('test', '<span></span>');
ok(DOM.isEmpty(DOM.get('test')), 'Empty span child');
DOM.setHTML('test', '<div><span><b></b></span><b></b><em></em></div>');
ok(DOM.isEmpty(DOM.get('test')), 'Empty complex HTML');
DOM.setHTML('test', '<div><span><b></b></span><b></b><em>X</em></div>');
ok(!DOM.isEmpty(DOM.get('test')), 'Non empty complex HTML');
DOM.setHTML('test', '<div><span><b></b></span><b></b><em> </em></div>');
ok(DOM.isEmpty(DOM.get('test')), 'Non empty complex HTML with space');
DOM.setHTML('test', '<div><span><b></b></span><b></b><em><a name="x"></a></em></div>');
ok(!DOM.isEmpty(DOM.get('test')), 'Non empty complex HTML with achor name');
DOM.setHTML('test', '<img src="x">');
ok(!DOM.isEmpty(DOM.get('test')), 'Non empty html with img element');
DOM.setHTML('test', '<span data-mce-bookmark="1"></span>');
ok(!DOM.isEmpty(DOM.get('test')), 'Span with bookmark attribute.');
DOM.setHTML('test', '<span data-mce-style="color:Red"></span>');
ok(DOM.isEmpty(DOM.get('test')), 'Span with data-mce attribute.');
DOM.setHTML('test', '<div><!-- comment --></div>');
ok(!DOM.isEmpty(DOM.get('test')), 'Element with comment.');
DOM.remove('test');
});
test('isEmpty on P with BR in EM', function() {
var elm = DOM.create('p', null, '<em><br></em>');
ok(DOM.isEmpty(elm, 'No children'));
});
test('isEmpty on P with two BR in EM', function() {
var elm = DOM.create('p', null, '<em><br><br></em>');
equal(false, DOM.isEmpty(elm));
});
test('bind/unbind/fire', function() {
var count = 0;
DOM.bind(document, 'click', function() {count++;});
DOM.fire(document, 'click');
DOM.unbind(document, 'click');
equal(count, 1);
count = 0;
DOM.bind([document, window], 'click', function(e) {e.stopPropagation(); count++;});
DOM.fire(document, 'click');
DOM.fire(window, 'click');
DOM.unbind([document, window], 'click');
equal(count, 2);
count = 0;
DOM.fire(document, 'click');
DOM.fire(window, 'click');
equal(count, 0);
});
DOM.remove('test');
})();

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.dom.DOMUtils</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../../js/tinymce/tinymce.jquery.min.js"></script>
</head>
<body>
<script>
QUnit.config.reorder = false;
module("tinymce.dom.DOMUtils (jQuery)", {
});
</script>
<script src="DOMUtils.js"></script>
<h1 id="qunit-header">Unit tests for tinymce.dom.DOMUtils</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,459 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for the EventUtils class</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var eventUtils = tinymce.dom.Event;
QUnit.config.reorder = false;
module("tinymce.dom.Event", {
teardown: function() {
eventUtils.clean(window);
}
});
// Bind dummy ready so it gets the domLoaded ready state
eventUtils.bind(window, "ready", function() {});
test("unbind all", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click = true;
});
eventUtils.bind(window, 'keydown', function(e) {
result.keydown1 = true;
});
eventUtils.bind(window, 'keydown', function(e) {
result.keydown2 = true;
});
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {click: true, keydown1: true, keydown2: true});
eventUtils.unbind(window);
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {});
});
test("unbind event", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click = true;
});
eventUtils.bind(window, 'keydown', function(e) {
result.keydown1 = true;
});
eventUtils.bind(window, 'keydown', function(e) {
result.keydown2 = true;
});
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {click: true, keydown1: true, keydown2: true});
eventUtils.unbind(window, 'click');
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {keydown1: true, keydown2: true});
});
test("unbind event non existing", function() {
eventUtils.unbind(window, 'noevent');
ok(true, "No exception");
});
test("unbind callback", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click = true;
});
eventUtils.bind(window, 'keydown', function(e) {
result.keydown1 = true;
});
function callback2(e) {
result.keydown2 = true;
};
eventUtils.bind(window, 'keydown', callback2);
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {click: true, keydown1: true, keydown2: true});
eventUtils.unbind(window, 'keydown', callback2);
result = {};
eventUtils.fire(window, 'click');
eventUtils.fire(window, 'keydown');
deepEqual(result, {click: true, keydown1: true});
});
test("unbind multiple", function() {
var result;
eventUtils.bind(window, 'mouseup mousedown click', function(e) {
result[e.type] = true;
});
eventUtils.unbind(window, 'mouseup mousedown');
result = {};
eventUtils.fire(window, 'mouseup');
eventUtils.fire(window, 'mousedown');
eventUtils.fire(window, 'click');
deepEqual(result, {click: true});
});
test("bind multiple", function() {
var result;
eventUtils.bind(window, 'mouseup mousedown', function(e) {
result[e.type] = true;
});
result = {};
eventUtils.fire(window, 'mouseup');
eventUtils.fire(window, 'mousedown');
eventUtils.fire(window, 'click');
deepEqual(result, {mouseup: true, mousedown: true});
});
test("bind/fire bubbling", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.window = true;
});
eventUtils.bind(document, 'click', function() {
result.document = true;
});
eventUtils.bind(document.body, 'click', function() {
result.body = true;
});
eventUtils.bind(document.getElementById('content'), 'click', function() {
result.content = true;
});
eventUtils.bind(document.getElementById('inner'), 'click', function() {
result.inner = true;
});
result = {};
eventUtils.fire(window, 'click');
deepEqual(result, {window: true});
result = {};
eventUtils.fire(document, 'click');
deepEqual(result, {document: true, window: true});
result = {};
eventUtils.fire(document.body, 'click');
deepEqual(result, {body: true, document: true, window: true});
result = {};
eventUtils.fire(document.getElementById('content'), 'click');
deepEqual(result, {content: true, body: true, document: true, window: true});
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {inner: true, content: true, body: true, document: true, window: true});
});
test("bind/fire stopImmediatePropagation", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click1 = true;
});
eventUtils.bind(window, 'click', function(e) {
result.click2 = true;
e.stopImmediatePropagation();
});
eventUtils.bind(window, 'click', function(e) {
result.click3 = true;
});
result = {};
eventUtils.fire(window, 'click');
deepEqual(result, {click1: true, click2: true});
});
test("bind/fire stopPropagation", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click1 = true;
});
eventUtils.bind(document.body, 'click', function(e) {
result.click2 = true;
});
eventUtils.bind(document.getElementById('inner'), 'click', function(e) {
result.click3 = true;
e.stopPropagation();
});
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click3: true});
});
test("clean window", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click1 = true;
});
eventUtils.bind(document.body, 'click', function(e) {
result.click2 = true;
});
eventUtils.bind(document.getElementById('content'), 'click', function(e) {
result.click3 = true;
});
eventUtils.bind(document.getElementById('inner'), 'click', function(e) {
result.click4 = true;
});
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click1: true, click2: true, click3: true, click4: true});
eventUtils.clean(window);
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {});
});
test("clean document", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click1 = true;
});
eventUtils.bind(document, 'click', function(e) {
result.click2 = true;
});
eventUtils.bind(document.body, 'click', function(e) {
result.click3 = true;
});
eventUtils.bind(document.getElementById('content'), 'click', function(e) {
result.click4 = true;
});
eventUtils.bind(document.getElementById('inner'), 'click', function(e) {
result.click5 = true;
});
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click1: true, click2: true, click3: true, click4: true, click5: true});
eventUtils.clean(document);
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click1: true});
});
test("clean element", function() {
var result;
eventUtils.bind(window, 'click', function(e) {
result.click1 = true;
});
eventUtils.bind(document.body, 'click', function(e) {
result.click2 = true;
});
eventUtils.bind(document.getElementById('content'), 'click', function(e) {
result.click3 = true;
});
eventUtils.bind(document.getElementById('inner'), 'click', function(e) {
result.click4 = true;
});
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click1: true, click2: true, click3: true, click4: true});
eventUtils.clean(document.getElementById('content'));
result = {};
eventUtils.fire(document.getElementById('inner'), 'click');
deepEqual(result, {click1: true, click2: true});
});
test("mouseenter/mouseleave bind/unbind", function() {
var result = {};
eventUtils.bind(document.body, 'mouseenter mouseleave', function(e) {
result[e.type] = true;
});
eventUtils.fire(document.body, 'mouseenter');
eventUtils.fire(document.body, 'mouseleave');
deepEqual(result, {mouseenter: true, mouseleave: true});
result = {};
eventUtils.clean(document.body);
eventUtils.fire(document.body, 'mouseenter');
eventUtils.fire(document.body, 'mouseleave');
deepEqual(result, {});
});
test("focusin/focusout bind/unbind", function() {
var result = {};
eventUtils.bind(document.body, 'focusin focusout', function(e) {
// IE will fire a focusout on the parent element if you focus an element within not a big deal so lets detect it in the test
if (e.type == "focusout" && e.target.contains(document.activeElement)) {
return;
}
result[e.type] = result[e.type] ? ++result[e.type] : 1;
});
document.getElementById('inner').focus();
document.getElementById('content').focus();
deepEqual(result, {focusin: 2, focusout: 1});
});
test("bind unbind fire clean on null", function() {
eventUtils.bind(null, 'click', function() {});
eventUtils.unbind(null, 'click', function() {});
eventUtils.fire(null, {});
eventUtils.clean(null);
ok(true, "No exception");
});
test("bind ready when page is loaded", function() {
var ready;
eventUtils.bind(window, 'ready', function() {
ready = true;
});
ok(eventUtils.domLoaded, "DomLoaded state true");
ok(ready, "Window is ready.");
});
test("event states when event object is fired twice", function() {
var result = {};
eventUtils.bind(window, 'keydown', function(e) {result[e.type] = true;e.preventDefault();e.stopPropagation();});
eventUtils.bind(window, 'keyup', function(e) {result[e.type] = true;e.stopImmediatePropagation();});
var event = {};
eventUtils.fire(window, 'keydown', event);
eventUtils.fire(window, 'keyup', event);
ok(event.isDefaultPrevented(), "Default is prevented.");
ok(event.isPropagationStopped(), "Propagation is stopped.");
ok(event.isImmediatePropagationStopped(), "Immediate propagation is stopped.");
deepEqual(result, {keydown: true, keyup: true});
});
test("unbind inside callback", function() {
var data;
function append(value) {
return function() {
data += value;
};
}
function callback() {
eventUtils.unbind(window, 'click', callback);
data += 'b';
}
data = '';
eventUtils.bind(window, 'click', append("a"));
eventUtils.bind(window, 'click', callback);
eventUtils.bind(window, 'click', append("c"));
eventUtils.fire(window, 'click', {});
equal(data, 'abc');
data = '';
eventUtils.fire(window, 'click', {});
equal(data, 'ac');
});
test("ready/DOMContentLoaded (domLoaded = true)", function() {
var evt;
eventUtils.bind(window, "ready", function(e) {evt = e});
equal(evt.type, "ready");
});
test("ready/DOMContentLoaded (document.readyState check)", function() {
var evt;
try {
document.readyState = "loading";
} catch (e) {
ok(true, "IE doesn't allow us to set document.readyState");
return;
}
eventUtils.domLoaded = false;
document.readyState = "loading";
eventUtils.bind(window, "ready", function(e) {evt = e});
ok(typeof(evt) !== "undefined");
eventUtils.domLoaded = false;
document.readyState = "complete";
eventUtils.bind(window, "ready", function(e) {evt = e});
equal(evt.type, "ready");
});
</script>
<h1 id="qunit-header">Unit tests for DOM Selection IE implementation</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content" tabindex="0">
<div id="inner" tabindex="0"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,606 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for DOM Range IE implementation</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/tinymce_loader.js"></script>
</head>
<body>
<script>
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Range", {
autostart: false
});
function createRng() {
return document.createRange ? document.createRange() : new tinymce.dom.Range(tinymce.DOM);
};
function getHTML(co) {
var div = document.createElement('div'), h;
if (!co)
return 'null';
div.appendChild(co.cloneNode(true));
h = div.innerHTML.toLowerCase();
h = h.replace(/[\r\n\t]/g, ''); // Remove line feeds and tabs
h = h.replace(/ (\w+)=([^\"][^\s>]*)/gi, ' $1="$2"'); // Restore attribs on IE
return h;
};
function setup() {
if (this.orgHTML)
document.getElementById('sample').innerHTML = this.orgHTML;
// Remove whitespace nodes to normalize IE and other browsers
function clean(n) {
var i;
if (n.nodeType == 3 && /^[\s]+$/.test(n.nodeValue))
return n.parentNode.removeChild(n);
for (i = n.childNodes.length - 1; i >= 0; i--)
clean(n.childNodes[i]);
};
clean(document.getElementById('sample'));
this.orgHTML = document.getElementById('sample').innerHTML;
};
test("Initial state", function() {
var r = createRng();
setup();
expect(5);
equal(r.startContainer, document)
equal(r.startOffset, 0)
equal(r.endContainer, document)
equal(r.endOffset, 0)
equal(r.commonAncestorContainer, document)
});
test("setStartSetEnd", function() {
var r = createRng();
setup();
expect(12);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('strong').firstChild, 3);
equal(r.startContainer.nodeValue, 'first')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeValue, 'strong')
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 3)
equal(r.commonAncestorContainer.nodeName, 'P')
r.setStart(document.getElementById('first'), 0);
r.setEnd(document.getElementById('strong'), 0);
equal(r.startContainer.nodeName, 'P')
equal(r.startOffset, 0)
equal(r.endContainer.nodeName, 'STRONG')
equal(r.endOffset, 0)
equal(r.commonAncestorContainer.nodeName, 'P')
});
test("setStartBeforeSetEndAfter", function() {
var r = createRng();
setup();
expect(5);
r.setStartBefore(document.getElementById('first'));
r.setEndAfter(document.getElementById('strong'));
equal(r.startContainer.nodeName, 'DIV')
equal(r.startOffset, 0)
equal(r.endContainer.nodeName, 'P')
equal(r.endOffset, 5)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_setStartAfterSetEndBefore", function() {
var r = createRng();
setup();
expect(5);
r.setStartAfter(document.getElementById('strong'));
r.setEndBefore(document.getElementById('em1'));
equal(r.startContainer.nodeName, 'P')
equal(r.startOffset, 5)
equal(r.endContainer.nodeName, 'P')
equal(r.endOffset, 6)
equal(r.commonAncestorContainer.nodeName, 'P')
});
test("test_collapse", function() {
var r = createRng();
setup();
expect(10);
r.setStart(document.getElementById('strong').firstChild, 0);
r.setEnd(document.getElementById('strong').firstChild, 6);
r.collapse(true);
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 0)
equal(r.commonAncestorContainer.nodeType, 3)
r.setStart(document.getElementById('strong').firstChild, 0);
r.setEnd(document.getElementById('strong').firstChild, 6);
r.collapse(false);
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 6)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 6)
equal(r.commonAncestorContainer.nodeType, 3)
});
test("test_selectNode", function() {
var r = createRng();
setup();
expect(4);
r.selectNode(document.getElementById('strong').firstChild);
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 1)
});
test("test_selectNodeContents", function() {
var r = createRng();
setup();
expect(8);
r.selectNodeContents(document.getElementById('strong').firstChild);
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 6)
r.selectNodeContents(document.getElementById('first'));
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 8)
});
test("test_insertNode", function() {
var r = createRng();
setup();
expect(4);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('first').firstChild, 2);
r.insertNode(document.createTextNode('ABC'));
equal(document.getElementById('first').childNodes[0].nodeValue, 'f')
equal(document.getElementById('first').childNodes[1].nodeValue, 'ABC')
equal(document.getElementById('first').childNodes[2].nodeValue, 'irst')
r.selectNode(document.getElementById('strong'));
r.insertNode(document.createElement('span'));
equal(document.getElementById('strong').previousSibling.nodeName, 'SPAN')
});
test("test_cloneRange", function() {
var r = createRng();
setup();
expect(6);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('strong').firstChild, 2);
var r2 = r.cloneRange();
equal(r2.startContainer.nodeType, 3)
equal(r2.startOffset, 1)
equal(r2.endContainer.nodeType, 3)
equal(r2.endOffset, 2)
equal(r2.collapsed, false)
equal(r2.commonAncestorContainer.nodeName, 'P')
});
if (tinymce.isGecko) {
test('test_cloneContents (SKIPPED)', function() {
ok(true, 'Before Firefox 3.6 this test fails because of a corner case bug but since the point is to test the IE Range implementation we skip it.');
});
} else {
test("test_cloneContents", function() {
var r = createRng();
setup();
expect(77);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('two').firstChild, 2);
equal(getHTML(r.cloneContents()), '<p id="first">irst<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">ab</td></tr></tbody></table>')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 2)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeName, 'DIV')
r.setStart(document.getElementById('two').firstChild, 1);
r.setEnd(document.getElementById('last').firstChild, 2);
equal(getHTML(r.cloneContents()), '<table id="table"><tbody><tr><td id="two">bc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">te</p>')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 2)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeName, 'DIV')
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('first').lastChild, 4);
equal(getHTML(r.cloneContents()), 'irst<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> str')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 4)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeName, 'P')
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('first').firstChild, 4);
equal(getHTML(r.cloneContents()), 'irs')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 4)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 3)
r.setStart(document.getElementById('first'), 0);
r.setEnd(document.getElementById('last'), 0);
equal(getHTML(r.cloneContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id=\"last\"></p>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 0)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('first'), 1);
r.setEnd(document.getElementById('last'), 1);
equal(getHTML(r.cloneContents()), '<p id="first"><!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc</p>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 1)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('sample'), document.getElementById('sample').childNodes.length - 1);
equal(getHTML(r.cloneContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, document.getElementById('sample').childNodes.length - 1)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('first'), 0);
r.setEnd(document.getElementById('last').firstChild, 1);
equal(getHTML(r.cloneContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">t</p>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 1)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('last'), 0);
equal(getHTML(r.cloneContents()), '<p id="first">irst<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id=\"last\"></p>')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 0)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('traverse'), 2);
equal(getHTML(r.cloneContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em></p>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 2)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('traverse'), 1);
equal(getHTML(r.cloneContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b></p>')
equal(r.startContainer.nodeType, 1)
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 1)
equal(r.collapsed, false)
equal(r.commonAncestorContainer.nodeType, 1)
});
}
test("test_extractContents1", function() {
var r = createRng();
setup();
expect(10);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('first').firstChild, 4);
equal(getHTML(r.extractContents()), 'irs')
equal(r.startContainer.nodeType, 3)
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 3)
equal(r.endOffset, 1)
equal(r.collapsed, true)
equal(r.startContainer == r.endContainer, true)
equal(r.startOffset == r.endOffset, true)
equal(r.commonAncestorContainer.nodeType, 3)
equal(getHTML(document.getElementById('first')), '<p id="first">ft<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p>')
});
test("test_extractContents2", function() {
var r = createRng();
setup();
expect(9);
r.setStart(document.getElementById('two').firstChild, 1);
r.setEnd(document.getElementById('last').firstChild, 2);
equal(getHTML(r.extractContents()), '<table id="table"><tbody><tr><td id="two">bc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">te</p>')
equal(r.startContainer.nodeType, 1)
equal(getHTML(r.startContainer), '<div id="sample"><p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">a</td></tr></tbody></table><p id="last">xtabc<span>span</span></p></div>')
equal(r.startOffset, 4)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 4)
equal(getHTML(r.endContainer), '<div id="sample"><p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">a</td></tr></tbody></table><p id="last">xtabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_extractContents3", function() {
var r = createRng();
setup();
expect(9);
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('traverse'), 2);
equal(getHTML(r.extractContents()), '<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em></p>')
equal(getHTML(r.startContainer), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 0)
equal(getHTML(r.endContainer), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(getHTML(document.getElementById('sample')), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_deleteContents1", function() {
var r = createRng();
setup();
expect(8);
r.setStart(document.getElementById('two').firstChild, 1);
r.setEnd(document.getElementById('last').firstChild, 2);
r.deleteContents();
equal(getHTML(r.startContainer), '<div id="sample"><p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">a</td></tr></tbody></table><p id="last">xtabc<span>span</span></p></div>')
equal(r.startOffset, 4)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 4)
equal(getHTML(r.endContainer), '<div id="sample"><p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">a</td></tr></tbody></table><p id="last">xtabc<span>span</span></p></div>')
equal(getHTML(document.getElementById('sample')), '<div id="sample"><p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">a</td></tr></tbody></table><p id="last">xtabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_deleteContents2", function() {
var r = createRng();
setup();
expect(8);
r.setStart(document.getElementById('first').firstChild, 1);
r.setEnd(document.getElementById('first').lastChild, 4);
r.deleteContents();
equal(getHTML(r.startContainer), '<p id="first">fong.</p>')
equal(r.startOffset, 1)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 1)
equal(getHTML(r.endContainer), '<p id="first">fong.</p>')
equal(getHTML(document.getElementById('sample')), '<div id="sample"><p id="first">fong.</p><p id="second">bar</p><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'P')
});
test("test_deleteContents3", function() {
var r = createRng();
setup();
expect(8);
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('sample'), 2);
r.deleteContents();
equal(getHTML(r.startContainer), '<div id="sample"><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 0)
equal(getHTML(r.endContainer), '<div id="sample"><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(getHTML(document.getElementById('sample')), '<div id="sample"><p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_deleteContents4", function() {
var r = createRng();
setup();
expect(8);
r.setStart(document.getElementById('sample'), 0);
r.setEnd(document.getElementById('traverse'), 2);
r.deleteContents();
equal(getHTML(r.startContainer), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.startOffset, 0)
equal(r.endContainer.nodeType, 1)
equal(r.endOffset, 0)
equal(getHTML(r.endContainer), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(getHTML(document.getElementById('sample')), '<div id="sample"><p id="traverse">more text</p><table id="table"><tbody><tr><td>1</td><td id="two">abc</td></tr><tr><td>3</td><td>4</td></tr></tbody></table><p id="last">textabc<span>span</span></p></div>')
equal(r.collapsed, true)
equal(r.commonAncestorContainer.nodeName, 'DIV')
});
test("test_compareBoundaryPoints", function() {
var r1 = createRng(), r2 = createRng(), START_TO_START = 0, START_TO_END = 1, END_TO_END = 2, END_TO_START = 3;
setup();
r1.setStartBefore(document.getElementById('strong'));
r1.setEndAfter(document.getElementById('strong'));
r2.setStartBefore(document.getElementById('strong'));
r2.setEndAfter(document.getElementById('strong'));
equal(r1.compareBoundaryPoints(START_TO_START, r2), 0, 'Start to start for same ranges');
equal(r1.compareBoundaryPoints(END_TO_END, r2), 0, 'End to end for same ranges');
equal(r1.compareBoundaryPoints(START_TO_END, r1), 1, 'Start to end for same ranges');
equal(r1.compareBoundaryPoints(END_TO_START, r2), -1, 'End to start for same ranges');
r1.setStartBefore(document.getElementById('strong'));
r1.setEndAfter(document.getElementById('strong'));
r2.setStartBefore(document.getElementById('em1'));
r2.setEndAfter(document.getElementById('em1'));
equal(r1.compareBoundaryPoints(START_TO_START, r2), -1, 'Start to start for range before');
equal(r1.compareBoundaryPoints(END_TO_END, r2), -1, 'End to end for range before');
equal(r1.compareBoundaryPoints(START_TO_END, r2), -1, 'Start to end for range before');
equal(r1.compareBoundaryPoints(END_TO_START, r2), -1, 'End to start for range before');
equal(r2.compareBoundaryPoints(START_TO_START, r1), 1, 'Start to start for range after');
equal(r2.compareBoundaryPoints(END_TO_END, r1), 1, 'End to end for range after');
equal(r2.compareBoundaryPoints(START_TO_END, r1), 1, 'Start to end for range after');
equal(r2.compareBoundaryPoints(END_TO_START, r1), 1, 'End to start for range after');
r1.setStartBefore(document.getElementById('strong'));
r1.setEndAfter(document.getElementById('strong'));
r2.setStart(document.getElementById('strong').firstChild, 2);
r2.setEnd(document.getElementById('strong').firstChild, 3);
equal(r1.compareBoundaryPoints(START_TO_START, r2), -1, 'Start to start for range inside');
equal(r1.compareBoundaryPoints(END_TO_END, r2), 1, 'End to end for range inside');
equal(r1.compareBoundaryPoints(START_TO_END, r2), 1, 'Start to end for range inside');
equal(r1.compareBoundaryPoints(END_TO_START, r2), -1, 'End to start for range inside');
});
test("toString in part of same text node", function() {
var rng = createRng();
rng.setStart(document.getElementById('strong').firstChild, 1);
rng.setEnd(document.getElementById('strong').firstChild, 3);
equal(rng.toString(), "tr");
});
test("toString in start/end of same text node", function() {
var rng = createRng();
rng.setStart(document.getElementById('strong').firstChild, 0);
rng.setEnd(document.getElementById('strong').firstChild, 6);
equal(rng.toString(), "strong");
});
test("toString in start in one text node end in another", function() {
var rng = createRng();
rng.setStart(document.getElementById('strong').firstChild, 1);
rng.setEnd(document.getElementById('em1').firstChild, 1);
equal(rng.toString(), "trong second e");
});
// Run on IE only
if (tinymce.isIE) {
test("toString in start in one text node end in another", function() {
var rng = createRng();
rng.setStartBefore(document.getElementById('strong'));
rng.setEndAfter(document.getElementById('em2'));
equal(rng.toString().replace(/\r\n/g, ''), "strong second em strong.barsome text");
});
}
tinymce.DOM.bind(window, 'load', function() {
QUnit.start();
});
</script>
<h1 id="qunit-header">Unit tests for DOM Range IE implementation</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="sample">
<p id="first">first<!--not--> strong <!-- --><strong id="strong">strong</strong> second <em id="em1">em</em> strong.</p>
<p id="second">bar</p>
<p id="traverse"><b><em id="em2">some text</em></b><em>em text</em>more text</p>
<table id="table">
<tr>
<td>1</td>
<td id="two">abc</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<p id="last">textabc<span>span</span></p>
</div>
</body>
</html>

View File

@ -0,0 +1,878 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.dom.Selection</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("Selection", {
autostart: false
});
test('getContent', function() {
var rng, eventObj;
// Get selected contents
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
equal(editor.selection.getContent(), '<p>text</p>', 'Get selected contents');
// Get selected contents (collapsed)
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 0);
editor.selection.setRng(rng);
equal(editor.selection.getContent(), '', 'Get selected contents (collapsed)');
// Get selected contents, onGetContent event
eventObj = {};
function handler(event) {
eventObj = event;
};
editor.on('GetContent', handler);
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.getContent();
equal(eventObj.content, '<p>text</p>', 'Get selected contents, onGetContent event');
editor.off('GetContent', handler);
});
test('setContent', function() {
var rng, eventObj;
// Set contents at selection
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.setContent('<div>test</div>');
equal(editor.getContent(), '<div>test</div>', 'Set contents at selection');
// Set contents at selection (collapsed)
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 0);
editor.selection.setRng(rng);
editor.selection.setContent('<div>test</div>');
equal(editor.getContent(), '<div>test</div>\n<p>text</p>', 'Set contents at selection (collapsed)');
// Insert in middle of paragraph
editor.setContent('<p>beforeafter</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 'before'.length);
rng.setEnd(editor.getBody().firstChild.firstChild, 'before'.length);
editor.selection.setRng(rng);
editor.selection.setContent('<br />');
equal(editor.getContent(), '<p>before<br />after</p>', 'Set contents at selection (inside paragraph)');
// Check the caret is left in the correct position.
rng = editor.selection.getRng(true);
if (document.createRange) {
equal(rng.startContainer, editor.getBody().firstChild, 'Selection start container');
equal(rng.startOffset, 2, 'Selection start offset');
equal(rng.endContainer, editor.getBody().firstChild, 'Selection end container');
equal(rng.endOffset, 2, 'Selection end offset');
} else {
// TridentSelection resolves indexed text nodes
equal(rng.startContainer, editor.getBody().firstChild.lastChild, 'Selection start container');
equal(rng.startOffset, 0, 'Selection start offset');
equal(rng.endContainer, editor.getBody().firstChild.lastChild, 'Selection end container');
equal(rng.endOffset, 0, 'Selection end offset');
}
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 0);
editor.selection.setRng(rng);
editor.selection.setContent('');
equal(editor.getContent(), '<p>text</p>', 'Set contents to empty at selection (collapsed)');
rng = editor.selection.getRng(true);
if (!document.createRange) {
// The old IE selection can only be positioned in text nodes
equal(rng.startContainer, editor.getBody().firstChild.firstChild, 'Selection start container');
equal(rng.startOffset, 0, 'Selection start offset');
equal(rng.endContainer, editor.getBody().firstChild.firstChild, 'Selection end container');
equal(rng.endOffset, 0, 'Selection end offset');
} else {
equal(rng.startContainer, editor.getBody(), 'Selection start container');
equal(rng.startOffset, 0, 'Selection start offset');
equal(rng.endContainer, editor.getBody(), 'Selection end container');
equal(rng.endOffset, 0, 'Selection end offset');
}
// Set selected contents, onSetContent event
eventObj = {};
function handler(event) {
eventObj = event;
};
editor.on('SetContent', handler);
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.setContent('<div>text</div>');
equal(eventObj.content, '<div>text</div>', 'Set selected contents, onSetContent event');
editor.off('SetContent', handler);
});
test('getStart/getEnd', function() {
var rng;
// Selected contents
editor.setContent('<p id="a">text</p><p id="b">text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 0);
rng.setEnd(editor.getBody().lastChild.firstChild, 0);
editor.selection.setRng(rng);
equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart)');
equal(editor.selection.getEnd().id, 'b', 'Selected contents (getEnd)');
// Selected contents (collapsed)
editor.setContent('<p id="a">text</p>\n<p id="b">text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 0);
rng.setEnd(editor.getBody().firstChild.firstChild, 0);
editor.selection.setRng(rng);
equal(editor.selection.getStart().id, 'a', 'Selected contents (getStart, collapsed)');
equal(editor.selection.getEnd().id, 'a', 'Selected contents (getEnd, collapsed)');
});
test('getBookmark/setBookmark (persistent)', function() {
var rng, bookmark;
// Get persistent bookmark simple text selection
editor.setContent('text');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark();
equal(editor.getContent(), 'text', 'Editor contents (text)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), 'ex', 'Selected contents (text)');
// Get persistent bookmark multiple elements text selection
editor.setContent('<p>text</p>\n<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().lastChild.firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark();
equal(editor.getContent(), '<p>text</p>\n<p>text</p>', 'Editor contents (elements)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<p>ext</p>\n<p>tex</p>', 'Selected contents (elements)');
});
test('getBookmark/setBookmark (simple)', function() {
var rng, bookmark;
// Get persistent bookmark simple text selection
editor.setContent('text');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(1);
equal(editor.getContent(), 'text', 'Editor contents (text)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), 'ex', 'Selected contents (text)');
// Get persistent bookmark multiple elements text selection
editor.setContent('<p>text</p>\n<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().lastChild.firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(1);
equal(editor.getContent(), '<p>text</p>\n<p>text</p>', 'Editor contents (elements)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<p>ext</p>\n<p>tex</p>', 'Selected contents (elements)');
});
test('getBookmark/setBookmark (nonintrusive) - simple text selection', function() {
var rng, bookmark;
expect(2);
editor.setContent('text');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2);
equal(editor.getContent(), 'text', 'Editor contents (text)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), 'ex', 'Selected contents (text)');
});
test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark simple element selection', function() {
var rng, bookmark;
expect(1);
// Get non intrusive bookmark simple element selection
editor.setContent('<p>text<em>a<strong>b</strong>c</em></p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.select('em')[0], 1);
rng.setEnd(editor.dom.select('em')[0], 2);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2);
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<strong>b</strong>', 'Selected contents (element)');
});
test('getBookmark/setBookmark (nonintrusive) - Get non intrusive bookmark multiple elements text selection', function() {
var rng, bookmark;
expect(2);
// Get non intrusive bookmark multiple elements text selection
editor.setContent('<p>text</p>\n<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().lastChild.firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2);
equal(editor.getContent(), '<p>text</p>\n<p>text</p>', 'Editor contents (elements)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<p>ext</p>\n<p>tex</p>', 'Selected contents (elements)');
});
test('getBookmark/setBookmark (nonintrusive)', function() {
var rng, bookmark;
expect(2);
// Get non intrusive bookmark multiple elements text selection fragmented
editor.setContent('<p>text</p><p>text</p>');
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('text'));
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.lastChild, 1);
rng.setEnd(editor.getBody().lastChild.firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2);
equal(editor.getContent(), '<p>textaaatext</p>\n<p>text</p>', 'Editor contents (fragmented, elements)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<p>ext</p>\n<p>tex</p>', 'Selected contents (fragmented, elements)');
});
test('getBookmark/setBookmark (nonintrusive) - fragmentext text (normalized)', function() {
var rng, bookmark;
expect(2);
// Get non intrusive bookmark multiple elements text selection fragmented
editor.setContent('<p>text</p><p>text</p>');
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('a'));
editor.dom.select('p')[0].appendChild(editor.dom.doc.createTextNode('text'));
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.lastChild, 1);
rng.setEnd(editor.getBody().lastChild.firstChild, 3);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.setContent(editor.getContent());
equal(editor.getContent(), '<p>textaaatext</p>\n<p>text</p>', 'Editor contents (fragmented, elements)');
editor.selection.moveToBookmark(bookmark);
equal(editor.selection.getContent(), '<p>ext</p>\n<p>tex</p>', 'Selected contents (fragmented, elements)');
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark before image', function() {
var rng, bookmark;
expect(4);
editor.setContent('<p><img src="about:blank" /></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 0);
rng.setEnd(editor.getBody().firstChild, 0);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().firstChild);
equal(rng.startOffset, 0);
equal(rng.endContainer, editor.getBody().firstChild);
equal(rng.endOffset, 0);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark before/after image', function() {
var rng, bookmark;
expect(4);
editor.setContent('<p><img src="about:blank" /></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 0);
rng.setEnd(editor.getBody().firstChild, 1);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().firstChild);
equal(rng.startOffset, 0);
equal(rng.endContainer, editor.getBody().firstChild);
equal(rng.endOffset, 1);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark after image', function() {
var rng, bookmark;
expect(4);
editor.setContent('<p><img src="about:blank" /></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 1);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().firstChild);
equal(rng.startOffset, 1);
equal(rng.endContainer, editor.getBody().firstChild);
equal(rng.endOffset, 1);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark before element', function() {
var rng, bookmark;
expect(4);
editor.setContent('abc<b>123</b>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 0);
rng.setEnd(editor.getBody().firstChild, 2);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().firstChild);
equal(rng.startOffset, 0);
equal(rng.endContainer, editor.getBody().firstChild);
equal(rng.endOffset, 2);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark after element', function() {
var rng, bookmark;
expect(4);
// Get bookmark after element
editor.setContent('<b>123</b>abc');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().lastChild, 1);
rng.setEnd(editor.getBody().lastChild, 2);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().lastChild);
equal(rng.startOffset, 1);
equal(rng.endContainer, editor.getBody().lastChild);
equal(rng.endOffset, 2);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside element', function() {
var rng, bookmark;
expect(4);
editor.setContent('abc<b>123</b>abc');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().childNodes[1].firstChild, 1);
rng.setEnd(editor.getBody().childNodes[1].firstChild, 2);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().childNodes[1].firstChild);
equal(rng.startOffset, 1);
equal(rng.endContainer, editor.getBody().childNodes[1].firstChild);
equal(rng.endOffset, 2);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside root text', function() {
var rng, bookmark;
expect(4);
editor.setContent('abc');
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 2);
editor.selection.setRng(rng);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.getBody().firstChild);
equal(rng.startOffset, 1);
equal(rng.endContainer, editor.getBody().firstChild);
equal(rng.endOffset, 2);
});
test('getBookmark/setBookmark (nonintrusive) - Get bookmark inside complex html', function() {
var rng, bookmark;
expect(4);
editor.setContent('<p>abc</p>123<p>123</p><p>123<b>123</b><table><tr><td>abc</td></tr></table></p>');
editor.execCommand('SelectAll');
setSelection('td', 1, 'td', 2);
bookmark = editor.selection.getBookmark(2, true);
editor.getBody().innerHTML = editor.getBody().innerHTML;
editor.selection.moveToBookmark(bookmark);
rng = editor.selection.getRng(true);
equal(rng.startContainer, editor.dom.select('td')[0].firstChild);
equal(rng.startOffset, 1);
equal(rng.endContainer, editor.dom.select('td')[0].firstChild);
equal(rng.endOffset, 2);
});
test('select first p', 2, function() {
editor.setContent('<p>text1</p><p>text2</p>');
editor.selection.select(editor.dom.select('p')[0]);
equal(editor.selection.getContent(), '<p>text1</p>', 'Select simple element, content');
equal(editor.selection.getStart().nodeName, 'P', 'Select simple element, nodeName');
});
test('select table', 2, function() {
editor.setContent('<table><tbody><tr><td>text1</td></tr></tbody></table>');
editor.selection.select(editor.dom.select('table')[0]);
equal(editor.selection.getContent(), '<table>\n<tbody>\n<tr>\n<td>text1</td>\n</tr>\n</tbody>\n</table>', 'Select complex element, content');
equal(editor.selection.getNode().nodeName, 'TABLE', 'Select complex element, nodeName');
});
test('select table text 1', 2, function() {
editor.setContent('<table><tbody><tr><td id="a">text1</td><td id="b">text2</td></tr></tbody></table>');
editor.selection.select(editor.dom.select('table')[0], true);
equal(editor.selection.getStart().id, 'a', 'Expand to text content 1 (start)');
equal(editor.selection.getEnd().id, 'b', 'Expand to text content 1 (end)');
});
test('select table text 2', 2, function() {
editor.setContent('<table><tbody><tr><td id="a"><br /></td><td id="b"><br /></td></tr></tbody></table>');
editor.selection.select(editor.dom.select('table')[0], true);
equal(editor.dom.getParent(editor.selection.getStart(), 'td').id, 'a', 'Expand to text content 2 (start)');
equal(editor.dom.getParent(editor.selection.getEnd(), 'td').id, 'b', 'Expand to text content 2 (end)');
});
test('getNode', function() {
var rng;
editor.setContent('<p id="p1"><span id="s1">span1</span> word <span id="s2">span2</span> word <span id="s3">span3</span></p>');
rng = editor.dom.createRng();
rng.setStart(editor.dom.get('s1').firstChild, 0);
rng.setEnd(editor.dom.get('s1').nextSibling, 0);
editor.selection.setRng(rng);
deepEqual(editor.selection.getNode(), editor.dom.get('s1'), 'Detect selection ends immediately after node at start of paragraph.');
rng = editor.dom.createRng();
rng.setStart(editor.dom.get('s2').previousSibling, editor.dom.get('s2').previousSibling.length);
rng.setEnd(editor.dom.get('s2').nextSibling, 0);
editor.selection.setRng(rng);
deepEqual(editor.selection.getNode(), editor.dom.get('s2'), 'Detect selection immediately surrounds node in middle of paragraph.');
rng = editor.dom.createRng();
rng.setStart(editor.dom.get('s3').previousSibling, editor.dom.get('s3').previousSibling.length);
rng.setEnd(editor.dom.get('s3').lastChild, editor.dom.get('s3').lastChild.length);
editor.selection.setRng(rng);
deepEqual(editor.selection.getNode(), editor.dom.get('s3'), 'Detect selection starts immediately before node at end of paragraph.');
rng = editor.dom.createRng();
rng.setStart(editor.dom.get('s2').previousSibling, editor.dom.get('s2').previousSibling.length);
rng.setEnd(editor.dom.get('s3').lastChild, editor.dom.get('s3').lastChild.length);
editor.selection.setRng(rng);
deepEqual(editor.selection.getNode(), editor.dom.get('p1'), 'Detect selection wrapping multiple nodes does not collapse.');
});
test('normalize to text node from document', function() {
var rng;
if (tinymce.isOpera || tinymce.isIE) {
ok(true, "Skipped on Opera/IE since Opera doesn't let you to set the range to document and IE will steal focus.");
return;
}
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getDoc(), 0);
rng.setEnd(editor.getDoc(), 0);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeType, 3, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeType, 3, 'endContainer node type');
equal(rng.endOffset, 0, 'endOffset offset');
});
test('normalize to br from document', function() {
var rng;
if (tinymce.isOpera || tinymce.isIE) {
ok(true, "Skipped on Opera/IE since Opera doesn't let you to set the range to document and IE will steal focus.");
return;
}
editor.setContent('<p><br /></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getDoc(), 0);
rng.setEnd(editor.getDoc(), 0);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
equal(rng.startContainer.nodeType, 1, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeType, 1, 'endContainer node type');
equal(rng.endOffset, 0, 'endOffset offset');
});
// Only run on non IE browsers since it's not an issue on IE
if (!tinymce.isIE) {
test('normalize to text node from body', function() {
var rng;
editor.setContent('<p>text</p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 0);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeType, 3, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeType, 3, 'endContainer node type');
equal(rng.endOffset, 0, 'endOffset offset');
});
test('normalize to br from body', function() {
var rng;
editor.setContent('<p><br /></p>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 0);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
equal(rng.startContainer.nodeType, 1, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeType, 1, 'endContainer node type');
equal(rng.endOffset, 0, 'endOffset offset');
});
test('normalize ignore img', function() {
var rng;
editor.getBody().innerHTML = '<img src="about:blank " />';
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'BODY', 'startContainer node name');
equal(rng.startContainer.nodeType, 1, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeName, 'BODY', 'endContainer node name');
equal(rng.endContainer.nodeType, 1, 'endContainer node type');
equal(rng.endOffset, 1, 'endOffset offset');
});
test('normalize to before/after img', function() {
var rng;
editor.getBody().innerHTML = '<p><img src="about:blank " /></p>';
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
equal(rng.startContainer.nodeType, 1, 'startContainer node type');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
equal(rng.endContainer.nodeType, 1, 'endContainer node type');
equal(rng.endOffset, 1, 'endOffset offset');
});
test('normalize to text node inside P', function() {
var rng;
editor.getBody().innerHTML = '<p>abc</p>';
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeName, '#text', 'endContainer node name');
equal(rng.endOffset, 3, 'endOffset offset');
});
test('normalize lean left if at the start of text node', function() {
var rng;
editor.getBody().innerHTML = '<p><b>a</b><i>b</i></p>';
setSelection('i', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
equal(rng.startContainer.parentNode.nodeName, 'B');
equal(rng.startOffset, 1, 'startContainer offset');
equal(rng.endContainer.nodeName, '#text');
equal(rng.endContainer.parentNode.nodeName, 'B');
equal(rng.endOffset, 1, 'endOffset offset');
});
test('normalize lean start to the right if at end of text node', function() {
var rng;
editor.getBody().innerHTML = '<p><b>a</b><i>b</i></p>';
setSelection('b', 1, 'i', 1);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
equal(rng.startContainer.parentNode.nodeName, 'I');
equal(rng.startOffset, 0, 'startContainer offset');
equal(rng.endContainer.nodeName, '#text');
equal(rng.endContainer.parentNode.nodeName, 'I');
equal(rng.endOffset, 1, 'endOffset offset');
});
test('normalize lean left but break before br', function() {
var rng;
editor.getBody().innerHTML = '<p>a<br><b>b</b></p>';
setSelection('b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeValue, 'b');
equal(rng.startOffset, 0);
});
test('normalize lean left but break before img', function() {
var rng;
editor.getBody().innerHTML = '<p>a<img><b>b</b></p>';
setSelection('b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeValue, 'b');
equal(rng.startOffset, 0);
});
test('normalize lean left but don\'t walk out the parent block', function() {
var rng;
editor.getBody().innerHTML = '<p>a</p><p><b>b</b></p>';
setSelection('b', 0);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeValue, 'b');
equal(rng.startOffset, 0);
});
test('normalize lean left into empty inline elements when caret is before br', function() {
var rng;
editor.getBody().innerHTML = '<p><i><b></b></i><br /></p>';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'B');
equal(rng.startOffset, 0);
});
test('normalize don\'t lean left into empty inline elements if there is a br element after caret', function() {
var rng;
editor.getBody().innerHTML = '<p><i><b></b></i><br /><br /></p>';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 2);
});
test('normalize don\'t lean left into empty inline elements if there is a br element before caret', function() {
var rng;
editor.getBody().innerHTML = '<p><i><b><br /></b></i><br /></p>';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild.lastChild);
rng.setEndBefore(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'P');
equal(rng.startOffset, 1);
});
test('normalize don\'t move start/end if it\'s before/after table', function() {
var rng;
editor.getBody().innerHTML = '<table><tr><td>X</td></tr></table>';
rng = editor.dom.createRng();
rng.setStartBefore(editor.getBody().firstChild);
rng.setEndAfter(editor.getBody().lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'BODY');
equal(rng.startOffset, 0);
equal(rng.endContainer.nodeName, 'BODY');
equal(rng.endOffset, 1);
});
test('normalize after paragraph', function() {
var rng;
editor.getBody().innerHTML = '<p>a</p>';
rng = editor.dom.createRng();
rng.setStartAfter(editor.getBody().firstChild);
rng.setEndAfter(editor.getBody().lastChild);
editor.selection.setRng(rng);
editor.selection.normalize();
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, '#text');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, '#text');
equal(rng.endOffset, 1);
});
}
test('custom elements', function() {
var rng;
editor.setContent('<custom1>test</custom1><custom2>test</custom2>');
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 2);
editor.selection.setRng(rng);
equal(editor.selection.getContent(), '<custom1>test</custom1><custom2>test</custom2>');
});
test('selectorChanged', function() {
var newState, newArgs;
editor.selection.selectorChanged('a[href]', function(state, args) {
newState = state;
newArgs = args;
});
editor.getBody().innerHTML = '<p><a href="#">text</a></p>';
setSelection('a', 0, 'a', 4);
editor.nodeChanged();
ok(newState);
equal(newArgs.selector, 'a[href]');
equal(newArgs.node, editor.getBody().firstChild.firstChild);
equal(newArgs.parents.length, 2);
editor.getBody().innerHTML = '<p>text</p>';
setSelection('p', 0, 'p', 4);
editor.nodeChanged();
equal(newArgs.selector, 'a[href]');
equal(newArgs.node, editor.getBody().firstChild);
equal(newArgs.parents.length, 1);
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
fix_list_elements : 0,
fix_table_elements : 0,
forced_root_block : '',
entities : 'raw',
valid_styles : {
'*' : 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display'
},
custom_elements : 'custom1,~custom2',
extended_valid_elements : 'custom1,custom2',
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Unit tests for tinymce.dom.Selection</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,515 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for tinymce.dom.Serializer</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var DOM = tinymce.DOM;
QUnit.config.reorder = false;
module("tinymce.dom.Serializer", {
});
test('Schema rules', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(8);
ser.setRules('@[id|title|class|style],div,img[src|alt|-style|border],span,hr');
DOM.setHTML('test', '<img title="test" src="file.gif" data-mce-src="file.gif" alt="test" border="0" style="border: 1px solid red" class="test" /><span id="test2">test</span><hr />');
equal(ser.serialize(DOM.get('test')), '<div id="test"><img title="test" class="test" src="file.gif" alt="test" border="0" /><span id="test2">test</span><hr /></div>', 'Global rule');
ser.setRules('*a[*],em/i[*],strong/b[*i*]');
DOM.setHTML('test', '<a href="test" data-mce-href="test">test</a><strong title="test" class="test">test2</strong><em title="test">test3</em>');
equal(ser.serialize(DOM.get('test')), '<a href="test">test</a><strong title="test">test2</strong><em title="test">test3</em>', 'Wildcard rules');
ser.setRules('br,hr,input[type|name|value],div[id],span[id],strong/b,a,em/i,a[!href|!name],img[src|border=0|title={$uid}]');
DOM.setHTML('test', '<br /><hr /><input type="text" name="test" value="val" class="no" /><span id="test2" class="no"><b class="no">abc</b><em class="no">123</em></span>123<a href="file.html" data-mce-href="file.html">link</a><a name="anchor"></a><a>no</a><img src="file.gif" data-mce-src="file.gif" />');
equal(ser.serialize(DOM.get('test')), '<div id="test"><br /><hr /><input type="text" name="test" value="val" /><span id="test2"><strong>abc</strong><em>123</em></span>123<a href="file.html">link</a><a name="anchor"></a>no<img src="file.gif" border="0" title="mce_0" /></div>', 'Output name and attribute rules');
ser.setRules('a[href|target<_blank?_top|title:forced value]');
DOM.setHTML('test', '<a href="file.htm" data-mce-href="file.htm" target="_blank" title="title">link</a><a href="#" data-mce-href="#" target="test">test2</a>');
equal(ser.serialize(DOM.get('test')), '<a href="file.htm" target="_blank" title="forced value">link</a><a href="#" title="forced value">test2</a>');
ser.setRules('img[src|border=0|alt=]');
DOM.setHTML('test', '<img src="file.gif" data-mce-src="file.gif" border="0" alt="" />');
equal(ser.serialize(DOM.get('test')), '<img src="file.gif" border="0" alt="" />', 'Default attribute with empty value');
ser.setRules('img[src|border=0|alt=],*[*]');
DOM.setHTML('test', '<img src="file.gif" data-mce-src="file.gif" /><hr />');
equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="file.gif" border="0" alt="" /><hr /></div>');
ser = new tinymce.dom.Serializer({
valid_elements : 'img[src|border=0|alt=]',
extended_valid_elements : 'div[id],img[src|alt=]'
});
DOM.setHTML('test', '<img src="file.gif" data-mce-src="file.gif" alt="" />');
equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="file.gif" alt="" /></div>');
ser = new tinymce.dom.Serializer({invalid_elements : 'hr,br'});
DOM.setHTML('test', '<img src="file.gif" data-mce-src="file.gif" /><hr /><br />');
equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="file.gif" alt="" /></div>');
});
test('Entity encoding', function() {
var ser;
expect(4);
ser = new tinymce.dom.Serializer({entity_encoding : 'numeric'});
DOM.setHTML('test', '&lt;&gt;&amp;&quot;&nbsp;&aring;&auml;&ouml;');
equal(ser.serialize(DOM.get('test')), '<div id="test">&lt;&gt;&amp;"&#160;&#229;&#228;&#246;</div>');
ser = new tinymce.dom.Serializer({entity_encoding : 'named'});
DOM.setHTML('test', '&lt;&gt;&amp;&quot;&nbsp;&aring;&auml;&ouml;');
equal(ser.serialize(DOM.get('test')), '<div id="test">&lt;&gt;&amp;"&nbsp;&aring;&auml;&ouml;</div>');
ser = new tinymce.dom.Serializer({entity_encoding : 'named+numeric', entities : '160,nbsp,34,quot,38,amp,60,lt,62,gt'});
DOM.setHTML('test', '&lt;&gt;&amp;&quot;&nbsp;&aring;&auml;&ouml;');
equal(ser.serialize(DOM.get('test')), '<div id="test">&lt;&gt;&amp;"&nbsp;&#229;&#228;&#246;</div>');
ser = new tinymce.dom.Serializer({entity_encoding : 'raw'});
DOM.setHTML('test', '&lt;&gt;&amp;&quot;&nbsp;&aring;&auml;&ouml;');
equal(ser.serialize(DOM.get('test')), '<div id="test">&lt;&gt;&amp;"\u00a0\u00e5\u00e4\u00f6</div>');
});
test('Form elements (general)', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(5);
ser.setRules('form[method],label[for],input[type|name|value|checked|disabled|readonly|length|maxlength],select[multiple],option[value|selected],textarea[name|disabled|readonly]');
DOM.setHTML('test', '<input type="text" />');
equal(ser.serialize(DOM.get('test')), '<input type="text" />');
DOM.setHTML('test', '<input type="text" value="text" length="128" maxlength="129" />');
equal(ser.serialize(DOM.get('test')), '<input type="text" value="text" length="128" maxlength="129" />');
DOM.setHTML('test', '<form method="post"><input type="hidden" name="method" value="get" /></form>');
equal(ser.serialize(DOM.get('test')), '<form method="post"><input type="hidden" name="method" value="get" /></form>');
DOM.setHTML('test', '<label for="test">label</label>');
equal(ser.serialize(DOM.get('test')), '<label for="test">label</label>');
DOM.setHTML('test', '<input type="checkbox" value="test" /><input type="button" /><textarea></textarea>');
equal(ser.serialize(DOM.get('test')), '<input type="checkbox" value="test" /><input type="button" /><textarea></textarea>');
});
test('Form elements (checkbox)', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(4);
ser.setRules('form[method],label[for],input[type|name|value|checked|disabled|readonly|length|maxlength],select[multiple],option[value|selected]');
DOM.setHTML('test', '<input type="checkbox" value="1">');
equal(ser.serialize(DOM.get('test')), '<input type="checkbox" value="1" />');
DOM.setHTML('test', '<input type="checkbox" value="1" checked disabled readonly>');
equal(ser.serialize(DOM.get('test')), '<input type="checkbox" value="1" checked="checked" disabled="disabled" readonly="readonly" />');
DOM.setHTML('test', '<input type="checkbox" value="1" checked="1" disabled="1" readonly="1">');
equal(ser.serialize(DOM.get('test')), '<input type="checkbox" value="1" checked="checked" disabled="disabled" readonly="readonly" />');
DOM.setHTML('test', '<input type="checkbox" value="1" checked="true" disabled="true" readonly="true">');
equal(ser.serialize(DOM.get('test')), '<input type="checkbox" value="1" checked="checked" disabled="disabled" readonly="readonly" />');
});
test('Form elements (select)', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(7);
ser.setRules('form[method],label[for],input[type|name|value|checked|disabled|readonly|length|maxlength],select[multiple],option[value|selected]');
DOM.setHTML('test', '<select><option value="1">test1</option><option value="2" selected>test2</option></select>');
equal(ser.serialize(DOM.get('test')), '<select><option value="1">test1</option><option value="2" selected="selected">test2</option></select>');
DOM.setHTML('test', '<select><option value="1">test1</option><option selected="1" value="2">test2</option></select>');
equal(ser.serialize(DOM.get('test')), '<select><option value="1">test1</option><option value="2" selected="selected">test2</option></select>');
DOM.setHTML('test', '<select><option value="1">test1</option><option value="2" selected="true">test2</option></select>');
equal(ser.serialize(DOM.get('test')), '<select><option value="1">test1</option><option value="2" selected="selected">test2</option></select>');
DOM.setHTML('test', '<select multiple></select>');
equal(ser.serialize(DOM.get('test')), '<select multiple="multiple"></select>');
DOM.setHTML('test', '<select multiple="multiple"></select>');
equal(ser.serialize(DOM.get('test')), '<select multiple="multiple"></select>');
DOM.setHTML('test', '<select multiple="1"></select>');
equal(ser.serialize(DOM.get('test')), '<select multiple="multiple"></select>');
DOM.setHTML('test', '<select></select>');
equal(ser.serialize(DOM.get('test')), '<select></select>');
});
test('List elements', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(5);
ser.setRules('ul[compact],ol,li');
DOM.setHTML('test', '<ul compact></ul>');
equal(ser.serialize(DOM.get('test')), '<ul compact="compact"></ul>');
DOM.setHTML('test', '<ul compact="compact"></ul>');
equal(ser.serialize(DOM.get('test')), '<ul compact="compact"></ul>');
DOM.setHTML('test', '<ul compact="1"></ul>');
equal(ser.serialize(DOM.get('test')), '<ul compact="compact"></ul>');
DOM.setHTML('test', '<ul></ul>');
equal(ser.serialize(DOM.get('test')), '<ul></ul>');
DOM.setHTML('test', '<ol><li>a</li><ol><li>b</li><li>c</li></ol><li>e</li></ol>');
equal(ser.serialize(DOM.get('test')), '<ol><li>a<ol><li>b</li><li>c</li></ol></li><li>e</li></ol>');
});
test('Tables', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(4);
ser.setRules('table,tr,td[nowrap]');
DOM.setHTML('test', '<table><tr><td></td></tr></table>');
equal(ser.serialize(DOM.get('test')), '<table><tr><td></td></tr></table>');
DOM.setHTML('test', '<table><tr><td nowrap></td></tr></table>');
equal(ser.serialize(DOM.get('test')), '<table><tr><td nowrap="nowrap"></td></tr></table>');
DOM.setHTML('test', '<table><tr><td nowrap="nowrap"></td></tr></table>');
equal(ser.serialize(DOM.get('test')), '<table><tr><td nowrap="nowrap"></td></tr></table>');
DOM.setHTML('test', '<table><tr><td nowrap="1"></td></tr></table>');
equal(ser.serialize(DOM.get('test')), '<table><tr><td nowrap="nowrap"></td></tr></table>');
});
test('Styles', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(1);
ser.setRules('*[*]');
DOM.setHTML('test', '<span style="border: 1px solid red" data-mce-style="border: 1px solid red;">test</span>');
equal(ser.serialize(DOM.get('test')), '<div id="test"><span style="border: 1px solid red;">test</span></div>');
});
test('Comments', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(1);
ser.setRules('*[*]');
DOM.setHTML('test', '<!-- abc -->');
equal(ser.serialize(DOM.get('test')), '<div id="test"><!-- abc --></div>');
});
test('Non HTML elements and attributes', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(2);
ser.setRules('*[*]');
ser.schema.addValidChildren('+div[prefix:test]');
DOM.setHTML('test', '<div test:attr="test">test</div>');
equal(ser.serialize(DOM.get('test'), {getInner : 1}), '<div test:attr="test">test</div>');
DOM.setHTML('test', 'test1<prefix:test>Test</prefix:test>test2');
equal(ser.serialize(DOM.get('test')), '<div id="test">test1<prefix:test>Test</prefix:test>test2</div>');
});
test('Padd empty elements', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(1);
ser.setRules('#p');
DOM.setHTML('test', '<p>test</p><p></p>');
equal(ser.serialize(DOM.get('test')), '<p>test</p><p>&nbsp;</p>');
});
test('Remove empty elements', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(1);
ser.setRules('-p');
DOM.setHTML('test', '<p>test</p><p></p>');
equal(ser.serialize(DOM.get('test')), '<p>test</p>');
});
test('Pre/post process events', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(3);
ser.setRules('div[id],span[id|class],a[href],b[class]');
ser.onPreProcess = function(o) {
equal(o.test, 'abc');
DOM.setAttrib(o.node.getElementsByTagName('span')[0], 'class', 'abc');
};
ser.onPostProcess = function(o) {
equal(o.test, 'abc');
o.content = o.content.replace(/<b>/g, '<b class="123">');
};
DOM.setHTML('test', '<span id="test2"><b>abc</b></span>123<a href="file.html" data-mce-href="file.html">link</a>');
equal(ser.serialize(DOM.get('test'), {test : 'abc'}), '<div id="test"><span id="test2" class="abc"><b class="123">abc</b></span>123<a href="file.html">link</a></div>');
});
test('Script with non JS type attribute', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<s'+'cript type="mylanguage"></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript type="mylanguage"></s'+'cript>');
});
test('Script with tags inside a comment', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<s'+'cript>// <img src="test"><a href="#"></a></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n// <img src="test"><a href="#"></a>\n// ]]></s'+'cript>');
});
test('Script with less than', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<s'+'cript>1 < 2;</s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with type attrib and less than', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<s'+'cript type="text/javascript">1 < 2;</s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<script>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with whitespace in beginning/end', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>\n\t1 < 2;\n\t if (2 < 1)\n\t\talert(1);\n</s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n\t1 < 2;\n\t if (2 < 1)\n\t\talert(1);\n// ]]></s'+'cript>');
});
test('Script with a HTML comment and less than', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script><!-- 1 < 2; // --></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with white space in beginning, comment and less than', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>\n\n<!-- 1 < 2;\n\n--></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with comments and cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>// <![CDATA[1 < 2; // ]]></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script><![CDATA[1 < 2; ]]></s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script whitespace in beginning/end and cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>\n\n<![CDATA[\n\n1 < 2;\n\n]]>\n\n</s'+'cript>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s'+'cript>// <![CDATA[\n1 < 2;\n// ]]></s'+'cript>');
});
test('Script with src attr', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script src="test.js" data-mce-src="test.js"></s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<s'+'cript src="test.js"></s'+'cript>');
});
test('Script with HTML comment, comment and CDATA', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script><!--// <![CDATA[var hi = "hello";// ]]>--></s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<script>// <![CDATA[\nvar hi = \"hello\";\n// ]]></s'+'cript>');
});
test('Script with block comment around cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>/* <![CDATA[ */\nvar hi = "hello";\n/* ]]> */</s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<script>// <![CDATA[\nvar hi = \"hello\";\n// ]]></s'+'cript>');
});
test('Script with html comment and block comment around cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script><!-- /* <![CDATA[ */\nvar hi = "hello";\n/* ]]>*/--></s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<script>// <![CDATA[\nvar hi = \"hello\";\n// ]]></s'+'cript>');
});
test('Script with line comment and html comment', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>// <!--\nvar hi = "hello";\n// --></s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<script>// <![CDATA[\nvar hi = \"hello\";\n// ]]></s'+'cript>');
});
test('Script with block comment around html comment', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('script[type|language|src]');
DOM.setHTML('test', '<script>/* <!-- */\nvar hi = "hello";\n/*-->*/</s'+'cript>');
equal(ser.serialize(DOM.get('test')), '<script>// <![CDATA[\nvar hi = \"hello\";\n// ]]></s'+'cript>');
});
test('Protected blocks', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(3);
ser.setRules('noscript[test]');
DOM.setHTML('test', '<!--mce:protected ' + escape('<noscript test="test"><br></noscript>') + '-->');
equal(ser.serialize(DOM.get('test')), '<noscript test="test"><br></noscript>');
DOM.setHTML('test', '<!--mce:protected ' + escape('<noscript><br></noscript>') + '-->');
equal(ser.serialize(DOM.get('test')), '<noscript><br></noscript>');
DOM.setHTML('test', '<!--mce:protected ' + escape('<noscript><!-- text --><br></noscript>') + '-->');
equal(ser.serialize(DOM.get('test')), '<noscript><!-- text --><br></noscript>');
});
test('Style with whitespace at beginning', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true, valid_children: '+body[style]'});
ser.setRules('style');
DOM.setHTML('test', '<style> body { background:#fff }</style>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<style><!--\n body { background:#fff }\n--></style>');
});
test('Style with cdata', 1, function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true, valid_children: '+body[style]'});
ser.setRules('style');
DOM.setHTML('test', '<style>\r\n<![CDATA[\r\n body { background:#fff }]]></style>');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<style><!--\nbody { background:#fff }\n--></style>');
});
test('CDATA', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
expect(2);
ser.setRules('span');
DOM.setHTML('test', '123<!--[CDATA[<test>]]-->abc');
equal(ser.serialize(DOM.get('test')), '123<![CDATA[<test>]]>abc');
DOM.setHTML('test', '123<!--[CDATA[<te\n\nst>]]-->abc');
equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '123<![CDATA[<te\n\nst>]]>abc');
});
test('BR at end of blocks', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('ul,li,br');
DOM.setHTML('test', '<ul><li>test<br /></li><li>test<br /></li><li>test<br /></li></ul>');
equal(ser.serialize(DOM.get('test')), '<ul><li>test</li><li>test</li><li>test</li></ul>');
});
test('Map elements', function() {
var ser = new tinymce.dom.Serializer({fix_list_elements : true});
ser.setRules('map[id|name],area[shape|coords|href|target|alt]');
DOM.setHTML('test', '<map id="planetmap" name="planetmap"><area shape="rect" coords="0,0,82,126" href="sun.htm" data-mce-href="sun.htm" target="_blank" alt="sun" /></map>');
equal(ser.serialize(DOM.get('test')).toLowerCase(), '<map id="planetmap" name="planetmap"><area shape="rect" coords="0,0,82,126" href="sun.htm" target="_blank" alt="sun" /></map>');
});
test('Custom elements', function() {
var ser = new tinymce.dom.Serializer({
custom_elements: 'custom1,~custom2',
valid_elements: 'custom1,custom2'
});
document.createElement('custom1');
document.createElement('custom2');
DOM.setHTML('test', '<p><custom1>c1</custom1><custom2>c2</custom2></p>');
equal(ser.serialize(DOM.get('test')), '<custom1>c1</custom1><custom2>c2</custom2>');
});
test('Remove internal classes', function() {
var ser = new tinymce.dom.Serializer({
valid_elements: 'span[class]'
});
DOM.setHTML('test', '<span class="a mce-item-X mce-item-selected b"></span>');
equal(ser.serialize(DOM.get('test')), '<span class="a b"></span>');
DOM.setHTML('test', '<span class="a mce-item-X"></span>');
equal(ser.serialize(DOM.get('test')), '<span class="a"></span>');
DOM.setHTML('test', '<span class="mce-item-X"></span>');
equal(ser.serialize(DOM.get('test')), '<span></span>');
DOM.setHTML('test', '<span class="mce-item-X b"></span>');
equal(ser.serialize(DOM.get('test')), '<span class=" b"></span>');
DOM.setHTML('test', '<span class="b mce-item-X"></span>');
equal(ser.serialize(DOM.get('test')), '<span class="b"></span>');
});
</script>
<h1 id="qunit-header">Unit tests for tinymce.dom.Serializer</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<div id="test"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,586 @@
<!DOCTYPE html>
<html>
<head>
<title>Unit tests for DOM Selection IE implementation</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
</head>
<body>
<script>
var editor, rng;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("IE Selection", {
autostart: false
});
if (tinymce.isIE && !window.getSelection) {
test("Selection of element containing text", function(){
expect(5);
editor.setContent('<p>123</p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, '#text', 'Start container is text node');
equal(rng.endContainer.nodeName, '#text', 'End container is text node');
equal(rng.startOffset, 0, 'Start of text node');
equal(rng.endOffset, 3, 'End of text node');
equal(editor.dom.getOuterHTML(rng.cloneContents()), '123', 'Contents matches');
});
test("Single image selection", function(){
expect(6);
editor.setContent('<p><img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartBefore(editor.dom.select('img')[0]);
rng.setEndAfter(editor.dom.select('img')[0]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P', 'Check startContainer');
equal(rng.endContainer.nodeName, 'P', 'Check endContainer');
equal(rng.startOffset, 0, 'Check startOffset');
equal(rng.endOffset, 1, 'Check endOffset');
equal(cleanHtml(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase()), '<img src="about:blank">', 'Check contents');
ok(editor.selection.getRng().item, 'Check if it\'s a control selection');
});
test("Multiple image selection", function(){
expect(6);
editor.setContent('<p><img src="about:blank" /><img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartBefore(editor.dom.select('img')[0]);
rng.setEndAfter(editor.dom.select('img')[1]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P');
equal(rng.endContainer.nodeName, 'P');
equal(rng.startOffset, 0);
equal(rng.endOffset, 2);
equal(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase(), '<img src="about:blank"><img src="about:blank">');
ok(editor.selection.getRng().parentElement, 'Is text selection');
});
test("Text node selection", function(){
expect(5);
editor.setContent('<p>1234</p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().firstChild.firstChild, 3);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, '#text');
equal(rng.endContainer.nodeName, '#text');
equal(rng.startOffset, 1);
equal(rng.endOffset, 3);
equal(editor.dom.getOuterHTML(rng.cloneContents()), '23');
});
test("Text node selection between two elements", function(){
expect(5);
editor.setContent('<p>1234</p><p>abcd</p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEnd(editor.getBody().childNodes[1].firstChild, 3);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, '#text');
equal(rng.endContainer.nodeName, '#text');
equal(rng.startOffset, 1);
equal(rng.endOffset, 3);
equal(editor.dom.getOuterHTML(rng.cloneContents()).replace(/[\r\n]/g, '').toLowerCase(), '<p>234</p><p>abc</p>');
editor.setContent('<p>1</p><p>1234</p><p>abcd</p><p>2</p>', {
format: 'raw'
});
/*
rng = editor.dom.createRng();
rng.setStartBefore(editor.dom.select('p')[1]);
rng.setEndAfter(editor.dom.select('p')[2]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'BODY', "startContainer type check");
equal(rng.startOffset, 1, "startOffset doesn't match");
equal(rng.endContainer.nodeName, 'BODY', "endContainer type check");
equal(rng.endOffset, 3, "endOffset doesn't match");
equal(editor.dom.getOuterHTML(rng.cloneContents()).replace(/[\r\n]/g, '').toLowerCase(), '<p>1234</p><p>abcd</p>');*/
});
test("Mixed selection start at element end at text", function(){
expect(5);
editor.setContent('<p><img src="about:blank" />text</p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartBefore(editor.dom.select('img')[0]);
rng.setEnd(editor.getBody().firstChild.lastChild, 3);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P');
equal(rng.endContainer.nodeName, '#text');
equal(rng.startOffset, 0);
equal(rng.endOffset, 3);
equal(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase(), '<img src="about:blank">tex');
});
test("Mixed selection start at text end at element", function(){
expect(5);
editor.setContent('<p>text<img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild.firstChild, 1);
rng.setEndAfter(editor.getBody().firstChild.lastChild);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, '#text');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'P');
equal(rng.endOffset, 2);
equal(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase(), 'ext<img src="about:blank">');
});
test("Caret position before image", function(){
expect(4);
editor.setContent('<p><img src="about:blank" /><img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartBefore(editor.dom.select('img')[0]);
rng.setEndBefore(editor.dom.select('img')[0]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P');
equal(rng.endContainer.nodeName, 'P');
equal(rng.startOffset, 0);
equal(rng.endOffset, 0);
});
test("Caret position between images", function(){
expect(4);
editor.setContent('<p><img src="about:blank" /><img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartAfter(editor.dom.select('img')[0]);
rng.setEndAfter(editor.dom.select('img')[0]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P');
equal(rng.endContainer.nodeName, 'P');
equal(rng.startOffset, 1);
equal(rng.endOffset, 1);
});
test("Caret position after image", function(){
expect(4);
editor.setContent('<p><img src="about:blank" /><img src="about:blank" /></p>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStartAfter(editor.dom.select('img')[1]);
rng.setEndAfter(editor.dom.select('img')[1]);
editor.selection.setRng(rng);
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'P');
equal(rng.endContainer.nodeName, 'P');
equal(rng.startOffset, 2);
equal(rng.endOffset, 2);
});
test("Selection of empty text element", function(){
expect(6);
editor.setContent('<div></div>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody(), 0);
rng.setEnd(editor.getBody(), 1);
editor.selection.setRng(rng);
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'BODY');
equal(rng.endContainer.nodeName, 'BODY');
equal(rng.startOffset, 0);
equal(rng.endOffset, 1);
equal(rng.startContainer.childNodes[0].innerHTML, '');
equal(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase(), '<div></div>');
});
test("Selection of empty text element with caret inside", function(){
expect(6);
editor.setContent('<div></div>', {
format: 'raw'
});
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 0);
rng.setEnd(editor.getBody().firstChild, 0);
editor.selection.setRng(rng);
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, 'DIV');
equal(rng.endContainer.nodeName, 'DIV');
equal(rng.startOffset, 0);
equal(rng.endOffset, 0);
equal(rng.startContainer.innerHTML, '');
equal(editor.dom.getOuterHTML(rng.cloneContents()).toLowerCase(), '');
});
/*test("Caret position before table", function() {
var table, rng;
editor.focus();
editor.setContent('<p>Before</p><table id="table" border="1"><tr><td>Cell 1</td><td>Cell 2</td></tr><tr><td>Cell 3</td><td>Cell 4</td></tr></table><p>After</p>');
table = editor.dom.get('table');
rng = editor.selection.getRng();
rng.moveToElementText(table);
rng.move('character', -1);
rng.select();
rng = editor.selection.getRng(1);
equal(rng.startContainer.nodeName, 'BODY');
equal(rng.startOffset, 1);
equal(rng.endContainer.nodeName, 'BODY');
equal(rng.endOffset, 1);
});*/
test("Selection end within empty element", function() {
var rng;
editor.focus();
editor.getBody().innerHTML = '<p>123</p><p></p>';
rng = editor.execCommand('SelectAll');
rng = editor.selection.getRng(true);
equal(rng.startContainer.nodeName, '#text');
equal(rng.startOffset, 0);
equal(rng.endContainer.nodeName, 'BODY');
equal(rng.endOffset, 2);
});
test("Selection after paragraph", function() {
var rng;
editor.focus();
editor.getBody().innerHTML = '<p>123</p><p>abcd</p>';
rng = editor.dom.createRng();
rng.setStart(editor.getBody().firstChild, 1);
rng.setEnd(editor.getBody().firstChild, 1);
editor.selection.setRng(rng);
rng = editor.selection.getRng(true);
ok(rng.startContainer == rng.endContainer);
equal(rng.startContainer.nodeName, '#text');
equal(rng.startOffset, 3);
equal(rng.endContainer.nodeName, '#text');
equal(rng.endOffset, 3);
});
test("Selection of text outside of a block element", function() {
var r;
editor.settings.forced_root_block = '';
editor.focus();
editor.getBody().innerHTML = '<ul><li>Item</li></ul>Text';
r = editor.dom.createRng();
r.setStart(editor.getBody().lastChild, 2);
r.setEnd(editor.getBody().lastChild, 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().lastChild, "Start container is text node.");
equal(r.endContainer, editor.getBody().lastChild, "End container is text node.");
equal(r.startOffset, 2);
equal(r.endOffset, 2);
equal(editor.selection.getStart(), editor.getBody(), "Selection start is body.");
deepEqual(editor.selection.getSelectedBlocks(), [], "No blocks selected.");
});
test("Resizable element text selection", function() {
var r;
editor.getBody().innerHTML = '<div style="width: 100px; height:100px;"><table><tr><td>.</td></tr></table>abc</div>';
editor.focus();
r = editor.dom.createRng();
r.setStart(editor.getBody().firstChild.lastChild, 1);
r.setEnd(editor.getBody().firstChild.lastChild, 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().firstChild.lastChild, "Start container is text node.");
equal(r.endContainer, editor.getBody().firstChild.lastChild, "End container is text node.");
equal(r.startOffset, 1);
equal(r.endOffset, 2);
});
test("Resizable element before table selection", function() {
var r;
editor.getBody().innerHTML = '<div style="width: 100px; height:100px;"><table><tr><td>.</td></tr></table></div>';
editor.focus();
r = editor.dom.createRng();
r.setStart(editor.getBody().firstChild, 0);
r.setEnd(editor.getBody().firstChild, 0);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().firstChild, "Start container is div node.");
equal(r.endContainer, editor.getBody().firstChild, "End container is div node.");
equal(r.startOffset, 0);
equal(r.endOffset, 0);
});
test("Fragmented text nodes after element", function() {
var r;
editor.getBody().innerHTML = '<b>x</b>';
editor.getBody().appendChild(editor.getDoc().createTextNode('1'));
editor.getBody().appendChild(editor.getDoc().createTextNode('23'));
editor.getBody().appendChild(editor.getDoc().createTextNode('456'));
editor.getBody().appendChild(editor.getDoc().createTextNode('7890'));
editor.focus();
r = editor.dom.createRng();
r.setStart(editor.getBody().lastChild, 1);
r.setEnd(editor.getBody().lastChild, 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().lastChild, "Start container is last text node.");
equal(r.endContainer, editor.getBody().lastChild, "End container is last text node.");
equal(r.startOffset, 1);
equal(r.endOffset, 1);
r = editor.dom.createRng();
r.setStart(editor.getBody().childNodes[2], 2);
r.setEnd(editor.getBody().childNodes[2], 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().childNodes[2], "Start container is second text node.");
equal(r.endContainer, editor.getBody().childNodes[2], "End container is second text node.");
equal(r.startOffset, 2);
equal(r.endOffset, 2);
r = editor.dom.createRng();
r.setStart(editor.getBody().childNodes[3], 0);
r.setEnd(editor.getBody().childNodes[3], 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().childNodes[2], "Start container is second text node (lean left).");
equal(r.endContainer, editor.getBody().childNodes[3], "End container is third text node.");
equal(r.startOffset, 2);
equal(r.endOffset, 1);
});
test("Fragmented text nodes before element", function() {
var r;
editor.getBody().innerHTML = '';
editor.getBody().appendChild(editor.getDoc().createTextNode('1'));
editor.getBody().appendChild(editor.getDoc().createTextNode('23'));
editor.getBody().appendChild(editor.getDoc().createTextNode('456'));
editor.getBody().appendChild(editor.getDoc().createTextNode('7890'));
editor.getBody().appendChild(editor.dom.create('b', null, 'x'));
editor.focus();
r = editor.dom.createRng();
r.setStart(editor.getBody().childNodes[3], 1);
r.setEnd(editor.getBody().childNodes[3], 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().childNodes[3], "Start container is last text node.");
equal(r.endContainer, editor.getBody().childNodes[3], "End container is last text node.");
equal(r.startContainer.nodeValue, '7890');
equal(r.startOffset, 1);
equal(r.endOffset, 1);
r = editor.dom.createRng();
r.setStart(editor.getBody().childNodes[1], 2);
r.setEnd(editor.getBody().childNodes[1], 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().childNodes[2], "Start container is second text node. (lean right)");
equal(r.endContainer, editor.getBody().childNodes[2], "End container is second text node.");
equal(r.startContainer.nodeValue, '456');
equal(r.startOffset, 0);
equal(r.endOffset, 0);
r = editor.dom.createRng();
r.setStart(editor.getBody().childNodes[1], 0);
r.setEnd(editor.getBody().childNodes[1], 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody().childNodes[1], "Start container is second text node.");
equal(r.endContainer, editor.getBody().childNodes[1], "End container is third text node.");
equal(r.startContainer.nodeValue, '23');
equal(r.endContainer.nodeValue, '23');
equal(r.startOffset, 0);
equal(r.endOffset, 1);
});
test("Non contentEditable elements", function() {
var r;
editor.getBody().innerHTML = '<span contentEditable="false">a</span><span contentEditable="false">a</span><span contentEditable="false">a</span>';
editor.focus();
r = editor.dom.createRng();
r.setStart(editor.getBody(), 0);
r.setEnd(editor.getBody(), 0);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody(), "Start container is before first nonEditable.");
equal(r.endContainer, editor.getBody(), "End container is before first nonEditable.");
equal(r.startOffset, 0);
equal(r.endOffset, 0);
r = editor.dom.createRng();
r.setStart(editor.getBody(), 0);
r.setEnd(editor.getBody(), 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody(), "Start container before first nonEditable.");
equal(r.endContainer, editor.getBody(), "End container is after first nonEditable.");
equal(r.startOffset, 0);
equal(r.endOffset, 1);
r = editor.dom.createRng();
r.setStart(editor.getBody(), 0);
r.setEnd(editor.getBody(), 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody(), "Start container before first nonEditable.");
equal(r.endContainer, editor.getBody(), "End container is after second nonEditable.");
equal(r.startOffset, 0);
equal(r.endOffset, 2);
r = editor.dom.createRng();
r.setStart(editor.getBody(), 1);
r.setEnd(editor.getBody(), 1);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody(), "Start container is before second nonEditable.");
equal(r.endContainer, editor.getBody(), "End container is div before second nonEditable.");
equal(r.startOffset, 1);
equal(r.endOffset, 1);
r = editor.dom.createRng();
r.setStart(editor.getBody(), 2);
r.setEnd(editor.getBody(), 2);
editor.selection.setRng(r);
r = editor.selection.getRng(true);
equal(r.startContainer, editor.getBody(), "Start container is after last nonEditable.");
equal(r.endContainer, editor.getBody(), "End container is after last nonEditable.");
equal(r.startOffset, 2);
equal(r.endOffset, 2);
});
} else {
test("Skipped ie_selection tests as not running in IE.", function() {
ok(true, "Dummy assert");
});
}
function getCaretInfo() {
editor.focus();
var rng = editor.selection.getRng(1);
alert(rng.startContainer + " - " + rng.startOffset);
alert(rng.endContainer + " - " + rng.endOffset);
editor.focus();
}
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
<h1 id="qunit-header">Unit tests for DOM Selection IE implementation</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content">
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
<a href="javascript:getCaretInfo();">[getCaretInfo]</a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,120 @@
body, div, h1 { font-family: 'trebuchet ms', verdana, arial; margin: 0; padding: 0 }
body {font-size: 10pt; }
h1 { padding: 15px; font-size: large; background-color: #06b; color: white; }
h1 a { color: white; }
h2 { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal }
.pass { color: green; }
.fail { color: red; }
p.result { margin-left: 1em; }
#banner { height: 2em; border-bottom: 1px solid white; }
h2.pass { background-color: green; }
h2.fail { background-color: red; }
div.testrunner-toolbar { background: #eee; border-top: 1px solid black; padding: 10px; }
ol#tests > li > strong { cursor:pointer; }
div#fx-tests h4 {
background: red;
}
div#fx-tests h4.pass {
background: green;
}
div#fx-tests div.box {
background: red url(data/cow.jpg) no-repeat;
overflow: hidden;
border: 2px solid #000;
}
div#fx-tests div.overflow {
overflow: visible;
}
div.inline {
display: inline;
}
div.autoheight {
height: auto;
}
div.autowidth {
width: auto;
}
div.autoopacity {
opacity: auto;
}
div.largewidth {
width: 100px;
}
div.largeheight {
height: 100px;
}
div.largeopacity {
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100);
}
div.medwidth {
width: 50px;
}
div.medheight {
height: 50px;
}
div.medopacity {
opacity: 0.5;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);
}
div.nowidth {
width: 0px;
}
div.noheight {
height: 0px;
}
div.noopacity {
opacity: 0;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
}
div.hidden {
display: none;
}
div#fx-tests div.widewidth {
background-repeat: repeat-x;
}
div#fx-tests div.wideheight {
background-repeat: repeat-y;
}
div#fx-tests div.widewidth.wideheight {
background-repeat: repeat;
}
div#fx-tests div.noback {
background-image: none;
}
div.chain, div.chain div { width: 100px; height: 20px; position: relative; float: left; }
div.chain div { position: absolute; top: 0px; left: 0px; }
div.chain.test { background: red; }
div.chain.test div { background: green; }
div.chain.out { background: green; }
div.chain.out div { background: red; display: none; }
div#show-tests * { display: none; }

View File

@ -0,0 +1,12 @@
{
"title": "tinymce.dom",
"tests": [
{"title": "DOMUtils", "url": "DOMUtils.html"},
{"title": "DOMUtils (jQuery)", "url": "DOMUtils_jquery.html"},
{"title": "EventUtils", "url": "EventUtils.html"},
{"title": "Range (IE/Native)", "url": "Range.html"},
{"title": "Selection", "url": "Selection.html"},
{"title": "Serializer", "url": "Serializer.html"},
{"title": "TridentSelection (IE)", "url": "TridentSelection.html"}
]
}

View File

@ -0,0 +1,506 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.DomParser tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.DomParser");
QUnit.config.reorder = false;
var schema = new tinymce.html.Schema({valid_elements: '*[class|title]'});
var serializer = new tinymce.html.Serializer({}, schema);
var parser, root;
function countNodes(node, counter) {
var sibling;
if (!counter)
counter = {};
if (node.name in counter) {
counter[node.name]++;
} else
counter[node.name] = 1;
for (sibling = node.firstChild; sibling; sibling = sibling.next) {
countNodes(sibling, counter);
}
return counter;
}
schema.addValidChildren('+body[style]');
test('Parse element', function() {
var parser, root;
expect(7);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<B title="title" class="class">test</B>');
equal(serializer.serialize(root), '<b class="class" title="title">test</b>', 'Inline element');
equal(root.firstChild.type, 1, 'Element type');
equal(root.firstChild.name, 'b', 'Element name');
deepEqual(root.firstChild.attributes, [{name: 'title', value: 'title'}, {name: 'class', value: 'class'}], 'Element attributes');
deepEqual(countNodes(root), {body:1, b:1, '#text':1}, 'Element attributes (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <SCRIPT> \t\r\n a < b > \t\r\n </S' + 'CRIPT> \t\r\n ');
equal(serializer.serialize(root), '<script> \t\r\n a < b > \t\r\n </s' + 'cript>', 'Retain code inside SCRIPT');
deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Retain code inside SCRIPT (count)');
});
test('Whitespace', function() {
expect(12);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <B> \t\r\n test \t\r\n </B> \t\r\n ');
equal(serializer.serialize(root), ' <b> test </b> ', 'Redundant whitespace (inline element)');
deepEqual(countNodes(root), {body:1, b:1, '#text':3}, 'Redundant whitespace (inline element) (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <P> \t\r\n test \t\r\n </P> \t\r\n ');
equal(serializer.serialize(root), '<p>test</p>', 'Redundant whitespace (block element)');
deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'Redundant whitespace (block element) (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <SCRIPT> \t\r\n test \t\r\n </S' + 'CRIPT> \t\r\n ');
equal(serializer.serialize(root), '<script> \t\r\n test \t\r\n </s' + 'cript>', 'Whitespace around and inside SCRIPT');
deepEqual(countNodes(root), {body:1, script:1, '#text':1}, 'Whitespace around and inside SCRIPT (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <STYLE> \t\r\n test \t\r\n </STYLE> \t\r\n ');
equal(serializer.serialize(root), '<style> \t\r\n test \t\r\n </style>', 'Whitespace around and inside STYLE');
deepEqual(countNodes(root), {body:1, style:1, '#text':1}, 'Whitespace around and inside STYLE (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<ul>\n<li>Item 1\n<ul>\n<li>\n \t Indented \t \n</li>\n</ul>\n</li>\n</ul>\n');
equal(serializer.serialize(root), '<ul><li>Item 1<ul><li>Indented</li></ul></li></ul>', 'Whitespace around and inside blocks (ul/li)');
deepEqual(countNodes(root), {body:1, li:2, ul:2, '#text':2}, 'Whitespace around and inside blocks (ul/li) (count)');
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({invalid_elements : 'hr,br'}));
root = parser.parse('\n<hr />\n<br />\n<div>\n<hr />\n<br />\n<img src="file.gif" data-mce-src="file.gif" />\n<hr />\n<br />\n</div>\n<hr />\n<br />\n');
equal(serializer.serialize(root), '<div><img src="file.gif" data-mce-src="file.gif" alt="" /></div>', 'Whitespace where SaxParser will produce multiple whitespace nodes');
deepEqual(countNodes(root), {body:1, div:1, img:1}, 'Whitespace where SaxParser will produce multiple whitespace nodes (count)');
});
test('Whitespace before/after invalid element with text in block', function() {
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({invalid_elements : 'em'}));
root = parser.parse('<p>a <em>b</em> c</p>');
equal(serializer.serialize(root), '<p>a b c</p>');
});
test('Whitespace before/after invalid element whitespace element in block', function() {
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({invalid_elements : 'span'}));
root = parser.parse('<p> <span></span> </p>');
equal(serializer.serialize(root), '<p>\u00a0</p>');
});
test('Whitespace preserved in PRE', function() {
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <PRE> \t\r\n test \t\r\n </PRE> \t\r\n ');
equal(serializer.serialize(root), '<pre> \t\r\n test \t\r\n </pre>', 'Whitespace around and inside PRE');
deepEqual(countNodes(root), {body:1, pre:1, '#text':1}, 'Whitespace around and inside PRE (count)');
});
test('Whitespace preserved in SPAN inside PRE', function() {
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse(' \t\r\n <PRE> \t\r\n <span> test </span> \t\r\n </PRE> \t\r\n ');
equal(serializer.serialize(root), '<pre> \t\r\n <span> test </span> \t\r\n </pre>', 'Whitespace around and inside PRE');
deepEqual(countNodes(root), {body:1, pre:1, span:1, '#text':3}, 'Whitespace around and inside PRE (count)');
});
test('Parse invalid contents', function() {
var parser, root;
expect(20);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a"><p class="b">123</p></p>');
equal(serializer.serialize(root), '<p class="b">123</p>', 'P in P, no nodes before/after');
deepEqual(countNodes(root), {body:1, p:1, '#text':1}, 'P in P, no nodes before/after (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a">a<p class="b">b</p><p class="c">c</p>d</p>');
equal(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="a">d</p>', 'Two P in P, no nodes before/after');
deepEqual(countNodes(root), {body: 1, p:4, '#text': 4}, 'Two P in P, no nodes before/after (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a">abc<p class="b">def</p></p>');
equal(serializer.serialize(root), '<p class="a">abc</p><p class="b">def</p>', 'P in P with nodes before');
deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes before (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a"><p class="b">abc</p>def</p>');
equal(serializer.serialize(root), '<p class="b">abc</p><p class="a">def</p>', 'P in P with nodes after');
deepEqual(countNodes(root), {body: 1, p:2, '#text': 2}, 'P in P with nodes after (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a"><p class="b">abc</p><br></p>');
equal(serializer.serialize(root), '<p class="b">abc</p>', 'P in P with BR after');
deepEqual(countNodes(root), {body: 1, p:1, '#text': 1}, 'P in P with BR after (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a">a<strong>b<span>c<em>d<p class="b">e</p>f</em>g</span>h</strong>i</p>');
equal(serializer.serialize(root), '<p class="a">a<strong>b<span>c<em>d</em></span></strong></p><p class="b">e</p><p class="a"><strong><span><em>f</em>g</span>h</strong>i</p>', 'P in P wrapped in inline elements');
deepEqual(countNodes(root), {"body":1, "p":3, "#text":9, "strong":2, "span":2, "em": 2}, 'P in P wrapped in inline elements (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p class="a">a<p class="b">b<p class="c">c</p>d</p>e</p>');
equal(serializer.serialize(root), '<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="b">d</p><p class="a">e</p>', 'P in P in P with text before/after');
deepEqual(countNodes(root), {body: 1, p:5, '#text': 5}, 'P in P in P with text before/after (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p>a<ul><li>b</li><li>c</li></ul>d</p>');
equal(serializer.serialize(root), '<p>a</p><ul><li>b</li><li>c</li></ul><p>d</p>', 'UL inside P');
deepEqual(countNodes(root), {body: 1, p:2, ul:1, li:2, '#text': 4}, 'UL inside P (count)');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<table><tr><td><tr>a</tr></td></tr></table>');
equal(serializer.serialize(root), '<table><tr><td>a</td></tr></table>', 'TR inside TD');
deepEqual(countNodes(root), {body: 1, table:1, tr:1, td:1, '#text': 1}, 'TR inside TD (count)');
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({valid_elements: 'p,section,div'}));
root = parser.parse('<div><section><p>a</p></section></div>');
equal(serializer.serialize(root), '<div><section><p>a</p></section></div>', 'P inside SECTION');
deepEqual(countNodes(root), {"body":1, "div":1, "section":1, "p":1, "#text":1}, 'P inside SECTION (count)');
});
test('addNodeFilter', function() {
var parser, result;
expect(7);
parser = new tinymce.html.DomParser({}, schema);
parser.addNodeFilter('#comment', function(nodes, name, args) {
result = {nodes : nodes, name : name, args : args};
});
parser.parse('text<!--text1-->text<!--text2-->');
deepEqual(result.args, {}, 'Parser args');
equal(result.name, '#comment', 'Parser filter result name');
equal(result.nodes.length, 2, 'Parser filter result node');
equal(result.nodes[0].name, '#comment', 'Parser filter result node(0) name');
equal(result.nodes[0].value, 'text1', 'Parser filter result node(0) value');
equal(result.nodes[1].name, '#comment', 'Parser filter result node(1) name');
equal(result.nodes[1].value, 'text2', 'Parser filter result node(1) value');
});
test('addNodeFilter multiple names', function() {
var parser, results = {};
expect(14);
parser = new tinymce.html.DomParser({}, schema);
parser.addNodeFilter('#comment,#text', function(nodes, name, args) {
results[name] = {nodes : nodes, name : name, args : args};
});
parser.parse('text1<!--text1-->text2<!--text2-->');
deepEqual(results['#comment'].args, {}, 'Parser args');
equal(results['#comment'].name, '#comment', 'Parser filter result name');
equal(results['#comment'].nodes.length, 2, 'Parser filter result node');
equal(results['#comment'].nodes[0].name, '#comment', 'Parser filter result node(0) name');
equal(results['#comment'].nodes[0].value, 'text1', 'Parser filter result node(0) value');
equal(results['#comment'].nodes[1].name, '#comment', 'Parser filter result node(1) name');
equal(results['#comment'].nodes[1].value, 'text2', 'Parser filter result node(1) value');
deepEqual(results['#text'].args, {}, 'Parser args');
equal(results['#text'].name, '#text', 'Parser filter result name');
equal(results['#text'].nodes.length, 2, 'Parser filter result node');
equal(results['#text'].nodes[0].name, '#text', 'Parser filter result node(0) name');
equal(results['#text'].nodes[0].value, 'text1', 'Parser filter result node(0) value');
equal(results['#text'].nodes[1].name, '#text', 'Parser filter result node(1) name');
equal(results['#text'].nodes[1].value, 'text2', 'Parser filter result node(1) value');
});
test('addNodeFilter with parser args', function() {
var parser, result;
expect(1);
parser = new tinymce.html.DomParser({}, schema);
parser.addNodeFilter('#comment', function(nodes, name, args) {
result = {nodes : nodes, name : name, args : args};
});
parser.parse('text<!--text1-->text<!--text2-->', {value: 1});
deepEqual(result.args, {value: 1}, 'Parser args');
});
test('addAttributeFilter', function() {
var parser, result;
expect(7);
parser = new tinymce.html.DomParser({});
parser.addAttributeFilter('src', function(nodes, name, args) {
result = {nodes : nodes, name : name, args : args};
});
parser.parse('<b>a<img src="1.gif" />b<img src="1.gif" />c</b>');
deepEqual(result.args, {}, 'Parser args');
equal(result.name, 'src', 'Parser filter result name');
equal(result.nodes.length, 2, 'Parser filter result node');
equal(result.nodes[0].name, 'img', 'Parser filter result node(0) name');
equal(result.nodes[0].attr('src'), '1.gif', 'Parser filter result node(0) attr');
equal(result.nodes[1].name, 'img', 'Parser filter result node(1) name');
equal(result.nodes[1].attr('src'), '1.gif', 'Parser filter result node(1) attr');
});
test('addAttributeFilter multiple', function() {
var parser, results = {};
expect(14);
parser = new tinymce.html.DomParser({});
parser.addAttributeFilter('src,href', function(nodes, name, args) {
results[name] = {nodes : nodes, name : name, args : args};
});
parser.parse('<b><a href="1.gif">a</a><img src="1.gif" />b<img src="1.gif" /><a href="2.gif">c</a></b>');
deepEqual(results['src'].args, {}, 'Parser args');
equal(results['src'].name, 'src', 'Parser filter result name');
equal(results['src'].nodes.length, 2, 'Parser filter result node');
equal(results['src'].nodes[0].name, 'img', 'Parser filter result node(0) name');
equal(results['src'].nodes[0].attr('src'), '1.gif', 'Parser filter result node(0) attr');
equal(results['src'].nodes[1].name, 'img', 'Parser filter result node(1) name');
equal(results['src'].nodes[1].attr('src'), '1.gif', 'Parser filter result node(1) attr');
deepEqual(results['href'].args, {}, 'Parser args');
equal(results['href'].name, 'href', 'Parser filter result name');
equal(results['href'].nodes.length, 2, 'Parser filter result node');
equal(results['href'].nodes[0].name, 'a', 'Parser filter result node(0) name');
equal(results['href'].nodes[0].attr('href'), '1.gif', 'Parser filter result node(0) attr');
equal(results['href'].nodes[1].name, 'a', 'Parser filter result node(1) name');
equal(results['href'].nodes[1].attr('href'), '2.gif', 'Parser filter result node(1) attr');
});
test('Fix orphan LI elements', function() {
var parser, result;
expect(3);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<ul><li>a</li></ul><li>b</li>');
equal(serializer.serialize(root), '<ul><li>a</li><li>b</li></ul>', 'LI moved to previous sibling UL');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<li>a</li><ul><li>b</li></ul>');
equal(serializer.serialize(root), '<ul><li>a</li><li>b</li></ul>', 'LI moved to next sibling UL');
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<li>a</li>');
equal(serializer.serialize(root), '<ul><li>a</li></ul>', 'LI wrapped in new UL');
});
test('Remove empty elements', function() {
var parser, result, schema = new tinymce.html.Schema({valid_elements: 'span,-a,img'});
expect(3);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<span></span><a href="#"></a>');
equal(serializer.serialize(root), '<span></span>', 'Remove empty a element');
/* parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<span></span><a href="#"><!-'+'- x -'+'-></a>');
equal(serializer.serialize(root), '<span></span>', 'Remove empty a element containing comment');*/
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({valid_elements: 'span,a[name],img'}));
root = parser.parse('<span></span><a name="anchor"></a>');
equal(serializer.serialize(root), '<span></span><a name="anchor"></a>', 'Leave a with name attribute');
parser = new tinymce.html.DomParser({}, new tinymce.html.Schema({valid_elements: 'span,a[href],img[src]'}));
root = parser.parse('<span></span><a href="#"><img src="about:blank" /></a>');
equal(serializer.serialize(root), '<span></span><a href="#"><img src="about:blank" /></a>', 'Leave elements with img in it');
});
test('Self closing list elements', function() {
var parser, root, schema = new tinymce.html.Schema();
expect(1);
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<ul><li>1<li><b>2</b><li><em><b>3</b></em></ul>');
equal(serializer.serialize(root), '<ul><li>1</li><li><strong>2</strong></li><li><em><strong>3</strong></em></li></ul>', 'Split out LI elements in LI elements.');
});
test('Remove redundant br elements', function() {
var parser, root, schema = new tinymce.html.Schema();
expect(1);
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse(
'<p>a<br></p>' +
'<p>a<br>b<br></p>' +
'<p>a<br><br></p><p>a<br><span data-mce-type="bookmark"></span><br></p>' +
'<p>a<span data-mce-type="bookmark"></span><br></p>'
);
equal(serializer.serialize(root), '<p>a</p><p>a<br />b</p><p>a<br /><br /></p><p>a<br /><br /></p><p>a</p>', 'Remove traling br elements.');
});
test('Replace br with nbsp when wrapped in two inline elements and one block', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse('<p><strong><em><br /></em></strong></p>');
equal(serializer.serialize(root), '<p><strong><em>\u00a0</em></strong></p>');
});
test('Replace br with nbsp when wrapped in an inline element and placed in the root', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse('<strong><br /></strong>');
equal(serializer.serialize(root), '<strong>\u00a0</strong>');
});
test('Don\'t replace br inside root element when there is multiple brs', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse('<strong><br /><br /></strong>');
equal(serializer.serialize(root), '<strong><br /><br /></strong>');
});
test('Don\'t replace br inside root element when there is siblings', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse('<strong><br /></strong><em>x</em>');
equal(serializer.serialize(root), '<strong><br /></strong><em>x</em>');
});
test('Remove br in invalid parent bug', function() {
var parser, root, schema = new tinymce.html.Schema({valid_elements: 'br'});
expect(1);
parser = new tinymce.html.DomParser({remove_trailing_brs : true}, schema);
root = parser.parse('<br>');
equal(serializer.serialize(root), '', 'Remove traling br elements.');
});
test('Forced root blocks', function() {
var parser, root, schema = new tinymce.html.Schema();
expect(1);
parser = new tinymce.html.DomParser({forced_root_block : 'p'}, schema);
root = parser.parse(
'<!-- a -->' +
'b' +
'<b>c</b>' +
'<p>d</p>' +
'<p>e</p>' +
'f' +
'<b>g</b>' +
'h'
);
equal(serializer.serialize(root), '<!-- a --><p>b<strong>c</strong></p><p>d</p><p>e</p><p>f<strong>g</strong>h</p>', 'Mixed text nodes, inline elements and blocks.');
});
test('Forced root blocks attrs', function() {
var parser, root, schema = new tinymce.html.Schema();
expect(1);
parser = new tinymce.html.DomParser({forced_root_block: 'p', forced_root_block_attrs: {"class": "class1"}}, schema);
root = parser.parse(
'<!-- a -->' +
'b' +
'<b>c</b>' +
'<p>d</p>' +
'<p>e</p>' +
'f' +
'<b>g</b>' +
'h'
);
equal(serializer.serialize(root), '<!-- a -->' +
'<p class="class1">b<strong>c</strong></p>' +
'<p>d</p>' +
'<p>e</p>' +
'<p class="class1">f<strong>g</strong>h</p>',
'Mixed text nodes, inline elements and blocks.');
});
test('Parse contents with html4 anchors and allow_html_in_named_anchor: false', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({allow_html_in_named_anchor : false}, schema);
root = parser.parse('<a name="x">a</a><a href="x">x</a>');
equal(serializer.serialize(root), '<a name="x"></a>a<a href="x">x</a>');
});
test('Parse contents with html5 anchors and allow_html_in_named_anchor: false', function() {
var parser, root, schema = new tinymce.html.Schema({schema: "html5"});
parser = new tinymce.html.DomParser({allow_html_in_named_anchor : false}, schema);
root = parser.parse('<a id="x">a</a><a href="x">x</a>');
equal(serializer.serialize(root), '<a id="x"></a>a<a href="x">x</a>');
});
test('Parse contents with html4 anchors and allow_html_in_named_anchor: true', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({allow_html_in_named_anchor : true}, schema);
root = parser.parse('<a name="x">a</a><a href="x">x</a>');
equal(serializer.serialize(root), '<a name="x">a</a><a href="x">x</a>');
});
test('Parse contents with html5 anchors and allow_html_in_named_anchor: true', function() {
var parser, root, schema = new tinymce.html.Schema({schema: "html5"});
parser = new tinymce.html.DomParser({allow_html_in_named_anchor : true}, schema);
root = parser.parse('<a id="x">a</a><a href="x">x</a>');
equal(serializer.serialize(root), '<a id="x">a</a><a href="x">x</a>');
});
test('Parse contents with html5 self closing datalist options', function() {
var parser, root, schema = new tinymce.html.Schema({schema: "html5"});
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<datalist><option label="a1" value="b1"><option label="a2" value="b2"><option label="a3" value="b3"></datalist>');
equal(serializer.serialize(root), '<datalist><option label="a1" value="b1"></option><option label="a2" value="b2"></option><option label="a3" value="b3"></option></datalist>');
});
test('Parse inline contents before block bug #5424', function() {
var parser, root, schema = new tinymce.html.Schema({schema: "html5"});
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<b>1</b> 2<p>3</p>');
equal(serializer.serialize(root), '<b>1</b> 2<p>3</p>');
});
test('Invalid text blocks within a li', function() {
var parser, root, schema = new tinymce.html.Schema({schema: "html5", valid_children: '-li[p]'});
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<ul><li>1<p>2</p></li><li>a<p>b</p><p>c</p></li></ul>');
equal(serializer.serialize(root), '<ul><li>12</li><li>ab</li><li>c</li></ul>');
});
test('Invalid inline element with space before', function() {
var parser, root, schema = new tinymce.html.Schema();
parser = new tinymce.html.DomParser({}, schema);
root = parser.parse('<p><span>1</span> <strong>2</strong></p>');
equal(serializer.serialize(root), '<p>1 <strong>2</strong></p>');
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.DomParser tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Entities tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Entities");
QUnit.config.reorder = false;
test('encodeRaw', function() {
expect(2);
equal(tinymce.html.Entities.encodeRaw('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;\u00e5\u00e4\u00f6', 'Raw encoding text');
equal(tinymce.html.Entities.encodeRaw('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;\u00e5\u00e4\u00f6', 'Raw encoding attribute');
});
test('encodeAllRaw', function() {
expect(1);
equal(tinymce.html.Entities.encodeAllRaw('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;&quot;&#39;&amp;\u00e5\u00e4\u00f6', 'Raw encoding all');
});
test('encodeNumeric', function() {
expect(2);
equal(tinymce.html.Entities.encodeNumeric('<>"\'&\u00e5\u00e4\u00f6\u03b8\u2170\ufa11'), '&lt;&gt;"\'&amp;&#229;&#228;&#246;&#952;&#8560;&#64017;', 'Numeric encoding text');
equal(tinymce.html.Entities.encodeNumeric('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&#229;&#228;&#246;', 'Numeric encoding attribute');
});
test('encodeNamed', function() {
expect(4);
equal(tinymce.html.Entities.encodeNamed('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;&aring;&auml;&ouml;', 'Named encoding text');
equal(tinymce.html.Entities.encodeNamed('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&aring;&auml;&ouml;', 'Named encoding attribute');
equal(tinymce.html.Entities.encodeNamed('<>"\'\u00e5\u00e4\u00f6', false, {'\u00e5' : '&aring;'}), '&lt;&gt;"\'&aring;\u00e4\u00f6', 'Named encoding text');
equal(tinymce.html.Entities.encodeNamed('<>"\'\u00e5\u00e4\u00f6', true, {'\u00e5' : '&aring;'}), '&lt;&gt;&quot;\'&aring;\u00e4\u00f6', 'Named encoding attribute');
});
test('getEncodeFunc', function() {
var encodeFunc;
expect(10);
encodeFunc = tinymce.html.Entities.getEncodeFunc('raw');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;\u00e5\u00e4\u00f6', 'Raw encoding text');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;\u00e5\u00e4\u00f6', 'Raw encoding attribute');
encodeFunc = tinymce.html.Entities.getEncodeFunc('named');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;&aring;&auml;&ouml;', 'Named encoding text');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&aring;&auml;&ouml;', 'Named encoding attribute');
encodeFunc = tinymce.html.Entities.getEncodeFunc('numeric');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;&#229;&#228;&#246;', 'Named encoding text');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&#229;&#228;&#246;', 'Named encoding attribute');
encodeFunc = tinymce.html.Entities.getEncodeFunc('named+numeric', '229,aring');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;&aring;&#228;&#246;', 'Named+numeric encoding text');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&aring;&#228;&#246;', 'Named+numeric encoding attribute');
encodeFunc = tinymce.html.Entities.getEncodeFunc('named,numeric', '229,aring');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6'), '&lt;&gt;"\'&amp;&aring;&#228;&#246;', 'Named+numeric encoding text');
equal(encodeFunc('<>"\'&\u00e5\u00e4\u00f6', true), '&lt;&gt;&quot;\'&amp;&aring;&#228;&#246;', 'Named+numeric encoding attribute');
});
test('decode', function() {
expect(3);
equal(tinymce.html.Entities.decode('&lt;&gt;&quot;&#39;&amp;&aring;&auml;&ouml;&unknown;&#039;&#x27;'), '<>"\'&\u00e5\u00e4\u00f6&unknown;\'\'', 'Decode text with various entities');
equal(tinymce.html.Entities.encodeNumeric(tinymce.html.Entities.decode(
'&#130;&#131;&#132;&#133;&#134;&#135;&#136;&#137;&#138;' +
'&#139;&#140;&#141;&#142;&#143;&#144;&#145;&#146;&#147;&#148;&#149;&#150;&#151;&#152;' +
'&#153;&#154;&#155;&#156;&#157;&#158;&#159;')
), '&#8218;&#402;&#8222;&#8230;&#8224;&#8225;&#710;&#8240;&#352;&#8249;&#338;&#141;&#381;' +
'&#143;&#144;&#8216;&#8217;&#8220;&#8221;&#8226;&#8211;&#8212;&#732;&#8482;&#353;' +
'&#8250;&#339;&#157;&#382;&#376;',
'Entity decode ascii');
equal(tinymce.html.Entities.encodeNumeric(tinymce.html.Entities.decode('&#194564;')), '&#194564;', "High byte non western character.");
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Entities tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,466 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Node tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Node");
QUnit.config.reorder = false;
test('construction', function() {
var node;
expect(15);
node = new tinymce.html.Node('#text', 3);
equal(node.name, '#text');
equal(node.type, 3);
node = new tinymce.html.Node('#comment', 8);
equal(node.name, '#comment');
equal(node.type, 8);
node = new tinymce.html.Node('b', 1);
equal(node.name, 'b');
equal(node.type, 1);
deepEqual(node.attributes, []);
node = new tinymce.html.Node('#pi', 7);
equal(node.name, '#pi');
equal(node.type, 7);
node = new tinymce.html.Node('#doctype', 10);
equal(node.name, '#doctype');
equal(node.type, 10);
node = new tinymce.html.Node('#cdata', 4);
equal(node.name, '#cdata');
equal(node.type, 4);
node = new tinymce.html.Node('#frag', 11);
equal(node.name, '#frag');
equal(node.type, 11);
});
test('append inside empty node', function() {
var root, node, node2;
expect(10);
root = new tinymce.html.Node('#frag', 11);
node = root.append(new tinymce.html.Node('b', 1));
ok(root.firstChild.parent === root);
equal(root.firstChild.next, undefined);
equal(root.firstChild.prev, undefined);
equal(root.firstChild.firstChild, undefined);
equal(root.firstChild.lastChild, undefined);
ok(node.parent === root);
equal(node.next, undefined);
equal(node.prev, undefined);
equal(node.firstChild, undefined);
equal(node.lastChild, undefined);
});
test('append node after node', function() {
var root, node, node2;
expect(17);
root = new tinymce.html.Node('#frag', 11);
node2 = root.append(new tinymce.html.Node('a', 1));
node = root.append(new tinymce.html.Node('b', 1));
ok(root.firstChild.parent === root, 'root.firstChild.parent === root');
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node, 'root.firstChild');
ok(root.firstChild.next === node, 'root.firstChild.next');
equal(root.firstChild.prev, undefined, 'root.firstChild.prev');
equal(root.firstChild.firstChild, undefined, 'root.firstChild.firstChild');
equal(root.firstChild.lastChild, undefined, 'root.firstChild.lastChild');
ok(node2.parent === root, 'node2.parent === root');
ok(node2.next === node, 'node2.next');
equal(node2.prev, undefined, 'node2.prev');
equal(node2.firstChild, undefined, 'node2.firstChild');
equal(node2.lastChild, undefined, 'node2.lastChild');
ok(node.parent === root, 'node.parent === root');
equal(node.next, undefined, 'node.next');
ok(node.prev === node2, 'node.prev');
equal(node.firstChild, undefined, 'node.firstChild');
equal(node.lastChild, undefined, 'node.lastChild');
});
test('append existing node before other existing node', function() {
var root, node, node2;
expect(8);
root = new tinymce.html.Node('#frag', 11);
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.append(new tinymce.html.Node('b', 1));
root.append(node);
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node, 'root.lastChild');
equal(node.next, undefined, 'node.next');
ok(node.prev === node2, 'node.prev');
ok(node.parent === root, 'node.parent');
ok(node2.parent === root, 'node2.parent');
equal(node2.prev, undefined, 'node2.prev');
ok(node2.next === node, 'node2.next');
});
test('remove unattached node', function() {
expect(1);
ok(!new tinymce.html.Node('#text', 3).remove().parent);
});
test('remove single child', function() {
var root, node, node2, node3;
expect(6);
root = new tinymce.html.Node('#frag', 11);
node = root.append(new tinymce.html.Node('p', 1));
node = root.firstChild.remove();
equal(root.firstChild, undefined);
equal(root.lastChild, undefined);
equal(node.parent, undefined);
equal(node.next, undefined);
equal(node.prev, undefined);
equal(node.name, 'p');
});
test('remove middle node', function() {
var root, node, node2, node3;
expect(9);
root = new tinymce.html.Node('#frag', 11);
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.append(new tinymce.html.Node('b', 1));
node3 = root.append(new tinymce.html.Node('c', 1));
node2.remove();
equal(node2.parent, undefined);
equal(node2.next, undefined);
equal(node2.prev, undefined);
ok(root.firstChild === node, 'root.firstChild');
ok(root.lastChild === node3, 'root.lastChild');
ok(node.next === node3, 'node.next');
equal(node.prev, undefined, 'node.prev');
ok(node3.prev, node, 'node3.prev');
equal(node3.next, undefined, 'node3.next');
});
test('insert after last', function() {
var fragment, root, node, node2;
expect(5);
fragment = new tinymce.html.Node('#frag', 11);
root = fragment.append(new tinymce.html.Node('body', 1));
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.insert(new tinymce.html.Node('x', 1), node);
ok(root.firstChild === node, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node.next === node2, 'node.next');
ok(node2.prev === node, 'node2.prev');
ok(node2.parent === root, 'node3.next');
});
test('insert before first', function() {
var fragment, root, node, node2;
expect(8);
fragment = new tinymce.html.Node('#frag', 11);
root = fragment.append(new tinymce.html.Node('body', 1));
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.insert(new tinymce.html.Node('x', 1), node, true);
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node, 'root.lastChild');
ok(node2.parent === root, 'node2.lastChild');
ok(node2.next === node, 'node2.next');
ok(node2.prev === undefined, 'node2.prev');
ok(node.parent === root, 'node.lastChild');
ok(node.next === undefined, 'node.next');
ok(node.prev === node2, 'node.prev');
});
test('insert before second', function() {
var fragment, root, node, node2;
expect(5);
fragment = new tinymce.html.Node('#frag', 11);
root = fragment.append(new tinymce.html.Node('body', 1));
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.append(new tinymce.html.Node('b', 1));
node3 = root.insert(new tinymce.html.Node('x', 1), node2, true);
ok(root.firstChild === node, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node3.parent === root, 'node3.parent');
ok(node3.next === node2, 'node3.next');
ok(node3.prev === node, 'node3.prev');
});
test('insert after and between two nodes', function() {
var root, node, node2, node3;
expect(7);
fragment = new tinymce.html.Node('#frag', 11);
root = fragment.append(new tinymce.html.Node('body', 1));
node = root.append(new tinymce.html.Node('a', 1));
node2 = root.append(new tinymce.html.Node('b', 1));
node3 = root.insert(new tinymce.html.Node('x', 1), node);
ok(root.firstChild === node, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node.next === node3, 'node.next');
ok(node2.prev === node3, 'node2.prev');
ok(node3.parent === root, 'node3.next');
ok(node3.next === node2, 'node3.next');
ok(node3.prev === node, 'node3.prev');
});
test('replace single child', function() {
var root, node1, node2;
expect(5);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = root.append(new tinymce.html.Node('em', 1));
node1.replace(node2);
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node2.parent === root, 'node2.parent');
ok(!node2.next, 'node2.next');
ok(!node2.prev, 'node2.prev');
});
test('replace first child', function() {
var root, node1, node2, node3;
expect(5);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = root.append(new tinymce.html.Node('em', 1));
node3 = root.append(new tinymce.html.Node('b', 1));
node1.replace(node2);
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node3, 'root.lastChild');
ok(node2.parent === root, 'node2.parent');
ok(node2.next === node3, 'node2.next');
ok(!node2.prev, 'node2.prev');
});
test('replace last child', function() {
var root, node1, node2, node3;
expect(5);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node3 = root.append(new tinymce.html.Node('b', 1));
node2 = root.append(new tinymce.html.Node('em', 1));
node3.replace(node2);
ok(root.firstChild === node1, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node2.parent === root, 'node2.parent');
ok(!node2.next, 'node2.next');
ok(node2.prev === node1, 'node2.prev');
});
test('replace middle child', function() {
var root, node1, node2, node3, node4;
expect(5);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = root.append(new tinymce.html.Node('b', 1));
node3 = root.append(new tinymce.html.Node('b', 1));
node4 = root.append(new tinymce.html.Node('em', 1));
node2.replace(node4);
ok(root.firstChild === node1, 'root.firstChild');
ok(root.lastChild === node3, 'root.lastChild');
ok(node4.parent === root, 'node4.parent');
ok(node4.next === node3, 'node4.next');
ok(node4.prev === node1, 'node4.prev');
});
test('attr', 22, function() {
var node;
node = new tinymce.html.Node('b', 1);
deepEqual(node.attributes, []);
node.attr('attr1', 'value1');
equal(node.attr('attr1'), 'value1');
equal(node.attr('attr2'), undefined);
deepEqual(node.attributes, [{name: 'attr1', value: 'value1'}]);
deepEqual(node.attributes.map, {'attr1': 'value1'});
node = new tinymce.html.Node('b', 1);
deepEqual(node.attributes, []);
node.attr('attr1', 'value1');
node.attr('attr1', 'valueX');
equal(node.attr('attr1'), 'valueX');
deepEqual(node.attributes, [{name: 'attr1', value: 'valueX'}]);
deepEqual(node.attributes.map, {'attr1': 'valueX'});
node = new tinymce.html.Node('b', 1);
deepEqual(node.attributes, []);
node.attr('attr1', 'value1');
node.attr('attr2', 'value2');
equal(node.attr('attr1'), 'value1');
equal(node.attr('attr2'), 'value2');
deepEqual(node.attributes, [{name: 'attr1', value: 'value1'}, {name: 'attr2', value: 'value2'}]);
deepEqual(node.attributes.map, {'attr1': 'value1', 'attr2': 'value2'});
node = new tinymce.html.Node('b', 1);
deepEqual(node.attributes, []);
node.attr('attr1', 'value1');
node.attr('attr1', null);
equal(node.attr('attr1'), undefined);
deepEqual(node.attributes, []);
deepEqual(node.attributes.map, {});
node = new tinymce.html.Node('b', 1);
node.attr({a:'1', b:'2'});
deepEqual(node.attributes, [{name: 'a', value: '1'}, {name: 'b', value: '2'}]);
deepEqual(node.attributes.map, {a:'1', b:'2'});
node = new tinymce.html.Node('b', 1);
node.attr(null);
deepEqual(node.attributes, []);
deepEqual(node.attributes.map, {});
});
test('clone', function() {
var root, node, clone;
expect(16);
node = new tinymce.html.Node('#text', 3);
node.value = 'value';
clone = node.clone();
equal(clone.name, '#text');
equal(clone.type, 3);
equal(clone.value, 'value');
equal(clone.parent, undefined);
equal(clone.next, undefined);
equal(clone.prev, undefined);
root = new tinymce.html.Node('#frag', 11);
node = new tinymce.html.Node('#text', 3);
node.value = 'value';
root.append(node);
equal(clone.name, '#text');
equal(clone.type, 3);
equal(clone.value, 'value');
equal(clone.parent, undefined);
equal(clone.next, undefined);
equal(clone.prev, undefined);
node = new tinymce.html.Node('b', 1);
node.attr('id', 'id');
node.attr('class', 'class');
node.attr('title', 'title');
clone = node.clone();
equal(clone.name, 'b');
equal(clone.type, 1);
deepEqual(clone.attributes, [{name: 'class', value: 'class'}, {name: 'title', value: 'title'}]);
deepEqual(clone.attributes.map, {'class': 'class', 'title': 'title'});
});
test('unwrap', function() {
var root, node1, node2, node3;
expect(7);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = node1.append(new tinymce.html.Node('em', 1));
node1.unwrap();
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node2, 'root.lastChild');
ok(node2.parent === root, 'node2.parent');
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = node1.append(new tinymce.html.Node('em', 1));
node3 = node1.append(new tinymce.html.Node('span', 1));
node1.unwrap();
ok(root.firstChild === node2, 'root.firstChild');
ok(root.lastChild === node3, 'root.lastChild');
ok(node2.parent === root, 'node2.parent');
ok(node3.parent === root, 'node3.parent');
});
test('empty', function() {
var root, node1, node2;
expect(4);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('b', 1));
node2 = node1.append(new tinymce.html.Node('em', 1));
node1.empty();
ok(root.firstChild === node1, 'root.firstChild');
ok(root.lastChild === node1, 'root.firstChild');
ok(!node1.firstChild, 'node1.firstChild');
ok(!node1.lastChild, 'node1.firstChild');
});
test('isEmpty', function() {
var root, node1, node2;
expect(9);
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('p', 1));
node2 = node1.append(new tinymce.html.Node('b', 1));
ok(root.isEmpty({img: 1}), 'Is empty 1');
ok(node1.isEmpty({img: 1}), 'Is empty 2');
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('p', 1));
node2 = node1.append(new tinymce.html.Node('img', 1));
ok(!root.isEmpty({img: 1}), 'Is not empty 1');
ok(!node1.isEmpty({img: 1}), 'Is not empty 2');
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('p', 1));
node2 = node1.append(new tinymce.html.Node('#text', 3));
node2.value = 'X';
ok(!root.isEmpty({img: 1}), 'Is not empty 3');
ok(!node1.isEmpty({img: 1}), 'Is not empty 4');
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('p', 1));
node2 = node1.append(new tinymce.html.Node('#text', 3));
node2.value = '';
ok(root.isEmpty({img: 1}), 'Is empty 4');
ok(node1.isEmpty({img: 1}), 'Is empty 5');
root = new tinymce.html.Node('#frag', 11);
node1 = root.append(new tinymce.html.Node('a', 1)).attr('name', 'x');
ok(!root.isEmpty({img: 1}), 'Contains anchor with name attribute.');
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Node tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,616 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.SaxParser tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.SaxParser");
QUnit.config.reorder = false;
var writer = new tinymce.html.Writer(), schema = new tinymce.html.Schema();
function createCounter(writer) {
var counts = {};
return {
counts : counts,
comment: function(text) {
if ("comment" in counts)
counts.comment++;
else
counts.comment = 1;
writer.comment(text);
},
cdata: function(text) {
if ("cdata" in counts)
counts.cdata++;
else
counts.cdata = 1;
writer.cdata(text);
},
text: function(text, raw) {
if ("text" in counts)
counts.text++;
else
counts.text = 1;
writer.text(text, raw);
},
start: function(name, attrs, empty) {
if ("start" in counts)
counts.start++;
else
counts.start = 1;
writer.start(name, attrs, empty);
},
end: function(name) {
if ("end" in counts)
counts.end++;
else
counts.end = 1;
writer.end(name);
},
pi: function(name, text) {
if ("pi" in counts)
counts.pi++;
else
counts.pi = 1;
writer.pi(name, text);
},
doctype: function(text) {
if ("doctype:" in counts)
counts.doctype++;
else
counts.doctype = 1;
writer.doctype(text);
}
};
}
test('Parse elements', function() {
expect(46);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span id=id1 title="title value" class=\'class1 class2\' data-value="value1" MYATTR="val1" myns:myattr="val2" disabled empty=""></span>');
equal(writer.getContent(), '<span id="id1" title="title value" class="class1 class2" data-value="value1" myattr="val1" myns:myattr="val2" disabled="disabled" empty=""></span>', 'Parse attribute formats.');
deepEqual(counter.counts, {start:1, end:1}, 'Parse attribute formats counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<b href=\'"&amp;<>\'></b>');
equal(writer.getContent(), '<b href="&quot;&amp;&lt;&gt;"></b>', 'Parse attributes with <> in them.');
deepEqual(counter.counts, {start:1, end:1}, 'Parse attributes with <> in them (count).');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span title=" "class=" "></span>');
equal(writer.getContent(), '<span title=" " class=" "></span>', 'Parse compressed attributes.');
deepEqual(counter.counts, {start:1, end:1}, 'Parse compressed attributes (count).');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span title></span>');
equal(writer.getContent(), '<span title=""></span>', 'Single empty attribute.');
deepEqual(counter.counts, {start:1, end:1}, 'Single empty attributes (count).');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span class="class" title></span>');
equal(writer.getContent(), '<span class="class" title=""></span>', 'Empty attribute at end.');
deepEqual(counter.counts, {start:1, end:1}, 'Empty attribute at end (count).');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span title class="class"></span>');
equal(writer.getContent(), '<span title="" class="class"></span>', 'Empty attribute at start.');
deepEqual(counter.counts, {start:1, end:1}, 'Empty attribute at start (count).');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<img src="test">');
equal(writer.getContent(), '<img src="test" />', 'Parse empty element.');
deepEqual(counter.counts, {start:1}, 'Parse empty element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<img\nsrc="test"\ntitle="row1\nrow2">');
equal(writer.getContent(), '<img src="test" title="row1\nrow2" />', 'Parse attributes with linebreak.');
deepEqual(counter.counts, {start: 1}, 'Parse attributes with linebreak counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<img \t \t src="test" \t \t title="\t row1\t row2">');
equal(writer.getContent(), '<img src="test" title="\t row1\t row2" />', 'Parse attributes with whitespace.');
deepEqual(counter.counts, {start: 1}, 'Parse attributes with whitespace counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<myns:mytag>text</myns:mytag>');
equal(writer.getContent(), '<myns:mytag>text</myns:mytag>', 'Parse element with namespace.');
deepEqual(counter.counts, {start:1, text:1, end: 1}, 'Parse element with namespace counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<myns-mytag>text</myns-mytag>');
equal(writer.getContent(), '<myns-mytag>text</myns-mytag>', 'Parse element with dash name.');
deepEqual(counter.counts, {start:1, text:1, end:1}, 'Parse element with dash name counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<p>text2<b>text3</p>text4</b>text5');
equal(writer.getContent(), 'text1<p>text2<b>text3</b></p>text4text5', 'Parse tag soup 1.');
deepEqual(counter.counts, {text:5, start: 2, end: 2}, 'Parse tag soup 1 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<P>text2<B>text3</p>text4</b>text5');
equal(writer.getContent(), 'text1<p>text2<b>text3</b></p>text4text5', 'Parse tag soup 2.');
deepEqual(counter.counts, {text: 5, start: 2, end: 2}, 'Parse tag soup 2 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<P>text2<B>tex<t3</p>te>xt4</b>text5');
equal(writer.getContent(), 'text1<p>text2<b>tex&lt;t3</b></p>te&gt;xt4text5', 'Parse tag soup 3.');
deepEqual(counter.counts, {text: 5, start: 2, end: 2}, 'Parse tag soup 3 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<p>text2<b>text3');
equal(writer.getContent(), 'text1<p>text2<b>text3</b></p>', 'Parse tag soup 4.');
deepEqual(counter.counts, {text: 3, start: 2, end: 2}, 'Parse tag soup 4 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<script>text2');
equal(writer.getContent(), 'text1<script>text2</s' + 'cript>', 'Parse tag soup 5.');
deepEqual(counter.counts, {text: 2, start: 1, end: 1}, 'Parse tag soup 5 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<style>text2');
equal(writer.getContent(), 'text1<style>text2</st' + 'yle>', 'Parse tag soup 6.');
deepEqual(counter.counts, {text: 2, start: 1, end: 1}, 'Parse tag soup 6 counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<span title="<test" data-test="test>"></span>');
equal(writer.getContent(), 'text1<span title="&lt;test" data-test="test&gt;"></span>', 'Parse element with </> in attributes.');
deepEqual(counter.counts, {text: 1, start: 1, end: 1}, 'Parse element with </> in attributes counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse("text\n<SC"+"RIPT type=mce-text/javascript>// <![CDATA[\nalert('HELLO WORLD!');\n// ]]></SC"+"RIPT>");
equal(writer.getContent(), "text\n<sc"+"ript type=\"mce-text/javascript\">// <![CDATA[\nalert('HELLO WORLD!');\n// ]]></sc"+"ript>", 'Parse cdata script.');
deepEqual(counter.counts, {text: 2, start: 1, end: 1}, 'Parse cdata script counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<noscript>te<br>xt2</noscript>text3');
equal(writer.getContent(), 'text1<noscript>te<br>xt2</noscript>text3', 'Parse noscript elements.');
deepEqual(counter.counts, {text: 3, start: 1, end: 1}, 'Parse noscript elements counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<p>a</p><p /><p>b</p>');
equal(writer.getContent(), '<p>a</p><p></p><p>b</p>', 'Parse invalid closed element.');
deepEqual(counter.counts, {text: 2, start: 3, end: 3}, 'Parse invalid closed element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<br><br /><br/>');
equal(writer.getContent(), '<br /><br /><br />', 'Parse short ended elements.');
deepEqual(counter.counts, {start: 3}, 'Parse short ended elements counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<p ></p>');
equal(writer.getContent(), '<p></p>', 'Parse start elements with whitespace only attribs part.');
deepEqual(counter.counts, {start: 1, end: 1}, 'Parse start elements with whitespace only attribs part (counts).');
});
test('Parse style elements', function() {
expect(8);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><style>// <b>tag</b></st' + 'yle>text2</em>');
equal(writer.getContent(), 'text1<em><style>// <b>tag</b></st' + 'yle>text2</em>', 'Parse style element.');
deepEqual(counter.counts, {start: 2, end: 2, text: 3}, 'Parse style element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><style id="id">// <b>tag</b></st' + 'yle>text2</em>');
equal(writer.getContent(), 'text1<em><style id="id">// <b>tag</b></st' + 'yle>text2</em>', 'Parse style element with attributes.');
deepEqual(counter.counts, {text:3, start:2, end:2}, 'Parse style element with attributes counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><style></st' + 'yle>text2</span>');
equal(writer.getContent(), 'text1<em><style></st' + 'yle>text2</em>', 'Parse empty style element.');
deepEqual(counter.counts, {text:2, start:2, end:2}, 'Parse empty style element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(tinymce.extend({validate : true}, counter), new tinymce.html.Schema({invalid_elements: 'style'}));
writer.reset();
parser.parse('text1<em><style>text2</st' + 'yle>text3</em>');
equal(writer.getContent(), 'text1<em>text3</em>', 'Parse invalid style element.');
deepEqual(counter.counts, {text:2, start:1, end:1}, 'Parse invalid style element (count).');
});
test('Parse script elements', function() {
expect(8);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><script>// <b>tag</b></s' + 'cript>text2</em>');
equal(writer.getContent(), 'text1<em><script>// <b>tag</b></s' + 'cript>text2</em>', 'Parse script element.');
deepEqual(counter.counts, {start:2, end:2, text:3}, 'Parse script element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><script id="id">// <b>tag</b></s' + 'cript>text2</em>');
equal(writer.getContent(), 'text1<em><script id="id">// <b>tag</b></s' + 'cript>text2</em>', 'Parse script element with attributes.');
deepEqual(counter.counts, {start:2, end:2, text:3}, 'Parse script element with attributes counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<em><script></s' + 'cript>text2</em>');
equal(writer.getContent(), 'text1<em><script></s' + 'cript>text2</em>', 'Parse empty script element.');
deepEqual(counter.counts, {text: 2, start:2, end: 2}, 'Parse empty script element counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(tinymce.extend({validate : true}, counter), new tinymce.html.Schema({invalid_elements: 'script'}));
writer.reset();
parser.parse('text1<em><s' + 'cript>text2</s' + 'cript>text3</em>');
equal(writer.getContent(), 'text1<em>text3</em>', 'Parse invalid script element.');
deepEqual(counter.counts, {text:2, start:1, end:1}, 'Parse invalid script element (count).');
});
test('Parse text', function() {
expect(10);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('');
equal(writer.getContent(), '', 'Parse empty.');
deepEqual(counter.counts, {}, 'Parse empty counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text');
equal(writer.getContent(), 'text', 'Parse single text node.');
deepEqual(counter.counts, {text: 1}, 'Parse single text node counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<b>text</b>');
equal(writer.getContent(), '<b>text</b>', 'Parse wrapped text.');
deepEqual(counter.counts, {start:1, text:1, end:1}, 'Parse wrapped text counts');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('text1<b>text2</b>');
equal(writer.getContent(), 'text1<b>text2</b>', 'Parse text at start.');
deepEqual(counter.counts, {start:1, text:2, end:1}, 'Parse text at start counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<b>text1</b>text2');
equal(writer.getContent(), '<b>text1</b>text2', 'Parse text at end.');
deepEqual(counter.counts, {start:1, end:1, text:2}, 'Parse text at end counts.');
});
test('Parsing comments', function() {
expect(8);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!-- comment value -->');
equal(writer.getContent(), '<!-- comment value -->', 'Parse comment with value.');
deepEqual(counter.counts, {comment:1}, 'Parse comment with value count.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!---->');
equal(writer.getContent(), '', 'Parse comment without value.');
deepEqual(counter.counts, {}, 'Parse comment without value count.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!--<b></b>-->');
equal(writer.getContent(), '<!--<b></b>-->', 'Parse comment with tag inside.');
deepEqual(counter.counts, {comment:1}, 'Parse comment with tag inside counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<b>a<!-- value -->b</b>');
equal(writer.getContent(), '<b>a<!-- value -->b</b>', 'Parse comment with tags around it.');
deepEqual(counter.counts, {comment:1, text:2, start:1, end:1}, 'Parse comment with tags around it counts.');
});
test('Parsing cdata', function() {
expect(8);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<![CDATA[test text]]>');
equal(writer.getContent(), '<![CDATA[test text]]>', 'Parse cdata with value.');
deepEqual(counter.counts, {cdata:1}, 'Parse cdata with value counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<![CDATA[]]>');
equal(writer.getContent(), '', 'Parse cdata without value.');
deepEqual(counter.counts, {}, 'Parse cdata without value counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<![CDATA[<b>a</b>]]>');
equal(writer.getContent(), '<![CDATA[<b>a</b>]]>', 'Parse cdata with tag inside.');
deepEqual(counter.counts, {cdata:1}, 'Parse cdata with tag inside counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<b>a<![CDATA[value]]>b</b>');
equal(writer.getContent(), '<b>a<![CDATA[value]]>b</b>', 'Parse cdata with tags around it.');
deepEqual(counter.counts, {cdata:1, start:1, end:1, text:2}, 'Parse cdata with tags around it counts.');
});
test('Parse PI', function() {
expect(6);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<?xml version="1.0" encoding="UTF-8" ?>text1');
equal(writer.getContent(), '<?xml version="1.0" encoding="UTF-8" ?>text1', 'Parse PI with attributes.');
deepEqual(counter.counts, {pi:1, text:1}, 'Parse PI with attributes counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<?xml?>text1');
equal(writer.getContent(), '<?xml?>text1', 'Parse PI with no data.');
deepEqual(counter.counts, {pi:1, text:1}, 'Parse PI with data counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<?xml somevalue/>text1');
equal(writer.getContent(), '<?xml somevalue?>text1', 'Parse PI with IE style ending.');
deepEqual(counter.counts, {pi:1, text:1}, 'Parse PI with IE style ending counts.');
});
test('Parse doctype', function() {
expect(4);
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">text1');
equal(writer.getContent(), '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">text1', 'Parse DOCTYPE.');
deepEqual(counter.counts, {doctype:1, text:1}, 'Parse HTML5 DOCTYPE counts.');
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!DOCTYPE html>text1');
equal(writer.getContent(), '<!DOCTYPE html>text1', 'Parse HTML5 DOCTYPE.');
deepEqual(counter.counts, {doctype:1, text:1}, 'Parse HTML5 DOCTYPE counts.');
});
test('Parse (validate)', function() {
expect(2);
var counter = createCounter(writer);
counter.validate = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<invalid1>123<invalid2 />456<span title="title" invalid3="value">789</span>012</invalid1>');
equal(writer.getContent(), '123456<span title="title">789</span>012', 'Parse invalid elements and attributes.');
deepEqual(counter.counts, {start:1, end:1, text:4}, 'Parse invalid elements and attributes counts.');
});
test('Self closing', function() {
expect(1);
var counter = createCounter(writer);
counter.validate = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<ul><li>1<li><b>2</b><li><em><b>3</b></em></ul>');
equal(writer.getContent(), '<ul><li>1</li><li><b>2</b></li><li><em><b>3</b></em></li></ul>', 'Parse list with self closing items.');
});
test('Preserve internal elements', function() {
expect(2);
var schema = new tinymce.html.Schema({valid_elements : 'b'});
var counter = createCounter(writer);
counter.validate = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span id="id"><b>text</b></span><span id="id" data-mce-type="something"></span>');
equal(writer.getContent(), '<b>text</b><span id="id" data-mce-type="something"></span>', 'Preserve internal span element without any span schema rule.');
var schema = new tinymce.html.Schema({valid_elements : 'b,span[class]'});
var counter = createCounter(writer);
counter.validate = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span id="id" class="class"><b>text</b></span><span id="id" data-mce-type="something"></span>');
equal(writer.getContent(), '<span class="class"><b>text</b></span><span id="id" data-mce-type="something"></span>', 'Preserve internal span element with a span schema rule.');
});
test('Remove internal elements', function() {
expect(2);
var schema = new tinymce.html.Schema({valid_elements : 'b'});
var counter = createCounter(writer);
counter.validate = true;
counter.remove_internals = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span id="id"><b>text</b></span><span id="id" data-mce-type="something"></span>');
equal(writer.getContent(), '<b>text</b>', 'Remove internal span element without any span schema rule.');
var schema = new tinymce.html.Schema({valid_elements : 'b,span[class]'});
var counter = createCounter(writer);
counter.validate = true;
counter.remove_internals = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<span id="id" class="class"><b>text</b></span><span id="id" data-mce-type="something"></span>');
equal(writer.getContent(), '<span class="class"><b>text</b></span>', 'Remove internal span element with a span schema rule.');
// Reset
counter.remove_internals = false;
});
test('Parse attr with backslash #5436', function() {
var counter = createCounter(writer);
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<a title="\\" href="h">x</a>');
equal(writer.getContent(), '<a title="\\" href="h">x</a>');
});
test('Parse no attributes span before strong', function() {
var counter = createCounter(writer);
counter.validate = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<p><span>A</span> <strong>B</strong></p>');
equal(writer.getContent(), '<p>A <strong>B</strong></p>');
});
test('Conditional comments (allowed)', function() {
var counter = createCounter(writer);
counter.validate = false;
counter.allow_conditional_comments = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!--[if gte IE 4]>alert(1)<![endif]-->');
equal(writer.getContent(), '<!--[if gte IE 4]>alert(1)<![endif]-->');
});
test('Conditional comments (denied)', function() {
var counter = createCounter(writer);
counter.validate = false;
counter.allow_conditional_comments = false;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse('<!--[if gte IE 4]>alert(1)<![endif]-->');
equal(writer.getContent(), '<!-- [if gte IE 4]>alert(1)<![endif]-->');
writer.reset();
parser.parse('<!--[if !IE]>alert(1)<![endif]-->');
equal(writer.getContent(), '<!-- [if !IE]>alert(1)<![endif]-->');
});
test('Parse script urls (allowed)', function() {
var counter = createCounter(writer);
counter.validate = false;
counter.allow_script_urls = true;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse(
'<a href="javascript:alert(1)">1</a>' +
'<a href=" 2 ">2</a>'
);
equal(writer.getContent(), '<a href="javascript:alert(1)">1</a><a href=" 2 ">2</a>');
});
test('Parse script urls (denied)', function() {
var counter = createCounter(writer);
counter.validate = false;
var parser = new tinymce.html.SaxParser(counter, schema);
writer.reset();
parser.parse(
'<a href="jAvaScript:alert(1)">1</a>' +
'<a href="vbscript:alert(2)">2</a>' +
'<a href="java\u0000script:alert(3)">3</a>' +
'<a href="\njavascript:alert(4)">4</a>' +
'<a href="java\nscript:alert(5)">5</a>' +
'<a href="java\tscript:alert(6)">6</a>' +
'<a href="%6aavascript:alert(7)">7</a>' +
'<a href="%E3%82%AA%E3%83%BC%E3%83">Invalid url</a>'
);
equal(writer.getContent(), '<a>1</a><a>2</a><a>3</a><a>4</a><a>5</a><a>6</a><a>7</a><a href="%E3%82%AA%E3%83%BC%E3%83">Invalid url</a>');
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.SaxParser tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,374 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Schema tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Schema");
QUnit.config.reorder = false;
test('Valid elements global rule', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: '@[id|style],img[src|-style]'});
deepEqual(schema.getElementRule('img'), {"attributes": {"id": {}, "src": {}}, "attributesOrder": ["id", "src"]});
});
test('Whildcard element rule', function() {
expect(17);
var schema = new tinymce.html.Schema({valid_elements: '*[id|class]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
var schema = new tinymce.html.Schema({valid_elements: 'b*[id|class]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('body').attributesOrder, ["id", "class"]);
equal(schema.getElementRule('img'), undefined);
var schema = new tinymce.html.Schema({valid_elements: 'b?[id|class]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('bx').attributesOrder, ["id", "class"]);
equal(schema.getElementRule('body'), undefined);
var schema = new tinymce.html.Schema({valid_elements: 'b+[id|class]'});
deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('body').attributesOrder, ["id", "class"]);
deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('bx').attributesOrder, ["id", "class"]);
equal(schema.getElementRule('b'), undefined);
});
test('Whildcard attribute rule', function() {
expect(13);
var schema = new tinymce.html.Schema({valid_elements: 'b[id|class|*]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
ok(schema.getElementRule('b').attributePatterns[0].pattern.test('x'));
var schema = new tinymce.html.Schema({valid_elements: 'b[id|class|x?]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
ok(schema.getElementRule('b').attributePatterns[0].pattern.test('xy'));
ok(!schema.getElementRule('b').attributePatterns[0].pattern.test('xba'));
ok(!schema.getElementRule('b').attributePatterns[0].pattern.test('a'));
var schema = new tinymce.html.Schema({valid_elements: 'b[id|class|x+]'});
deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
ok(!schema.getElementRule('b').attributePatterns[0].pattern.test('x'));
ok(schema.getElementRule('b').attributePatterns[0].pattern.test('xb'));
ok(schema.getElementRule('b').attributePatterns[0].pattern.test('xba'));
});
test('Valid attributes and attribute order', function() {
expect(3);
var schema = new tinymce.html.Schema({valid_elements: 'div,a[href|title],b[title]'});
deepEqual(schema.getElementRule('div'), {"attributes": {}, "attributesOrder": []});
deepEqual(schema.getElementRule('a'), {"attributes": {"href": {}, "title": {}}, "attributesOrder": ["href", "title"]});
deepEqual(schema.getElementRule('b'), {"attributes": {"title": {}}, "attributesOrder": ["title"]});
});
test('Required any attributes', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: 'a![id|style|href]'});
deepEqual(schema.getElementRule('a'), {"attributes": {"href": {}, "id": {}, "style": {}}, "attributesOrder": ["id", "style", "href"], "removeEmptyAttrs": true});
});
test('Required attributes', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: 'a[!href|!name]'});
deepEqual(schema.getElementRule('a'), {"attributes": {"href": {"required": true}, "name": {"required": true}}, "attributesOrder": ["href", "name"], "attributesRequired": ["href", "name"]});
});
test('Default attribute values', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: 'img[border=0]'});
deepEqual(schema.getElementRule('img'), {"attributes": {"border": {"defaultValue": "0"}}, "attributesOrder": ["border"], "attributesDefault": [{"name": "border", "value": "0"}]});
});
test('Forced attribute values', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: 'img[border:0]'});
deepEqual(schema.getElementRule('img'), {"attributes": {"border": {"forcedValue": "0"}}, "attributesOrder": ["border"], "attributesForced": [{"name": "border", "value": "0"}]});
});
test('Required attribute values', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: 'span[dir<ltr?rtl]'});
deepEqual(schema.getElementRule('span'), {"attributes": {"dir": {"validValues": {"rtl": {}, "ltr": {}}}}, "attributesOrder": ["dir"]});
});
test('Remove empty elements', function() {
expect(2);
var schema = new tinymce.html.Schema({valid_elements: '-span'});
deepEqual(schema.getElementRule('span'), {"attributes": {}, "attributesOrder": [], "removeEmpty": true});
var schema = new tinymce.html.Schema({valid_elements: '#span'});
deepEqual(schema.getElementRule('span'), {"attributes": {}, "attributesOrder": [], "paddEmpty": true});
});
test('addValidElements', function() {
expect(1);
var schema = new tinymce.html.Schema({valid_elements: '@[id|style],img[src|-style]'});
schema.addValidElements('b[class]');
deepEqual(schema.getElementRule('b'), {"attributes": {"id": {}, "style": {}, "class": {}}, "attributesOrder": ["id", "style", "class"]});
});
test('setValidElements', function() {
expect(3);
var schema = new tinymce.html.Schema({valid_elements: '@[id|style],img[src|-style]'});
schema.setValidElements('b[class]');
equal(schema.getElementRule('img'), undefined);
deepEqual(schema.getElementRule('b'), {"attributes": {"class": {}}, "attributesOrder": ["class"]});
var schema = new tinymce.html.Schema({valid_elements: 'img[src]'});
schema.setValidElements('@[id|style],img[src]');
deepEqual(schema.getElementRule('img'), {"attributes": {"id": {}, "style": {}, "src": {}}, "attributesOrder": ["id", "style", "src"]});
});
test('getBoolAttrs', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getBoolAttrs(), {
"CONTROLS": {}, "LOOP": {}, "AUTOPLAY": {}, "SELECTED": {}, "READONLY": {}, "NOWRAP": {},
"NOSHADE": {}, "NORESIZE": {}, "NOHREF": {}, "MULTIPLE": {}, "ISMAP": {}, "DISABLED": {}, "DEFER": {},
"DECLARE": {}, "COMPACT": {}, "CHECKED": {},
"controls": {}, "loop": {}, "autoplay": {}, "selected": {}, "readonly": {}, "nowrap": {},
"noshade": {}, "noresize": {}, "nohref": {}, "multiple": {}, "ismap": {}, "disabled": {}, "defer": {},
"declare": {}, "compact": {}, "checked": {}
});
});
test('getBlockElements', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getBlockElements(), {
ASIDE: {}, HGROUP: {}, SECTION: {}, ARTICLE: {}, FOOTER: {}, HEADER: {}, SAMP: {},
ISINDEX: {}, MENU: {}, NOSCRIPT: {}, FIELDSET: {}, DIR: {}, DD: {}, DT: {},
DL: {}, CENTER: {}, BLOCKQUOTE: {}, CAPTION: {}, UL: {}, OL: {}, LI: {},
TD: {}, TR: {}, TH: {}, TFOOT: {}, THEAD: {}, TBODY: {}, TABLE: {}, FORM: {},
PRE: {}, ADDRESS: {}, DIV: {}, P: {}, HR: {}, H6: {}, H5: {}, H4: {}, H3: {},
H2: {}, H1: {}, NAV: {}, FIGURE: {}, DATALIST: {}, OPTGROUP: {}, OPTION: {}, SELECT: {},
aside: {}, hgroup: {}, section: {}, article: {}, footer: {}, header: {}, samp: {},
isindex: {}, menu: {}, noscript: {}, fieldset: {}, dir: {}, dd: {}, dt: {}, dl: {}, center: {},
blockquote: {}, caption: {}, ul: {}, ol: {}, li: {}, td: {}, tr: {}, th: {}, tfoot: {}, thead: {},
tbody: {}, table: {}, form: {}, pre: {}, address: {}, div: {}, p: {}, hr: {}, h6: {},
h5: {}, h4: {}, h3: {}, h2: {}, h1: {}, nav: {}, figure: {}, datalist: {}, optgroup: {},
option: {}, select: {}
});
});
test('getShortEndedElements', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getShortEndedElements(), {
"EMBED": {}, "PARAM": {}, "META": {}, "LINK": {}, "ISINDEX": {},
"INPUT": {}, "IMG": {}, "HR": {}, "FRAME": {}, "COL": {}, "BR": {},
"BASEFONT": {}, "BASE": {}, "AREA": {}, "SOURCE" : {}, "WBR" : {}, "TRACK" : {},
"embed": {}, "param": {}, "meta": {}, "link": {}, "isindex": {},
"input": {}, "img": {}, "hr": {}, "frame": {}, "col": {}, "br": {},
"basefont": {}, "base": {}, "area": {}, "source" : {}, "wbr" : {}, "track" : {}
});
});
test('getNonEmptyElements', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getNonEmptyElements(), {
"EMBED": {}, "PARAM": {}, "META": {}, "LINK": {}, "ISINDEX": {},
"INPUT": {}, "IMG": {}, "HR": {}, "FRAME": {}, "COL": {}, "BR": {},
"BASEFONT": {}, "BASE": {}, "AREA": {}, "SOURCE" : {},
"TD": {}, "TH": {}, "IFRAME": {}, "VIDEO": {}, "AUDIO": {}, "OBJECT": {}, "WBR": {}, "TRACK" : {}, "SCRIPT" : {},
"embed": {}, "param": {}, "meta": {}, "link": {}, "isindex": {},
"input": {}, "img": {}, "hr": {}, "frame": {}, "col": {}, "br": {},
"basefont": {}, "base": {}, "area": {}, "source" : {},
"td": {}, "th": {}, "iframe": {}, "video": {}, "audio": {}, "object": {}, "wbr" : {}, "track" : {}, "script" : {},
});
});
test('getWhiteSpaceElements', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getWhiteSpaceElements(), {
"IFRAME": {}, "NOSCRIPT": {}, "OBJECT": {}, "PRE": {},
"SCRIPT": {}, "STYLE": {}, "TEXTAREA": {}, "VIDEO": {}, "AUDIO": {},
"iframe": {}, "noscript": {}, "object": {}, "pre": {},
"script": {}, "style": {}, "textarea": {}, "video": {}, "audio": {}
});
});
test('getTextBlockElements', function() {
expect(1);
var schema = new tinymce.html.Schema();
deepEqual(schema.getTextBlockElements(), {
"ADDRESS": {}, "ARTICLE": {}, "ASIDE": {}, "BLOCKQUOTE": {}, "CENTER": {}, "DIR": {}, "DIV": {}, "FIELDSET": {}, "FIGURE": {}, "FOOTER": {}, "FORM": {},
"H1": {}, "H2": {}, "H3": {}, "H4": {}, "H5": {}, "H6": {}, "HEADER": {}, "HGROUP": {}, "NAV": {}, "P": {}, "PRE": {}, "SECTION": {},
"address": {}, "article": {}, "aside": {}, "blockquote": {}, "center": {}, "dir": {}, "div": {}, "fieldset": {}, "figure": {}, "footer": {}, "form": {},
"h1": {}, "h2": {}, "h3": {}, "h4": {}, "h5": {}, "h6": {}, "header": {}, "hgroup": {}, "nav": {}, "p": {}, "pre": {}, "section": {}
});
});
test('isValidChild', function() {
expect(4);
var schema = new tinymce.html.Schema();
ok(schema.isValidChild('body', 'p'));
ok(schema.isValidChild('p', 'img'));
ok(!schema.isValidChild('body', 'body'));
ok(!schema.isValidChild('p', 'body'));
});
test('getElementRule', function() {
expect(3);
var schema = new tinymce.html.Schema();
ok(schema.getElementRule('b'));
ok(!schema.getElementRule('bx'));
ok(!schema.getElementRule(null));
});
test('addCustomElements', function() {
expect(5);
var schema = new tinymce.html.Schema({valid_elements:'inline,block'});
schema.addCustomElements('~inline,block');
ok(schema.getElementRule('inline'));
ok(schema.getElementRule('block'));
ok(schema.isValidChild('body', 'block'));
ok(schema.isValidChild('block', 'inline'));
ok(schema.isValidChild('p', 'inline'));
});
test('addValidChildren', function() {
expect(7);
var schema = new tinymce.html.Schema();
ok(schema.isValidChild('body', 'p'));
ok(!schema.isValidChild('body', 'body'));
ok(!schema.isValidChild('body', 'html'));
schema.addValidChildren('+body[body|html]');
ok(schema.isValidChild('body', 'body'));
ok(schema.isValidChild('body', 'html'));
var schema = new tinymce.html.Schema();
ok(schema.isValidChild('body', 'p'));
schema.addValidChildren('-body[p]');
ok(!schema.isValidChild('body', 'p'));
});
test('addCustomElements/getCustomElements', function() {
expect(4);
var schema = new tinymce.html.Schema();
schema.addCustomElements('~inline,block');
ok(schema.getBlockElements()['block']);
ok(!schema.getBlockElements()['inline']);
ok(schema.getCustomElements()['inline']);
ok(schema.getCustomElements()['block']);
});
test('whitespaceElements', function() {
expect(3);
var schema = new tinymce.html.Schema({whitespace_elements : 'pre,p'});
ok(schema.getWhiteSpaceElements()['pre']);
ok(!schema.getWhiteSpaceElements()['span']);
var schema = new tinymce.html.Schema({whitespace_elements : 'code'});
ok(schema.getWhiteSpaceElements()['code']);
});
test('selfClosingElements', function() {
expect(3);
var schema = new tinymce.html.Schema({self_closing_elements : 'pre,p'});
ok(schema.getSelfClosingElements()['pre']);
ok(schema.getSelfClosingElements()['p']);
ok(!schema.getSelfClosingElements()['li']);
});
test('shortEndedElements', function() {
expect(3);
var schema = new tinymce.html.Schema({short_ended_elements : 'pre,p'});
ok(schema.getShortEndedElements()['pre']);
ok(schema.getShortEndedElements()['p']);
ok(!schema.getShortEndedElements()['img']);
});
test('booleanAttributes', function() {
expect(3);
var schema = new tinymce.html.Schema({boolean_attributes : 'href,alt'});
ok(schema.getBoolAttrs()['href']);
ok(schema.getBoolAttrs()['alt']);
ok(!schema.getBoolAttrs()['checked']);
});
test('nonEmptyElements', function() {
expect(3);
var schema = new tinymce.html.Schema({non_empty_elements : 'pre,p'});
ok(schema.getNonEmptyElements()['pre']);
ok(schema.getNonEmptyElements()['p']);
ok(!schema.getNonEmptyElements()['img']);
});
test('blockElements', function() {
expect(3);
var schema = new tinymce.html.Schema({block_elements : 'pre,p'});
ok(schema.getBlockElements()['pre']);
ok(schema.getBlockElements()['p']);
ok(!schema.getBlockElements()['h1']);
});
test('isValid', function() {
var schema = new tinymce.html.Schema({valid_elements : 'a[href],i[*]'});
ok(schema.isValid('a'));
ok(schema.isValid('a', 'href'));
ok(!schema.isValid('b'));
ok(!schema.isValid('b', 'href'));
ok(!schema.isValid('a', 'id'));
ok(schema.isValid('i'));
ok(schema.isValid('i', 'id'));
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Schema tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Serializer tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Serializer");
QUnit.config.reorder = false;
test('Basic serialization', function() {
var serializer = new tinymce.html.Serializer();
expect(6);
equal(serializer.serialize(new tinymce.html.DomParser().parse('text<text&')), 'text&lt;text&amp;');
equal(serializer.serialize(new tinymce.html.DomParser().parse('<B>text</B><IMG src="1.gif">')), '<strong>text</strong><img src="1.gif" alt="" />');
equal(serializer.serialize(new tinymce.html.DomParser().parse('<!-- comment -->')), '<!-- comment -->');
equal(serializer.serialize(new tinymce.html.DomParser().parse('<![CDATA[cdata]]>')), '<![CDATA[cdata]]>');
equal(serializer.serialize(new tinymce.html.DomParser().parse('<?xml attr="value" ?>')), '<?xml attr="value" ?>');
equal(serializer.serialize(new tinymce.html.DomParser().parse('<!DOCTYPE html>')), '<!DOCTYPE html>');
});
test('Sorting of attributes', function() {
var serializer = new tinymce.html.Serializer();
expect(1);
equal(serializer.serialize(new tinymce.html.DomParser().parse('<b class="class" id="id">x</b>')), '<strong id="id" class="class">x</strong>');
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Serializer tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,176 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Styles tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Styles");
QUnit.config.reorder = false;
test('Basic parsing/serializing', function() {
var styles = new tinymce.html.Styles();
expect(11);
equal(styles.serialize(styles.parse('FONT-SIZE:10px')), "font-size: 10px;");
equal(styles.serialize(styles.parse('FONT-SIZE:10px;COLOR:red')), "font-size: 10px; color: red;");
equal(styles.serialize(styles.parse(' FONT-SIZE : 10px ; COLOR : red ')), "font-size: 10px; color: red;");
equal(styles.serialize(styles.parse('key:"value"')), "key: 'value';");
equal(styles.serialize(styles.parse('key:"value1" \'value2\'')), "key: 'value1' 'value2';");
equal(styles.serialize(styles.parse('key:"val\\"ue1" \'val\\\'ue2\'')), "key: 'val\"ue1' 'val\\'ue2';");
equal(styles.serialize(styles.parse('width:100%')), 'width: 100%;');
equal(styles.serialize(styles.parse('value:_; value2:"_"')), 'value: _; value2: \'_\';');
equal(styles.serialize(styles.parse('value: "&amp;"')), "value: '&amp;';");
equal(styles.serialize(styles.parse('value: "&"')), "value: '&';");
equal(styles.serialize(styles.parse('value: ')), "");
});
test('Colors force hex and lowercase', function() {
var styles = new tinymce.html.Styles();
expect(6);
equal(styles.serialize(styles.parse('color: rgb(1,2,3)')), "color: #010203;");
equal(styles.serialize(styles.parse('color: RGB(1,2,3)')), "color: #010203;");
equal(styles.serialize(styles.parse('color: #FF0000')), "color: #ff0000;");
equal(styles.serialize(styles.parse(' color: RGB ( 1 , 2 , 3 ) ')), "color: #010203;");
equal(styles.serialize(styles.parse(' FONT-SIZE : 10px ; COLOR : RGB ( 1 , 2 , 3 ) ')), "font-size: 10px; color: #010203;");
equal(styles.serialize(styles.parse(' FONT-SIZE : 10px ; COLOR : RED ')), "font-size: 10px; color: red;");
});
test('Urls convert urls and force format', function() {
var styles = new tinymce.html.Styles({url_converter : function(url) {
return '|' + url + '|';
}});
expect(9);
equal(styles.serialize(styles.parse('background: url(a)')), "background: url('|a|');");
equal(styles.serialize(styles.parse('background: url("a")')), "background: url('|a|');");
equal(styles.serialize(styles.parse("background: url('a')")), "background: url('|a|');");
equal(styles.serialize(styles.parse('background: url( a )')), "background: url('|a|');");
equal(styles.serialize(styles.parse('background: url( "a" )')), "background: url('|a|');");
equal(styles.serialize(styles.parse("background: url( 'a' )")), "background: url('|a|');");
equal(styles.serialize(styles.parse('background1: url(a); background2: url("a"); background3: url(\'a\')')), "background1: url('|a|'); background2: url('|a|'); background3: url('|a|');");
equal(styles.serialize(styles.parse("background: url('http://www.site.com/a?a=b&c=d')")), "background: url('|http://www.site.com/a?a=b&c=d|');");
equal(styles.serialize(styles.parse("background: url('http://www.site.com/a_190x144.jpg');")), "background: url('|http://www.site.com/a_190x144.jpg|');");
});
test('Compress styles', function() {
var styles = new tinymce.html.Styles();
equal(
styles.serialize(styles.parse('border-top: 1px solid red; border-left: 1px solid red; border-bottom: 1px solid red; border-right: 1px solid red;')),
'border: 1px solid red;'
);
equal(
styles.serialize(styles.parse('border-width: 1pt 1pt 1pt 1pt; border-style: none none none none; border-color: black black black black;')),
'border: 1pt none black;'
);
equal(
styles.serialize(styles.parse('border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;')),
'border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;'
);
equal(
styles.serialize(styles.parse('border-top: 1px solid red; border-left: 1px solid red; border-right: 1px solid red; border-bottom: 1px solid red')),
'border: 1px solid red;'
);
equal(
styles.serialize(styles.parse('border-top: 1px solid red; border-right: 2px solid red; border-bottom: 3px solid red; border-left: 4px solid red')),
'border-top: 1px solid red; border-right: 2px solid red; border-bottom: 3px solid red; border-left: 4px solid red;'
);
equal(
styles.serialize(styles.parse('padding-top: 1px; padding-right: 2px; padding-bottom: 3px; padding-left: 4px')),
'padding: 1px 2px 3px 4px;'
);
equal(
styles.serialize(styles.parse('margin-top: 1px; margin-right: 2px; margin-bottom: 3px; margin-left: 4px')),
'margin: 1px 2px 3px 4px;'
);
equal(
styles.serialize(styles.parse('margin-top: 1px; margin-right: 1px; margin-bottom: 1px; margin-left: 2px')),
'margin: 1px 1px 1px 2px;'
);
equal(
styles.serialize(styles.parse('margin-top: 2px; margin-right: 1px; margin-bottom: 1px; margin-left: 1px')),
'margin: 2px 1px 1px 1px;'
);
equal(
styles.serialize(styles.parse('border-top-color: red; border-right-color: green; border-bottom-color: blue; border-left-color: yellow')),
'border-color: red green blue yellow;'
);
equal(
styles.serialize(styles.parse('border-width: 1px; border-style: solid; border-color: red')),
'border: 1px solid red;'
);
equal(
styles.serialize(styles.parse('border-width: 1px; border-color: red')),
'border-width: 1px; border-color: red;'
);
});
test('Font weight', function() {
var styles = new tinymce.html.Styles();
expect(1);
equal(styles.serialize(styles.parse('font-weight: 700')), "font-weight: bold;");
});
test('Valid styles', function() {
var styles = new tinymce.html.Styles({}, new tinymce.html.Schema({valid_styles : {'*' : 'color,font-size', 'a' : 'margin-left'}}));
expect(2);
equal(styles.serialize(styles.parse('color: #ff0000; font-size: 10px; margin-left: 10px; invalid: 1;'), 'b'), "color: #ff0000; font-size: 10px;");
equal(styles.serialize(styles.parse('color: #ff0000; font-size: 10px; margin-left: 10px; invalid: 2;'), 'a'), "color: #ff0000; font-size: 10px; margin-left: 10px;");
});
test('Script urls denied', function() {
var styles = new tinymce.html.Styles();
equal(styles.serialize(styles.parse('behavior:url(test.htc)')), "");
equal(styles.serialize(styles.parse('color:expression(alert(1))')), "");
equal(styles.serialize(styles.parse('color: expression ( alert(1))')), "");
equal(styles.serialize(styles.parse('background:url(jAvaScript:alert(1)')), "");
equal(styles.serialize(styles.parse('background:url(javascript:alert(1)')), "");
equal(styles.serialize(styles.parse('background:url(vbscript:alert(1)')), "");
equal(styles.serialize(styles.parse('background:url(j\navas\u0000cr\tipt:alert(1)')), "");
});
test('Script urls allowed', function() {
var styles = new tinymce.html.Styles({allow_script_urls: true});
equal(styles.serialize(styles.parse('behavior:url(test.htc)')), "behavior: url('test.htc');");
equal(styles.serialize(styles.parse('color:expression(alert(1))')), "color: expression(alert(1));");
equal(styles.serialize(styles.parse('background:url(javascript:alert(1)')), "background: url('javascript:alert(1');");
equal(styles.serialize(styles.parse('background:url(vbscript:alert(1)')), "background: url('vbscript:alert(1');");
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Styles tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,174 @@
<!DOCTYPE html>
<html>
<head>
<title>tinymce.html.Writer tests</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
module("tinymce.html.Writer");
QUnit.config.reorder = false;
test('Comment', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.comment('text');
equal(writer.getContent(), '<!--text-->');
var writer = new tinymce.html.Writer();
writer.comment('');
equal(writer.getContent(), '<!---->');
});
test('CDATA', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.cdata('text');
equal(writer.getContent(), '<![CDATA[text]]>');
var writer = new tinymce.html.Writer();
writer.cdata('');
equal(writer.getContent(), '<![CDATA[]]>');
});
test('PI', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.pi('xml', 'someval');
equal(writer.getContent(), '<?xml someval?>');
var writer = new tinymce.html.Writer();
writer.pi('xml');
equal(writer.getContent(), '<?xml?>');
});
test('Doctype', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.doctype(' text');
equal(writer.getContent(), '<!DOCTYPE text>');
var writer = new tinymce.html.Writer();
writer.doctype('');
equal(writer.getContent(), '<!DOCTYPE>');
});
test('Text', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.text('te<xt');
equal(writer.getContent(), 'te&lt;xt');
var writer = new tinymce.html.Writer();
writer.text('');
equal(writer.getContent(), '');
});
test('Text raw', function() {
expect(2);
var writer = new tinymce.html.Writer();
writer.text('te<xt', true);
equal(writer.getContent(), 'te<xt');
var writer = new tinymce.html.Writer();
writer.text('', true);
equal(writer.getContent(), '');
});
test('Start', function() {
expect(5);
var writer = new tinymce.html.Writer();
writer.start('b');
equal(writer.getContent(), '<b>');
var writer = new tinymce.html.Writer();
writer.start('b', [{name: 'attr1', value: 'value1'}, {name: 'attr2', value: 'value2'}]);
equal(writer.getContent(), '<b attr1="value1" attr2="value2">');
var writer = new tinymce.html.Writer();
writer.start('b', [{name: 'attr1', value: 'val<"ue1'}]);
equal(writer.getContent(), '<b attr1="val&lt;&quot;ue1">');
var writer = new tinymce.html.Writer();
writer.start('img', [{name: 'attr1', value: 'value1'}, {name: 'attr2', value: 'value2'}], true);
equal(writer.getContent(), '<img attr1="value1" attr2="value2" />');
var writer = new tinymce.html.Writer();
writer.start('br', null, true);
equal(writer.getContent(), '<br />');
});
test('End', function() {
expect(1);
var writer = new tinymce.html.Writer();
writer.end('b');
equal(writer.getContent(), '</b>');
});
test('Indentation', function() {
expect(2);
var writer = new tinymce.html.Writer({indent: true, indent_before: 'p', indent_after:'p'});
writer.start('p');
writer.start('span');
writer.text('a');
writer.end('span');
writer.end('p');
writer.start('p');
writer.text('a');
writer.end('p');
equal(writer.getContent(), '<p><span>a</span></p>\n<p>a</p>');
var writer = new tinymce.html.Writer({indent: true, indent_before: 'p', indent_after:'p'});
writer.start('p');
writer.text('a');
writer.end('p');
equal(writer.getContent(), '<p>a</p>');
});
test('Entities', function() {
expect(3);
var writer = new tinymce.html.Writer();
writer.start('p', [{name: "title", value: '<>"\'&\u00e5\u00e4\u00f6'}]);
writer.text('<>"\'&\u00e5\u00e4\u00f6');
writer.end('p');
equal(writer.getContent(), '<p title="&lt;&gt;&quot;\'&amp;\u00e5\u00e4\u00f6">&lt;&gt;"\'&amp;\u00e5\u00e4\u00f6</p>');
var writer = new tinymce.html.Writer({entity_encoding: 'numeric'});
writer.start('p', [{name: "title", value: '<>"\'&\u00e5\u00e4\u00f6'}]);
writer.text('<>"\'&\u00e5\u00e4\u00f6');
writer.end('p');
equal(writer.getContent(), '<p title="&lt;&gt;&quot;\'&amp;&#229;&#228;&#246;">&lt;&gt;"\'&amp;&#229;&#228;&#246;</p>');
var writer = new tinymce.html.Writer({entity_encoding: 'named'});
writer.start('p', [{name: "title", value: '<>"\'&\u00e5\u00e4\u00f6'}]);
writer.text('<>"\'&\u00e5\u00e4\u00f6');
writer.end('p');
equal(writer.getContent(), '<p title="&lt;&gt;&quot;\'&amp;&aring;&auml;&ouml;">&lt;&gt;"\'&amp;&aring;&auml;&ouml;</p>');
});
</script>
</head>
<body>
<h1 id="qunit-header">tinymce.html.Writer tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="content"></div>
</body>
</html>

View File

@ -0,0 +1,294 @@
<!DOCTYPE html>
<html>
<head>
<title>Support for obsolete tags and attributes in the default HTML 5.0 schema</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script>
var editor;
QUnit.config.reorder = false;
QUnit.config.autostart = false;
module("tinymce.html.Schema", {
autostart: false
});
function getContent() {
return editor.getContent().replace(/[\r\n]+/g, '');
};
/**
* Test whether attribute exists in a HTML string
*
* @param html The HTML string
* @param attr string|object When string, test for the first instance of attr.
* When object, break up the HTML string into individual tags and test for attr in the specified tag.
* Format: { tagName: 'attr1 attr2', ... }
* @return bool
*/
function hasAttr( html, attr ) {
var tagName, tags, tag, array, regex, i;
if ( typeof attr === 'string' ) {
return new RegExp( ' \\b' + attr + '\\b' ).test( html );
}
for ( tagName in attr ) {
if ( tags = html.match( new RegExp( '<' + tagName + ' [^>]+>', 'g' ) ) ) {
for ( tag in tags ) {
array = attr[tagName].split(' ');
for ( i in array ) {
regex = new RegExp( '\\b' + array[i] + '\\b' );
if ( regex.test( tags[tag] ) ) {
attr[tagName] = attr[tagName].replace( regex, '' );
}
}
}
if ( attr[tagName].replace( / +/g, '' ).length ) {
return false;
}
}
}
return true;
}
// Ref: http://www.w3.org/TR/html5/obsolete.html, http://developers.whatwg.org/obsolete.html
test('HTML elements non-conforming to HTML 5.0', function() {
var testString;
/*
Not supported, deprecated in HTML 4.0 or earlier, and/or proprietary:
applet
bgsound
dir
frame
frameset
noframes
isindex
listing
nextid
noembed
plaintext
rb
xmp
basefont
blink
marquee
multicol
nobr
spacer
The rest are still supported in TinyMCE but "...must not be used by authors".
*/
expect(6);
text = 'acronym';
testString = '<p><acronym title="www">WWW</acronym></p>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'strike, converted to span';
editor.setContent( '<strike>test</strike>' );
equal( getContent(), '<p><span style="text-decoration: line-through;">test</span></p>', text );
text = 'big';
testString = '<p><big>test</big></p>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'center';
testString = '<center>test</center>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'font, converted to span';
editor.setContent( '<p><font size="4">test</font></p>' );
equal( getContent(), '<p><span style="font-size: large;">test</span></p>', text );
text = 'tt';
testString = '<p><tt>test</tt></p>';
editor.setContent( testString );
equal( getContent(), testString, text );
});
test('Obsolete (but still conforming) HTML attributes', function() {
var testString;
expect(3);
text = 'border on <img>';
testString = '<p><img src="../../test.gif" alt="" border="5" /></p>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'Old style anchors';
testString = '<p><a name="test"></a></p>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'maxlength, size on input type="number"';
testString = '<p><input maxlength="5" size="10" type="number" value="" /></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { input: 'maxlength size' } ), text );
});
test('Obsolete attributes in HTML 5.0', function() {
var testString, text;
expect(22);
text = 'charset, rev, shape, coords on <a> elements';
testString = '<p><a href="javascript;:" charset="en" rev="made" shape="rect" coords="5,5">test</a></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { a: 'charset rev shape coords' } ), text );
text = 'name, align, hspace, vspace on img elements';
testString = '<p><img src="../../test.gif" alt="" name="test" align="left" hspace="5" vspace="5" /></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { img: 'name align hspace vspace' } ), text );
text = 'name, align, hspace, vspace, on embed elements';
testString = '<p><embed width="100" height="100" src="test.swf" vspace="5" hspace="5" align="left" name="test"></embed></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { embed: 'name align hspace vspace' } ), text );
text = 'archive, classid, code, codebase, codetype, declare, standby on object elements';
testString = '<p><object width="100" height="100" classid="clsid" codebase="clsid" standby="standby" codetype="1" code="1" archive="1" declare="declare"></object></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { object: 'archive classid code codebase codetype declare standby' } ), text );
text = 'type, valuetype on param elements';
testString = '<p><object width="100" height="100"><param type="" valuetype="" /></object></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { param: 'type valuetype' } ), text );
text = 'align, bgcolor, border, cellpadding, cellspacing, frame, rules, summary, width on table elements';
testString = '<table border="1" summary="" width="100" frame="" rules="" cellspacing="5" cellpadding="5" align="left" bgcolor="blue"><tbody><tr><td>test</td></tr></tbody></table>';
editor.setContent( testString );
ok( hasAttr( getContent(), { table: 'align bgcolor border cellpadding cellspacing frame rules summary width' } ), text );
text = 'align, char, charoff, valign on tbody, thead, and tfoot elements';
testString = '<table><thead align="left" char="" charoff="" valign="top"></thead><tfoot align="left" char="" charoff="" valign="top"></tfoot><tbody align="left" char="" charoff="" valign="top"><tr><th>test</th><td>test</td></tr></tbody></table>';
editor.setContent( testString );
ok( hasAttr( getContent(), {
thead: 'align char charoff valign',
tfoot: 'align char charoff valign',
tbody: 'align char charoff valign'
} ), text );
text = 'axis, align, bgcolor, char, charoff, height, nowrap, valign, width on td and th elements, scope on td elements';
testString = '<table><tbody><tr><th axis="" align="left" char="" charoff="" valign="top" nowrap="nowrap" bgcolor="blue" width="100" height="10">test</th><td axis="" align="left" char="" charoff="" valign="top" nowrap="nowrap" bgcolor="blue" width="100" height="10" scope="">test</td></tr></tbody></table>';
editor.setContent( testString );
ok( hasAttr( getContent(), {
th: 'axis align bgcolor char charoff height nowrap valign width',
td: 'axis align bgcolor char charoff height nowrap valign width scope'
} ), text );
text = 'align, bgcolor, char, charoff, valign on tr elements';
testString = '<table><tbody><tr align="left" char="" charoff="" valign="top" bgcolor="blue"><td>test</td></tr></tbody></table>';
editor.setContent( testString );
ok( hasAttr( getContent(), { tr: 'align bgcolor char charoff valign' } ), text );
text = 'clear on br elements';
testString = '<p>test<br clear="all" />test</p>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'align on caption elements';
testString = '<table><caption align="left">test</caption><tbody><tr><td>test</td></tr></tbody></table>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'align, char, charoff, valign, width on col elements';
testString = '<table><colgroup><col width="100" align="left" char="a" charoff="1" valign="top" /><col /></colgroup><tbody><tr><td>test</td><td>test</td></tr></tbody></table>';
editor.setContent( testString );
ok( hasAttr( getContent(), { col: 'align char charoff valign width' } ), text );
text = 'align on div, h1—h6, input, legend, p elements';
testString = '<div align="left">1</div><h3 align="left">1</h3><p align="left">1</p><form><fieldset><legend align="left">test</legend><input type="text" align="left" /></fieldset></form>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'compact on dl elements';
testString = '<dl compact="compact"><dd>1</dd></dl>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'align, hspace, vspace on embed elements';
testString = '<p><embed width="100" height="100" vspace="5" hspace="5" align="left"></embed></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { embed: 'align hspace vspace' } ), text );
text = 'align, noshade, size, width on hr elements';
testString = '<hr align="left" noshade="noshade" size="1" width="100" />';
editor.setContent( testString );
ok( hasAttr( getContent(), { hr: 'align noshade size width' } ), text );
text = 'align, frameborder, marginheight, marginwidth, scrolling on iframe elements';
testString = '<p><iframe width="100" height="100" frameborder="1" marginwidth="5" marginheight="5" scrolling="" align="left"></iframe></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { iframe: 'align frameborder marginheight marginwidth scrolling' } ), text );
text = 'type on li elements';
testString = '<ul><li type="disc">test</li></ul>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'align, border, hspace, vspace on object elements';
testString = '<p><object width="100" height="100" border="1" vspace="5" hspace="5" align="left"></object></p>';
editor.setContent( testString );
ok( hasAttr( getContent(), { object: 'align border hspace vspace' } ), text );
text = 'compact on ol elements';
testString = '<ol compact="compact"><li>test</li></ol>';
editor.setContent( testString );
equal( getContent(), testString, text );
text = 'compact, type on ul elements';
testString = '<ul type="disc" compact="compact"><li>test</li></ul>';
editor.setContent( testString );
ok( hasAttr( getContent(), { ul: 'compact type' } ), text );
text = 'width on pre elements';
testString = '<pre width="100">1</pre>';
editor.setContent( testString );
equal( getContent(), testString, text );
});
tinymce.init({
mode : "exact",
elements : "elm1",
add_unload_trigger : false,
indent : false,
entities : 'raw',
plugins: 'media',
convert_urls : false,
init_instance_callback : function(ed) {
editor = ed;
QUnit.start();
}
});
</script>
</head>
<body>
<h1 id="qunit-header">Support for obsolete tags and attributes in the default HTML 5.0 schema</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<textarea id="elm1" name="elm1"></textarea>
<div>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent({format : 'raw'}));">[getRawContents]</a>
<a href="javascript:alert(tinymce.EditorManager.get('elm1').getContent());">[getContents]</a>
</div>
</body>
</html>

View File

@ -0,0 +1,14 @@
{
"title": "tinymce.html",
"tests": [
{"title": "DomParser", "url": "DomParser.html"},
{"title": "Entities", "url": "Entities.html"},
{"title": "Node", "url": "Node.html"},
{"title": "SaxParser", "url": "SaxParser.html"},
{"title": "Schema", "url": "Schema.html"},
{"title": "Serializer", "url": "Serializer.html"},
{"title": "Styles", "url": "Styles.html"},
{"title": "Writer", "url": "Writer.html"},
{"title": "Obsolete tags and attributes", "url": "obsolete.html"}
]
}

View File

@ -0,0 +1,15 @@
{
"title": "tinymce",
"tests": [
{"title": "Editor", "url": "Editor.html"},
{"title": "EditorCommands", "url": "EditorCommands.html"},
{"title": "EnterKey", "url": "EnterKey.html"},
{"title": "ForceBlocks", "url": "ForceBlocks.html"},
{"title": "Formatter (Apply)", "url": "Formatter_apply.html"},
{"title": "Formatter (Remove)", "url": "Formatter_remove.html"},
{"title": "Formatter (Check)", "url": "Formatter_check.html"},
{"title": "Formatter (jsrobot)", "url": "Formatter_robot.html", "jsrobot":true},
{"title": "UndoManager", "url": "UndoManager.html"},
{"title": "Undo", "url": "UndoManager_robot.html", "jsrobot": true}
]
}

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.AbsoluteLayout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.AbsoluteLayout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function createPanel(settings) {
return tinymce.ui.Factory.create(tinymce.extend({
type: 'panel',
layout: 'absolute',
width: 200,
height: 200
}, settings)).renderTo(document.getElementById('view')).reflow();
}
test("spacer x:10, y:20, minWidth: 100, minHeight: 100", function() {
panel = createPanel({
items: [
{type: 'spacer', x: 10, y: 20, w: 100, h: 120, classes: 'red'}
]
});
deepEqual(rect(panel), [0, 0, 200, 200]);
deepEqual(rect(panel.find('spacer')[0]), [10, 20, 100, 120]);
});
</script>
</head>
<body>
<h1 id="qunit-header">ui.AbsoluteLayout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,133 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Button Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Button", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function createButton(settings) {
return tinymce.ui.Factory.create(tinymce.extend({
type: 'button'
}, settings)).renderTo(document.getElementById('view'));
}
test("button text, size default", function() {
var button = createButton({text: 'X'});
nearlyEqualRects(rect(button), [0, 0, 34, 30], 4);
});
test("button text, size large", function() {
var button = createButton({text: 'X', size: 'large'});
nearlyEqualRects(rect(button), [0, 0, 41, 39], 4);
});
test("button text, size small", function() {
var button = createButton({text: 'X', size: 'small'});
nearlyEqualRects(rect(button), [0, 0, 19, 23], 4);
});
test("button text, width 100, height 100", function() {
var button = createButton({text: 'X', width: 100, height: 100});
deepEqual(rect(button), [0, 0, 100, 100]);
deepEqual(rect(button.getEl().firstChild), [1, 1, 98, 98]);
});
test("button icon, size default", function() {
var button = createButton({icon: 'test'});
nearlyEqualRects(rect(button), [0, 0, 40, 30], 4);
});
test("button icon, size small", function() {
var button = createButton({icon: 'test', size: 'small'});
nearlyEqualRects(rect(button), [0, 0, 28, 24], 4);
});
test("button icon, size large", function() {
var button = createButton({icon: 'test', size: 'large'});
nearlyEqualRects(rect(button), [0, 0, 44, 40], 4);
});
test("button icon, width 100, height 100", function() {
var button = createButton({icon: 'test', width: 100, height: 100});
deepEqual(rect(button), [0, 0, 100, 100]);
deepEqual(rect(button.getEl().firstChild), [1, 1, 98, 98]);
});
test("button text & icon, size default", function() {
var button = createButton({text: 'X', icon: 'test'});
nearlyEqualRects(rect(button), [0, 0, 52, 30], 4);
});
test("button text & icon, size large", function() {
var button = createButton({text: 'X', icon: 'test', size: 'large'});
nearlyEqualRects(rect(button), [0, 0, 59, 40], 4);
});
test("button text & icon, size small", function() {
var button = createButton({text: 'X', icon: 'test', size: 'small'});
nearlyEqualRects(rect(button), [0, 0, 38, 24], 4);
});
test("button text & icon, width 100, height 100", function() {
var button = createButton({text: 'X', icon: 'test', width: 100, height: 100});
deepEqual(rect(button), [0, 0, 100, 100]);
deepEqual(rect(button.getEl().firstChild), [1, 1, 98, 98]);
});
test("button click event", function() {
var button, clicks = {};
button = createButton({text: 'X', onclick: function() {clicks.a = 'a';}});
button.on('click', function() {clicks.b = 'b';});
button.on('click', function() {clicks.c = 'c';});
button.fire('click');
deepEqual(clicks, {a: 'a', b: 'b', c: 'c'});
});
</script>
</head>
<body>
<h1 id="qunit-header">Button Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.ButtonGroup Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.ButtonGroup", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.ButtonGroup Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Checkbox Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Checkbox", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Checkbox Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,273 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Collection Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
module("ui.Collection");
window.onload = function() {
panel = tinymce.ui.Factory.create({
type: 'panel',
items: [
{type: 'button', name: 'button1', text: 'button1', classes: 'class1', disabled: true},
{type: 'button', name: 'button2', classes: 'class1 class2'},
{type: 'button', name: 'button3', classes: 'class2 class1 class3'},
{type: 'buttongroup', name: 'buttongroup1', items: [
{type: 'button', name: 'button4'},
{type: 'button', name: 'button5'},
{type: 'button', name: 'button6'}
]},
{type: 'buttongroup', name: 'buttongroup2', items: [
{type: 'button', name: 'button7'},
{type: 'button', name: 'button8'},
{type: 'button', name: 'button9'}
]},
{type: 'toolbar', name: 'toolbar1', items: [
{type: 'buttongroup', name: 'buttongroup3', items: [
{type: 'button', name: 'button10', disabled: true},
{type: 'button', name: 'button11'},
{type: 'button', name: 'button12', classes: 'class4'}
]}
]}
]
}).renderTo(document.getElementById('view'));
QUnit.start();
};
test("Constructor", function() {
equal(new tinymce.ui.Collection().length, 0);
equal(new tinymce.ui.Collection(panel.find('button').toArray()).length, 12);
equal(new tinymce.ui.Collection(panel.find('button')).length, 12);
equal(new tinymce.ui.Collection(panel.find('button:first')[0]).length, 1);
equal(new tinymce.ui.Collection(panel.find('button:first')[0])[0].type, 'button');
});
test("add", function() {
var collection = new tinymce.ui.Collection([panel, panel]);
equal(collection.add(panel).length, 3);
equal(collection.add([panel, panel]).length, 5);
});
test("set", function() {
var collection = new tinymce.ui.Collection([panel, panel]);
equal(collection.set(panel).length, 1);
equal(collection.set([panel, panel]).length, 2);
});
test("filter", function() {
equal(panel.find('button').filter('*:first').length, 4);
equal(panel.find('button').filter('buttongroup button').length, 9);
equal(panel.find('button').filter('*').length, 12);
equal(panel.find('button').filter('nomatch').length, 0);
equal(panel.find('button').filter(function(ctrl) {return ctrl.settings.name == "button7";}).length, 1);
});
test("slice", function() {
equal(panel.find('button').slice(1).length, 11);
equal(panel.find('button').slice(1)[0].name(), 'button2');
equal(panel.find('button').slice(0, 1).length, 1);
equal(panel.find('button').slice(0, 1)[0].name(), 'button1');
equal(panel.find('button').slice(-1).length, 1);
equal(panel.find('button').slice(-1)[0].name(), 'button12');
equal(panel.find('button').slice(-2).length, 2);
equal(panel.find('button').slice(-2)[0].name(), 'button11');
equal(panel.find('button').slice(-2, -1).length, 1);
equal(panel.find('button').slice(-2, -1)[0].name(), 'button11');
equal(panel.find('button').slice(1000).length, 0);
equal(panel.find('button').slice(-1000).length, 12);
});
test("eq", function() {
equal(panel.find('button').eq(1).length, 1);
equal(panel.find('button').eq(1)[0].name(), 'button2');
equal(panel.find('button').eq(-2).length, 1);
equal(panel.find('button').eq(-2)[0].name(), 'button11');
equal(panel.find('button').eq(1000).length, 0);
});
test("each", function() {
var count;
count = 0;
panel.find('button').each(function() {
count++;
});
equal(count, 12);
count = 0;
panel.find('nomatch').each(function() {
count++;
});
equal(count, 0);
count = 0;
panel.find('button').each(function(item, index) {
count += index;
});
equal(count, 66);
count = 0;
panel.find('button').each(function(item, index) {
if (item.type == 'button')
count++;
});
equal(count, 12);
count = 0;
panel.find('button').each(function(item, index) {
count++;
if (index == 3)
return false;
});
equal(count, 4);
});
test("toArray", function() {
equal(panel.find('button').toArray().length, 12);
equal(panel.find('button').toArray().concat, Array.prototype.concat);
});
test("fire/on/off", function() {
var value;
value = 0;
panel.find('button').off();
panel.find('button#button1,button#button2').on('test', function(args) {
value += args.value;
});
panel.find('button#button1').fire('test', {value: 42});
equal(value, 42);
value = 0;
panel.find('button').off();
panel.find('button#button1,button#button2').on('test', function(args) {
value += args.value;
});
panel.find('button').fire('test', {value: 42});
equal(value, 84);
value = 0;
panel.find('button').off();
panel.find('button#button1,button#button2').on('test', function(args) {
value += args.value;
});
panel.find('button#button1').off('test');
panel.find('button').fire('test', {value: 42});
equal(value, 42);
panel.find('button').off();
value = 0;
panel.find('button').fire('test', {value: 42});
equal(value, 0);
});
test("show/hide", function() {
panel.find('button#button1,button#button2').hide();
equal(panel.find('button:not(:visible)').length, 2);
panel.find('button#button1').show();
equal(panel.find('button:not(:visible)').length, 1);
panel.find('button#button2').show();
});
test("text", function() {
equal(panel.find('button#button1,button#button2').text(), 'button1');
equal(panel.find('button#button2').text('button2').text(), 'button2');
equal(panel.find('button#button2,button#button3').text('test').text(), 'test');
equal(panel.find('button#button3').text(), 'test');
});
test("disabled", function() {
ok(panel.find('button#button1').disabled());
ok(!panel.find('button#button2').disabled());
ok(panel.find('button#button2').disabled(true).disabled());
panel.find('button#button2').disabled(false);
});
test("visible", function() {
ok(panel.find('button#button2').visible());
ok(!panel.find('button#button2').visible(false).visible());
panel.find('button#button2').visible(true);
});
test("active", function() {
ok(!panel.find('button#button2').active());
ok(panel.find('button#button2').active(true).active());
panel.find('button#button2').active(false);
});
test("name", function() {
equal(panel.find('button#button1').name(), 'button1');
equal(panel.find('button#button2').name('buttonX').name(), 'buttonX');
panel.find('button#buttonX').name('button2');
});
test("addClass/removeClass/hasClass", function() {
panel.find('button#button1').addClass('test');
ok(panel.find('button#button1').hasClass('test'));
ok(!panel.find('button#button1').hasClass('nomatch'));
panel.find('button#button1').removeClass('test');
ok(!panel.find('button#button1').hasClass('test'));
});
test("prop", function() {
ok(panel.find('button#button1').prop('disabled'));
equal(panel.find('button#button1').prop('name'), 'button1');
equal(panel.find('button#button1').prop('name', 'buttonX').prop('name'), 'buttonX');
panel.find('button#buttonX').prop('name', 'button1');
equal(panel.find('button#button1').prop('missingProperty'), undefined);
});
test("exec", function() {
ok(!panel.find('button#button1').exec('disabled', false).disabled());
panel.find('button#button1').disabled(true);
});
</script>
</head>
<body>
<h1 id="qunit-header">ui.Collection Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Button Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.ColorButton", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function createColorButton(settings) {
return tinymce.ui.Factory.create(tinymce.extend({
type: 'colorbutton'
}, settings)).renderTo(document.getElementById('view'));
}
test("colorbutton text, size default", function() {
var colorButton = createColorButton({text: 'X'});
nearlyEqualRects(rect(colorButton), [0, 0, 42, 30], 4);
});
test("colorbutton text, size large", function() {
var colorButton = createColorButton({text: 'X', size: 'large'});
nearlyEqualRects(rect(colorButton), [0, 0, 49, 39], 4);
});
test("colorbutton text, size small", function() {
var colorButton = createColorButton({text: 'X', size: 'small'});
nearlyEqualRects(rect(colorButton), [0, 0, 34, 23], 4);
});
test("colorbutton text, width 100, height 100", function() {
var colorButton = createColorButton({text: 'X', width: 100, height: 100});
deepEqual(rect(colorButton), [0, 0, 100, 100]);
deepEqual(rect(colorButton.getEl().firstChild), [1, 1, 98, 98]);
});
test("colorbutton icon, size default", function() {
var colorButton = createColorButton({icon: 'test'});
nearlyEqualRects(rect(colorButton), [0, 0, 50, 30], 4);
});
test("colorbutton icon, size small", function() {
var colorButton = createColorButton({icon: 'test', size: 'small'});
nearlyEqualRects(rect(colorButton), [0, 0, 43, 24], 4);
});
test("colorbutton icon, size large", function() {
var colorButton = createColorButton({icon: 'test', size: 'large'});
nearlyEqualRects(rect(colorButton), [0, 0, 54, 40], 4);
});
test("colorbutton icon, width 100, height 100", function() {
var colorButton = createColorButton({icon: 'test', width: 100, height: 100});
deepEqual(rect(colorButton), [0, 0, 100, 100]);
deepEqual(rect(colorButton.getEl().firstChild), [1, 1, 98, 98]);
});
test("colorbutton text & icon, size default", function() {
var colorButton = createColorButton({text: 'X', icon: 'test'});
nearlyEqualRects(rect(colorButton), [0, 0, 62, 30], 4);
});
test("colorbutton text & icon, size large", function() {
var colorButton = createColorButton({text: 'X', icon: 'test', size: 'large'});
nearlyEqualRects(rect(colorButton), [0, 0, 69, 40], 4);
});
test("colorbutton text & icon, size small", function() {
var colorButton = createColorButton({text: 'X', icon: 'test', size: 'small'});
nearlyEqualRects(rect(colorButton), [0, 0, 53, 24], 4);
});
test("colorbutton text & icon, width 100, height 100", function() {
var colorButton = createColorButton({text: 'X', icon: 'test', width: 100, height: 100});
deepEqual(rect(colorButton), [0, 0, 100, 100]);
deepEqual(rect(colorButton.getEl().firstChild), [1, 1, 98, 98]);
});
test("colorbutton click event", function() {
var colorButton, clicks = {};
colorButton = createColorButton({text: 'X', onclick: function() {clicks.a = 'a';}});
colorButton.renderTo(document.getElementById('view'));
colorButton.fire('click', {target: colorButton.getEl()});
deepEqual(clicks, {a: 'a'});
});
</script>
</head>
<body>
<h1 id="qunit-header">Button Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.ComboBox Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.TextBox", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
/*
test("combobox text, size default", function() {
var combobox = new tinymce.ui.ComboBox({text: 'abc'}).renderTo(document.getElementById('view'));
deepEqual(rect(combobox), [0, 0, 40, 22]);
});
*/
</script>
</head>
<body>
<h1 id="qunit-header">ui.ComboBox Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Container Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Container", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Container Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,229 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Control Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
module("ui.Control");
test("Initial states", function() {
var ctrl;
ctrl = new tinymce.ui.Control({});
// Check inital states
equal(ctrl.disabled(), false);
equal(ctrl.active(), false);
equal(ctrl.visible(), true);
equal(ctrl.text(), "");
equal(ctrl.width(), 0);
equal(ctrl.height(), 0);
equal(ctrl.name(), "");
equal(ctrl.title(), "");
equal(ctrl.parent(), undefined);
deepEqual(ctrl.settings, {});
});
test("Settings", function() {
var ctrl = new tinymce.ui.Control({
disabled: true,
active: true,
visible: true,
text: 'Text',
title: 'Title',
width: 100,
height: 200,
name: 'Name'
});
// Check settings states
equal(ctrl.disabled(), true);
equal(ctrl.active(), true);
equal(ctrl.visible(), true);
equal(ctrl.text(), "Text");
equal(ctrl.width(), 100);
equal(ctrl.height(), 200);
equal(ctrl.name(), "Name");
equal(ctrl.title(), "Title");
equal(ctrl.parent(), undefined);
deepEqual(ctrl.settings, {
disabled: true,
active: true,
visible: true,
text: 'Text',
title: 'Title',
width: 100,
height: 200,
name: 'Name'
});
});
/*
test("Properties", function() {
var ctrl, cont;
cont = new tinymce.ui.Container({});
ctrl = new tinymce.ui.Control({});
// Set all states
ctrl = ctrl.
disabled(true).
active(true).
visible(true).
text("Text").
title("Title").
width(100).
height(200).
name("Name").parent(cont);
// Check states
equal(ctrl.disabled(), true);
equal(ctrl.active(), true);
equal(ctrl.visible(), true);
equal(ctrl.text(), "Text");
equal(ctrl.width(), 100);
equal(ctrl.height(), 200);
equal(ctrl.name(), "Name");
equal(ctrl.title(), "Title");
equal(ctrl.parent(), cont);
deepEqual(ctrl.settings, {});
});
test("Chained methods", function() {
var ctrl = new tinymce.ui.Control({});
// Set all states
ctrl = ctrl.
refresh().
bind('click', function() {}).
unbind().
renderTo(document.getElementById('viewport')).
fire("nothing").
remove();
// Check so that the chain worked
ok(ctrl instanceof tinymce.ui.Control);
});
test("Events", function() {
var ctrl = new tinymce.ui.Control({
handlers: {
handler1: function() {
count++;
}
}
}), count;
ctrl.bind('MyEvent', function(target, args) {
ok(target === ctrl);
ok(ctrl === this);
deepEqual(args, {myKey: 'myVal'});
});
ctrl.fire('MyEvent', {myKey: 'myVal'});
function countAndBreak(target, args) {
count++;
return false;
}
// Bind two events
ctrl.bind('MyEvent2', countAndBreak);
ctrl.bind('MyEvent2', countAndBreak);
// Check if only one of them was called
count = 0;
ctrl.fire('MyEvent2', {myKey: 'myVal'});
equal(count, 1);
// Fire unbound event
ctrl.fire('MyEvent3', {myKey: 'myVal'});
// Unbind all
ctrl.unbind();
count = 0;
ctrl.fire('MyEvent2', {myKey: 'myVal'});
equal(count, 0, 'Unbind all');
// Unbind by name
ctrl.bind('MyEvent1', countAndBreak);
ctrl.bind('MyEvent2', countAndBreak);
ctrl.unbind('MyEvent2');
count = 0;
ctrl.fire('MyEvent1', {myKey: 'myVal'});
ctrl.fire('MyEvent2', {myKey: 'myVal'});
equal(count, 1);
// Unbind by name callback
ctrl.bind('MyEvent1', countAndBreak);
ctrl.bind('MyEvent1', function() {count++;});
ctrl.unbind('MyEvent1', countAndBreak);
count = 0;
ctrl.fire('MyEvent1', {myKey: 'myVal'});
equal(count, 1);
// Bind by named handler
ctrl.unbind();
ctrl.bind('MyEvent', 'handler1');
count = 0;
ctrl.fire('MyEvent', {myKey: 'myVal'});
equal(count, 1);
});
test("hasClass,addClass,removeClass", function() {
var ctrl = new tinymce.ui.Control({classes: 'class1 class2 class3'});
equal(ctrl.classes(), 'class1 class2 class3');
ok(ctrl.hasClass('class1'));
ok(ctrl.hasClass('class2'));
ok(ctrl.hasClass('class3'));
ok(!ctrl.hasClass('class4'));
ctrl.addClass('class4');
equal(ctrl.classes(), 'class1 class2 class3 class4');
ok(ctrl.hasClass('class1'));
ok(ctrl.hasClass('class2'));
ok(ctrl.hasClass('class3'));
ok(ctrl.hasClass('class4'));
ctrl.removeClass('class4');
equal(ctrl.classes(), 'class1 class2 class3');
ok(ctrl.hasClass('class1'));
ok(ctrl.hasClass('class2'));
ok(ctrl.hasClass('class3'));
ok(!ctrl.hasClass('class4'));
ctrl.removeClass('class3').removeClass('class2');
equal(ctrl.classes(), 'class1');
ok(ctrl.hasClass('class1'));
ok(!ctrl.hasClass('class2'));
ok(!ctrl.hasClass('class3'));
ctrl.removeClass('class3').removeClass('class1');
equal(ctrl.classes(), '');
ok(!ctrl.hasClass('class1'));
ok(!ctrl.hasClass('class2'));
ok(!ctrl.hasClass('class3'));
});
*/
</script>
</head>
<body>
<h1 id="qunit-header">ui.Control Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.DragHelper Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.DragHelper", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.DragHelper Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.ElementPath Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.ElementPath", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.ElementPath Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Factory Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Factory", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Factory Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FieldSet Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FieldSet", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.FieldSet Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FilePicker Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FilePicker", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.FilePicker Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FitLayout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FitLayout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function createFitPanel(settings) {
return tinymce.ui.Factory.create(tinymce.extend({
type: 'panel',
layout: 'fit',
width: 200,
height: 200,
border: 1
}, settings)).renderTo(document.getElementById('view')).reflow();
}
test("fit with spacer inside", function() {
panel = createFitPanel({
items: [
{type: 'spacer', classes: 'red'}
]
});
deepEqual(rect(panel), [0, 0, 200, 200]);
deepEqual(rect(panel.find('spacer')[0]), [1, 1, 198, 198]);
});
test("fit with padding and spacer inside", function() {
panel = createFitPanel({
padding: 3,
items: [
{type: 'spacer', classes: 'red'}
]
});
deepEqual(rect(panel), [0, 0, 200, 200]);
deepEqual(rect(panel.find('spacer')[0]), [4, 4, 192, 192]);
});
test("fit with panel inside", function() {
panel = createFitPanel({
items: [
{type: 'panel', border: 1}
]
});
deepEqual(rect(panel), [0, 0, 200, 200]);
deepEqual(rect(panel.find('panel')[0]), [1, 1, 198, 198]);
});
</script>
</head>
<body>
<h1 id="qunit-header">ui.FitLayout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,915 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FlexLayout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FlexLayout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function renderPanel(settings) {
var panel = tinymce.ui.Factory.create(tinymce.extend({
type: "panel",
layout: "flex",
width: 200, height: 200,
items: [
{type: 'spacer', classes: 'red'},
{type: 'spacer', classes: 'green'},
{type: 'spacer', classes: 'blue'}
]
}, settings)).renderTo(document.getElementById('view')).reflow();
resetScroll(panel.getEl('body'));
return panel;
}
test("pack: default, align: default, flex: default", function() {
panel = renderPanel({});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
});
test("pack: default, align: default, flex: default, borders", function() {
panel = renderPanel({defaults: {border: 1}});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 22, 22]);
deepEqual(rect(panel.find('spacer')[1]), [22, 0, 22, 22]);
deepEqual(rect(panel.find('spacer')[2]), [44, 0, 22, 22]);
});
test("pack: default, flex: 1", function() {
panel = renderPanel({
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
});
test("pack: default, flex: 1, minWidth: various", function() {
panel = renderPanel({
defaults: {flex: 1},
items: [
{type: 'spacer', minWidth: 25, classes: 'red'},
{type: 'spacer', minWidth: 30, classes: 'green'},
{type: 'spacer', minWidth: 35, classes: 'blue'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 62, 20]);
deepEqual(rect(panel.find('spacer')[1]), [62, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [128, 0, 72, 20]);
});
test("pack: start, flex: default", function() {
panel = renderPanel({
pack: "start"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
});
test("pack: start, flex: 1", function() {
panel = renderPanel({
pack: "start",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
});
test("pack: end, flex: default", function() {
panel = renderPanel({
pack: "end"
});
deepEqual(rect(panel.find('spacer')[0]), [140, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [160, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
});
test("pack: end, flex: 1", function() {
panel = renderPanel({
pack: "end",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
});
test("pack: center, flex: default", function() {
panel = renderPanel({
pack: "center"
});
deepEqual(rect(panel.find('spacer')[0]), [70, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [110, 0, 20, 20]);
});
test("pack: center, flex: 1", function() {
panel = renderPanel({
pack: "center",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
});
test("pack: start, spacing: 3", function() {
panel = renderPanel({
layout: "flex",
pack: "start",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [23, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [46, 0, 20, 20]);
});
test("pack: end, spacing: 3", function() {
panel = renderPanel({
pack: "end",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [134, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [157, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
});
test("pack: center, spacing: 3", function() {
panel = renderPanel({
pack: "center",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [67, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [113, 0, 20, 20]);
});
test("pack: start, padding: 3", function() {
panel = renderPanel({
pack: "start",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [23, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [43, 3, 20, 20]);
});
test("pack: start, spacing: 3, padding: 3", function() {
panel = renderPanel({
pack: "start",
padding: 3,
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [26, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [49, 3, 20, 20]);
});
test("pack: start, align: start", function() {
panel = renderPanel({
pack: "start",
align: "start"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
});
test("pack start, align: center", function() {
panel = renderPanel({
pack: "start",
align: "center"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 90, 20, 20]);
});
test("pack: start, align: end", function() {
panel = renderPanel({
pack: "start",
align: "end"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 180, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 180, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 180, 20, 20]);
});
test("pack: start, align: stretch", function() {
panel = renderPanel({
pack: "start",
align: "stretch"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 200]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 200]);
deepEqual(rect(panel.find('spacer')[2]), [40, 0, 20, 200]);
});
test("pack: start, padding: 3, align: stretch", function() {
panel = renderPanel({
pack: "start",
align: "stretch",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 194]);
deepEqual(rect(panel.find('spacer')[1]), [23, 3, 20, 194]);
deepEqual(rect(panel.find('spacer')[2]), [43, 3, 20, 194]);
});
test("pack: start, flex: mixed values", function() {
panel = renderPanel({
pack: "start",
items: [
{type: 'spacer', classes: 'red', flex: 0.3},
{type: 'spacer', classes: 'green', flex: 1},
{type: 'spacer', classes: 'blue', flex: 0.5}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 43, 20]);
deepEqual(rect(panel.find('spacer')[1]), [43, 0, 98, 20]);
deepEqual(rect(panel.find('spacer')[2]), [141, 0, 59, 20]);
});
test("pack: justify", function() {
panel = renderPanel({
pack: "justify"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
});
test("pack: justify, padding: 3", function() {
panel = renderPanel({
pack: "justify",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [177, 3, 20, 20]);
});
test("pack: justify, minWidth: mixed values, padding: 3", function() {
panel = renderPanel({
pack: "justify",
padding: 3,
items: [
{type: 'spacer', classes: 'red'},
{type: 'spacer', classes: 'green', minWidth: 80},
{type: 'spacer', classes: 'blue', minWidth: 50}
]
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [45, 3, 80, 20]);
deepEqual(rect(panel.find('spacer')[2]), [147, 3, 50, 20]);
});
test("pack: start, flex: 1, maxWidth: 80 on second", function() {
panel = renderPanel({
pack: "start",
width: 400,
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', maxWidth: 80, flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 160, 20]);
deepEqual(rect(panel.find('spacer')[1]), [160, 0, 80, 20]);
deepEqual(rect(panel.find('spacer')[2]), [240, 0, 160, 20]);
});
test("pack: start, flex: 1, minWidth: 150 on second", function() {
panel = renderPanel({
pack: "start",
width: 400,
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', minWidth: 150, flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 90, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 0, 220, 20]);
deepEqual(rect(panel.find('spacer')[2]), [310, 0, 90, 20]);
});
test("pack: start, flex: default, hide item and reflow", function() {
panel = renderPanel({
pack: "start",
autoResize: true,
items: [
{type: 'spacer', classes: 'red'},
{type: 'spacer', classes: 'green'},
{type: 'spacer', classes: 'blue'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
deepEqual(rect(panel), [0, 0, 60, 20]);
panel.items().eq(0).hide();
panel.reflow();
deepEqual(rect(panel), [0, 0, 40, 20]);
});
test("pack: start, flex: 1, reflow after resize outer width", function() {
panel = renderPanel({
pack: "start",
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
deepEqual(rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
panel.layoutRect({w: 400, h: 400}).reflow();
deepEqual(rect(panel), [0, 0, 400, 400]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 133, 20]);
deepEqual(rect(panel.find('spacer')[1]), [133, 0, 133, 20]);
deepEqual(rect(panel.find('spacer')[2]), [267, 0, 133, 20]);
});
test("pack: start, maxWidth/maxHeight: 100, item minWidth/maxHeight: 200 (overflow W+H)", function() {
panel = renderPanel({
pack: "start",
autoResize: true,
autoScroll: true,
maxWidth: 100,
maxHeight: 100,
items: [
{type: 'spacer', minWidth: 200, minHeight: 200, classes: 'red dotted'}
]
});
deepEqual(rect(panel), [0, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 200, 200]);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
test("pack: start, direction: column, maxWidth/maxHeight: 100, padding: 20, spacing: 10, item minWidth/maxHeight: 200 (overflow W+H)", function() {
panel = renderPanel({
pack: "start",
direction: "column",
autoResize: true,
autoScroll: true,
maxWidth: 100,
maxHeight: 100,
padding: 20,
spacing: 10,
items: [
{type: 'spacer', minWidth: 100, minHeight: 100, classes: 'red dotted'},
{type: 'spacer', minWidth: 100, minHeight: 100, classes: 'green dotted'}
]
});
deepEqual(rect(panel), [0, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[0]), [20, 20, 100, 100]);
deepEqual(rect(panel.find('spacer')[1]), [20, 130, 100, 100]);
equal(panel.layoutRect().contentW, 20 + 100 + 20);
equal(panel.layoutRect().contentH, 20 + 100 + 10 + 100 + 20);
});
test("pack: start, maxWidth/maxHeight: 100, item minWidth/maxHeight: 200 (overflow W)", function() {
panel = renderPanel({
pack: "start",
autoResize: true,
autoScroll: true,
maxWidth: 100,
items: [
{type: 'spacer', minWidth: 200, minHeight: 200, classes: 'red dotted'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 200, 200]);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
test("pack: start, maxWidth/maxHeight: 100, item minWidth/maxHeight: 200 (overflow H)", function() {
panel = renderPanel({
pack: "start",
autoResize: true,
autoScroll: true,
maxHeight: 100,
items: [
{type: 'spacer', minWidth: 200, minHeight: 200, classes: 'red dotted'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 200, 200]);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
test("pack: start, minWidth: 200, item minWidth: 100 (underflow)", function() {
panel = renderPanel({
pack: "start",
autoResize: true,
minWidth: 200,
items: [
{type: 'spacer', minWidth: 100, classes: 'red'}
]
});
deepEqual(rect(panel), [0, 0, 200, 20]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 100, 20]);
});
test("pack: start, flex: 1, border: 1, reflow after resize inner width", function() {
panel = renderPanel({
pack: "start",
border: 1,
items: [
{type: 'spacer', classes: 'red', flex: 1}
]
});
panel.layoutRect({innerW: 400, innerH: 400}).reflow();
deepEqual(rect(panel), [0, 0, 402, 402]);
deepEqual(rect(panel.find('spacer')[0]), [1, 1, 400, 20]);
});
test("row flexbox in row flexbox", function() {
panel = tinymce.ui.Factory.create({
type: 'panel',
layout: 'flex',
align: 'end',
items: [
{type: 'spacer', classes: 'red'},
{type: 'panel', layout: 'flex', padding: 10, spacing: 10, items: [
{type: 'spacer', classes: 'yellow'},
{type: 'spacer', classes: 'magenta'}
]},
{type: 'spacer', classes: 'green'}
]
}).renderTo(document.getElementById('view')).reflow();
deepEqual(rect(panel), [0, 0, 110, 40]);
deepEqual(rect(panel.find("panel")[0]), [20, 0, 70, 40]);
deepEqual(rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [30, 10, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [60, 10, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [90, 20, 20, 20]);
});
test("row flexbox in row flexbox hide inner item and reflow", function() {
panel = tinymce.ui.Factory.create({
type: 'panel',
layout: 'flex',
align: 'end',
items: [
{type: 'spacer', classes: 'red'},
{type: 'panel', layout: 'flex', padding: 10, spacing: 10, items: [
{type: 'spacer', classes: 'yellow'},
{type: 'spacer', classes: 'magenta'}
]},
{type: 'spacer', classes: 'green'}
]
}).renderTo(document.getElementById('view')).reflow();
panel.find('spacer')[1].hide().parent().reflow();
deepEqual(rect(panel), [0, 0, 80, 40]);
deepEqual(rect(panel.find("panel")[0]), [20, 0, 40, 40]);
deepEqual(rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [30, 10, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [60, 20, 20, 20]);
});
// Direction column tests
function renderColumnPanel(settings) {
settings.direction = "column";
return renderPanel(settings);
}
test("direction: column, pack: default, align: default, flex: default", function() {
panel = renderColumnPanel({});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
});
test("direction: column, pack: default, flex: 1", function() {
panel = renderColumnPanel({
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
deepEqual(rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
});
test("direction: column, pack: default, flex: 1, minWidth: various", function() {
panel = renderColumnPanel({
defaults: {flex: 1},
items: [
{type: 'spacer', minHeight: 25, classes: 'red'},
{type: 'spacer', minHeight: 30, classes: 'green'},
{type: 'spacer', minHeight: 35, classes: 'blue'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 62]);
deepEqual(rect(panel.find('spacer')[1]), [0, 62, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 128, 20, 72]);
});
test("direction: column, pack: start, flex: default", function() {
panel = renderColumnPanel({
pack: "start"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
});
test("direction: column, pack: start, flex: 1", function() {
panel = renderColumnPanel({
pack: "start",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
deepEqual(rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
});
test("direction: column, pack: end, flex: default", function() {
panel = renderColumnPanel({
pack: "end"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 140, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 160, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
});
test("direction: column, pack: end, flex: 1", function() {
panel = renderColumnPanel({
pack: "end",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
deepEqual(rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
});
test("direction: column, pack: center, flex: default", function() {
panel = renderColumnPanel({
pack: "center"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 70, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 110, 20, 20]);
});
test("direction: column, pack: center, flex: 1", function() {
panel = renderColumnPanel({
pack: "center",
defaults: {flex: 1}
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
deepEqual(rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
});
test("direction: column, pack: start, spacing: 3", function() {
panel = renderColumnPanel({
layout: "flex",
pack: "start",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 23, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 46, 20, 20]);
});
test("direction: column, pack: end, spacing: 3", function() {
panel = renderColumnPanel({
pack: "end",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [0, 134, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 157, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
});
test("direction: column, pack: center, spacing: 3", function() {
panel = renderColumnPanel({
pack: "center",
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [0, 67, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 113, 20, 20]);
});
test("direction: column, pack: start, padding: 3", function() {
panel = renderColumnPanel({
pack: "start",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [3, 23, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 43, 20, 20]);
});
test("direction: column, pack: start, spacing: 3, padding: 3", function() {
panel = renderColumnPanel({
pack: "start",
padding: 3,
spacing: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [3, 26, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 49, 20, 20]);
});
test("direction: column, pack: start, align: start", function() {
panel = renderColumnPanel({
pack: "start",
align: "start"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
});
test("direction: column, pack start, align: center", function() {
panel = renderColumnPanel({
pack: "start",
align: "center"
});
deepEqual(rect(panel.find('spacer')[0]), [90, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [90, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [90, 40, 20, 20]);
});
test("direction: column, pack: start, align: end", function() {
panel = renderColumnPanel({
pack: "start",
align: "end"
});
deepEqual(rect(panel.find('spacer')[0]), [180, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [180, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [180, 40, 20, 20]);
});
test("direction: column, pack: start, align: stretch", function() {
panel = renderColumnPanel({
pack: "start",
align: "stretch"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 200, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 20, 200, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 40, 200, 20]);
});
test("direction: column, pack: start, padding: 3, align: stretch", function() {
panel = renderColumnPanel({
pack: "start",
align: "stretch",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 194, 20]);
deepEqual(rect(panel.find('spacer')[1]), [3, 23, 194, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 43, 194, 20]);
});
test("direction: column, pack: start, flex: mixed values", function() {
panel = renderColumnPanel({
pack: "start",
items: [
{type: 'spacer', classes: 'red', flex: 0.3},
{type: 'spacer', classes: 'green', flex: 1},
{type: 'spacer', classes: 'blue', flex: 0.5}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 43]);
deepEqual(rect(panel.find('spacer')[1]), [0, 43, 20, 98]);
deepEqual(rect(panel.find('spacer')[2]), [0, 141, 20, 59]);
});
test("direction: column, pack: justify", function() {
panel = renderColumnPanel({
pack: "justify"
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
});
test("direction: column, pack: justify, padding: 3", function() {
panel = renderColumnPanel({
pack: "justify",
padding: 3
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [3, 90, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 177, 20, 20]);
});
test("direction: column, pack: justify, minHeight: mixed values, padding: 3", function() {
panel = renderColumnPanel({
pack: "justify",
padding: 3,
items: [
{type: 'spacer', classes: 'red'},
{type: 'spacer', classes: 'green', minHeight: 80},
{type: 'spacer', classes: 'blue', minHeight: 50}
]
});
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [3, 45, 20, 80]);
deepEqual(rect(panel.find('spacer')[2]), [3, 147, 20, 50]);
});
test("direction: column, pack: start, flex: 1, maxHeight: 80 on second", function() {
panel = renderColumnPanel({
pack: "start",
height: 400,
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', maxHeight: 80, flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 160]);
deepEqual(rect(panel.find('spacer')[1]), [0, 160, 20, 80]);
deepEqual(rect(panel.find('spacer')[2]), [0, 240, 20, 160]);
});
test("direction: column, pack: start, flex: 1, minHeight: 150 on second", function() {
panel = renderColumnPanel({
pack: "start",
height: 400,
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', minHeight: 150, flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 90]);
deepEqual(rect(panel.find('spacer')[1]), [0, 90, 20, 220]);
deepEqual(rect(panel.find('spacer')[2]), [0, 310, 20, 90]);
});
test("direction: column, pack: start, flex: 1, reflow after resize outer height", function() {
panel = renderColumnPanel({
pack: "start",
items: [
{type: 'spacer', classes: 'red', flex: 1},
{type: 'spacer', classes: 'green', flex: 1},
{type: 'spacer', classes: 'blue', flex: 1}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
deepEqual(rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
deepEqual(rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
panel.layoutRect({w: 400, h: 400}).reflow();
deepEqual(rect(panel), [0, 0, 400, 400]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 133]);
deepEqual(rect(panel.find('spacer')[1]), [0, 133, 20, 133]);
deepEqual(rect(panel.find('spacer')[2]), [0, 267, 20, 133]);
});
test("direction: column, pack: start, flex: 1, border: 1, reflow after resize inner width", function() {
panel = renderColumnPanel({
pack: "start",
border: 1,
items: [
{type: 'spacer', classes: 'red', flex: 1}
]
});
panel.layoutRect({innerW: 400, innerH: 400}).reflow();
deepEqual(rect(panel), [0, 0, 402, 402]);
deepEqual(rect(panel.find('spacer')[0]), [1, 1, 20, 400]);
});
test("direction: column, row flexbox in row flexbox and resize parent", function() {
panel = tinymce.ui.Factory.create({
type: 'panel',
layout: 'flex',
align: 'end',
items: [
{type: 'spacer', classes: 'red'},
{type: 'panel', layout: 'flex', padding: 10, spacing: 10, items: [
{type: 'spacer', classes: 'yellow'},
{type: 'spacer', classes: 'magenta'}
]},
{type: 'spacer', classes: 'green'}
]
}).renderTo(document.getElementById('view')).reflow();
deepEqual(rect(panel), [0, 0, 110, 40]);
deepEqual(rect(panel.find("panel")[0]), [20, 0, 70, 40]);
deepEqual(rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [30, 10, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [60, 10, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [90, 20, 20, 20]);
});
</script>
</head>
<body>
<h1 id="qunit-header">ui.FlexLayout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FloatPanel Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FloatPanel", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.FloatPanel Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FlowLayout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FlowLayout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.FlowLayout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Form Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Form", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Form Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.FormItem Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.FormItem", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.FormItem Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,244 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.GridLayout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.GridLayout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
function renderGridPanel(settings) {
var panel = tinymce.ui.Factory.create(tinymce.extend({
type: "panel",
layout: "grid",
defaults: {type: 'spacer'}
}, settings)).renderTo(document.getElementById('view')).reflow();
resetScroll(panel.getEl('body'));
return panel;
}
test("automatic grid size 2x2", function() {
panel = renderGridPanel({
items: [
{classes: 'red'}, {classes: 'green'},
{classes: 'blue'}, {classes: 'cyan'}
]
});
deepEqual(rect(panel), [0, 0, 40, 40]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 20, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [20, 20, 20, 20]);
});
/*
test("fixed pixel size, automatic grid size 2x2", function() {
panel = renderGridPanel({
width: 100, height: 100,
align: "center",
items: [
{classes: 'red'}, {classes: 'green'},
{classes: 'blue'}, {classes: 'cyan'}
]
});
deepEqual(rect(panel), [0, 0, 200, 200]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 17, 22]);
deepEqual(rect(panel.find('spacer')[1]), [17, 0, 17, 22]);
deepEqual(rect(panel.find('spacer')[2]), [0, 22, 16, 22]);
deepEqual(rect(panel.find('spacer')[3]), [17, 22, 17, 22]);
});
*/
test("spacing: 3, automatic grid size 2x2", function() {
panel = renderGridPanel({
spacing: 3,
items: [
{classes: 'red'}, {classes: 'green'},
{classes: 'blue'}, {classes: 'cyan'}
]
});
deepEqual(rect(panel), [0, 0, 43, 43]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [23, 0, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [0, 23, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [23, 23, 20, 20]);
});
test("padding: 3, automatic grid size 2x2", function() {
panel = renderGridPanel({
padding: 3,
items: [
{classes: 'red'}, {classes: 'green'},
{classes: 'blue'}, {classes: 'cyan'}
]
});
deepEqual(rect(panel), [0, 0, 46, 46]);
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [23, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 23, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [23, 23, 20, 20]);
});
test("spacing: 3, padding: 3, automatic grid size 2x2", function() {
panel = renderGridPanel({
padding: 3,
spacing: 3,
items: [
{classes: 'red'}, {classes: 'green'},
{classes: 'blue'}, {classes: 'cyan'}
]
});
deepEqual(rect(panel), [0, 0, 49, 49]);
deepEqual(rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[1]), [26, 3, 20, 20]);
deepEqual(rect(panel.find('spacer')[2]), [3, 26, 20, 20]);
deepEqual(rect(panel.find('spacer')[3]), [26, 26, 20, 20]);
});
test("inner elements 100x100 maxWidth/maxHeight: 118 (overflow W+H)", function() {
panel = renderGridPanel({
autoResize: true,
autoScroll: true,
maxWidth: 118,
maxHeight: 118,
defaults: {
type: 'spacer',
minWidth: 100,
minHeight: 100
},
items: [
{classes: 'red dotted'}, {classes: 'green dotted'},
{classes: 'blue dotted'}, {classes: 'cyan dotted'}
]
});
deepEqual(rect(panel), [0, 0, 118, 118]);
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
deepEqual(rect(panel.find('spacer')[3]), [100, 100, 100, 100]);
equal(panel.layoutRect().w, 118);
equal(panel.layoutRect().h, 118);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
test("inner elements: 100x100, padding: 20, spacing: 10, maxWidth/maxHeight: 118 (overflow W+H)", function() {
panel = renderGridPanel({
autoResize: true,
autoScroll: true,
maxWidth: 118,
maxHeight: 118,
padding: 20,
spacing: 10,
defaults: {
type: 'spacer',
minWidth: 100,
minHeight: 100
},
items: [
{classes: 'red dotted'}, {classes: 'green dotted'},
{classes: 'blue dotted'}, {classes: 'cyan dotted'}
]
});
deepEqual(rect(panel), [0, 0, 118, 118]);
deepEqual(rect(panel.find('spacer')[0]), [20, 20, 100, 100]);
deepEqual(rect(panel.find('spacer')[1]), [130, 20, 100, 100]);
deepEqual(rect(panel.find('spacer')[2]), [20, 130, 100, 100]);
deepEqual(rect(panel.find('spacer')[3]), [130, 130, 100, 100]);
equal(panel.layoutRect().w, 118);
equal(panel.layoutRect().h, 118);
equal(panel.layoutRect().contentW, 20 + 200 + 10 + 20);
equal(panel.layoutRect().contentH, 20 + 200 + 10 + 20);
});
test("inner elements 100x100 maxWidth: 118 (overflow W)", function() {
panel = renderGridPanel({
autoResize: true,
autoScroll: true,
maxWidth: 100,
defaults: {
type: 'spacer',
minWidth: 100,
minHeight: 100
},
items: [
{classes: 'red dotted'}, {classes: 'green dotted'},
{classes: 'blue dotted'}, {classes: 'cyan dotted'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
deepEqual(rect(panel.find('spacer')[3]), [100, 100, 100, 100]);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
test("inner elements 100x100 maxHeight: 118 (overflow H)", function() {
panel = renderGridPanel({
autoResize: true,
autoScroll: true,
maxHeight: 100,
defaults: {
type: 'spacer',
minWidth: 100,
minHeight: 100
},
items: [
{classes: 'red dotted'}, {classes: 'green dotted'},
{classes: 'blue dotted'}, {classes: 'cyan dotted'}
]
});
deepEqual(rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
deepEqual(rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
deepEqual(rect(panel.find('spacer')[3]), [100, 100, 100, 100]);
equal(panel.layoutRect().contentW, 200);
equal(panel.layoutRect().contentH, 200);
});
</script>
</head>
<body>
<h1 id="qunit-header">ui.GridLayout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Iframe Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Iframe", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Iframe Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.KeyboardNavigation Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.KeyboardNavigation", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.KeyboardNavigation Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Label Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Label", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Label Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>ui.Layout Test Suite</title>
<link type="text/css" rel="stylesheet" href="../../../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="css/ui-overrides.css" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="../../js/qunit/reporter.js"></script>
<script src="../../js/utils.js"></script>
<script src="../../js/tinymce_loader.js"></script>
<script type="text/javascript">
var panel;
QUnit.config.autostart = false;
QUnit.config.reorder = false;
module("ui.Layout", {
setup: function() {
document.getElementById('view').innerHTML = '';
},
teardown: function() {
//document.getElementById('view').innerHTML = '';
}
});
window.onload = function() {
QUnit.start();
};
</script>
</head>
<body>
<h1 id="qunit-header">ui.Layout Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests">
</ol>
<div id="view" style="position: absolute; right: 0; top: 0"></div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More