<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[27679] trunk/tests/qunit/editor: Update the TinyMCE tests.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/27679">27679</a></dd>
<dt>Author</dt> <dd>azaozz</dd>
<dt>Date</dt> <dd>2014-03-24 05:59:45 +0000 (Mon, 24 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Update the TinyMCE tests.

In 4.0.20 all tests were reworked. The 'testrunner' was removed and the PhantomJS Runner QUnit plugin was added making it possible to run the tests from cli. However it is still necessary to run the tests in all supported browsers to test the fixes for all browser quirks and normalization. Also all tests are loaded in one html file.

See <a href="http://core.trac.wordpress.org/ticket/27014">#27014</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunktestsquniteditorindexhtml">trunk/tests/qunit/editor/index.html</a></li>
<li><a href="#trunktestsquniteditorjsqunitqunitcss">trunk/tests/qunit/editor/js/qunit/qunit.css</a></li>
<li><a href="#trunktestsquniteditorjsqunitqunitjs">trunk/tests/qunit/editor/js/qunit/qunit.js</a></li>
<li><a href="#trunktestsquniteditorjsutilsjs">trunk/tests/qunit/editor/js/utils.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomDOMUtilsjs">trunk/tests/qunit/editor/tinymce/dom/DOMUtils.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsquniteditorjsinitjs">trunk/tests/qunit/editor/js/init.js</a></li>
<li><a href="#trunktestsquniteditorjsrunnerjs">trunk/tests/qunit/editor/js/runner.js</a></li>
<li><a href="#trunktestsquniteditorpluginsautosavejs">trunk/tests/qunit/editor/plugins/autosave.js</a></li>
<li><a href="#trunktestsquniteditorpluginsfullpagejs">trunk/tests/qunit/editor/plugins/fullpage.js</a></li>
<li><a href="#trunktestsquniteditorpluginsjquery_pluginjs">trunk/tests/qunit/editor/plugins/jquery_plugin.js</a></li>
<li><a href="#trunktestsquniteditorpluginslegacyoutputjs">trunk/tests/qunit/editor/plugins/legacyoutput.js</a></li>
<li><a href="#trunktestsquniteditorpluginslistsjs">trunk/tests/qunit/editor/plugins/lists.js</a></li>
<li><a href="#trunktestsquniteditorpluginsmediajs">trunk/tests/qunit/editor/plugins/media.js</a></li>
<li><a href="#trunktestsquniteditorpluginsnoneditablejs">trunk/tests/qunit/editor/plugins/noneditable.js</a></li>
<li><a href="#trunktestsquniteditorpluginspastejs">trunk/tests/qunit/editor/plugins/paste.js</a></li>
<li><a href="#trunktestsquniteditorpluginssearchreplacejs">trunk/tests/qunit/editor/plugins/searchreplace.js</a></li>
<li><a href="#trunktestsquniteditorpluginsspellcheckerjs">trunk/tests/qunit/editor/plugins/spellchecker.js</a></li>
<li><a href="#trunktestsquniteditorpluginstablejs">trunk/tests/qunit/editor/plugins/table.js</a></li>
<li><a href="#trunktestsquniteditorpluginswordcountjs">trunk/tests/qunit/editor/plugins/wordcount.js</a></li>
<li><a href="#trunktestsquniteditortinymceEditorjs">trunk/tests/qunit/editor/tinymce/Editor.js</a></li>
<li><a href="#trunktestsquniteditortinymceEditorCommandsjs">trunk/tests/qunit/editor/tinymce/EditorCommands.js</a></li>
<li><a href="#trunktestsquniteditortinymceEnterKeyjs">trunk/tests/qunit/editor/tinymce/EnterKey.js</a></li>
<li><a href="#trunktestsquniteditortinymceForceBlocksjs">trunk/tests/qunit/editor/tinymce/ForceBlocks.js</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_applyjs">trunk/tests/qunit/editor/tinymce/Formatter_apply.js</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_checkjs">trunk/tests/qunit/editor/tinymce/Formatter_check.js</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_removejs">trunk/tests/qunit/editor/tinymce/Formatter_remove.js</a></li>
<li><a href="#trunktestsquniteditortinymceUndoManagerjs">trunk/tests/qunit/editor/tinymce/UndoManager.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomEventUtilsjs">trunk/tests/qunit/editor/tinymce/dom/EventUtils.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomRangejs">trunk/tests/qunit/editor/tinymce/dom/Range.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomSelectionjs">trunk/tests/qunit/editor/tinymce/dom/Selection.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomSerializerjs">trunk/tests/qunit/editor/tinymce/dom/Serializer.js</a></li>
<li><a href="#trunktestsquniteditortinymcedomTridentSelectionjs">trunk/tests/qunit/editor/tinymce/dom/TridentSelection.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlDomParserjs">trunk/tests/qunit/editor/tinymce/html/DomParser.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlEntitiesjs">trunk/tests/qunit/editor/tinymce/html/Entities.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlNodejs">trunk/tests/qunit/editor/tinymce/html/Node.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlObsoletejs">trunk/tests/qunit/editor/tinymce/html/Obsolete.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSaxParserjs">trunk/tests/qunit/editor/tinymce/html/SaxParser.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSchemajs">trunk/tests/qunit/editor/tinymce/html/Schema.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSerializerjs">trunk/tests/qunit/editor/tinymce/html/Serializer.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlStylesjs">trunk/tests/qunit/editor/tinymce/html/Styles.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlWriterjs">trunk/tests/qunit/editor/tinymce/html/Writer.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiAbsoluteLayoutjs">trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiButtonjs">trunk/tests/qunit/editor/tinymce/ui/Button.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiCollectionjs">trunk/tests/qunit/editor/tinymce/ui/Collection.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiColorButtonjs">trunk/tests/qunit/editor/tinymce/ui/ColorButton.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiControljs">trunk/tests/qunit/editor/tinymce/ui/Control.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiFitLayoutjs">trunk/tests/qunit/editor/tinymce/ui/FitLayout.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiFlexLayoutjs">trunk/tests/qunit/editor/tinymce/ui/FlexLayout.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiGridLayoutjs">trunk/tests/qunit/editor/tinymce/ui/GridLayout.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiMenuButtonjs">trunk/tests/qunit/editor/tinymce/ui/MenuButton.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiPaneljs">trunk/tests/qunit/editor/tinymce/ui/Panel.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiSelectorjs">trunk/tests/qunit/editor/tinymce/ui/Selector.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiSplitButtonjs">trunk/tests/qunit/editor/tinymce/ui/SplitButton.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiTabPaneljs">trunk/tests/qunit/editor/tinymce/ui/TabPanel.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiTextBoxjs">trunk/tests/qunit/editor/tinymce/ui/TextBox.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiWindowjs">trunk/tests/qunit/editor/tinymce/ui/Window.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilJSONjs">trunk/tests/qunit/editor/tinymce/util/JSON.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilJSONRequestjs">trunk/tests/qunit/editor/tinymce/util/JSONRequest.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilLocalStoragejs">trunk/tests/qunit/editor/tinymce/util/LocalStorage.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_webkitjs">trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilURIjs">trunk/tests/qunit/editor/tinymce/util/URI.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilXHRjs">trunk/tests/qunit/editor/tinymce/util/XHR.js</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li>trunk/tests/qunit/editor/external-plugins/table/</li>
<li><a href="#trunktestsquniteditorjsqunitreporterjs">trunk/tests/qunit/editor/js/qunit/reporter.js</a></li>
<li><a href="#trunktestsquniteditorjsqunittestrunnercss">trunk/tests/qunit/editor/js/qunit/testrunner.css</a></li>
<li><a href="#trunktestsquniteditorjsqunittestrunnerjs">trunk/tests/qunit/editor/js/qunit/testrunner.js</a></li>
<li><a href="#trunktestsquniteditorpluginsautolinkhtml">trunk/tests/qunit/editor/plugins/autolink.html</a></li>
<li><a href="#trunktestsquniteditorpluginsautosavehtml">trunk/tests/qunit/editor/plugins/autosave.html</a></li>
<li><a href="#trunktestsquniteditorpluginsfullpagehtml">trunk/tests/qunit/editor/plugins/fullpage.html</a></li>
<li><a href="#trunktestsquniteditorpluginsjquery_pluginhtml">trunk/tests/qunit/editor/plugins/jquery_plugin.html</a></li>
<li>trunk/tests/qunit/editor/plugins/js/</li>
<li><a href="#trunktestsquniteditorpluginslegacyoutputhtml">trunk/tests/qunit/editor/plugins/legacyoutput.html</a></li>
<li><a href="#trunktestsquniteditorpluginslistshtml">trunk/tests/qunit/editor/plugins/lists.html</a></li>
<li><a href="#trunktestsquniteditorpluginsmediahtml">trunk/tests/qunit/editor/plugins/media.html</a></li>
<li><a href="#trunktestsquniteditorpluginsnoneditablehtml">trunk/tests/qunit/editor/plugins/noneditable.html</a></li>
<li><a href="#trunktestsquniteditorpluginspastehtml">trunk/tests/qunit/editor/plugins/paste.html</a></li>
<li><a href="#trunktestsquniteditorpluginsplugin_dependency_chainhtml">trunk/tests/qunit/editor/plugins/plugin_dependency_chain.html</a></li>
<li><a href="#trunktestsquniteditorpluginsplugin_dependency_chain_legacyhtml">trunk/tests/qunit/editor/plugins/plugin_dependency_chain_legacy.html</a></li>
<li><a href="#trunktestsquniteditorpluginsplugin_dependency_init_call_orderhtml">trunk/tests/qunit/editor/plugins/plugin_dependency_init_call_order.html</a></li>
<li><a href="#trunktestsquniteditorpluginsplugin_dependency_specific_locationhtml">trunk/tests/qunit/editor/plugins/plugin_dependency_specific_location.html</a></li>
<li><a href="#trunktestsquniteditorpluginssearchreplacehtml">trunk/tests/qunit/editor/plugins/searchreplace.html</a></li>
<li><a href="#trunktestsquniteditorpluginsspellcheckerhtml">trunk/tests/qunit/editor/plugins/spellchecker.html</a></li>
<li><a href="#trunktestsquniteditorpluginstablehtml">trunk/tests/qunit/editor/plugins/table.html</a></li>
<li><a href="#trunktestsquniteditorpluginstable_robothtml">trunk/tests/qunit/editor/plugins/table_robot.html</a></li>
<li><a href="#trunktestsquniteditorpluginstestsjs">trunk/tests/qunit/editor/plugins/tests.js</a></li>
<li><a href="#trunktestsquniteditorpluginswordcounthtml">trunk/tests/qunit/editor/plugins/wordcount.html</a></li>
<li><a href="#trunktestsquniteditortestgif">trunk/tests/qunit/editor/test.gif</a></li>
<li><a href="#trunktestsquniteditortinymceEditorhtml">trunk/tests/qunit/editor/tinymce/Editor.html</a></li>
<li><a href="#trunktestsquniteditortinymceEditorCommandshtml">trunk/tests/qunit/editor/tinymce/EditorCommands.html</a></li>
<li><a href="#trunktestsquniteditortinymceEnterKeyhtml">trunk/tests/qunit/editor/tinymce/EnterKey.html</a></li>
<li><a href="#trunktestsquniteditortinymceForceBlockshtml">trunk/tests/qunit/editor/tinymce/ForceBlocks.html</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_applyhtml">trunk/tests/qunit/editor/tinymce/Formatter_apply.html</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_checkhtml">trunk/tests/qunit/editor/tinymce/Formatter_check.html</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_removehtml">trunk/tests/qunit/editor/tinymce/Formatter_remove.html</a></li>
<li><a href="#trunktestsquniteditortinymceFormatter_robothtml">trunk/tests/qunit/editor/tinymce/Formatter_robot.html</a></li>
<li><a href="#trunktestsquniteditortinymceUndoManagerhtml">trunk/tests/qunit/editor/tinymce/UndoManager.html</a></li>
<li><a href="#trunktestsquniteditortinymceUndoManager_robothtml">trunk/tests/qunit/editor/tinymce/UndoManager_robot.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomDOMUtilshtml">trunk/tests/qunit/editor/tinymce/dom/DOMUtils.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomDOMUtils_jqueryhtml">trunk/tests/qunit/editor/tinymce/dom/DOMUtils_jquery.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomEventUtilshtml">trunk/tests/qunit/editor/tinymce/dom/EventUtils.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomRangehtml">trunk/tests/qunit/editor/tinymce/dom/Range.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomSelectionhtml">trunk/tests/qunit/editor/tinymce/dom/Selection.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomSerializerhtml">trunk/tests/qunit/editor/tinymce/dom/Serializer.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomTridentSelectionhtml">trunk/tests/qunit/editor/tinymce/dom/TridentSelection.html</a></li>
<li><a href="#trunktestsquniteditortinymcedomtestsjs">trunk/tests/qunit/editor/tinymce/dom/tests.js</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlDomParserhtml">trunk/tests/qunit/editor/tinymce/html/DomParser.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlEntitieshtml">trunk/tests/qunit/editor/tinymce/html/Entities.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlNodehtml">trunk/tests/qunit/editor/tinymce/html/Node.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSaxParserhtml">trunk/tests/qunit/editor/tinymce/html/SaxParser.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSchemahtml">trunk/tests/qunit/editor/tinymce/html/Schema.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlSerializerhtml">trunk/tests/qunit/editor/tinymce/html/Serializer.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlStyleshtml">trunk/tests/qunit/editor/tinymce/html/Styles.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlWriterhtml">trunk/tests/qunit/editor/tinymce/html/Writer.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmlobsoletehtml">trunk/tests/qunit/editor/tinymce/html/obsolete.html</a></li>
<li><a href="#trunktestsquniteditortinymcehtmltestsjs">trunk/tests/qunit/editor/tinymce/html/tests.js</a></li>
<li><a href="#trunktestsquniteditortinymcetestsjs">trunk/tests/qunit/editor/tinymce/tests.js</a></li>
<li><a href="#trunktestsquniteditortinymceuiAbsoluteLayouthtml">trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiButtonhtml">trunk/tests/qunit/editor/tinymce/ui/Button.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiButtonGrouphtml">trunk/tests/qunit/editor/tinymce/ui/ButtonGroup.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiCheckboxhtml">trunk/tests/qunit/editor/tinymce/ui/Checkbox.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiCollectionhtml">trunk/tests/qunit/editor/tinymce/ui/Collection.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiColorButtonhtml">trunk/tests/qunit/editor/tinymce/ui/ColorButton.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiComboBoxhtml">trunk/tests/qunit/editor/tinymce/ui/ComboBox.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiContainerhtml">trunk/tests/qunit/editor/tinymce/ui/Container.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiControlhtml">trunk/tests/qunit/editor/tinymce/ui/Control.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiDragHelperhtml">trunk/tests/qunit/editor/tinymce/ui/DragHelper.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiElementPathhtml">trunk/tests/qunit/editor/tinymce/ui/ElementPath.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFactoryhtml">trunk/tests/qunit/editor/tinymce/ui/Factory.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFieldSethtml">trunk/tests/qunit/editor/tinymce/ui/FieldSet.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFilePickerhtml">trunk/tests/qunit/editor/tinymce/ui/FilePicker.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFitLayouthtml">trunk/tests/qunit/editor/tinymce/ui/FitLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFlexLayouthtml">trunk/tests/qunit/editor/tinymce/ui/FlexLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFloatPanelhtml">trunk/tests/qunit/editor/tinymce/ui/FloatPanel.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFlowLayouthtml">trunk/tests/qunit/editor/tinymce/ui/FlowLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFormhtml">trunk/tests/qunit/editor/tinymce/ui/Form.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiFormItemhtml">trunk/tests/qunit/editor/tinymce/ui/FormItem.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiGridLayouthtml">trunk/tests/qunit/editor/tinymce/ui/GridLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiIframehtml">trunk/tests/qunit/editor/tinymce/ui/Iframe.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiKeyboardNavigationhtml">trunk/tests/qunit/editor/tinymce/ui/KeyboardNavigation.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiLabelhtml">trunk/tests/qunit/editor/tinymce/ui/Label.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiLayouthtml">trunk/tests/qunit/editor/tinymce/ui/Layout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiListBoxhtml">trunk/tests/qunit/editor/tinymce/ui/ListBox.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMenuhtml">trunk/tests/qunit/editor/tinymce/ui/Menu.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMenuBarhtml">trunk/tests/qunit/editor/tinymce/ui/MenuBar.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMenuButtonhtml">trunk/tests/qunit/editor/tinymce/ui/MenuButton.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMenuItemhtml">trunk/tests/qunit/editor/tinymce/ui/MenuItem.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMessageBoxhtml">trunk/tests/qunit/editor/tinymce/ui/MessageBox.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiMovablehtml">trunk/tests/qunit/editor/tinymce/ui/Movable.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiPanelhtml">trunk/tests/qunit/editor/tinymce/ui/Panel.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiPanelButtonhtml">trunk/tests/qunit/editor/tinymce/ui/PanelButton.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiPathhtml">trunk/tests/qunit/editor/tinymce/ui/Path.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiRadiohtml">trunk/tests/qunit/editor/tinymce/ui/Radio.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiResizeHandlehtml">trunk/tests/qunit/editor/tinymce/ui/ResizeHandle.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiScrollablehtml">trunk/tests/qunit/editor/tinymce/ui/Scrollable.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiSelectorhtml">trunk/tests/qunit/editor/tinymce/ui/Selector.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiSpacerhtml">trunk/tests/qunit/editor/tinymce/ui/Spacer.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiSplitButtonhtml">trunk/tests/qunit/editor/tinymce/ui/SplitButton.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiStackLayouthtml">trunk/tests/qunit/editor/tinymce/ui/StackLayout.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiTabPanelhtml">trunk/tests/qunit/editor/tinymce/ui/TabPanel.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiTextBoxhtml">trunk/tests/qunit/editor/tinymce/ui/TextBox.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiThrobberhtml">trunk/tests/qunit/editor/tinymce/ui/Throbber.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiToolbarhtml">trunk/tests/qunit/editor/tinymce/ui/Toolbar.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiTooltiphtml">trunk/tests/qunit/editor/tinymce/ui/Tooltip.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiWidgethtml">trunk/tests/qunit/editor/tinymce/ui/Widget.html</a></li>
<li><a href="#trunktestsquniteditortinymceuiWindowhtml">trunk/tests/qunit/editor/tinymce/ui/Window.html</a></li>
<li><a href="#trunktestsquniteditortinymceuitestsjs">trunk/tests/qunit/editor/tinymce/ui/tests.js</a></li>
<li><a href="#trunktestsquniteditortinymceutilJSONhtml">trunk/tests/qunit/editor/tinymce/util/JSON.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilJSONRequesthtml">trunk/tests/qunit/editor/tinymce/util/JSONRequest.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilLocalStoragehtml">trunk/tests/qunit/editor/tinymce/util/LocalStorage.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_allhtml">trunk/tests/qunit/editor/tinymce/util/Quirks_all.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_firefoxhtml">trunk/tests/qunit/editor/tinymce/util/Quirks_firefox.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_ie8html">trunk/tests/qunit/editor/tinymce/util/Quirks_ie8.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_removehtml">trunk/tests/qunit/editor/tinymce/util/Quirks_remove.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_webkithtml">trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilQuirks_webkit_jsrobothtml">trunk/tests/qunit/editor/tinymce/util/Quirks_webkit_jsrobot.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilURIhtml">trunk/tests/qunit/editor/tinymce/util/URI.html</a></li>
<li><a href="#trunktestsquniteditortinymceutilXHRhtml">trunk/tests/qunit/editor/tinymce/util/XHR.html</a></li>
<li><a href="#trunktestsquniteditortinymceutiltestsjs">trunk/tests/qunit/editor/tinymce/util/tests.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunktestsquniteditorindexhtml"></a>
<div class="modfile"><h4>Modified: trunk/tests/qunit/editor/index.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/index.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/index.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,22 +1,96 @@
</span><span class="cx"> <!DOCTYPE html>
</span><span class="cx"> <html>
</span><span class="cx"> <head>
</span><del>-<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>
</del><ins>+        <meta charset="UTF-8" />
+       <title>TinyMCE QUnit tests</title>
+       <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+       <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />
+       <title>QUnit tests</title>
+       <link rel="stylesheet" href="js/qunit/qunit.css" type="text/css" />
+       <link rel="stylesheet" href="../../../src/wp-includes/js/tinymce/skins/lightgray/skin.min.css" type="text/css" />
+       <link rel="stylesheet" href="tinymce/ui/css/ui-overrides.css" type="text/css" />
+       <style>
+               #qunit-modulefilter-container { float: none; }
+       </style>
</ins><span class="cx"> </head>
</span><span class="cx"> <body>
</span><ins>+       <div id="qunit"></div>
+       <div id="qunit-fixture"></div>
+       <div id="view" style="position: absolute; right: 0; top: 0"></div>
+
+       <script src="http://www.google.com/jsapi"></script>
+       <script>google.load("jquery", "1");</script>
+       <script src="js/qunit/qunit.js"></script>
+       <script src="../../../src/wp-includes/js/tinymce/tinymce.min.js"></script>
+<!--<script src="../js/tinymce/classes/jquery.tinymce.js"></script> -->
+       <script src="js/utils.js"></script>
+       <script src="js/init.js"></script>
+
+       <!-- tinymce.dom.* -->
+       <script src="tinymce/dom/DOMUtils.js"></script>
+       <script src="tinymce/dom/EventUtils.js"></script>
+       <script src="tinymce/dom/Range.js"></script>
+       <script src="tinymce/dom/Selection.js"></script>
+       <script src="tinymce/dom/Serializer.js"></script>
+       <script src="tinymce/dom/TridentSelection.js"></script>
+
+       <!-- tinymce.html.* -->
+       <script src="tinymce/html/DomParser.js"></script>
+       <script src="tinymce/html/Entities.js"></script>
+       <script src="tinymce/html/Node.js"></script>
+       <script src="tinymce/html/SaxParser.js"></script>
+       <script src="tinymce/html/Schema.js"></script>
+       <script src="tinymce/html/Obsolete.js"></script>
+       <script src="tinymce/html/Styles.js"></script>
+       <script src="tinymce/html/Writer.js"></script>
+
+       <!-- tnymce.ui.* -->
+       <script src="tinymce/ui/AbsoluteLayout.js"></script>
+       <script src="tinymce/ui/Button.js"></script>
+       <script src="tinymce/ui/Collection.js"></script>
+       <script src="tinymce/ui/ColorButton.js"></script>
+       <script src="tinymce/ui/Control.js"></script>
+       <script src="tinymce/ui/FitLayout.js"></script>
+       <script src="tinymce/ui/FlexLayout.js"></script>
+       <script src="tinymce/ui/GridLayout.js"></script>
+       <script src="tinymce/ui/MenuButton.js"></script>
+       <script src="tinymce/ui/Panel.js"></script>
+       <script src="tinymce/ui/Selector.js"></script>
+       <script src="tinymce/ui/SplitButton.js"></script>
+       <script src="tinymce/ui/TabPanel.js"></script>
+       <script src="tinymce/ui/TextBox.js"></script>
+       <script src="tinymce/ui/Window.js"></script>
+
+       <!-- tinymce.util.* -->
+       <script src="tinymce/util/JSON.js"></script>
+       <script src="tinymce/util/JSONRequest.js"></script>
+       <script src="tinymce/util/LocalStorage.js"></script>
+       <script src="tinymce/util/Quirks_webkit.js"></script>
+       <script src="tinymce/util/URI.js"></script>
+       <script src="tinymce/util/XHR.js"></script>
+
+       <!-- tinymce.* -->
+       <script src="tinymce/Editor.js"></script>
+       <script src="tinymce/EditorCommands.js"></script>
+       <script src="tinymce/EnterKey.js"></script>
+       <script src="tinymce/ForceBlocks.js"></script>
+       <script src="tinymce/Formatter_apply.js"></script>
+       <script src="tinymce/Formatter_check.js"></script>
+       <script src="tinymce/Formatter_remove.js"></script>
+       <script src="tinymce/UndoManager.js"></script>
+
+       <!-- tinymce.plugins.* -->
+<!--<script src="plugins/autosave.js"></script>
+       <script src="plugins/fullpage.js"></script>
+       <script src="plugins/jquery_plugin.js"></script>
+       <script src="plugins/legacyoutput.js"></script>
+       <script src="plugins/lists.js"></script> -->
+       <script src="plugins/media.js"></script>
+<!--<script src="plugins/noneditable.js"></script> -->
+       <script src="plugins/paste.js"></script>
+<!--<script src="plugins/searchreplace.js"></script>
+       <script src="plugins/spellchecker.js"></script>
+       <script src="plugins/table.js"></script>
+       <script src="plugins/wordcount.js"></script> -->
</ins><span class="cx"> </body>
</span><span class="cx"> </html>
</span></span></pre></div>
<a id="trunktestsquniteditorjsinitjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/js/init.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/init.js                              (rev 0)
+++ trunk/tests/qunit/editor/js/init.js 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+(function() {
+       var coverObjects = [], modulesExecuted = {};
+
+       QUnit.config.reorder = false;
+
+       var oldModule = module;
+
+       QUnit.moduleStart(function(details) {
+               modulesExecuted[details.name] = true;
+
+               tinymce.remove();
+               document.getElementById('view').innerHTML = '<textarea></textarea>';
+       });
+
+       QUnit.moduleDone(function() {
+               tinymce.remove();
+               window.editor = window.inlineEditor = null;
+       });
+
+       QUnit.done(function() {
+               document.getElementById("view").style.display = 'none';
+
+               if (window.__$coverObject) {
+                       coverObjects.push(window.__$coverObject);
+
+                       $('<button>Coverage report</button>').on('click', function() {
+                               window.open('coverage/index.html', 'coverage');
+                       }).appendTo(document.body);
+               }
+       });
+
+       window.module = function(name, settings) {
+               settings = settings || {};
+
+               if (settings.setupModule) {
+                       QUnit.moduleStart(function(details) {
+                               if (details.name == name) {
+                                       settings.setupModule();
+                               }
+                       });
+               }
+
+               if (settings.teardownModule) {
+                       QUnit.moduleDone(function(details) {
+                               if (details.name == name) {
+                                       settings.teardownModule();
+                               }
+                       });
+               }
+
+               oldModule(name, settings);
+       };
+
+       window.getCoverObject = function() {
+               var coverObject = {}, fileName, gaps, gap, count, targetModuleName;
+               var isScoped = document.location.search.indexOf('module=') != -1;
+
+               for (var i = 0, length = coverObjects.length; i < length; i++) {
+                       for (fileName in coverObjects[i]) {
+                               gaps = coverObjects[i][fileName];
+
+                               if (isScoped && fileName.indexOf('js/tinymce/classes') === 0) {
+                                       targetModuleName = "tinymce." + fileName.substr('js/tinymce/classes'.length + 1).replace(/\//g, '.');
+                                       targetModuleName = targetModuleName.replace(/\.js$/, '');
+
+                                       if (!modulesExecuted[targetModuleName]) {
+                                               continue;
+                                       }
+                               }
+
+                               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;
+       };
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/js/init.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorjsqunitqunitcss"></a>
<div class="modfile"><h4>Modified: trunk/tests/qunit/editor/js/qunit/qunit.css (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/qunit/qunit.css      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/qunit/qunit.css 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,119 +1,237 @@
</span><ins>+/*!
+ * QUnit 1.14.0
+ * http://qunitjs.com/
+ *
+ * Copyright 2013 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-01-31T16:40Z
+ */
</ins><span class="cx"> 
</span><del>-ol#qunit-tests {
-       font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
-       margin:0;
-       padding:0;
-       list-style-position:inside;
</del><ins>+/** Font Family and Sizes */
</ins><span class="cx"> 
</span><del>-       font-size: smaller;
</del><ins>+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
+       font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
</ins><span class="cx"> }
</span><del>-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;
</del><ins>+
+#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+       margin: 0;
+       padding: 0;
</ins><span class="cx"> }
</span><del>-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;
</del><ins>+
+
+/** Header */
+
+#qunit-header {
+       padding: 0.5em 0 0.5em 1em;
+
+       color: #8699A4;
+       background-color: #0D3349;
+
+       font-size: 1.5em;
+       line-height: 1em;
+       font-weight: 400;
+
+       border-radius: 5px 5px 0 0;
</ins><span class="cx"> }
</span><del>-ol#qunit-tests li li{
-       border-bottom:none;
-       margin:0.5em;
-       background-color:#fff;
</del><ins>+
+#qunit-header a {
+       text-decoration: none;
+       color: #C2CCD1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+       color: #FFF;
+}
+
+#qunit-testrunner-toolbar label {
+       display: inline-block;
+       padding: 0 0.5em 0 0.1em;
+}
+
+#qunit-banner {
+       height: 5px;
+}
+
+#qunit-testrunner-toolbar {
+       padding: 0.5em 0 0.5em 2em;
+       color: #5E740B;
+       background-color: #EEE;
+       overflow: hidden;
+}
+
+#qunit-userAgent {
+       padding: 0.5em 0 0.5em 2.5em;
+       background-color: #2B81AF;
+       color: #FFF;
+       text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+#qunit-modulefilter-container {
+       float: right;
+}
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
</ins><span class="cx">   list-style-position: inside;
</span><del>-       padding:0.4em 0.5em 0.4em 0.5em;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-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;
</del><ins>+#qunit-tests li {
+       padding: 0.4em 0.5em 0.4em 2.5em;
+       border-bottom: 1px solid #FFF;
+       list-style-position: inside;
</ins><span class="cx"> }
</span><del>-ol#qunit-tests li.pass{
-       background-color:#D2E0E6;
-       color:#528CE0;
</del><ins>+
+#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
+       display: none;
</ins><span class="cx"> }
</span><del>-ol#qunit-tests li.fail{
-       background-color:#EE5757;
-       color:#000;
</del><ins>+
+#qunit-tests li strong {
+       cursor: pointer;
</ins><span class="cx"> }
</span><del>-ol#qunit-tests li strong {
-       cursor:pointer;
</del><ins>+
+#qunit-tests li a {
+       padding: 0.5em;
+       color: #C2CCD1;
+       text-decoration: none;
</ins><span class="cx"> }
</span><del>-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;
</del><ins>+#qunit-tests li a:hover,
+#qunit-tests li a:focus {
+       color: #000;
</ins><span class="cx"> }
</span><del>-h2#qunit-banner{
-       font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
-       height:5px;
-       margin:0;
-       padding:0;
</del><ins>+
+#qunit-tests li .runtime {
+       float: right;
+       font-size: smaller;
</ins><span class="cx"> }
</span><del>-h2#qunit-banner.qunit-pass{
-       background-color:#C6E746;
</del><ins>+
+.qunit-assert-list {
+       margin-top: 0.5em;
+       padding: 0.5em;
+
+       background-color: #FFF;
+
+       border-radius: 5px;
</ins><span class="cx"> }
</span><del>-h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar {
-       background-color:#EE5757;
</del><ins>+
+.qunit-collapsed {
+       display: none;
</ins><span class="cx"> }
</span><del>-#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;
</del><ins>+
+#qunit-tests table {
+       border-collapse: collapse;
+       margin-top: 0.2em;
</ins><span class="cx"> }
</span><del>-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;
</del><ins>+
+#qunit-tests th {
+       text-align: right;
+       vertical-align: top;
+       padding: 0 0.5em 0 0;
</ins><span class="cx"> }
</span><del>-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;
</del><ins>+
+#qunit-tests td {
+       vertical-align: top;
</ins><span class="cx"> }
</span><del>-strong b.fail{
-       color:#710909;
-       }
-strong b.pass{
-       color:#5E740B;
-       }
</del><ins>+
+#qunit-tests pre {
+       margin: 0;
+       white-space: pre-wrap;
+       word-wrap: break-word;
+}
+
+#qunit-tests del {
+       background-color: #E0F2BE;
+       color: #374E0C;
+       text-decoration: none;
+}
+
+#qunit-tests ins {
+       background-color: #FFCACA;
+       color: #500;
+       text-decoration: none;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts                       { color: #000; }
+#qunit-tests b.passed                       { color: #5E740B; }
+#qunit-tests b.failed                       { color: #710909; }
+
+#qunit-tests li li {
+       padding: 5px;
+       background-color: #FFF;
+       border-bottom: none;
+       list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+       color: #3C510C;
+       background-color: #FFF;
+       border-left: 10px solid #C6E746;
+}
+
+#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name               { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected           { color: #999; }
+
+#qunit-banner.qunit-pass                    { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+       color: #710909;
+       background-color: #FFF;
+       border-left: 10px solid #EE5757;
+       white-space: pre;
+}
+
+#qunit-tests > li:last-child {
+       border-radius: 0 0 5px 5px;
+}
+
+#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name             { color: #000; }
+
+#qunit-tests .fail .test-actual             { color: #EE5757; }
+#qunit-tests .fail .test-expected           { color: #008000; }
+
+#qunit-banner.qunit-fail                    { background-color: #EE5757; }
+
+
+/** Result */
+
+#qunit-testresult {
+       padding: 0.5em 0.5em 0.5em 2.5em;
+
+       color: #2B81AF;
+       background-color: #D2E0E6;
+
+       border-bottom: 1px solid #FFF;
+}
+#qunit-testresult .module-name {
+       font-weight: 700;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+       position: absolute;
+       top: -10000px;
+       left: -10000px;
+       width: 1000px;
+       height: 1000px;
+}
</ins></span></pre></div>
<a id="trunktestsquniteditorjsqunitqunitjs"></a>
<div class="modfile"><h4>Modified: trunk/tests/qunit/editor/js/qunit/qunit.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/qunit/qunit.js       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/qunit/qunit.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,401 +1,359 @@
</span><del>-/*
- * QUnit - A JavaScript Unit Testing Framework
- * 
- * http://docs.jquery.com/QUnit
</del><ins>+/*!
+ * QUnit 1.14.0
+ * http://qunitjs.com/
</ins><span class="cx">  *
</span><del>- * Copyright (c) 2009 John Resig, Jörn Zaefferer
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
</del><ins>+ * Copyright 2013 jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-01-31T16:40Z
</ins><span class="cx">  */
</span><span class="cx"> 
</span><del>-(function(window) {
</del><ins>+(function( window ) {
</ins><span class="cx"> 
</span><del>-var QUnit = {
</del><ins>+var QUnit,
+       assert,
+       config,
+       onErrorFnPrev,
+       testId = 0,
+       fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
+       toString = Object.prototype.toString,
+       hasOwn = Object.prototype.hasOwnProperty,
+       // Keep a local reference to Date (GH-283)
+       Date = window.Date,
+       setTimeout = window.setTimeout,
+       clearTimeout = window.clearTimeout,
+       defined = {
+               document: typeof window.document !== "undefined",
+               setTimeout: typeof window.setTimeout !== "undefined",
+               sessionStorage: (function() {
+                       var x = "qunit-test-string";
+                       try {
+                               sessionStorage.setItem( x, x );
+                               sessionStorage.removeItem( x );
+                               return true;
+                       } catch( e ) {
+                               return false;
+                       }
+               }())
+       },
+       /**
+        * Provides a normalized error string, correcting an issue
+        * with IE 7 (and prior) where Error.prototype.toString is
+        * not properly implemented
+        *
+        * Based on http://es5.github.com/#x15.11.4.4
+        *
+        * @param {String|Error} error
+        * @return {String} error message
+        */
+       errorString = function( error ) {
+               var name, message,
+                       errorString = error.toString();
+               if ( errorString.substring( 0, 7 ) === "[object" ) {
+                       name = error.name ? error.name.toString() : "Error";
+                       message = error.message ? error.message.toString() : "";
+                       if ( name && message ) {
+                               return name + ": " + message;
+                       } else if ( name ) {
+                               return name;
+                       } else if ( message ) {
+                               return message;
+                       } else {
+                               return "Error";
+                       }
+               } else {
+                       return errorString;
+               }
+       },
+       /**
+        * Makes a clone of an object using only Array or Object as base,
+        * and copies over the own enumerable properties.
+        *
+        * @param {Object} obj
+        * @return {Object} New object with only the own properties (recursively).
+        */
+       objectValues = function( obj ) {
+               // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
+               /*jshint newcap: false */
+               var key, val,
+                       vals = QUnit.is( "array", obj ) ? [] : {};
+               for ( key in obj ) {
+                       if ( hasOwn.call( obj, key ) ) {
+                               val = obj[key];
+                               vals[key] = val === Object(val) ? objectValues(val) : val;
+                       }
+               }
+               return vals;
+       };
</ins><span class="cx"> 
</span><ins>+
+// Root QUnit object.
+// `QUnit` initialized at top of scope
+QUnit = {
+
</ins><span class="cx">   // call on start of module test to prepend name to all tests
</span><del>-       module: function(name, testEnvironment) {
</del><ins>+        module: function( name, testEnvironment ) {
</ins><span class="cx">           config.currentModule = name;
</span><del>-
-               synchronize(function() {
-                       if ( config.currentModule ) {
-                               QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
-                       }
-
-                       config.currentModule = name;
-                       config.moduleTestEnvironment = testEnvironment;
-                       config.moduleStats = { all: 0, bad: 0 };
-
-                       QUnit.moduleStart( name, testEnvironment );
-               });
</del><ins>+                config.currentModuleTestEnvironment = testEnvironment;
+               config.modules[name] = true;
</ins><span class="cx">   },
</span><span class="cx"> 
</span><del>-       asyncTest: function(testName, expected, callback) {
</del><ins>+        asyncTest: function( testName, expected, callback ) {
</ins><span class="cx">           if ( arguments.length === 2 ) {
</span><span class="cx">                  callback = expected;
</span><del>-                       expected = 0;
</del><ins>+                        expected = null;
</ins><span class="cx">           }
</span><span class="cx"> 
</span><del>-               QUnit.test(testName, expected, callback, true);
</del><ins>+                QUnit.test( testName, expected, callback, true );
</ins><span class="cx">   },
</span><del>-       
-       test: function(testName, expected, callback, async) {
-               var name = '<span class="test-name">' + testName + '</span>', testEnvironment, testEnvironmentArg;
</del><span class="cx"> 
</span><ins>+       test: function( testName, expected, callback, async ) {
+               var test,
+                       nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
+
</ins><span class="cx">           if ( arguments.length === 2 ) {
</span><span class="cx">                  callback = expected;
</span><span class="cx">                  expected = null;
</span><span class="cx">          }
</span><del>-               // is 2nd argument a testEnvironment?
-               if ( expected && typeof expected === 'object') {
-                       testEnvironmentArg =  expected;
-                       expected = null;
-               }
</del><span class="cx"> 
</span><span class="cx">          if ( config.currentModule ) {
</span><del>-                       name = '<span class="module-name">' + config.currentModule + "</span>: " + name;
</del><ins>+                        nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
</ins><span class="cx">           }
</span><span class="cx"> 
</span><del>-               if ( !validTest(config.currentModule + ": " + testName) ) {
-                       return;
-               }
-
-               synchronize(function() {
-
-                       testEnvironment = extend({
-                               setup: function() {},
-                               teardown: function() {}
-                       }, config.moduleTestEnvironment);
-                       if (testEnvironmentArg) {
-                               extend(testEnvironment,testEnvironmentArg);
-                       }
-
-                       QUnit.testStart( testName, testEnvironment );
-
-                       // allow utility functions to access the current test environment
-                       QUnit.current_testEnvironment = testEnvironment;
-                       
-                       config.assertions = [];
-                       config.expected = expected;
-                       
-                       var tests = id("qunit-tests");
-                       if (tests) {
-                               var b = document.createElement("strong");
-                                       b.innerHTML = "Running " + name;
-                               var li = document.createElement("li");
-                                       li.appendChild( b );
-                                       li.id = "current-test-output";
-                               tests.appendChild( li )
-                       }
-
-                       try {
-                               if ( !config.pollution ) {
-                                       saveGlobal();
-                               }
-
-                               testEnvironment.setup.call(testEnvironment);
-                       } catch(e) {
-                               QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
-                       }
-           });
-       
-           synchronize(function() {
-                       if ( async ) {
-                               QUnit.stop();
-                       }
-
-                       try {
-                               callback.call(testEnvironment);
-                       } catch(e) {
-                               fail("Test " + name + " died, exception and test follows", e, callback);
-                               QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
-                               // else next test will carry the responsibility
-                               saveGlobal();
-
-                               // Restart the tests if they're blocking
-                               if ( config.blocking ) {
-                                       start();
-                               }
-                       }
</del><ins>+                test = new Test({
+                       nameHtml: nameHtml,
+                       testName: testName,
+                       expected: expected,
+                       async: async,
+                       callback: callback,
+                       module: config.currentModule,
+                       moduleTestEnvironment: config.currentModuleTestEnvironment,
+                       stack: sourceFromStacktrace( 2 )
</ins><span class="cx">           });
</span><span class="cx"> 
</span><del>-               synchronize(function() {
-                       try {
-                               checkPollution();
-                               testEnvironment.teardown.call(testEnvironment);
-                       } catch(e) {
-                               QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
-                       }
-           });
-       
-           synchronize(function() {
-                       try {
-                               QUnit.reset();
-                       } catch(e) {
-                               fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset);
-                       }
-
-                       if ( config.expected && config.expected != config.assertions.length ) {
-                               QUnit.ok( false, "Expected " + config.expected + " assertions, but " + config.assertions.length + " were run" );
-                       }
-
-                       var good = 0, bad = 0,
-                               tests = id("qunit-tests");
-
-                       config.stats.all += config.assertions.length;
-                       config.moduleStats.all += config.assertions.length;
-
-                       if ( tests ) {
-                               var ol  = document.createElement("ol");
-
-                               for ( var i = 0; i < config.assertions.length; i++ ) {
-                                       var assertion = config.assertions[i];
-
-                                       var li = document.createElement("li");
-                                       li.className = assertion.result ? "pass" : "fail";
-                                       li.innerHTML = assertion.message || "(no message)";
-                                       ol.appendChild( li );
-
-                                       if ( assertion.result ) {
-                                               good++;
-                                       } else {
-                                               bad++;
-                                               config.stats.bad++;
-                                               config.moduleStats.bad++;
-                                       }
-                               }
-                               if (bad == 0) {
-                                       ol.style.display = "none";
-                               }
-
-                               var b = document.createElement("strong");
-                               b.innerHTML = name + " <b style='color:black;'>(<b class='fail'>" + bad + "</b>, <b class='pass'>" + good + "</b>, " + config.assertions.length + ")</b>";
-                               
-                               addEvent(b, "click", function() {
-                                       var next = b.nextSibling, display = next.style.display;
-                                       next.style.display = display === "none" ? "block" : "none";
-                               });
-                               
-                               addEvent(b, "dblclick", function(e) {
-                                       var target = e && e.target ? e.target : window.event.srcElement;
-                                       if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) {
-                                               target = target.parentNode;
-                                       }
-                                       if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
-                                               window.location.search = "?" + encodeURIComponent(getText([target]).replace(/\(.+\)$/, "").replace(/(^\s*|\s*$)/g, ""));
-                                       }
-                               });
-
-                               var li = id("current-test-output");
-                               li.id = "";
-                               li.className = bad ? "fail" : "pass";
-                               li.removeChild( li.firstChild );
-                               li.appendChild( b );
-                               li.appendChild( ol );
-
-                               if ( bad ) {
-                                       var toolbar = id("qunit-testrunner-toolbar");
-                                       if ( toolbar ) {
-                                               toolbar.style.display = "block";
-                                               id("qunit-filter-pass").disabled = null;
-                                               id("qunit-filter-missing").disabled = null;
-                                       }
-                               }
-
-                       } else {
-                               for ( var i = 0; i < config.assertions.length; i++ ) {
-                                       if ( !config.assertions[i].result ) {
-                                               bad++;
-                                               config.stats.bad++;
-                                               config.moduleStats.bad++;
-                                       }
-                               }
-                       }
-
-                       QUnit.testDone( testName, bad, config.assertions.length );
-
-                       if ( !window.setTimeout && !config.queue.length ) {
-                               done();
-                       }
-               });
-
-               if ( window.setTimeout && !config.doneTimer ) {
-                       config.doneTimer = window.setTimeout(function(){
-                               if ( !config.queue.length ) {
-                                       done();
-                               } else {
-                                       synchronize( done );
-                               }
-                       }, 13);
</del><ins>+                if ( !validTest( test ) ) {
+                       return;
</ins><span class="cx">           }
</span><del>-       },
-       
-       /**
-        * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
-        */
-       expect: function(asserts) {
-               config.expected = asserts;
-       },
</del><span class="cx"> 
</span><del>-       /**
-        * Asserts true.
-        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
-        */
-       ok: function(a, msg) {
-               msg = escapeHtml(msg);
-               QUnit.log(a, msg);
-
-               config.assertions.push({
-                       result: !!a,
-                       message: msg
-               });
</del><ins>+                test.queue();
</ins><span class="cx">   },
</span><span class="cx"> 
</span><del>-       /**
-        * Checks that the first two arguments are equal, with an optional message.
-        * Prints out both actual and expected values.
-        *
-        * Prefered to ok( actual == expected, message )
-        *
-        * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
-        *
-        * @param Object actual
-        * @param Object expected
-        * @param String message (optional)
-        */
-       equal: function(actual, expected, message) {
-               push(expected == actual, actual, expected, message);
</del><ins>+        // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.
+       expect: function( asserts ) {
+               if (arguments.length === 1) {
+                       config.current.expected = asserts;
+               } else {
+                       return config.current.expected;
+               }
</ins><span class="cx">   },
</span><span class="cx"> 
</span><del>-       notEqual: function(actual, expected, message) {
-               push(expected != actual, actual, expected, message);
-       },
-       
-       deepEqual: function(actual, expected, message) {
-               push(QUnit.equiv(actual, expected), actual, expected, message);
-       },
</del><ins>+        start: function( count ) {
+               // QUnit hasn't been initialized yet.
+               // Note: RequireJS (et al) may delay onLoad
+               if ( config.semaphore === undefined ) {
+                       QUnit.begin(function() {
+                               // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
+                               setTimeout(function() {
+                                       QUnit.start( count );
+                               });
+                       });
+                       return;
+               }
</ins><span class="cx"> 
</span><del>-       notDeepEqual: function(actual, expected, message) {
-               push(!QUnit.equiv(actual, expected), actual, expected, message);
-       },
-
-       strictEqual: function(actual, expected, message) {
-               push(expected === actual, actual, expected, message);
-       },
-
-       notStrictEqual: function(actual, expected, message) {
-               push(expected !== actual, actual, expected, message);
-       },
-
-       raises: function(fn,  message) {
-               try {
-                       fn();
-                       ok( false, message );
</del><ins>+                config.semaphore -= count || 1;
+               // don't start until equal number of stop-calls
+               if ( config.semaphore > 0 ) {
+                       return;
</ins><span class="cx">           }
</span><del>-               catch (e) {
-                       ok( true, message );
</del><ins>+                // ignore if start is called more often then stop
+               if ( config.semaphore < 0 ) {
+                       config.semaphore = 0;
+                       QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
+                       return;
</ins><span class="cx">           }
</span><del>-       },
-
-       start: function() {
</del><span class="cx">           // A slight delay, to avoid any current callbacks
</span><del>-               if ( window.setTimeout ) {
-                       window.setTimeout(function() {
</del><ins>+                if ( defined.setTimeout ) {
+                       setTimeout(function() {
+                               if ( config.semaphore > 0 ) {
+                                       return;
+                               }
</ins><span class="cx">                           if ( config.timeout ) {
</span><del>-                                       clearTimeout(config.timeout);
</del><ins>+                                        clearTimeout( config.timeout );
</ins><span class="cx">                           }
</span><span class="cx"> 
</span><span class="cx">                          config.blocking = false;
</span><del>-                               process();
</del><ins>+                                process( true );
</ins><span class="cx">                   }, 13);
</span><span class="cx">          } else {
</span><span class="cx">                  config.blocking = false;
</span><del>-                       process();
</del><ins>+                        process( true );
</ins><span class="cx">           }
</span><span class="cx">  },
</span><del>-       
-       stop: function(timeout) {
</del><ins>+
+       stop: function( count ) {
+               config.semaphore += count || 1;
</ins><span class="cx">           config.blocking = true;
</span><span class="cx"> 
</span><del>-               if ( timeout && window.setTimeout ) {
-                       config.timeout = window.setTimeout(function() {
</del><ins>+                if ( config.testTimeout && defined.setTimeout ) {
+                       clearTimeout( config.timeout );
+                       config.timeout = setTimeout(function() {
</ins><span class="cx">                           QUnit.ok( false, "Test timed out" );
</span><ins>+                               config.semaphore = 1;
</ins><span class="cx">                           QUnit.start();
</span><del>-                       }, timeout);
</del><ins>+                        }, config.testTimeout );
</ins><span class="cx">           }
</span><span class="cx">  }
</span><del>-
</del><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Backwards compatibility, deprecated
-QUnit.equals = QUnit.equal;
-QUnit.same = QUnit.deepEqual;
</del><ins>+// We use the prototype to distinguish between properties that should
+// be exposed as globals (and in exports) and those that shouldn't
+(function() {
+       function F() {}
+       F.prototype = QUnit;
+       QUnit = new F();
+       // Make F QUnit's constructor so that we can add to the prototype later
+       QUnit.constructor = F;
+}());
</ins><span class="cx"> 
</span><del>-// Maintain internal state
-var config = {
</del><ins>+/**
+ * Config object: Maintain internal state
+ * Later exposed as QUnit.config
+ * `config` initialized at top of scope
+ */
+config = {
</ins><span class="cx">   // The queue of tests to run
</span><span class="cx">  queue: [],
</span><span class="cx"> 
</span><span class="cx">  // block until document ready
</span><del>-       blocking: true
</del><ins>+        blocking: true,
+
+       // when enabled, show only failing tests
+       // gets persisted through sessionStorage and can be changed in UI via checkbox
+       hidepassed: false,
+
+       // by default, run previously failed tests first
+       // very useful in combination with "Hide passed tests" checked
+       reorder: true,
+
+       // by default, modify document.title when suite is done
+       altertitle: true,
+
+       // by default, scroll to top of the page when suite is done
+       scrolltop: true,
+
+       // when enabled, all tests must call expect()
+       requireExpects: false,
+
+       // add checkboxes that are persisted in the query-string
+       // when enabled, the id is set to `true` as a `QUnit.config` property
+       urlConfig: [
+               {
+                       id: "noglobals",
+                       label: "Check for Globals",
+                       tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
+               },
+               {
+                       id: "notrycatch",
+                       label: "No try-catch",
+                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
+               }
+       ],
+
+       // Set of all modules.
+       modules: {},
+
+       // logging callback queues
+       begin: [],
+       done: [],
+       log: [],
+       testStart: [],
+       testDone: [],
+       moduleStart: [],
+       moduleDone: []
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-// Load parameters
</del><ins>+// Initialize more QUnit.config and QUnit.urlParams
</ins><span class="cx"> (function() {
</span><del>-       var location = window.location || { search: "", protocol: "file:" },
-               GETParams = location.search.slice(1).split('&');
</del><ins>+        var i, current,
+               location = window.location || { search: "", protocol: "file:" },
+               params = location.search.slice( 1 ).split( "&" ),
+               length = params.length,
+               urlParams = {};
</ins><span class="cx"> 
</span><del>-       for ( var i = 0; i < GETParams.length; i++ ) {
-               GETParams[i] = decodeURIComponent( GETParams[i] );
-               if ( GETParams[i] === "noglobals" ) {
-                       GETParams.splice( i, 1 );
-                       i--;
-                       config.noglobals = true;
-               } else if ( GETParams[i].search('=') > -1 ) {
-                       GETParams.splice( i, 1 );
-                       i--;
</del><ins>+        if ( params[ 0 ] ) {
+               for ( i = 0; i < length; i++ ) {
+                       current = params[ i ].split( "=" );
+                       current[ 0 ] = decodeURIComponent( current[ 0 ] );
+
+                       // allow just a key to turn on a flag, e.g., test.html?noglobals
+                       current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;
+                       if ( urlParams[ current[ 0 ] ] ) {
+                               urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );
+                       } else {
+                               urlParams[ current[ 0 ] ] = current[ 1 ];
+                       }
</ins><span class="cx">           }
</span><span class="cx">  }
</span><del>-       
-       // restrict modules/tests by get parameters
-       config.filters = GETParams;
-       
</del><ins>+
+       QUnit.urlParams = urlParams;
+
+       // String search anywhere in moduleName+testName
+       config.filter = urlParams.filter;
+
+       // Exact match of the module name
+       config.module = urlParams.module;
+
+       config.testNumber = [];
+       if ( urlParams.testNumber ) {
+
+               // Ensure that urlParams.testNumber is an array
+               urlParams.testNumber = [].concat( urlParams.testNumber );
+               for ( i = 0; i < urlParams.testNumber.length; i++ ) {
+                       current = urlParams.testNumber[ i ];
+                       config.testNumber.push( parseInt( current, 10 ) );
+               }
+       }
+
</ins><span class="cx">   // Figure out if we're running the tests from a server or not
</span><del>-       QUnit.isLocal = !!(location.protocol === 'file:');
-})();
</del><ins>+        QUnit.isLocal = location.protocol === "file:";
+}());
</ins><span class="cx"> 
</span><del>-// Expose the API as global variables, unless an 'exports'
-// object exists, in that case we assume we're in CommonJS
-if ( typeof exports === "undefined" || typeof require === "undefined" ) {
-       extend(window, QUnit);
-       window.QUnit = QUnit;
-} else {
-       extend(exports, QUnit);
-       exports.QUnit = QUnit;
-}
</del><ins>+extend( QUnit, {
</ins><span class="cx"> 
</span><del>-// define these after exposing globals to keep them in these QUnit namespace only
-extend(QUnit, {
</del><span class="cx">   config: config,
</span><span class="cx"> 
</span><span class="cx">  // Initialize the configuration options
</span><span class="cx">  init: function() {
</span><del>-               extend(config, {
</del><ins>+                extend( config, {
</ins><span class="cx">                   stats: { all: 0, bad: 0 },
</span><span class="cx">                  moduleStats: { all: 0, bad: 0 },
</span><del>-                       started: +new Date,
</del><ins>+                        started: +new Date(),
</ins><span class="cx">                   updateRate: 1000,
</span><span class="cx">                  blocking: false,
</span><span class="cx">                  autostart: true,
</span><span class="cx">                  autorun: false,
</span><del>-                       assertions: [],
-                       filters: [],
-                       queue: []
</del><ins>+                        filter: "",
+                       queue: [],
+                       semaphore: 1
</ins><span class="cx">           });
</span><span class="cx"> 
</span><del>-               var tests = id("qunit-tests"),
-                       banner = id("qunit-banner"),
-                       result = id("qunit-testresult");
</del><ins>+                var tests, banner, result,
+                       qunit = id( "qunit" );
</ins><span class="cx"> 
</span><ins>+               if ( qunit ) {
+                       qunit.innerHTML =
+                               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                               "<h2 id='qunit-banner'></h2>" +
+                               "<div id='qunit-testrunner-toolbar'></div>" +
+                               "<h2 id='qunit-userAgent'></h2>" +
+                               "<ol id='qunit-tests'></ol>";
+               }
+
+               tests = id( "qunit-tests" );
+               banner = id( "qunit-banner" );
+               result = id( "qunit-testresult" );
+
</ins><span class="cx">           if ( tests ) {
</span><span class="cx">                  tests.innerHTML = "";
</span><span class="cx">          }
</span><span class="lines">@@ -407,325 +365,709 @@
</span><span class="cx">          if ( result ) {
</span><span class="cx">                  result.parentNode.removeChild( result );
</span><span class="cx">          }
</span><ins>+
+               if ( tests ) {
+                       result = document.createElement( "p" );
+                       result.id = "qunit-testresult";
+                       result.className = "result";
+                       tests.parentNode.insertBefore( result, tests );
+                       result.innerHTML = "Running...<br/>&nbsp;";
+               }
</ins><span class="cx">   },
</span><del>-       
-       /**
-        * Resets the test setup. Useful for tests that modify the DOM.
-        */
</del><ins>+
+       // Resets the test setup. Useful for tests that modify the DOM.
+       /*
+       DEPRECATED: Use multiple tests instead of resetting inside a test.
+       Use testStart or testDone for custom cleanup.
+       This method will throw an error in 2.0, and will be removed in 2.1
+       */
</ins><span class="cx">   reset: function() {
</span><del>-               if ( window.jQuery ) {
-                       jQuery("#main, #qunit-fixture").html( config.fixture );
</del><ins>+                var fixture = id( "qunit-fixture" );
+               if ( fixture ) {
+                       fixture.innerHTML = config.fixture;
</ins><span class="cx">           }
</span><span class="cx">  },
</span><del>-       
-       /**
-        * Trigger an event on an element.
-        *
-        * @example triggerEvent( document.body, "click" );
-        *
-        * @param DOMElement elem
-        * @param String type
-        */
-       triggerEvent: function( elem, type, event ) {
-               if ( document.createEvent ) {
-                       event = document.createEvent("MouseEvents");
-                       event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
-                               0, 0, 0, 0, 0, false, false, false, false, 0, null);
-                       elem.dispatchEvent( event );
</del><span class="cx"> 
</span><del>-               } else if ( elem.fireEvent ) {
-                       elem.fireEvent("on"+type);
-               }
-       },
-       
</del><span class="cx">   // Safe object type checking
</span><span class="cx">  is: function( type, obj ) {
</span><del>-               return QUnit.objectType( obj ) == type;
</del><ins>+                return QUnit.objectType( obj ) === type;
</ins><span class="cx">   },
</span><del>-       
</del><ins>+
</ins><span class="cx">   objectType: function( obj ) {
</span><del>-               if (typeof obj === "undefined") {
-                               return "undefined";
</del><ins>+                if ( typeof obj === "undefined" ) {
+                       return "undefined";
+               }
</ins><span class="cx"> 
</span><del>-               // consider: typeof null === object
</del><ins>+                // Consider: typeof null === object
+               if ( obj === null ) {
+                       return "null";
</ins><span class="cx">           }
</span><del>-               if (obj === null) {
-                               return "null";
-               }
</del><span class="cx"> 
</span><del>-               var type = Object.prototype.toString.call( obj )
-                       .match(/^\[object\s(.*)\]$/)[1] || '';
</del><ins>+                var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
+                       type = match && match[1] || "";
</ins><span class="cx"> 
</span><del>-               switch (type) {
-                               case 'Number':
-                                               if (isNaN(obj)) {
-                                                               return "nan";
-                                               } else {
-                                                               return "number";
-                                               }
-                               case 'String':
-                               case 'Boolean':
-                               case 'Array':
-                               case 'Date':
-                               case 'RegExp':
-                               case 'Function':
-                                               return type.toLowerCase();
</del><ins>+                switch ( type ) {
+                       case "Number":
+                               if ( isNaN(obj) ) {
+                                       return "nan";
+                               }
+                               return "number";
+                       case "String":
+                       case "Boolean":
+                       case "Array":
+                       case "Date":
+                       case "RegExp":
+                       case "Function":
+                               return type.toLowerCase();
</ins><span class="cx">           }
</span><del>-               if (typeof obj === "object") {
-                               return "object";
</del><ins>+                if ( typeof obj === "object" ) {
+                       return "object";
</ins><span class="cx">           }
</span><span class="cx">          return undefined;
</span><span class="cx">  },
</span><del>-       
-       // Logging callbacks
-       begin: function() {},
-       done: function(failures, total) {},
-       log: function(result, message) {},
-       testStart: function(name, testEnvironment) {},
-       testDone: function(name, failures, total) {},
-       moduleStart: function(name, testEnvironment) {},
-       moduleDone: function(name, failures, total) {}
</del><ins>+
+       push: function( result, actual, expected, message ) {
+               if ( !config.current ) {
+                       throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
+               }
+
+               var output, source,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: result,
+                               message: message,
+                               actual: actual,
+                               expected: expected
+                       };
+
+               message = escapeText( message ) || ( result ? "okay" : "failed" );
+               message = "<span class='test-message'>" + message + "</span>";
+               output = message;
+
+               if ( !result ) {
+                       expected = escapeText( QUnit.jsDump.parse(expected) );
+                       actual = escapeText( QUnit.jsDump.parse(actual) );
+                       output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
+
+                       if ( actual !== expected ) {
+                               output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
+                               output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
+                       }
+
+                       source = sourceFromStacktrace();
+
+                       if ( source ) {
+                               details.source = source;
+                               output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+                       }
+
+                       output += "</table>";
+               }
+
+               runLoggingCallbacks( "log", QUnit, details );
+
+               config.current.assertions.push({
+                       result: !!result,
+                       message: output
+               });
+       },
+
+       pushFailure: function( message, source, actual ) {
+               if ( !config.current ) {
+                       throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
+               }
+
+               var output,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: false,
+                               message: message
+                       };
+
+               message = escapeText( message ) || "error";
+               message = "<span class='test-message'>" + message + "</span>";
+               output = message;
+
+               output += "<table>";
+
+               if ( actual ) {
+                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
+               }
+
+               if ( source ) {
+                       details.source = source;
+                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+               }
+
+               output += "</table>";
+
+               runLoggingCallbacks( "log", QUnit, details );
+
+               config.current.assertions.push({
+                       result: false,
+                       message: output
+               });
+       },
+
+       url: function( params ) {
+               params = extend( extend( {}, QUnit.urlParams ), params );
+               var key,
+                       querystring = "?";
+
+               for ( key in params ) {
+                       if ( hasOwn.call( params, key ) ) {
+                               querystring += encodeURIComponent( key ) + "=" +
+                                       encodeURIComponent( params[ key ] ) + "&";
+                       }
+               }
+               return window.location.protocol + "//" + window.location.host +
+                       window.location.pathname + querystring.slice( 0, -1 );
+       },
+
+       extend: extend,
+       id: id,
+       addEvent: addEvent,
+       addClass: addClass,
+       hasClass: hasClass,
+       removeClass: removeClass
+       // load, equiv, jsDump, diff: Attached later
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-if ( typeof document === "undefined" || document.readyState === "complete" ) {
</del><ins>+/**
+ * @deprecated: Created for backwards compatibility with test runner that set the hook function
+ * into QUnit.{hook}, instead of invoking it and passing the hook function.
+ * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
+ * Doing this allows us to tell if the following methods have been overwritten on the actual
+ * QUnit object.
+ */
+extend( QUnit.constructor.prototype, {
+
+       // Logging callbacks; all receive a single argument with the listed properties
+       // run test/logs.html for any related changes
+       begin: registerLoggingCallback( "begin" ),
+
+       // done: { failed, passed, total, runtime }
+       done: registerLoggingCallback( "done" ),
+
+       // log: { result, actual, expected, message }
+       log: registerLoggingCallback( "log" ),
+
+       // testStart: { name }
+       testStart: registerLoggingCallback( "testStart" ),
+
+       // testDone: { name, failed, passed, total, runtime }
+       testDone: registerLoggingCallback( "testDone" ),
+
+       // moduleStart: { name }
+       moduleStart: registerLoggingCallback( "moduleStart" ),
+
+       // moduleDone: { name, failed, passed, total }
+       moduleDone: registerLoggingCallback( "moduleDone" )
+});
+
+if ( !defined.document || document.readyState === "complete" ) {
</ins><span class="cx">   config.autorun = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-addEvent(window, "load", function() {
-       QUnit.begin();
-       
</del><ins>+QUnit.load = function() {
+       runLoggingCallbacks( "begin", QUnit, {} );
+
</ins><span class="cx">   // Initialize the config, saving the execution queue
</span><del>-       var oldconfig = extend({}, config);
</del><ins>+        var banner, filter, i, j, label, len, main, ol, toolbar, val, selection,
+               urlConfigContainer, moduleFilter, userAgent,
+               numModules = 0,
+               moduleNames = [],
+               moduleFilterHtml = "",
+               urlConfigHtml = "",
+               oldconfig = extend( {}, config );
+
</ins><span class="cx">   QUnit.init();
</span><span class="cx">  extend(config, oldconfig);
</span><span class="cx"> 
</span><span class="cx">  config.blocking = false;
</span><span class="cx"> 
</span><del>-       var userAgent = id("qunit-userAgent");
</del><ins>+        len = config.urlConfig.length;
+
+       for ( i = 0; i < len; i++ ) {
+               val = config.urlConfig[i];
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val
+                       };
+               }
+               config[ val.id ] = QUnit.urlParams[ val.id ];
+               if ( !val.value || typeof val.value === "string" ) {
+                       urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
+                               "' name='" + escapeText( val.id ) +
+                               "' type='checkbox'" +
+                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
+                               ( config[ val.id ] ? " checked='checked'" : "" ) +
+                               " title='" + escapeText( val.tooltip ) +
+                               "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
+                               "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
+               } else {
+                       urlConfigHtml += "<label for='qunit-urlconfig-" + escapeText( val.id ) +
+                               "' title='" + escapeText( val.tooltip ) +
+                               "'>" + val.label +
+                               ": </label><select id='qunit-urlconfig-" + escapeText( val.id ) +
+                               "' name='" + escapeText( val.id ) +
+                               "' title='" + escapeText( val.tooltip ) +
+                               "'><option></option>";
+                       selection = false;
+                       if ( QUnit.is( "array", val.value ) ) {
+                               for ( j = 0; j < val.value.length; j++ ) {
+                                       urlConfigHtml += "<option value='" + escapeText( val.value[j] ) + "'" +
+                                               ( config[ val.id ] === val.value[j] ?
+                                                       (selection = true) && " selected='selected'" :
+                                                       "" ) +
+                                               ">" + escapeText( val.value[j] ) + "</option>";
+                               }
+                       } else {
+                               for ( j in val.value ) {
+                                       if ( hasOwn.call( val.value, j ) ) {
+                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
+                                                       ( config[ val.id ] === j ?
+                                                               (selection = true) && " selected='selected'" :
+                                                               "" ) +
+                                                       ">" + escapeText( val.value[j] ) + "</option>";
+                                       }
+                               }
+                       }
+                       if ( config[ val.id ] && !selection ) {
+                               urlConfigHtml += "<option value='" + escapeText( config[ val.id ] ) +
+                                       "' selected='selected' disabled='disabled'>" +
+                                       escapeText( config[ val.id ] ) +
+                                       "</option>";
+                       }
+                       urlConfigHtml += "</select>";
+               }
+       }
+       for ( i in config.modules ) {
+               if ( config.modules.hasOwnProperty( i ) ) {
+                       moduleNames.push(i);
+               }
+       }
+       numModules = moduleNames.length;
+       moduleNames.sort( function( a, b ) {
+               return a.localeCompare( b );
+       });
+       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+               ( config.module === undefined  ? "selected='selected'" : "" ) +
+               ">< All Modules ></option>";
+
+
+       for ( i = 0; i < numModules; i++) {
+                       moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(moduleNames[i]) ) + "' " +
+                               ( config.module === moduleNames[i] ? "selected='selected'" : "" ) +
+                               ">" + escapeText(moduleNames[i]) + "</option>";
+       }
+       moduleFilterHtml += "</select>";
+
+       // `userAgent` initialized at top of scope
+       userAgent = id( "qunit-userAgent" );
</ins><span class="cx">   if ( userAgent ) {
</span><span class="cx">          userAgent.innerHTML = navigator.userAgent;
</span><span class="cx">  }
</span><del>-       
-       var toolbar = id("qunit-testrunner-toolbar");
</del><ins>+
+       // `banner` initialized at top of scope
+       banner = id( "qunit-header" );
+       if ( banner ) {
+               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
+       }
+
+       // `toolbar` initialized at top of scope
+       toolbar = id( "qunit-testrunner-toolbar" );
</ins><span class="cx">   if ( toolbar ) {
</span><del>-               toolbar.style.display = "none";
-               
-               var filter = document.createElement("input");
</del><ins>+                // `filter` initialized at top of scope
+               filter = document.createElement( "input" );
</ins><span class="cx">           filter.type = "checkbox";
</span><span class="cx">          filter.id = "qunit-filter-pass";
</span><del>-               filter.disabled = true;
</del><ins>+
</ins><span class="cx">           addEvent( filter, "click", function() {
</span><del>-                       var li = document.getElementsByTagName("li");
-                       for ( var i = 0; i < li.length; i++ ) {
-                               if ( li[i].className.indexOf("pass") > -1 ) {
-                                       li[i].style.display = filter.checked ? "none" : "";
</del><ins>+                        var tmp,
+                               ol = id( "qunit-tests" );
+
+                       if ( filter.checked ) {
+                               ol.className = ol.className + " hidepass";
+                       } else {
+                               tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
+                               ol.className = tmp.replace( / hidepass /, " " );
+                       }
+                       if ( defined.sessionStorage ) {
+                               if (filter.checked) {
+                                       sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
+                               } else {
+                                       sessionStorage.removeItem( "qunit-filter-passed-tests" );
</ins><span class="cx">                           }
</span><span class="cx">                  }
</span><span class="cx">          });
</span><ins>+
+               if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
+                       filter.checked = true;
+                       // `ol` initialized at top of scope
+                       ol = id( "qunit-tests" );
+                       ol.className = ol.className + " hidepass";
+               }
</ins><span class="cx">           toolbar.appendChild( filter );
</span><span class="cx"> 
</span><del>-               var label = document.createElement("label");
-               label.setAttribute("for", "qunit-filter-pass");
</del><ins>+                // `label` initialized at top of scope
+               label = document.createElement( "label" );
+               label.setAttribute( "for", "qunit-filter-pass" );
+               label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." );
</ins><span class="cx">           label.innerHTML = "Hide passed tests";
</span><span class="cx">          toolbar.appendChild( label );
</span><span class="cx"> 
</span><del>-               var missing = document.createElement("input");
-               missing.type = "checkbox";
-               missing.id = "qunit-filter-missing";
-               missing.disabled = true;
-               addEvent( missing, "click", function() {
-                       var li = document.getElementsByTagName("li");
-                       for ( var i = 0; i < li.length; i++ ) {
-                               if ( li[i].className.indexOf("fail") > -1 && li[i].innerHTML.indexOf('missing test - untested code is broken code') > - 1 ) {
-                                       li[i].parentNode.parentNode.style.display = missing.checked ? "none" : "block";
-                               }
-                       }
</del><ins>+                urlConfigContainer = document.createElement("span");
+               urlConfigContainer.innerHTML = urlConfigHtml;
+               // For oldIE support:
+               // * Add handlers to the individual elements instead of the container
+               // * Use "click" instead of "change" for checkboxes
+               // * Fallback from event.target to event.srcElement
+               addEvents( urlConfigContainer.getElementsByTagName("input"), "click", function( event ) {
+                       var params = {},
+                               target = event.target || event.srcElement;
+                       params[ target.name ] = target.checked ?
+                               target.defaultValue || true :
+                               undefined;
+                       window.location = QUnit.url( params );
</ins><span class="cx">           });
</span><del>-               toolbar.appendChild( missing );
</del><ins>+                addEvents( urlConfigContainer.getElementsByTagName("select"), "change", function( event ) {
+                       var params = {},
+                               target = event.target || event.srcElement;
+                       params[ target.name ] = target.options[ target.selectedIndex ].value || undefined;
+                       window.location = QUnit.url( params );
+               });
+               toolbar.appendChild( urlConfigContainer );
</ins><span class="cx"> 
</span><del>-               label = document.createElement("label");
-               label.setAttribute("for", "qunit-filter-missing");
-               label.innerHTML = "Hide missing tests (untested code is broken code)";
-               toolbar.appendChild( label );
</del><ins>+                if (numModules > 1) {
+                       moduleFilter = document.createElement( "span" );
+                       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
+                       moduleFilter.innerHTML = moduleFilterHtml;
+                       addEvent( moduleFilter.lastChild, "change", function() {
+                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
+                                       selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
+
+                               window.location = QUnit.url({
+                                       module: ( selectedModule === "" ) ? undefined : selectedModule,
+                                       // Remove any existing filters
+                                       filter: undefined,
+                                       testNumber: undefined
+                               });
+                       });
+                       toolbar.appendChild(moduleFilter);
+               }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       var main = id('main') || id('qunit-fixture');
</del><ins>+        // `main` initialized at top of scope
+       main = id( "qunit-fixture" );
</ins><span class="cx">   if ( main ) {
</span><span class="cx">          config.fixture = main.innerHTML;
</span><span class="cx">  }
</span><span class="cx"> 
</span><del>-       if (config.autostart) {
</del><ins>+        if ( config.autostart ) {
</ins><span class="cx">           QUnit.start();
</span><span class="cx">  }
</span><del>-});
</del><ins>+};
</ins><span class="cx"> 
</span><del>-function done() {
-       if ( config.doneTimer && window.clearTimeout ) {
-               window.clearTimeout( config.doneTimer );
-               config.doneTimer = null;
</del><ins>+if ( defined.document ) {
+       addEvent( window, "load", QUnit.load );
+}
+
+// `onErrorFnPrev` initialized at top of scope
+// Preserve other handlers
+onErrorFnPrev = window.onerror;
+
+// Cover uncaught exceptions
+// Returning true will suppress the default browser handler,
+// returning false will let it run.
+window.onerror = function ( error, filePath, linerNr ) {
+       var ret = false;
+       if ( onErrorFnPrev ) {
+               ret = onErrorFnPrev( error, filePath, linerNr );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       if ( config.queue.length ) {
-               config.doneTimer = window.setTimeout(function(){
-                       if ( !config.queue.length ) {
-                               done();
-                       } else {
-                               synchronize( done );
</del><ins>+        // Treat return value as window.onerror itself does,
+       // Only do our handling if not suppressed.
+       if ( ret !== true ) {
+               if ( QUnit.config.current ) {
+                       if ( QUnit.config.current.ignoreGlobalErrors ) {
+                               return true;
</ins><span class="cx">                   }
</span><del>-               }, 13);
-
-               return;
</del><ins>+                        QUnit.pushFailure( error, filePath + ":" + linerNr );
+               } else {
+                       QUnit.test( "global failure", extend( function() {
+                               QUnit.pushFailure( error, filePath + ":" + linerNr );
+                       }, { validTest: validTest } ) );
+               }
+               return false;
</ins><span class="cx">   }
</span><span class="cx"> 
</span><ins>+       return ret;
+};
+
+function done() {
</ins><span class="cx">   config.autorun = true;
</span><span class="cx"> 
</span><span class="cx">  // Log the last module results
</span><del>-       if ( config.currentModule ) {
-               QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
</del><ins>+        if ( config.previousModule ) {
+               runLoggingCallbacks( "moduleDone", QUnit, {
+                       name: config.previousModule,
+                       failed: config.moduleStats.bad,
+                       passed: config.moduleStats.all - config.moduleStats.bad,
+                       total: config.moduleStats.all
+               });
</ins><span class="cx">   }
</span><ins>+       delete config.previousModule;
</ins><span class="cx"> 
</span><del>-       var banner = id("qunit-banner"),
-               tests = id("qunit-tests"),
-               html = ['Tests completed in ',
-               +new Date - config.started, ' milliseconds.<br/>',
-               '<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
</del><ins>+        var i, key,
+               banner = id( "qunit-banner" ),
+               tests = id( "qunit-tests" ),
+               runtime = +new Date() - config.started,
+               passed = config.stats.all - config.stats.bad,
+               html = [
+                       "Tests completed in ",
+                       runtime,
+                       " milliseconds.<br/>",
+                       "<span class='passed'>",
+                       passed,
+                       "</span> assertions of <span class='total'>",
+                       config.stats.all,
+                       "</span> passed, <span class='failed'>",
+                       config.stats.bad,
+                       "</span> failed."
+               ].join( "" );
</ins><span class="cx"> 
</span><span class="cx">  if ( banner ) {
</span><del>-               banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
</del><ins>+                banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       if ( tests ) {  
-               var result = id("qunit-testresult");
</del><ins>+        if ( tests ) {
+               id( "qunit-testresult" ).innerHTML = html;
+       }
</ins><span class="cx"> 
</span><del>-               if ( !result ) {
-                       result = document.createElement("p");
-                       result.id = "qunit-testresult";
-                       result.className = "result";
-                       tests.parentNode.insertBefore( result, tests.nextSibling );
</del><ins>+        if ( config.altertitle && defined.document && document.title ) {
+               // show âœ– for good, âœ” for bad suite result in title
+               // use escape sequences in case file gets loaded with non-utf-8-charset
+               document.title = [
+                       ( config.stats.bad ? "\u2716" : "\u2714" ),
+                       document.title.replace( /^[\u2714\u2716] /i, "" )
+               ].join( " " );
+       }
+
+       // clear own sessionStorage items if all tests passed
+       if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
+               // `key` & `i` initialized at top of scope
+               for ( i = 0; i < sessionStorage.length; i++ ) {
+                       key = sessionStorage.key( i++ );
+                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
+                               sessionStorage.removeItem( key );
+                       }
</ins><span class="cx">           }
</span><ins>+       }
</ins><span class="cx"> 
</span><del>-               result.innerHTML = html;
</del><ins>+        // scroll back to top to show results
+       if ( config.scrolltop && window.scrollTo ) {
+               window.scrollTo(0, 0);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       QUnit.done( config.stats.bad, config.stats.all );
</del><ins>+        runLoggingCallbacks( "done", QUnit, {
+               failed: config.stats.bad,
+               passed: passed,
+               total: config.stats.all,
+               runtime: runtime
+       });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-function validTest( name ) {
-       var i = config.filters.length,
-               run = false;
</del><ins>+/** @return Boolean: true if this test should be ran */
+function validTest( test ) {
+       var include,
+               filter = config.filter && config.filter.toLowerCase(),
+               module = config.module && config.module.toLowerCase(),
+               fullName = ( test.module + ": " + test.testName ).toLowerCase();
</ins><span class="cx"> 
</span><del>-       if ( !i ) {
</del><ins>+        // Internally-generated tests are always valid
+       if ( test.callback && test.callback.validTest === validTest ) {
+               delete test.callback.validTest;
</ins><span class="cx">           return true;
</span><span class="cx">  }
</span><del>-       
-       while ( i-- ) {
-               var filter = config.filters[i],
-                       not = filter.charAt(0) == '!';
</del><span class="cx"> 
</span><del>-               if ( not ) {
-                       filter = filter.slice(1);
</del><ins>+        if ( config.testNumber.length > 0 ) {
+               if ( inArray( test.testNumber, config.testNumber ) < 0 ) {
+                       return false;
</ins><span class="cx">           }
</span><ins>+       }
</ins><span class="cx"> 
</span><del>-               if ( name.indexOf(filter) !== -1 ) {
-                       return !not;
-               }
</del><ins>+        if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
+               return false;
+       }
</ins><span class="cx"> 
</span><del>-               if ( not ) {
-                       run = true;
-               }
</del><ins>+        if ( !filter ) {
+               return true;
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       return run;
</del><ins>+        include = filter.charAt( 0 ) !== "!";
+       if ( !include ) {
+               filter = filter.slice( 1 );
+       }
+
+       // If the filter matches, we need to honour include
+       if ( fullName.indexOf( filter ) !== -1 ) {
+               return include;
+       }
+
+       // Otherwise, do the opposite
+       return !include;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-function escapeHtml(s) {
-       s = s === null ? "" : s + "";
-       return s.replace(/[\&"<>\\]/g, function(s) {
-               switch(s) {
-                       case "&": return "&amp;";
-                       case "\\": return "\\\\";
-                       case '"': return '\"';
-                       case "<": return "&lt;";
-                       case ">": return "&gt;";
-                       default: return s;
</del><ins>+// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
+// Later Safari and IE10 are supposed to support error.stack as well
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+       offset = offset === undefined ? 3 : offset;
+
+       var stack, include, i;
+
+       if ( e.stacktrace ) {
+               // Opera
+               return e.stacktrace.split( "\n" )[ offset + 3 ];
+       } else if ( e.stack ) {
+               // Firefox, Chrome
+               stack = e.stack.split( "\n" );
+               if (/^error$/i.test( stack[0] ) ) {
+                       stack.shift();
</ins><span class="cx">           }
</span><del>-       });
</del><ins>+                if ( fileName ) {
+                       include = [];
+                       for ( i = offset; i < stack.length; i++ ) {
+                               if ( stack[ i ].indexOf( fileName ) !== -1 ) {
+                                       break;
+                               }
+                               include.push( stack[ i ] );
+                       }
+                       if ( include.length ) {
+                               return include.join( "\n" );
+                       }
+               }
+               return stack[ offset ];
+       } else if ( e.sourceURL ) {
+               // Safari, PhantomJS
+               // hopefully one day Safari provides actual stacktraces
+               // exclude useless self-reference for generated Error objects
+               if ( /qunit.js$/.test( e.sourceURL ) ) {
+                       return;
+               }
+               // for actual exceptions, this is useful
+               return e.sourceURL + ":" + e.line;
+       }
</ins><span class="cx"> }
</span><ins>+function sourceFromStacktrace( offset ) {
+       try {
+               throw new Error();
+       } catch ( e ) {
+               return extractStacktrace( e, offset );
+       }
+}
</ins><span class="cx"> 
</span><del>-function push(result, actual, expected, message) {
-       message = escapeHtml(message) || (result ? "okay" : "failed");
-       message = '<span class="test-message">' + message + "</span>";
-       expected = escapeHtml(QUnit.jsDump.parse(expected));
-       actual = escapeHtml(QUnit.jsDump.parse(actual));
-       var output = message + ', expected: <span class="test-expected">' + expected + '</span>';
-       if (actual != expected) {
-               output += ' result: <span class="test-actual">' + actual + '</span>, diff: ' + QUnit.diff(expected, actual);
</del><ins>+/**
+ * Escape text for attribute or text content.
+ */
+function escapeText( s ) {
+       if ( !s ) {
+               return "";
</ins><span class="cx">   }
</span><del>-       
-       // can't use ok, as that would double-escape messages
-       QUnit.log(result, output);
-       config.assertions.push({
-               result: !!result,
-               message: output
</del><ins>+        s = s + "";
+       // Both single quotes and double quotes (for attributes)
+       return s.replace( /['"<>&]/g, function( s ) {
+               switch( s ) {
+                       case "'":
+                               return "&#039;";
+                       case "\"":
+                               return "&quot;";
+                       case "<":
+                               return "&lt;";
+                       case ">":
+                               return "&gt;";
+                       case "&":
+                               return "&amp;";
+               }
</ins><span class="cx">   });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function synchronize( callback ) {
</del><ins>+function synchronize( callback, last ) {
</ins><span class="cx">   config.queue.push( callback );
</span><span class="cx"> 
</span><span class="cx">  if ( config.autorun && !config.blocking ) {
</span><del>-               process();
</del><ins>+                process( last );
</ins><span class="cx">   }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function process() {
-       var start = (new Date()).getTime();
</del><ins>+function process( last ) {
+       function next() {
+               process( last );
+       }
+       var start = new Date().getTime();
+       config.depth = config.depth ? config.depth + 1 : 1;
</ins><span class="cx"> 
</span><span class="cx">  while ( config.queue.length && !config.blocking ) {
</span><del>-               if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
</del><ins>+                if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
</ins><span class="cx">                   config.queue.shift()();
</span><del>-
</del><span class="cx">           } else {
</span><del>-                       setTimeout( process, 13 );
</del><ins>+                        setTimeout( next, 13 );
</ins><span class="cx">                   break;
</span><span class="cx">          }
</span><span class="cx">  }
</span><ins>+       config.depth--;
+       if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
+               done();
+       }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function saveGlobal() {
</span><span class="cx">  config.pollution = [];
</span><del>-       
</del><ins>+
</ins><span class="cx">   if ( config.noglobals ) {
</span><span class="cx">          for ( var key in window ) {
</span><del>-                       config.pollution.push( key );
</del><ins>+                        if ( hasOwn.call( window, key ) ) {
+                               // in Opera sometimes DOM element ids show up here, ignore them
+                               if ( /^qunit-test-output/.test( key ) ) {
+                                       continue;
+                               }
+                               config.pollution.push( key );
+                       }
</ins><span class="cx">           }
</span><span class="cx">  }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function checkPollution( name ) {
-       var old = config.pollution;
</del><ins>+function checkPollution() {
+       var newGlobals,
+               deletedGlobals,
+               old = config.pollution;
+
</ins><span class="cx">   saveGlobal();
</span><del>-       
-       var newGlobals = diff( old, config.pollution );
</del><ins>+
+       newGlobals = diff( config.pollution, old );
</ins><span class="cx">   if ( newGlobals.length > 0 ) {
</span><del>-               ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
-               config.expected++;
</del><ins>+                QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       var deletedGlobals = diff( config.pollution, old );
</del><ins>+        deletedGlobals = diff( old, config.pollution );
</ins><span class="cx">   if ( deletedGlobals.length > 0 ) {
</span><del>-               ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
-               config.expected++;
</del><ins>+                QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
</ins><span class="cx">   }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // returns a new Array with the elements that are in a but not in b
</span><span class="cx"> function diff( a, b ) {
</span><del>-       var result = a.slice();
-       for ( var i = 0; i < result.length; i++ ) {
-               for ( var j = 0; j < b.length; j++ ) {
</del><ins>+        var i, j,
+               result = a.slice();
+
+       for ( i = 0; i < result.length; i++ ) {
+               for ( j = 0; j < b.length; j++ ) {
</ins><span class="cx">                   if ( result[i] === b[j] ) {
</span><del>-                               result.splice(i, 1);
</del><ins>+                                result.splice( i, 1 );
</ins><span class="cx">                           i--;
</span><span class="cx">                          break;
</span><span class="cx">                  }
</span><span class="lines">@@ -734,210 +1076,826 @@
</span><span class="cx">  return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function fail(message, exception, callback) {
-       if ( typeof console !== "undefined" && console.error && console.warn ) {
-               console.error(message);
-               console.error(exception);
-               console.warn(callback.toString());
-
-       } else if ( window.opera && opera.postError ) {
-               opera.postError(message, exception, callback.toString);
-       }
-}
-
-function extend(a, b) {
</del><ins>+function extend( a, b ) {
</ins><span class="cx">   for ( var prop in b ) {
</span><del>-               a[prop] = b[prop];
</del><ins>+                if ( hasOwn.call( b, prop ) ) {
+                       // Avoid "Member not found" error in IE8 caused by messing with window.constructor
+                       if ( !( prop === "constructor" && a === window ) ) {
+                               if ( b[ prop ] === undefined ) {
+                                       delete a[ prop ];
+                               } else {
+                                       a[ prop ] = b[ prop ];
+                               }
+                       }
+               }
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">  return a;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function addEvent(elem, type, fn) {
</del><ins>+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
</ins><span class="cx">   if ( elem.addEventListener ) {
</span><ins>+
+               // Standards-based browsers
</ins><span class="cx">           elem.addEventListener( type, fn, false );
</span><span class="cx">  } else if ( elem.attachEvent ) {
</span><ins>+
+               // support: IE <9
</ins><span class="cx">           elem.attachEvent( "on" + type, fn );
</span><span class="cx">  } else {
</span><del>-               fn();
</del><ins>+
+               // Caller must ensure support for event listeners is present
+               throw new Error( "addEvent() was called in a context without event listener support" );
</ins><span class="cx">   }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-function id(name) {
-       return !!(typeof document !== "undefined" && document && document.getElementById) &&
-               document.getElementById( name );
</del><ins>+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+       var i = elems.length;
+       while ( i-- ) {
+               addEvent( elems[i], type, fn );
+       }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function hasClass( elem, name ) {
+       return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
+}
+
+function addClass( elem, name ) {
+       if ( !hasClass( elem, name ) ) {
+               elem.className += (elem.className ? " " : "") + name;
+       }
+}
+
+function removeClass( elem, name ) {
+       var set = " " + elem.className + " ";
+       // Class name may appear multiple times
+       while ( set.indexOf(" " + name + " ") > -1 ) {
+               set = set.replace(" " + name + " " , " ");
+       }
+       // If possible, trim it for prettiness, but not necessarily
+       elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, "");
+}
+
+function id( name ) {
+       return defined.document && document.getElementById && document.getElementById( name );
+}
+
+function registerLoggingCallback( key ) {
+       return function( callback ) {
+               config[key].push( callback );
+       };
+}
+
+// Supports deprecated method of completely overwriting logging callbacks
+function runLoggingCallbacks( key, scope, args ) {
+       var i, callbacks;
+       if ( QUnit.hasOwnProperty( key ) ) {
+               QUnit[ key ].call(scope, args );
+       } else {
+               callbacks = config[ key ];
+               for ( i = 0; i < callbacks.length; i++ ) {
+                       callbacks[ i ].call( scope, args );
+               }
+       }
+}
+
+// from jquery.js
+function inArray( elem, array ) {
+       if ( array.indexOf ) {
+               return array.indexOf( elem );
+       }
+
+       for ( var i = 0, length = array.length; i < length; i++ ) {
+               if ( array[ i ] === elem ) {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+function Test( settings ) {
+       extend( this, settings );
+       this.assertions = [];
+       this.testNumber = ++Test.count;
+}
+
+Test.count = 0;
+
+Test.prototype = {
+       init: function() {
+               var a, b, li,
+                       tests = id( "qunit-tests" );
+
+               if ( tests ) {
+                       b = document.createElement( "strong" );
+                       b.innerHTML = this.nameHtml;
+
+                       // `a` initialized at top of scope
+                       a = document.createElement( "a" );
+                       a.innerHTML = "Rerun";
+                       a.href = QUnit.url({ testNumber: this.testNumber });
+
+                       li = document.createElement( "li" );
+                       li.appendChild( b );
+                       li.appendChild( a );
+                       li.className = "running";
+                       li.id = this.id = "qunit-test-output" + testId++;
+
+                       tests.appendChild( li );
+               }
+       },
+       setup: function() {
+               if (
+                       // Emit moduleStart when we're switching from one module to another
+                       this.module !== config.previousModule ||
+                               // They could be equal (both undefined) but if the previousModule property doesn't
+                               // yet exist it means this is the first test in a suite that isn't wrapped in a
+                               // module, in which case we'll just emit a moduleStart event for 'undefined'.
+                               // Without this, reporters can get testStart before moduleStart  which is a problem.
+                               !hasOwn.call( config, "previousModule" )
+               ) {
+                       if ( hasOwn.call( config, "previousModule" ) ) {
+                               runLoggingCallbacks( "moduleDone", QUnit, {
+                                       name: config.previousModule,
+                                       failed: config.moduleStats.bad,
+                                       passed: config.moduleStats.all - config.moduleStats.bad,
+                                       total: config.moduleStats.all
+                               });
+                       }
+                       config.previousModule = this.module;
+                       config.moduleStats = { all: 0, bad: 0 };
+                       runLoggingCallbacks( "moduleStart", QUnit, {
+                               name: this.module
+                       });
+               }
+
+               config.current = this;
+
+               this.testEnvironment = extend({
+                       setup: function() {},
+                       teardown: function() {}
+               }, this.moduleTestEnvironment );
+
+               this.started = +new Date();
+               runLoggingCallbacks( "testStart", QUnit, {
+                       name: this.testName,
+                       module: this.module
+               });
+
+               /*jshint camelcase:false */
+
+
+               /**
+                * Expose the current test environment.
+                *
+                * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.
+                */
+               QUnit.current_testEnvironment = this.testEnvironment;
+
+               /*jshint camelcase:true */
+
+               if ( !config.pollution ) {
+                       saveGlobal();
+               }
+               if ( config.notrycatch ) {
+                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
+                       return;
+               }
+               try {
+                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
+               } catch( e ) {
+                       QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+               }
+       },
+       run: function() {
+               config.current = this;
+
+               var running = id( "qunit-testresult" );
+
+               if ( running ) {
+                       running.innerHTML = "Running: <br/>" + this.nameHtml;
+               }
+
+               if ( this.async ) {
+                       QUnit.stop();
+               }
+
+               this.callbackStarted = +new Date();
+
+               if ( config.notrycatch ) {
+                       this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+                       return;
+               }
+
+               try {
+                       this.callback.call( this.testEnvironment, QUnit.assert );
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+               } catch( e ) {
+                       this.callbackRuntime = +new Date() - this.callbackStarted;
+
+                       QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
+                       // else next test will carry the responsibility
+                       saveGlobal();
+
+                       // Restart the tests if they're blocking
+                       if ( config.blocking ) {
+                               QUnit.start();
+                       }
+               }
+       },
+       teardown: function() {
+               config.current = this;
+               if ( config.notrycatch ) {
+                       if ( typeof this.callbackRuntime === "undefined" ) {
+                               this.callbackRuntime = +new Date() - this.callbackStarted;
+                       }
+                       this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
+                       return;
+               } else {
+                       try {
+                               this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
+                       } catch( e ) {
+                               QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+                       }
+               }
+               checkPollution();
+       },
+       finish: function() {
+               config.current = this;
+               if ( config.requireExpects && this.expected === null ) {
+                       QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
+               } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
+                       QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
+               } else if ( this.expected === null && !this.assertions.length ) {
+                       QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
+               }
+
+               var i, assertion, a, b, time, li, ol,
+                       test = this,
+                       good = 0,
+                       bad = 0,
+                       tests = id( "qunit-tests" );
+
+               this.runtime = +new Date() - this.started;
+               config.stats.all += this.assertions.length;
+               config.moduleStats.all += this.assertions.length;
+
+               if ( tests ) {
+                       ol = document.createElement( "ol" );
+                       ol.className = "qunit-assert-list";
+
+                       for ( i = 0; i < this.assertions.length; i++ ) {
+                               assertion = this.assertions[i];
+
+                               li = document.createElement( "li" );
+                               li.className = assertion.result ? "pass" : "fail";
+                               li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
+                               ol.appendChild( li );
+
+                               if ( assertion.result ) {
+                                       good++;
+                               } else {
+                                       bad++;
+                                       config.stats.bad++;
+                                       config.moduleStats.bad++;
+                               }
+                       }
+
+                       // store result when possible
+                       if ( QUnit.config.reorder && defined.sessionStorage ) {
+                               if ( bad ) {
+                                       sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
+                               } else {
+                                       sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
+                               }
+                       }
+
+                       if ( bad === 0 ) {
+                               addClass( ol, "qunit-collapsed" );
+                       }
+
+                       // `b` initialized at top of scope
+                       b = document.createElement( "strong" );
+                       b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
+
+                       addEvent(b, "click", function() {
+                               var next = b.parentNode.lastChild,
+                                       collapsed = hasClass( next, "qunit-collapsed" );
+                               ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
+                       });
+
+                       addEvent(b, "dblclick", function( e ) {
+                               var target = e && e.target ? e.target : window.event.srcElement;
+                               if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
+                                       target = target.parentNode;
+                               }
+                               if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
+                                       window.location = QUnit.url({ testNumber: test.testNumber });
+                               }
+                       });
+
+                       // `time` initialized at top of scope
+                       time = document.createElement( "span" );
+                       time.className = "runtime";
+                       time.innerHTML = this.runtime + " ms";
+
+                       // `li` initialized at top of scope
+                       li = id( this.id );
+                       li.className = bad ? "fail" : "pass";
+                       li.removeChild( li.firstChild );
+                       a = li.firstChild;
+                       li.appendChild( b );
+                       li.appendChild( a );
+                       li.appendChild( time );
+                       li.appendChild( ol );
+
+               } else {
+                       for ( i = 0; i < this.assertions.length; i++ ) {
+                               if ( !this.assertions[i].result ) {
+                                       bad++;
+                                       config.stats.bad++;
+                                       config.moduleStats.bad++;
+                               }
+                       }
+               }
+
+               runLoggingCallbacks( "testDone", QUnit, {
+                       name: this.testName,
+                       module: this.module,
+                       failed: bad,
+                       passed: this.assertions.length - bad,
+                       total: this.assertions.length,
+                       runtime: this.runtime,
+                       // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
+                       duration: this.runtime
+               });
+
+               QUnit.reset();
+
+               config.current = undefined;
+       },
+
+       queue: function() {
+               var bad,
+                       test = this;
+
+               synchronize(function() {
+                       test.init();
+               });
+               function run() {
+                       // each of these can by async
+                       synchronize(function() {
+                               test.setup();
+                       });
+                       synchronize(function() {
+                               test.run();
+                       });
+                       synchronize(function() {
+                               test.teardown();
+                       });
+                       synchronize(function() {
+                               test.finish();
+                       });
+               }
+
+               // `bad` initialized at top of scope
+               // defer when previous test run passed, if storage is available
+               bad = QUnit.config.reorder && defined.sessionStorage &&
+                                               +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
+
+               if ( bad ) {
+                       run();
+               } else {
+                       synchronize( run, true );
+               }
+       }
+};
+
+// `assert` initialized at top of scope
+// Assert helpers
+// All of these must either call QUnit.push() or manually do:
+// - runLoggingCallbacks( "log", .. );
+// - config.current.assertions.push({ .. });
+assert = QUnit.assert = {
+       /**
+        * Asserts rough true-ish result.
+        * @name ok
+        * @function
+        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
+        */
+       ok: function( result, msg ) {
+               if ( !config.current ) {
+                       throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
+               }
+               result = !!result;
+               msg = msg || ( result ? "okay" : "failed" );
+
+               var source,
+                       details = {
+                               module: config.current.module,
+                               name: config.current.testName,
+                               result: result,
+                               message: msg
+                       };
+
+               msg = "<span class='test-message'>" + escapeText( msg ) + "</span>";
+
+               if ( !result ) {
+                       source = sourceFromStacktrace( 2 );
+                       if ( source ) {
+                               details.source = source;
+                               msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" +
+                                       escapeText( source ) +
+                                       "</pre></td></tr></table>";
+                       }
+               }
+               runLoggingCallbacks( "log", QUnit, details );
+               config.current.assertions.push({
+                       result: result,
+                       message: msg
+               });
+       },
+
+       /**
+        * Assert that the first two arguments are equal, with an optional message.
+        * Prints out both actual and expected values.
+        * @name equal
+        * @function
+        * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
+        */
+       equal: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               QUnit.push( expected == actual, actual, expected, message );
+       },
+
+       /**
+        * @name notEqual
+        * @function
+        */
+       notEqual: function( actual, expected, message ) {
+               /*jshint eqeqeq:false */
+               QUnit.push( expected != actual, actual, expected, message );
+       },
+
+       /**
+        * @name propEqual
+        * @function
+        */
+       propEqual: function( actual, expected, message ) {
+               actual = objectValues(actual);
+               expected = objectValues(expected);
+               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name notPropEqual
+        * @function
+        */
+       notPropEqual: function( actual, expected, message ) {
+               actual = objectValues(actual);
+               expected = objectValues(expected);
+               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name deepEqual
+        * @function
+        */
+       deepEqual: function( actual, expected, message ) {
+               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name notDeepEqual
+        * @function
+        */
+       notDeepEqual: function( actual, expected, message ) {
+               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+       },
+
+       /**
+        * @name strictEqual
+        * @function
+        */
+       strictEqual: function( actual, expected, message ) {
+               QUnit.push( expected === actual, actual, expected, message );
+       },
+
+       /**
+        * @name notStrictEqual
+        * @function
+        */
+       notStrictEqual: function( actual, expected, message ) {
+               QUnit.push( expected !== actual, actual, expected, message );
+       },
+
+       "throws": function( block, expected, message ) {
+               var actual,
+                       expectedOutput = expected,
+                       ok = false;
+
+               // 'expected' is optional
+               if ( !message && typeof expected === "string" ) {
+                       message = expected;
+                       expected = null;
+               }
+
+               config.current.ignoreGlobalErrors = true;
+               try {
+                       block.call( config.current.testEnvironment );
+               } catch (e) {
+                       actual = e;
+               }
+               config.current.ignoreGlobalErrors = false;
+
+               if ( actual ) {
+
+                       // we don't want to validate thrown error
+                       if ( !expected ) {
+                               ok = true;
+                               expectedOutput = null;
+
+                       // expected is an Error object
+                       } else if ( expected instanceof Error ) {
+                               ok = actual instanceof Error &&
+                                        actual.name === expected.name &&
+                                        actual.message === expected.message;
+
+                       // expected is a regexp
+                       } else if ( QUnit.objectType( expected ) === "regexp" ) {
+                               ok = expected.test( errorString( actual ) );
+
+                       // expected is a string
+                       } else if ( QUnit.objectType( expected ) === "string" ) {
+                               ok = expected === errorString( actual );
+
+                       // expected is a constructor
+                       } else if ( actual instanceof expected ) {
+                               ok = true;
+
+                       // expected is a validation function which returns true is validation passed
+                       } else if ( expected.call( {}, actual ) === true ) {
+                               expectedOutput = null;
+                               ok = true;
+                       }
+
+                       QUnit.push( ok, actual, expectedOutput, message );
+               } else {
+                       QUnit.pushFailure( message, null, "No exception was thrown." );
+               }
+       }
+};
+
+/**
+ * @deprecated since 1.8.0
+ * Kept assertion helpers in root for backwards compatibility.
+ */
+extend( QUnit.constructor.prototype, assert );
+
+/**
+ * @deprecated since 1.9.0
+ * Kept to avoid TypeErrors for undefined methods.
+ */
+QUnit.constructor.prototype.raises = function() {
+       QUnit.push( false, false, false, "QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead" );
+};
+
+/**
+ * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
+ * Kept to avoid TypeErrors for undefined methods.
+ */
+QUnit.constructor.prototype.equals = function() {
+       QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
+};
+QUnit.constructor.prototype.same = function() {
+       QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
+};
+
</ins><span class="cx"> // Test for equality any JavaScript type.
</span><del>-// Discussions and reference: http://philrathe.com/articles/equiv
-// Test suites: http://philrathe.com/tests/equiv
</del><span class="cx"> // Author: Philippe Rathé <prathe@gmail.com>
</span><del>-QUnit.equiv = function () {
</del><ins>+QUnit.equiv = (function() {
</ins><span class="cx"> 
</span><del>-    var innerEquiv; // the real equiv function
-    var callers = []; // stack to decide between skip/abort functions
-    var parents = []; // stack to avoiding loops from circular referencing
</del><ins>+        // Call the o related callback with the given arguments.
+       function bindCallbacks( o, callbacks, args ) {
+               var prop = QUnit.objectType( o );
+               if ( prop ) {
+                       if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {
+                               return callbacks[ prop ].apply( callbacks, args );
+                       } else {
+                               return callbacks[ prop ]; // or undefined
+                       }
+               }
+       }
</ins><span class="cx"> 
</span><del>-    // Call the o related callback with the given arguments.
-    function bindCallbacks(o, callbacks, args) {
-        var prop = QUnit.objectType(o);
-        if (prop) {
-            if (QUnit.objectType(callbacks[prop]) === "function") {
-                return callbacks[prop].apply(callbacks, args);
-            } else {
-                return callbacks[prop]; // or undefined
-            }
-        }
-    }
-    
-    var callbacks = function () {
</del><ins>+        // the real equiv function
+       var innerEquiv,
+               // stack to decide between skip/abort functions
+               callers = [],
+               // stack to avoiding loops from circular referencing
+               parents = [],
+               parentsB = [],
</ins><span class="cx"> 
</span><del>-        // for string, boolean, number and null
-        function useStrictEquality(b, a) {
-            if (b instanceof a.constructor || a instanceof b.constructor) {
-                // to catch short annotaion VS 'new' annotation of a declaration
-                // e.g. var i = 1;
-                //      var j = new Number(1);
-                return a == b;
-            } else {
-                return a === b;
-            }
-        }
</del><ins>+                getProto = Object.getPrototypeOf || function ( obj ) {
+                       /*jshint camelcase:false */
+                       return obj.__proto__;
+               },
+               callbacks = (function () {
</ins><span class="cx"> 
</span><del>-        return {
-            "string": useStrictEquality,
-            "boolean": useStrictEquality,
-            "number": useStrictEquality,
-            "null": useStrictEquality,
-            "undefined": useStrictEquality,
</del><ins>+                        // for string, boolean, number and null
+                       function useStrictEquality( b, a ) {
+                               /*jshint eqeqeq:false */
+                               if ( b instanceof a.constructor || a instanceof b.constructor ) {
+                                       // to catch short annotation VS 'new' annotation of a
+                                       // declaration
+                                       // e.g. var i = 1;
+                                       // var j = new Number(1);
+                                       return a == b;
+                               } else {
+                                       return a === b;
+                               }
+                       }
</ins><span class="cx"> 
</span><del>-            "nan": function (b) {
-                return isNaN(b);
-            },
</del><ins>+                        return {
+                               "string": useStrictEquality,
+                               "boolean": useStrictEquality,
+                               "number": useStrictEquality,
+                               "null": useStrictEquality,
+                               "undefined": useStrictEquality,
</ins><span class="cx"> 
</span><del>-            "date": function (b, a) {
-                return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf();
-            },
</del><ins>+                                "nan": function( b ) {
+                                       return isNaN( b );
+                               },
</ins><span class="cx"> 
</span><del>-            "regexp": function (b, a) {
-                return QUnit.objectType(b) === "regexp" &&
-                    a.source === b.source && // the regex itself
-                    a.global === b.global && // and its modifers (gmi) ...
-                    a.ignoreCase === b.ignoreCase &&
-                    a.multiline === b.multiline;
-            },
</del><ins>+                                "date": function( b, a ) {
+                                       return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();
+                               },
</ins><span class="cx"> 
</span><del>-            // - skip when the property is a method of an instance (OOP)
-            // - abort otherwise,
-            //   initial === would have catch identical references anyway
-            "function": function () {
-                var caller = callers[callers.length - 1];
-                return caller !== Object &&
-                        typeof caller !== "undefined";
-            },
</del><ins>+                                "regexp": function( b, a ) {
+                                       return QUnit.objectType( b ) === "regexp" &&
+                                               // the regex itself
+                                               a.source === b.source &&
+                                               // and its modifiers
+                                               a.global === b.global &&
+                                               // (gmi) ...
+                                               a.ignoreCase === b.ignoreCase &&
+                                               a.multiline === b.multiline &&
+                                               a.sticky === b.sticky;
+                               },
</ins><span class="cx"> 
</span><del>-            "array": function (b, a) {
-                var i, j, loop;
-                var len;
</del><ins>+                                // - skip when the property is a method of an instance (OOP)
+                               // - abort otherwise,
+                               // initial === would have catch identical references anyway
+                               "function": function() {
+                                       var caller = callers[callers.length - 1];
+                                       return caller !== Object && typeof caller !== "undefined";
+                               },
</ins><span class="cx"> 
</span><del>-                // b could be an object literal here
-                if ( ! (QUnit.objectType(b) === "array")) {
-                    return false;
-                }   
-                
-                len = a.length;
-                if (len !== b.length) { // safe and faster
-                    return false;
-                }
-                
-                //track reference to avoid circular references
-                parents.push(a);
-                for (i = 0; i < len; i++) {
-                    loop = false;
-                    for(j=0;j<parents.length;j++){
-                        if(parents[j] === a[i]){
-                            loop = true;//dont rewalk array
-                        }
-                    }
-                    if (!loop && ! innerEquiv(a[i], b[i])) {
-                        parents.pop();
-                        return false;
-                    }
-                }
-                parents.pop();
-                return true;
-            },
</del><ins>+                                "array": function( b, a ) {
+                                       var i, j, len, loop, aCircular, bCircular;
</ins><span class="cx"> 
</span><del>-            "object": function (b, a) {
-                var i, j, loop;
-                var eq = true; // unless we can proove it
-                var aProperties = [], bProperties = []; // collection of strings
</del><ins>+                                        // b could be an object literal here
+                                       if ( QUnit.objectType( b ) !== "array" ) {
+                                               return false;
+                                       }
</ins><span class="cx"> 
</span><del>-                // comparing constructors is more strict than using instanceof
-                if ( a.constructor !== b.constructor) {
-                    return false;
-                }
</del><ins>+                                        len = a.length;
+                                       if ( len !== b.length ) {
+                                               // safe and faster
+                                               return false;
+                                       }
</ins><span class="cx"> 
</span><del>-                // stack constructor before traversing properties
-                callers.push(a.constructor);
-                //track reference to avoid circular references
-                parents.push(a);
-                
-                for (i in a) { // be strict: don't ensures hasOwnProperty and go deep
-                    loop = false;
-                    for(j=0;j<parents.length;j++){
-                        if(parents[j] === a[i])
-                            loop = true; //don't go down the same path twice
-                    }
-                    aProperties.push(i); // collect a's properties
</del><ins>+                                        // track reference to avoid circular references
+                                       parents.push( a );
+                                       parentsB.push( b );
+                                       for ( i = 0; i < len; i++ ) {
+                                               loop = false;
+                                               for ( j = 0; j < parents.length; j++ ) {
+                                                       aCircular = parents[j] === a[i];
+                                                       bCircular = parentsB[j] === b[i];
+                                                       if ( aCircular || bCircular ) {
+                                                               if ( a[i] === b[i] || aCircular && bCircular ) {
+                                                                       loop = true;
+                                                               } else {
+                                                                       parents.pop();
+                                                                       parentsB.pop();
+                                                                       return false;
+                                                               }
+                                                       }
+                                               }
+                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
+                                                       parents.pop();
+                                                       parentsB.pop();
+                                                       return false;
+                                               }
+                                       }
+                                       parents.pop();
+                                       parentsB.pop();
+                                       return true;
+                               },
</ins><span class="cx"> 
</span><del>-                    if (!loop && ! innerEquiv(a[i], b[i])) {
-                        eq = false;
-                        break;
-                    }
-                }
</del><ins>+                                "object": function( b, a ) {
+                                       /*jshint forin:false */
+                                       var i, j, loop, aCircular, bCircular,
+                                               // Default to true
+                                               eq = true,
+                                               aProperties = [],
+                                               bProperties = [];
</ins><span class="cx"> 
</span><del>-                callers.pop(); // unstack, we are done
-                parents.pop();
</del><ins>+                                        // comparing constructors is more strict than using
+                                       // instanceof
+                                       if ( a.constructor !== b.constructor ) {
+                                               // Allow objects with no prototype to be equivalent to
+                                               // objects with Object as their constructor.
+                                               if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
+                                                       ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
+                                                               return false;
+                                               }
+                                       }
</ins><span class="cx"> 
</span><del>-                for (i in b) {
-                    bProperties.push(i); // collect b's properties
-                }
</del><ins>+                                        // stack constructor before traversing properties
+                                       callers.push( a.constructor );
</ins><span class="cx"> 
</span><del>-                // Ensures identical properties name
-                return eq && innerEquiv(aProperties.sort(), bProperties.sort());
-            }
-        };
-    }();
</del><ins>+                                        // track reference to avoid circular references
+                                       parents.push( a );
+                                       parentsB.push( b );
</ins><span class="cx"> 
</span><del>-    innerEquiv = function () { // can take multiple arguments
-        var args = Array.prototype.slice.apply(arguments);
-        if (args.length < 2) {
-            return true; // end transition
-        }
</del><ins>+                                        // be strict: don't ensure hasOwnProperty and go deep
+                                       for ( i in a ) {
+                                               loop = false;
+                                               for ( j = 0; j < parents.length; j++ ) {
+                                                       aCircular = parents[j] === a[i];
+                                                       bCircular = parentsB[j] === b[i];
+                                                       if ( aCircular || bCircular ) {
+                                                               if ( a[i] === b[i] || aCircular && bCircular ) {
+                                                                       loop = true;
+                                                               } else {
+                                                                       eq = false;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                               aProperties.push(i);
+                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
+                                                       eq = false;
+                                                       break;
+                                               }
+                                       }
</ins><span class="cx"> 
</span><del>-        return (function (a, b) {
-            if (a === b) {
-                return true; // catch the most you can
-            } else if (a === null || b === null || typeof a === "undefined" || typeof b === "undefined" || QUnit.objectType(a) !== QUnit.objectType(b)) {
-                return false; // don't lose time with error prone cases
-            } else {
-                return bindCallbacks(a, callbacks, [b, a]);
-            }
</del><ins>+                                        parents.pop();
+                                       parentsB.pop();
+                                       callers.pop(); // unstack, we are done
</ins><span class="cx"> 
</span><del>-        // apply transition with (1..n) arguments
-        })(args[0], args[1]) && arguments.callee.apply(this, args.splice(1, args.length -1));
-    };
</del><ins>+                                        for ( i in b ) {
+                                               bProperties.push( i ); // collect b's properties
+                                       }
</ins><span class="cx"> 
</span><del>-    return innerEquiv;
</del><ins>+                                        // Ensures identical properties name
+                                       return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
+                               }
+                       };
+               }());
</ins><span class="cx"> 
</span><del>-}();
</del><ins>+        innerEquiv = function() { // can take multiple arguments
+               var args = [].slice.apply( arguments );
+               if ( args.length < 2 ) {
+                       return true; // end transition
+               }
</ins><span class="cx"> 
</span><ins>+               return (function( a, b ) {
+                       if ( a === b ) {
+                               return true; // catch the most you can
+                       } else if ( a === null || b === null || typeof a === "undefined" ||
+                                       typeof b === "undefined" ||
+                                       QUnit.objectType(a) !== QUnit.objectType(b) ) {
+                               return false; // don't lose time with error prone cases
+                       } else {
+                               return bindCallbacks(a, callbacks, [ b, a ]);
+                       }
+
+                       // apply transition with (1..n) arguments
+               }( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );
+       };
+
+       return innerEquiv;
+}());
+
</ins><span class="cx"> /**
</span><del>- * jsDump
- * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
- * Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
- * Date: 5/15/2008
</del><ins>+ * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
+ * http://flesler.blogspot.com Licensed under BSD
+ * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
+ *
</ins><span class="cx">  * @projectDescription Advanced and extensible data dumping for Javascript.
</span><span class="cx">  * @version 1.0.0
</span><span class="cx">  * @author Ariel Flesler
</span><span class="lines">@@ -945,186 +1903,225 @@
</span><span class="cx">  */
</span><span class="cx"> QUnit.jsDump = (function() {
</span><span class="cx">  function quote( str ) {
</span><del>-               return '"' + str.toString().replace(/"/g, '\\"') + '"';
-       };
</del><ins>+                return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\"";
+       }
</ins><span class="cx">   function literal( o ) {
</span><del>-               return o + '';  
-       };
</del><ins>+                return o + "";
+       }
</ins><span class="cx">   function join( pre, arr, post ) {
</span><span class="cx">          var s = jsDump.separator(),
</span><span class="cx">                  base = jsDump.indent(),
</span><span class="cx">                  inner = jsDump.indent(1);
</span><del>-               if ( arr.join )
-                       arr = arr.join( ',' + s + inner );
-               if ( !arr )
</del><ins>+                if ( arr.join ) {
+                       arr = arr.join( "," + s + inner );
+               }
+               if ( !arr ) {
</ins><span class="cx">                   return pre + post;
</span><ins>+               }
</ins><span class="cx">           return [ pre, inner + arr, base + post ].join(s);
</span><del>-       };
-       function array( arr ) {
-               var i = arr.length,     ret = Array(i);                                 
</del><ins>+        }
+       function array( arr, stack ) {
+               var i = arr.length, ret = new Array(i);
</ins><span class="cx">           this.up();
</span><del>-               while ( i-- )
-                       ret[i] = this.parse( arr[i] );                          
</del><ins>+                while ( i-- ) {
+                       ret[i] = this.parse( arr[i] , undefined , stack);
+               }
</ins><span class="cx">           this.down();
</span><del>-               return join( '[', ret, ']' );
-       };
-       
-       var reName = /^function (\w+)/;
-       
-       var jsDump = {
-               parse:function( obj, type ) { //type is used mostly internally, you can fix a (custom)type in advance
-                       var     parser = this.parsers[ type || this.typeOf(obj) ];
-                       type = typeof parser;                   
-                       
-                       return type == 'function' ? parser.call( this, obj ) :
-                                  type == 'string' ? parser :
-                                  this.parsers.error;
-               },
-               typeOf:function( obj ) {
-                       var type;
-                       if ( obj === null ) {
-                               type = "null";
-                       } else if (typeof obj === "undefined") {
-                               type = "undefined";
-                       } else if (QUnit.is("RegExp", obj)) {
-                               type = "regexp";
-                       } else if (QUnit.is("Date", obj)) {
-                               type = "date";
-                       } else if (QUnit.is("Function", obj)) {
-                               type = "function";
-                       } else if (obj.setInterval && obj.document && !obj.nodeType) {
-                               type = "window";
-                       } else if (obj.nodeType === 9) {
-                               type = "document";
-                       } else if (obj.nodeType) {
-                               type = "node";
-                       } else if (typeof obj === "object" && typeof obj.length === "number" && obj.length >= 0) {
-                               type = "array";
-                       } else {
-                               type = typeof obj;
-                       }
-                       return type;
-               },
-               separator:function() {
-                       return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
-               },
-               indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing
-                       if ( !this.multiline )
-                               return '';
-                       var chr = this.indentChar;
-                       if ( this.HTML )
-                               chr = chr.replace(/\t/g,'   ').replace(/ /g,'&nbsp;');
-                       return Array( this._depth_ + (extra||0) ).join(chr);
-               },
-               up:function( a ) {
-                       this._depth_ += a || 1;
-               },
-               down:function( a ) {
-                       this._depth_ -= a || 1;
-               },
-               setParser:function( name, parser ) {
-                       this.parsers[name] = parser;
-               },
-               // The next 3 are exposed so you can use them
-               quote:quote, 
-               literal:literal,
-               join:join,
-               //
-               _depth_: 1,
-               // This is the list of parsers, to modify them, use jsDump.setParser
-               parsers:{
-                       window: '[Window]',
-                       document: '[Document]',
-                       error:'[ERROR]', //when no parser is found, shouldn't happen
-                       unknown: '[Unknown]',
-                       'null':'null',
-                       undefined:'undefined',
-                       'function':function( fn ) {
-                               var ret = 'function',
-                                       name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
-                               if ( name )
-                                       ret += ' ' + name;
-                               ret += '(';
-                               
-                               ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
-                               return join( ret, this.parse(fn,'functionCode'), '}' );
</del><ins>+                return join( "[", ret, "]" );
+       }
+
+       var reName = /^function (\w+)/,
+               jsDump = {
+                       // type is used mostly internally, you can fix a (custom)type in advance
+                       parse: function( obj, type, stack ) {
+                               stack = stack || [ ];
+                               var inStack, res,
+                                       parser = this.parsers[ type || this.typeOf(obj) ];
+
+                               type = typeof parser;
+                               inStack = inArray( obj, stack );
+
+                               if ( inStack !== -1 ) {
+                                       return "recursion(" + (inStack - stack.length) + ")";
+                               }
+                               if ( type === "function" )  {
+                                       stack.push( obj );
+                                       res = parser.call( this, obj, stack );
+                                       stack.pop();
+                                       return res;
+                               }
+                               return ( type === "string" ) ? parser : this.parsers.error;
</ins><span class="cx">                   },
</span><del>-                       array: array,
-                       nodelist: array,
-                       arguments: array,
-                       object:function( map ) {
-                               var ret = [ ];
-                               this.up();
-                               for ( var key in map )
-                                       ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
-                               this.down();
-                               return join( '{', ret, '}' );
</del><ins>+                        typeOf: function( obj ) {
+                               var type;
+                               if ( obj === null ) {
+                                       type = "null";
+                               } else if ( typeof obj === "undefined" ) {
+                                       type = "undefined";
+                               } else if ( QUnit.is( "regexp", obj) ) {
+                                       type = "regexp";
+                               } else if ( QUnit.is( "date", obj) ) {
+                                       type = "date";
+                               } else if ( QUnit.is( "function", obj) ) {
+                                       type = "function";
+                               } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
+                                       type = "window";
+                               } else if ( obj.nodeType === 9 ) {
+                                       type = "document";
+                               } else if ( obj.nodeType ) {
+                                       type = "node";
+                               } else if (
+                                       // native arrays
+                                       toString.call( obj ) === "[object Array]" ||
+                                       // NodeList objects
+                                       ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
+                               ) {
+                                       type = "array";
+                               } else if ( obj.constructor === Error.prototype.constructor ) {
+                                       type = "error";
+                               } else {
+                                       type = typeof obj;
+                               }
+                               return type;
</ins><span class="cx">                   },
</span><del>-                       node:function( node ) {
-                               var open = this.HTML ? '&lt;' : '<',
-                                       close = this.HTML ? '&gt;' : '>';
-                                       
-                               var tag = node.nodeName.toLowerCase(),
-                                       ret = open + tag;
-                                       
-                               for ( var a in this.DOMAttrs ) {
-                                       var val = node[this.DOMAttrs[a]];
-                                       if ( val )
-                                               ret += ' ' + a + '=' + this.parse( val, 'attribute' );
</del><ins>+                        separator: function() {
+                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
+                       },
+                       // extra can be a number, shortcut for increasing-calling-decreasing
+                       indent: function( extra ) {
+                               if ( !this.multiline ) {
+                                       return "";
</ins><span class="cx">                           }
</span><del>-                               return ret + close + open + '/' + tag + close;
</del><ins>+                                var chr = this.indentChar;
+                               if ( this.HTML ) {
+                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
+                               }
+                               return new Array( this.depth + ( extra || 0 ) ).join(chr);
</ins><span class="cx">                   },
</span><del>-                       functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function
-                               var l = fn.length;
-                               if ( !l ) return '';                            
-                               
-                               var args = Array(l);
-                               while ( l-- )
-                                       args[l] = String.fromCharCode(97+l);//97 is 'a'
-                               return ' ' + args.join(', ') + ' ';
</del><ins>+                        up: function( a ) {
+                               this.depth += a || 1;
</ins><span class="cx">                   },
</span><del>-                       key:quote, //object calls it internally, the key part of an item in a map
-                       functionCode:'[code]', //function calls it internally, it's the content of the function
-                       attribute:quote, //node calls it internally, it's an html attribute value
-                       string:quote,
-                       date:quote,
-                       regexp:literal, //regex
-                       number:literal,
-                       'boolean':literal
-               },
-               DOMAttrs:{//attributes to dump from nodes, name=>realName
-                       id:'id',
-                       name:'name',
-                       'class':'className'
-               },
-               HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
-               indentChar:'   ',//indentation unit
-               multiline:false //if true, items in a collection, are separated by a \n, else just a space.
-       };
</del><ins>+                        down: function( a ) {
+                               this.depth -= a || 1;
+                       },
+                       setParser: function( name, parser ) {
+                               this.parsers[name] = parser;
+                       },
+                       // The next 3 are exposed so you can use them
+                       quote: quote,
+                       literal: literal,
+                       join: join,
+                       //
+                       depth: 1,
+                       // This is the list of parsers, to modify them, use jsDump.setParser
+                       parsers: {
+                               window: "[Window]",
+                               document: "[Document]",
+                               error: function(error) {
+                                       return "Error(\"" + error.message + "\")";
+                               },
+                               unknown: "[Unknown]",
+                               "null": "null",
+                               "undefined": "undefined",
+                               "function": function( fn ) {
+                                       var ret = "function",
+                                               // functions never have name in IE
+                                               name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
</ins><span class="cx"> 
</span><del>-       return jsDump;
-})();
</del><ins>+                                        if ( name ) {
+                                               ret += " " + name;
+                                       }
+                                       ret += "( ";
</ins><span class="cx"> 
</span><del>-// from Sizzle.js
-function getText( elems ) {
-       var ret = "", elem;
</del><ins>+                                        ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
+                                       return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
+                               },
+                               array: array,
+                               nodelist: array,
+                               "arguments": array,
+                               object: function( map, stack ) {
+                                       /*jshint forin:false */
+                                       var ret = [ ], keys, key, val, i;
+                                       QUnit.jsDump.up();
+                                       keys = [];
+                                       for ( key in map ) {
+                                               keys.push( key );
+                                       }
+                                       keys.sort();
+                                       for ( i = 0; i < keys.length; i++ ) {
+                                               key = keys[ i ];
+                                               val = map[ key ];
+                                               ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
+                                       }
+                                       QUnit.jsDump.down();
+                                       return join( "{", ret, "}" );
+                               },
+                               node: function( node ) {
+                                       var len, i, val,
+                                               open = QUnit.jsDump.HTML ? "&lt;" : "<",
+                                               close = QUnit.jsDump.HTML ? "&gt;" : ">",
+                                               tag = node.nodeName.toLowerCase(),
+                                               ret = open + tag,
+                                               attrs = node.attributes;
</ins><span class="cx"> 
</span><del>-       for ( var i = 0; elems[i]; i++ ) {
-               elem = elems[i];
</del><ins>+                                        if ( attrs ) {
+                                               for ( i = 0, len = attrs.length; i < len; i++ ) {
+                                                       val = attrs[i].nodeValue;
+                                                       // IE6 includes all attributes in .attributes, even ones not explicitly set.
+                                                       // Those have values like undefined, null, 0, false, "" or "inherit".
+                                                       if ( val && val !== "inherit" ) {
+                                                               ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
+                                                       }
+                                               }
+                                       }
+                                       ret += close;
</ins><span class="cx"> 
</span><del>-               // Get the text from text nodes and CDATA nodes
-               if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
-                       ret += elem.nodeValue;
</del><ins>+                                        // Show content of TextNode or CDATASection
+                                       if ( node.nodeType === 3 || node.nodeType === 4 ) {
+                                               ret += node.nodeValue;
+                                       }
</ins><span class="cx"> 
</span><del>-               // Traverse everything else, except comment nodes
-               } else if ( elem.nodeType !== 8 ) {
-                       ret += getText( elem.childNodes );
-               }
-       }
</del><ins>+                                        return ret + open + "/" + tag + close;
+                               },
+                               // function calls it internally, it's the arguments part of the function
+                               functionArgs: function( fn ) {
+                                       var args,
+                                               l = fn.length;
</ins><span class="cx"> 
</span><del>-       return ret;
-};
</del><ins>+                                        if ( !l ) {
+                                               return "";
+                                       }
</ins><span class="cx"> 
</span><ins>+                                       args = new Array(l);
+                                       while ( l-- ) {
+                                               // 97 is 'a'
+                                               args[l] = String.fromCharCode(97+l);
+                                       }
+                                       return " " + args.join( ", " ) + " ";
+                               },
+                               // object calls it internally, the key part of an item in a map
+                               key: quote,
+                               // function calls it internally, it's the content of the function
+                               functionCode: "[code]",
+                               // node calls it internally, it's an html attribute value
+                               attribute: quote,
+                               string: quote,
+                               date: quote,
+                               regexp: literal,
+                               number: literal,
+                               "boolean": literal
+                       },
+                       // if true, entities are escaped ( <, >, \t, space and \n )
+                       HTML: false,
+                       // indentation unit
+                       indentChar: "  ",
+                       // if true, items in a collection, are separated by a \n, else just a space.
+                       multiline: true
+               };
+
+       return jsDump;
+}());
+
</ins><span class="cx"> /*
</span><span class="cx">  * Javascript Diff Algorithm
</span><span class="cx">  *  By John Resig (http://ejohn.org/)
</span><span class="lines">@@ -1134,132 +2131,158 @@
</span><span class="cx">  *
</span><span class="cx">  * More Info:
</span><span class="cx">  *  http://ejohn.org/projects/javascript-diff-algorithm/
</span><del>- *  
</del><ins>+ *
</ins><span class="cx">  * Usage: QUnit.diff(expected, actual)
</span><del>- * 
- * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
</del><ins>+ *
+ * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
</ins><span class="cx">  */
</span><span class="cx"> QUnit.diff = (function() {
</span><del>-       function diff(o, n){
-               var ns = new Object();
-               var os = new Object();
-               
-               for (var i = 0; i < n.length; i++) {
-                       if (ns[n[i]] == null) 
-                               ns[n[i]] = {
-                                       rows: new Array(),
</del><ins>+        /*jshint eqeqeq:false, eqnull:true */
+       function diff( o, n ) {
+               var i,
+                       ns = {},
+                       os = {};
+
+               for ( i = 0; i < n.length; i++ ) {
+                       if ( !hasOwn.call( ns, n[i] ) ) {
+                               ns[ n[i] ] = {
+                                       rows: [],
</ins><span class="cx">                                   o: null
</span><span class="cx">                          };
</span><del>-                       ns[n[i]].rows.push(i);
</del><ins>+                        }
+                       ns[ n[i] ].rows.push( i );
</ins><span class="cx">           }
</span><del>-               
-               for (var i = 0; i < o.length; i++) {
-                       if (os[o[i]] == null) 
-                               os[o[i]] = {
-                                       rows: new Array(),
</del><ins>+
+               for ( i = 0; i < o.length; i++ ) {
+                       if ( !hasOwn.call( os, o[i] ) ) {
+                               os[ o[i] ] = {
+                                       rows: [],
</ins><span class="cx">                                   n: null
</span><span class="cx">                          };
</span><del>-                       os[o[i]].rows.push(i);
</del><ins>+                        }
+                       os[ o[i] ].rows.push( i );
</ins><span class="cx">           }
</span><del>-               
-               for (var i in ns) {
-                       if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
-                               n[ns[i].rows[0]] = {
-                                       text: n[ns[i].rows[0]],
-                                       row: os[i].rows[0]
-                               };
-                               o[os[i].rows[0]] = {
-                                       text: o[os[i].rows[0]],
-                                       row: ns[i].rows[0]
-                               };
</del><ins>+
+               for ( i in ns ) {
+                       if ( hasOwn.call( ns, i ) ) {
+                               if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
+                                       n[ ns[i].rows[0] ] = {
+                                               text: n[ ns[i].rows[0] ],
+                                               row: os[i].rows[0]
+                                       };
+                                       o[ os[i].rows[0] ] = {
+                                               text: o[ os[i].rows[0] ],
+                                               row: ns[i].rows[0]
+                                       };
+                               }
</ins><span class="cx">                   }
</span><span class="cx">          }
</span><del>-               
-               for (var i = 0; i < n.length - 1; i++) {
-                       if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null &&
-                       n[i + 1] == o[n[i].row + 1]) {
-                               n[i + 1] = {
-                                       text: n[i + 1],
</del><ins>+
+               for ( i = 0; i < n.length - 1; i++ ) {
+                       if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
+                                               n[ i + 1 ] == o[ n[i].row + 1 ] ) {
+
+                               n[ i + 1 ] = {
+                                       text: n[ i + 1 ],
</ins><span class="cx">                                   row: n[i].row + 1
</span><span class="cx">                          };
</span><del>-                               o[n[i].row + 1] = {
-                                       text: o[n[i].row + 1],
</del><ins>+                                o[ n[i].row + 1 ] = {
+                                       text: o[ n[i].row + 1 ],
</ins><span class="cx">                                   row: i + 1
</span><span class="cx">                          };
</span><span class="cx">                  }
</span><span class="cx">          }
</span><del>-               
-               for (var i = n.length - 1; i > 0; i--) {
-                       if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
-                       n[i - 1] == o[n[i].row - 1]) {
-                               n[i - 1] = {
-                                       text: n[i - 1],
</del><ins>+
+               for ( i = n.length - 1; i > 0; i-- ) {
+                       if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
+                                               n[ i - 1 ] == o[ n[i].row - 1 ]) {
+
+                               n[ i - 1 ] = {
+                                       text: n[ i - 1 ],
</ins><span class="cx">                                   row: n[i].row - 1
</span><span class="cx">                          };
</span><del>-                               o[n[i].row - 1] = {
-                                       text: o[n[i].row - 1],
</del><ins>+                                o[ n[i].row - 1 ] = {
+                                       text: o[ n[i].row - 1 ],
</ins><span class="cx">                                   row: i - 1
</span><span class="cx">                          };
</span><span class="cx">                  }
</span><span class="cx">          }
</span><del>-               
</del><ins>+
</ins><span class="cx">           return {
</span><span class="cx">                  o: o,
</span><span class="cx">                  n: n
</span><span class="cx">          };
</span><span class="cx">  }
</span><del>-       
-       return function(o, n){
-               o = o.replace(/\s+$/, '');
-               n = n.replace(/\s+$/, '');
-               var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/));
</del><span class="cx"> 
</span><del>-               var str = "";
-               
-               var oSpace = o.match(/\s+/g);
-               if (oSpace == null) {
-                       oSpace = [" "];
</del><ins>+        return function( o, n ) {
+               o = o.replace( /\s+$/, "" );
+               n = n.replace( /\s+$/, "" );
+
+               var i, pre,
+                       str = "",
+                       out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
+                       oSpace = o.match(/\s+/g),
+                       nSpace = n.match(/\s+/g);
+
+               if ( oSpace == null ) {
+                       oSpace = [ " " ];
</ins><span class="cx">           }
</span><span class="cx">          else {
</span><del>-                       oSpace.push(" ");
</del><ins>+                        oSpace.push( " " );
</ins><span class="cx">           }
</span><del>-               var nSpace = n.match(/\s+/g);
-               if (nSpace == null) {
-                       nSpace = [" "];
</del><ins>+
+               if ( nSpace == null ) {
+                       nSpace = [ " " ];
</ins><span class="cx">           }
</span><span class="cx">          else {
</span><del>-                       nSpace.push(" ");
</del><ins>+                        nSpace.push( " " );
</ins><span class="cx">           }
</span><del>-               
-               if (out.n.length == 0) {
-                       for (var i = 0; i < out.o.length; i++) {
-                               str += '<del>' + out.o[i] + oSpace[i] + "</del>";
</del><ins>+
+               if ( out.n.length === 0 ) {
+                       for ( i = 0; i < out.o.length; i++ ) {
+                               str += "<del>" + out.o[i] + oSpace[i] + "</del>";
</ins><span class="cx">                   }
</span><span class="cx">          }
</span><span class="cx">          else {
</span><del>-                       if (out.n[0].text == null) {
-                               for (n = 0; n < out.o.length && out.o[n].text == null; n++) {
-                                       str += '<del>' + out.o[n] + oSpace[n] + "</del>";
</del><ins>+                        if ( out.n[0].text == null ) {
+                               for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
+                                       str += "<del>" + out.o[n] + oSpace[n] + "</del>";
</ins><span class="cx">                           }
</span><span class="cx">                  }
</span><del>-                       
-                       for (var i = 0; i < out.n.length; i++) {
</del><ins>+
+                       for ( i = 0; i < out.n.length; i++ ) {
</ins><span class="cx">                           if (out.n[i].text == null) {
</span><del>-                                       str += '<ins>' + out.n[i] + nSpace[i] + "</ins>";
</del><ins>+                                        str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
</ins><span class="cx">                           }
</span><span class="cx">                          else {
</span><del>-                                       var pre = "";
-                                       
-                                       for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) {
-                                               pre += '<del>' + out.o[n] + oSpace[n] + "</del>";
</del><ins>+                                        // `pre` initialized at top of scope
+                                       pre = "";
+
+                                       for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
+                                               pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
</ins><span class="cx">                                   }
</span><span class="cx">                                  str += " " + out.n[i].text + nSpace[i] + pre;
</span><span class="cx">                          }
</span><span class="cx">                  }
</span><span class="cx">          }
</span><del>-               
</del><ins>+
</ins><span class="cx">           return str;
</span><del>-       }
-})();
</del><ins>+        };
+}());
</ins><span class="cx"> 
</span><del>-})(this);
</del><ins>+// For browser, export only select globals
+if ( typeof window !== "undefined" ) {
+       extend( window, QUnit.constructor.prototype );
+       window.QUnit = QUnit;
+}
+
+// For CommonJS environments, export everything
+if ( typeof module !== "undefined" && module.exports ) {
+       module.exports = QUnit;
+}
+
+
+// Get a reference to the global object, like window in browsers
+}( (function() {
+       return this;
+})() ));
</ins></span></pre></div>
<a id="trunktestsquniteditorjsqunitreporterjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/js/qunit/reporter.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/qunit/reporter.js    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/qunit/reporter.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,13 +0,0 @@
</span><del>-(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);
-                       }
-               };
-       }
-})();
</del></span></pre></div>
<a id="trunktestsquniteditorjsqunittestrunnercss"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/js/qunit/testrunner.css (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/qunit/testrunner.css 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/qunit/testrunner.css    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,151 +0,0 @@
</span><del>-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);
-}
</del><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunktestsquniteditorjsqunittestrunnerjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/js/qunit/testrunner.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/qunit/testrunner.js  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/qunit/testrunner.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,543 +0,0 @@
</span><del>-// 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();
-                                       // Auto-start
-                                       started = true;
-                                       start();
-                               }
-                       }
-
-                       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;
-})();
</del></span></pre></div>
<a id="trunktestsquniteditorjsrunnerjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/js/runner.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/runner.js                            (rev 0)
+++ trunk/tests/qunit/editor/js/runner.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,148 @@
</span><ins>+/*
+ * PhantomJS Runner QUnit Plugin 1.2.0
+ *
+ * PhantomJS binaries: http://phantomjs.org/download.html
+ * Requires PhantomJS 1.6+ (1.7+ recommended)
+ *
+ * Run with:
+ *   phantomjs runner.js [url-of-your-qunit-testsuite]
+ *
+ * e.g.
+ *   phantomjs runner.js http://localhost/qunit/test/index.html
+ */
+
+/*global phantom:false, require:false, console:false, window:false, QUnit:false */
+
+(function() {
+       'use strict';
+
+       var url, page, timeout,
+               args = require('system').args;
+
+       // arg[0]: scriptName, args[1...]: arguments
+       if (args.length < 2 || args.length > 3) {
+               console.error('Usage:\n  phantomjs runner.js [url-of-your-qunit-testsuite] [timeout-in-seconds]');
+               phantom.exit(1);
+       }
+
+       url = args[1];
+       page = require('webpage').create();
+       if (args[2] !== undefined) {
+               timeout = parseInt(args[2], 10);
+       }
+
+       // Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
+       page.onConsoleMessage = function(msg) {
+               console.log(msg);
+       };
+
+       page.onInitialized = function() {
+               page.evaluate(addLogging);
+       };
+
+       page.onCallback = function(message) {
+               var result,
+                       failed;
+
+               if (message) {
+                       if (message.name === 'QUnit.done') {
+                               result = message.data;
+                               failed = !result || !result.total || result.failed;
+
+                               if (!result.total) {
+                                       console.error('No tests were executed. Are you loading tests asynchronously?');
+                               }
+
+                               phantom.exit(failed ? 1 : 0);
+                       }
+               }
+       };
+
+       page.open(url, function(status) {
+               if (status !== 'success') {
+                       console.error('Unable to access network: ' + status);
+                       phantom.exit(1);
+               } else {
+                       // Cannot do this verification with the 'DOMContentLoaded' handler because it
+                       // will be too late to attach it if a page does not have any script tags.
+                       var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
+                       if (qunitMissing) {
+                               console.error('The `QUnit` object is not present on this page.');
+                               phantom.exit(1);
+                       }
+
+                       // Set a timeout on the test running, otherwise tests with async problems will hang forever
+                       if (typeof timeout === 'number') {
+                               setTimeout(function() {
+                                       console.error('The specified timeout of ' + timeout + ' seconds has expired. Aborting...');
+                                       phantom.exit(1);
+                               }, timeout * 1000);
+                       }
+
+                       // Do nothing... the callback mechanism will handle everything!
+               }
+       });
+
+       function addLogging() {
+               window.document.addEventListener('DOMContentLoaded', function() {
+                       var currentTestAssertions = [];
+
+                       QUnit.log(function(details) {
+                               var response;
+
+                               // Ignore passing assertions
+                               if (details.result) {
+                                       return;
+                               }
+
+                               response = details.message || '';
+
+                               if (typeof details.expected !== 'undefined') {
+                                       if (response) {
+                                               response += ', ';
+                                       }
+
+                                       response += 'expected: ' + details.expected + ', but was: ' + details.actual;
+                               }
+
+                               if (details.source) {
+                                       response += "\n" + details.source;
+                               }
+
+                               currentTestAssertions.push('Failed assertion: ' + response);
+                       });
+
+                       QUnit.testDone(function(result) {
+                               var i,
+                                       len,
+                                       name = '';
+
+                               if (result.module) {
+                                       name += result.module + ': ';
+                               }
+                               name += result.name;
+
+                               if (result.failed) {
+                                       console.log('\n' + 'Test failed: ' + name);
+
+                                       for (i = 0, len = currentTestAssertions.length; i < len; i++) {
+                                               console.log('    ' + currentTestAssertions[i]);
+                                       }
+                               }
+
+                               currentTestAssertions.length = 0;
+                       });
+
+                       QUnit.done(function(result) {
+                               console.log('\n' + 'Took ' + result.runtime +  'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
+
+                               if (typeof window.callPhantom === 'function') {
+                                       window.callPhantom({
+                                               'name': 'QUnit.done',
+                                               'data': result
+                                       });
+                               }
+                       });
+               }, false);
+       }
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/js/runner.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorjsutilsjs"></a>
<div class="modfile"><h4>Modified: trunk/tests/qunit/editor/js/utils.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/js/utils.js     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/js/utils.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,299 +1,339 @@
</span><del>-function fontFace(face) {
-       if (tinymce.isOpera) {
-               return "'" + face + "'";
-       } else {
-               return face;
</del><ins>+(function() {
+       function fontFace(face) {
+               if (tinymce.isOpera) {
+                       return "'" + face + "'";
+               } else {
+                       return face;
+               }
</ins><span class="cx">   }
</span><del>-}
</del><span class="cx"> 
</span><del>-function findContainer(selector) {
-       var container;
-       if (tinymce.is(selector, 'string')) {
-               container = editor.dom.select(selector)[0];
-       } else {
-               container = selector;
</del><ins>+        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;
</ins><span class="cx">   }
</span><del>-       if (container.firstChild) {
-               container = container.firstChild;
-       }
-       return container;
-}
</del><span class="cx"> 
</span><del>-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();
</del><ins>+        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();
</ins><span class="cx"> 
</span><del>-       function setRange(container, offset, start) {
-               offset = offset || 0;
</del><ins>+                function setRange(container, offset, start) {
+                       offset = offset || 0;
</ins><span class="cx"> 
</span><del>-               if (offset === 'after') {
</del><ins>+                        if (offset === 'after') {
+                               if (start) {
+                                       rng.setStartAfter(container);
+                               } else {
+                                       rng.setEndAfter(container);
+                               }
+                               return;
+                       } else if (offset === 'afterNextCharacter') {
+                               container = container.nextSibling;
+                               offset = 1;
+                       }
</ins><span class="cx">                   if (start) {
</span><del>-                               rng.setStartAfter(container);
</del><ins>+                                rng.setStart(container, offset);
</ins><span class="cx">                   } else {
</span><del>-                               rng.setEndAfter(container);
</del><ins>+                                rng.setEnd(container, offset);
</ins><span class="cx">                   }
</span><del>-                       return;
-               } else if (offset === 'afterNextCharacter') {
-                       container = container.nextSibling;
-                       offset = 1;
</del><span class="cx">           }
</span><del>-               if (start) {
-                       rng.setStart(container, offset);
-               } else {
-                       rng.setEnd(container, offset);
-               }
</del><ins>+
+               setRange(startContainer, startOffset, true);
+               setRange(endContainer, endOffset, false);
+               editor.selection.setRng(rng);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       setRange(startContainer, startOffset, true);
-       setRange(endContainer, endOffset, false);
-       editor.selection.setRng(rng);
-}
-
-function initWhenTinyAndRobotAreReady(initTinyFunction) {
-       function loaded() {
-               QUnit.start();
</del><ins>+        function trimContent(content) {
+               return content.replace(/^<p>&nbsp;<\/p>\n?/, '').replace(/\n?<p>&nbsp;<\/p>$/, '');
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       tinymce.on('AddEditor', function(e) {
-               e.editor.on('Init', function() {
-                       loaded();
-               });
-       });
</del><ins>+        /**
+        * 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;
</ins><span class="cx"> 
</span><del>-       window.robot.onload(initTinyFunction);
-}
</del><ins>+                o = tinymce.extend({
+                       keyCode : 13,
+                       charCode : 0
+               }, o);
</ins><span class="cx"> 
</span><del>-function trimContent(content) {
-       return content.replace(/^<p>&nbsp;<\/p>\n?/, '').replace(/\n?<p>&nbsp;<\/p>$/, '');
-}
</del><ins>+                e = tinymce.DOM.get(e);
</ins><span class="cx"> 
</span><del>-/**
- * 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;
</del><ins>+                if (e.fireEvent) {
+                       ev = document.createEventObject();
+                       tinymce.extend(ev, o);
+                       e.fireEvent('on' + na, ev);
+                       return;
+               }
</ins><span class="cx"> 
</span><del>-       o = tinymce.extend({
-               keyCode : 13,
-               charCode : 0
-       }, o);
</del><ins>+                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);
</ins><span class="cx"> 
</span><del>-       e = tinymce.DOM.get(e);
</del><ins>+                                ev.keyCode = o.keyCode;
+                               ev.charCode = o.charCode;
+                       }
+               } else {
+                       ev = document.createEvent('UIEvents');
</ins><span class="cx"> 
</span><del>-       if (e.fireEvent) {
-               ev = document.createEventObject();
-               tinymce.extend(ev, o);
-               e.fireEvent('on' + na, ev);
-               return;
-       }
</del><ins>+                        if (ev.initUIEvent)
+                               ev.initUIEvent(na, true, true, window, 1);
</ins><span class="cx"> 
</span><del>-       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);
-
</del><span class="cx">                   ev.keyCode = o.keyCode;
</span><span class="cx">                  ev.charCode = o.charCode;
</span><span class="cx">          }
</span><del>-       } else {
-               ev = document.createEvent('UIEvents');
</del><span class="cx"> 
</span><del>-               if (ev.initUIEvent)
-                       ev.initUIEvent(na, true, true, window, 1);
-
-               ev.keyCode = o.keyCode;
-               ev.charCode = o.charCode;
</del><ins>+                e.dispatchEvent(ev);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       e.dispatchEvent(ev);
-}
</del><ins>+        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);
+               }
</ins><span class="cx"> 
</span><del>-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);
-       }
</del><ins>+                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);
+               }
</ins><span class="cx"> 
</span><del>-       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);
</del><ins>+                return rng;
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       return rng;
-}
</del><ins>+        // 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;
</ins><span class="cx"> 
</span><del>-// 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;
</del><ins>+                function fakeEvent(target, type, evt) {
+                       editor.dom.fire(target, type, evt);
+               }
</ins><span class="cx"> 
</span><del>-       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);
</del><ins>+                // 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;
+                       }
</ins><span class="cx">           } else {
</span><del>-                       charCode = chr.charCodeAt(0);
-                       keyCode = charCode;
</del><ins>+                        evt = chr;
</ins><span class="cx">           }
</span><del>-       } else {
-               evt = chr;
-       }
</del><span class="cx"> 
</span><del>-       evt = evt || {keyCode: keyCode, charCode: charCode};
</del><ins>+                evt = evt || {keyCode: keyCode, charCode: charCode};
</ins><span class="cx"> 
</span><del>-       startElm = editor.selection.getStart();
-       fakeEvent(startElm, 'keydown', evt);
-       fakeEvent(startElm, 'keypress', evt);
</del><ins>+                startElm = editor.selection.getStart();
+               fakeEvent(startElm, 'keydown', evt);
+               fakeEvent(startElm, 'keypress', evt);
</ins><span class="cx"> 
</span><del>-       if (!evt.isDefaultPrevented()) {
-               if (keyCode == 8) {
-                       if (editor.getDoc().selection) {
-                               rng = editor.getDoc().selection.createRange();
</del><ins>+                if (!evt.isDefaultPrevented()) {
+                       if (keyCode == 8) {
+                               if (editor.getDoc().selection) {
+                                       rng = editor.getDoc().selection.createRange();
</ins><span class="cx"> 
</span><del>-                               if (rng.text.length === 0) {
-                                       rng.moveStart('character', -1);
-                                       rng.select();
-                               }
</del><ins>+                                        if (rng.text.length === 0) {
+                                               rng.moveStart('character', -1);
+                                               rng.select();
+                                       }
</ins><span class="cx"> 
</span><del>-                               rng.execCommand('Delete', false, null);
-                       } else {
-                               rng = editor.selection.getRng();
</del><ins>+                                        rng.execCommand('Delete', false, null);
+                               } else {
+                                       rng = editor.selection.getRng();
</ins><span class="cx"> 
</span><del>-                               if (rng.startContainer.nodeType == 1 && rng.collapsed) {
-                                       var nodes = rng.startContainer.childNodes, lastNode = nodes[nodes.length - 1];
</del><ins>+                                        if (rng.startContainer.nodeType == 1 && rng.collapsed) {
+                                               var nodes = rng.startContainer.childNodes, lastNode = nodes[nodes.length - 1];
</ins><span class="cx"> 
</span><del>-                                       // 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);
</del><ins>+                                                // 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);
+                                               }
</ins><span class="cx">                                   }
</span><ins>+
+                                       editor.getDoc().execCommand('Delete', false, null);
</ins><span class="cx">                           }
</span><ins>+                       } else if (typeof(chr) == 'string') {
+                               rng = editor.selection.getRng(true);
</ins><span class="cx"> 
</span><del>-                               editor.getDoc().execCommand('Delete', false, null);
</del><ins>+                                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));
+                               }
</ins><span class="cx">                   }
</span><del>-               } else if (typeof(chr) == 'string') {
-                       rng = editor.selection.getRng(true);
</del><ins>+                }
</ins><span class="cx"> 
</span><del>-                       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));
-                       }
-               }
</del><ins>+                fakeEvent(startElm, 'keyup', evt);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       fakeEvent(startElm, 'keyup', evt);
-}
</del><ins>+        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, '');
+               html = html.replace(/ style="([^"]+)"/gi, function(val1, val2) {
+                       val2 = val2.replace(/;$/, '');
+                       return ' style="' + val2.replace(/\:([^ ])/g, ': $1') + ';"';
+               });
</ins><span class="cx"> 
</span><del>-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, '');
</del><ins>+                return html;
+       }
</ins><span class="cx"> 
</span><del>-       return html;
-}
</del><ins>+        function normalizeHtml(html) {
+               var writer = new tinymce.html.Writer();
</ins><span class="cx"> 
</span><del>-function normalizeHtml(html) {
-       var writer = new tinymce.html.Writer();
</del><ins>+                new tinymce.html.SaxParser({
+                       validate: false,
+                       comment: writer.comment,
+                       cdata: writer.cdata,
+                       text: writer.text,
+                       end: writer.end,
+                       pi: writer.pi,
+                       doctype: writer.doctype,
</ins><span class="cx"> 
</span><del>-       new tinymce.html.SaxParser({
-               validate: false,
-               comment: writer.comment,
-               cdata: writer.cdata,
-               text: writer.text,
-               end: writer.end,
-               pi: writer.pi,
-               doctype: writer.doctype,
</del><ins>+                        start: function(name, attrs, empty) {
+                               attrs.sort(function(a, b) {
+                                       if (a.name === b.name) {
+                                               return 0;
+                                       }
</ins><span class="cx"> 
</span><del>-               start: function(name, attrs, empty) {
-                       attrs.sort(function(a, b) {
-                               if (a.name === b.name) {
-                                       return 0;
-                               }
</del><ins>+                                        return a.name > b.name ? 1 : -1;
+                               });
</ins><span class="cx"> 
</span><del>-                               return a.name > b.name ? 1 : -1;
-                       });
</del><ins>+                                writer.start(name, attrs, empty);
+                       }
+               }).parse(html);
</ins><span class="cx"> 
</span><del>-                       writer.start(name, attrs, empty);
</del><ins>+                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();
</ins><span class="cx">           }
</span><del>-       }).parse(html);
</del><span class="cx"> 
</span><del>-       return writer.getContent();
-}
</del><ins>+                outerRect = document.getElementById('view').getBoundingClientRect();
</ins><span class="cx"> 
</span><del>-/**
- * Measures the x, y, w, h of the specified element/control relative to the view element.
- */
-function rect(ctrl) {
-       var outerRect, innerRect;
</del><ins>+                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)
+               ];
+       }
</ins><span class="cx"> 
</span><del>-       if (ctrl.nodeType) {
-               innerRect = ctrl.getBoundingClientRect();
-       } else {
-               innerRect = ctrl.getEl().getBoundingClientRect();
</del><ins>+        function size(ctrl) {
+               return rect(ctrl).slice(2);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       outerRect = document.getElementById('view').getBoundingClientRect();
</del><ins>+        function resetScroll(elm) {
+               elm.scrollTop = 0;
+               elm.scrollLeft = 0;
+       }
</ins><span class="cx"> 
</span><del>-       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)
-       ];
-}
</del><ins>+        // Needed since fonts render differently on different platforms
+       function nearlyEqualRects(rect1, rect2, diff) {
+               diff = diff || 1;
</ins><span class="cx"> 
</span><del>-function size(ctrl) {
-       return rect(ctrl).slice(2);
-}
</del><ins>+                for (var i = 0; i < 4; i++) {
+                       if (Math.abs(rect1[i] - rect2[i]) > diff) {
+                               deepEqual(rect1, rect2);
+                               return;
+                       }
+               }
</ins><span class="cx"> 
</span><del>-function resetScroll(elm) {
-       elm.scrollTop = 0;
-       elm.scrollLeft = 0;
-}
</del><ins>+                ok(true);
+       }
</ins><span class="cx"> 
</span><del>-// Needed since fonts render differently on different platforms
-function nearlyEqualRects(rect1, rect2, diff) {
-       diff = diff || 1;
</del><ins>+        function getFontmostWindow() {
+               return editor.windowManager.windows[editor.windowManager.windows.length - 1];
+       }
</ins><span class="cx"> 
</span><del>-       for (var i = 0; i < 4; i++) {
-               if (Math.abs(rect1[i] - rect2[i]) > diff) {
-                       deepEqual(rect1, rect2);
-                       return;
-               }
</del><ins>+        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);
</ins><span class="cx">   }
</span><span class="cx"> 
</span><del>-       ok(true);
-}
</del><ins>+        function pressEnter(evt) {
+               var dom = editor.dom, target = editor.selection.getNode();
+
+               evt = tinymce.extend({keyCode: 13}, evt);
+
+               dom.fire(target, 'keydown', evt);
+               dom.fire(target, 'keypress', evt);
+               dom.fire(target, 'keyup', evt);
+       }
+
+       function trimBrsOnIE(html) {
+               return html.replace(/<br[^>]*>/gi, '');
+       }
+
+       window.Utils = {
+               fontFace: fontFace,
+               findContainer: findContainer,
+               setSelection: setSelection,
+               trimContent: trimContent,
+               fakeKeyEvent: fakeKeyEvent,
+               normalizeRng: normalizeRng,
+               type: type,
+               cleanHtml: cleanHtml,
+               normalizeHtml: normalizeHtml,
+               rect: rect,
+               size: size,
+               resetScroll: resetScroll,
+               nearlyEqualRects: nearlyEqualRects,
+               getFontmostWindow: getFontmostWindow,
+               pressArrowKey: pressArrowKey,
+               pressEnter: pressEnter,
+               trimBrsOnIE: trimBrsOnIE
+       };
+})();
</ins></span></pre></div>
<a id="trunktestsquniteditorpluginsautolinkhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/autolink.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/autolink.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/autolink.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,170 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsautosavehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/autosave.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/autosave.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/autosave.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,104 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsautosavejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/autosave.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/autosave.js                             (rev 0)
+++ trunk/tests/qunit/editor/plugins/autosave.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+module("tinymce.plugins.Autosave", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: 'autosave',
+                       autosave_ask_before_unload: false,
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               editor.plugins.autosave.removeDraft();
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/autosave.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsfullpagehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/fullpage.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/fullpage.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/fullpage.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,154 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsfullpagejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/fullpage.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/fullpage.js                             (rev 0)
+++ trunk/tests/qunit/editor/plugins/fullpage.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+module("tinymce.plugins.Fullpage", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       plugins: "fullpage",
+                       add_unload_trigger: false,
+                       skin: 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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       },
+
+       teardown: function() {
+               editor.getBody().dir = 'ltr';
+       }
+});
+
+test('Keep header/footer intact', function() {
+       expect(2);
+
+       function normalizeHTML(html) {
+               return html.replace(/\s/g, '');
+       }
+
+       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('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('add/remove stylesheets', function() {
+       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;
+                       }
+               }
+       }
+
+       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"));
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/fullpage.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsjquery_pluginhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/jquery_plugin.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/jquery_plugin.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/jquery_plugin.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,126 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsjquery_pluginjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/jquery_plugin.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/jquery_plugin.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/jquery_plugin.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+module("tinymce.plugins.jQuery", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = (
+                       '<textarea id="elm1"></textarea>' +
+                       '<textarea id="elm2"></textarea>' +
+                       '<textarea id="elm3">Textarea</textarea>'
+               );
+
+               QUnit.stop();
+
+               $(function() {
+                       $('#elm1,#elm2').tinymce({
+                               plugins: [
+                                       "pagebreak,layer,table,save,emoticons,insertdatetime,preview,media,searchreplace",
+                                       "print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,template"
+                               ],
+
+                               init_instance_callback: function() {
+                                       var ed1 = tinymce.get('elm1'), ed2 = tinymce.get('elm2');
+
+                                       // When both editors are initialized
+                                       if (ed1 && ed1.initialized && ed2 && ed2.initialized) {
+                                               QUnit.start();
+                                       }
+                               }
+                       });
+               });
+       }
+});
+
+test("Get editor instance", function() {
+       equal($('#elm1').tinymce().id, 'elm1');
+       equal($('#elm2').tinymce().id, 'elm2');
+       equal($('#elm3').tinymce(), null);
+});
+
+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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/jquery_plugin.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginslegacyoutputhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/legacyoutput.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/legacyoutput.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/legacyoutput.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,130 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginslegacyoutputjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/legacyoutput.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/legacyoutput.js                         (rev 0)
+++ trunk/tests/qunit/editor/plugins/legacyoutput.js    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+module("tinymce.plugins.Legacyoutput", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: 'legacyoutput',
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+test("Font color", function() {
+       editor.setContent('<p>text</p>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('bold');
+       equal(editor.getContent(), '<p><b>text</b></p>');
+});
+
+test("Italic", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('italic');
+       equal(editor.getContent(), '<p><i>text</i></p>');
+});
+
+test("Underline", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('underline');
+       equal(editor.getContent(), '<p><u>text</u></p>');
+});
+
+test("Strikethrough", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('strikethrough');
+       equal(editor.getContent(), '<p><strike>text</strike></p>');
+});
+
+test("Justifyleft", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('justifyleft');
+       equal(editor.getContent(), '<p align="left">text</p>');
+});
+
+test("Justifycenter", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('justifycenter');
+       equal(editor.getContent(), '<p align="center">text</p>');
+});
+
+test("Justifyright", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('justifyright');
+       equal(editor.getContent(), '<p align="right">text</p>');
+});
+
+test("Justifyfull", function() {
+       editor.setContent('<p>text</p>');
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.execCommand('justifyfull');
+       equal(editor.getContent(), '<p align="justify">text</p>');
+});
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/legacyoutput.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginslistshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/lists.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/lists.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/lists.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,1770 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Unit tests for lists 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, inlineEditor, rng;
-
-QUnit.config.reorder = false;
-QUnit.config.autostart = false;
-
-module("tinymce.Lists", {
-       autostart: false,
-       setup: function() {
-               editor.settings.forced_root_block = 'p';
-       }
-});
-
-function trimBrs(html) {
-       return html.toLowerCase().replace(/<br[^>]*>|[\r\n]+/gi, '');
-}
-
-function execCommand(cmd) {
-       // Make sure we execute custom execCommands not browser commands
-       var cmdItem = editor.execCommands[cmd];
-       return cmdItem.func.call(cmdItem.scope, false, null);
-}
-
-test('Apply UL list to single P', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p>a</p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), '<ul><li>a</li></ul>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply UL list to single empty P', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p><br></p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(trimBrs(editor.getContent({format: 'raw'})), '<ul><li></li></ul>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply UL list to multiple Ps', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p>a</p>' +
-               '<p>b</p>' +
-               '<p>c</p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0, 'p:last', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply OL list to single P', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p>a</p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0);
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), '<ol><li>a</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply OL list to single empty P', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p><br></p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0);
-       execCommand('InsertOrderedList');
-
-       equal(trimBrs(editor.getContent({format: 'raw'})), '<ol><li></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply OL list to multiple Ps', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<p>a</p>' +
-               '<p>b</p>' +
-               '<p>c</p>'
-       );
-
-       editor.focus();
-       setSelection('p', 0, 'p:last', 0);
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply OL to UL list', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 0, 'li:last', 0);
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply OL to UL list with collapsed selection', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)');
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL to OL list', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li', 0, 'li:last', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL to OL list collapsed selection', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL to P and merge with adjacent lists', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>' +
-               '<p>b</p>' +
-               '<ul>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('p', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL to OL and merge with adjacent lists', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>' +
-               '<ol><li>b</li></ol>' +
-               '<ul>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('ol li', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply OL to P and merge with adjacent lists', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-               '</ol>' +
-               '<p>b</p>' +
-               '<ol>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('p', 1);
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply OL to UL and merge with adjacent lists', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-               '</ol>' +
-               '<ul><li>b</li></ul>' +
-               '<ol>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ul li', 1);
-       execCommand('InsertOrderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL list to single text line', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               'a'
-       );
-
-       editor.focus();
-       setSelection('body', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), '<ul><li>a</li></ul>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply UL list to single text line with BR', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               'a<br>'
-       );
-
-       editor.focus();
-       setSelection('body', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), '<ul><li>a</li></ul>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Apply UL list to multiple lines separated by BR', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               'a<br>' +
-               'b<br>' +
-               'c'
-       );
-
-       editor.focus();
-       editor.execCommand('SelectAll');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL list to multiple lines separated by BR and with trailing BR', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               'a<br>' +
-               'b<br>' +
-               'c<br>'
-       );
-
-       editor.focus();
-       editor.execCommand('SelectAll');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'LI');
-});
-
-test('Apply UL list to multiple formatted lines separated by BR', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               '<strong>a</strong><br>' +
-               '<span>b</span><br>' +
-               '<em>c</em>'
-       );
-
-       editor.focus();
-       setSelection('strong', 0, 'em', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li><strong>a</strong></li>' +
-                       '<li><span>b</span></li>' +
-                       '<li><em>c</em></li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getStart().nodeName, 'STRONG');
-       equal(editor.selection.getEnd().nodeName, tinymce.Env.ie && tinymce.Env.ie < 9 ? 'LI' : 'EM'); // Old IE will return the end LI not a big deal
-});
-
-test('Apply UL list to br line and text block line', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.setContent(
-               'a' +
-               '<p>b</p>'
-       );
-
-       var rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild, 0);
-       rng.setEnd(editor.getBody().lastChild.firstChild, 1);
-       editor.selection.setRng(rng);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getStart().nodeName, 'LI');
-       equal(editor.selection.getEnd().nodeName, 'LI');
-});
-
-test('Apply UL list to text block line and br line', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               '<p>a</p>' +
-               'b'
-       );
-
-       editor.focus();
-       var rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().lastChild, 1);
-       editor.selection.setRng(rng);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getStart().nodeName, 'LI');
-       equal(editor.selection.getEnd().nodeName, 'LI');
-});
-
-test('Apply UL list to all BR lines (SelectAll)', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = (
-               'a<br>' +
-               'b<br>' +
-               'c<br>'
-       );
-
-       editor.focus();
-       editor.execCommand('SelectAll');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-});
-
-test('Apply UL list to all P lines (SelectAll)', function() {
-       editor.getBody().innerHTML = (
-               '<p>a</p>' +
-               '<p>b</p>' +
-               '<p>c</p>'
-       );
-
-       editor.focus();
-       editor.execCommand('SelectAll');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-});
-
-// Remove
-
-test('Remove UL at single LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<p>a</p>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL at start LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<p>a</p>' +
-               '<ul>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL at start empty LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li><br></li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li');
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<p>\u00a0</p>' +
-               '<ul>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Remove UL at middle LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>' +
-               '<p>b</p>' +
-               '<ul>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL at middle empty LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li><br></li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>' +
-               '<p>\u00a0</p>' +
-               '<ul>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Remove UL at end LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:last', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>' +
-               '<p>c</p>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL at end empty LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li><br></li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:last', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>' +
-               '<p>\u00a0</p>'
-       );
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Remove UL at middle LI inside parent OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ul>' +
-                               '<li>b</li>' +
-                               '<li>c</li>' +
-                               '<li>d</li>' +
-                       '</ul>' +
-                       '<li>e</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ul li:nth-child(2)', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ul>' +
-                               '<li>b</li>' +
-                       '</ul>' +
-               '</ol>' +
-               '<p>c</p>' +
-               '<ol>' +
-                       '<ul>' +
-                               '<li>d</li>' +
-                       '</ul>' +
-                       '<li>e</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL at middle LI inside parent OL (html5)', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-                       '<li>e</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ul li:nth-child(2)', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ol>' +
-               '<p>c</p>' +
-               '<ol>' +
-                       '<li>' +
-                               '<ul>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-                       '<li>e</li>' +
-               '</ol>'
-       );
-       equal(editor.selection.getStart().nodeName, 'P');
-});
-
-test('Remove UL with single LI in BR mode', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               'a'
-       );
-       equal(editor.selection.getStart().nodeName, 'BODY');
-});
-
-test('Remove UL with multiple LI in BR mode', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:first', 1, 'li:last', 1);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               'a<br />' +
-               'b'
-       );
-       equal(editor.selection.getStart().nodeName, 'BODY');
-});
-
-test('Remove empty UL between two textblocks', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<div>a</div>' +
-               '<ul>' +
-                       '<li></li>' +
-               '</ul>' +
-               '<div>b</div>'
-       );
-
-       editor.focus();
-       setSelection('li:first', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<div>a</div>' +
-               '<p>\u00a0</p>' +
-               '<div>b</div>'
-       );
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Remove empty UL between two textblocks in BR mode', function() {
-       editor.settings.forced_root_block = false;
-
-       editor.getBody().innerHTML = trimBrs(
-               '<div>a</div>' +
-               '<ul>' +
-                       '<li></li>' +
-               '</ul>' +
-               '<div>b</div>'
-       );
-
-       editor.focus();
-       setSelection('li:first', 0);
-       execCommand('InsertUnorderedList');
-
-       equal(editor.getContent(), 
-               '<div>a</div>' +
-               '<br />' +
-               '<div>b</div>'
-       );
-       equal(editor.selection.getStart().nodeName, 'BR');
-});
-
-// Outdent
-
-test('Outdent inside LI in beginning of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li li', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b' +
-                               '<ol>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside LI in middle of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                                       '<li>d</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li li:nth-child(2)', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li>c' +
-                               '<ol>' +
-                                       '<li>d</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside LI in end of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li li:last', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-// Nested lists in OL elements
-
-test('Outdent inside LI in beginning of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                               '<li>c</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<ol>' +
-                               '<li>c</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside LI in middle of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                               '<li>c</li>' +
-                               '<li>d</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li:nth-child(2)', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                       '</ol>' +
-                       '<li>c</li>' +
-                       '<ol>' +
-                               '<li>d</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside first/last LI in inner OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>1' +
-                       '<ol>' +
-                               '<li>2</li>' +
-                               '<li>3</li>' +
-                       '</ol>' +
-                       '</li>' +
-                       '<li>4</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li:nth-child(1)', 0, 'ol ol li:nth-child(2)', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>1</li>' +
-                       '<li>2</li>' +
-                       '<li>3</li>' +
-                       '<li>4</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getRng(true).startContainer.nodeValue, '2');
-       equal(editor.selection.getRng(true).endContainer.nodeValue, '3');
-});
-
-test('Outdent inside first LI in inner OL where OL is single child of parent LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li:first', 0);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b' +
-                               '<ol>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside LI in end of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                               '<li>c</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li:last', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                       '</ol>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent inside only child LI in OL in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('ol ol li', 0);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Outdent multiple LI in OL and nested OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li', 0, 'li li', 1);
-       execCommand('Outdent');
-
-       equal(editor.getContent(), 
-               '<p>a</p>' +
-               '<ol>' +
-                       '<li>b</li>' +
-               '</ol>'
-       );
-});
-
-// Indent
-
-test('Indent single LI in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li', 0);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent middle LI in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 0);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent last LI in OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li:last', 0);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent last LI to same level as middle LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li>c</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li:last', 1);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent first LI and nested LI OL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       editor.focus();
-       setSelection('li', 0, 'li li', 0);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent second LI to same level as nested LI', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b' +
-                               '<ul>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 0);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Indent second LI to same level as nested LI 2', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                               '</ul>' +
-                       '</li>' +
-                       '<li>cd' +
-                               '<ul>' +
-                                       '<li>e</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 1);
-       execCommand('Indent');
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>cd</li>' +
-                                       '<li>e</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-// Backspace
-
-test('Backspace at beginning of single LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<p>a</p>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Backspace at beginning of first LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(),
-               '<p>a</p>' +
-               '<ul>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Backspace at beginning of middle LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>ab</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Backspace at beginning of start LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>ab' +
-                               '<ul>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Backspace at beginning of middle LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li:nth-child(2)', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>bc</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Backspace at beginning of single LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<p>a</p>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Backspace at beginning of first LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(),
-               '<p>a</p>' +
-               '<ul>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Backspace at beginning of middle LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>ab</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Backspace at beginning of start LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>ab' +
-                               '<ul>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Backspace at beginning of middle LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li:nth-child(2)', 0);
-       editor.plugins.lists.backspaceDelete();
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>bc</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-// Delete
-
-test('Delete at end of single LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 1);
-       editor.plugins.lists.backspaceDelete(true);
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Delete at end of first LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li', 1);
-       editor.plugins.lists.backspaceDelete(true);
-
-       equal(editor.getContent(),
-               '<ul>' +
-                       '<li>ab</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Delete at end of middle LI in UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>b</li>' +
-                       '<li>c</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li:nth-child(2)', 1);
-       editor.plugins.lists.backspaceDelete(true);
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a</li>' +
-                       '<li>bc</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Delete at end of start LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li', 1);
-       editor.plugins.lists.backspaceDelete(true);
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>bc</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Delete at end of middle LI in UL inside UL', function() {
-       editor.getBody().innerHTML = trimBrs(
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                                       '<li>d</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       editor.focus();
-       setSelection('li li:nth-child(2)', 1);
-       editor.plugins.lists.backspaceDelete(true);
-
-       equal(editor.getContent(), 
-               '<ul>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>cd</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ul>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Remove UL in inline body element contained in LI', function() {
-       inlineEditor.setContent('<ul><li>a</li></ul>');
-       inlineEditor.focus();
-       inlineEditor.execCommand('InsertUnorderedList');
-       equal(inlineEditor.getContent(), '<p>a</p>');
-});
-
-test('Backspace in LI in UL in inline body element contained within LI', function() {
-       inlineEditor.setContent('<ul><li>a</li></ul>');
-       inlineEditor.focus();
-       inlineEditor.selection.select(inlineEditor.getBody(), true);
-       inlineEditor.selection.collapse(true);
-       inlineEditor.plugins.lists.backspaceDelete();
-       equal(inlineEditor.getContent(), '<p>a</p>');
-});
-
-function wait() {
-       if (editor && inlineEditor) {
-               if (!QUnit.started) {
-                       QUnit.start();
-                       QUnit.started = true;
-               }
-       } else {
-               setTimeout(wait, 0);
-       }
-}
-
-tinymce.init({
-       mode: "exact",
-       plugins: "lists",
-       elements: "elm1",
-       add_unload_trigger: false,
-       indent: false,
-       schema: 'html5',
-       entities: 'raw',
-       valid_elements: 'li,ol,ul,em,strong,span,#p,div,br',
-       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,position,top,left'
-       },
-       disable_nodechange: true,
-       init_instance_callback: function(ed) {
-               editor = ed;
-               wait();
-       }
-});
-
-tinymce.init({
-       selector: '#elm2',
-       inline: true,
-       add_unload_trigger: false,
-       plugins: "lists",
-       init_instance_callback: function(ed) {
-               inlineEditor = ed;
-               wait();
-       }
-});
-</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>
-
-       <ul><li><div id="elm2"></div></li></ul>
-       <a href="javascript:;" onclick="alert(tinymce.get('elm2').getContent({format: 'raw'}));return false;">[Get raw]</a>
-</body>
-</html>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginslistsjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/lists.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/lists.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/lists.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,1745 @@
</span><ins>+module("tinymce.plugins.Lists", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div>';
+               QUnit.stop();
+
+               function wait() {
+                       if (editor && inlineEditor) {
+                               if (!QUnit.started) {
+                                       QUnit.start();
+                                       QUnit.started = true;
+                               }
+                       } else {
+                               setTimeout(wait, 0);
+                       }
+               }
+
+               tinymce.init({
+                       selector: '#elm1',
+                       plugins: "lists",
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       schema: 'html5',
+                       entities: 'raw',
+                       valid_elements: 'li,ol,ul,em,strong,span,#p,div,br',
+                       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,position,top,left'
+                       },
+                       disable_nodechange: true,
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               wait();
+                       }
+               });
+
+               tinymce.init({
+                       selector: '#elm2',
+                       inline: true,
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: "lists",
+                       disable_nodechange: true,
+                       init_instance_callback: function(ed) {
+                               window.inlineEditor = ed;
+                               wait();
+                       }
+               });
+       },
+
+       teardown: function() {
+               editor.settings.forced_root_block = 'p';
+       }
+});
+
+function trimBrs(html) {
+       return html.toLowerCase().replace(/<br[^>]*>|[\r\n]+/gi, '');
+}
+
+function execCommand(cmd) {
+       // Make sure we execute custom execCommands not browser commands
+       var cmdItem = editor.execCommands[cmd];
+       return cmdItem.func.call(cmdItem.scope, false, null);
+}
+
+test('Apply UL list to single P', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p>a</p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),'<ul><li>a</li></ul>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply UL list to single empty P', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p><br></p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(trimBrs(editor.getContent({format: 'raw'})), '<ul><li></li></ul>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply UL list to multiple Ps', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p>a</p>' +
+               '<p>b</p>' +
+               '<p>c</p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0, 'p:last', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply OL list to single P', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p>a</p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0);
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),'<ol><li>a</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply OL list to single empty P', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p><br></p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0);
+       execCommand('InsertOrderedList');
+
+       equal(trimBrs(editor.getContent({format: 'raw'})), '<ol><li></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply OL list to multiple Ps', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<p>a</p>' +
+               '<p>b</p>' +
+               '<p>c</p>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 0, 'p:last', 0);
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply OL to UL list', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0, 'li:last', 0);
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply OL to UL list with collapsed selection', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)');
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL to OL list', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0, 'li:last', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL to OL list collapsed selection', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL to P and merge with adjacent lists', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>' +
+               '<p>b</p>' +
+               '<ul>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL to OL and merge with adjacent lists', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>' +
+               '<ol><li>b</li></ol>' +
+               '<ul>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol li', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply OL to P and merge with adjacent lists', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+               '</ol>' +
+               '<p>b</p>' +
+               '<ol>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('p', 1);
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply OL to UL and merge with adjacent lists', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+               '</ol>' +
+               '<ul><li>b</li></ul>' +
+               '<ol>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ul li', 1);
+       execCommand('InsertOrderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL list to single text line', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               'a'
+       );
+
+       editor.focus();
+       Utils.setSelection('body', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),'<ul><li>a</li></ul>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply UL list to single text line with BR', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               'a<br>'
+       );
+
+       editor.focus();
+       Utils.setSelection('body', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),'<ul><li>a</li></ul>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Apply UL list to multiple lines separated by BR', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               'a<br>' +
+               'b<br>' +
+               'c'
+       );
+
+       editor.focus();
+       editor.execCommand('SelectAll');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL list to multiple lines separated by BR and with trailing BR', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               'a<br>' +
+               'b<br>' +
+               'c<br>'
+       );
+
+       editor.focus();
+       editor.execCommand('SelectAll');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'LI');
+});
+
+test('Apply UL list to multiple formatted lines separated by BR', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               '<strong>a</strong><br>' +
+               '<span>b</span><br>' +
+               '<em>c</em>'
+       );
+
+       editor.focus();
+       Utils.setSelection('strong', 0, 'em', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li><strong>a</strong></li>' +
+                       '<li><span>b</span></li>' +
+                       '<li><em>c</em></li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getStart().nodeName, 'STRONG');
+       equal(editor.selection.getEnd().nodeName, tinymce.Env.ie && tinymce.Env.ie < 9 ? 'LI' : 'EM'); // Old IE will return the end LI not a big deal
+});
+
+test('Apply UL list to br line and text block line', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.setContent(
+               'a' +
+               '<p>b</p>'
+       );
+
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild, 0);
+       rng.setEnd(editor.getBody().lastChild.firstChild, 1);
+       editor.selection.setRng(rng);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getStart().nodeName, 'LI');
+       equal(editor.selection.getEnd().nodeName, 'LI');
+});
+
+test('Apply UL list to text block line and br line', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               '<p>a</p>' +
+               'b'
+       );
+
+       editor.focus();
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().lastChild, 1);
+       editor.selection.setRng(rng);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getStart().nodeName, 'LI');
+       equal(editor.selection.getEnd().nodeName, 'LI');
+});
+
+test('Apply UL list to all BR lines (SelectAll)', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = (
+               'a<br>' +
+               'b<br>' +
+               'c<br>'
+       );
+
+       editor.focus();
+       editor.execCommand('SelectAll');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+});
+
+test('Apply UL list to all P lines (SelectAll)', function() {
+       editor.getBody().innerHTML = (
+               '<p>a</p>' +
+               '<p>b</p>' +
+               '<p>c</p>'
+       );
+
+       editor.focus();
+       editor.execCommand('SelectAll');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+});
+
+// Remove
+
+test('Remove UL at single LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<p>a</p>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL at start LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<p>a</p>' +
+               '<ul>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL at start empty LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li><br></li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li');
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<p>\u00a0</p>' +
+               '<ul>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Remove UL at middle LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>' +
+               '<p>b</p>' +
+               '<ul>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL at middle empty LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li><br></li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>' +
+               '<p>\u00a0</p>' +
+               '<ul>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Remove UL at end LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:last', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>' +
+               '<p>c</p>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL at end empty LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li><br></li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:last', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>' +
+               '<p>\u00a0</p>'
+       );
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Remove UL at middle LI inside parent OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ul>' +
+                               '<li>b</li>' +
+                               '<li>c</li>' +
+                               '<li>d</li>' +
+                       '</ul>' +
+                       '<li>e</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ul li:nth-child(2)', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ul>' +
+                               '<li>b</li>' +
+                       '</ul>' +
+               '</ol>' +
+               '<p>c</p>' +
+               '<ol>' +
+                       '<ul>' +
+                               '<li>d</li>' +
+                       '</ul>' +
+                       '<li>e</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL at middle LI inside parent OL (html5)', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+                       '<li>e</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ul li:nth-child(2)', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ol>' +
+               '<p>c</p>' +
+               '<ol>' +
+                       '<li>' +
+                               '<ul>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+                       '<li>e</li>' +
+               '</ol>'
+       );
+       equal(editor.selection.getStart().nodeName, 'P');
+});
+
+test('Remove UL with single LI in BR mode', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               'a'
+       );
+       equal(editor.selection.getStart().nodeName, 'BODY');
+});
+
+test('Remove UL with multiple LI in BR mode', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:first', 1, 'li:last', 1);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               'a<br />' +
+               'b'
+       );
+       equal(editor.selection.getStart().nodeName, 'BODY');
+});
+
+test('Remove empty UL between two textblocks', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<div>a</div>' +
+               '<ul>' +
+                       '<li></li>' +
+               '</ul>' +
+               '<div>b</div>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:first', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<div>a</div>' +
+               '<p>\u00a0</p>' +
+               '<div>b</div>'
+       );
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Remove empty UL between two textblocks in BR mode', function() {
+       editor.settings.forced_root_block = false;
+
+       editor.getBody().innerHTML = trimBrs(
+               '<div>a</div>' +
+               '<ul>' +
+                       '<li></li>' +
+               '</ul>' +
+               '<div>b</div>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:first', 0);
+       execCommand('InsertUnorderedList');
+
+       equal(editor.getContent(),
+               '<div>a</div>' +
+               '<br />' +
+               '<div>b</div>'
+       );
+       equal(editor.selection.getStart().nodeName, 'BR');
+});
+
+// Outdent
+
+test('Outdent inside LI in beginning of OL in LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b' +
+                               '<ol>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside LI in middle of OL in LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                                       '<li>d</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li:nth-child(2)', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li>c' +
+                               '<ol>' +
+                                       '<li>d</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside LI in end of OL in LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li:last', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+// Nested lists in OL elements
+
+test('Outdent inside LI in beginning of OL in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                               '<li>c</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<ol>' +
+                               '<li>c</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside LI in middle of OL in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                               '<li>c</li>' +
+                               '<li>d</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li:nth-child(2)', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                       '</ol>' +
+                       '<li>c</li>' +
+                       '<ol>' +
+                               '<li>d</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside first/last LI in inner OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>1' +
+                       '<ol>' +
+                               '<li>2</li>' +
+                               '<li>3</li>' +
+                       '</ol>' +
+                       '</li>' +
+                       '<li>4</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li:nth-child(1)', 0, 'ol ol li:nth-child(2)', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>1</li>' +
+                       '<li>2</li>' +
+                       '<li>3</li>' +
+                       '<li>4</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getRng(true).startContainer.nodeValue, '2');
+       equal(editor.selection.getRng(true).endContainer.nodeValue, '3');
+});
+
+test('Outdent inside first LI in inner OL where OL is single child of parent LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li:first', 0);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b' +
+                               '<ol>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside LI in end of OL in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                               '<li>c</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li:last', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                       '</ol>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent inside only child LI in OL in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('ol ol li', 0);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Outdent multiple LI in OL and nested OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0, 'li li', 1);
+       execCommand('Outdent');
+
+       equal(editor.getContent(),
+               '<p>a</p>' +
+               '<ol>' +
+                       '<li>b</li>' +
+               '</ol>'
+       );
+});
+
+// Indent
+
+test('Indent single LI in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent middle LI in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 0);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent last LI in OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:last', 0);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent last LI to same level as middle LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li>c</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:last', 1);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent first LI and nested LI OL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0, 'li li', 0);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent second LI to same level as nested LI', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b' +
+                               '<ul>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 0);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Indent second LI to same level as nested LI 2', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                               '</ul>' +
+                       '</li>' +
+                       '<li>cd' +
+                               '<ul>' +
+                                       '<li>e</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 1);
+       execCommand('Indent');
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>cd</li>' +
+                                       '<li>e</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+// Backspace
+
+test('Backspace at beginning of single LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<p>a</p>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Backspace at beginning of first LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<p>a</p>' +
+               '<ul>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Backspace at beginning of middle LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>ab</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Backspace at beginning of start LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>ab' +
+                               '<ul>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Backspace at beginning of middle LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li:nth-child(2)', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>bc</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Backspace at beginning of single LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<p>a</p>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Backspace at beginning of first LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<p>a</p>' +
+               '<ul>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Backspace at beginning of middle LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>ab</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Backspace at beginning of start LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>ab' +
+                               '<ul>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Backspace at beginning of middle LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li:nth-child(2)', 0);
+       editor.plugins.lists.backspaceDelete();
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>bc</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+// Delete
+
+test('Delete at end of single LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 1);
+       editor.plugins.lists.backspaceDelete(true);
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Delete at end of first LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li', 1);
+       editor.plugins.lists.backspaceDelete(true);
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>ab</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Delete at end of middle LI in UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>b</li>' +
+                       '<li>c</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li:nth-child(2)', 1);
+       editor.plugins.lists.backspaceDelete(true);
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a</li>' +
+                       '<li>bc</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Delete at end of start LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li', 1);
+       editor.plugins.lists.backspaceDelete(true);
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>bc</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Delete at end of middle LI in UL inside UL', function() {
+       editor.getBody().innerHTML = trimBrs(
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                                       '<li>d</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       editor.focus();
+       Utils.setSelection('li li:nth-child(2)', 1);
+       editor.plugins.lists.backspaceDelete(true);
+
+       equal(editor.getContent(),
+               '<ul>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>cd</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ul>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Remove UL in inline body element contained in LI', function() {
+       inlineEditor.setContent('<ul><li>a</li></ul>');
+       inlineEditor.focus();
+       inlineEditor.execCommand('InsertUnorderedList');
+       equal(inlineEditor.getContent(), '<p>a</p>');
+});
+
+test('Backspace in LI in UL in inline body element contained within LI', function() {
+       inlineEditor.setContent('<ul><li>a</li></ul>');
+       inlineEditor.focus();
+       inlineEditor.selection.select(inlineEditor.getBody(), true);
+       inlineEditor.selection.collapse(true);
+       inlineEditor.plugins.lists.backspaceDelete();
+       equal(inlineEditor.getContent(), '<p>a</p>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/lists.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsmediahtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/media.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/media.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/media.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,180 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsmediajs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/media.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/media.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/media.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,151 @@
</span><ins>+module("tinymce.plugins.Media", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: 'media',
+                       document_base_url: '/tinymce/tinymce/trunk/tests/',
+                       media_scripts: [
+                               {filter: 'http://media1.tinymce.com'},
+                               {filter: 'http://media2.tinymce.com', width: 100, height: 200}
+                       ],
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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>'
+       );
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/media.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsnoneditablehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/noneditable.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/noneditable.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/noneditable.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,237 +0,0 @@
</span><del>-<!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|codeb
 ase|*],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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsnoneditablejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/noneditable.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/noneditable.js                          (rev 0)
+++ trunk/tests/qunit/editor/plugins/noneditable.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,208 @@
</span><ins>+module("tinymce.plugins.Noneditable", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       noneditable_regexp: [/\{[^\}]+\}/g],
+                       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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+test('expand to noneditable (start)', function() {
+       editor.setContent('<p><span class="mceNonEditable">no</span>yes</p>');
+
+       var 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 = Utils.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>');
+
+       var 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 = Utils.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>');
+
+       var 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 = Utils.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>');
+
+       var 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');
+       Utils.type('X');
+       rng = Utils.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>');
+
+       var 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');
+       Utils.type('X');
+       rng = Utils.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>');
+
+       var 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');
+       Utils.type('X');
+       rng = Utils.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 rng = editor.dom.createRng();
+       rng.selectNode(editor.dom.select('span')[0]);
+       editor.selection.setRng(rng);
+
+       Utils.type({keyCode: 37});
+       rng = Utils.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 rng = editor.dom.createRng();
+       rng.selectNode(editor.dom.select('span')[0]);
+       editor.selection.setRng(rng);
+
+       Utils.type({keyCode: 39});
+       rng = Utils.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>');
+
+       var rng = editor.dom.createRng();
+       rng.selectNode(editor.dom.select('p')[1]);
+       editor.selection.setRng(rng);
+
+       Utils.type({keyCode: 37});
+       rng = Utils.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>');
+
+       var rng = editor.dom.createRng();
+       rng.selectNode(editor.dom.select('p')[1]);
+       editor.selection.setRng(rng);
+
+       Utils.type({keyCode: 39});
+       rng = Utils.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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/noneditable.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginspastehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/paste.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/paste.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/paste.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,440 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Unit tests for the Paste 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("Paste plugin", {
-       autostart: false
-});
-
-test("Paste simple text content", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p>1234</p>');
-       editor.focus();
-       rng.setStart(editor.getBody().firstChild.firstChild, 1);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: 'TEST'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1TEST4</p>');
-});
-
-test("Paste styled text content", function() {
-       var rng = editor.dom.createRng();
-
-       editor.settings.paste_remove_styles_if_webkit = false;
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 1);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<strong><em><span style="color: red;">TEST</span></em></strong>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1<strong><em><span style="color: red;">TEST</span></em></strong>4</p>');
-});
-
-test("Paste paragraph in paragraph", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 1);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p>TEST</p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1</p><p>TEST</p><p>4</p>');
-});
-
-test("Paste paragraphs in complex paragraph", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p><strong><em>1234</em></strong></p>');
-       rng.setStart(editor.dom.select('em,i')[0].firstChild, 1);
-       rng.setEnd(editor.dom.select('em,i')[0].firstChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p>TEST 1</p><p>TEST 2</p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p><strong><em>1</em></strong></p><p>TEST 1</p><p>TEST 2</p><p><strong><em>4</em></strong></p>');
-});
-
-test("Paste Word fake list", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature
 :0 268435456 0 0 -2147483648 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:
 yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-th
 eme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-
 US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-fam
 ily:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1742563504; mso-list-type:hybrid; mso-list-template-ids:-524928352 69009409 69009411 69009413 69009409 69009411 69009413 69009409 69009411 69009413;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:?; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso
 -style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <p class="MsoListParagraphCxSpFirst" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"&gt
 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 1</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 2</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;
 <span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 3</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--
 [endif]-->Item 4</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 5</p> <p class="MsoListParagraphCxSpLast" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: norm
 al; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 6</p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul>');
-
-       editor.settings.paste_retain_style_properties = 'border';
-       
-       rng = editor.dom.createRng();
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="ListStyle" style="margin-top:0cm;margin-right:0cm;margin-bottom:3.0pt;margin-left:18.0pt;mso-add-space:auto;text-align:justify;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 18.0pt"><span lang="DE" style="font-family:Verdana;mso-fareast-font-family:Verdana;mso-bidi-font-family:Verdana;color:black"><span style="mso-list:Ignore">\u25CF<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span lang="DE" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black">Item&nbsp; Spaces.<o:p></o:p></span></p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item&nbsp; Spaces.</li></ul>');
-
-       rng = editor.dom.createRng();
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="ListStyle" style="margin-left:36.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"><span lang="EN-US" style="color:black;mso-ansi-language:EN-US"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">Version 7.0</span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">:<o:p></o:p></span></p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ol><li>Version 7.0:</li></ol>');
-       editor.settings.paste_retain_style_properties = '';
-});
-
-test("Paste Word fake list before BR", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertContent', false, '<br>a');
-
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild, 0);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature
 :0 268435456 0 0 -2147483648 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:
 yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-th
 eme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-
 US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-fam
 ily:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1742563504; mso-list-type:hybrid; mso-list-template-ids:-524928352 69009409 69009411 69009413 69009409 69009411 69009413 69009409 69009411 69009413;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:?; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso
 -style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <p class="MsoListParagraphCxSpFirst" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"&gt
 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 1</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 2</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;
 <span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 3</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--
 [endif]-->Item 4</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 5</p> <p class="MsoListParagraphCxSpLast" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: norm
 al; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 6</p>'});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul><p><br />a</p>');
-});
-
-test("Paste list like paragraph and list", function() {
-       editor.setContent('');
-
-       editor.execCommand('mceInsertClipboardContent', false, {
-               content: '<p class=MsoNormal><span style=\'font-size:10.0pt;line-height:115%;font-family:"Trebuchet MS","sans-serif";color:#666666\'>A. X<o:p></o:p></span></p><p class=MsoListParagraph style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>1.<span style=\'font:7.0pt "Times New Roman"\'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><![endif]>Y</p>'
-       });
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>A. X</p><ol><li>Y</li></ol>');
-});
-
-test("Paste Word table", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('<p>1234</p>');
-       rng.setStart(editor.getBody().firstChild.firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
-       editor.selection.setRng(rng);
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm
 ; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Cali
 bri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34;
  mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri",&q
 uot;sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style>&
 lt;!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} table.MsoTableGrid {mso-style-name:"Table Grid"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-priority:59; mso-style-unhide:no; border:solid black 1.0pt; mso-border-themecolor:text1; mso-border-alt:solid black .5pt; mso-border-themecolor:text1; mso-padding-alt:0
 cm 5.4pt 0cm 5.4pt; mso-border-insideh:.5pt solid black; mso-border-insideh-themecolor:text1; mso-border-insidev:.5pt solid black; mso-border-insidev-themecolor:text1; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <table class="MsoTableGrid" style="border: medium none ; margin-left: 36pt; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0"> <tbody><tr style=""> <td style="border: 1pt solid black; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpFirst" style="margin: 0cm 0cm 0.0001pt; line-heigh
 t: normal;">Cell 1</p> </td> <td style="border-style: solid solid solid none; border-color: black black black -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpLast" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 2</p> </td> </tr> <tr style=""> <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpFirst" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 3</p> </td> <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium;
  padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpLast" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 4</p> </td> </tr> </tbody></table> <p class="MsoListParagraph"><o:p>&nbsp;</o:p></p>'});
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<table><tbody><tr><td width="307"><p>Cell 1</p></td><td width="307"><p>Cell 2</p></td></tr><tr><td width="307"><p>Cell 3</p></td><td width="307"><p>Cell 4</p></td></tr></tbody></table><p>&nbsp;</p>');
-});
-
-test("Paste Word without mso markings", function() {
-       editor.setContent('');
-       editor.execCommand('mceInsertClipboardContent', false, {
-               content: (
-                       '<font face="Times New Roman" size="3"></font>' +
-                       '<p style="margin: 0in 0in 10pt;">' +
-                       '<span style=\'line-height: 115%; font-family: "Comic Sans MS"; font-size: 22pt;\'>Comic Sans MS</span>' +
-                       '</p>' +
-                       '<font face="Times New Roman" size="3"></font>'
-               )
-       });
-
-       equal(trimContent(editor.getContent()), (
-               '<p>Comic Sans MS</p>'
-       ));
-});
-
-test("Paste Word links", function() {
-       editor.setContent('');
-       editor.execCommand('mceInsertClipboardContent', false, {
-               content: (
-                       '<p class="MsoNormal">' +
-                               '<a href="file:///C:/somelocation/filename.doc#_Toc238571849">1</a>' +
-                               '<a href="#_Toc238571849">2</a>' +
-                               '<a name="Toc238571849">3</a>' +
-                               '<a href="http://www.tinymce.com/someurl">4</a>' +
-                               '<a>5</a>' +
-                       '</p>'
-               )
-       });
-
-       equal(trimContent(editor.getContent()), (
-               '<p>' +
-                       '<a href="#_Toc238571849">1</a>' +
-                       '<a href="#_Toc238571849">2</a>' +
-                       '<a name="Toc238571849"></a>3' +
-                       '<a href="http://www.tinymce.com/someurl">4</a>' +
-                       '5' +
-               '</p>'
-       ));
-});
-
-test("Paste Word retain styles", function() {
-       var rng = editor.dom.createRng();
-
-       editor.settings.paste_retain_style_properties = 'color,background-color,font-family';
-
-       // Test color
-       editor.setContent('');
-       editor.execCommand('SelectAll');
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="color: #ff0000">Test</p>'});
-       equal(trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p style=\"color: #ff0000;\">Test</p>');
-
-       // Test background-color
-       editor.setContent('');
-       editor.execCommand('SelectAll');
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="background-color: #ff0000">Test</p>'});
-       equal(trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p style=\"background-color: #ff0000;\">Test</p>');
-
-       editor.settings.paste_retain_style_properties = '';
-});
-
-test("Paste part of list from IE", function() {
-       var rng = editor.dom.createRng();
-
-       editor.setContent('');
-       editor.execCommand('SelectAll');
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<li>item2</li><li>item3</li>'});
-       equal(trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<ul><li>item2</li><li>item3</li></ul>', 'List tags are inferred when pasting LI');
-});
-
-test("Disable default filters", function() {
-       var rng = editor.dom.createRng();
-
-       editor.settings.paste_enable_default_filters = false;
-
-       // Test color
-       editor.setContent('');
-       editor.execCommand('SelectAll');
-       
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="color: #ff0000;">Test</p>'});
-       equal(trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p class="MsoNormal" style="color: #ff0000;">Test</p>');
-
-       editor.settings.paste_enable_default_filters = true;
-});
-
-test('paste invalid content with spans on page', function() {
-       var startingContent = '<p>123 testing <span id="x">span later in document</span></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('mceInsertClipboardContent', false, {content: insertedContent});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), insertedContent + startingContent);
-});
-
-test('paste plain text with space', function() {
-       editor.setContent('<p>text</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('mceInsertClipboardContent', false, {text: ' a '});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t a xt</p>');
-});
-
-test('paste plain text with linefeeds', function() {
-       editor.setContent('<p>text</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('mceInsertClipboardContent', false, {text: 'a\nb\n\c\n'});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>ta<br />b<br />c<br />xt</p>');
-});
-
-test('paste plain text with double linefeeds', function() {
-       editor.setContent('<p>text</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('mceInsertClipboardContent', false, {text: 'a\n\nb\n\nc'});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t</p><p>a</p><p>b</p><p>c</p><p>xt</p>');
-});
-
-test('paste plain text with entities', function() {
-       editor.setContent('<p>text</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('mceInsertClipboardContent', false, {text: '< & >'});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t&lt; &amp; &gt;xt</p>');
-});
-
-test('paste plain text with paragraphs', function() {
-       editor.setContent('<p>text</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('mceInsertClipboardContent', false, {text: 'a\n<b>b</b>\n\nc'});
-
-       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t</p><p>a<br />&lt;b&gt;b&lt;/b&gt;</p><p>c</p><p>xt</p>');
-});
-
-test('paste data image with paste_data_images: false', function() {
-       editor.setContent('');
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<img src="data:image/png;base64,...">'});
-       equal(editor.getContent(), '');
-
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<img alt="alt" src="data:image/png;base64,...">'});
-       equal(editor.getContent(), '');
-});
-
-test('paste data image with paste_data_images: true', function() {
-       editor.settings.paste_data_images = true;
-
-       editor.setContent('');
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<img src="data:image/png;base64,...">'});
-
-       equal(editor.getContent(), '<p><img src="data:image/png;base64,..." alt="" /></p>');
-});
-
-test('paste pre process text (event)', function() {
-       function callback(e) {
-               e.content = 'PRE:' + e.content;
-       }
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.on('PastePreProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {text: 'b\n2'});
-       equal(editor.getContent(), '<p>PRE:b<br />2</p>');
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.off('PastePreProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {text: 'c'});
-       equal(editor.getContent(), '<p>c</p>');
-});
-
-test('paste pre process html (event)', function() {
-       function callback(e) {
-               e.content = 'PRE:' + e.content;
-       }
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.on('PastePreProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>b</em>'});
-       equal(editor.getContent(), '<p>PRE:<em>b</em></p>');
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.off('PastePreProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>c</em>'});
-       equal(editor.getContent(), '<p><em>c</em></p>');
-});
-
-test('paste post process (event)', function() {
-       function callback(e) {
-               e.node.innerHTML += ':POST';
-       }
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.on('PastePostProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>b</em>'});
-       equal(editor.getContent(), '<p><em>b</em>:POST</p>');
-
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.off('PastePostProcess', callback);
-       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>c</em>'});
-       equal(editor.getContent(), '<p><em>c</em></p>');
-});
-
-test('paste innerText of single P', function() {
-       editor.setContent('<p>a</p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a');
-});
-
-test('paste innerText of single P with whitespace wrapped content', function() {
-       editor.setContent('<p>   a   </p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a');
-});
-
-test('paste innerText of two P', function() {
-       editor.setContent('<p>a</p><p>b</p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\n\nb');
-});
-
-test('paste innerText of H1 and P', function() {
-       editor.setContent('<h1>a</h1><p>b</p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\nb');
-});
-
-test('paste innerText of P with BR', function() {
-       editor.setContent('<p>a<br>b</p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\nb');
-});
-
-test('paste innerText of P with VIDEO', function() {
-       editor.setContent('<p>a<video>b<br>c</video>d</p>');
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a d');
-});
-
-test('paste innerText of PRE', function() {
-       editor.getBody().innerHTML = '<pre>a\nb\n</pre>';
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML).replace(/\r\n/g, '\n'), 'a\nb\n');
-});
-
-test('paste innerText of textnode with whitespace', function() {
-       editor.getBody().innerHTML = '<pre> a </pre>';
-       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().firstChild.innerHTML), ' a ');
-});
-
-tinymce.init({
-       mode: "exact",
-       elements: "elm1",
-       add_unload_trigger: false,
-       plugins: 'paste',
-       setup: function(ed) {
-               ed.on('NodeChange', false);
-       },
-       init_instance_callback: function(ed) {
-               editor = ed;
-               QUnit.start();
-       }
-});
-</script>
-
-       <h1 id="qunit-header">Unit tests for the Paste 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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginspastejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/paste.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/paste.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/paste.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,403 @@
</span><ins>+module("tinymce.plugins.Paste", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: 'paste',
+                       setup: function(ed) {
+                               ed.on('NodeChange', false);
+                       },
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+test("Paste simple text content", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p>1234</p>');
+       editor.focus();
+       rng.setStart(editor.getBody().firstChild.firstChild, 1);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: 'TEST'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1TEST4</p>');
+});
+
+test("Paste styled text content", function() {
+       var rng = editor.dom.createRng();
+
+       editor.settings.paste_remove_styles_if_webkit = false;
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 1);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<strong><em><span style="color: red;">TEST</span></em></strong>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1<strong><em><span style="color: red;">TEST</span></em></strong>4</p>');
+});
+
+test("Paste paragraph in paragraph", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 1);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p>TEST</p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>1</p><p>TEST</p><p>4</p>');
+});
+
+test("Paste paragraphs in complex paragraph", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p><strong><em>1234</em></strong></p>');
+       rng.setStart(editor.dom.select('em,i')[0].firstChild, 1);
+       rng.setEnd(editor.dom.select('em,i')[0].firstChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p>TEST 1</p><p>TEST 2</p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p><strong><em>1</em></strong></p><p>TEST 1</p><p>TEST 2</p><p><strong><em>4</em></strong></p>');
+});
+
+test("Paste Word fake list", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature
 :0 268435456 0 0 -2147483648 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:
 yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-th
 eme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-
 US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-fam
 ily:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1742563504; mso-list-type:hybrid; mso-list-template-ids:-524928352 69009409 69009411 69009413 69009409 69009411 69009413 69009409 69009411 69009413;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:?; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso
 -style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <p class="MsoListParagraphCxSpFirst" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"&gt
 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 1</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 2</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;
 <span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 3</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--
 [endif]-->Item 4</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 5</p> <p class="MsoListParagraphCxSpLast" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: norm
 al; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 6</p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul>');
+
+       editor.settings.paste_retain_style_properties = 'border';
+       
+       rng = editor.dom.createRng();
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="ListStyle" style="margin-top:0cm;margin-right:0cm;margin-bottom:3.0pt;margin-left:18.0pt;mso-add-space:auto;text-align:justify;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 18.0pt"><span lang="DE" style="font-family:Verdana;mso-fareast-font-family:Verdana;mso-bidi-font-family:Verdana;color:black"><span style="mso-list:Ignore">\u25CF<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span lang="DE" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black">Item&nbsp; Spaces.<o:p></o:p></span></p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item&nbsp; Spaces.</li></ul>');
+
+       rng = editor.dom.createRng();
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="ListStyle" style="margin-left:36.0pt;mso-add-space:auto;text-indent:-18.0pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"><span lang="EN-US" style="color:black;mso-ansi-language:EN-US"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">Version 7.0</span><span lang="EN-US" style="font-family:Arial;mso-fareast-font-family:Arial;mso-bidi-font-family:Arial;color:black;mso-ansi-language:EN-US">:<o:p></o:p></span></p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ol><li>Version 7.0:</li></ol>');
+       editor.settings.paste_retain_style_properties = '';
+});
+
+test("Paste Word fake list before BR", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertContent', false, '<br>a');
+
+       rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild, 0);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature
 :0 268435456 0 0 -2147483648 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:
 yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-th
 eme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-
 US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-fam
 ily:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1742563504; mso-list-type:hybrid; mso-list-template-ids:-524928352 69009409 69009411 69009413 69009409 69009411 69009413 69009409 69009411 69009413;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:?; mso-level-tab-stop:none; mso-level-number-position:left; text-indent:-18.0pt; font-family:Symbol;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso
 -style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <p class="MsoListParagraphCxSpFirst" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"&gt
 ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 1</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 2</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;
 <span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 3</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--
 [endif]-->Item 4</p> <p class="MsoListParagraphCxSpMiddle" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 5</p> <p class="MsoListParagraphCxSpLast" style="text-indent: -18pt;"><!--[if !supportLists]--><span style="font-family: Symbol;"><span style="">&middot;<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: norm
 al; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><!--[endif]-->Item 6</p>'});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul><p><br />a</p>');
+});
+
+test("Paste list like paragraph and list", function() {
+       editor.setContent('');
+
+       editor.execCommand('mceInsertClipboardContent', false, {
+               content: '<p class=MsoNormal><span style=\'font-size:10.0pt;line-height:115%;font-family:"Trebuchet MS","sans-serif";color:#666666\'>A. X<o:p></o:p></span></p><p class=MsoListParagraph style=\'text-indent:-.25in;mso-list:l0 level1 lfo1\'><![if !supportLists]><span style=\'mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin\'><span style=\'mso-list:Ignore\'>1.<span style=\'font:7.0pt "Times New Roman"\'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><![endif]>Y</p>'
+       });
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>A. X</p><ol><li>Y</li></ol>');
+});
+
+test("Paste Word table", function() {
+       var rng = editor.dom.createRng();
+
+       editor.setContent('<p>1234</p>');
+       rng.setStart(editor.getBody().firstChild.firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild.firstChild, 4);
+       editor.selection.setRng(rng);
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 12"><meta name="Originator" content="Microsoft Word 12"><link rel="File-List" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"><link rel="themeData" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"><link rel="colorSchemeMapping" href="file:///C:%5CUsers%5Cspocke%5CAppData%5CLocal%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/&gt
 ; <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>SV</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:DontVertAlignCellWithSp/> <w:DontBreakConstrainedForcedTables/> <w:DontVertAlignInTxbx/> <w:Word11KerningPairs/> <w:CachedColBalance/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:
 BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true" DefSemiHidden="true" DefQFormat="false" DefPriority="99" LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Normal"/&gt
 ; <w:LsdException Locked="false" Priority="9" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="heading 1"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/> <w:LsdException Locked="false" Priority="9&quot
 ; QFormat="true" Name="heading 8"/> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/> <w:LsdException Locked="false" Priority="39" Name="toc 1"/> <w:LsdException Locked="false" Priority="39" Name="toc 2"/> <w:LsdException Locked="false" Priority="39" Name="toc 3"/> <w:LsdException Locked="false" Priority="39" Name="toc 4"/> <w:LsdException Locked="false" Priority="39" Name="toc 5"/> <w:LsdException Locked="false" Priority="39" Name="toc 6"/> <w:LsdException Locked="false" Priority="39" Name="toc 7"/> <w:LsdException Locked="false" Priority="39" Name="toc 8"/> <w:LsdException Locked="false" Pr
 iority="39" Name="toc 9"/> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/> <w:LsdException Locked="false" Priority="10" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Title"/> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/> <w:LsdException Locked="false" Priority="11" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/> <w:LsdException Locked="false" Priority="22" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Nam
 e="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false" UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid"/>  <
 w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2"
 />  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading A
 ccent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision&
 quot;/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68&qu
 ot; SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:
 LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" 
 SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdExc
 eption Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false
 " Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:
 LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false&quo
 t; Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" Sem
 iHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:
 LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false" UnhideWhenUsed="false&
 quot; Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false" UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false" UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66&quo
 t; SemiHidden="false" UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false" UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false" UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:L
 sdException Locked="false" Priority="72" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false" UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" 
 SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false" UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>  </w:LatentStyles> </xml><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0cm
 ; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Cali
 bri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle {mso-style-priority:34;
  mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:0cm; margin-left:36.0pt; margin-bottom:.0001pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast {mso-style-priority:34; mso-style-unhide:no; mso-style-qformat:yes; mso-style-type:export-only; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:36.0pt; mso-add-space:auto; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri",&q
 uot;sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-fareast-language:EN-US;} .MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;} @page Section1 {size:595.3pt 841.9pt; margin:70.85pt 70.85pt 70.85pt 70.85pt; mso-header-margin:35.4pt; mso-footer-margin:35.4pt; mso-paper-source:0;} div.Section1 {page:Section1;} --> </style>&
 lt;!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin-top:0cm; mso-para-margin-right:0cm; mso-para-margin-bottom:10.0pt; mso-para-margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} table.MsoTableGrid {mso-style-name:"Table Grid"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-priority:59; mso-style-unhide:no; border:solid black 1.0pt; mso-border-themecolor:text1; mso-border-alt:solid black .5pt; mso-border-themecolor:text1; mso-padding-alt:0
 cm 5.4pt 0cm 5.4pt; mso-border-insideh:.5pt solid black; mso-border-insideh-themecolor:text1; mso-border-insidev:.5pt solid black; mso-border-insidev-themecolor:text1; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-fareast-language:EN-US;} </style> <![endif]--> <table class="MsoTableGrid" style="border: medium none ; margin-left: 36pt; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0"> <tbody><tr style=""> <td style="border: 1pt solid black; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpFirst" style="margin: 0cm 0cm 0.0001pt; line-heigh
 t: normal;">Cell 1</p> </td> <td style="border-style: solid solid solid none; border-color: black black black -moz-use-text-color; border-width: 1pt 1pt 1pt medium; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpLast" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 2</p> </td> </tr> <tr style=""> <td style="border-style: none solid solid; border-color: -moz-use-text-color black black; border-width: medium 1pt 1pt; padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpFirst" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 3</p> </td> <td style="border-style: none solid solid none; border-color: -moz-use-text-color black black -moz-use-text-color; border-width: medium 1pt 1pt medium;
  padding: 0cm 5.4pt; width: 230.3pt;" valign="top" width="307"> <p class="MsoListParagraphCxSpLast" style="margin: 0cm 0cm 0.0001pt; line-height: normal;">Cell 4</p> </td> </tr> </tbody></table> <p class="MsoListParagraph"><o:p>&nbsp;</o:p></p>'});
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<table><tbody><tr><td width="307"><p>Cell 1</p></td><td width="307"><p>Cell 2</p></td></tr><tr><td width="307"><p>Cell 3</p></td><td width="307"><p>Cell 4</p></td></tr></tbody></table><p>&nbsp;</p>');
+});
+
+test("Paste Word without mso markings", function() {
+       editor.setContent('');
+       editor.execCommand('mceInsertClipboardContent', false, {
+               content: (
+                       '<font face="Times New Roman" size="3"></font>' +
+                       '<p style="margin: 0in 0in 10pt;">' +
+                       '<span style=\'line-height: 115%; font-family: "Comic Sans MS"; font-size: 22pt;\'>Comic Sans MS</span>' +
+                       '</p>' +
+                       '<font face="Times New Roman" size="3"></font>'
+               )
+       });
+
+       equal(Utils.trimContent(editor.getContent()), (
+               '<p>Comic Sans MS</p>'
+       ));
+});
+
+test("Paste Word links", function() {
+       editor.setContent('');
+       editor.execCommand('mceInsertClipboardContent', false, {
+               content: (
+                       '<p class="MsoNormal">' +
+                               '<a href="file:///C:/somelocation/filename.doc#_Toc238571849">1</a>' +
+                               '<a href="#_Toc238571849">2</a>' +
+                               '<a name="Toc238571849">3</a>' +
+                               '<a href="http://www.tinymce.com/someurl">4</a>' +
+                               '<a>5</a>' +
+                       '</p>'
+               )
+       });
+
+       equal(Utils.trimContent(editor.getContent()), (
+               '<p>' +
+                       '<a href="#_Toc238571849">1</a>' +
+                       '<a href="#_Toc238571849">2</a>' +
+                       '<a name="Toc238571849"></a>3' +
+                       '<a href="http://www.tinymce.com/someurl">4</a>' +
+                       '5' +
+               '</p>'
+       ));
+});
+
+test("Paste Word retain styles", function() {
+       editor.settings.paste_retain_style_properties = 'color,background-color,font-family';
+
+       // Test color
+       editor.setContent('');
+       editor.execCommand('SelectAll');
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="color: #ff0000">Test</p>'});
+       equal(Utils.trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p style=\"color: #ff0000;\">Test</p>');
+
+       // Test background-color
+       editor.setContent('');
+       editor.execCommand('SelectAll');
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="background-color: #ff0000">Test</p>'});
+       equal(Utils.trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p style=\"background-color: #ff0000;\">Test</p>');
+
+       editor.settings.paste_retain_style_properties = '';
+});
+
+test("Paste part of list from IE", function() {
+       editor.setContent('');
+       editor.execCommand('SelectAll');
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<li>item2</li><li>item3</li>'});
+       equal(Utils.trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<ul><li>item2</li><li>item3</li></ul>', 'List tags are inferred when pasting LI');
+});
+
+test("Disable default filters", function() {
+       editor.settings.paste_enable_default_filters = false;
+
+       // Test color
+       editor.setContent('');
+       editor.execCommand('SelectAll');
+       
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<p class="MsoNormal" style="color: #ff0000;">Test</p>'});
+       equal(Utils.trimContent(editor.getContent().replace(/[\r\n]+/g, '')), '<p class="MsoNormal" style="color: #ff0000;">Test</p>');
+
+       editor.settings.paste_enable_default_filters = true;
+});
+
+test('paste invalid content with spans on page', function() {
+       var startingContent = '<p>123 testing <span id="x">span later in document</span></p>',
+               insertedContent = '<ul><li>u</li><li>l</li></ul>';
+       editor.setContent(startingContent);
+       var 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('mceInsertClipboardContent', false, {content: insertedContent});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), insertedContent + startingContent);
+});
+
+test('paste plain text with space', function() {
+       editor.setContent('<p>text</p>');
+       var 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('mceInsertClipboardContent', false, {text: ' a '});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t a xt</p>');
+});
+
+test('paste plain text with linefeeds', function() {
+       editor.setContent('<p>text</p>');
+       var 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('mceInsertClipboardContent', false, {text: 'a\nb\nc\n'});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>ta<br />b<br />c<br />xt</p>');
+});
+
+test('paste plain text with double linefeeds', function() {
+       editor.setContent('<p>text</p>');
+       var 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('mceInsertClipboardContent', false, {text: 'a\n\nb\n\nc'});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t</p><p>a</p><p>b</p><p>c</p><p>xt</p>');
+});
+
+test('paste plain text with entities', function() {
+       editor.setContent('<p>text</p>');
+       var 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('mceInsertClipboardContent', false, {text: '< & >'});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t&lt; &amp; &gt;xt</p>');
+});
+
+test('paste plain text with paragraphs', function() {
+       editor.setContent('<p>text</p>');
+       var 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('mceInsertClipboardContent', false, {text: 'a\n<b>b</b>\n\nc'});
+
+       equal(editor.getContent().replace(/[\r\n]+/g, ''), '<p>t</p><p>a<br />&lt;b&gt;b&lt;/b&gt;</p><p>c</p><p>xt</p>');
+});
+
+test('paste data image with paste_data_images: false', function() {
+       editor.setContent('');
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<img src="data:image/png;base64,...">'});
+       equal(editor.getContent(), '');
+
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<img alt="alt" src="data:image/png;base64,...">'});
+       equal(editor.getContent(), '');
+});
+
+test('paste data image with paste_data_images: true', function() {
+       editor.settings.paste_data_images = true;
+
+       editor.setContent('');
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<img src="data:image/png;base64,...">'});
+
+       equal(editor.getContent(), '<p><img src="data:image/png;base64,..." alt="" /></p>');
+});
+
+test('paste pre process text (event)', function() {
+       function callback(e) {
+               e.content = 'PRE:' + e.content;
+       }
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.on('PastePreProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {text: 'b\n2'});
+       equal(editor.getContent(), '<p>PRE:b<br />2</p>');
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.off('PastePreProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {text: 'c'});
+       equal(editor.getContent(), '<p>c</p>');
+});
+
+test('paste pre process html (event)', function() {
+       function callback(e) {
+               e.content = 'PRE:' + e.content;
+       }
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.on('PastePreProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>b</em>'});
+       equal(editor.getContent(), '<p>PRE:<em>b</em></p>');
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.off('PastePreProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>c</em>'});
+       equal(editor.getContent(), '<p><em>c</em></p>');
+});
+
+test('paste post process (event)', function() {
+       function callback(e) {
+               e.node.innerHTML += ':POST';
+       }
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.on('PastePostProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>b</em>'});
+       equal(editor.getContent(), '<p><em>b</em>:POST</p>');
+
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.off('PastePostProcess', callback);
+       editor.execCommand('mceInsertClipboardContent', false, {content: '<em>c</em>'});
+       equal(editor.getContent(), '<p><em>c</em></p>');
+});
+
+test('paste innerText of single P', function() {
+       editor.setContent('<p>a</p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a');
+});
+
+test('paste innerText of single P with whitespace wrapped content', function() {
+       editor.setContent('<p>   a   </p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a');
+});
+
+test('paste innerText of two P', function() {
+       editor.setContent('<p>a</p><p>b</p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\n\nb');
+});
+
+test('paste innerText of H1 and P', function() {
+       editor.setContent('<h1>a</h1><p>b</p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\nb');
+});
+
+test('paste innerText of P with BR', function() {
+       editor.setContent('<p>a<br>b</p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a\nb');
+});
+
+test('paste innerText of P with VIDEO', function() {
+       editor.setContent('<p>a<video>b<br>c</video>d</p>');
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML), 'a d');
+});
+
+test('paste innerText of PRE', function() {
+       editor.getBody().innerHTML = '<pre>a\nb\n</pre>';
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().innerHTML).replace(/\r\n/g, '\n'), 'a\nb\n');
+});
+
+test('paste innerText of textnode with whitespace', function() {
+       editor.getBody().innerHTML = '<pre> a </pre>';
+       equal(tinymce.pasteplugin.Utils.innerText(editor.getBody().firstChild.innerHTML), ' a ');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/paste.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsplugin_dependency_chainhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/plugin_dependency_chain.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/plugin_dependency_chain.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/plugin_dependency_chain.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,59 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsplugin_dependency_chain_legacyhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/plugin_dependency_chain_legacy.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/plugin_dependency_chain_legacy.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/plugin_dependency_chain_legacy.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,59 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsplugin_dependency_init_call_orderhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/plugin_dependency_init_call_order.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/plugin_dependency_init_call_order.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/plugin_dependency_init_call_order.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,69 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsplugin_dependency_specific_locationhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/plugin_dependency_specific_location.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/plugin_dependency_specific_location.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/plugin_dependency_specific_location.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,58 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginssearchreplacehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/searchreplace.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/searchreplace.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/searchreplace.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,132 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginssearchreplacejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/searchreplace.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/searchreplace.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/searchreplace.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+module("tinymce.plugins.SearchReplace", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       plugins: "searchreplace",
+                       elements: "elm1",
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       disable_nodechange: true,
+                       init_instance_callback : function(ed) {
+                               window.editor = ed;
+                               window.setTimeout(function() {
+                                       QUnit.start();
+                               }, 0);
+                       }
+               });
+       }
+});
+
+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(Utils.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'
+       ));
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/searchreplace.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginsspellcheckerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/spellchecker.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/spellchecker.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/spellchecker.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,108 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginsspellcheckerjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/spellchecker.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/spellchecker.js                         (rev 0)
+++ trunk/tests/qunit/editor/plugins/spellchecker.js    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+(function() {
+       var count = 0;
+
+       module("tinymce.plugins.Spellchecker", {
+               setupModule: function() {
+                       document.getElementById('view').innerHTML = (
+                               '<textarea id="no_lang"></textarea>' +
+                               '<textarea id="one_lang"></textarea>' +
+                               '<textarea id="many_lang"></textarea>'
+                       );
+
+                       QUnit.stop();
+
+                       function wait() {
+                               if (++count == 3) {
+                                       QUnit.start();
+                               }
+                       }
+
+                       tinymce.init({
+                               selector: '#no_lang',
+                               plugins: "spellchecker",
+                               add_unload_trigger: false,
+                               skin: false,
+                               disable_nodechange: true,
+                               toolbar: 'spellchecker',
+                               init_instance_callback: function(ed) {
+                                       window.editor = ed;
+                                       wait();
+                               }
+                       });
+
+                       tinymce.init({
+                               selector: '#one_lang',
+                               plugins: "spellchecker",
+                               add_unload_trigger: false,
+                               skin: false,
+                               spellchecker_languages: 'English=en',
+                               disable_nodechange: true,
+                               toolbar: 'spellchecker',
+                               init_instance_callback: function(ed) {
+                                       window.editor = ed;
+                                       wait();
+                               }
+                       });
+
+                       tinymce.init({
+                               selector: '#many_lang',
+                               plugins: "spellchecker",
+                               add_unload_trigger: false,
+                               skin: false,
+                               spellchecker_languages: 'English=en,French=fr,German=de',
+                               disable_nodechange: true,
+                               toolbar: 'spellchecker',
+                               init_instance_callback: function(ed) {
+                                       window.editor = ed;
+                                       wait();
+                               }
+                       });
+               },
+
+               teardown: function() {
+                       editor.settings.forced_root_block = 'p';
+               }
+       });
+
+       // Default spellchecker language should match editor language
+       test('Check default language', function() {
+               var mainLanguage = tinymce.get('no_lang').settings.language || 'en';
+               equal(tinymce.get('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 = tinymce.get('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 = tinymce.get('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 = tinymce.get('many_lang').buttons.spellchecker;
+               equal(spellcheckButton.type, 'splitbutton');
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/spellchecker.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginstablehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/table.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/table.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/table.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,348 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginstablejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/table.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/table.js                                (rev 0)
+++ trunk/tests/qunit/editor/plugins/table.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,314 @@
</span><ins>+module("tinymce.plugins.Table", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       plugins: 'table',
+                       valid_styles: {
+                               '*' : 'width,height,text-align,float'
+                       },
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+function fillAndSubmitWindowForm(data) {
+       var win = Utils.getFontmostWindow();
+
+       win.fromJSON(data);
+       win.find('form')[0].submit();
+       win.close();
+}
+
+function cleanTableHtml(html) {
+       return Utils.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>');
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceInsertTable');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "",
+               "border": "",
+               "caption": false,
+               "cellpadding": "",
+               "cellspacing": "",
+               "height": "",
+               "width": ""
+       });
+
+       Utils.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>'
+       );
+
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceInsertTable');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "",
+               "border": "4",
+               "caption": true,
+               "cellpadding": "3",
+               "cellspacing": "2",
+               "height": "101",
+               "width": "100"
+       });
+
+       Utils.getFontmostWindow().close();
+});
+
+test("Table properties dialog (add caption)", function() {
+       editor.setContent('<table><tr><td>X</td></tr></table>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceTableCellProps');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "",
+               "height": "",
+               "scope": "",
+               "type": "td",
+               "width": ""
+       });
+
+       Utils.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>');
+       Utils.setSelection('th', 0);
+       editor.execCommand('mceTableCellProps');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "right",
+               "height": "11",
+               "scope": "row",
+               "type": "th",
+               "width": "10"
+       });
+
+       Utils.getFontmostWindow().close();
+});
+
+test("Table cell properties dialog (update all)", function() {
+       editor.setContent('<table><tr><td>X</td></tr></table>');
+       Utils.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>');
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceTableRowProps');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "",
+               "height": "",
+               "type": "tbody"
+       });
+
+       Utils.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>');
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceTableRowProps');
+
+       deepEqual(Utils.getFontmostWindow().toJSON(), {
+               "align": "right",
+               "height": "10",
+               "type": "thead"
+       });
+
+       Utils.getFontmostWindow().close();
+});
+
+test("Table row properties dialog (update all)", function() {
+       editor.setContent('<table><tr><td>X</td></tr></table>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.setSelection('td', 0);
+       editor.execCommand('mceTableSplitCells');
+       equal(
+               cleanTableHtml(editor.getContent()),
+               '<table><tbody><tr><td>12</td><td>&nbsp;</td></tr></tbody></table>'
+       );
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/table.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditorpluginstable_robothtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/table_robot.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/table_robot.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/table_robot.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,189 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginstestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/tests.js        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/tests.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,24 +0,0 @@
</span><del>-{
-       "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"}
-       ]
-}
</del></span></pre></div>
<a id="trunktestsquniteditorpluginswordcounthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/plugins/wordcount.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/wordcount.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/plugins/wordcount.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,122 +0,0 @@
</span><del>-<!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; &#8211; &#x2013; 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>
</del></span></pre></div>
<a id="trunktestsquniteditorpluginswordcountjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/plugins/wordcount.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/plugins/wordcount.js                            (rev 0)
+++ trunk/tests/qunit/editor/plugins/wordcount.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+module("tinymce.plugins.Wordcount", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       wordcount_target_id: 'current-count',
+                       plugins: 'wordcount',
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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\u00b7 something else</p>');
+       var result = editor.plugins.wordcount.getCount();
+       equal(result, 3);
+});
+
+test("Does not count numbers", function() {
+       expect(1);
+
+       editor.setContent('<p>Something 123 ok</p>');
+       var result = editor.plugins.wordcount.getCount();
+       equal(result, 2);
+});
+
+test("Does not count htmlentities", function() {
+       expect(1);
+
+       editor.setContent('<p>It&rsquo;s my life &ndash; &#8211; &#x2013; 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);
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/plugins/wordcount.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortestgif"></a>
<div class="binary"><h4>Deleted: trunk/tests/qunit/editor/test.gif</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<a id="trunktestsquniteditortinymceEditorhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/Editor.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Editor.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/Editor.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,221 +0,0 @@
</span><del>-<!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>
</del><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunktestsquniteditortinymceEditorjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/Editor.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Editor.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/Editor.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,195 @@
</span><ins>+module("tinymce.Editor", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       disable_nodechange: true,
+                       skin: 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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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 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>');
+});
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/Editor.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceEditorCommandshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/EditorCommands.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/EditorCommands.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/EditorCommands.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,770 +0,0 @@
</span><del>-<!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(4);
-
-       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>');
-
-       editor.setContent('<p><dfn>dfn tag </dfn> <code>code tag </code> <samp>samp tag</samp> <kbd> kbd tag</kbd> <var> var tag</var> <cite> cite tag</cite> <mark> mark tag</mark> <q> q tag</q></p>');
-       editor.execCommand('SelectAll');
-       editor.execCommand('RemoveFormat');
-       equal(editor.getContent(), '<p>dfn tag code tag samp tag kbd tag var tag cite tag mark tag q tag</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceEditorCommandsjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/EditorCommands.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/EditorCommands.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/EditorCommands.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,723 @@
</span><ins>+module("tinymce.EditorCommands", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       disable_nodechange: true,
+                       indent: false,
+                       skin: 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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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 = Utils.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 = Utils.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 = Utils.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 = Utils.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 = Utils.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 = Utils.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>';
+       Utils.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 = Utils.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 = Utils.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 = Utils.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 = Utils.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() {
+       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() {
+       expect(1);
+
+       // Forced root block
+       editor.getBody().innerHTML = '<table><tr><td>X</td></tr></table>';
+       Utils.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);
+       var 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>';
+       Utils.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>';
+       Utils.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>';
+       Utils.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>';
+       Utils.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>';
+       Utils.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 = Utils.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>');
+       Utils.setSelection('#a', 0, '#b', 3);
+       equal(editor.queryCommandState('JustifyLeft'), false);
+       ok(editor.queryCommandState('JustifyRight'));
+});
+
+test('Formatting commands (xhtmlTextStyles)', function() {
+       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: ' + Utils.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: ' + Utils.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: ' + Utils.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: ' + Utils.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: ' + Utils.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="tinymce/ui/img/raster.gif" />');
+       editor.selection.select(editor.dom.select('img')[0]);
+       editor.execCommand('JustifyLeft');
+       equal(editor.getContent(), '<p><img style="float: left;" src="tinymce/ui/img/raster.gif" alt="" /></p>');
+
+       editor.setContent('<img src="tinymce/ui/img/raster.gif" />');
+       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="tinymce/ui/img/raster.gif" alt="" /></p>');
+
+       editor.setContent('<img src="tinymce/ui/img/raster.gif" />');
+       editor.selection.select(editor.dom.select('img')[0]);
+       editor.execCommand('JustifyRight');
+       equal(editor.getContent(), '<p><img style="float: right;" src="tinymce/ui/img/raster.gif" 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() {
+       expect(1);
+
+       editor.setContent('<p><a href="#"><em>abc</em></a></p>');
+       Utils.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() {
+       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() {
+       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() {
+       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() {
+       expect(1);
+
+       editor.setContent('<p><a href="#">test</a></p>');
+       Utils.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() {
+       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() {
+       expect(4);
+
+       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>');
+
+       editor.setContent('<p><dfn>dfn tag </dfn> <code>code tag </code> <samp>samp tag</samp> <kbd> kbd tag</kbd> <var> var tag</var> <cite> cite tag</cite> <mark> mark tag</mark> <q> q tag</q></p>');
+       editor.execCommand('SelectAll');
+       editor.execCommand('RemoveFormat');
+       equal(editor.getContent(), '<p>dfn tag code tag samp tag kbd tag var tag cite tag mark tag q tag</p>');
+});
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/EditorCommands.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceEnterKeyhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/EnterKey.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/EnterKey.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/EnterKey.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,1018 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Unit tests for EnterKey</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.EnterKey", {
-       autostart: false,
-       setup: function() {
-               editor.settings.forced_root_block = 'p';
-               editor.settings.forced_root_block_attrs = null;
-               editor.settings.end_container_on_empty_block = false;
-               editor.settings.br_in_pre = true;
-               editor.settings.keep_styles = true;
-               delete editor.settings.force_p_newlines;
-       }
-});
-
-function pressEnter(evt) {
-       var dom = editor.dom, target = editor.selection.getNode();
-
-       evt = tinymce.extend({keyCode: 13}, evt);
-
-       dom.fire(target, 'keydown', evt);
-       dom.fire(target, 'keypress', evt);
-       dom.fire(target, 'keyup', evt);
-}
-
-function trimBrsOnIE(html) {
-       return html.replace(/<br[^>]*>/gi, '');
-}
-
-test('Enter at end of H1', function() {
-       editor.setContent('<h1>abc</h1>');
-       setSelection('h1', 3);
-       pressEnter();
-       equal(editor.getContent(), '<h1>abc</h1><p>\u00a0</p>');
-       equal(editor.selection.getRng(true).startContainer.nodeName, 'P');
-});
-
-test('Enter in midde of H1', function() {
-       editor.setContent('<h1>abcd</h1>');
-       setSelection('h1', 2);
-       pressEnter();
-       equal(editor.getContent(), '<h1>ab</h1><h1>cd</h1>');
-       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'H1');
-});
-
-test('Enter before text after EM', function() {
-       editor.setContent('<p><em>a</em>b</p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
-       pressEnter();
-       equal(editor.getContent(), '<p><em>a</em></p><p>b</p>');
-       rng = editor.selection.getRng(true);
-       equal(rng.startContainer.nodeValue, 'b');
-});
-
-test('Enter before first IMG in P', function() {
-       editor.setContent('<p><img alt="" src="about:blank" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><p><img src="about:blank" alt="" /></p>');
-});
-
-test('Enter before last IMG in P with text', function() {
-       editor.setContent('<p>abc<img alt="" src="about:blank" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
-       pressEnter();
-       equal(editor.getContent(), '<p>abc</p><p><img src="about:blank" alt="" /></p>');
-       rng = editor.selection.getRng(true);
-       equal(rng.startContainer.nodeName, 'P');
-       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'IMG');  
-});
-
-test('Enter before last IMG in P with IMG sibling', function() {
-       editor.setContent('<p><img src="about:blank" alt="" /><img src="about:blank" alt="" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
-       pressEnter();
-       equal(editor.getContent(), '<p><img src="about:blank" alt="" /></p><p><img src="about:blank" alt="" /></p>');
-       rng = editor.selection.getRng(true);
-       equal(rng.startContainer.nodeName, 'P');
-       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'IMG');  
-});
-
-test('Enter after last IMG in P', function() {
-       editor.setContent('<p>abc<img alt="" src="about:blank" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 2);
-       pressEnter();
-       equal(editor.getContent(), '<p>abc<img src="about:blank" alt="" /></p><p>\u00a0</p>');
-});
-
-test('Enter before last INPUT in P with text', function() {
-       editor.setContent('<p>abc<input type="text" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
-       pressEnter();
-       equal(editor.getContent(), '<p>abc</p><p><input type="text" /></p>');
-       rng = editor.selection.getRng(true);
-       equal(rng.startContainer.nodeName, 'P');
-       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'INPUT');        
-});
-
-test('Enter before last INPUT in P with IMG sibling', function() {
-       editor.setContent('<p><input type="text" /><input type="text" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
-       pressEnter();
-       equal(editor.getContent(), '<p><input type="text" /></p><p><input type="text" /></p>');
-       rng = editor.selection.getRng(true);
-       equal(rng.startContainer.nodeName, 'P');
-       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'INPUT');        
-});
-
-test('Enter after last INPUT in P', function() {
-       editor.setContent('<p>abc<input type="text" /></p>');
-       editor.selection.setCursorLocation(editor.getBody().firstChild, 2);
-       pressEnter();
-       equal(editor.getContent(), '<p>abc<input type="text" /></p><p>\u00a0</p>');
-});
-
-test('Enter at end of P', function() {
-       editor.setContent('<p>abc</p>');
-       setSelection('p', 3);
-       pressEnter();
-       equal(editor.getContent(), '<p>abc</p><p>\u00a0</p>');
-       equal(editor.selection.getRng(true).startContainer.nodeName, 'P');
-});
-
-test('Enter at end of EM inside P', function() {
-       editor.setContent('<p><em>abc</em></p>');
-       setSelection('em', 3);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em>abc</em></p><p><em></em></p>');
-       equal(editor.selection.getRng(true).startContainer.nodeName, 'EM');
-});
-
-test('Enter at middle of EM inside P', function() {
-       editor.setContent('<p><em>abcd</em></p>');
-       setSelection('em', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p><em>ab</em></p><p><em>cd</em></p>');
-       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'EM');
-});
-
-test('Enter at beginning EM inside P', function() {
-       editor.setContent('<p><em>abc</em></p>');
-       setSelection('em', 0);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em></em></p><p><em>abc</em></p>');
-       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
-});
-
-test('Enter at end of STRONG in EM inside P', function() {
-       editor.setContent('<p><em><strong>abc</strong></em></p>');
-       setSelection('strong', 3);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em><strong>abc</strong></em></p><p><em><strong></strong></em></p>');
-       equal(editor.selection.getRng(true).startContainer.nodeName, 'STRONG');
-});
-
-test('Enter at middle of STRONG in EM inside P', function() {
-       editor.setContent('<p><em><strong>abcd</strong></em></p>');
-       setSelection('strong', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p><em><strong>ab</strong></em></p><p><em><strong>cd</strong></em></p>');
-       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'STRONG');
-});
-
-test('Enter at beginning STRONG in EM inside P', function() {
-       editor.setContent('<p><em><strong>abc</strong></em></p>');
-       setSelection('strong', 0);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em><strong></strong></em></p><p><em><strong>abc</strong></em></p>');
-       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
-});
-
-test('Enter at beginning of P', function() {
-       editor.setContent('<p>abc</p>');
-       setSelection('p', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><p>abc</p>');
-       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
-});
-
-test('Enter at middle of P with style, id and class attributes', function() {
-       editor.setContent('<p id="a" class="b" style="color:#000">abcd</p>');
-       setSelection('p', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p id="a" class="b" style="color: #000;">ab</p><p class="b" style="color: #000;">cd</p>');
-       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'P');
-});
-
-test('Enter at a range between H1 and P', function() {
-       editor.setContent('<h1>abcd</h1><p>efgh</p>');
-       setSelection('h1', 2, 'p', 2);
-       pressEnter();
-       equal(editor.getContent(), '<h1>abgh</h1>');
-       equal(editor.selection.getNode().nodeName, 'H1');
-});
-
-test('Enter at end of H1 in HGROUP', function() {
-       editor.setContent('<hgroup><h1>abc</h1></hgroup>');
-       setSelection('h1', 3);
-       pressEnter();
-       equal(editor.getContent(), '<hgroup><h1>abc</h1><h1>\u00a0</h1></hgroup>');
-       equal(editor.selection.getRng(true).startContainer.nodeName, 'H1');
-});
-
-test('Enter inside empty TD', function() {
-       editor.getBody().innerHTML = '<table><tr><td></td></tr></table>';
-       setSelection('td', 0);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<table><tbody><tr><td><p></p><p></p></td></tr></tbody></table>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter inside STRONG inside TD with BR', function() {
-       editor.getBody().innerHTML = '<table><tr><td>d <strong>e</strong><br></td></tr></table>';
-       setSelection('strong', 1);
-       pressEnter({shiftKey: true});
-       equal(cleanHtml(editor.getBody().innerHTML), '<table><tbody><tr><td>d <strong>e<br></strong><br></td></tr></tbody></table>');
-       equal(editor.selection.getNode().nodeName, 'STRONG');
-});
-
-test('Enter inside middle of text node in body', function() {
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p>ab</p><p>cd</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside at beginning of text node in body', function() {
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><p>abcd</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside at end of text node in body', function() {
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 4);
-       pressEnter();
-       equal(editor.getContent(), '<p>abcd</p><p>\u00a0</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside empty body', function() {
-       editor.getBody().innerHTML = '';
-       setSelection('body', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><p>\u00a0</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside empty li in beginning of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>' : '<ol><li><br></li><li>a</li></ol>';
-       setSelection('li', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><ol><li>a</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside empty li at the end of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>' : '<ol><li>a</li><li><br></li></ol>';
-       setSelection('li:last', 0);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li>a</li></ol><p>\u00a0</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter inside empty li in the middle of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>' :  '<ol><li>a</li><li><br></li><li>b</li></ol>';
-       setSelection('li:nth-child(2)', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<ol><li>a</li></ol><p>\u00a0</p><ol><li>b</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter inside empty li in beginning of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>' : '<ol><li><br></li><li>a</li></ol>';
-       setSelection('li', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>\u00a0</p><ol><li>a</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter inside empty li at the end of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>' : '<ol><li>a</li><li><br></li></ol>';
-       setSelection('li:last', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<ol><li>a</li></ol><p>\u00a0</p>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside empty li in the middle of ol with forced_root_block: false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>' :  '<ol><li>a</li><li><br></li><li>b</li></ol>';
-       setSelection('li:nth-child(2)', 0);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li>a</li></ol><br /><ol><li>b</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'BODY');
-});
-
-test('Enter inside empty li in beginning of ol with forced_root_block: false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>' : '<ol><li><br></li><li>a</li></ol>';
-       setSelection('li', 0);
-       pressEnter();
-       equal(editor.getContent(), '<br /><ol><li>a</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'BODY');
-});
-
-test('Enter inside empty li at the end of ol with forced_root_block: false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>' : '<ol><li>a</li><li><br></li></ol>';
-       setSelection('li:last', 0);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<ol><li>a</li></ol><br>');
-       equal(editor.selection.getNode().nodeName, 'BODY');
-});
-
-test('Enter inside empty li in the middle of ol', function() {
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>' :  '<ol><li>a</li><li><br></li><li>b</li></ol>';
-       setSelection('li:nth-child(2)', 0);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li>a</li></ol><p>\u00a0</p><ol><li>b</li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-// Nested lists in LI elements
-
-test('Enter inside empty LI in beginning of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li><br></li>' +
-                                       '<li>a</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       setSelection('li li', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>' +
-                               '<ol>' +
-                                       '<li>a</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Enter inside empty LI in middle of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>a</li>' +
-                                       '<li><br></li>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       setSelection('li li:nth-child(2)', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>a</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li>\u00a0' +
-                               '<ol>' +
-                                       '<li>b</li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Enter inside empty LI in end of OL in LI', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>a</li>' +
-                                       '<li><br></li>' +
-                               '</ol>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       setSelection('li li:last', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a' +
-                               '<ol>' +
-                                       '<li>a</li>' +
-                               '</ol>' +
-                       '</li>' +
-                       '<li></li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-// Nested lists in OL elements
-
-test('Enter before nested list', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       setSelection('ol > li', 1);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li>\u00a0' +
-                               '<ul>' +
-                                       '<li>b</li>' +
-                                       '<li>c</li>' +
-                               '</ul>' +
-                       '</li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Enter inside empty LI in beginning of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li><br></li>' +
-                               '<li>a</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       setSelection('ol ol li', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<li></li>' +
-                       '<ol>' +
-                               '<li>a</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Enter inside empty LI in middle of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>a</li>' +
-                               '<li><br></li>' +
-                               '<li>b</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       setSelection('ol ol li:nth-child(2)', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>a</li>' +
-                       '</ol>' +
-                       '<li></li>' +
-                       '<ol>' +
-                               '<li>b</li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-test('Enter inside empty LI in end of OL in OL', function() {
-       editor.getBody().innerHTML = trimBrsOnIE(
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>a</li>' +
-                               '<li><br></li>' +
-                       '</ol>' +
-               '</ol>'
-       );
-
-       setSelection('ol ol li:last', 0);
-       editor.focus();
-       pressEnter();
-
-       equal(editor.getContent(), 
-               '<ol>' +
-                       '<li>a</li>' +
-                       '<ol>' +
-                               '<li>a</li>' +
-                       '</ol>' +
-                       '<li></li>' +
-               '</ol>'
-       );
-
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-
-
-test('Enter at beginning of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 0);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li></li><li><p>abcd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter inside middle of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 2);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li><p>ab</p></li><li><p>cd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Enter at end of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 4);
-       pressEnter();
-       equal(editor.getContent(), '<ol><li><p>abcd</p></li><li></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'LI');
-});
-
-
-test('Shift+Enter at beginning of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<ol><li><p><br />abcd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter inside middle of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<ol><li><p>ab<br />cd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Shift+Enter at end of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 4);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li><p>abcd</p></li></ol>' : '<ol><li><p>abcd<br /><br /></p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-
-test('Ctrl+Enter at beginning of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 0);
-       pressEnter({ctrlKey: true});
-       equal(editor.getContent(), '<ol><li><p>\u00a0</p><p>abcd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Ctrl+Enter inside middle of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 2);
-       pressEnter({ctrlKey: true});
-       equal(editor.getContent(), '<ol><li><p>ab</p><p>cd</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-test('Ctrl+Enter at end of P inside LI', function() {
-       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
-       setSelection('p', 4);
-       pressEnter({ctrlKey: true});
-       equal(editor.getContent(), '<ol><li><p>abcd</p><p>\u00a0</p></li></ol>');
-       equal(editor.selection.getNode().nodeName, 'P');
-});
-
-
-test('Enter in the middle of text in P with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<p>abc</p>';
-       setSelection('p', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p>ab<br />c</p>');
-});
-
-test('Enter at the end of text in P with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<p>abc</p>';
-       setSelection('p', 3);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), (tinymce.isIE && tinymce.Env.ie < 11) ? '<p>abc<br></p>' : '<p>abc<br><br></p>');
-});
-
-test('Enter at the middle of text in BODY with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 2);
-       editor.focus();
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), 'ab<br>cd');
-});
-
-test('Enter at the beginning of text in BODY with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 0);
-       editor.focus();
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<br>abcd');
-});
-
-test('Enter at the end of text in BODY with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = 'abcd';
-       setSelection('body', 4);
-       editor.focus();
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), (tinymce.isIE && tinymce.Env.ie < 11) ? 'abcd<br>' : 'abcd<br><br>');
-});
-
-test('Enter in empty P at the end of a blockquote and end_container_on_empty_block: true', function() {
-       editor.settings.end_container_on_empty_block = true;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p>abc</p><p></p></blockquote>' : '<blockquote><p>abc</p><p><br></p></blockquote>';
-       setSelection('p:last', 0);
-       pressEnter();
-       equal(editor.getContent(), '<blockquote><p>abc</p></blockquote><p>\u00a0</p>');
-});
-
-test('Enter in empty P at the beginning of a blockquote and end_container_on_empty_block: true', function() {
-       editor.settings.end_container_on_empty_block = true;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p></p><p>abc</p></blockquote>' : '<blockquote><p><br></p><p>abc</p></blockquote>';
-       setSelection('p', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><blockquote><p>abc</p></blockquote>');
-});
-
-test('Enter in empty P at in the middle of a blockquote and end_container_on_empty_block: true', function() {
-       editor.settings.end_container_on_empty_block = true;
-       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p>abc</p><p></p><p>123</p></blockquote>' : '<blockquote><p>abc</p><p><br></p><p>123</p></blockquote>';
-       setSelection('p:nth-child(2)', 0);
-       pressEnter();
-       equal(editor.getContent(), '<blockquote><p>abc</p></blockquote><p>\u00a0</p><blockquote><p>123</p></blockquote>');
-});
-
-test('Enter inside empty P with empty P siblings', function() {
-       // Tests that a workaround for an IE bug is working correctly
-       editor.getBody().innerHTML = '<p></p><p></p><p>X</p>';
-       setSelection('p', 0);
-       pressEnter();
-       equal(editor.getContent(), '<p>\u00a0</p><p>\u00a0</p><p>\u00a0</p><p>X</p>');
-});
-
-test('Enter at end of H1 with forced_root_block_attrs', function() {
-       editor.settings.forced_root_block_attrs = {"class": "class1"};
-       editor.getBody().innerHTML = '<h1>a</h1>';
-       setSelection('h1', 1);
-       pressEnter();
-       equal(editor.getContent(), '<h1>a</h1><p class="class1">\u00a0</p>');
-});
-
-test('Shift+Enter at beginning of P', function() {
-       editor.getBody().innerHTML = '<p>abc</p>';
-       setSelection('p', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p><br />abc</p>');
-});
-
-test('Shift+Enter in the middle of P', function() {
-       editor.getBody().innerHTML = '<p>abcd</p>';
-       setSelection('p', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>ab<br />cd</p>');
-});
-
-test('Shift+Enter at the end of P', function() {
-       editor.getBody().innerHTML = '<p>abcd</p>';
-       setSelection('p', 4);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), (tinymce.isIE && tinymce.Env.ie < 11) ? '<p>abcd</p>' : '<p>abcd<br /><br /></p>');
-});
-
-test('Shift+Enter in the middle of B with a BR after it', function() {
-       editor.getBody().innerHTML = '<p><b>abcd</b><br></p>';
-       setSelection('b', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p><b>ab<br />cd</b></p>');
-});
-
-test('Shift+Enter at the end of B with a BR after it', function() {
-       editor.getBody().innerHTML = '<p><b>abcd</b><br></p>';
-       setSelection('b', 4);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p><b>abcd<br /></b></p>');
-});
-
-test('Enter in beginning of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abc</pre>';
-       setSelection('pre', 0);
-       pressEnter();
-       equal(editor.getContent(), '<pre><br />abc</pre>');
-});
-
-test('Enter in the middle of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 2);
-       pressEnter();
-       equal(editor.getContent(), '<pre>ab<br />cd</pre>');
-});
-
-test('Enter at the end of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 4);
-       pressEnter();
-       equal(editor.getContent(), (tinymce.isIE && tinymce.Env.ie < 11) ? '<pre>abcd</pre>' : '<pre>abcd<br /><br /></pre>');
-});
-
-test('Enter in beginning of PRE and br_in_pre: false', function() {
-       editor.settings.br_in_pre = false;
-       editor.getBody().innerHTML = '<pre>abc</pre>';
-       setSelection('pre', 0);
-       pressEnter();
-       equal(editor.getContent(), '<pre>\u00a0</pre><pre>abc</pre>');
-});
-
-test('Enter in the middle of PRE and br_in_pre: false', function() {
-       editor.settings.br_in_pre = false;
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 2);
-       pressEnter();
-       equal(editor.getContent(), '<pre>ab</pre><pre>cd</pre>');
-});
-
-test('Enter at the end of PRE and br_in_pre: false', function() {
-       editor.settings.br_in_pre = false;
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 4);
-       pressEnter();
-       equal(editor.getContent(), '<pre>abcd</pre><p>\u00a0</p>');
-});
-
-test('Shift+Enter in beginning of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abc</pre>';
-       setSelection('pre', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<pre>\u00a0</pre><pre>abc</pre>');
-});
-
-test('Shift+Enter in the middle of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<pre>ab</pre><pre>cd</pre>');
-});
-
-test('Shift+Enter at the end of PRE', function() {
-       editor.getBody().innerHTML = '<pre>abcd</pre>';
-       setSelection('pre', 4);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<pre>abcd</pre><p>\u00a0</p>');
-});
-
-test('Shift+Enter in beginning of P with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<p>abc</p>';
-       setSelection('p', 0);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>\u00a0</p><p>abc</p>');
-});
-
-test('Shift+Enter in middle of P with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<p>abcd</p>';
-       setSelection('p', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>ab</p><p>cd</p>');
-});
-
-test('Shift+Enter at the end of P with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<p>abc</p>';
-       setSelection('p', 3);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>abc</p><p>\u00a0</p>');
-});
-
-test('Shift+Enter in body with forced_root_block set to false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = 'abcd';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild, 2);
-       rng.setEnd(editor.getBody().firstChild, 2);
-       editor.selection.setRng(rng);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<p>ab</p><p>cd</p>');
-});
-
-test('Enter at the end of DIV layer', function() {
-       editor.settings.br_in_pre = false;
-       editor.setContent('<div style="position: absolute; top: 1px; left: 2px;">abcd</div>');
-       setSelection('div', 4);
-       pressEnter();
-       equal(editor.getContent(), '<div style="position: absolute; top: 1px; left: 2px;"><p>abcd</p><p>\u00a0</p></div>');
-});
-
-test('Enter in div inside contentEditable:false div', function() {
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div>abcd</div></div>';
-       setSelection('div div', 2);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div>abcd</div></div>');
-});
-
-test('Enter in div with contentEditable:true inside contentEditable:false div', function() {
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true">abcd</div></div>';
-       setSelection('div div', 2);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><p>ab</p><p>cd</p></div></div>');
-});
-
-test('Enter in span with contentEditable:true inside contentEditable:false div', function() {
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
-       setSelection('span', 2);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>');
-});
-
-test('Shift+Enter in span with contentEditable:true inside contentEditable:false div', function() {
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
-       setSelection('span', 2);
-       pressEnter({shiftKey: true});
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">ab<br>cd</span></div>');
-});
-
-test('Enter in span with contentEditable:true inside contentEditable:false div and forced_root_block: false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
-       setSelection('span', 2);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">ab<br>cd</span></div>');
-});
-
-test('Enter in em within contentEditable:true div inside contentEditable:false div', function() {
-       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><em>abcd</em></div></div>';
-       setSelection('em', 2);
-       pressEnter();
-       equal(cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><p><em>ab</em></p><p><em>cd</em></p></div></div>');
-});
-
-test('Enter at end of text in a span inside a P and keep_styles: false', function() {
-       editor.settings.keep_styles = false;
-       editor.getBody().innerHTML = '<p><em><span style="font-size: 13px;">X</span></em></p>';
-       setSelection('span', 1);
-       pressEnter();
-       equal(editor.getContent(), '<p><em><span style="font-size: 13px;">X</span></em></p><p>\u00a0</p>');
-});
-
-test('Shift+enter in LI when forced_root_block: false', function() {
-       editor.settings.forced_root_block = false;
-       editor.getBody().innerHTML = '<ul><li>text</li></ul>';
-       setSelection('li', 2);
-       pressEnter({shiftKey: true});
-       equal(editor.getContent(), '<ul><li>te<br />xt</li></ul>');
-});
-
-test('Enter when forced_root_block: false and force_p_newlines : true', function() {
-       editor.settings.forced_root_block = false;
-       editor.settings.force_p_newlines = true;
-       editor.getBody().innerHTML = 'text';
-       setSelection('body', 2);
-       pressEnter();
-       equal(editor.getContent(), '<p>te</p><p>xt</p>');
-});
-
-test('Enter before BR between DIVs', function() {
-       editor.getBody().innerHTML = '<div>a<span>b</span>c</div><br /><div>d</div>';
-       var rng = editor.dom.createRng();
-       rng.setStartBefore(editor.dom.select('br')[0]);
-       rng.setEndBefore(editor.dom.select('br')[0]);
-       editor.selection.setRng(rng);
-       pressEnter();
-       equal(editor.getContent(), '<div>a<span>b</span>c</div><p>\u00a0</p><p>\u00a0</p><div>d</div>');
-});
-
-// Only test these on modern browsers
-if (window.getSelection) {
-       test('Enter behind table element', function() {
-               var rng = editor.dom.createRng();
-
-               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table>';
-               rng.setStartAfter(editor.getBody().lastChild);
-               rng.setEndAfter(editor.getBody().lastChild);
-               editor.selection.setRng(rng);
-
-               pressEnter();
-               equal(editor.getContent(), '<table><tbody><tr><td>x</td></tr></tbody></table><p>\u00a0</p>');
-       });
-
-       test('Enter before table element', function() {
-               var rng = editor.dom.createRng();
-
-               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table>';
-               rng.setStartBefore(editor.getBody().lastChild);
-               rng.setEndBefore(editor.getBody().lastChild);
-               editor.selection.setRng(rng);
-
-               pressEnter();
-               equal(editor.getContent(), '<p>\u00a0</p><table><tbody><tr><td>x</td></tr></tbody></table>');
-       });
-
-       test('Enter behind table followed by a p', function() {
-               var rng = editor.dom.createRng();
-
-               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table><p>x</p>';
-               rng.setStartAfter(editor.getBody().firstChild);
-               rng.setEndAfter(editor.getBody().firstChild);
-               editor.selection.setRng(rng);
-
-               pressEnter();
-               equal(editor.getContent(), '<table><tbody><tr><td>x</td></tr></tbody></table><p>\u00a0</p><p>x</p>');
-       });
-
-       test('Enter before table element preceded by a p', function() {
-               var rng = editor.dom.createRng();
-
-               editor.getBody().innerHTML = '<p>x</p><table><tbody><td>x</td></tbody></table>';
-               rng.setStartBefore(editor.getBody().lastChild);
-               rng.setStartBefore(editor.getBody().lastChild);
-               editor.selection.setRng(rng);
-
-               pressEnter();
-               equal(editor.getContent(), '<p>x</p><p>\u00a0</p><table><tbody><tr><td>x</td></tr></tbody></table>');
-       });
-}
-
-tinymce.init({
-       mode : "exact",
-       elements : "elm1",
-       add_unload_trigger : false,
-       indent : false,
-       schema: 'html5',
-       entities : 'raw',
-       extended_valid_elements: 'div[id|style|contenteditable],span[id|style|contenteditable]',
-       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,position,top,left'
-       },
-       disable_nodechange: true,
-       init_instance_callback : function(ed) {
-               editor = ed;
-               QUnit.start();
-       }
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">Unit tests for tinymce.EnterKey</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceEnterKeyjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/EnterKey.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/EnterKey.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/EnterKey.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,980 @@
</span><ins>+module("tinymce.EnterKey", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       disable_nodechange: true,
+                       indent: false,
+                       skin: false,
+                       entities: 'raw',
+                       schema: 'html5',
+                       extended_valid_elements: 'div[id|style|contenteditable],span[id|style|contenteditable]',
+                       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,position,top,left'
+                       },
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       },
+
+       teardown: function() {
+               editor.settings.forced_root_block = 'p';
+               editor.settings.forced_root_block_attrs = null;
+               editor.settings.end_container_on_empty_block = false;
+               editor.settings.br_in_pre = true;
+               editor.settings.keep_styles = true;
+               delete editor.settings.force_p_newlines;
+       }
+});
+
+test('Enter at end of H1', function() {
+       editor.setContent('<h1>abc</h1>');
+       Utils.setSelection('h1', 3);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<h1>abc</h1><p>\u00a0</p>');
+       equal(editor.selection.getRng(true).startContainer.nodeName, 'P');
+});
+
+test('Enter in midde of H1', function() {
+       editor.setContent('<h1>abcd</h1>');
+       Utils.setSelection('h1', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<h1>ab</h1><h1>cd</h1>');
+       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'H1');
+});
+
+test('Enter before text after EM', function() {
+       editor.setContent('<p><em>a</em>b</p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><em>a</em></p><p>b</p>');
+       var rng = editor.selection.getRng(true);
+       equal(rng.startContainer.nodeValue, 'b');
+});
+
+test('Enter before first IMG in P', function() {
+       editor.setContent('<p><img alt="" src="about:blank" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><p><img src="about:blank" alt="" /></p>');
+});
+
+test('Enter before last IMG in P with text', function() {
+       editor.setContent('<p>abc<img alt="" src="about:blank" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abc</p><p><img src="about:blank" alt="" /></p>');
+       var rng = editor.selection.getRng(true);
+       equal(rng.startContainer.nodeName, 'P');
+       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'IMG');
+});
+
+test('Enter before last IMG in P with IMG sibling', function() {
+       editor.setContent('<p><img src="about:blank" alt="" /><img src="about:blank" alt="" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><img src="about:blank" alt="" /></p><p><img src="about:blank" alt="" /></p>');
+       var rng = editor.selection.getRng(true);
+       equal(rng.startContainer.nodeName, 'P');
+       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'IMG');
+});
+
+test('Enter after last IMG in P', function() {
+       editor.setContent('<p>abc<img alt="" src="about:blank" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abc<img src="about:blank" alt="" /></p><p>\u00a0</p>');
+});
+
+test('Enter before last INPUT in P with text', function() {
+       editor.setContent('<p>abc<input type="text" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abc</p><p><input type="text" /></p>');
+       var rng = editor.selection.getRng(true);
+       equal(rng.startContainer.nodeName, 'P');
+       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'INPUT');
+});
+
+test('Enter before last INPUT in P with IMG sibling', function() {
+       editor.setContent('<p><input type="text" /><input type="text" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><input type="text" /></p><p><input type="text" /></p>');
+       var rng = editor.selection.getRng(true);
+       equal(rng.startContainer.nodeName, 'P');
+       equal(rng.startContainer.childNodes[rng.startOffset].nodeName, 'INPUT');
+});
+
+test('Enter after last INPUT in P', function() {
+       editor.setContent('<p>abc<input type="text" /></p>');
+       editor.selection.setCursorLocation(editor.getBody().firstChild, 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abc<input type="text" /></p><p>\u00a0</p>');
+});
+
+test('Enter at end of P', function() {
+       editor.setContent('<p>abc</p>');
+       Utils.setSelection('p', 3);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abc</p><p>\u00a0</p>');
+       equal(editor.selection.getRng(true).startContainer.nodeName, 'P');
+});
+
+test('Enter at end of EM inside P', function() {
+       editor.setContent('<p><em>abc</em></p>');
+       Utils.setSelection('em', 3);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em>abc</em></p><p><em></em></p>');
+       equal(editor.selection.getRng(true).startContainer.nodeName, 'EM');
+});
+
+test('Enter at middle of EM inside P', function() {
+       editor.setContent('<p><em>abcd</em></p>');
+       Utils.setSelection('em', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><em>ab</em></p><p><em>cd</em></p>');
+       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'EM');
+});
+
+test('Enter at beginning EM inside P', function() {
+       editor.setContent('<p><em>abc</em></p>');
+       Utils.setSelection('em', 0);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em></em></p><p><em>abc</em></p>');
+       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
+});
+
+test('Enter at end of STRONG in EM inside P', function() {
+       editor.setContent('<p><em><strong>abc</strong></em></p>');
+       Utils.setSelection('strong', 3);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em><strong>abc</strong></em></p><p><em><strong></strong></em></p>');
+       equal(editor.selection.getRng(true).startContainer.nodeName, 'STRONG');
+});
+
+test('Enter at middle of STRONG in EM inside P', function() {
+       editor.setContent('<p><em><strong>abcd</strong></em></p>');
+       Utils.setSelection('strong', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><em><strong>ab</strong></em></p><p><em><strong>cd</strong></em></p>');
+       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'STRONG');
+});
+
+test('Enter at beginning STRONG in EM inside P', function() {
+       editor.setContent('<p><em><strong>abc</strong></em></p>');
+       Utils.setSelection('strong', 0);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<p><em><strong></strong></em></p><p><em><strong>abc</strong></em></p>');
+       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
+});
+
+test('Enter at beginning of P', function() {
+       editor.setContent('<p>abc</p>');
+       Utils.setSelection('p', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><p>abc</p>');
+       equal(editor.selection.getRng(true).startContainer.nodeValue, 'abc');
+});
+
+test('Enter at middle of P with style, id and class attributes', function() {
+       editor.setContent('<p id="a" class="b" style="color:#000">abcd</p>');
+       Utils.setSelection('p', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p id="a" class="b" style="color: #000;">ab</p><p class="b" style="color: #000;">cd</p>');
+       equal(editor.selection.getRng(true).startContainer.parentNode.nodeName, 'P');
+});
+
+test('Enter at a range between H1 and P', function() {
+       editor.setContent('<h1>abcd</h1><p>efgh</p>');
+       Utils.setSelection('h1', 2, 'p', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<h1>abgh</h1>');
+       equal(editor.selection.getNode().nodeName, 'H1');
+});
+
+test('Enter at end of H1 in HGROUP', function() {
+       editor.setContent('<hgroup><h1>abc</h1></hgroup>');
+       Utils.setSelection('h1', 3);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<hgroup><h1>abc</h1><h1>\u00a0</h1></hgroup>');
+       equal(editor.selection.getRng(true).startContainer.nodeName, 'H1');
+});
+
+test('Enter inside empty TD', function() {
+       editor.getBody().innerHTML = '<table><tr><td></td></tr></table>';
+       Utils.setSelection('td', 0);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML).replace(/<br([^>]+|)>|&nbsp;/g, ''), '<table><tbody><tr><td><p></p><p></p></td></tr></tbody></table>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter inside STRONG inside TD with BR', function() {
+       editor.getBody().innerHTML = '<table><tr><td>d <strong>e</strong><br></td></tr></table>';
+       Utils.setSelection('strong', 1);
+       Utils.pressEnter({shiftKey: true});
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<table><tbody><tr><td>d <strong>e<br></strong><br></td></tr></tbody></table>');
+       equal(editor.selection.getNode().nodeName, 'STRONG');
+});
+
+test('Enter inside middle of text node in body', function() {
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>ab</p><p>cd</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside at beginning of text node in body', function() {
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><p>abcd</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside at end of text node in body', function() {
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 4);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>abcd</p><p>\u00a0</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside empty body', function() {
+       editor.getBody().innerHTML = '';
+       Utils.setSelection('body', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><p>\u00a0</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside empty li in beginning of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>': '<ol><li><br></li><li>a</li></ol>';
+       Utils.setSelection('li', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><ol><li>a</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside empty li at the end of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>': '<ol><li>a</li><li><br></li></ol>';
+       Utils.setSelection('li:last', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li>a</li></ol><p>\u00a0</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter inside empty li in the middle of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>':  '<ol><li>a</li><li><br></li><li>b</li></ol>';
+       Utils.setSelection('li:nth-child(2)', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<ol><li>a</li></ol><p>\u00a0</p><ol><li>b</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter inside empty li in beginning of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>': '<ol><li><br></li><li>a</li></ol>';
+       Utils.setSelection('li', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>\u00a0</p><ol><li>a</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter inside empty li at the end of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>': '<ol><li>a</li><li><br></li></ol>';
+       Utils.setSelection('li:last', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<ol><li>a</li></ol><p>\u00a0</p>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside empty li in the middle of ol with forced_root_block: false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>':  '<ol><li>a</li><li><br></li><li>b</li></ol>';
+       Utils.setSelection('li:nth-child(2)', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li>a</li></ol><br /><ol><li>b</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'BODY');
+});
+
+test('Enter inside empty li in beginning of ol with forced_root_block: false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li></li><li>a</li></ol>': '<ol><li><br></li><li>a</li></ol>';
+       Utils.setSelection('li', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<br /><ol><li>a</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'BODY');
+});
+
+test('Enter inside empty li at the end of ol with forced_root_block: false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li></ol>': '<ol><li>a</li><li><br></li></ol>';
+       Utils.setSelection('li:last', 0);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<ol><li>a</li></ol><br>');
+       equal(editor.selection.getNode().nodeName, 'BODY');
+});
+
+test('Enter inside empty li in the middle of ol', function() {
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li>a</li><li></li><li>b</li></ol>':  '<ol><li>a</li><li><br></li><li>b</li></ol>';
+       Utils.setSelection('li:nth-child(2)', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li>a</li></ol><p>\u00a0</p><ol><li>b</li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+// Nested lists in LI elements
+
+test('Enter inside empty LI in beginning of OL in LI', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li><br></li>' +
+                                       '<li>a</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('li li', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>' +
+                               '<ol>' +
+                                       '<li>a</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Enter inside empty LI in middle of OL in LI', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>a</li>' +
+                                       '<li><br></li>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('li li:nth-child(2)', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>a</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li>\u00a0' +
+                               '<ol>' +
+                                       '<li>b</li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Enter inside empty LI in end of OL in LI', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>a</li>' +
+                                       '<li><br></li>' +
+                               '</ol>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('li li:last', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a' +
+                               '<ol>' +
+                                       '<li>a</li>' +
+                               '</ol>' +
+                       '</li>' +
+                       '<li></li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+// Nested lists in OL elements
+
+test('Enter before nested list', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('ol > li', 1);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li>\u00a0' +
+                               '<ul>' +
+                                       '<li>b</li>' +
+                                       '<li>c</li>' +
+                               '</ul>' +
+                       '</li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Enter inside empty LI in beginning of OL in OL', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li><br></li>' +
+                               '<li>a</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('ol ol li', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<li></li>' +
+                       '<ol>' +
+                               '<li>a</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Enter inside empty LI in middle of OL in OL', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>a</li>' +
+                               '<li><br></li>' +
+                               '<li>b</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('ol ol li:nth-child(2)', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>a</li>' +
+                       '</ol>' +
+                       '<li></li>' +
+                       '<ol>' +
+                               '<li>b</li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+test('Enter inside empty LI in end of OL in OL', function() {
+       editor.getBody().innerHTML = Utils.trimBrsOnIE(
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>a</li>' +
+                               '<li><br></li>' +
+                       '</ol>' +
+               '</ol>'
+       );
+
+       Utils.setSelection('ol ol li:last', 0);
+       editor.focus();
+       Utils.pressEnter();
+
+       equal(editor.getContent(),
+               '<ol>' +
+                       '<li>a</li>' +
+                       '<ol>' +
+                               '<li>a</li>' +
+                       '</ol>' +
+                       '<li></li>' +
+               '</ol>'
+       );
+
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+
+
+test('Enter at beginning of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li></li><li><p>abcd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter inside middle of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li><p>ab</p></li><li><p>cd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Enter at end of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 4);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<ol><li><p>abcd</p></li><li></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'LI');
+});
+
+
+test('Shift+Enter at beginning of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<ol><li><p><br />abcd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter inside middle of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<ol><li><p>ab<br />cd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Shift+Enter at end of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 4);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),(tinymce.isIE && tinymce.Env.ie < 11) ? '<ol><li><p>abcd</p></li></ol>': '<ol><li><p>abcd<br /><br /></p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+
+test('Ctrl+Enter at beginning of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter({ctrlKey: true});
+       equal(editor.getContent(),'<ol><li><p>\u00a0</p><p>abcd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Ctrl+Enter inside middle of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter({ctrlKey: true});
+       equal(editor.getContent(),'<ol><li><p>ab</p><p>cd</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+test('Ctrl+Enter at end of P inside LI', function() {
+       editor.getBody().innerHTML = '<ol><li><p>abcd</p></li></ol>';
+       Utils.setSelection('p', 4);
+       Utils.pressEnter({ctrlKey: true});
+       equal(editor.getContent(),'<ol><li><p>abcd</p><p>\u00a0</p></li></ol>');
+       equal(editor.selection.getNode().nodeName, 'P');
+});
+
+
+test('Enter in the middle of text in P with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<p>abc</p>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>ab<br />c</p>');
+});
+
+test('Enter at the end of text in P with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<p>abc</p>';
+       Utils.setSelection('p', 3);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), (tinymce.isIE && tinymce.Env.ie < 11) ? '<p>abc<br></p>': '<p>abc<br><br></p>');
+});
+
+test('Enter at the middle of text in BODY with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 2);
+       editor.focus();
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), 'ab<br>cd');
+});
+
+test('Enter at the beginning of text in BODY with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 0);
+       editor.focus();
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<br>abcd');
+});
+
+test('Enter at the end of text in BODY with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 4);
+       editor.focus();
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), (tinymce.isIE && tinymce.Env.ie < 11) ? 'abcd<br>': 'abcd<br><br>');
+});
+
+test('Enter in empty P at the end of a blockquote and end_container_on_empty_block: true', function() {
+       editor.settings.end_container_on_empty_block = true;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p>abc</p><p></p></blockquote>': '<blockquote><p>abc</p><p><br></p></blockquote>';
+       Utils.setSelection('p:last', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<blockquote><p>abc</p></blockquote><p>\u00a0</p>');
+});
+
+test('Enter in empty P at the beginning of a blockquote and end_container_on_empty_block: true', function() {
+       editor.settings.end_container_on_empty_block = true;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p></p><p>abc</p></blockquote>': '<blockquote><p><br></p><p>abc</p></blockquote>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><blockquote><p>abc</p></blockquote>');
+});
+
+test('Enter in empty P at in the middle of a blockquote and end_container_on_empty_block: true', function() {
+       editor.settings.end_container_on_empty_block = true;
+       editor.getBody().innerHTML = (tinymce.isIE && tinymce.Env.ie < 11) ? '<blockquote><p>abc</p><p></p><p>123</p></blockquote>': '<blockquote><p>abc</p><p><br></p><p>123</p></blockquote>';
+       Utils.setSelection('p:nth-child(2)', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<blockquote><p>abc</p></blockquote><p>\u00a0</p><blockquote><p>123</p></blockquote>');
+});
+
+test('Enter inside empty P with empty P siblings', function() {
+       // Tests that a workaround for an IE bug is working correctly
+       editor.getBody().innerHTML = '<p></p><p></p><p>X</p>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>\u00a0</p><p>\u00a0</p><p>\u00a0</p><p>X</p>');
+});
+
+test('Enter at end of H1 with forced_root_block_attrs', function() {
+       editor.settings.forced_root_block_attrs = {"class": "class1"};
+       editor.getBody().innerHTML = '<h1>a</h1>';
+       Utils.setSelection('h1', 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<h1>a</h1><p class="class1">\u00a0</p>');
+});
+
+test('Shift+Enter at beginning of P', function() {
+       editor.getBody().innerHTML = '<p>abc</p>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p><br />abc</p>');
+});
+
+test('Shift+Enter in the middle of P', function() {
+       editor.getBody().innerHTML = '<p>abcd</p>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>ab<br />cd</p>');
+});
+
+test('Shift+Enter at the end of P', function() {
+       editor.getBody().innerHTML = '<p>abcd</p>';
+       Utils.setSelection('p', 4);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),(tinymce.isIE && tinymce.Env.ie < 11) ? '<p>abcd</p>': '<p>abcd<br /><br /></p>');
+});
+
+test('Shift+Enter in the middle of B with a BR after it', function() {
+       editor.getBody().innerHTML = '<p><b>abcd</b><br></p>';
+       Utils.setSelection('b', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p><b>ab<br />cd</b></p>');
+});
+
+test('Shift+Enter at the end of B with a BR after it', function() {
+       editor.getBody().innerHTML = '<p><b>abcd</b><br></p>';
+       Utils.setSelection('b', 4);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p><b>abcd<br /></b></p>');
+});
+
+test('Enter in beginning of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abc</pre>';
+       Utils.setSelection('pre', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<pre><br />abc</pre>');
+});
+
+test('Enter in the middle of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<pre>ab<br />cd</pre>');
+});
+
+test('Enter at the end of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 4);
+       Utils.pressEnter();
+       equal(editor.getContent(),(tinymce.isIE && tinymce.Env.ie < 11) ? '<pre>abcd</pre>': '<pre>abcd<br /><br /></pre>');
+});
+
+test('Enter in beginning of PRE and br_in_pre: false', function() {
+       editor.settings.br_in_pre = false;
+       editor.getBody().innerHTML = '<pre>abc</pre>';
+       Utils.setSelection('pre', 0);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<pre>\u00a0</pre><pre>abc</pre>');
+});
+
+test('Enter in the middle of PRE and br_in_pre: false', function() {
+       editor.settings.br_in_pre = false;
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<pre>ab</pre><pre>cd</pre>');
+});
+
+test('Enter at the end of PRE and br_in_pre: false', function() {
+       editor.settings.br_in_pre = false;
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 4);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<pre>abcd</pre><p>\u00a0</p>');
+});
+
+test('Shift+Enter in beginning of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abc</pre>';
+       Utils.setSelection('pre', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<pre>\u00a0</pre><pre>abc</pre>');
+});
+
+test('Shift+Enter in the middle of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<pre>ab</pre><pre>cd</pre>');
+});
+
+test('Shift+Enter at the end of PRE', function() {
+       editor.getBody().innerHTML = '<pre>abcd</pre>';
+       Utils.setSelection('pre', 4);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<pre>abcd</pre><p>\u00a0</p>');
+});
+
+test('Shift+Enter in beginning of P with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<p>abc</p>';
+       Utils.setSelection('p', 0);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>\u00a0</p><p>abc</p>');
+});
+
+test('Shift+Enter in middle of P with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<p>abcd</p>';
+       Utils.setSelection('p', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>ab</p><p>cd</p>');
+});
+
+test('Shift+Enter at the end of P with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<p>abc</p>';
+       Utils.setSelection('p', 3);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>abc</p><p>\u00a0</p>');
+});
+
+test('Shift+Enter in body with forced_root_block set to false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = 'abcd';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild, 2);
+       rng.setEnd(editor.getBody().firstChild, 2);
+       editor.selection.setRng(rng);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<p>ab</p><p>cd</p>');
+});
+
+test('Enter at the end of DIV layer', function() {
+       editor.settings.br_in_pre = false;
+       editor.setContent('<div style="position: absolute; top: 1px; left: 2px;">abcd</div>');
+       Utils.setSelection('div', 4);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<div style="position: absolute; top: 1px; left: 2px;"><p>abcd</p><p>\u00a0</p></div>');
+});
+
+test('Enter in div inside contentEditable:false div', function() {
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div>abcd</div></div>';
+       Utils.setSelection('div div', 2);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div>abcd</div></div>');
+});
+
+test('Enter in div with contentEditable:true inside contentEditable:false div', function() {
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true">abcd</div></div>';
+       Utils.setSelection('div div', 2);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><p>ab</p><p>cd</p></div></div>');
+});
+
+test('Enter in span with contentEditable:true inside contentEditable:false div', function() {
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
+       Utils.setSelection('span', 2);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>');
+});
+
+test('Shift+Enter in span with contentEditable:true inside contentEditable:false div', function() {
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
+       Utils.setSelection('span', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">ab<br>cd</span></div>');
+});
+
+test('Enter in span with contentEditable:true inside contentEditable:false div and forced_root_block: false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">abcd</span></div>';
+       Utils.setSelection('span', 2);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><span data-mce-contenteditable="true">ab<br>cd</span></div>');
+});
+
+test('Enter in em within contentEditable:true div inside contentEditable:false div', function() {
+       editor.getBody().innerHTML = '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><em>abcd</em></div></div>';
+       Utils.setSelection('em', 2);
+       Utils.pressEnter();
+       equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div data-mce-contenteditable="false"><div data-mce-contenteditable="true"><p><em>ab</em></p><p><em>cd</em></p></div></div>');
+});
+
+test('Enter at end of text in a span inside a P and keep_styles: false', function() {
+       editor.settings.keep_styles = false;
+       editor.getBody().innerHTML = '<p><em><span style="font-size: 13px;">X</span></em></p>';
+       Utils.setSelection('span', 1);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p><em><span style="font-size: 13px;">X</span></em></p><p>\u00a0</p>');
+});
+
+test('Shift+enter in LI when forced_root_block: false', function() {
+       editor.settings.forced_root_block = false;
+       editor.getBody().innerHTML = '<ul><li>text</li></ul>';
+       Utils.setSelection('li', 2);
+       Utils.pressEnter({shiftKey: true});
+       equal(editor.getContent(),'<ul><li>te<br />xt</li></ul>');
+});
+
+test('Enter when forced_root_block: false and force_p_newlines: true', function() {
+       editor.settings.forced_root_block = false;
+       editor.settings.force_p_newlines = true;
+       editor.getBody().innerHTML = 'text';
+       Utils.setSelection('body', 2);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<p>te</p><p>xt</p>');
+});
+
+test('Enter before BR between DIVs', function() {
+       editor.getBody().innerHTML = '<div>a<span>b</span>c</div><br /><div>d</div>';
+       var rng = editor.dom.createRng();
+       rng.setStartBefore(editor.dom.select('br')[0]);
+       rng.setEndBefore(editor.dom.select('br')[0]);
+       editor.selection.setRng(rng);
+       Utils.pressEnter();
+       equal(editor.getContent(),'<div>a<span>b</span>c</div><p>\u00a0</p><p>\u00a0</p><div>d</div>');
+});
+
+// Only test these on modern browsers
+if (window.getSelection) {
+       test('Enter behind table element', function() {
+               var rng = editor.dom.createRng();
+
+               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table>';
+               rng.setStartAfter(editor.getBody().lastChild);
+               rng.setEndAfter(editor.getBody().lastChild);
+               editor.selection.setRng(rng);
+
+               Utils.pressEnter();
+               equal(editor.getContent(),'<table><tbody><tr><td>x</td></tr></tbody></table><p>\u00a0</p>');
+       });
+
+       test('Enter before table element', function() {
+               var rng = editor.dom.createRng();
+
+               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table>';
+               rng.setStartBefore(editor.getBody().lastChild);
+               rng.setEndBefore(editor.getBody().lastChild);
+               editor.selection.setRng(rng);
+
+               Utils.pressEnter();
+               equal(editor.getContent(),'<p>\u00a0</p><table><tbody><tr><td>x</td></tr></tbody></table>');
+       });
+
+       test('Enter behind table followed by a p', function() {
+               var rng = editor.dom.createRng();
+
+               editor.getBody().innerHTML = '<table><tbody><td>x</td></tbody></table><p>x</p>';
+               rng.setStartAfter(editor.getBody().firstChild);
+               rng.setEndAfter(editor.getBody().firstChild);
+               editor.selection.setRng(rng);
+
+               Utils.pressEnter();
+               equal(editor.getContent(),'<table><tbody><tr><td>x</td></tr></tbody></table><p>\u00a0</p><p>x</p>');
+       });
+
+       test('Enter before table element preceded by a p', function() {
+               var rng = editor.dom.createRng();
+
+               editor.getBody().innerHTML = '<p>x</p><table><tbody><td>x</td></tbody></table>';
+               rng.setStartBefore(editor.getBody().lastChild);
+               rng.setStartBefore(editor.getBody().lastChild);
+               editor.selection.setRng(rng);
+
+               Utils.pressEnter();
+               equal(editor.getContent(),'<p>x</p><p>\u00a0</p><table><tbody><tr><td>x</td></tr></tbody></table>');
+       });
+}
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/EnterKey.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceForceBlockshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ForceBlocks.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ForceBlocks.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ForceBlocks.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,116 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceForceBlocksjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ForceBlocks.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ForceBlocks.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ForceBlocks.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+module("tinymce.ForceBlocks", {
+       autostart: false,
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       indent: false,
+                       skin: 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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       },
+
+       teardown: function() {
+               editor.settings.forced_root_block = 'p';
+               editor.settings.forced_root_block_attrs = null;
+       }
+});
+
+test('Wrap single root text node in P', function() {
+       editor.getBody().innerHTML = 'abcd';
+       Utils.setSelection('body', 2);
+       Utils.pressArrowKey();
+       equal(Utils.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';
+       Utils.setSelection('body', 2);
+       Utils.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>';
+       Utils.setSelection('body', 2);
+       Utils.pressArrowKey();
+       equal(Utils.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>';
+       Utils.setSelection('em', 2);
+       Utils.pressArrowKey();
+       equal(Utils.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';
+       Utils.setSelection('body', 2);
+       Utils.pressArrowKey();
+       equal(Utils.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>';
+       Utils.setSelection('body', 2);
+       body.insertBefore(editor.getDoc().createTextNode(''), body.firstChild);
+       body.appendChild(editor.getDoc().createTextNode(''));
+       Utils.pressArrowKey();
+       equal(Utils.cleanHtml(body.innerHTML), '<div>abcd</div><div>abcd</div>');
+       equal(editor.selection.getNode().nodeName, 'DIV');
+       equal(body.childNodes.length, 2);
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ForceBlocks.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceFormatter_applyhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/Formatter_apply.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_apply.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/Formatter_apply.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,1255 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Unit tests for apply 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, inlineEditor, rng, format;
-
-QUnit.config.reorder = false;
-QUnit.config.autostart = false;
-module("Apply formatting", {
-       autostart: false
-});
-
-function getContent() {
-       return editor.getContent().toLowerCase().replace(/[\r]+/g, '');
-};
-
-test('apply inline to a list', function(){
-       editor.formatter.register('format', {inline : 'b', toggle: false});
-       editor.getBody().innerHTML = '<p>1234</p><ul><li>first element</li><li>second element</li></ul><p>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>1234</b></p><ul><li><b>first element</b></li><li><b>second element</b></li></ul><p><b>5678</b></p>', 'selection of a list');
-});
-
-test('Toggle OFF - Inline element on selected text', function() {
-       // Toggle OFF - Inline element on selected text
-       editor.formatter.register('format', {inline : 'b', toggle: false});
-       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.toggle('format');
-       equal(getContent(), '<p><b>1234</b></p>');
-});
-
-test('Toggle OFF - Inline element on partially selected text', function() {
-       // Toggle OFF - Inline element on partially selected text
-       editor.formatter.register('format', {inline : 'b', toggle: 0});
-       editor.getBody().innerHTML = '<p>1<b>23</b>4</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('b')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('b')[0].firstChild, 2);
-       editor.selection.setRng(rng);
-       editor.formatter.toggle('format');
-       equal(getContent(), '<p>1<b>23</b>4</p>');
-});
-
-test('Toggle OFF - Inline element on partially selected text in start/end elements', function() {
-       // Toggle OFF - Inline element on partially selected text in start/end elements
-       editor.formatter.register('format', {inline : 'b', toggle: false});
-       editor.getBody().innerHTML = '<p>1<b>234</b></p><p><b>123</b>4</p>';//'<p>1234</p><p>1234</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.toggle('format');
-       equal(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
-});
-
-test('Toggle ON - NO inline element on selected text', function() {
-       // Inline element on selected text
-       editor.formatter.register('format', {inline : 'b', toggle: true});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>1234</b></p>', 'Inline element on selected text');
-       editor.formatter.toggle('format');
-       equal(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on selected text');
-});
-
-test('Selection spanning from within format to outside format with toggle off', function() {
-       editor.formatter.register('format', {inline : 'b', toggle: false});
-       editor.getBody().innerHTML = '<p><b>12</b>34</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('b')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
-       editor.selection.setRng(rng);
-       editor.formatter.toggle('format');
-       equal(getContent(), '<p><b>1234</b></p>', 'Extend formating if start of selection is already formatted');
-});
-
-test('Inline element on partially selected text', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>1234</p>';
-       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.formatter.apply('format');
-       equal(getContent(), '<p>1<b>23</b>4</p>', 'Inline element on partially selected text');
-       editor.formatter.toggle('format');
-       equal(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on partially selected text');
-});
-
-test('Inline element on partially selected text in start/end elements', function() {
-       // Inline element on partially selected text in start/end elements
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 1);
-       rng.setEnd(editor.dom.select('p')[1].firstChild, 3);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
-});
-
-test('Inline element on selected element', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>1234</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>1234</b></p>', 'Inline element on selected element');
-});
-
-test('Inline element on multiple selected elements', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>1234</b></p><p><b>1234</b></p>', 'Inline element on multiple selected elements');
-});
-
-test('Inline element on multiple selected elements with various childnodes', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><em>1234</em>5678<span>9</span></p><p><em>1234</em>5678<span>9</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b><em>1234</em>5678<span>9</span></b></p><p><b><em>1234</em>5678<span>9</span></b></p>', 'Inline element on multiple selected elements with various childnodes');
-});
-
-test('Inline element with attributes', function() {
-       editor.formatter.register('format', {inline : 'b', attributes : {title : 'value1', id : 'value2'}});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b id="value2" title="value1">1234</b></p>', 'Inline element with attributes');
-});
-
-test('Inline element with styles', function() {
-       editor.formatter.register('format', {inline : 'b', styles : {color : '#ff0000', fontSize : '10px'}});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b style=\"color: #ff0000; font-size: 10px;\">1234</b></p>', 'Inline element with styles');
-});
-
-test('Inline element with attributes and styles', function() {
-       editor.formatter.register('format', {inline : 'b', attributes : {title : 'value1', id : 'value2'}, styles : {color : '#ff0000', fontSize : '10px'}});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b id="value2" style="color: #ff0000; font-size: 10px;" title="value1">1234</b></p>', 'Inline element with attributes and styles');
-});
-
-test('Inline element with wrapable parents', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>x<em><span>1234</span></em>y</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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p>x<b><em><span>1234</span></em></b>y</p>', 'Inline element with wrapable parents');
-});
-
-test('Inline element with redundant child', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><b>1234</b></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.apply('format');
-       equal(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child');
-});
-
-test('Inline element with redundant parent', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><b>a<em>1234</em>b</b></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>a<em>1234</em>b</b></p>', 'Inline element with redundant parent');
-});
-
-test('Inline element with redundant child of similar type 1', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'strong'}
-       ]);
-       editor.getBody().innerHTML = '<p>a<strong>1234</strong>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0], 0);
-       rng.setEnd(editor.dom.select('p')[0], 3);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>a1234b</b></p>', 'Inline element with redundant child of similar type 1');
-});
-
-test('Inline element with redundant child of similar type 2', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'span', styles : {fontWeight : 'bold'}}
-       ]);
-       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.apply('format');
-       equal(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child of similar type 2');
-});
-
-test('Inline element with redundant children of similar types', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'strong'},
-               {inline : 'span', styles : {fontWeight : 'bold'}}
-       ]);
-       editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<strong>1234</strong><b>5678</b>b</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.apply('format');
-       equal(getContent(), '<p><b>a12345678b</b></p>', 'Inline element with redundant children of similar types');
-});
-
-test('Inline element with redundant parent 1', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'strong'}
-       ]);
-       editor.getBody().innerHTML = '<p><strong>a<em>1234</em>b</strong></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><strong>a<em>1234</em>b</strong></p>', 'Inline element with redundant parent 1');
-});
-
-test('Inline element with redundant parent 2', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'span', styles : {fontWeight : 'bold'}}
-       ]);
-       editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<em>1234</em>b</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="font-weight: bold;">a<em>1234</em>b</span></p>', 'Inline element with redundant parent 2');
-});
-
-test('Inline element with redundant parents of similar types', function() {
-       editor.formatter.register('format', [
-               {inline : 'b'},
-               {inline : 'strong'},
-               {inline : 'span', styles : {fontWeight : 'bold'}}
-       ]);
-       editor.getBody().innerHTML = '<p><span style="font-weight:bold"><strong><b>a<em>1234</em>b</b></strong></span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="font-weight: bold;"><strong><b>a<em>1234</em>b</b></strong></span></p>', 'Inline element with redundant parents of similar types');
-});
-
-test('Inline element merged with parent and child', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>a<b>12<b>34</b>56</b>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('b')[0].firstChild, 1);
-       rng.setEnd(editor.dom.select('b')[0].lastChild, 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p>a<b>123456</b>b</p>', 'Inline element merged with parent and child');
-});
-
-test('Inline element merged with child 1', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
-       editor.getBody().innerHTML = '<p>a<span style="font-weight:bold">1234</span>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="font-weight: bold;">a1234b</span></p>', 'Inline element merged with child 1');
-});
-
-test('Inline element merged with child 2', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
-       editor.getBody().innerHTML = '<p>a<span style="font-weight:bold; color:#ff0000">1234</span>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style=\"font-weight: bold;\">a<span style=\"color: #ff0000;\">1234</span>b</span></p>', 'Inline element merged with child 2');
-});
-
-test('Inline element merged with child 3', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}});
-       editor.getBody().innerHTML = '<p>a<span id="id" style="font-weight:bold">1234</span>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style=\"font-weight: bold;\">a<span id=\"id\">1234</span>b</span></p>', 'Inline element merged with child 3');
-});
-
-test('Inline element merged with child 3', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {fontWeight : 'bold'}, merge : true});
-       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="color: #ff0000; font-weight: bold;">1234</span></p>', 'Inline element merged with child 3');
-});
-
-test('Inline element merged with child 4', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {color : '#00ff00'}});
-       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="color: #00ff00;">1234</span></p>', 'Inline element merged with child 4');
-});
-
-test('Inline element with attributes merged with child 1', function() {
-       editor.formatter.register('format', {inline : 'font', attributes : {face : 'arial'}, merge : true});
-       editor.getBody().innerHTML = '<p><font size="7">1234</font></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><font face="arial" size="7">1234</font></p>', 'Inline element with attributes merged with child 1');
-});
-
-test('Inline element with attributes merged with child 2', function() {
-       editor.formatter.register('format', {inline : 'font', attributes : {size : '7'}});
-       editor.getBody().innerHTML = '<p>a<font size="7">1234</font>b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><font size="7">a1234b</font></p>', 'Inline element with attributes merged with child 2');
-});
-
-test('Inline element merged with left sibling', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><b>1234</b>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].lastChild, 0);
-       rng.setEnd(editor.dom.select('p')[0].lastChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with left sibling');
-});
-
-test('Inline element merged with right sibling', function() {
-       editor.formatter.register('format', {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('p')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with right sibling');
-});
-
-test('Inline element merged with left and right siblings', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><b>12</b>34<b>56</b></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].childNodes[1], 0);
-       rng.setEnd(editor.dom.select('p')[0].childNodes[1], 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>123456</b></p>', 'Inline element merged with left and right siblings');
-});
-
-test('Don\'t merge siblings with whitespace between 1', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><b>a</b> b</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].lastChild, 1);
-       rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 1');
-});
-
-test('Don\'t merge siblings with whitespace between 1', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>a <b>b</b></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.formatter.apply('format');
-       equal(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 2');
-});
-
-test('Inline element not merged in exact mode', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {color : '#00ff00'}, exact : true});
-       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="color: #00ff00;"><span style="color: #ff0000;">1234</span></span></p>', 'Inline element not merged in exact mode');
-});
-
-test('Inline element merged in exact mode', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {color : '#ff0000'}, exact : true});
-       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><span style="color: #ff0000;">1234</span></p>', 'Inline element merged in exact mode');
-});
-
-test('Deep left branch', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p><p><em>5678</em></p><p>9012</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('ins')[0].firstChild, 1);
-       rng.setEnd(editor.dom.select('p')[2].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><em><i><ins>1<b>234</b></ins></i></em><b><em>text1</em><em>text2</em></b></p><p><b><em>5678</em></b></p><p><b>9012</b></p>', 'Deep left branch');
-});
-
-test('Deep right branch', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>9012</p><p><em>5678</em></p><p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('em')[3].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>9012</b></p><p><b><em>5678</em></b></p><p><b><em><i><ins>1234</ins></i></em><em>text1</em></b><em><b>text</b>2</em></p>', 'Deep right branch');
-});
-
-test('Full element text selection on two elements with a table in the middle', function() {
-       editor.formatter.register('format', {inline : 'b'});
-       editor.getBody().innerHTML = '<p>1234</p><table><tbody><tr><td>123</td></tr></tbody></table><p>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><b>1234</b></p><table><tbody><tr><td><b>123</b></td></tr></tbody></table><p><b>5678</b></p>', 'Full element text selection on two elements with a table in the middle');
-});
-
-test('Inline element on selected text with variables', function() {
-       editor.formatter.register('format', {inline : 'b', styles : {color : '%color'}, attributes : {title : '%title'}}, {color : '#ff0000', title : 'title'});
-       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);
-       editor.formatter.apply('format', {color : '#ff0000', title : 'title'});
-       equal(getContent(), '<p><b style="color: #ff0000;" title="title">1234</b></p>', 'Inline element on selected text');
-});
-
-test('Remove redundant children', function() {
-       editor.formatter.register('format', {inline : 'span', styles : {fontFamily : 'arial'}});
-       editor.getBody().innerHTML = '<p><span style="font-family: sans-serif;"><span style="font-family: palatino;">1</span>2<span style="font-family: verdana;">3</span>4</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.apply('format');
-       equal(getContent(), '<p><span style=\"font-family: ' + fontFace('arial') + ';\">1234</span></p>', 'Remove redundant children');
-});
-
-test('Inline element on selected text with function values', function() {
-       editor.formatter.register('format', {
-               inline : 'b',
-               styles : {
-                       color : function(vars) {
-                               return vars.color + '00ff';
-                       }
-               },
-               attributes : {
-                       title : function(vars) {
-                               return vars.title + '2';
-                       }
-               }
-       });
-       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);
-       editor.formatter.apply('format', {
-               color : '#ff',
-               title : 'title'
-       });
-       equal(getContent(), '<p><b style="color: #ff00ff;" title="title2">1234</b></p>', 'Inline element on selected text with function values');
-});
-
-test('Block element on selected text', function() {
-       editor.formatter.register('format', {block : 'div'});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div>', 'Block element on selected text');
-});
-
-test('Block element on partially selected text', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '<p>1234</p>';
-       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.formatter.apply('format');
-       equal(getContent(), '<div>1234</div>', 'Block element on partially selected text');
-});
-
-test('Block element on selected element', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '<p>1234</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div>', 'Block element on selected element');
-});
-
-test('Block element on selected elements', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div><div>5678</div>', 'Block element on selected elements');
-});
-
-test('Block element on selected elements with attributes', function() {
-       editor.formatter.register('format', {block : 'div', attributes : {'title' : 'test'}});
-       editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div title="test">1234</div><div title="test">5678</div>', 'Block element on selected elements with attributes');
-});
-
-test('Block element on nested element', function() {
-       editor.formatter.register('format', {block : 'p'});
-       editor.getBody().innerHTML = '<div><h1>1234</h1></div>';
-       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.apply('format');
-       equal(getContent(), '<div><p>1234</p></div>', 'Block element on nested element');
-});
-
-test('Block element on selected non wrapped text 1', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '1234';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild, 0);
-       rng.setEnd(editor.getBody().firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div>', 'Block element on selected non wrapped text 1');
-});
-
-test('Block element on selected non wrapped text 2', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '1234<br />4567<br />8910';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody().firstChild, 0);
-       rng.setEnd(editor.getBody().lastChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 2');
-});
-
-test('Block element on selected non wrapped text 3', function() {
-       editor.formatter.register('format', {block : 'div'});
-       editor.getBody().innerHTML = '<br />1234<br /><br />4567<br />8910<br />';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 7);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 3');
-});
-
-test('Block element wrapper 1', function() {
-       editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
-       editor.getBody().innerHTML = '<h1>1234</h1><p>5678</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<blockquote><h1>1234</h1><p>5678</p></blockquote>', 'Block element wrapper 1');
-});
-
-test('Block element wrapper 2', function() {
-       editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
-       editor.getBody().innerHTML = '<h1>1234</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.apply('format');
-       equal(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 2');
-});
-
-test('Block element wrapper 3', function() {
-       editor.formatter.register('format', {block : 'blockquote', wrapper : 1});
-       editor.getBody().innerHTML = '<br /><h1>1234</h1><br />';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.getBody(), 0);
-       rng.setEnd(editor.getBody(), 3);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 3');
-});
-
-test('Apply format on single element that matches a selector 1', function() {
-       editor.formatter.register('format', {selector : 'p', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
-       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);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on single element that matches a selector');
-});
-
-test('Apply format on single element parent that matches a selector 2', function() {
-       editor.formatter.register('format', {selector : 'div', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
-       editor.getBody().innerHTML = '<div><p>1234</p><p>test</p><p>1234</p></div>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('div')[0], 1);
-       rng.setEnd(editor.dom.select('div')[0], 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div class="a b c" style="color: #ff0000;" title="test"><p>1234</p><p>test</p><p>1234</p></div>', 'Apply format on single element parent that matches a selector');
-});
-
-test('Apply format on multiple elements that matches a selector 2', function() {
-       editor.formatter.register('format', {selector : 'p', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
-       editor.getBody().innerHTML = '<p>1234</p><div>test</div><p>1234</p>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p><div>test</div><p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on multiple elements that matches a selector');
-});
-
-test('Apply format on top of existing selector element', function() {
-       editor.formatter.register('format', {selector : 'p', attributes : {title : 'test2'}, styles : {'color' : '#00ff00'}, classes : 'a b c'});
-       editor.getBody().innerHTML = '<p class=\"c d\" title=\"test\">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.formatter.apply('format');
-       equal(getContent(), '<p class="c d a b" style="color: #00ff00;" title="test2">1234</p>', 'Apply format on top of existing selector element');
-});
-
-test('Format on single li that matches a selector', function() {
-       editor.formatter.register('format', {inline : 'span', selector : 'li', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
-       editor.getBody().innerHTML = '<div>text</div>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('div')[0], 0);
-       rng.setEnd(editor.dom.select('div')[0], 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div><span class="a b c" style="color: #ff0000;" title="test">text</span></div>', 'Apply format on single element that matches a selector');
-});
-
-test('Format on single div that matches a selector', function() {
-       editor.formatter.register('format', {inline : 'span', selector : 'div', attributes : {title : 'test'}, styles : {'color' : '#ff0000'}, classes : 'a b c'});
-       editor.getBody().innerHTML = '<div>text</div>';
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('div')[0], 0);
-       rng.setEnd(editor.dom.select('div')[0], 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<div class="a b c" style="color: #ff0000;" title="test">text</div>', 'Apply format on single element that matches a selector');
-});
-
-test('Bold and italics is applied to text that is not highlighted', function() {
-       rng = editor.dom.createRng();
-       editor.setContent('<p><span style="font-family: Arial;"><strong>test1 test2</strong> test3 test4 test5 test6</span></p>');
-       rng.setStart(editor.dom.select('strong')[0].firstChild, 6);
-       rng.setEnd(editor.dom.select('strong')[0].firstChild, 11);
-       editor.focus();
-       editor.selection.setRng(rng);
-       editor.execCommand('Italic');
-       equal(editor.getContent(), '<p><span style="font-family: Arial;"><strong>test1 <em>test2</em></strong> test3 test4 test5 test6</span></p>', 'Selected text should be bold.');
-});
-
-test('No wrapping of links', function() {
-       editor.setContent('<p>123<a href="#">abc</a>456</p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[0].lastChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.formatter.register('format', {inline : 'span', styles : {color : '#FF0000'}, wrap_links : false});
-       editor.formatter.apply('format');
-
-       equal(editor.getContent(), '<p><span style="color: #ff0000;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
-});
-
-test('Color on link element', function() {
-       editor.setContent('<p><span style="font-size: 10px;">123<a href="#">abc</a>456</span></p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('span')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('span')[0].lastChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.formatter.register('format', {inline : 'span', styles : {color : '#FF0000'}, wrap_links : false});
-       editor.formatter.apply('format');
-
-       equal(editor.getContent(), '<p><span style="color: #ff0000; font-size: 10px;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
-});
-
-test("Applying formats in lists", function(){
-       editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('li')[0].firstChild, 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply("h1");
-       equal(editor.getContent(), '<ul><li><h1>text</h1><ul><li>nested</li></ul></li></ul>', "heading should not automatically apply to sublists");
-});
-
-test('Block format on li element', function() {
-       editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('li')[1].firstChild, 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply("h1");
-       equal(editor.getContent(), '<ul><li><h1>text</h1><ul><li><h1>nested</h1></li></ul></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
-});
-
-test('Block on li element 2', function() {
-       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('li')[0].lastChild, 1);
-       rng.setEnd(editor.dom.select('li')[0].lastChild, 2);
-       editor.selection.setRng(rng);
-       editor.formatter.apply("h1");
-       equal(editor.getContent(), '<ul><li>before<ul><li>nested</li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
-});
-
-test('Block on li element 3', function() {
-       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('li')[1].firstChild, 0);
-       rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply("h1");
-       equal(editor.getContent(), '<ul><li>before<ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
-});
-
-test('Block on li element 4', function() {
-       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
-       editor.selection.setRng(rng);
-       editor.formatter.apply("h1");
-       equal(editor.getContent(), '<ul><li><h1>before</h1><ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should apply correctly when selection is after a sublist");
-});
-
-test('Underline colors 1', function() {
-       editor.formatter.register('format', {inline: 'span', styles : {'color' : '#ff0000'}});
-       editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;">test</span></p>');
-       editor.execCommand('SelectAll');
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></p>', 'Coloring an underlined text should result in a colored underline');
-});
-
-test('Underline colors 2', function() {
-       editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
-       editor.setContent('<p><span style="font-family: \'arial black\'; color: rgb(255, 0, 0);">test</span></p>');
-       editor.execCommand('SelectAll');
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></span></p>', 'Underlining colored text should result in a colored underline');
-});
-
-test('Underline colors 3', function() {
-       editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
-       editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
-       editor.execCommand('SelectAll');
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p>', 'Underlining colored and underlined text should result in a colored underline');
-});
-
-test('Underline colors 4', function() {
-       editor.formatter.register('format', {inline: 'span', styles : {'color' : '#ff0000'}});
-       editor.setContent('<p style="font-size: 22pt;"><span style=\"text-decoration: underline;\"><span style=\"color: yellow; text-decoration: underline;\">yellowredyellow</span></span></p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('span')[1].firstChild, 6);
-       rng.setEnd(editor.dom.select('span')[1].firstChild, 9);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(getContent(), '<p style="font-size: 22pt;"><span style="text-decoration: underline;"><span style="color: yellow; text-decoration: underline;">yellow<span style="color: #ff0000; text-decoration: underline;">red</span>yellow</span></span></p>', 'Coloring an colored underdlined text should result in newly colored underline');
-});
-
-test('Underline colors 5', function() {
-       editor.formatter.register('format', {inline: "span", exact: true, styles: {'textDecoration' : 'underline'}});
-       editor.setContent('<p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('strong')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('span')[4].lastChild, 5);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong
 ></em> text</span></span></p>', 'Colored elements should be underlined when selection is across multiple paragraphs');
-});
-
-test('Underline colors 6', function() {
-       editor.formatter.register('format', {inline: 'span', exact: true, styles : {'color' : '#ff0000'}});
-       editor.setContent('<p><span style="text-decoration: underline;">This is some text.</span></p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('span')[0].firstChild, 8);
-       rng.setEnd(editor.dom.select('span')[0].firstChild, 12);
-       editor.selection.setRng(rng);
-       editor.formatter.apply('format');
-       editor.formatter.remove('format');
-       equal(editor.getContent(), '<p><span style="text-decoration: underline;">This is some text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
-});
-
-test('Underline colors 7', function() {
-       editor.formatter.register('format', {inline: 'span', exact: true, styles : {'color' : '#ff0000'}});
-       editor.setContent('<p><span style="text-decoration: underline;">This is <span style="color: #ff0000; text-decoration: underline; background-color: #ff0000">some</span> text.</span></p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('span')[1].firstChild, 0);
-       rng.setEnd(editor.dom.select('span')[1].firstChild, 4);
-       editor.selection.setRng(rng);
-       editor.formatter.remove('format');
-       equal(editor.getContent(), '<p><span style=\"text-decoration: underline;\">This is <span style=\"background-color: #ff0000;\">some</span> text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
-});
-
-test('Caret format inside single block word', function() {
-       editor.setContent('<p>abc</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 2, 'p', 2);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><b>abc</b></p>');
-});
-
-test('Caret format inside first block word', function() {
-       editor.setContent('<p>abc 123</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 2, 'p', 2);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><b>abc</b> 123</p>');
-});
-
-test('Caret format inside last block word', function() {
-       editor.setContent('<p>abc 123</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 5, 'p', 5);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc <b>123</b></p>');
-});
-
-test('Caret format inside middle block word', function() {
-       editor.setContent('<p>abc 123 456</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 5, 'p', 5);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc <b>123</b> 456</p>');
-});
-
-test('Caret format on word separated by non breaking space', function() {
-       editor.setContent('<p>one&nbsp;two</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 1, 'p', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><b>one</b>\u00a0two</p>');
-});
-
-test('Caret format inside single inline wrapped word', function() {
-       editor.setContent('<p>abc <em>123</em> 456</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('em', 1, 'em', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc <b><em>123</em></b> 456</p>');
-});
-
-test('Caret format inside word before similar format', function() {
-       editor.setContent('<p>abc 123 <b>456</b></p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 1, 'p', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><b>abc</b> 123 <b>456</b></p>');
-});
-
-test('Caret format inside last inline wrapped word', function() {
-       editor.setContent('<p>abc <em>abc 123</em> 456</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('em', 5, 'em', 5);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc <em>abc <b>123</b></em> 456</p>');
-});
-
-test('Caret format before text', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 0, 'p', 0);
-       editor.formatter.apply('format');
-       type('b');
-       equal(editor.getContent(), '<p><b>b</b>a</p>');
-});
-
-test('Caret format after text', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 1, 'p', 1);
-       editor.formatter.apply('format');
-       type('b');
-       equal(editor.getContent(), '<p>a<b>b</b></p>');
-});
-
-test('Caret format and no key press', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 0, 'p', 0);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>a</p>');
-});
-
-test('Caret format and arrow left', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 0, 'p', 0);
-       editor.formatter.apply('format');
-       type({keyCode: 37});
-       equal(editor.getContent(), '<p>a</p>');
-});
-
-test('Caret format and arrow right', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('p', 0, 'p', 0);
-       editor.formatter.apply('format');
-       type({keyCode: 39});
-       equal(editor.getContent(), '<p>a</p>');
-});
-
-test('Caret format and backspace', function() {
-       var rng;
-
-       if (tinymce.isOpera) {
-               ok(true, "Skip Opera since faking backspace doesn't work.");
-               return;
-       }
-
-       editor.formatter.register('format', {inline: 'b'});
-
-       editor.setContent('<p>abc</p>');
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 3);
-       rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
-       editor.selection.setRng(rng);
-
-       editor.formatter.apply('format');
-       type('\b');
-       equal(editor.getContent(), '<p>ab</p>');
-});
-
-test('Caret format on word in li with word in parent li before it', function() {
-       editor.setContent('<ul><li>one<ul><li>two</li></ul></li></ul>');
-       editor.formatter.register('format', {inline: 'b'});
-       setSelection('ul li li', 1, 'ul li li', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<ul><li>one<ul><li><b>two</b></li></ul></li></ul>');
-});
-
-test('Selector format on whole contents', function() {
-       editor.setContent('<p>a</p>');
-       editor.formatter.register('format', {inline: 'span', selector: '*', classes: 'test'});
-       setSelection('p', 0, 'p', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p class="test">a</p>');
-});
-
-test('format inline on contentEditable: false block', function() {
-       editor.formatter.register('format', {inline: 'b'});
-       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
-       setSelection('p:nth-child(2)', 0, 'p:nth-child(2)', 3);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc</p><p>def</p>', 'Text is not bold');
-});
-
-test('format block on contentEditable: false block', function() {
-       editor.formatter.register('format', {block: 'h1'});
-       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
-       setSelection('p:nth-child(2)', 0, 'p:nth-child(2)', 3);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc</p><p>def</p>', 'P is not h1');
-});
-
-test('contentEditable: false on start and contentEditable: true on end', function() {
-       editor.formatter.register('format', {inline: 'b'});
-       editor.setContent('<p>abc</p><p contenteditable="false">def</p><p>ghi</p>');
-       setSelection('p:nth-child(2)', 0, 'p:nth-child(3)', 3);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc</p><p>def</p><p><b>ghi</b></p>', 'Text in last paragraph is bold');
-});
-
-test('contentEditable: true on start and contentEditable: false on end', function() {
-       editor.formatter.register('format', {inline: 'b'});
-       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
-       setSelection('p:nth-child(1)', 0, 'p:nth-child(2)', 3);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><b>abc</b></p><p>def</p>', 'Text in first paragraph is 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">def</span></p>');
-       setSelection('span', 0, 'span', 3);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p>abc</p><p><span><b>def</b></span></p>', 'Text is bold');
-});
-
-test('Del element wrapping blocks', function() {
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.formatter.register('format', {block : 'del', wrapper: true});
-       editor.formatter.apply('format');
-       equal(getContent(), '<del><p>a</p></del>');
-});
-
-test('Del element replacing block', function() {
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.formatter.register('format', {block : 'del'});
-       editor.formatter.apply('format');
-       equal(getContent(), '<del>a</del>');
-});
-
-test('Del element as inline', function() {
-       editor.setContent('<p>a</p>');
-       setSelection('p', 0, 'p', 1);
-       editor.formatter.register('format', {inline : 'del'});
-       editor.formatter.apply('format');
-       equal(getContent(), '<p><del>a</del></p>');
-});
-
-test('Align specified table element with collapsed: false and selection collapsed', function() {
-       editor.setContent('<table><tr><td>a</td></tr></table>');
-       setSelection('td', 0, 'td', 0);
-       editor.formatter.register('format', {selector: 'table', collapsed: false, styles: {'float': 'right'}});
-       editor.formatter.apply('format', {}, editor.getBody().firstChild);
-       equal(getContent(), '<table style="float: right;"><tbody><tr><td>a</td></tr></tbody></table>');
-});
-
-test('Apply ID format to around existing bookmark node', function() {
-       editor.getBody().innerHTML = '<p>a<span id="b" data-mce-type="bookmark"></span>b</p>';
-
-       rng = editor.dom.createRng();
-       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
-       rng.setEnd(editor.dom.select('p')[0].lastChild, 1);
-       editor.selection.setRng(rng);
-
-       editor.formatter.register('format', {inline: 'span', attributes: {id: 'id'}});
-       editor.formatter.apply('format');
-
-       equal(normalizeHtml(editor.getBody().innerHTML), '<p><span id="id">a<span data-mce-type="bookmark" id="b"></span>b</span></p>');
-});
-
-test('Bug #5134 - TinyMCE removes formatting tags in the getContent', function() {
-       editor.setContent('');
-       editor.formatter.register('format', {inline : 'strong', toggle: false});
-       editor.formatter.apply('format');
-       equal(getContent(), '', 'empty TinyMCE');
-       editor.selection.setContent('a');
-       equal(getContent(), '<strong>a</strong>', 'bold text inside TinyMCE');
-});
-
-test('Bug #5134 - TinyMCE removes formatting tags in the getContent - typing', function() {
-       editor.setContent('');
-       editor.formatter.register('format', {inline : 'strong', toggle: false});
-       editor.formatter.apply('format');
-       equal(getContent(), '', 'empty TinyMCE');
-       type('a');
-       equal(getContent(), '<strong>a</strong>', 'bold text inside TinyMCE');
-});
-
-test('Bug #5453 - TD contents with BR gets wrapped in block format', function() {
-       editor.setContent('<table><tr><td>abc<br />123</td></tr></table>');
-       setSelection('td', 1, 'td', 1);
-       editor.formatter.register('format', {block : 'h1'});
-       editor.formatter.apply('format');
-       equal(getContent(), '<table><tbody><tr><td><h1>abc</h1>123</td></tr></tbody></table>');
-});
-
-test('Bug #6471 - Merge left/right style properties', function() {
-       editor.formatter.register('format', {inline: 'span', styles: {fontWeight: 'bold'}});
-       editor.setContent('<p>abc</p>');
-       setSelection('p', 2, 'p', 3);
-       editor.formatter.apply('format');
-       setSelection('p', 1, 'p', 2);
-       editor.formatter.apply('format');
-       setSelection('p', 0, 'p', 1);
-       editor.formatter.apply('format');
-       equal(editor.getContent(), '<p><span style="font-weight: bold;">abc</span></p>');
-});
-
-test('Bug #6518 - Apply div blocks to inline editor paragraph', function() {
-       inlineEditor.setContent('<p>a</p><p>b</p>');
-       inlineEditor.selection.select(inlineEditor.getBody().firstChild, true);
-       inlineEditor.selection.collapse(true);
-       inlineEditor.formatter.register('format', {block: 'div'});
-       inlineEditor.formatter.apply('format');
-       equal(inlineEditor.getContent(), '<div>a</div><p>b</p>');
-});
-
-// WP
-var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
-
-tinymce.init({
-       selector: "#elm1",
-       // WP
-       external_plugins: {
-               noneditable: url + 'external-plugins/noneditable/plugin.js'
-       },
-       // WP end
-       add_unload_trigger: false,
-       indent: 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|codeba
 se|*],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',
-       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) {
-               editor = ed;
-
-               if (inlineEditor) {
-                       QUnit.start();
-               }
-       }
-});
-
-tinymce.init({
-       selector: "#elm2",
-       inline: true,
-       // WP
-       external_plugins: {
-               noneditable: url + 'external-plugins/noneditable/plugin.js'
-       },
-       // WP end
-       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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceFormatter_applyjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/Formatter_apply.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_apply.js                              (rev 0)
+++ trunk/tests/qunit/editor/tinymce/Formatter_apply.js 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,1600 @@
</span><ins>+module("tinymce.Formatter - Apply", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div>';
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "#elm1",
+                       external_plugins: {
+                               noneditable: '../../../../tests/qunit/editor/external-plugins/noneditable/plugin.min.js'
+                       },
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       extended_valid_elements: 'b[id|style|title],i[id|style|title],span[id|class|style|title|contenteditable],font[face|size]',
+                       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) {
+                               window.editor = ed;
+
+                               if (window.inlineEditor) {
+                                       QUnit.start();
+                               }
+                       }
+               });
+
+               tinymce.init({
+                       selector: "#elm2",
+                       inline: true,
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       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) {
+                               window.inlineEditor = ed;
+
+                               if (window.editor) {
+                                       QUnit.start();
+                               }
+                       }
+               });
+       }
+});
+
+function getContent() {
+       return editor.getContent().toLowerCase().replace(/[\r]+/g, '');
+}
+
+test('apply inline to a list', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: false
+       });
+       editor.getBody().innerHTML = '<p>1234</p><ul><li>first element</li><li>second element</li></ul><p>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>1234</b></p><ul><li><b>first element</b></li><li><b>second element</b></li></ul><p><b>5678</b></p>', 'selection of a list');
+});
+
+test('Toggle OFF - Inline element on selected text', function() {
+       // Toggle OFF - Inline element on selected text
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: false
+       });
+       editor.getBody().innerHTML = '<p><b>1234</b></p>';
+       var 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.toggle('format');
+       equal(getContent(), '<p><b>1234</b></p>');
+});
+
+test('Toggle OFF - Inline element on partially selected text', function() {
+       // Toggle OFF - Inline element on partially selected text
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: 0
+       });
+       editor.getBody().innerHTML = '<p>1<b>23</b>4</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('b')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('b')[0].firstChild, 2);
+       editor.selection.setRng(rng);
+       editor.formatter.toggle('format');
+       equal(getContent(), '<p>1<b>23</b>4</p>');
+});
+
+test('Toggle OFF - Inline element on partially selected text in start/end elements', function() {
+       // Toggle OFF - Inline element on partially selected text in start/end elements
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: false
+       });
+       editor.getBody().innerHTML = '<p>1<b>234</b></p><p><b>123</b>4</p>'; //'<p>1234</p><p>1234</p>';
+       var 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.toggle('format');
+       equal(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
+});
+
+test('Toggle ON - NO inline element on selected text', function() {
+       // Inline element on selected text
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: true
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b>1234</b></p>', 'Inline element on selected text');
+       editor.formatter.toggle('format');
+       equal(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on selected text');
+});
+
+test('Selection spanning from within format to outside format with toggle off', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               toggle: false
+       });
+       editor.getBody().innerHTML = '<p><b>12</b>34</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('b')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
+       editor.selection.setRng(rng);
+       editor.formatter.toggle('format');
+       equal(getContent(), '<p><b>1234</b></p>', 'Extend formating if start of selection is already formatted');
+});
+
+test('Inline element on partially selected text', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.formatter.apply('format');
+       equal(getContent(), '<p>1<b>23</b>4</p>', 'Inline element on partially selected text');
+       editor.formatter.toggle('format');
+       equal(getContent(), '<p>1234</p>', 'Toggle ON - NO inline element on partially selected text');
+});
+
+test('Inline element on partially selected text in start/end elements', function() {
+       // Inline element on partially selected text in start/end elements
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 1);
+       rng.setEnd(editor.dom.select('p')[1].firstChild, 3);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p>1<b>234</b></p><p><b>123</b>4</p>');
+});
+
+test('Inline element on selected element', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>1234</b></p>', 'Inline element on selected element');
+});
+
+test('Inline element on multiple selected elements', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234</p><p>1234</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>1234</b></p><p><b>1234</b></p>', 'Inline element on multiple selected elements');
+});
+
+test('Inline element on multiple selected elements with various childnodes', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><em>1234</em>5678<span>9</span></p><p><em>1234</em>5678<span>9</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b><em>1234</em>5678<span>9</span></b></p><p><b><em>1234</em>5678<span>9</span></b></p>', 'Inline element on multiple selected elements with various childnodes');
+});
+
+test('Inline element with attributes', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               attributes: {
+                       title: 'value1',
+                       id: 'value2'
+               }
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b id="value2" title="value1">1234</b></p>', 'Inline element with attributes');
+});
+
+test('Inline element with styles', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               styles: {
+                       color: '#ff0000',
+                       fontSize: '10px'
+               }
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b style=\"color: #ff0000; font-size: 10px;\">1234</b></p>', 'Inline element with styles');
+});
+
+test('Inline element with attributes and styles', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               attributes: {
+                       title: 'value1',
+                       id: 'value2'
+               },
+               styles: {
+                       color: '#ff0000',
+                       fontSize: '10px'
+               }
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b id="value2" style="color: #ff0000; font-size: 10px;" title="value1">1234</b></p>', 'Inline element with attributes and styles');
+});
+
+test('Inline element with wrapable parents', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>x<em><span>1234</span></em>y</p>';
+       var 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);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p>x<b><em><span>1234</span></em></b>y</p>', 'Inline element with wrapable parents');
+});
+
+test('Inline element with redundant child', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><b>1234</b></p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child');
+});
+
+test('Inline element with redundant parent', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><b>a<em>1234</em>b</b></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>a<em>1234</em>b</b></p>', 'Inline element with redundant parent');
+});
+
+test('Inline element with redundant child of similar type 1', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'strong'
+       }]);
+       editor.getBody().innerHTML = '<p>a<strong>1234</strong>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0], 0);
+       rng.setEnd(editor.dom.select('p')[0], 3);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>a1234b</b></p>', 'Inline element with redundant child of similar type 1');
+});
+
+test('Inline element with redundant child of similar type 2', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       }]);
+       editor.getBody().innerHTML = '<p><span style="font-weight:bold">1234</span></p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b>1234</b></p>', 'Inline element with redundant child of similar type 2');
+});
+
+test('Inline element with redundant children of similar types', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'strong'
+       }, {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       }]);
+       editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<strong>1234</strong><b>5678</b>b</span></p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b>a12345678b</b></p>', 'Inline element with redundant children of similar types');
+});
+
+test('Inline element with redundant parent 1', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'strong'
+       }]);
+       editor.getBody().innerHTML = '<p><strong>a<em>1234</em>b</strong></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><strong>a<em>1234</em>b</strong></p>', 'Inline element with redundant parent 1');
+});
+
+test('Inline element with redundant parent 2', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       }]);
+       editor.getBody().innerHTML = '<p><span style="font-weight:bold">a<em>1234</em>b</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="font-weight: bold;">a<em>1234</em>b</span></p>', 'Inline element with redundant parent 2');
+});
+
+test('Inline element with redundant parents of similar types', function() {
+       editor.formatter.register('format', [{
+               inline: 'b'
+       }, {
+               inline: 'strong'
+       }, {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       }]);
+       editor.getBody().innerHTML = '<p><span style="font-weight:bold"><strong><b>a<em>1234</em>b</b></strong></span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('em')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('em')[0].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="font-weight: bold;"><strong><b>a<em>1234</em>b</b></strong></span></p>', 'Inline element with redundant parents of similar types');
+});
+
+test('Inline element merged with parent and child', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>a<b>12<b>34</b>56</b>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('b')[0].firstChild, 1);
+       rng.setEnd(editor.dom.select('b')[0].lastChild, 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p>a<b>123456</b>b</p>', 'Inline element merged with parent and child');
+});
+
+test('Inline element merged with child 1', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       });
+       editor.getBody().innerHTML = '<p>a<span style="font-weight:bold">1234</span>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="font-weight: bold;">a1234b</span></p>', 'Inline element merged with child 1');
+});
+
+test('Inline element merged with child 2', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       });
+       editor.getBody().innerHTML = '<p>a<span style="font-weight:bold; color:#ff0000">1234</span>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style=\"font-weight: bold;\">a<span style=\"color: #ff0000;\">1234</span>b</span></p>', 'Inline element merged with child 2');
+});
+
+test('Inline element merged with child 3', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       });
+       editor.getBody().innerHTML = '<p>a<span id="id" style="font-weight:bold">1234</span>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style=\"font-weight: bold;\">a<span id=\"id\">1234</span>b</span></p>', 'Inline element merged with child 3');
+});
+
+test('Inline element merged with child 3', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               },
+               merge: true
+       });
+       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="color: #ff0000; font-weight: bold;">1234</span></p>', 'Inline element merged with child 3');
+});
+
+test('Inline element merged with child 4', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       color: '#00ff00'
+               }
+       });
+       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="color: #00ff00;">1234</span></p>', 'Inline element merged with child 4');
+});
+
+test('Inline element with attributes merged with child 1', function() {
+       editor.formatter.register('format', {
+               inline: 'font',
+               attributes: {
+                       face: 'arial'
+               },
+               merge: true
+       });
+       editor.getBody().innerHTML = '<p><font size="7">1234</font></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><font face="arial" size="7">1234</font></p>', 'Inline element with attributes merged with child 1');
+});
+
+test('Inline element with attributes merged with child 2', function() {
+       editor.formatter.register('format', {
+               inline: 'font',
+               attributes: {
+                       size: '7'
+               }
+       });
+       editor.getBody().innerHTML = '<p>a<font size="7">1234</font>b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><font size="7">a1234b</font></p>', 'Inline element with attributes merged with child 2');
+});
+
+test('Inline element merged with left sibling', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><b>1234</b>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].lastChild, 0);
+       rng.setEnd(editor.dom.select('p')[0].lastChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with left sibling');
+});
+
+test('Inline element merged with right sibling', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234<b>5678</b></p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><b>12345678</b></p>', 'Inline element merged with right sibling');
+});
+
+test('Inline element merged with left and right siblings', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><b>12</b>34<b>56</b></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].childNodes[1], 0);
+       rng.setEnd(editor.dom.select('p')[0].childNodes[1], 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>123456</b></p>', 'Inline element merged with left and right siblings');
+});
+
+test('Don\'t merge siblings with whitespace between 1', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><b>a</b> b</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].lastChild, 1);
+       rng.setEnd(editor.dom.select('p')[0].lastChild, 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 1');
+});
+
+test('Don\'t merge siblings with whitespace between 1', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>a <b>b</b></p>';
+       var 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.formatter.apply('format');
+       equal(getContent(), '<p><b>a</b> <b>b</b></p>', 'Don\'t merge siblings with whitespace between 2');
+});
+
+test('Inline element not merged in exact mode', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       color: '#00ff00'
+               },
+               exact: true
+       });
+       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="color: #00ff00;"><span style="color: #ff0000;">1234</span></span></p>', 'Inline element not merged in exact mode');
+});
+
+test('Inline element merged in exact mode', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       color: '#ff0000'
+               },
+               exact: true
+       });
+       editor.getBody().innerHTML = '<p><span style="color:#ff0000">1234</span></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><span style="color: #ff0000;">1234</span></p>', 'Inline element merged in exact mode');
+});
+
+test('Deep left branch', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p><p><em>5678</em></p><p>9012</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('ins')[0].firstChild, 1);
+       rng.setEnd(editor.dom.select('p')[2].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><em><i><ins>1<b>234</b></ins></i></em><b><em>text1</em><em>text2</em></b></p><p><b><em>5678</em></b></p><p><b>9012</b></p>', 'Deep left branch');
+});
+
+test('Deep right branch', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>9012</p><p><em>5678</em></p><p><em><i><ins>1234</ins></i></em><em>text1</em><em>text2</em></p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('em')[3].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>9012</b></p><p><b><em>5678</em></b></p><p><b><em><i><ins>1234</ins></i></em><em>text1</em></b><em><b>text</b>2</em></p>', 'Deep right branch');
+});
+
+test('Full element text selection on two elements with a table in the middle', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.getBody().innerHTML = '<p>1234</p><table><tbody><tr><td>123</td></tr></tbody></table><p>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><b>1234</b></p><table><tbody><tr><td><b>123</b></td></tr></tbody></table><p><b>5678</b></p>', 'Full element text selection on two elements with a table in the middle');
+});
+
+test('Inline element on selected text with variables', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               styles: {
+                       color: '%color'
+               },
+               attributes: {
+                       title: '%title'
+               }
+       }, {
+               color: '#ff0000',
+               title: 'title'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format', {
+               color: '#ff0000',
+               title: 'title'
+       });
+       equal(getContent(), '<p><b style="color: #ff0000;" title="title">1234</b></p>', 'Inline element on selected text');
+});
+
+test('Remove redundant children', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontFamily: 'arial'
+               }
+       });
+       editor.getBody().innerHTML = '<p><span style="font-family: sans-serif;"><span style="font-family: palatino;">1</span>2<span style="font-family: verdana;">3</span>4</span></p>';
+       var 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.apply('format');
+       equal(getContent(), '<p><span style=\"font-family: ' + Utils.fontFace('arial') + ';\">1234</span></p>', 'Remove redundant children');
+});
+
+test('Inline element on selected text with function values', function() {
+       editor.formatter.register('format', {
+               inline: 'b',
+               styles: {
+                       color: function(vars) {
+                               return vars.color + '00ff';
+                       }
+               },
+               attributes: {
+                       title: function(vars) {
+                               return vars.title + '2';
+                       }
+               }
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format', {
+               color: '#ff',
+               title: 'title'
+       });
+       equal(getContent(), '<p><b style="color: #ff00ff;" title="title2">1234</b></p>', 'Inline element on selected text with function values');
+});
+
+test('Block element on selected text', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<div>1234</div>', 'Block element on selected text');
+});
+
+test('Block element on partially selected text', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.formatter.apply('format');
+       equal(getContent(), '<div>1234</div>', 'Block element on partially selected text');
+});
+
+test('Block element on selected element', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div>1234</div>', 'Block element on selected element');
+});
+
+test('Block element on selected elements', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div>1234</div><div>5678</div>', 'Block element on selected elements');
+});
+
+test('Block element on selected elements with attributes', function() {
+       editor.formatter.register('format', {
+               block: 'div',
+               attributes: {
+                       'title': 'test'
+               }
+       });
+       editor.getBody().innerHTML = '<p>1234</p><p>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div title="test">1234</div><div title="test">5678</div>', 'Block element on selected elements with attributes');
+});
+
+test('Block element on nested element', function() {
+       editor.formatter.register('format', {
+               block: 'p'
+       });
+       editor.getBody().innerHTML = '<div><h1>1234</h1></div>';
+       var 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.apply('format');
+       equal(getContent(), '<div><p>1234</p></div>', 'Block element on nested element');
+});
+
+test('Block element on selected non wrapped text 1', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '1234';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild, 0);
+       rng.setEnd(editor.getBody().firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div>1234</div>', 'Block element on selected non wrapped text 1');
+});
+
+test('Block element on selected non wrapped text 2', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '1234<br />4567<br />8910';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody().firstChild, 0);
+       rng.setEnd(editor.getBody().lastChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 2');
+});
+
+test('Block element on selected non wrapped text 3', function() {
+       editor.formatter.register('format', {
+               block: 'div'
+       });
+       editor.getBody().innerHTML = '<br />1234<br /><br />4567<br />8910<br />';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 7);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div>1234</div><div>4567</div><div>8910</div>', 'Block element on selected non wrapped text 3');
+});
+
+test('Block element wrapper 1', function() {
+       editor.formatter.register('format', {
+               block: 'blockquote',
+               wrapper: 1
+       });
+       editor.getBody().innerHTML = '<h1>1234</h1><p>5678</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('h1')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[0].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<blockquote><h1>1234</h1><p>5678</p></blockquote>', 'Block element wrapper 1');
+});
+
+test('Block element wrapper 2', function() {
+       editor.formatter.register('format', {
+               block: 'blockquote',
+               wrapper: 1
+       });
+       editor.getBody().innerHTML = '<h1>1234</h1>';
+       var 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.apply('format');
+       equal(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 2');
+});
+
+test('Block element wrapper 3', function() {
+       editor.formatter.register('format', {
+               block: 'blockquote',
+               wrapper: 1
+       });
+       editor.getBody().innerHTML = '<br /><h1>1234</h1><br />';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.getBody(), 0);
+       rng.setEnd(editor.getBody(), 3);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<blockquote><h1>1234</h1></blockquote>', 'Block element wrapper 3');
+});
+
+test('Apply format on single element that matches a selector 1', function() {
+       editor.formatter.register('format', {
+               selector: 'p',
+               attributes: {
+                       title: 'test'
+               },
+               styles: {
+                       'color': '#ff0000'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<p>1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on single element that matches a selector');
+});
+
+test('Apply format on single element parent that matches a selector 2', function() {
+       editor.formatter.register('format', {
+               selector: 'div',
+               attributes: {
+                       title: 'test'
+               },
+               styles: {
+                       'color': '#ff0000'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<div><p>1234</p><p>test</p><p>1234</p></div>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('div')[0], 1);
+       rng.setEnd(editor.dom.select('div')[0], 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div class="a b c" style="color: #ff0000;" title="test"><p>1234</p><p>test</p><p>1234</p></div>', 'Apply format on single element parent that matches a selector');
+});
+
+test('Apply format on multiple elements that matches a selector 2', function() {
+       editor.formatter.register('format', {
+               selector: 'p',
+               attributes: {
+                       title: 'test'
+               },
+               styles: {
+                       'color': '#ff0000'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<p>1234</p><div>test</div><p>1234</p>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[1].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p class="a b c" style="color: #ff0000;" title="test">1234</p><div>test</div><p class="a b c" style="color: #ff0000;" title="test">1234</p>', 'Apply format on multiple elements that matches a selector');
+});
+
+test('Apply format on top of existing selector element', function() {
+       editor.formatter.register('format', {
+               selector: 'p',
+               attributes: {
+                       title: 'test2'
+               },
+               styles: {
+                       'color': '#00ff00'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<p class=\"c d\" title=\"test\">1234</p>';
+       var 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.apply('format');
+       equal(getContent(), '<p class="c d a b" style="color: #00ff00;" title="test2">1234</p>', 'Apply format on top of existing selector element');
+});
+
+test('Format on single li that matches a selector', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               selector: 'li',
+               attributes: {
+                       title: 'test'
+               },
+               styles: {
+                       'color': '#ff0000'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<div>text</div>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('div')[0], 0);
+       rng.setEnd(editor.dom.select('div')[0], 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div><span class="a b c" style="color: #ff0000;" title="test">text</span></div>', 'Apply format on single element that matches a selector');
+});
+
+test('Format on single div that matches a selector', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               selector: 'div',
+               attributes: {
+                       title: 'test'
+               },
+               styles: {
+                       'color': '#ff0000'
+               },
+               classes: 'a b c'
+       });
+       editor.getBody().innerHTML = '<div>text</div>';
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('div')[0], 0);
+       rng.setEnd(editor.dom.select('div')[0], 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<div class="a b c" style="color: #ff0000;" title="test">text</div>', 'Apply format on single element that matches a selector');
+});
+
+test('Bold and italics is applied to text that is not highlighted', function() {
+       var rng = editor.dom.createRng();
+       editor.setContent('<p><span style="font-family: Arial;"><strong>test1 test2</strong> test3 test4 test5 test6</span></p>');
+       rng.setStart(editor.dom.select('strong')[0].firstChild, 6);
+       rng.setEnd(editor.dom.select('strong')[0].firstChild, 11);
+       editor.focus();
+       editor.selection.setRng(rng);
+       editor.execCommand('Italic');
+       equal(editor.getContent(), '<p><span style="font-family: Arial;"><strong>test1 <em>test2</em></strong> test3 test4 test5 test6</span></p>', 'Selected text should be bold.');
+});
+
+test('No wrapping of links', function() {
+       editor.setContent('<p>123<a href="#">abc</a>456</p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[0].lastChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       color: '#FF0000'
+               },
+               wrap_links: false
+       });
+       editor.formatter.apply('format');
+
+       equal(editor.getContent(), '<p><span style="color: #ff0000;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
+});
+
+test('Color on link element', function() {
+       editor.setContent('<p><span style="font-size: 10px;">123<a href="#">abc</a>456</span></p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('span')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('span')[0].lastChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       color: '#FF0000'
+               },
+               wrap_links: false
+       });
+       editor.formatter.apply('format');
+
+       equal(editor.getContent(), '<p><span style="color: #ff0000; font-size: 10px;">123<a href="#"><span style="color: #ff0000;">abc</span></a>456</span></p>', 'Link should have it\'s own span.');
+});
+
+test("Applying formats in lists", function() {
+       editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('li')[0].firstChild, 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply("h1");
+       equal(editor.getContent(), '<ul><li><h1>text</h1><ul><li>nested</li></ul></li></ul>', "heading should not automatically apply to sublists");
+});
+
+test('Block format on li element', function() {
+       editor.setContent('<ul><li>text<ul><li>nested</li></ul></li></ul>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('li')[1].firstChild, 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply("h1");
+       equal(editor.getContent(), '<ul><li><h1>text</h1><ul><li><h1>nested</h1></li></ul></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
+});
+
+test('Block on li element 2', function() {
+       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('li')[0].lastChild, 1);
+       rng.setEnd(editor.dom.select('li')[0].lastChild, 2);
+       editor.selection.setRng(rng);
+       editor.formatter.apply("h1");
+       equal(editor.getContent(), '<ul><li>before<ul><li>nested</li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
+});
+
+test('Block on li element 3', function() {
+       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('li')[1].firstChild, 0);
+       rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply("h1");
+       equal(editor.getContent(), '<ul><li>before<ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should automatically apply to sublists, when selection spans the sublist");
+});
+
+test('Block on li element 4', function() {
+       editor.setContent('<ul><li>before<ul><li>nested</li></ul>after</li></ul>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('li')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('li')[0].lastChild, 1);
+       editor.selection.setRng(rng);
+       editor.formatter.apply("h1");
+       equal(editor.getContent(), '<ul><li><h1>before</h1><ul><li><h1>nested</h1></li></ul><h1>after</h1></li></ul>', "heading should apply correctly when selection is after a sublist");
+});
+
+test('Underline colors 1', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       'color': '#ff0000'
+               }
+       });
+       editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;">test</span></p>');
+       editor.execCommand('SelectAll');
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></p>', 'Coloring an underlined text should result in a colored underline');
+});
+
+test('Underline colors 2', function() {
+       editor.formatter.register('format', {
+               inline: "span",
+               exact: true,
+               styles: {
+                       'textDecoration': 'underline'
+               }
+       });
+       editor.setContent('<p><span style="font-family: \'arial black\'; color: rgb(255, 0, 0);">test</span></p>');
+       editor.execCommand('SelectAll');
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="color: #ff0000; font-family: \'arial black\'; text-decoration: underline;">test</span></span></p>', 'Underlining colored text should result in a colored underline');
+});
+
+test('Underline colors 3', function() {
+       editor.formatter.register('format', {
+               inline: "span",
+               exact: true,
+               styles: {
+                       'textDecoration': 'underline'
+               }
+       });
+       editor.setContent('<p><span style="font-family: \'arial black\'; text-decoration: underline;"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
+       editor.execCommand('SelectAll');
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p>', 'Underlining colored and underlined text should result in a colored underline');
+});
+
+test('Underline colors 4', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       'color': '#ff0000'
+               }
+       });
+       editor.setContent('<p style="font-size: 22pt;"><span style=\"text-decoration: underline;\"><span style=\"color: yellow; text-decoration: underline;\">yellowredyellow</span></span></p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('span')[1].firstChild, 6);
+       rng.setEnd(editor.dom.select('span')[1].firstChild, 9);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(getContent(), '<p style="font-size: 22pt;"><span style="text-decoration: underline;"><span style="color: yellow;' +
+               ' text-decoration: underline;">yellow<span style="color: #ff0000; text-decoration: underline;">red</span>yellow</span></span></p>',
+               'Coloring an colored underdlined text should result in newly colored underline'
+       );
+});
+
+test('Underline colors 5', function() {
+       editor.formatter.register('format', {
+               inline: "span",
+               exact: true,
+               styles: {
+                       'textDecoration': 'underline'
+               }
+       });
+       editor.setContent('<p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p><p><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: rgb(255, 0, 0);">example</span></strong></em> text</span></p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('strong')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('span')[4].lastChild, 5);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\',\'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong></em> text</span></span></p><p><span style="text-decoration: underline;"><span style="font-family: \'arial black\', \'avant garde\';"><em><strong>This is some <span style="color: #ff0000; text-decoration: underline;">example</span></strong
 ></em> text</span></span></p>', 'Colored elements should be underlined when selection is across multiple paragraphs');
+});
+
+test('Underline colors 6', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               exact: true,
+               styles: {
+                       'color': '#ff0000'
+               }
+       });
+       editor.setContent('<p><span style="text-decoration: underline;">This is some text.</span></p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('span')[0].firstChild, 8);
+       rng.setEnd(editor.dom.select('span')[0].firstChild, 12);
+       editor.selection.setRng(rng);
+       editor.formatter.apply('format');
+       editor.formatter.remove('format');
+       equal(editor.getContent(), '<p><span style="text-decoration: underline;">This is some text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
+});
+
+test('Underline colors 7', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               exact: true,
+               styles: {
+                       'color': '#ff0000'
+               }
+       });
+       editor.setContent('<p><span style="text-decoration: underline;">This is <span style="color: #ff0000; text-decoration: underline; background-color: #ff0000">some</span> text.</span></p>');
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('span')[1].firstChild, 0);
+       rng.setEnd(editor.dom.select('span')[1].firstChild, 4);
+       editor.selection.setRng(rng);
+       editor.formatter.remove('format');
+       equal(editor.getContent(), '<p><span style=\"text-decoration: underline;\">This is <span style=\"background-color: #ff0000;\">some</span> text.</span></p>', 'Children nodes that are underlined should be removed if their parent nodes are underlined');
+});
+
+test('Caret format inside single block word', function() {
+       editor.setContent('<p>abc</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 2, 'p', 2);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><b>abc</b></p>');
+});
+
+test('Caret format inside first block word', function() {
+       editor.setContent('<p>abc 123</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 2, 'p', 2);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><b>abc</b> 123</p>');
+});
+
+test('Caret format inside last block word', function() {
+       editor.setContent('<p>abc 123</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 5, 'p', 5);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc <b>123</b></p>');
+});
+
+test('Caret format inside middle block word', function() {
+       editor.setContent('<p>abc 123 456</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 5, 'p', 5);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc <b>123</b> 456</p>');
+});
+
+test('Caret format on word separated by non breaking space', function() {
+       editor.setContent('<p>one&nbsp;two</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 1, 'p', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><b>one</b>\u00a0two</p>');
+});
+
+test('Caret format inside single inline wrapped word', function() {
+       editor.setContent('<p>abc <em>123</em> 456</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('em', 1, 'em', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc <b><em>123</em></b> 456</p>');
+});
+
+test('Caret format inside word before similar format', function() {
+       editor.setContent('<p>abc 123 <b>456</b></p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 1, 'p', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><b>abc</b> 123 <b>456</b></p>');
+});
+
+test('Caret format inside last inline wrapped word', function() {
+       editor.setContent('<p>abc <em>abc 123</em> 456</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('em', 5, 'em', 5);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc <em>abc <b>123</b></em> 456</p>');
+});
+
+test('Caret format before text', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 0, 'p', 0);
+       editor.formatter.apply('format');
+       Utils.type('b');
+       equal(editor.getContent(), '<p><b>b</b>a</p>');
+});
+
+test('Caret format after text', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 1, 'p', 1);
+       editor.formatter.apply('format');
+       Utils.type('b');
+       equal(editor.getContent(), '<p>a<b>b</b></p>');
+});
+
+test('Caret format and no key press', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 0, 'p', 0);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>a</p>');
+});
+
+test('Caret format and arrow left', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 0, 'p', 0);
+       editor.formatter.apply('format');
+       Utils.type({
+               keyCode: 37
+       });
+       equal(editor.getContent(), '<p>a</p>');
+});
+
+test('Caret format and arrow right', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('p', 0, 'p', 0);
+       editor.formatter.apply('format');
+       Utils.type({
+               keyCode: 39
+       });
+       equal(editor.getContent(), '<p>a</p>');
+});
+
+test('Caret format and backspace', function() {
+       var rng;
+
+       if (tinymce.isOpera) {
+               ok(true, "Skip Opera since faking backspace doesn't work.");
+               return;
+       }
+
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+
+       editor.setContent('<p>abc</p>');
+       rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 3);
+       rng.setEnd(editor.dom.select('p')[0].firstChild, 3);
+       editor.selection.setRng(rng);
+
+       editor.formatter.apply('format');
+       Utils.type('\b');
+       equal(editor.getContent(), '<p>ab</p>');
+});
+
+test('Caret format on word in li with word in parent li before it', function() {
+       editor.setContent('<ul><li>one<ul><li>two</li></ul></li></ul>');
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       Utils.setSelection('ul li li', 1, 'ul li li', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<ul><li>one<ul><li><b>two</b></li></ul></li></ul>');
+});
+
+test('Selector format on whole contents', function() {
+       editor.setContent('<p>a</p>');
+       editor.formatter.register('format', {
+               inline: 'span',
+               selector: '*',
+               classes: 'test'
+       });
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p class="test">a</p>');
+});
+
+test('format inline on contentEditable: false block', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
+       Utils.setSelection('p:nth-child(2)', 0, 'p:nth-child(2)', 3);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc</p><p>def</p>', 'Text is not bold');
+});
+
+test('format block on contentEditable: false block', function() {
+       editor.formatter.register('format', {
+               block: 'h1'
+       });
+       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
+       Utils.setSelection('p:nth-child(2)', 0, 'p:nth-child(2)', 3);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc</p><p>def</p>', 'P is not h1');
+});
+
+test('contentEditable: false on start and contentEditable: true on end', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.setContent('<p>abc</p><p contenteditable="false">def</p><p>ghi</p>');
+       Utils.setSelection('p:nth-child(2)', 0, 'p:nth-child(3)', 3);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc</p><p>def</p><p><b>ghi</b></p>', 'Text in last paragraph is bold');
+});
+
+test('contentEditable: true on start and contentEditable: false on end', function() {
+       editor.formatter.register('format', {
+               inline: 'b'
+       });
+       editor.setContent('<p>abc</p><p contenteditable="false">def</p>');
+       Utils.setSelection('p:nth-child(1)', 0, 'p:nth-child(2)', 3);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><b>abc</b></p><p>def</p>', 'Text in first paragraph is 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">def</span></p>');
+       Utils.setSelection('span', 0, 'span', 3);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p>abc</p><p><span><b>def</b></span></p>', 'Text is bold');
+});
+
+test('Del element wrapping blocks', function() {
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.formatter.register('format', {
+               block: 'del',
+               wrapper: true
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '<del><p>a</p></del>');
+});
+
+test('Del element replacing block', function() {
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.formatter.register('format', {
+               block: 'del'
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '<del>a</del>');
+});
+
+test('Del element as inline', function() {
+       editor.setContent('<p>a</p>');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.formatter.register('format', {
+               inline: 'del'
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '<p><del>a</del></p>');
+});
+
+test('Align specified table element with collapsed: false and selection collapsed', function() {
+       editor.setContent('<table><tr><td>a</td></tr></table>');
+       Utils.setSelection('td', 0, 'td', 0);
+       editor.formatter.register('format', {
+               selector: 'table',
+               collapsed: false,
+               styles: {
+                       'float': 'right'
+               }
+       });
+       editor.formatter.apply('format', {}, editor.getBody().firstChild);
+       equal(getContent(), '<table style="float: right;"><tbody><tr><td>a</td></tr></tbody></table>');
+});
+
+test('Apply ID format to around existing bookmark node', function() {
+       editor.getBody().innerHTML = '<p>a<span id="b" data-mce-type="bookmark"></span>b</p>';
+
+       var rng = editor.dom.createRng();
+       rng.setStart(editor.dom.select('p')[0].firstChild, 0);
+       rng.setEnd(editor.dom.select('p')[0].lastChild, 1);
+       editor.selection.setRng(rng);
+
+       editor.formatter.register('format', {
+               inline: 'span',
+               attributes: {
+                       id: 'id'
+               }
+       });
+       editor.formatter.apply('format');
+
+       equal(Utils.normalizeHtml(editor.getBody().innerHTML), '<p><span id="id">a<span data-mce-type="bookmark" id="b"></span>b</span></p>');
+});
+
+test('Bug #5134 - TinyMCE removes formatting tags in the getContent', function() {
+       editor.setContent('');
+       editor.formatter.register('format', {
+               inline: 'strong',
+               toggle: false
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '', 'empty TinyMCE');
+       editor.selection.setContent('a');
+       equal(getContent(), '<strong>a</strong>', 'bold text inside TinyMCE');
+});
+
+test('Bug #5134 - TinyMCE removes formatting tags in the getContent - typing', function() {
+       editor.setContent('');
+       editor.formatter.register('format', {
+               inline: 'strong',
+               toggle: false
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '', 'empty TinyMCE');
+       Utils.type('a');
+       equal(getContent(), '<strong>a</strong>', 'bold text inside TinyMCE');
+});
+
+test('Bug #5453 - TD contents with BR gets wrapped in block format', function() {
+       editor.setContent('<table><tr><td>abc<br />123</td></tr></table>');
+       Utils.setSelection('td', 1, 'td', 1);
+       editor.formatter.register('format', {
+               block: 'h1'
+       });
+       editor.formatter.apply('format');
+       equal(getContent(), '<table><tbody><tr><td><h1>abc</h1>123</td></tr></tbody></table>');
+});
+
+test('Bug #6471 - Merge left/right style properties', function() {
+       editor.formatter.register('format', {
+               inline: 'span',
+               styles: {
+                       fontWeight: 'bold'
+               }
+       });
+       editor.setContent('<p>abc</p>');
+       Utils.setSelection('p', 2, 'p', 3);
+       editor.formatter.apply('format');
+       Utils.setSelection('p', 1, 'p', 2);
+       editor.formatter.apply('format');
+       Utils.setSelection('p', 0, 'p', 1);
+       editor.formatter.apply('format');
+       equal(editor.getContent(), '<p><span style="font-weight: bold;">abc</span></p>');
+});
+
+test('Bug #6518 - Apply div blocks to inline editor paragraph', function() {
+       inlineEditor.setContent('<p>a</p><p>b</p>');
+       inlineEditor.selection.select(inlineEditor.getBody().firstChild, true);
+       inlineEditor.selection.collapse(true);
+       inlineEditor.formatter.register('format', {
+               block: 'div'
+       });
+       inlineEditor.formatter.apply('format');
+       equal(inlineEditor.getContent(), '<div>a</div><p>b</p>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/Formatter_apply.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceFormatter_checkhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/Formatter_check.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_check.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/Formatter_check.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,274 +0,0 @@
</span><del>-<!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[nam
 e|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();
-               }
-       }
-});
-
-// WP
-var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
-
-tinymce.init({
-       selector: "#elm2",
-       inline: true,
-       // WP
-       external_plugins: {
-               noneditable: url + 'external-plugins/noneditable/plugin.js'
-       },
-       // WP end
-       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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceFormatter_checkjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/Formatter_check.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_check.js                              (rev 0)
+++ trunk/tests/qunit/editor/tinymce/Formatter_check.js 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,230 @@
</span><ins>+module("tinymce.Formatter - Check", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div>';
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "#elm1",
+                       add_unload_trigger: false,
+                       extended_valid_elements: 'b,i,span[style|contenteditable]',
+                       skin: 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) {
+                               window.editor = ed;
+
+                               if (window.inlineEditor) {
+                                       QUnit.start();
+                               }
+                       }
+               });
+
+               tinymce.init({
+                       selector: "#elm2",
+                       inline: true,
+                       add_unload_trigger: false,
+                       indent: false,
+                       skin: false,
+                       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) {
+                               window.inlineEditor = ed;
+
+                               if (window.editor) {
+                                       QUnit.start();
+                               }
+                       }
+               });
+       }
+});
+
+test('Selected style element text', function() {
+       editor.formatter.register('bold', {inline: 'b'});
+       editor.getBody().innerHTML = '<p><b>1234</b></p>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       Utils.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>';
+       Utils.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');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/Formatter_check.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceFormatter_removehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/Formatter_remove.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_remove.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/Formatter_remove.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,404 +0,0 @@
</span><del>-<!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>');
-});
-*/
-
-// WP
-var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
-
-tinymce.init({
-       mode : "exact",
-       elements : "elm1",
-       // WP
-       external_plugins: {
-               noneditable: url + 'external-plugins/noneditable/plugin.js'
-       },
-       // WP end
-       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|codeb
 ase|*],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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceFormatter_removejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/Formatter_remove.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_remove.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/Formatter_remove.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,367 @@
</span><ins>+module("tinymce.Formatter - Remove", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div>';
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       external_plugins: {
+                               noneditable: '../../../../tests/qunit/editor/external-plugins/noneditable/plugin.min.js'
+                       },
+                       indent: false,
+                       add_unload_trigger: false,
+                       skin: false,
+                       extended_valid_elements: 'b,i,span[style|contenteditable]',
+                       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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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>';
+       var 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});
+       var 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'});
+       var 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'});
+       var 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'});
+       Utils.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'});
+       Utils.setSelection('b', 3, 'b', 3);
+       editor.formatter.remove('format');
+       Utils.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'});
+       Utils.setSelection('b', 3, 'b', 3);
+       editor.formatter.remove('format');
+       Utils.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'});
+       Utils.setSelection('b', 3, 'b', 3);
+       editor.formatter.remove('format');
+       Utils.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'});
+       Utils.setSelection('b', 3, 'b', 3);
+       editor.formatter.remove('format');
+       Utils.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'});
+       Utils.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() {
+       editor.formatter.register('format', {inline: 'b'});
+       editor.setContent('<p>abc</p><p contenteditable="false"><b>def</b></p><p><b>ghj</b></p>');
+       var 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>');
+       Utils.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>');
+       Utils.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>');
+       Utils.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'});
+       Utils.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>');
+});
+*/
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/Formatter_remove.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceFormatter_robothtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/Formatter_robot.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/Formatter_robot.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/Formatter_robot.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,94 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceUndoManagerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/UndoManager.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/UndoManager.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/UndoManager.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,194 +0,0 @@
</span><del>-<!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');
-
-       // Move focus to an input element
-       var input = document.createElement('input');
-       document.body.appendChild(input);
-       input.focus();
-       input.parentNode.removeChild(input);
-
-       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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceUndoManagerjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/UndoManager.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/UndoManager.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/UndoManager.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,174 @@
</span><ins>+module("tinymce.UndoManager", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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);
+});
+
+asyncTest('Undo added when typing and losing focus', function() {
+       window.focus();
+
+       window.setTimeout(function() {
+               start();
+
+               editor.focus();
+               editor.undoManager.clear();
+               editor.setContent("<p>some text</p>");
+               Utils.setSelection('p', 4, 'p', 9);
+               Utils.type('\b');
+
+               // Move focus to an input element
+               var input = document.createElement('input');
+               document.getElementById('view').appendChild(input);
+               input.focus();
+               input.parentNode.removeChild(input);
+
+               editor.execCommand('FormatBlock', false, 'h1');
+               editor.undoManager.undo();
+               equal(editor.getContent(), "<p>some</p>");
+       }, 0);
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/UndoManager.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceUndoManager_robothtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/UndoManager_robot.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/UndoManager_robot.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/UndoManager_robot.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,115 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomDOMUtilshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/DOMUtils.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/DOMUtils.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/DOMUtils.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,27 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomDOMUtilsjs"></a>
<div class="modfile"><h4>Modified: trunk/tests/qunit/editor/tinymce/dom/DOMUtils.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/DOMUtils.js 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/DOMUtils.js    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,4 +1,6 @@
</span><span class="cx"> (function() {
</span><ins>+       module("tinymce.dom.DOMUtils");
+
</ins><span class="cx">   var DOM = new tinymce.dom.DOMUtils(document, {keep_values : true, schema : new tinymce.html.Schema()});
</span><span class="cx"> 
</span><span class="cx">  test('parseStyle', 11, function() {
</span><span class="lines">@@ -6,7 +8,7 @@
</span><span class="cx"> 
</span><span class="cx">          DOM.add(document.body, 'div', {id : 'test'});
</span><span class="cx"> 
</span><del>-               dom = new tinymce.dom.DOMUtils(document, {hex_colors : true, keep_values : true, url_converter : function(u, n, e) {
</del><ins>+                dom = new tinymce.dom.DOMUtils(document, {hex_colors : true, keep_values : true, url_converter : function(u) {
</ins><span class="cx">                   return 'X' + u + 'Y';
</span><span class="cx">          }});
</span><span class="cx"> 
</span><span class="lines">@@ -218,10 +220,10 @@
</span><span class="cx">          equal(DOM.select('div', 'test').length, 4);
</span><span class="cx">          ok(DOM.select('div', 'test').reverse);
</span><span class="cx"> 
</span><del>-               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>')
</del><ins>+                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>');
</ins><span class="cx">           equal(DOM.select('div.test2', 'test').length, 2);
</span><span class="cx"> 
</span><del>-               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>')
</del><ins>+                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>');
</ins><span class="cx">           equal(DOM.select('div div', 'test').length, 1, null, tinymce.isWebKit); // Issue: http://bugs.webkit.org/show_bug.cgi?id=17461
</span><span class="cx">          //alert(DOM.select('div div', 'test').length +","+DOM.get('test').querySelectorAll('div div').length);
</span><span class="cx"> 
</span><span class="lines">@@ -264,7 +266,7 @@
</span><span class="cx">          equal(DOM.getAttrib('test', 'class'), '123');
</span><span class="cx">          equal(DOM.getAttrib('test', 'title'), 'abc');
</span><span class="cx"> 
</span><del>-               dom = new tinymce.dom.DOMUtils(document, {keep_values : true, url_converter : function(u, n, e) {
</del><ins>+                dom = new tinymce.dom.DOMUtils(document, {keep_values : true, url_converter : function(u, n) {
</ins><span class="cx">                   return '&<>"' + u + '&<>"' + n;
</span><span class="cx">          }});
</span><span class="cx"> 
</span><span class="lines">@@ -286,20 +288,19 @@
</span><span class="cx">  });
</span><span class="cx"> 
</span><span class="cx">  test('getAttribs', 2, function() {
</span><del>-               var dom;
-
</del><span class="cx">           function check(obj, val) {
</span><span class="cx">                  var count = 0;
</span><span class="cx"> 
</span><span class="cx">                  val = val.split(',');
</span><span class="cx"> 
</span><span class="cx">                  tinymce.each(obj, function(o) {
</span><del>-                               if (tinymce.inArray(val, o.nodeName.toLowerCase()) != -1 && o.specified)
</del><ins>+                                if (tinymce.inArray(val, o.nodeName.toLowerCase()) != -1 && o.specified) {
</ins><span class="cx">                                   count++;
</span><ins>+                               }
</ins><span class="cx">                   });
</span><span class="cx"> 
</span><span class="cx">                  return count == obj.length;
</span><del>-               };
</del><ins>+                }
</ins><span class="cx"> 
</span><span class="cx">          DOM.add(document.body, 'div', {id : 'test'});
</span><span class="cx"> 
</span><span class="lines">@@ -356,7 +357,7 @@
</span><span class="cx">          equal(DOM.getParent('test2', function(n) {return n.nodeName == 'SPAN';}).nodeName, 'SPAN');
</span><span class="cx">          equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}).nodeName, 'BODY');
</span><span class="cx">          equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}, document.body), null);
</span><del>-               equal(DOM.getParent('test2', function(n) {return false;}), null);
</del><ins>+                equal(DOM.getParent('test2', function() {return false;}), null);
</ins><span class="cx">           equal(DOM.getParent('test2', 'SPAN').nodeName, 'SPAN');
</span><span class="cx">          equal(DOM.getParent('test2', 'body', DOM.get('test')), null);
</span><span class="cx"> 
</span><span class="lines">@@ -435,8 +436,6 @@
</span><span class="cx">  });
</span><span class="cx"> 
</span><span class="cx">  test('getNext', 5, function() {
</span><del>-               var r;
-
</del><span class="cx">           DOM.add(document.body, 'div', {id : 'test'});
</span><span class="cx"> 
</span><span class="cx">          DOM.get('test').innerHTML = '<strong>A</strong><span>B</span><em>C</em>';
</span><span class="lines">@@ -444,14 +443,12 @@
</span><span class="cx">          equal(DOM.getNext(DOM.get('test').firstChild, 'em').nodeName, 'EM');
</span><span class="cx">          equal(DOM.getNext(DOM.get('test').firstChild, 'div'), null);
</span><span class="cx">          equal(DOM.getNext(null, 'div'), null);
</span><del>-               equal(DOM.getNext(DOM.get('test').firstChild, function(n) {return n.nodeName == 'EM'}).nodeName, 'EM');
</del><ins>+                equal(DOM.getNext(DOM.get('test').firstChild, function(n) {return n.nodeName == 'EM';}).nodeName, 'EM');
</ins><span class="cx"> 
</span><span class="cx">          DOM.remove('test');
</span><span class="cx">  });
</span><span class="cx"> 
</span><span class="cx">  test('getPrev', 5, function() {
</span><del>-               var r;
-
</del><span class="cx">           DOM.add(document.body, 'div', {id : 'test'});
</span><span class="cx"> 
</span><span class="cx">          DOM.get('test').innerHTML = '<strong>A</strong><span>B</span><em>C</em>';
</span><span class="lines">@@ -459,7 +456,7 @@
</span><span class="cx">          equal(DOM.getPrev(DOM.get('test').lastChild, 'strong').nodeName, 'STRONG');
</span><span class="cx">          equal(DOM.getPrev(DOM.get('test').lastChild, 'div'), null);
</span><span class="cx">          equal(DOM.getPrev(null, 'div'), null);
</span><del>-               equal(DOM.getPrev(DOM.get('test').lastChild, function(n) {return n.nodeName == 'STRONG'}).nodeName, 'STRONG');
</del><ins>+                equal(DOM.getPrev(DOM.get('test').lastChild, function(n) {return n.nodeName == 'STRONG';}).nodeName, 'STRONG');
</ins><span class="cx"> 
</span><span class="cx">          DOM.remove('test');
</span><span class="cx">  });
</span><span class="lines">@@ -467,11 +464,12 @@
</span><span class="cx">  test('loadCSS', 1, function() {
</span><span class="cx">          var c = 0;
</span><span class="cx"> 
</span><del>-               DOM.loadCSS('css/test.css?a=1,css/test.css?a=2,css/test.css?a=3');
</del><ins>+                DOM.loadCSS('tinymce/dom/test.css?a=1,tinymce/dom/test.css?a=2,tinymce/dom/test.css?a=3');
</ins><span class="cx"> 
</span><span class="cx">          tinymce.each(document.getElementsByTagName('link'), function(n) {
</span><del>-                       if (n.href.indexOf('test.css?a=') != -1)
</del><ins>+                        if (n.href.indexOf('test.css?a=') != -1) {
</ins><span class="cx">                           c++;
</span><ins>+                       }
</ins><span class="cx">           });
</span><span class="cx"> 
</span><span class="cx">          equal(c, 3, null, tinymce.isOpera);
</span><span class="lines">@@ -576,7 +574,7 @@
</span><span class="cx">          parent = DOM.select('li:nth-child(1)', DOM.get('test'))[0];
</span><span class="cx">          point = DOM.select('ul li:nth-child(2)', DOM.get('test'))[0];
</span><span class="cx">          DOM.split(parent, point);
</span><del>-               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>');
</del><ins>+                equal(Utils.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>');
</ins><span class="cx"> 
</span><span class="cx">          DOM.remove('test');
</span><span class="cx">  });
</span><span class="lines">@@ -630,7 +628,7 @@
</span><span class="cx">          DOM.setHTML('test', '<div><span><b></b></span><b></b><em><a name="x"></a></em></div>');
</span><span class="cx">          ok(!DOM.isEmpty(DOM.get('test')), 'Non empty complex HTML with achor name');
</span><span class="cx"> 
</span><del>-               DOM.setHTML('test', '<img src="x">');
</del><ins>+                DOM.setHTML('test', '<img src="tinymce/ui/img/raster.gif">');
</ins><span class="cx">           ok(!DOM.isEmpty(DOM.get('test')), 'Non empty html with img element');
</span><span class="cx"> 
</span><span class="cx">          DOM.setHTML('test', '<span data-mce-bookmark="1"></span>');
</span></span></pre></div>
<a id="trunktestsquniteditortinymcedomDOMUtils_jqueryhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/DOMUtils_jquery.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/DOMUtils_jquery.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/DOMUtils_jquery.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,29 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomEventUtilshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/EventUtils.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/EventUtils.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/EventUtils.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,459 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomEventUtilsjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/dom/EventUtils.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/EventUtils.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/dom/EventUtils.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,441 @@
</span><ins>+var eventUtils = tinymce.dom.Event;
+
+module("tinymce.dom.Event", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = (
+                       '<div id="content" tabindex="0">' +
+                       '<div id="inner" tabindex="0"></div>' +
+                       '</div>'
+               );
+       },
+
+       teardown: function() {
+               eventUtils.clean(window);
+       }
+});
+
+test("unbind all", function() {
+       var result;
+
+       eventUtils.bind(window, 'click', function() {
+               result.click = true;
+       });
+
+       eventUtils.bind(window, 'keydown', function() {
+               result.keydown1 = true;
+       });
+
+       eventUtils.bind(window, 'keydown', function() {
+               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() {
+               result.click = true;
+       });
+
+       eventUtils.bind(window, 'keydown', function() {
+               result.keydown1 = true;
+       });
+
+       eventUtils.bind(window, 'keydown', function() {
+               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() {
+               result.click = true;
+       });
+
+       eventUtils.bind(window, 'keydown', function() {
+               result.keydown1 = true;
+       });
+
+       function callback2() {
+               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() {
+               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() {
+               result.click1 = true;
+       });
+
+       eventUtils.bind(window, 'click', function(e) {
+               result.click2 = true;
+               e.stopImmediatePropagation();
+       });
+
+       eventUtils.bind(window, 'click', function() {
+               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() {
+               result.click1 = true;
+       });
+
+       eventUtils.bind(document.body, 'click', function() {
+               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() {
+               result.click1 = true;
+       });
+
+       eventUtils.bind(document.body, 'click', function() {
+               result.click2 = true;
+       });
+
+       eventUtils.bind(document.getElementById('content'), 'click', function() {
+               result.click3 = true;
+       });
+
+       eventUtils.bind(document.getElementById('inner'), 'click', function() {
+               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() {
+               result.click1 = true;
+       });
+
+       eventUtils.bind(document, 'click', function() {
+               result.click2 = true;
+       });
+
+       eventUtils.bind(document.body, 'click', function() {
+               result.click3 = true;
+       });
+
+       eventUtils.bind(document.getElementById('content'), 'click', function() {
+               result.click4 = true;
+       });
+
+       eventUtils.bind(document.getElementById('inner'), 'click', function() {
+               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() {
+               result.click1 = true;
+       });
+
+       eventUtils.bind(document.body, 'click', function() {
+               result.click2 = true;
+       });
+
+       eventUtils.bind(document.getElementById('content'), 'click', function() {
+               result.click3 = true;
+       });
+
+       eventUtils.bind(document.getElementById('inner'), 'click', function() {
+               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, {});
+});
+
+asyncTest("focusin/focusout bind/unbind", function() {
+       var result = {};
+
+       window.setTimeout(function() {
+               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;
+               });
+
+               start();
+               document.getElementById('content').focus();
+               document.getElementById('inner').focus();
+
+               deepEqual(result, {focusin: 2, focusout: 1});
+       }, 0);
+});
+
+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");
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/dom/EventUtils.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcedomRangehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/Range.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Range.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/Range.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,606 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomRangejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/dom/Range.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Range.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/dom/Range.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,548 @@
</span><ins>+(function() {
+       module("tinymce.dom.Range", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = (
+                               '<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>'
+                       );
+               }
+       });
+
+       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;
+       }
+
+       test("Initial state", function() {
+               var r = createRng();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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();
+
+               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;
+                
+               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");
+               });
+       }
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/dom/Range.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcedomSelectionhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/Selection.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Selection.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/Selection.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,948 +0,0 @@
</span><del>-<!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('normalize caret after trailing BR', function() {
-               var rng;
-
-               editor.setContent('<p>a<br /></p>');
-               rng = editor.dom.createRng();
-               rng.setStart(editor.getBody().firstChild, 2);
-               rng.setEnd(editor.getBody().firstChild, 2);
-               editor.selection.setRng(rng);
-               editor.selection.normalize();
-
-               rng = editor.selection.getRng(true);
-               equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
-               equal(rng.startOffset, 1, 'startContainer offset');
-               equal(rng.endContainer.nodeName, '#text', 'endContainer node name');
-               equal(rng.endOffset, 1, 'endOffset offset');
-       });
-
-       test('normalize caret after bogus block BR', function() {
-               var rng;
-
-               editor.setContent('<p><br /></p>');
-               rng = editor.dom.createRng();
-               rng.setStart(editor.getBody().firstChild, 1);
-               rng.setEnd(editor.getBody().firstChild, 1);
-               editor.selection.setRng(rng);
-               editor.selection.normalize();
-
-               rng = editor.selection.getRng(true);
-               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
-               equal(rng.startOffset, 0, 'startContainer offset');
-               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
-               equal(rng.endOffset, 0, 'endOffset offset');
-       });
-
-/*
-       test('normalize caret after last BR in block', function() {
-               var rng;
-
-               editor.setContent('<p><br /><br /></p>');
-               rng = editor.dom.createRng();
-               rng.setStart(editor.getBody().firstChild, 2);
-               rng.setEnd(editor.getBody().firstChild, 2);
-               editor.selection.setRng(rng);
-               editor.selection.normalize();
-
-               rng = editor.selection.getRng(true);
-               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
-               equal(rng.startOffset, 1, 'startContainer offset');
-               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
-               equal(rng.endOffset, 1, 'endOffset offset');
-       });
-*/
-
-       test('normalize caret after double BR', function() {
-               var rng;
-
-               editor.setContent('<p>a<br /><br /></p>');
-               rng = editor.dom.createRng();
-               rng.setStart(editor.getBody().firstChild, 3);
-               rng.setEnd(editor.getBody().firstChild, 3);
-               editor.selection.setRng(rng);
-               editor.selection.normalize();
-
-               rng = editor.selection.getRng(true);
-               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
-               equal(rng.startOffset, 3, 'startContainer offset');
-               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
-               equal(rng.endOffset, 3, 'endOffset offset');
-       });
-}
-
-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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomSelectionjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/dom/Selection.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Selection.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/dom/Selection.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,919 @@
</span><ins>+module("tinymce.dom.Selection", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       add_unload_trigger: false,
+                       skin: false,
+                       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) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+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');
+       Utils.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>';
+               Utils.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>';
+               Utils.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>';
+               Utils.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>';
+               Utils.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>';
+               Utils.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('normalize caret after trailing BR', function() {
+               var rng;
+
+               editor.setContent('<p>a<br /></p>');
+               rng = editor.dom.createRng();
+               rng.setStart(editor.getBody().firstChild, 2);
+               rng.setEnd(editor.getBody().firstChild, 2);
+               editor.selection.setRng(rng);
+               editor.selection.normalize();
+
+               rng = editor.selection.getRng(true);
+               equal(rng.startContainer.nodeName, '#text', 'startContainer node name');
+               equal(rng.startOffset, 1, 'startContainer offset');
+               equal(rng.endContainer.nodeName, '#text', 'endContainer node name');
+               equal(rng.endOffset, 1, 'endOffset offset');
+       });
+
+       test('normalize caret after bogus block BR', function() {
+               var rng;
+
+               editor.setContent('<p><br /></p>');
+               rng = editor.dom.createRng();
+               rng.setStart(editor.getBody().firstChild, 1);
+               rng.setEnd(editor.getBody().firstChild, 1);
+               editor.selection.setRng(rng);
+               editor.selection.normalize();
+
+               rng = editor.selection.getRng(true);
+               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
+               equal(rng.startOffset, 0, 'startContainer offset');
+               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
+               equal(rng.endOffset, 0, 'endOffset offset');
+       });
+
+/*
+       test('normalize caret after last BR in block', function() {
+               var rng;
+
+               editor.setContent('<p><br /><br /></p>');
+               rng = editor.dom.createRng();
+               rng.setStart(editor.getBody().firstChild, 2);
+               rng.setEnd(editor.getBody().firstChild, 2);
+               editor.selection.setRng(rng);
+               editor.selection.normalize();
+
+               rng = editor.selection.getRng(true);
+               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
+               equal(rng.startOffset, 1, 'startContainer offset');
+               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
+               equal(rng.endOffset, 1, 'endOffset offset');
+       });
+*/
+
+       test('normalize caret after double BR', function() {
+               var rng;
+
+               editor.setContent('<p>a<br /><br /></p>');
+               rng = editor.dom.createRng();
+               rng.setStart(editor.getBody().firstChild, 3);
+               rng.setEnd(editor.getBody().firstChild, 3);
+               editor.selection.setRng(rng);
+               editor.selection.normalize();
+
+               rng = editor.selection.getRng(true);
+               equal(rng.startContainer.nodeName, 'P', 'startContainer node name');
+               equal(rng.startOffset, 3, 'startContainer offset');
+               equal(rng.endContainer.nodeName, 'P', 'endContainer node name');
+               equal(rng.endOffset, 3, 'endOffset offset');
+       });
+}
+
+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>';
+       Utils.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>';
+       Utils.setSelection('p', 0, 'p', 4);
+       editor.nodeChanged();
+       equal(newArgs.selector, 'a[href]');
+       equal(newArgs.node, editor.getBody().firstChild);
+       equal(newArgs.parents.length, 1);
+});
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/dom/Selection.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcedomSerializerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/Serializer.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Serializer.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/Serializer.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,515 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomSerializerjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/dom/Serializer.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/Serializer.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/dom/Serializer.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,492 @@
</span><ins>+var DOM = tinymce.DOM;
+
+module("tinymce.dom.Serializer", {
+       setupModule: function() {
+               document.getElementById('view').innerHTML = '<div id="content"><div id="test"></div></div>';
+       }
+});
+
+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="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.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="tinymce/ui/img/raster.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="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.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="tinymce/ui/img/raster.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="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.gif" border="0" alt="" />');
+       equal(ser.serialize(DOM.get('test')), '<img src="tinymce/ui/img/raster.gif" border="0" alt="" />', 'Default attribute with empty value');
+
+       ser.setRules('img[src|border=0|alt=],*[*]');
+       DOM.setHTML('test', '<img src="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.gif" /><hr />');
+       equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="tinymce/ui/img/raster.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="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.gif" alt="" />');
+       equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="tinymce/ui/img/raster.gif" alt="" /></div>');
+
+       ser = new tinymce.dom.Serializer({invalid_elements : 'hr,br'});
+       DOM.setHTML('test', '<img src="tinymce/ui/img/raster.gif" data-mce-src="tinymce/ui/img/raster.gif" /><hr /><br />');
+       equal(ser.serialize(DOM.get('test')), '<div id="test"><img src="tinymce/ui/img/raster.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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/dom/Serializer.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcedomTridentSelectionhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/TridentSelection.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/TridentSelection.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/TridentSelection.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,586 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcedomTridentSelectionjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/dom/TridentSelection.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/TridentSelection.js                         (rev 0)
+++ trunk/tests/qunit/editor/tinymce/dom/TridentSelection.js    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,543 @@
</span><ins>+module("tinymce.dom.TridentSelection", {
+       setupModule: function() {
+               if (window.getSelection) {
+                       return;
+               }
+
+               QUnit.stop();
+               document.getElementById('view').innerHTML = '<textarea></textarea>';
+
+               tinymce.init({
+                       selector: "textarea",
+                       elements: "elm1",
+                       add_unload_trigger: false,
+                       disable_nodechange: true,
+                       skin: false,
+                       init_instance_callback: function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+if (!window.getSelection) {
+       test("Selection of element containing text", function(){
+               expect(5);
+               
+               editor.setContent('<p>123</p>', {
+                       format: 'raw'
+               });
+               
+               var 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'
+               });
+               
+               var 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(Utils.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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+       });
+       
+       test("Mixed selection start at element end at text", function(){
+               expect(5);
+               
+               editor.setContent('<p><img src="about:blank" />text</p>', {
+                       format: 'raw'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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'
+               });
+               
+               var 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");
+       });
+}
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/dom/TridentSelection.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcedomtestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/dom/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/dom/tests.js    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/dom/tests.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,12 +0,0 @@
</span><del>-{
-       "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"}
-       ]
-}
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlDomParserhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/DomParser.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/DomParser.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/DomParser.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,506 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlDomParserjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/DomParser.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/DomParser.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/DomParser.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,483 @@
</span><ins>+(function() {
+       module("tinymce.html.DomParser");
+
+       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;
+
+               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, 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({}, 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>');
+       });
+})();
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/DomParser.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlEntitieshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Entities.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Entities.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Entities.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,98 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlEntitiesjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Entities.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Entities.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Entities.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+module("tinymce.html.Entities");
+
+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.");
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Entities.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlNodehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Node.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Node.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Node.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,466 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlNodejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Node.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Node.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Node.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,442 @@
</span><ins>+module("tinymce.html.Node");
+
+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;
+
+       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;
+
+       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, node3;
+
+       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, fragment;
+
+       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.');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Node.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlObsoletejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Obsolete.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Obsolete.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Obsolete.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,262 @@
</span><ins>+module( 'tinymce.html.Obsolete', {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: 'textarea',
+                       add_unload_trigger : false,
+                       skin: false,
+                       indent : false,
+                       entities : 'raw',
+                       plugins: 'media',
+                       convert_urls : false,
+                       init_instance_callback : function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+/**
+ * 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( editor.getContent(), testString, text );
+
+       text = 'strike, converted to span';
+       editor.setContent( '<strike>test</strike>' );
+       equal( editor.getContent(), '<p><span style="text-decoration: line-through;">test</span></p>', text );
+
+       text = 'big';
+       testString = '<p><big>test</big></p>';
+       editor.setContent( testString );
+       equal( editor.getContent(), testString, text );
+
+       text = 'center';
+       testString = '<center>test</center>';
+       editor.setContent( testString );
+       equal( editor.getContent(), testString, text );
+
+       text = 'font, converted to span';
+       editor.setContent( '<p><font size="4">test</font></p>' );
+       equal( editor.getContent(), '<p><span style="font-size: large;">test</span></p>', text );
+
+       text = 'tt';
+       testString = '<p><tt>test</tt></p>';
+       editor.setContent( testString );
+       equal( editor.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( editor.getContent(), testString, text );
+
+       text = 'Old style anchors';
+       testString = '<p><a name="test"></a></p>';
+       editor.setContent( testString );
+       equal( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.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( editor.getContent(), testString, text );
+
+       text = 'compact on dl elements';
+       testString = '<dl compact="compact"><dd>1</dd></dl>';
+       editor.setContent( testString );
+       equal( editor.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( editor.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( editor.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( editor.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( editor.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( editor.getContent(), { object: 'align border hspace vspace' } ), text );
+
+       text = 'compact on ol elements';
+       testString = '<ol compact="compact"><li>test</li></ol>';
+       editor.setContent( testString );
+       equal( editor.getContent(), testString, text );
+
+       text = 'compact, type on ul elements';
+       testString = '<ul type="disc" compact="compact"><li>test</li></ul>';
+       editor.setContent( testString );
+       ok( hasAttr( editor.getContent(), { ul: 'compact type' } ), text );
+
+       text = 'width on pre elements';
+       testString = '<pre width="100">1</pre>';
+       editor.setContent( testString );
+       equal( editor.getContent(), testString, text );
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Obsolete.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlSaxParserhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/SaxParser.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/SaxParser.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/SaxParser.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,616 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlSaxParserjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/SaxParser.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/SaxParser.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/SaxParser.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,637 @@
</span><ins>+(function() {
+       module("tinymce.html.SaxParser");
+
+       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() {
+               var counter, parser;
+
+               expect(46);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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).');
+
+               counter = createCounter(writer);
+               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).');
+
+               counter = createCounter(writer);
+               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).');
+
+               counter = createCounter(writer);
+               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).');
+
+               counter = createCounter(writer);
+               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).');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(8);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(8);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(10);
+
+               counter = createCounter(writer);
+               parser = new tinymce.html.SaxParser(counter, schema);
+               writer.reset();
+               parser.parse('');
+               equal(writer.getContent(), '', 'Parse empty.');
+               deepEqual(counter.counts, {}, 'Parse empty counts.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(8);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(8);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(6);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(4);
+
+               counter = createCounter(writer);
+               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.');
+
+               counter = createCounter(writer);
+               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() {
+               var counter, parser;
+
+               expect(2);
+
+               counter = createCounter(writer);
+               counter.validate = true;
+               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() {
+               var counter, parser;
+
+               expect(1);
+
+               counter = createCounter(writer);
+               counter.validate = true;
+               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() {
+               var counter, parser, schema;
+
+               expect(2);
+
+               schema = new tinymce.html.Schema({valid_elements : 'b'});
+               counter = createCounter(writer);
+               counter.validate = true;
+               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.');
+
+               schema = new tinymce.html.Schema({valid_elements : 'b,span[class]'});
+               counter = createCounter(writer);
+               counter.validate = true;
+               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() {
+               var counter, parser, schema;
+
+               expect(2);
+
+               schema = new tinymce.html.Schema({valid_elements : 'b'});
+               counter = createCounter(writer);
+               counter.validate = true;
+               counter.remove_internals = true;
+               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.');
+
+               schema = new tinymce.html.Schema({valid_elements : 'b,span[class]'});
+               counter = createCounter(writer);
+               counter.validate = true;
+               counter.remove_internals = true;
+               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, parser;
+
+               counter = createCounter(writer);
+               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, parser;
+
+               counter = createCounter(writer);
+               counter.validate = true;
+               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, parser;
+
+               counter = createCounter(writer);
+               counter.validate = false;
+               counter.allow_conditional_comments = true;
+               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, parser;
+
+               counter = createCounter(writer);
+               counter.validate = false;
+               counter.allow_conditional_comments = false;
+               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, parser;
+
+               counter = createCounter(writer);
+               counter.validate = false;
+               counter.allow_script_urls = true;
+               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, parser;
+
+               counter = createCounter(writer);
+               counter.validate = false;
+               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>');
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/SaxParser.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlSchemahtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Schema.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Schema.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Schema.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,374 +0,0 @@
</span><del>-<!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: {},
-               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: {},
-               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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlSchemajs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Schema.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Schema.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Schema.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,409 @@
</span><ins>+module("tinymce.html.Schema");
+
+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() {
+       var schema;
+
+       expect(17);
+
+       schema = new tinymce.html.Schema({valid_elements: '*[id|class]'});
+       deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
+       deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
+
+       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);
+
+       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);
+
+       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() {
+       var schema;
+
+       expect(13);
+
+       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'));
+
+       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'));
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(2);
+
+       schema = new tinymce.html.Schema({valid_elements: '-span'});
+       deepEqual(schema.getElementRule('span'), {"attributes": {}, "attributesOrder": [], "removeEmpty": true});
+
+       schema = new tinymce.html.Schema({valid_elements: '#span'});
+       deepEqual(schema.getElementRule('span'), {"attributes": {}, "attributesOrder": [], "paddEmpty": true});
+});
+
+test('addValidElements', function() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       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"]});
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       schema = new tinymce.html.Schema();
+       deepEqual(schema.getBlockElements(), {
+               ASIDE: {}, HGROUP: {}, SECTION: {}, ARTICLE: {}, FOOTER: {}, HEADER: {},
+               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: {},
+               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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(1);
+
+       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() {
+       var schema;
+
+       expect(4);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       schema = new tinymce.html.Schema();
+       ok(schema.getElementRule('b'));
+       ok(!schema.getElementRule('bx'));
+       ok(!schema.getElementRule(null));
+});
+
+test('addCustomElements', function() {
+       var schema;
+
+       expect(5);
+
+       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() {
+       var schema;
+
+       expect(7);
+
+       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'));
+
+       schema = new tinymce.html.Schema();
+       ok(schema.isValidChild('body', 'p'));
+       schema.addValidChildren('-body[p]');
+       ok(!schema.isValidChild('body', 'p'));
+});
+
+test('addCustomElements/getCustomElements', function() {
+       var schema;
+
+       expect(4);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       schema = new tinymce.html.Schema({whitespace_elements : 'pre,p'});
+       ok(schema.getWhiteSpaceElements().pre);
+       ok(!schema.getWhiteSpaceElements().span);
+
+       schema = new tinymce.html.Schema({whitespace_elements : 'code'});
+       ok(schema.getWhiteSpaceElements().code);
+});
+
+test('selfClosingElements', function() {
+       var schema;
+
+       expect(3);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       schema = new tinymce.html.Schema({boolean_attributes : 'href,alt'});
+       ok(schema.getBoolAttrs().href);
+       ok(schema.getBoolAttrs().alt);
+       ok(!schema.getBoolAttrs().checked);
+});
+
+test('nonEmptyElements', function() {
+       var schema;
+
+       expect(3);
+
+       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() {
+       var schema;
+
+       expect(3);
+
+       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;
+
+       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'));
+});
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Schema.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlSerializerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Serializer.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Serializer.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Serializer.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,46 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlSerializerjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Serializer.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Serializer.js                              (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Serializer.js 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+module("tinymce.html.Serializer");
+
+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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Serializer.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlStyleshtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Styles.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Styles.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Styles.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,176 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlStylesjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Styles.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Styles.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Styles.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,152 @@
</span><ins>+module("tinymce.html.Styles");
+
+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');");
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Styles.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlWriterhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/Writer.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Writer.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/Writer.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,174 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmlWriterjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/html/Writer.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/Writer.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/html/Writer.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,168 @@
</span><ins>+module("tinymce.html.Writer");
+
+test('Comment', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.comment('text');
+       equal(writer.getContent(), '<!--text-->');
+
+       writer = new tinymce.html.Writer();
+       writer.comment('');
+       equal(writer.getContent(), '<!---->');
+});
+
+test('CDATA', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.cdata('text');
+       equal(writer.getContent(), '<![CDATA[text]]>');
+
+       writer = new tinymce.html.Writer();
+       writer.cdata('');
+       equal(writer.getContent(), '<![CDATA[]]>');
+});
+
+test('PI', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.pi('xml', 'someval');
+       equal(writer.getContent(), '<?xml someval?>');
+
+       writer = new tinymce.html.Writer();
+       writer.pi('xml');
+       equal(writer.getContent(), '<?xml?>');
+});
+
+test('Doctype', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.doctype(' text');
+       equal(writer.getContent(), '<!DOCTYPE text>');
+
+       writer = new tinymce.html.Writer();
+       writer.doctype('');
+       equal(writer.getContent(), '<!DOCTYPE>');
+});
+
+test('Text', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.text('te<xt');
+       equal(writer.getContent(), 'te&lt;xt');
+
+       writer = new tinymce.html.Writer();
+       writer.text('');
+       equal(writer.getContent(), '');
+});
+
+test('Text raw', function() {
+       var writer;
+
+       expect(2);
+
+       writer = new tinymce.html.Writer();
+       writer.text('te<xt', true);
+       equal(writer.getContent(), 'te<xt');
+
+       writer = new tinymce.html.Writer();
+       writer.text('', true);
+       equal(writer.getContent(), '');
+});
+
+test('Start', function() {
+       var writer;
+
+       expect(5);
+
+       writer = new tinymce.html.Writer();
+       writer.start('b');
+       equal(writer.getContent(), '<b>');
+
+       writer = new tinymce.html.Writer();
+       writer.start('b', [{name: 'attr1', value: 'value1'}, {name: 'attr2', value: 'value2'}]);
+       equal(writer.getContent(), '<b attr1="value1" attr2="value2">');
+
+       writer = new tinymce.html.Writer();
+       writer.start('b', [{name: 'attr1', value: 'val<"ue1'}]);
+       equal(writer.getContent(), '<b attr1="val&lt;&quot;ue1">');
+
+       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" />');
+
+       writer = new tinymce.html.Writer();
+       writer.start('br', null, true);
+       equal(writer.getContent(), '<br />');
+});
+
+test('End', function() {
+       var writer;
+
+       expect(1);
+
+       writer = new tinymce.html.Writer();
+       writer.end('b');
+       equal(writer.getContent(), '</b>');
+});
+
+test('Indentation', function() {
+       var writer;
+
+       expect(2);
+
+       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>');
+
+       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() {
+       var writer;
+
+       expect(3);
+
+       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>');
+
+       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>');
+
+       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>');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/html/Writer.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymcehtmlobsoletehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/obsolete.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/obsolete.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/obsolete.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,294 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymcehtmltestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/html/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/html/tests.js   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/html/tests.js      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,14 +0,0 @@
</span><del>-{
-       "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"}
-       ]
-}
</del></span></pre></div>
<a id="trunktestsquniteditortinymcetestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/tests.js        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/tests.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,15 +0,0 @@
</span><del>-{
-       "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}
-       ]
-}
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiAbsoluteLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,63 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiAbsoluteLayoutjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+(function() {
+       module("tinymce.ui.AbsoluteLayout", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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() {
+               var panel = createPanel({
+                       items: [
+                               {type: 'spacer', x: 10, y: 20, w: 100, h: 120, classes: 'red'}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 200, 200]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [10, 20, 100, 120]);
+       });
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/AbsoluteLayout.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiButtonhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Button.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Button.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Button.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,133 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiButtonjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Button.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Button.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Button.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,104 @@
</span><ins>+(function() {
+       module("tinymce.ui.Button", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 34, 30], 4);
+       });
+
+       test("button text, size large", function() {
+               var button = createButton({text: 'X', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 41, 39], 4);
+       });
+
+       test("button text, size small", function() {
+               var button = createButton({text: 'X', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(button), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(button.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("button icon, size default", function() {
+               var button = createButton({icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 40, 30], 4);
+       });
+
+       test("button icon, size small", function() {
+               var button = createButton({icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 28, 24], 4);
+       });
+
+       test("button icon, size large", function() {
+               var button = createButton({icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(button), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(button.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("button text & icon, size default", function() {
+               var button = createButton({text: 'X', icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 52, 30], 4);
+       });
+
+       test("button text & icon, size large", function() {
+               var button = createButton({text: 'X', icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(button), [0, 0, 59, 40], 4);
+       });
+
+       test("button text & icon, size small", function() {
+               var button = createButton({text: 'X', icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(button), [0, 0, 100, 100]);
+               deepEqual(Utils.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'});
+       });
+})();
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Button.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiButtonGrouphtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ButtonGroup.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ButtonGroup.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ButtonGroup.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiCheckboxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Checkbox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Checkbox.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Checkbox.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiCollectionhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Collection.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Collection.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Collection.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,273 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiCollectionjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Collection.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Collection.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Collection.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,253 @@
</span><ins>+(function() {
+       var panel;
+
+       module("tinymce.ui.Collection", {
+               setupModule: 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'));
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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) {
+                       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);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Collection.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiColorButtonhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ColorButton.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ColorButton.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ColorButton.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,132 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiColorButtonjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/ColorButton.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ColorButton.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/ColorButton.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,102 @@
</span><ins>+(function() {
+       module("tinymce.ui.ColorButton", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 42, 30], 4);
+       });
+
+       test("colorbutton text, size large", function() {
+               var colorButton = createColorButton({text: 'X', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 49, 39], 4);
+       });
+
+       test("colorbutton text, size small", function() {
+               var colorButton = createColorButton({text: 'X', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(colorButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(colorButton.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("colorbutton icon, size default", function() {
+               var colorButton = createColorButton({icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 50, 30], 4);
+       });
+
+       test("colorbutton icon, size small", function() {
+               var colorButton = createColorButton({icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 43, 24], 4);
+       });
+
+       test("colorbutton icon, size large", function() {
+               var colorButton = createColorButton({icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(colorButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(colorButton.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("colorbutton text & icon, size default", function() {
+               var colorButton = createColorButton({text: 'X', icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 62, 30], 4);
+       });
+
+       test("colorbutton text & icon, size large", function() {
+               var colorButton = createColorButton({text: 'X', icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(colorButton), [0, 0, 69, 40], 4);
+       });
+
+       test("colorbutton text & icon, size small", function() {
+               var colorButton = createColorButton({text: 'X', icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.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(Utils.rect(colorButton), [0, 0, 100, 100]);
+               deepEqual(Utils.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'});
+       });
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/ColorButton.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiComboBoxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ComboBox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ComboBox.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ComboBox.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,49 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiContainerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Container.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Container.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Container.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiControlhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Control.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Control.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Control.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,229 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiControljs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Control.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Control.js                           (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Control.js      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,204 @@
</span><ins>+(function() {
+       module("tinymce.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'));
+       });
+       */
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Control.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiDragHelperhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/DragHelper.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/DragHelper.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/DragHelper.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiElementPathhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ElementPath.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ElementPath.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ElementPath.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFactoryhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Factory.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Factory.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Factory.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFieldSethtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FieldSet.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FieldSet.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FieldSet.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFilePickerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FilePicker.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FilePicker.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FilePicker.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFitLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FitLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FitLayout.html       2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FitLayout.html  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,87 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFitLayoutjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/FitLayout.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FitLayout.js                         (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/FitLayout.js    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+(function() {
+       var panel;
+
+       module("tinymce.ui.FitLayout", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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(Utils.rect(panel), [0, 0, 200, 200]);
+               deepEqual(Utils.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(Utils.rect(panel), [0, 0, 200, 200]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [4, 4, 192, 192]);
+       });
+
+       test("fit with panel inside", function() {
+               panel = createFitPanel({
+                       items: [
+                               {type: 'panel', border: 1}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 200, 200]);
+               deepEqual(Utils.rect(panel.find('panel')[0]), [1, 1, 198, 198]);
+       });
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/FitLayout.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiFlexLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FlexLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FlexLayout.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FlexLayout.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,915 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFlexLayoutjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/FlexLayout.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FlexLayout.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/FlexLayout.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,884 @@
</span><ins>+(function() {
+       var panel;
+
+       module("tinymce.ui.FlexLayout", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       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();
+
+               Utils.resetScroll(panel.getEl('body'));
+
+               return panel;
+       }
+
+       test("pack: default, align: default, flex: default", function() {
+               panel = renderPanel({});
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
+       });
+
+       test("pack: default, align: default, flex: default, borders", function() {
+               panel = renderPanel({defaults: {border: 1}});
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 22, 22]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [22, 0, 22, 22]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [44, 0, 22, 22]);
+       });
+
+       test("pack: default, flex: 1", function() {
+               panel = renderPanel({
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 62, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [62, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [128, 0, 72, 20]);
+       });
+
+       test("pack: start, flex: default", function() {
+               panel = renderPanel({
+                       pack: "start"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
+       });
+
+       test("pack: start, flex: 1", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
+       });
+
+       test("pack: end, flex: default", function() {
+               panel = renderPanel({
+                       pack: "end"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [140, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [160, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
+       });
+
+       test("pack: end, flex: 1", function() {
+               panel = renderPanel({
+                       pack: "end",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
+       });
+
+       test("pack: center, flex: default", function() {
+               panel = renderPanel({
+                       pack: "center"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [70, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [110, 0, 20, 20]);
+       });
+
+       test("pack: center, flex: 1", function() {
+               panel = renderPanel({
+                       pack: "center",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
+       });
+
+       test("pack: start, spacing: 3", function() {
+               panel = renderPanel({
+                       layout: "flex",
+                       pack: "start",
+                       spacing: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [23, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [46, 0, 20, 20]);
+       });
+
+       test("pack: end, spacing: 3", function() {
+               panel = renderPanel({
+                       pack: "end",
+                       spacing: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [134, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [157, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
+       });
+
+       test("pack: center, spacing: 3", function() {
+               panel = renderPanel({
+                       pack: "center",
+                       spacing: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [67, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [113, 0, 20, 20]);
+       });
+
+       test("pack: start, padding: 3", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       padding: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [23, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [26, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [49, 3, 20, 20]);
+       });
+
+       test("pack: start, align: start", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       align: "start"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
+       });
+
+       test("pack start, align: center", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       align: "center"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 90, 20, 20]);
+       });
+
+       test("pack: start, align: end", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       align: "end"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 180, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 180, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 180, 20, 20]);
+       });
+
+       test("pack: start, align: stretch", function() {
+               panel = renderPanel({
+                       pack: "start",
+                       align: "stretch"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 200]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 200]);
+               Utils.nearlyEqualRects(Utils.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
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 194]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [23, 3, 20, 194]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 43, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [43, 0, 98, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [141, 0, 59, 20]);
+       });
+
+       test("pack: justify", function() {
+               panel = renderPanel({
+                       pack: "justify"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [180, 0, 20, 20]);
+       });
+
+       test("pack: justify, padding: 3", function() {
+               panel = renderPanel({
+                       pack: "justify",
+                       padding: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [45, 3,  80, 20]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 160, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [160, 0, 80, 20]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 90, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 0, 220, 20]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [40, 0, 20, 20]);
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 60, 20]);
+               panel.items().eq(0).hide();
+               panel.reflow();
+
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [67, 0, 67, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [133, 0, 67, 20]);
+
+               panel.layoutRect({w: 400, h: 400}).reflow();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 400, 400]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 133, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [133, 0, 133, 20]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 100, 100]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 100, 100]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [20, 20, 100, 100]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 200, 20]);
+               Utils.nearlyEqualRects(Utils.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();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 402, 402]);
+               Utils.nearlyEqualRects(Utils.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();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 110, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find("panel")[0]), [20, 0, 70, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [30, 10, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [60, 10, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 80, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find("panel")[0]), [20, 0, 40, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [30, 10, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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({});
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
+       });
+
+       test("direction: column, pack: default, flex: 1", function() {
+               panel = renderColumnPanel({
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
+               Utils.nearlyEqualRects(Utils.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'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 62]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 62, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 128, 20, 72]);
+       });
+
+       test("direction: column, pack: start, flex: default", function() {
+               panel = renderColumnPanel({
+                       pack: "start"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
+       });
+
+       test("direction: column, pack: start, flex: 1", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
+       });
+
+       test("direction: column, pack: end, flex: default", function() {
+               panel = renderColumnPanel({
+                       pack: "end"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 140, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 160, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
+       });
+
+       test("direction: column, pack: end, flex: 1", function() {
+               panel = renderColumnPanel({
+                       pack: "end",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
+       });
+
+       test("direction: column, pack: center, flex: default", function() {
+               panel = renderColumnPanel({
+                       pack: "center"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 70, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 110, 20, 20]);
+       });
+
+       test("direction: column, pack: center, flex: 1", function() {
+               panel = renderColumnPanel({
+                       pack: "center",
+                       defaults: {flex: 1}
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
+               Utils.nearlyEqualRects(Utils.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
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 23, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 46, 20, 20]);
+       });
+
+       test("direction: column, pack: end, spacing: 3", function() {
+               panel = renderColumnPanel({
+                       pack: "end",
+                       spacing: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 134, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 157, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
+       });
+
+       test("direction: column, pack: center, spacing: 3", function() {
+               panel = renderColumnPanel({
+                       pack: "center",
+                       spacing: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 67, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 113, 20, 20]);
+       });
+
+       test("direction: column, pack: start, padding: 3", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       padding: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [3, 23, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [3, 26, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [3, 49, 20, 20]);
+       });
+
+       test("direction: column, pack: start, align: start", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       align: "start"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 40, 20, 20]);
+       });
+
+       test("direction: column, pack start, align: center", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       align: "center"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [90, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [90, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [90, 40, 20, 20]);
+       });
+
+       test("direction: column, pack: start, align: end", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       align: "end"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [180, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [180, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [180, 40, 20, 20]);
+       });
+
+       test("direction: column, pack: start, align: stretch", function() {
+               panel = renderColumnPanel({
+                       pack: "start",
+                       align: "stretch"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 200, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 20, 200, 20]);
+               Utils.nearlyEqualRects(Utils.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
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 194, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [3, 23, 194, 20]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 43]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 43, 20, 98]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 141, 20, 59]);
+       });
+
+       test("direction: column, pack: justify", function() {
+               panel = renderColumnPanel({
+                       pack: "justify"
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 180, 20, 20]);
+       });
+
+       test("direction: column, pack: justify, padding: 3", function() {
+               panel = renderColumnPanel({
+                       pack: "justify",
+                       padding: 3
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [3, 90, 20, 20]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [3, 45, 20, 80]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 160]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 160, 20, 80]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 90]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 90, 20, 220]);
+               Utils.nearlyEqualRects(Utils.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}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 67, 20, 67]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [0, 133, 20, 67]);
+
+               panel.layoutRect({w: 400, h: 400}).reflow();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 400, 400]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 133]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [0, 133, 20, 133]);
+               Utils.nearlyEqualRects(Utils.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();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 402, 402]);
+               Utils.nearlyEqualRects(Utils.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();
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 110, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find("panel")[0]), [20, 0, 70, 40]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[0]), [0, 20, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[1]), [30, 10, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[2]), [60, 10, 20, 20]);
+               Utils.nearlyEqualRects(Utils.rect(panel.find('spacer')[3]), [90, 20, 20, 20]);
+       });
+})();
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/FlexLayout.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiFloatPanelhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FloatPanel.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FloatPanel.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FloatPanel.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFlowLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FlowLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FlowLayout.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FlowLayout.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFormhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Form.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Form.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Form.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiFormItemhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/FormItem.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/FormItem.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/FormItem.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiGridLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/GridLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/GridLayout.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/GridLayout.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,244 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiGridLayoutjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/GridLayout.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/GridLayout.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/GridLayout.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,212 @@
</span><ins>+(function() {
+       module("tinymce.ui.GridLayout", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function renderGridPanel(settings) {
+               var panel = tinymce.ui.Factory.create(tinymce.extend({
+                       type: "panel",
+                       layout: "grid",
+                       defaults: {type: 'spacer'}
+               }, settings)).renderTo(document.getElementById('view')).reflow();
+
+               Utils.resetScroll(panel.getEl('body'));
+
+               return panel;
+       }
+
+       test("automatic grid size 2x2", function() {
+               var panel = renderGridPanel({
+                       items: [
+                               {classes: 'red'}, {classes: 'green'},
+                               {classes: 'blue'}, {classes: 'cyan'}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 40, 40]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [20, 0, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 20,  20, 20]);
+               deepEqual(Utils.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(Utils.rect(panel), [0, 0, 200, 200]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [0, 0, 17, 22]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [17, 0, 17, 22]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 22, 16, 22]);
+               deepEqual(Utils.rect(panel.find('spacer')[3]), [17, 22, 17, 22]);
+       });
+       */
+
+       test("spacing: 3, automatic grid size 2x2", function() {
+               var panel = renderGridPanel({
+                       spacing: 3,
+                       items: [
+                               {classes: 'red'}, {classes: 'green'},
+                               {classes: 'blue'}, {classes: 'cyan'}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 43, 43]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [0, 0, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [23, 0, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 23, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[3]), [23, 23, 20, 20]);
+       });
+
+       test("padding: 3, automatic grid size 2x2", function() {
+               var panel = renderGridPanel({
+                       padding: 3,
+                       items: [
+                               {classes: 'red'}, {classes: 'green'},
+                               {classes: 'blue'}, {classes: 'cyan'}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 46, 46]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [23, 3, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [3, 23, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[3]), [23, 23, 20, 20]);
+       });
+
+       test("spacing: 3, padding: 3, automatic grid size 2x2", function() {
+               var panel = renderGridPanel({
+                       padding: 3,
+                       spacing: 3,
+                       items: [
+                               {classes: 'red'}, {classes: 'green'},
+                               {classes: 'blue'}, {classes: 'cyan'}
+                       ]
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 49, 49]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [3, 3, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [26, 3, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [3, 26, 20, 20]);
+               deepEqual(Utils.rect(panel.find('spacer')[3]), [26, 26, 20, 20]);
+       });
+
+       test("inner elements 100x100 maxWidth/maxHeight: 118 (overflow W+H)", function() {
+               var 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(Utils.rect(panel), [0, 0, 118, 118]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
+               deepEqual(Utils.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() {
+               var 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(Utils.rect(panel), [0, 0, 118, 118]);
+               deepEqual(Utils.rect(panel.find('spacer')[0]), [20, 20, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [130, 20, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [20, 130, 100, 100]);
+               deepEqual(Utils.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() {
+               var 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(Utils.rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
+               deepEqual(Utils.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() {
+               var 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(Utils.rect(panel.find('spacer')[0]), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[1]), [100, 0, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[2]), [0, 100, 100, 100]);
+               deepEqual(Utils.rect(panel.find('spacer')[3]), [100, 100, 100, 100]);
+               equal(panel.layoutRect().contentW, 200);
+               equal(panel.layoutRect().contentH, 200);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/GridLayout.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiIframehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Iframe.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Iframe.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Iframe.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiKeyboardNavigationhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/KeyboardNavigation.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/KeyboardNavigation.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/KeyboardNavigation.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiLabelhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Label.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Label.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Label.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Layout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Layout.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Layout.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiListBoxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ListBox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ListBox.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ListBox.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.ListBox 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.ListBox", {
-       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.ListBox 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMenuhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Menu.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Menu.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Menu.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Menu 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.Menu", {
-       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.Menu 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMenuBarhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/MenuBar.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/MenuBar.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/MenuBar.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.MenuBar 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.MenuBar", {
-       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.MenuBar 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMenuButtonhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/MenuButton.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/MenuButton.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/MenuButton.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,139 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.MenuButton 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.MenuButton", {
-       setup: function() {
-               document.getElementById('view').innerHTML = '';
-       },
-
-       teardown: function() {
-               //document.getElementById('view').innerHTML = '';
-       }
-});
-
-window.onload = function() {
-       QUnit.start();
-};
-
-function createMenuButton(settings) {
-       return tinymce.ui.Factory.create(tinymce.extend({
-               type: 'menubutton',
-               menu: [
-                       {text: '1'},
-                       {text: '2'},
-                       {text: '3'}
-               ]
-       }, settings)).renderTo(document.getElementById('view'));
-}
-
-test("menubutton text, size default", function() {
-       var menuButton = createMenuButton({text: 'X'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 46, 30], 4);
-});
-
-test("menubutton text, size large", function() {
-       var menuButton = createMenuButton({text: 'X', size: 'large'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 53, 39], 4);
-});
-
-test("menubutton text, size small", function() {
-       var menuButton = createMenuButton({text: 'X', size: 'small'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 30, 23], 4);
-});
-
-test("menubutton text, width 100, height 100", function() {
-       var menuButton = createMenuButton({text: 'X', width: 100, height: 100});
-
-       deepEqual(rect(menuButton), [0, 0, 100, 100]);
-       deepEqual(rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
-});
-
-test("menubutton icon, size default", function() {
-       var menuButton = createMenuButton({icon: 'test'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 52, 30], 4);
-});
-
-test("menubutton icon, size small", function() {
-       var menuButton = createMenuButton({icon: 'test', size: 'small'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 39, 24], 4);
-});
-
-test("menubutton icon, size large", function() {
-       var menuButton = createMenuButton({icon: 'test', size: 'large'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 56, 40], 4);
-});
-
-test("menubutton icon, width 100, height 100", function() {
-       var menuButton = createMenuButton({icon: 'test', width: 100, height: 100});
-
-       deepEqual(rect(menuButton), [0, 0, 100, 100]);
-       deepEqual(rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
-});
-
-test("menubutton text & icon, size default", function() {
-       var menuButton = createMenuButton({text: 'X', icon: 'test'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 64, 30], 4);
-});
-
-test("menubutton text & icon, size large", function() {
-       var menuButton = createMenuButton({text: 'X', icon: 'test', size: 'large'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 71, 40], 4);
-});
-
-test("menubutton text & icon, size small", function() {
-       var menuButton = createMenuButton({text: 'X', icon: 'test', size: 'small'});
-
-       nearlyEqualRects(rect(menuButton), [0, 0, 49, 24], 4);
-});
-
-test("menubutton text & icon, width 100, height 100", function() {
-       var menuButton = createMenuButton({text: 'X', icon: 'test', width: 100, height: 100});
-
-       deepEqual(rect(menuButton), [0, 0, 100, 100]);
-       deepEqual(rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
-});
-
-test("menubutton click event", function() {
-       var menuButton, clicks = {};
-
-       menuButton = createMenuButton({text: 'X', onclick: function() {clicks.a = 'a';}});
-       menuButton.on('click', function() {clicks.b = 'b';});
-       menuButton;
-       menuButton.on('click', function() {clicks.c = 'c';});
-       menuButton.fire('click');
-
-       deepEqual(clicks, {a: 'a', b: 'b', c: 'c'});
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">MenuButton 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMenuButtonjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/MenuButton.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/MenuButton.js                                (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/MenuButton.js   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,108 @@
</span><ins>+(function() {
+       module("tinymce.ui.MenuButton", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function createMenuButton(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'menubutton',
+                       menu: [
+                               {text: '1'},
+                               {text: '2'},
+                               {text: '3'}
+                       ]
+               }, settings)).renderTo(document.getElementById('view'));
+       }
+
+       test("menubutton text, size default", function() {
+               var menuButton = createMenuButton({text: 'X'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 46, 30], 4);
+       });
+
+       test("menubutton text, size large", function() {
+               var menuButton = createMenuButton({text: 'X', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 53, 39], 4);
+       });
+
+       test("menubutton text, size small", function() {
+               var menuButton = createMenuButton({text: 'X', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 30, 23], 4);
+       });
+
+       test("menubutton text, width 100, height 100", function() {
+               var menuButton = createMenuButton({text: 'X', width: 100, height: 100});
+
+               deepEqual(Utils.rect(menuButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("menubutton icon, size default", function() {
+               var menuButton = createMenuButton({icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 52, 30], 4);
+       });
+
+       test("menubutton icon, size small", function() {
+               var menuButton = createMenuButton({icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 39, 24], 4);
+       });
+
+       test("menubutton icon, size large", function() {
+               var menuButton = createMenuButton({icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 56, 40], 6);
+       });
+
+       test("menubutton icon, width 100, height 100", function() {
+               var menuButton = createMenuButton({icon: 'test', width: 100, height: 100});
+
+               deepEqual(Utils.rect(menuButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("menubutton text & icon, size default", function() {
+               var menuButton = createMenuButton({text: 'X', icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 64, 30], 4);
+       });
+
+       test("menubutton text & icon, size large", function() {
+               var menuButton = createMenuButton({text: 'X', icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 71, 40], 4);
+       });
+
+       test("menubutton text & icon, size small", function() {
+               var menuButton = createMenuButton({text: 'X', icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(menuButton), [0, 0, 49, 24], 4);
+       });
+
+       test("menubutton text & icon, width 100, height 100", function() {
+               var menuButton = createMenuButton({text: 'X', icon: 'test', width: 100, height: 100});
+
+               deepEqual(Utils.rect(menuButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(menuButton.getEl().firstChild), [1, 1, 98, 98]);
+       });
+
+       test("menubutton click event", function() {
+               var menuButton, clicks = {};
+
+               menuButton = createMenuButton({text: 'X', onclick: function() {clicks.a = 'a';}});
+               menuButton.on('click', function() {clicks.b = 'b';});
+               menuButton.on('click', function() {clicks.c = 'c';});
+               menuButton.fire('click');
+
+               deepEqual(clicks, {a: 'a', b: 'b', c: 'c'});
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/MenuButton.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiMenuItemhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/MenuItem.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/MenuItem.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/MenuItem.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.MenuItem 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.MenuItem", {
-       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.MenuItem 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMessageBoxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/MessageBox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/MessageBox.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/MessageBox.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.MessageBox 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.MessageBox", {
-       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.MessageBox 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiMovablehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Movable.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Movable.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Movable.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Movable 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.Movable", {
-       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.Movable 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiPanelhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Panel.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Panel.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Panel.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,67 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Panel</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.Panel", {
-       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'
-       }, settings)).renderTo(document.getElementById('view')).reflow();
-}
-
-test("panel width: 100, height: 100", function() {
-       panel = createPanel({
-               width: 100,
-               height: 100
-       });
-
-       nearlyEqualRects(rect(panel), [0, 0, 100, 100], 4);
-});
-
-test("panel border: 1, width: 100, height: 100", function() {
-       panel = createPanel({
-               width: 100,
-               height: 100,
-               border: 1
-       });
-
-       nearlyEqualRects(rect(panel), [0, 0, 100, 100], 4);
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">ui.Panel 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiPaneljs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Panel.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Panel.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Panel.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+(function() {
+       var panel;
+
+       module("tinymce.ui.Panel", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function createPanel(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'panel'
+               }, settings)).renderTo(document.getElementById('view')).reflow();
+       }
+
+       test("panel width: 100, height: 100", function() {
+               panel = createPanel({
+                       width: 100,
+                       height: 100
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 100, 100], 4);
+       });
+
+       test("panel border: 1, width: 100, height: 100", function() {
+               panel = createPanel({
+                       width: 100,
+                       height: 100,
+                       border: 1
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 100, 100], 4);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Panel.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiPanelButtonhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/PanelButton.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/PanelButton.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/PanelButton.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.PanelButton 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.PanelButton", {
-       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.PanelButton 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiPathhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Path.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Path.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Path.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Path 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.Path", {
-       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.Path 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiRadiohtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Radio.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Radio.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Radio.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Radio 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.Radio", {
-       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.Radio 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiResizeHandlehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/ResizeHandle.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/ResizeHandle.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/ResizeHandle.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.ResizeHandle 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.ResizeHandle", {
-       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.ResizeHandle 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiScrollablehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Scrollable.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Scrollable.html      2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Scrollable.html 2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Scrollable 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.Scrollable", {
-       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.Scrollable 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiSelectorhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Selector.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Selector.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Selector.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,148 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Selector 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.Selector");
-
-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("Basic", function() {
-       var matches;
-
-       matches = panel.find('button');
-       equal(matches.length, 12);
-       equal(matches[0].type, 'button');
-
-       equal(panel.find('Button').length, 12);
-       equal(panel.find('buttongroup').length, 3);
-       equal(panel.find('buttongroup button').length, 9);
-       equal(panel.find('toolbar buttongroup button').length, 3);
-       equal(panel.find('button#button1').length, 1);
-       equal(panel.find('buttongroup#buttongroup1 button#button4').length, 1);
-       equal(panel.find('button,button,buttongroup button').length, 12, 'Check unique');
-});
-
-test("Classes", function() {
-       equal(panel.find('button.class1').length, 3);
-       equal(panel.find('button.class1.class2').length, 2);
-       equal(panel.find('button.class2.class1').length, 2);
-       equal(panel.find('button.classX').length, 0);
-       equal(panel.find('button.class1, button.class2').length, 3);
-});
-
-test("Psuedo:not", function() {
-       equal(panel.find('button:not(.class1)').length, 9);
-       equal(panel.find('button:not(buttongroup button)').length, 3);
-       equal(panel.find('button:not(toolbar button)').length, 9);
-       equal(panel.find('button:not(toolbar buttongroup button)').length, 9);
-       equal(panel.find('button:not(panel button)').length, 0);
-       equal(panel.find('button:not(.class1)').length, 9);
-       equal(panel.find('button:not(.class3, .class4)').length, 10);
-});
-
-test("Psuedo:odd/even/first/last", function() {
-       var matches;
-
-       matches = panel.find('button:first');
-
-       equal(matches.length, 4);
-       ok(matches[0].name() == 'button1');
-       ok(matches[3].name() == 'button10');
-
-       matches = panel.find('button:last');
-
-       equal(matches.length, 3);
-       ok(matches[0].name() == 'button6');
-       ok(matches[1].name() == 'button9');
-
-       matches = panel.find('button:odd');
-
-       equal(matches.length, 4);
-       ok(matches[0].name() == 'button2');
-       ok(matches[1].name() == 'button5');
-
-       matches = panel.find('button:even');
-
-       equal(matches.length, 8);
-       ok(matches[0].name() == 'button1');
-       ok(matches[1].name() == 'button3');
-});
-
-test("Psuedo:disabled", function() {
-       equal(panel.find('button:disabled').length, 2);
-});
-
-test("Attribute value", function() {
-       equal(panel.find('button[name]').length, 12);
-       equal(panel.find('button[name=button1]').length, 1);
-       equal(panel.find('button[name^=button1]').length, 4);
-       equal(panel.find('button[name$=1]').length, 2);
-       equal(panel.find('button[name*=utt]').length, 12);
-       equal(panel.find('button[name!=button1]').length, 11);
-});
-
-test("Direct descendant", function() {
-       equal(panel.find('> button').length, 3);
-       equal(panel.find('toolbar > buttongroup').length, 1);
-       equal(panel.find('toolbar > button').length, 0);
-});
-
-test("Parents", function() {
-       equal(panel.find("#button10")[0].parents("toolbar,buttongroup").length, 2);
-       equal(panel.find("#button10")[0].parents("panel").length, 1);
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">ui.Selector 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiSelectorjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Selector.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Selector.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Selector.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,127 @@
</span><ins>+(function() {
+       var panel;
+
+       module("tinymce.ui.Selector", {
+               setupModule: 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'));
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       test("Basic", function() {
+               var matches;
+
+               matches = panel.find('button');
+               equal(matches.length, 12);
+               equal(matches[0].type, 'button');
+
+               equal(panel.find('Button').length, 12);
+               equal(panel.find('buttongroup').length, 3);
+               equal(panel.find('buttongroup button').length, 9);
+               equal(panel.find('toolbar buttongroup button').length, 3);
+               equal(panel.find('button#button1').length, 1);
+               equal(panel.find('buttongroup#buttongroup1 button#button4').length, 1);
+               equal(panel.find('button,button,buttongroup button').length, 12, 'Check unique');
+       });
+
+       test("Classes", function() {
+               equal(panel.find('button.class1').length, 3);
+               equal(panel.find('button.class1.class2').length, 2);
+               equal(panel.find('button.class2.class1').length, 2);
+               equal(panel.find('button.classX').length, 0);
+               equal(panel.find('button.class1, button.class2').length, 3);
+       });
+
+       test("Psuedo:not", function() {
+               equal(panel.find('button:not(.class1)').length, 9);
+               equal(panel.find('button:not(buttongroup button)').length, 3);
+               equal(panel.find('button:not(toolbar button)').length, 9);
+               equal(panel.find('button:not(toolbar buttongroup button)').length, 9);
+               equal(panel.find('button:not(panel button)').length, 0);
+               equal(panel.find('button:not(.class1)').length, 9);
+               equal(panel.find('button:not(.class3, .class4)').length, 10);
+       });
+
+       test("Psuedo:odd/even/first/last", function() {
+               var matches;
+
+               matches = panel.find('button:first');
+
+               equal(matches.length, 4);
+               ok(matches[0].name() == 'button1');
+               ok(matches[3].name() == 'button10');
+
+               matches = panel.find('button:last');
+
+               equal(matches.length, 3);
+               ok(matches[0].name() == 'button6');
+               ok(matches[1].name() == 'button9');
+
+               matches = panel.find('button:odd');
+
+               equal(matches.length, 4);
+               ok(matches[0].name() == 'button2');
+               ok(matches[1].name() == 'button5');
+
+               matches = panel.find('button:even');
+
+               equal(matches.length, 8);
+               ok(matches[0].name() == 'button1');
+               ok(matches[1].name() == 'button3');
+       });
+
+       test("Psuedo:disabled", function() {
+               equal(panel.find('button:disabled').length, 2);
+       });
+
+       test("Attribute value", function() {
+               equal(panel.find('button[name]').length, 12);
+               equal(panel.find('button[name=button1]').length, 1);
+               equal(panel.find('button[name^=button1]').length, 4);
+               equal(panel.find('button[name$=1]').length, 2);
+               equal(panel.find('button[name*=utt]').length, 12);
+               equal(panel.find('button[name!=button1]').length, 11);
+       });
+
+       test("Direct descendant", function() {
+               equal(panel.find('> button').length, 3);
+               equal(panel.find('toolbar > buttongroup').length, 1);
+               equal(panel.find('toolbar > button').length, 0);
+       });
+
+       test("Parents", function() {
+               equal(panel.find("#button10")[0].parents("toolbar,buttongroup").length, 2);
+               equal(panel.find("#button10")[0].parents("panel").length, 1);
+       });
+})();
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Selector.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiSpacerhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Spacer.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Spacer.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Spacer.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Spacer 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.Spacer", {
-       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.Spacer 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiSplitButtonhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/SplitButton.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/SplitButton.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/SplitButton.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,131 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.SplitButton 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.SplitButton", {
-       setup: function() {
-               document.getElementById('view').innerHTML = '';
-       },
-
-       teardown: function() {
-               //document.getElementById('view').innerHTML = '';
-       }
-});
-
-window.onload = function() {
-       QUnit.start();
-};
-
-function createSplitButton(settings) {
-       return tinymce.ui.Factory.create(tinymce.extend({
-               type: 'splitbutton'
-       }, settings)).renderTo(document.getElementById('view'));
-}
-
-test("splitbutton text, size default", function() {
-       var splitButton = createSplitButton({text: 'X'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 42, 30], 4);
-});
-
-test("splitbutton text, size large", function() {
-       var splitButton = createSplitButton({text: 'X', size: 'large'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 49, 39], 4);
-});
-
-test("splitbutton text, size small", function() {
-       var splitButton = createSplitButton({text: 'X', size: 'small'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 36, 23], 4);
-});
-
-test("splitbutton text, width 100, height 100", function() {
-       var splitButton = createSplitButton({text: 'X', width: 100, height: 100});
-
-       deepEqual(rect(splitButton), [0, 0, 100, 100]);
-       deepEqual(rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
-});
-
-test("splitbutton icon, size default", function() {
-       var splitButton = createSplitButton({icon: 'test'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 50, 30], 4);
-});
-
-test("splitbutton icon, size small", function() {
-       var splitButton = createSplitButton({icon: 'test', size: 'small'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 45, 24], 4);
-});
-
-test("splitbutton icon, size large", function() {
-       var splitButton = createSplitButton({icon: 'test', size: 'large'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 54, 40], 4);
-});
-
-test("splitbutton icon, width 100, height 100", function() {
-       var splitButton = createSplitButton({icon: 'test', width: 100, height: 100});
-
-       deepEqual(rect(splitButton), [0, 0, 100, 100]);
-       deepEqual(rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
-});
-
-test("splitbutton text & icon, size default", function() {
-       var splitButton = createSplitButton({text: 'X', icon: 'test'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 62, 30], 4);
-});
-
-test("splitbutton text & icon, size large", function() {
-       var splitButton = createSplitButton({text: 'X', icon: 'test', size: 'large'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 69, 40], 4);
-});
-
-test("splitbutton text & icon, size small", function() {
-       var splitButton = createSplitButton({text: 'X', icon: 'test', size: 'small'});
-
-       nearlyEqualRects(rect(splitButton), [0, 0, 55, 24], 4);
-});
-
-test("splitbutton text & icon, width 100, height 100", function() {
-       var splitButton = createSplitButton({text: 'X', icon: 'test', width: 100, height: 100});
-
-       deepEqual(rect(splitButton), [0, 0, 100, 100]);
-       deepEqual(rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
-});
-
-test("splitbutton click event", function() {
-       var splitButton, clicks = {};
-
-       splitButton = createSplitButton({text: 'X', onclick: function() {clicks.a = 'a';}});
-       splitButton.fire('click', {target: splitButton.getEl().firstChild});
-
-       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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiSplitButtonjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/SplitButton.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/SplitButton.js                               (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/SplitButton.js  2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,102 @@
</span><ins>+(function() {
+       module("tinymce.ui.SplitButton", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function createSplitButton(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'splitbutton'
+               }, settings)).renderTo(document.getElementById('view'));
+       }
+
+       test("splitbutton text, size default", function() {
+               var splitButton = createSplitButton({text: 'X'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 42, 30], 4);
+       });
+
+       test("splitbutton text, size large", function() {
+               var splitButton = createSplitButton({text: 'X', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 49, 39], 4);
+       });
+
+       test("splitbutton text, size small", function() {
+               var splitButton = createSplitButton({text: 'X', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 36, 23], 4);
+       });
+
+       test("splitbutton text, width 100, height 100", function() {
+               var splitButton = createSplitButton({text: 'X', width: 100, height: 100});
+
+               deepEqual(Utils.rect(splitButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
+       });
+
+       test("splitbutton icon, size default", function() {
+               var splitButton = createSplitButton({icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 50, 30], 4);
+       });
+
+       test("splitbutton icon, size small", function() {
+               var splitButton = createSplitButton({icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 45, 24], 4);
+       });
+
+       test("splitbutton icon, size large", function() {
+               var splitButton = createSplitButton({icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 54, 40], 4);
+       });
+
+       test("splitbutton icon, width 100, height 100", function() {
+               var splitButton = createSplitButton({icon: 'test', width: 100, height: 100});
+
+               deepEqual(Utils.rect(splitButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
+       });
+
+       test("splitbutton text & icon, size default", function() {
+               var splitButton = createSplitButton({text: 'X', icon: 'test'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 62, 30], 4);
+       });
+
+       test("splitbutton text & icon, size large", function() {
+               var splitButton = createSplitButton({text: 'X', icon: 'test', size: 'large'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 69, 40], 4);
+       });
+
+       test("splitbutton text & icon, size small", function() {
+               var splitButton = createSplitButton({text: 'X', icon: 'test', size: 'small'});
+
+               Utils.nearlyEqualRects(Utils.rect(splitButton), [0, 0, 55, 24], 4);
+       });
+
+       test("splitbutton text & icon, width 100, height 100", function() {
+               var splitButton = createSplitButton({text: 'X', icon: 'test', width: 100, height: 100});
+
+               deepEqual(Utils.rect(splitButton), [0, 0, 100, 100]);
+               deepEqual(Utils.rect(splitButton.getEl().firstChild), [1, 1, 82, 98]);
+       });
+
+       test("splitbutton click event", function() {
+               var splitButton, clicks = {};
+
+               splitButton = createSplitButton({text: 'X', onclick: function() {clicks.a = 'a';}});
+               splitButton.fire('click', {target: splitButton.getEl().firstChild});
+
+               deepEqual(clicks, {a: 'a'});
+       });
+})();
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/SplitButton.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiStackLayouthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/StackLayout.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/StackLayout.html     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/StackLayout.html        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.StackLayout 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.StackLayout", {
-       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.StackLayout 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiTabPanelhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/TabPanel.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/TabPanel.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/TabPanel.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,164 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.TabPanel 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.TabPanel", {
-       setup: function() {
-               document.getElementById('view').innerHTML = '';
-       },
-
-       teardown: function() {
-               //document.getElementById('view').innerHTML = '';
-       }
-});
-
-window.onload = function() {
-       QUnit.start();
-};
-
-function createTabPanel(settings) {
-       return tinymce.ui.Factory.create(tinymce.extend({
-               type: 'tabpanel',
-               items: [
-                       {title: 'a', type: 'spacer', classes: 'red'},
-                       {title: 'b', type: 'spacer', classes: 'green'},
-                       {title: 'c', type: 'spacer', classes: 'blue'}
-               ]
-       }, settings)).renderTo(document.getElementById('view')).reflow();
-}
-
-test("panel width: 100, height: 100", function() {
-       panel = createTabPanel({
-               width: 100,
-               height: 100,
-               layout: 'fit'
-       });
-
-       deepEqual(rect(panel), [0, 0, 100, 100]);
-       nearlyEqualRects(rect(panel.items()[0]), [0, 31, 100, 69], 4);
-});
-
-test("panel width: 100, height: 100, border: 1", function() {
-       panel = createTabPanel({
-               width: 100,
-               height: 100,
-               border: 1,
-               layout: 'fit'
-       });
-
-       deepEqual(rect(panel), [0, 0, 100, 100]);
-       nearlyEqualRects(rect(panel.items()[0]), [0, 31, 100, 69], 4);
-});
-
-test("panel width: 100, height: 100, activeTab: 1", function() {
-       panel = createTabPanel({
-               width: 100,
-               height: 100,
-               activeTab: 1,
-               layout: 'fit'
-       });
-
-       deepEqual(rect(panel), [0, 0, 100, 100]);
-       nearlyEqualRects(rect(panel.items()[1]), [0, 31, 100, 69], 4);
-});
-
-test("panel width: auto, height: auto, mixed sized widgets", function() {
-       panel = createTabPanel({
-               items: [
-                       {title: 'a', type: 'spacer', classes: 'red', style: 'width: 100px; height: 100px'},
-                       {title: 'b', type: 'spacer', classes: 'green', style: 'width: 70px; height: 70px'},
-                       {title: 'c', type: 'spacer', classes: 'blue', style: 'width: 120px; height: 120px'}
-               ]
-       });
-
-       nearlyEqualRects(rect(panel), [0, 0, 120, 151], 4);
-       nearlyEqualRects(rect(panel.items()[0]), [0, 31, 120, 120], 4);
-
-       panel.activateTab(1);
-       nearlyEqualRects(rect(panel.items()[1]), [0, 31, 120, 120], 4);
-
-       panel.activateTab(2);
-       nearlyEqualRects(rect(panel.items()[2]), [0, 31, 120, 120], 4);
-});
-
-test("panel width: auto, height: auto, mixed sized containers", function() {
-       panel = createTabPanel({
-               items: [
-                       {
-                               title: 'a',
-                               type: 'panel',
-                               layout: 'flex',
-                               align: 'stretch',
-                               items: {
-                                       type: 'spacer',
-                                       classes: 'red',
-                                       flex: 1,
-                                       minWidth: 100,
-                                       minHeight: 100
-                               }
-                       },
-
-                       {
-                               title: 'b',
-                               type: 'panel',
-                               layout: 'flex',
-                               align: 'stretch',
-                               items: {
-                                       type: 'spacer',
-                                       flex: 1,
-                                       classes: 'green',
-                                       minWidth: 70,
-                                       minHeight: 70
-                               }
-                       },
-
-                       {
-                               title: 'c',
-                               type: 'panel',
-                               layout: 'flex',
-                               align: 'stretch',
-                               items: {
-                                       type: 'spacer',
-                                       classes: 'blue',
-                                       flex: 1,
-                                       minWidth: 120,
-                                       minHeight: 120
-                               }
-                       }
-               ]
-       });
-
-       nearlyEqualRects(rect(panel), [0, 0, 120, 151], 4);
-       nearlyEqualRects(rect(panel.items()[0]), [0, 31, 120, 120], 4);
-
-       panel.activateTab(1);
-       nearlyEqualRects(rect(panel.items()[1]), [0, 31, 120, 120], 4);
-
-       panel.activateTab(2);
-       nearlyEqualRects(rect(panel.items()[2]), [0, 31, 120, 120], 4);
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">ui.TabPanel 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiTabPaneljs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/TabPanel.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/TabPanel.js                          (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/TabPanel.js     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,133 @@
</span><ins>+(function() {
+       module("tinymce.ui.TabPanel", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function createTabPanel(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'tabpanel',
+                       items: [
+                               {title: 'a', type: 'spacer', classes: 'red'},
+                               {title: 'b', type: 'spacer', classes: 'green'},
+                               {title: 'c', type: 'spacer', classes: 'blue'}
+                       ]
+               }, settings)).renderTo(document.getElementById('view')).reflow();
+       }
+
+       test("panel width: 100, height: 100", function() {
+               var panel = createTabPanel({
+                       width: 100,
+                       height: 100,
+                       layout: 'fit'
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 100, 100]);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[0]), [0, 31, 100, 69], 4);
+       });
+
+       test("panel width: 100, height: 100, border: 1", function() {
+               var panel = createTabPanel({
+                       width: 100,
+                       height: 100,
+                       border: 1,
+                       layout: 'fit'
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 100, 100]);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[0]), [0, 31, 100, 69], 4);
+       });
+
+       test("panel width: 100, height: 100, activeTab: 1", function() {
+               var panel = createTabPanel({
+                       width: 100,
+                       height: 100,
+                       activeTab: 1,
+                       layout: 'fit'
+               });
+
+               deepEqual(Utils.rect(panel), [0, 0, 100, 100]);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[1]), [0, 31, 100, 69], 4);
+       });
+
+       test("panel width: auto, height: auto, mixed sized widgets", function() {
+               var panel = createTabPanel({
+                       items: [
+                               {title: 'a', type: 'spacer', classes: 'red', style: 'width: 100px; height: 100px'},
+                               {title: 'b', type: 'spacer', classes: 'green', style: 'width: 70px; height: 70px'},
+                               {title: 'c', type: 'spacer', classes: 'blue', style: 'width: 120px; height: 120px'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 120, 151], 4);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[0]), [0, 31, 120, 120], 4);
+
+               panel.activateTab(1);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[1]), [0, 31, 120, 120], 4);
+
+               panel.activateTab(2);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[2]), [0, 31, 120, 120], 4);
+       });
+
+       test("panel width: auto, height: auto, mixed sized containers", function() {
+               var panel = createTabPanel({
+                       items: [
+                               {
+                                       title: 'a',
+                                       type: 'panel',
+                                       layout: 'flex',
+                                       align: 'stretch',
+                                       items: {
+                                               type: 'spacer',
+                                               classes: 'red',
+                                               flex: 1,
+                                               minWidth: 100,
+                                               minHeight: 100
+                                       }
+                               },
+
+                               {
+                                       title: 'b',
+                                       type: 'panel',
+                                       layout: 'flex',
+                                       align: 'stretch',
+                                       items: {
+                                               type: 'spacer',
+                                               flex: 1,
+                                               classes: 'green',
+                                               minWidth: 70,
+                                               minHeight: 70
+                                       }
+                               },
+
+                               {
+                                       title: 'c',
+                                       type: 'panel',
+                                       layout: 'flex',
+                                       align: 'stretch',
+                                       items: {
+                                               type: 'spacer',
+                                               classes: 'blue',
+                                               flex: 1,
+                                               minWidth: 120,
+                                               minHeight: 120
+                                       }
+                               }
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.rect(panel), [0, 0, 120, 151], 4);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[0]), [0, 31, 120, 120], 4);
+
+               panel.activateTab(1);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[1]), [0, 31, 120, 120], 4);
+
+               panel.activateTab(2);
+               Utils.nearlyEqualRects(Utils.rect(panel.items()[2]), [0, 31, 120, 120], 4);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/TabPanel.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiTextBoxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/TextBox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/TextBox.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/TextBox.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,59 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.TextBox 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();
-};
-
-function createTextBox(settings) {
-       return tinymce.ui.Factory.create(tinymce.extend({
-               type: 'textbox'
-       }, settings)).renderTo(document.getElementById('view'));
-}
-
-test("textbox text, size chars: 5", function() {
-       var textBox = createTextBox({text: 'X', size: 5});
-
-       nearlyEqualRects(size(textBox), [69, 30], 20);
-});
-
-test("textbox text, size 100x100", function() {
-       var textBox = createTextBox({text: 'X', width: 100, height: 100});
-
-       deepEqual(size(textBox), [100, 100]);
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">ui.TextBox 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiTextBoxjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/TextBox.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/TextBox.js                           (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/TextBox.js      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+(function() {
+       module("tinymce.ui.TextBox", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+               }
+       });
+
+       function createTextBox(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'textbox'
+               }, settings)).renderTo(document.getElementById('view'));
+       }
+
+       test("textbox text, size chars: 5", function() {
+               var textBox = createTextBox({text: 'X', size: 5});
+
+               Utils.nearlyEqualRects(Utils.size(textBox), [69, 30], 30);
+       });
+
+       test("textbox text, size 100x100", function() {
+               var textBox = createTextBox({text: 'X', width: 100, height: 100});
+
+               deepEqual(Utils.size(textBox), [100, 100]);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/TextBox.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuiThrobberhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Throbber.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Throbber.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Throbber.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Throbber 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.Throbber", {
-       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.Throbber 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiToolbarhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Toolbar.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Toolbar.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Toolbar.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Toolbar 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.Toolbar", {
-       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.Toolbar 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiTooltiphtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Tooltip.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Tooltip.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Tooltip.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Tooltip 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.Tooltip", {
-       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.Tooltip 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiWidgethtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Widget.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Widget.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Widget.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,43 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Widget 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.Widget", {
-       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.Widget 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiWindowhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/Window.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Window.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/Window.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,118 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="UTF-8" />
-<title>ui.Window</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 win;
-
-QUnit.config.autostart = false;
-QUnit.config.reorder = false;
-
-module("ui.Window", {
-       setup: function() {
-               document.getElementById('view').innerHTML = '';
-       },
-
-       teardown: function() {
-               tinymce.DOM.remove(document.getElementById('mce-modal-block'));
-       }
-});
-
-window.onload = function() {
-       QUnit.start();
-};
-
-function createWindow(settings) {
-       return tinymce.ui.Factory.create(tinymce.extend({
-               type: 'window'
-       }, settings)).renderTo(document.getElementById('view')).reflow();
-}
-
-test("window x, y, w, h", function() {
-       win = createWindow({x: 100, y: 120, width: 200, height: 210});
-
-       deepEqual(size(win), [200, 210]);
-});
-
-test("no title, no buttonbar, autoResize", function() {
-       win = createWindow({
-               x: 100,
-               y: 120,
-               items: [
-                       {type: 'spacer', classes: 'red'}
-               ]
-       });
-
-       deepEqual(size(win), [22, 22]);
-       deepEqual(size(win.find("spacer")[0]), [20, 20]);
-});
-
-test("title, no buttonbar, autoResize, title is widest", function() {
-       win = createWindow({
-               x: 100,
-               y: 120,
-               title: "XXXXXXXXXXXXXXXXXXXXXX",
-               items: [
-                       {type: 'spacer', classes: 'red', flex: 1}
-               ]
-       });
-
-       nearlyEqualRects(size(win), [326, 61], 10);
-       nearlyEqualRects(size(win.find("spacer")[0]), [324, 20], 10);
-});
-
-test("buttonbar, autoResize, buttonbar is widest", function() {
-       win = createWindow({
-               x: 100,
-               y: 120,
-               items: [
-                       {type: 'spacer', classes: 'red', flex: 1}
-               ],
-               buttons: [
-                       {type: 'spacer', classes: 'green', minWidth: 400}
-               ]
-       });
-
-       deepEqual(size(win), [422, 63]);
-       deepEqual(size(win.find("spacer")[0]), [420, 20]);
-       deepEqual(size(win.statusbar.find("spacer")[0]), [400, 20]);
-});
-
-test("buttonbar, title, autoResize, content is widest", function() {
-       win = createWindow({
-               x: 100,
-               y: 120,
-               title: "X",
-               items: [
-                       {type: 'spacer', classes: 'red', minWidth: 400}
-               ],
-               buttons: [
-                       {type: 'spacer', classes: 'green'}
-               ]
-       });
-
-       deepEqual(size(win), [402, 102]);
-       deepEqual(size(win.getEl("head")), [400, 39]);
-       deepEqual(size(win.find("spacer")[0]), [400, 20]);
-       deepEqual(size(win.statusbar.find("spacer")[0]), [20, 20]);
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">ui.Window Test Suite</h1>
-       <h2 id="qunit-banner"></h2>
-       <h2 id="qunit-userAgent"></h2>
-       <ol id="qunit-tests">
-       </ol>
-       <div id="view" style="position: absolute; left: 0; top: 0"></div>
-</body>
-</html>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceuiWindowjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/ui/Window.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/Window.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/ui/Window.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,87 @@
</span><ins>+(function() {
+       module("tinymce.ui.Window", {
+               setup: function() {
+                       document.getElementById('view').innerHTML = '';
+               },
+
+               teardown: function() {
+                       tinymce.dom.Event.clean(document.getElementById('view'));
+                       tinymce.DOM.remove(document.getElementById('mce-modal-block'));
+               }
+       });
+
+       function createWindow(settings) {
+               return tinymce.ui.Factory.create(tinymce.extend({
+                       type: 'window'
+               }, settings)).renderTo(document.getElementById('view')).reflow();
+       }
+
+       test("window x, y, w, h", function() {
+               var win = createWindow({x: 100, y: 120, width: 200, height: 210});
+
+               Utils.nearlyEqualRects(Utils.size(win), [200, 210]);
+       });
+
+       test("no title, no buttonbar, autoResize", function() {
+               var win = createWindow({
+                       x: 100,
+                       y: 120,
+                       items: [
+                               {type: 'spacer', classes: 'red'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.size(win), [22, 22]);
+               Utils.nearlyEqualRects(Utils.size(win.find("spacer")[0]), [20, 20]);
+       });
+
+       test("title, no buttonbar, autoResize, title is widest", function() {
+               var win = createWindow({
+                       x: 100,
+                       y: 120,
+                       title: "XXXXXXXXXXXXXXXXXXXXXX",
+                       items: [
+                               {type: 'spacer', classes: 'red', flex: 1}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.size(win), [326, 61], 60);
+               Utils.nearlyEqualRects(Utils.size(win.find("spacer")[0]), [324, 20], 60);
+       });
+
+       test("buttonbar, autoResize, buttonbar is widest", function() {
+               var win = createWindow({
+                       x: 100,
+                       y: 120,
+                       items: [
+                               {type: 'spacer', classes: 'red', flex: 1}
+                       ],
+                       buttons: [
+                               {type: 'spacer', classes: 'green', minWidth: 400}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.size(win), [422, 63]);
+               Utils.nearlyEqualRects(Utils.size(win.find("spacer")[0]), [420, 20]);
+               Utils.nearlyEqualRects(Utils.size(win.statusbar.find("spacer")[0]), [400, 20]);
+       });
+
+       test("buttonbar, title, autoResize, content is widest", function() {
+               var win = createWindow({
+                       x: 100,
+                       y: 120,
+                       title: "X",
+                       items: [
+                               {type: 'spacer', classes: 'red', minWidth: 400}
+                       ],
+                       buttons: [
+                               {type: 'spacer', classes: 'green'}
+                       ]
+               });
+
+               Utils.nearlyEqualRects(Utils.size(win), [402, 102]);
+               Utils.nearlyEqualRects(Utils.size(win.getEl("head")), [400, 39]);
+               Utils.nearlyEqualRects(Utils.size(win.find("spacer")[0]), [400, 20]);
+               Utils.nearlyEqualRects(Utils.size(win.statusbar.find("spacer")[0]), [20, 20]);
+       });
+})();
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/ui/Window.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceuitestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/ui/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/ui/tests.js     2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/ui/tests.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,55 +0,0 @@
</span><del>-{
-       "title": "tinymce.ui",
-       "tests": [
-               {"title": "AbsoluteLayout", "url": "AbsoluteLayout.html"},
-               {"title": "Button", "url": "Button.html"},
-               {"title": "ButtonGroup", "url": "ButtonGroup.html"},
-               {"title": "Checkbox", "url": "Checkbox.html"},
-               {"title": "Collection", "url": "Collection.html"},
-               {"title": "ColorButton", "url": "ColorButton.html"},
-               {"title": "ComboBox", "url": "ComboBox.html"},
-               {"title": "Container", "url": "Container.html"},
-               {"title": "Control", "url": "Control.html"},
-               {"title": "DragHelper", "url": "DragHelper.html"},
-               {"title": "ElementPath", "url": "ElementPath.html"},
-               {"title": "Factory", "url": "Factory.html"},
-               {"title": "FieldSet", "url": "FieldSet.html"},
-               {"title": "FilePicker", "url": "FilePicker.html"},
-               {"title": "FitLayout", "url": "FitLayout.html"},
-               {"title": "FlexLayout", "url": "FlexLayout.html"},
-               {"title": "FloatPanel", "url": "FloatPanel.html"},
-               {"title": "FlowLayout", "url": "FlowLayout.html"},
-               {"title": "Form", "url": "Form.html"},
-               {"title": "FormItem", "url": "FormItem.html"},
-               {"title": "GridLayout", "url": "GridLayout.html"},
-               {"title": "Iframe", "url": "Iframe.html"},
-               {"title": "KeyboardNavigation", "url": "KeyboardNavigation.html"},
-               {"title": "Label", "url": "Label.html"},
-               {"title": "Layout", "url": "Layout.html"},
-               {"title": "ListBox", "url": "ListBox.html"},
-               {"title": "Menu", "url": "Menu.html"},
-               {"title": "MenuBar", "url": "MenuBar.html"},
-               {"title": "MenuButton", "url": "MenuButton.html"},
-               {"title": "MenuItem", "url": "MenuItem.html"},
-               {"title": "MessageBox", "url": "MessageBox.html"},
-               {"title": "Movable", "url": "Movable.html"},
-               {"title": "Panel", "url": "Panel.html"},
-               {"title": "PanelButton", "url": "PanelButton.html"},
-               {"title": "Path", "url": "Path.html"},
-               {"title": "Radio", "url": "Radio.html"},
-               {"title": "Resizable", "url": "Resizable.html"},
-               {"title": "ResizeHandle", "url": "ResizeHandle.html"},
-               {"title": "Scrollable", "url": "Scrollable.html"},
-               {"title": "Selector", "url": "Selector.html"},
-               {"title": "Spacer", "url": "Spacer.html"},
-               {"title": "SplitButton", "url": "SplitButton.html"},
-               {"title": "StackLayout", "url": "StackLayout.html"},
-               {"title": "TabPanel", "url": "TabPanel.html"},
-               {"title": "TextBox", "url": "TextBox.html"},
-               {"title": "Throbber", "url": "Throbber.html"},
-               {"title": "Toolbar", "url": "Toolbar.html"},
-               {"title": "Tooltip", "url": "Tooltip.html"},
-               {"title": "Widget", "url": "Widget.html"},
-               {"title": "Window", "url": "Window.html"}
-       ]
-}
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilJSONhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/JSON.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/JSON.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/JSON.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,39 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>tinymce.util.JSON 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.util.JSON");
-
-QUnit.config.reorder = false;
-
-(function() {
-       var JSON = tinymce.util.JSON;
-
-       test('serialize', 2, function() {
-               equal(JSON.serialize({arr1 : [1, 2, 3, [1, 2, 3]], bool1 : true, float1: 3.14, int1 : 123, null1 : null, obj1 : {key1 : "val1", key2 : "val2"}, str1 : '\"\'abc\u00C5123\\'}), '{"arr1":[1,2,3,[1,2,3]],"bool1":true,"float1":3.14,"int1":123,"null1":null,"obj1":{"key1":"val1","key2":"val2"},"str1":"\\"\'abc\\u00c5123\\\\"}');
-
-               equal(JSON.serialize({arr1 : [1, 2, 3, [1, 2, 3]], bool1 : true, float1: 3.14, int1 : 123, null1 : null, obj1 : {key1 : "val1", key2 : "val2"}, str1 : '\"\'abc\u00C5123'}, "'"), "{'arr1':[1,2,3,[1,2,3]],'bool1':true,'float1':3.14,'int1':123,'null1':null,'obj1':{'key1':'val1','key2':'val2'},'str1':'\\\"\\'abc\\u00c5123'}");
-       });
-
-       test('parse', 1, function() {
-               equal(JSON.parse('{"arr1":[1,2,3,[1,2,3]],"bool1":true,"float1":3.14,"int1":123,"null1":null,"obj1":{"key1":"val1","key2":"val2"},"str1":"abc\\u00c5123"}').str1, 'abc\u00c5123');
-       });
-})();
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">tinymce.util.JSON 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilJSONjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/JSON.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/JSON.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/JSON.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+module("tinymce.util.JSON");
+
+test('serialize', 2, function() {
+       equal(
+               tinymce.util.JSON.serialize({
+                       arr1 : [1, 2, 3, [1, 2, 3]],
+                       bool1 : true,
+                       float1: 3.14,
+                       int1 : 123,
+                       null1 : null,
+                       obj1 : {key1 : "val1", key2 : "val2"}, str1 : '\"\'abc\u00C5123\\'}
+               ),
+               '{"arr1":[1,2,3,[1,2,3]],"bool1":true,"float1":3.14,"int1":123,"null1":null,"obj1":{"key1":"val1","key2":"val2"},"str1":"\\"\'abc\\u00c5123\\\\"}'
+       );
+
+       equal(
+               tinymce.util.JSON.serialize({
+                       arr1 : [1, 2, 3, [1, 2, 3]],
+                       bool1 : true,
+                       float1: 3.14,
+                       int1 : 123,
+                       null1 : null,
+                       obj1 : {key1 : "val1", key2 : "val2"}, str1 : '\"\'abc\u00C5123'}, "'"
+               ),
+               "{'arr1':[1,2,3,[1,2,3]],'bool1':true,'float1':3.14,'int1':123,'null1':null,'obj1':{'key1':'val1','key2':'val2'},'str1':'\\\"\\'abc\\u00c5123'}"
+       );
+});
+
+test('parse', 1, function() {
+       equal(tinymce.util.JSON.parse('{"arr1":[1,2,3,[1,2,3]],"bool1":true,"float1":3.14,"int1":123,"null1":null,"obj1":{"key1":"val1","key2":"val2"},"str1":"abc\\u00c5123"}').str1, 'abc\u00c5123');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/JSON.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutilJSONRequesthtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/JSONRequest.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/JSONRequest.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/JSONRequest.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,77 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>tinymce.util.JSONRequest 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.util.JSONRequest");
-
-QUnit.config.reorder = false;
-
-asyncTest("Successful request - send method", function() {
-       expect(1);
-
-       new tinymce.util.JSONRequest({}).send({
-               type : 'GET',
-               url : 'json_rpc_ok.js',
-               success: function(data) {
-                       equal(data, 'Hello JSON-RPC');
-                       start();
-               }
-       });
-});
-
-asyncTest("Successful request - sendRPC static method", function() {
-       expect(1);
-
-       tinymce.util.JSONRequest.sendRPC({
-               type : 'GET',
-               url : 'json_rpc_ok.js',
-               success: function(data) {
-                       equal(data, 'Hello JSON-RPC');
-                       start();
-               }
-       });
-});
-
-asyncTest("Error request - send method", function() {
-       expect(1);
-
-       new tinymce.util.JSONRequest({}).send({
-               type : 'GET',
-               url : 'json_rpc_error.js',
-               error: function(error) {
-                       equal(error.code, 42);
-                       start();
-               }
-       });
-});
-
-asyncTest("Error request - sendRPC static method", function() {
-       expect(1);
-
-       tinymce.util.JSONRequest.sendRPC({
-               type : 'GET',
-               url : 'json_rpc_error.js',
-               error: function(error) {
-                       equal(error.code, 42);
-                       start();
-               }
-       });
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">tinymce.util.JSONRequest 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilJSONRequestjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/JSONRequest.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/JSONRequest.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/JSONRequest.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+if (location.protocol != "file:") {
+       module("tinymce.util.JSONRequest");
+
+       asyncTest("Successful request - send method", function() {
+               expect(1);
+
+               new tinymce.util.JSONRequest({}).send({
+                       type : 'GET',
+                       url : 'tinymce/util/json_rpc_ok.js',
+                       success: function(data) {
+                               equal(data, 'Hello JSON-RPC');
+                               start();
+                       }
+               });
+       });
+
+       asyncTest("Successful request - sendRPC static method", function() {
+               expect(1);
+
+               tinymce.util.JSONRequest.sendRPC({
+                       type : 'GET',
+                       url : 'tinymce/util/json_rpc_ok.js',
+                       success: function(data) {
+                               equal(data, 'Hello JSON-RPC');
+                               start();
+                       }
+               });
+       });
+
+       asyncTest("Error request - send method", function() {
+               expect(1);
+
+               new tinymce.util.JSONRequest({}).send({
+                       type : 'GET',
+                       url : 'tinymce/util/json_rpc_error.js',
+                       error: function(error) {
+                               equal(error.code, 42);
+                               start();
+                       }
+               });
+       });
+
+       asyncTest("Error request - sendRPC static method", function() {
+               expect(1);
+
+               tinymce.util.JSONRequest.sendRPC({
+                       type : 'GET',
+                       url : 'tinymce/util/json_rpc_error.js',
+                       error: function(error) {
+                               equal(error.code, 42);
+                               start();
+                       }
+               });
+       });
+}
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/JSONRequest.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutilLocalStoragehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/LocalStorage.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/LocalStorage.html  2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/LocalStorage.html     2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,118 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>tinymce.util.LocalStorage 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 LocalStorage = tinymce.util.LocalStorage;
-
-module("tinymce.util.LocalStorage", {
-       setup: function() {
-               LocalStorage.clear();
-       },
-
-       teardown: function() {
-               LocalStorage.clear();
-       }
-});
-
-QUnit.config.reorder = false;
-
-test('setItem', function() {
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.getItem("a"), "1");
-       LocalStorage.setItem("a", "2");
-       equal(LocalStorage.getItem("a"), "2");
-       LocalStorage.setItem("a", 3);
-       equal(LocalStorage.getItem("a"), "3");
-       LocalStorage.setItem("a", null);
-       equal(LocalStorage.getItem("a"), "null");
-       LocalStorage.setItem("a", undefined);
-       equal(LocalStorage.getItem("a"), "undefined");
-       LocalStorage.setItem("a", new Date(0));
-       equal(LocalStorage.getItem("a"), new Date(0).toString());
-});
-
-test('getItem', function() {
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.getItem("a"), "1");
-       LocalStorage.setItem("a", "0");
-       equal(LocalStorage.getItem("a"), "0");
-       equal(LocalStorage.getItem("b"), null);
-});
-
-test('removeItem', function() {
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.getItem("a"), "1");
-       LocalStorage.removeItem("a");
-       equal(LocalStorage.getItem("a"), null);
-});
-
-test('key', function() {
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.key(0), "a");
-       equal(LocalStorage.length, 1);
-});
-
-test('length', function() {
-       equal(LocalStorage.length, 0);
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.length, 1);
-});
-
-test('clear', function() {
-       equal(LocalStorage.length, 0);
-       LocalStorage.setItem("a", "1");
-       equal(LocalStorage.length, 1);
-});
-
-test('setItem key and value with commas', function() {
-       LocalStorage.setItem("a,1", "1,2");
-       LocalStorage.setItem("b,2", "2,3");
-       equal(LocalStorage.getItem("a,1"), "1,2");
-       equal(LocalStorage.getItem("b,2"), "2,3");
-});
-
-test('setItem with two large values', function() {
-       var data = "";
-
-       for (var i = 0; i < 1024; i++) {
-               data += 'x';
-       }
-
-       LocalStorage.clear();
-       LocalStorage.setItem("a", data + "1");
-       LocalStorage.setItem("b", data);
-       equal(LocalStorage.getItem("a").length, 1024 + 1);
-       equal(LocalStorage.getItem("b").length, 1024);
-});
-
-test('setItem with two large keys', function() {
-       var key = "";
-
-       for (var i = 0; i < 1024; i++) {
-               key += 'x';
-       }
-
-       LocalStorage.clear();
-       LocalStorage.setItem(key + "1", "a");
-       LocalStorage.setItem(key + "2", "b");
-       equal(LocalStorage.key(0), key + "1");
-       equal(LocalStorage.key(1), key + "2");
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">tinymce.util.Cookie 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilLocalStoragejs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/LocalStorage.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/LocalStorage.js                            (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/LocalStorage.js       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,99 @@
</span><ins>+(function() {
+       var LocalStorage = tinymce.util.LocalStorage;
+
+       module("tinymce.util.LocalStorage", {
+               setup: function() {
+                       LocalStorage.clear();
+               },
+
+               teardown: function() {
+                       LocalStorage.clear();
+               }
+       });
+
+       QUnit.config.reorder = false;
+
+       test('setItem', function() {
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.getItem("a"), "1");
+               LocalStorage.setItem("a", "2");
+               equal(LocalStorage.getItem("a"), "2");
+               LocalStorage.setItem("a", 3);
+               equal(LocalStorage.getItem("a"), "3");
+               LocalStorage.setItem("a", null);
+               equal(LocalStorage.getItem("a"), "null");
+               LocalStorage.setItem("a", undefined);
+               equal(LocalStorage.getItem("a"), "undefined");
+               LocalStorage.setItem("a", new Date(0));
+               equal(LocalStorage.getItem("a"), new Date(0).toString());
+       });
+
+       test('getItem', function() {
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.getItem("a"), "1");
+               LocalStorage.setItem("a", "0");
+               equal(LocalStorage.getItem("a"), "0");
+               equal(LocalStorage.getItem("b"), null);
+       });
+
+       test('removeItem', function() {
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.getItem("a"), "1");
+               LocalStorage.removeItem("a");
+               equal(LocalStorage.getItem("a"), null);
+       });
+
+       test('key', function() {
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.key(0), "a");
+               equal(LocalStorage.length, 1);
+       });
+
+       test('length', function() {
+               equal(LocalStorage.length, 0);
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.length, 1);
+       });
+
+       test('clear', function() {
+               equal(LocalStorage.length, 0);
+               LocalStorage.setItem("a", "1");
+               equal(LocalStorage.length, 1);
+       });
+
+       test('setItem key and value with commas', function() {
+               LocalStorage.setItem("a,1", "1,2");
+               LocalStorage.setItem("b,2", "2,3");
+               equal(LocalStorage.getItem("a,1"), "1,2");
+               equal(LocalStorage.getItem("b,2"), "2,3");
+       });
+
+       test('setItem with two large values', function() {
+               var data = "";
+
+               for (var i = 0; i < 1024; i++) {
+                       data += 'x';
+               }
+
+               LocalStorage.clear();
+               LocalStorage.setItem("a", data + "1");
+               LocalStorage.setItem("b", data);
+               equal(LocalStorage.getItem("a").length, 1024 + 1);
+               equal(LocalStorage.getItem("b").length, 1024);
+       });
+
+       test('setItem with two large keys', function() {
+               var key = "";
+
+               for (var i = 0; i < 1024; i++) {
+                       key += 'x';
+               }
+
+               LocalStorage.clear();
+               LocalStorage.setItem(key + "1", "a");
+               LocalStorage.setItem(key + "2", "b");
+               equal(LocalStorage.key(0), key + "1");
+               equal(LocalStorage.key(1), key + "2");
+       });
+})();
+
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/LocalStorage.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutilQuirks_allhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_all.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_all.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_all.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,76 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>All browser types Quirks</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 src="../../js/dsl/dsl.js"></script>
-<script>
-var editor;
-
-QUnit.config.reorder = false;
-QUnit.config.autostart = false;
-
-var BACKSPACE = 0x08;
-
-module("Quirks Tests", {
-       autostart: false
-});
-
-// IE does the right thing
-if (!tinymce.isIE) {
-       test('Backspace when whole body contents is selected', function() {
-               editor.getBody().innerHTML = '<p><b>1</b></p><p><b>2</b></p>';
-               setSelection('p:first b', 0, 'p:last b', 1);
-               editor.dom.fire(editor.getBody(), 'keydown', {keyCode: BACKSPACE});
-               equal(editor.getContent(), '<p>&nbsp;</p>');
-       });
-}
-
-asyncTest('Backspace into <table> should be disabled', 1, function() {
-       var testContent = '<table class="mceItemTable" border="1"><tbody><tr><th><p>Table heading</p></th></tr><tr><td><p>Table contents</p></td></tr></tbody></table><h2 id="a">Paragraph Heading</h2>';
-       editor.setContent(testContent);
-       var initialContent = editor.getContent();
-       setSelection('#a', 0);
-       editor.focus();
-       robot.type(BACKSPACE, false, function() {
-               var expected = initialContent;
-               var actual = editor.getContent();
-               equal(actual, expected);
-               start();
-       }, editor.getBody());
-});
-
-function initTinyFunction() {
-       tinymce.init({
-               mode : "exact",
-               elements : "elm1",
-               init_instance_callback : function(ed) {
-                       editor = ed;
-               }
-       });
-}
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">All browser types Quirks</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilQuirks_firefoxhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_firefox.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_firefox.html        2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_firefox.html   2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,75 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Firefox Quirks</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>
-var editor;
-
-QUnit.config.reorder = false;
-QUnit.config.autostart = false;
-
-module("Quirks Tests", {
-       autostart: false
-});
-
-if (tinymce.isGecko) {
-       asyncTest('Remove hr between p with backspace', 1, function() {
-               setTimeout(function() {
-                       editor.setContent('<p>one</p><hr /><p id="a">two</p>');
-                       setSelection('#a', 0);
-                       editor.focus();
-                       robot.type(8, false, function() {
-                               var expected = '<p>one</p><p id="a">two</p>';
-                               var actual = editor.getContent({ format: 'raw' });
-                               equal(actual, expected);
-                               start();
-                       }, editor.getBody());
-               }, 100);
-       });
-
-       test('Add BR element at end of paragraphs with single link', function() {
-               editor.setContent('<p><b><a href="#">x</a></b></p>');
-               equal(editor.getBody().innerHTML, '<p><strong><a href="#" data-mce-href="#">x</a></strong><br data-mce-bogus="1"></p>');
-       });
-} else {
-       test('ignored', function() {
-               ok(true, "Tests ignored since the browser isn't Gecko.");
-       });
-}
-
-function initTinyFunction() {
-       tinymce.init({
-               mode : "exact",
-               elements : "elm1",
-               init_instance_callback : function(ed) {
-                       editor = ed;
-               }
-       });
-}
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">Firefox Quirks</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilQuirks_ie8html"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_ie8.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_ie8.html    2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_ie8.html       2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,82 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Internet Explorer 8 Quirks</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>
-var editor;
-
-QUnit.config.reorder = false;
-QUnit.config.autostart = false;
-
-module("Quirks Tests", {
-       autostart: false
-});
-
-if (tinymce.isIE) {
-       asyncTest('Remove hr between p with backspace', 1, function() {
-               setTimeout(function() {
-                       editor.setContent('<p>one</p><hr /><p>two</p>');
-                       setSelection('p:last', 0);
-                       editor.focus();
-                       robot.type(8, false, function() {
-                               var expected = '<p>one</p><p>two</p>';
-                               var actual = cleanHtml(editor.getContent({ format: 'raw' }));
-                               equal(actual, expected);
-                               start();
-                       }, editor.getBody());
-               }, 100);
-       });
-
-       asyncTest('Heading text alignment', 1, function() {
-               editor.setContent('<h1 id="x" style="text-align: center;">x</h1>');
-               setSelection('#x', 1);
-               editor.focus();
-               robot.type(0xA, false, function() {
-                       var expected = '<h1 id="x" style="text-align: center;">x</h1>\n<p>&nbsp;</p>';
-                       var actual = editor.getContent();
-                       equal(actual, expected);
-                       start();
-               }, editor.getBody());
-       });
-} else {
-       test('ignored', function() {
-               ok(true, "Tests ignored since the browser isn't IE8.");
-       });
-}
-
-var initTinyFunction = function() {
-       tinymce.init({
-               mode : "exact",
-               elements : "elm1",
-               init_instance_callback : function(ed) {
-                       editor = ed;
-               }
-       });
-}
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">Internet Explorer 8 Quirks</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilQuirks_removehtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_remove.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_remove.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_remove.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,270 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Removing content 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>
-var editor;
-
-QUnit.config.autostart = false;
-QUnit.config.reorder = false;
-
-module("Remove Content", {
-       autostart: false
-});
-
-asyncTest('Backspace with indented text', function() {
-       var c, originalContent = '<p>Line1</p>\n<p style="margin-left: 30px;">Line2</p>';
-
-       expect(2);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('p:nth-child(1)', 4, 'p:nth-child(2)', 4);
-       robot.type('\b', false, function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), "<p>Line2</p>", 'Delete content');
-                       editor.execCommand('undo', false, null);
-                       equal(editor.getContent(), originalContent, 'Undo deletion');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-// oncut is not supported by FireFox 2.0 so this is impossible to fix there.
-if (!tinymce.isGecko || !/Firefox\/[12].[0-9]/.test(navigator.userAgent)) {
-       asyncTest('Cut with indented text', function() {
-               var c, originalContent = '<p>Line1</p>\n<p style="margin-left: 30px;">Line2</p>';
-       
-               expect(3);
-       
-               editor.setContent(originalContent);
-               editor.focus();
-               setSelection('p:nth-child(1)', 4, 'p:nth-child(2)', 4);
-               robot.cut(function() {
-                       // The fix for this bug happens in a timeout after cut so we need to make sure that happens first by adding an additional delay.
-                       setTimeout(function() {
-                               equal(editor.getContent(), "<p>Line2</p>", 'Cut text');
-                               editor.execCommand('undo', false, null);
-                               equal(editor.getContent(), originalContent, 'Undo cut');
-                               editor.execCommand('SelectAll');
-                               robot.paste(function() {
-                                       ok(/Line/.test(editor.getContent()), 'Content should have been on clipboard. Got: ' + editor.getContent());
-                                       QUnit.start();
-                               }, editor.selection.getNode());
-                       }, 100);
-               }, editor.selection.getNode());
-       });
-} else {
-       test('Skipped on FireFox 2.x: Cut with indented text', function() {});
-}
-
-asyncTest('Forward delete with indented text', function() {
-       var c, originalContent = '<p>Line1</p>\n<p style="margin-left: 30px;">Line2</p>';
-
-       expect(2);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('p:nth-child(1)', 4, 'p:nth-child(2)', 4);
-       robot.forwardDelete(function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), "<p>Line2</p>", 'Delete content');
-                       editor.execCommand('undo', false, null);
-                       equal(editor.getContent(), originalContent, 'Undo deletion');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Forward delete with first paragraph indented', function() {
-       var c, originalContent = '<p style="margin-left: 30px;">Line1</p>\n<p>Line2</p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('p:nth-child(1)', 4, 'p:nth-child(2)', 4);
-       robot.forwardDelete(function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<p style="margin-left: 30px;">Line2</p>', 'Delete content');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Backward delete from paragraph to heading', function () {
-       var c, originalContent = '<h1>Heading</h1><p>text</p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('p', 0);
-       robot.type('\b', false, function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<h1>Headingtext</h1>', 'Delete content');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Forward delete from heading to paragraph', function () {
-       var c, originalContent = '<h1>Heading</h1><p>text</p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('h1', 7);
-       robot.forwardDelete(function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<h1>Headingtext</h1>', 'Delete content');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Forward delete from heading to paragraph with span', function () {
-       var c, originalContent = '<h1>Heading</h1><p><span style="color: #ff0000;">text</span></p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('h1', 7);
-       robot.forwardDelete(function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<h1>Heading<span style="color: #ff0000;">text</span></h1>', 'Delete content');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Backward delete from paragraph with span to heading', function () {
-       var c, originalContent = '<h1>Heading</h1><p><span style="color: #ff0000;">text</span></p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       setSelection('p', 0);
-       robot.type('\b', false, function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<h1>Heading<span style="color: #ff0000;">text</span></h1>', 'Delete content');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Backward delete all contents', function () {
-       var c, originalContent = '<h1>Heading</h1><p><span style="color: #ff0000;">text</span></p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       editor.execCommand('SelectAll');
-       robot.type('\b', false, function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<p>&nbsp;</p>', 'Empty contents');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Forward delete all contents', function () {
-       var c, originalContent = '<h1>Heading</h1><p><span style="color: #ff0000;">text</span></p>';
-
-       expect(1);
-
-       editor.setContent(originalContent);
-       editor.focus();
-       editor.execCommand('SelectAll');
-       robot.forwardDelete(function() {
-               // The content is fixed up after a small timeout to let the browser default behaviour kick in.
-               // As such we need to defer our checks as well.
-               setTimeout(function() {
-                       equal(editor.getContent(), '<p>&nbsp;</p>', 'Empty contents');
-                       QUnit.start();
-               }, 100);
-       }, editor.selection.getNode());
-});
-
-asyncTest('Backward delete blockquote contents', function () {
-       expect(1);
-
-       editor.setContent('<blockquote><p>some text here</p></blockquote>');
-       var textNode = editor.dom.select('p')[0].firstChild;
-       setSelection(textNode, 0, textNode, 5);
-       editor.focus();
-       robot.type('\b', false, function() {
-               equal(cleanHtml(editor.getContent()), '<blockquote><p>text here</p></blockquote>');
-               QUnit.start();
-       }, editor.selection.getNode());
-});
-
-asyncTest('Forward delete after empty paragraphs does not delete all content', function () {
-       expect(1);
-
-       editor.setContent('<p></p><p></p><p></p>');
-       setSelection('p:nth-child(3)', 0);
-       editor.focus();
-       robot.forwardDelete(function() {
-               QUnit.notEqual(editor.getContent(), '<p>&nbsp;</p>', 'Editor contents should not be empty');
-               QUnit.start();
-       }, editor.selection.getNode());
-});
-
-var initTinyFunction = function(){
-       tinymce.init({
-               mode : "exact",
-               elements : "elm1",
-               add_unload_trigger : 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'
-               },
-               init_instance_callback : function(ed) {
-                       editor = ed;
-               }
-       });
-};
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">Removing content 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>
-               initWhenTinyAndRobotAreReady(initTinyFunction);
-       </script>
-</body>
-</html>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilQuirks_webkithtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,135 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Webkit Quirks</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("WebKit Quirks Tests", {
-               autostart: false
-       });
-
-       if (tinymce.isWebKit) {
-               test('Delete from beginning of P into H1', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-                       setSelection('p', 0);
-                       editor.execCommand('Delete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('Delete whole H1 before P', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-
-                       rng = editor.selection.getRng();
-                       rng.setStartBefore(editor.getBody().firstChild);
-                       rng.setEndAfter(editor.getBody().firstChild);
-                       editor.selection.setRng(rng);
-
-                       editor.execCommand('Delete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>b<br></h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('Delete from beginning of P with style span inside into H1', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b<span style="color:red">c</span></p>';
-                       setSelection('p', 0);
-                       editor.execCommand('Delete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab<span data-mce-style="color:red" style="color:red">c</span></h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('ForwardDelete from end of H1 into P', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-                       setSelection('h1', 1);
-                       editor.execCommand('ForwardDelete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('ForwardDelete whole H1 before P', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-
-                       rng = editor.selection.getRng();
-                       rng.setStartBefore(editor.getBody().firstChild);
-                       rng.setEndAfter(editor.getBody().firstChild);
-                       editor.selection.setRng(rng);
-
-                       editor.execCommand('ForwardDelete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>b<br></h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('ForwardDelete from end of H1 into P with style span inside', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b<span style="color:red">c</span></p>';
-                       setSelection('h1', 1);
-                       editor.execCommand('ForwardDelete');
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab<span data-mce-style="color:red" style="color:red">c</span></h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('Backspace key from beginning of P into H1', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-                       setSelection('p', 0);
-                       editor.fire("keydown", {keyCode: 8});
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-
-               test('Delete key from end of H1 into P', function() {
-                       editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
-                       setSelection('h1', 1);
-                       editor.fire("keydown", {keyCode: 46});
-                       equal(cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
-                       equal(editor.selection.getStart().nodeName, 'H1');
-               });
-       } else {
-               test("Skipped since the browser isn't WebKit", function() {
-                       ok(true, "Skipped");
-               });
-       }
-
-       // WP
-       var url = document.location.href.substring( 0, document.location.href.lastIndexOf('tinymce/') );
-       
-       tinymce.init({
-               mode : "exact",
-               // WP
-               external_plugins: {
-                       table: url + 'external-plugins/table/plugin.js'
-               },
-               // WP end
-               elements : "elm1",
-               indent: false,
-               init_instance_callback : function(ed) {
-                       editor = ed;
-                       QUnit.start();
-               }
-       });
-</script>
-</head>
-<body>
-<h1 id="qunit-header">Webkit Quirks</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilQuirks_webkitjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js                           (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+module("tinymce.utils.Quirks_WebKit", {
+       setupModule: function() {
+               QUnit.stop();
+
+               tinymce.init({
+                       selector: "textarea",
+                       elements: "elm1",
+                       add_unload_trigger: false,
+                       skin: false,
+                       indent: false,
+                       disable_nodechange: true,
+                       init_instance_callback : function(ed) {
+                               window.editor = ed;
+                               QUnit.start();
+                       }
+               });
+       }
+});
+
+if (tinymce.isWebKit) {
+       test('Delete from beginning of P into H1', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+               Utils.setSelection('p', 0);
+               editor.execCommand('Delete');
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('Delete whole H1 before P', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+
+               var rng = editor.selection.getRng();
+               rng.setStartBefore(editor.getBody().firstChild);
+               rng.setEndAfter(editor.getBody().firstChild);
+               editor.selection.setRng(rng);
+
+               editor.execCommand('Delete');
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>b<br></h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('Delete from beginning of P with style span inside into H1', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b<span style="color:red">c</span></p>';
+               Utils.setSelection('p', 0);
+               editor.execCommand('Delete');
+               equal(Utils.normalizeHtml(Utils.cleanHtml(editor.getBody().innerHTML)), '<h1>ab<span data-mce-style="color:red" style="color: red;">c</span></h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('ForwardDelete from end of H1 into P', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+               Utils.setSelection('h1', 1);
+               editor.execCommand('ForwardDelete');
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('ForwardDelete whole H1 before P', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+
+               var rng = editor.selection.getRng();
+               rng.setStartBefore(editor.getBody().firstChild);
+               rng.setEndAfter(editor.getBody().firstChild);
+               editor.selection.setRng(rng);
+
+               editor.execCommand('ForwardDelete');
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>b<br></h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('ForwardDelete from end of H1 into P with style span inside', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b<span style="color:red">c</span></p>';
+               Utils.setSelection('h1', 1);
+               editor.execCommand('ForwardDelete');
+               equal(Utils.normalizeHtml(Utils.cleanHtml(editor.getBody().innerHTML)), '<h1>ab<span data-mce-style="color:red" style="color: red;">c</span></h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('Backspace key from beginning of P into H1', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+               Utils.setSelection('p', 0);
+               editor.fire("keydown", {keyCode: 8});
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+
+       test('Delete key from end of H1 into P', function() {
+               editor.getBody().innerHTML ='<h1>a</h1><p>b</p>';
+               Utils.setSelection('h1', 1);
+               editor.fire("keydown", {keyCode: 46});
+               equal(Utils.cleanHtml(editor.getBody().innerHTML), '<h1>ab</h1>');
+               equal(editor.selection.getStart().nodeName, 'H1');
+       });
+} else {
+       test("Skipped since the browser isn't WebKit", function() {
+               ok(true, "Skipped");
+       });
+}
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutilQuirks_webkit_jsrobothtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/Quirks_webkit_jsrobot.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/Quirks_webkit_jsrobot.html 2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/Quirks_webkit_jsrobot.html    2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,205 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>Webkit Quirks</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>
-       var editor;
-
-       QUnit.config.reorder = false;
-       QUnit.config.autostart = false;
-
-       module("Quirks Tests", {
-               autostart: false
-       });
-
-       var defaultTableContent =
-                       "<p id='p'>p</p>" +
-                                       "<table>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='b'>b</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "  <thead>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='a'>a</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </thead>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='c'>c</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  <tr>" +
-                                       "          <td>" +
-                                       "<p id='p'>p</p>" +
-                                       "<table>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='i'>i</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "  <thead>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='h'>h</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </thead>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='j'>j</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='k'>k</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "  <tfoot>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='m'>m</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tfoot>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='l'>l</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "</table>" +
-                                       "<p id='g'>g</p>" +
-                                       "</td>" +
-                                       "          <td id='d'>d</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "  <tfoot>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='f'>f</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tfoot>" +
-                                       "  <tbody>" +
-                                       "  <tr>" +
-                                       "          <td>z</td>" +
-                                       "          <td id='e'>e</td>" +
-                                       "          <td>z</td>" +
-                                       "  </tr>" +
-                                       "  </tbody>" +
-                                       "</table>" +
-                                       "<p id='g'>g</p>";
-
-       if (tinymce.isWebKit) {
-               asyncTest('tbody to tr', 1, function() {
-                       check('b', 40, 'c');
-               });
-               asyncTest('tr to tr', 1, function() {
-                       check('c', 40, 'd');
-               });
-               asyncTest('tr to tbody', 1, function() {
-                       check('d', 40, 'e');
-               });
-               asyncTest('tbody to tfoot', 1, function() {
-                       check('e', 40, 'f');
-               });
-               asyncTest('tfoot escaping down', 1, function() {
-                       check('f', 40, 'g');
-               });
-               asyncTest('thead to tbody', 1, function() {
-                       check('a', 40, 'b');
-               });
-               asyncTest('tfoot to tbody', 1, function() {
-                       check('f', 38, 'e');
-               });
-               asyncTest('tbody to thead', 1, function() {
-                       check('b', 38, 'a');
-               });
-               asyncTest('thead escaping up', 1, function() {
-                       check('a', 38, 'p');
-               });
-               asyncTest('nested tbody to tfoot', 1, function() {
-                       check('l', 40, 'm');
-               });
-               asyncTest('nested tfoot to tbody', 1, function() {
-                       check('m', 38, 'l');
-               });
-               asyncTest('nested tfoot to tbody', 1, function() {
-                       check('m', 38, 'l');
-               });
-               asyncTest('moving up around nested table', 1, function() {
-                       check('d', 38, 'c');
-               });
-       } else {
-               test("Skipped since the browser isn't WebKit", function() {
-                       ok(true, "Skipped");
-               });
-       }
-
-       function check(nodeId, keyStroke, expectedId) {
-               setSelection('#' + nodeId, 0);
-               editor.focus();
-               robot.type(keyStroke, false, getAssertFunction(expectedId), editor.getBody());
-       }
-
-       function getAssertFunction(expectedId) {
-               return function() {
-                       var actual = editor.selection.getNode().id;
-                       equal(actual, expectedId);
-                       start();
-               };
-       }
-
-       var initTinyFunction = function() {
-               tinymce.init({
-                       mode : "exact",
-                       plugins: 'table',
-                       elements : "elm1",
-                       indent: false,
-                       init_instance_callback : function(ed) {
-                               editor = ed;
-                               editor.setContent(defaultTableContent);
-                       }
-               });
-       }
-</script>
-</head>
-<body>
-<h1 id="qunit-header">Webkit Quirks</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilURIhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/URI.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/URI.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/URI.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,111 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>tinymce.util.URI 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.util.URI");
-
-QUnit.config.reorder = false;
-
-var URI = tinymce.util.URI;
-
-test('protocol relative url', function() {
-       var uri = new URI('//www.site.com/dir1/file?query#hash');
-
-       equal(uri.protocol, "");
-       equal(uri.host, "www.site.com");
-       equal(uri.path, "/dir1/file");
-       equal(uri.query, "query");
-       equal(uri.anchor, "hash");
-       equal(uri.source, "//www.site.com/dir1/file?query#hash");
-       equal(uri.getURI(), "//www.site.com/dir1/file?query#hash");
-       equal(uri.toRelative('//www.site.com/dir1/file2'), 'file2');
-       equal(uri.toRelative('//www.site2.com/dir1/file2'), '//www.site2.com/dir1/file2');
-       equal(uri.toAbsolute('../file2'), '//www.site.com/dir1/file2');
-       equal(uri.toAbsolute('//www.site2.com/dir1/file2'), '//www.site2.com/dir1/file2');
-});
-
-test('parseFullURLs', 3, function() {
-       equal(new URI('http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI(), 'http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
-       ok(new URI('http://a2bc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI() != 'http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
-       equal(new URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI(), 'chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
-});
-
-test('relativeURLs', 29, function() {
-       equal(new URI('http://www.site.com/dir1/dir2/file.html').toRelative('http://www.site.com/dir1/dir3/file.html'), '../dir3/file.html');
-       equal(new URI('http://www.site.com/dir1/dir2/file.html').toRelative('http://www.site.com/dir3/dir4/file.html'), '../../dir3/dir4/file.html');
-       equal(new URI('http://www.site.com/dir1/').toRelative('http://www.site.com/dir1/dir3/file.htm'), 'dir3/file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site2.com/dir1/dir3/file.htm'), 'http://www.site2.com/dir1/dir3/file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site.com:8080/dir1/dir3/file.htm'), 'http://www.site.com:8080/dir1/dir3/file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('https://www.site.com/dir1/dir3/file.htm'), 'https://www.site.com/dir1/dir3/file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('/file.htm'), '../../file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('/file.htm?id=1#a'), '../../file.htm?id=1#a');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('mailto:test@test.com'), 'mailto:test@test.com');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('news:test'), 'news:test');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('javascript:void(0);'), 'javascript:void(0);');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('about:blank'), 'about:blank');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('#test'), '#test');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('test.htm'), 'test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site.com/dir1/dir2/test.htm'), 'test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('dir2/test.htm'), 'dir2/test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('../dir2/test.htm'), 'test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('../dir3/'), '../dir3/');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('../../../../../../test.htm'), '../../test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('//www.site.com/test.htm'), '../../test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('@@tinymce'), '@@tinymce'); // Zope 3 URL
-       equal(new URI('http://www.site.com/dir1/dir2/').toRelative('../@@tinymce'), '../@@tinymce'); // Zope 3 URL
-       equal(new URI('http://www.site.com/').toRelative('dir2/test.htm'), 'dir2/test.htm');
-       equal(new URI('http://www.site.com/').toRelative('./'), './');
-       equal(new URI('http://www.site.com/test/').toRelative('../'), '../');
-       equal(new URI('http://www.site.com/test/test/').toRelative('../'), '../');
-       equal(new URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/').toRelative('/dir1', true), '../');
-       equal(new URI('http://www.site.com/').toRelative('http://www.site.com/'), 'http://www.site.com/');
-       equal(new URI('http://www.site.com/').toRelative('http://www.site.com'), 'http://www.site.com/');
-});
-
-test('absoluteURLs', 18, function() {
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('../dir3'), 'http://www.site.com/dir1/dir3');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('../dir3', 1), '/dir1/dir3');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('../../../../dir3'), 'http://www.site.com/dir3');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('../abc/def/../../abc/../dir3/file.htm'), 'http://www.site.com/dir1/dir3/file.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('http://www.site.com/dir2/dir3'), 'http://www.site.com/dir2/dir3');
-       equal(new URI('http://www.site2.com/dir1/dir2/').toAbsolute('http://www.site2.com/dir2/dir3'), 'http://www.site2.com/dir2/dir3');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('mailto:test@test.com'), 'mailto:test@test.com');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('news:test'), 'news:test');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('javascript:void(0);'), 'javascript:void(0);');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('about:blank'), 'about:blank');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('#test'), '#test');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('test.htm'), 'http://www.site.com/dir1/dir2/test.htm');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('../@@tinymce'), 'http://www.site.com/dir1/@@tinymce'); // Zope 3 URL
-       equal(new URI('http://www.site.com/dir1/dir2/').getURI(), 'http://www.site.com/dir1/dir2/');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('/dir1/dir1/'), 'http://www.site.com/dir1/dir1/');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('https://www.site.com/dir1/dir2/', true), 'https://www.site.com/dir1/dir2/');
-       equal(new URI('http://www.site.com/dir1/dir2/').toAbsolute('http://www.site.com/dir1/dir2/', true), '/dir1/dir2/');
-       equal(new URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/').toAbsolute('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/', true), '/dir1/dir2/');
-});
-
-test('strangeURLs', 6, function() {
-       equal(new URI('//www.site.com').getURI(), '//www.site.com');
-       equal(new URI('mailto:test@test.com').getURI(), 'mailto:test@test.com');
-       equal(new URI('news:somegroup').getURI(), 'news:somegroup');
-       equal(new URI('skype:somegroup').getURI(), 'skype:somegroup');
-       equal(new URI('tel:somegroup').getURI(), 'tel:somegroup');
-       equal(new URI('//www.site.com/a@b').getURI(), '//www.site.com/a@b');
-});
-</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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilURIjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/URI.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/URI.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/URI.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+module("tinymce.util.URI");
+
+test('protocol relative url', function() {
+       var uri = new tinymce.util.URI('//www.site.com/dir1/file?query#hash');
+
+       equal(uri.protocol, "");
+       equal(uri.host, "www.site.com");
+       equal(uri.path, "/dir1/file");
+       equal(uri.query, "query");
+       equal(uri.anchor, "hash");
+       equal(uri.source, "//www.site.com/dir1/file?query#hash");
+       equal(uri.getURI(), "//www.site.com/dir1/file?query#hash");
+       equal(uri.toRelative('//www.site.com/dir1/file2'), 'file2');
+       equal(uri.toRelative('//www.site2.com/dir1/file2'), '//www.site2.com/dir1/file2');
+       equal(uri.toAbsolute('../file2'), '//www.site.com/dir1/file2');
+       equal(uri.toAbsolute('//www.site2.com/dir1/file2'), '//www.site2.com/dir1/file2');
+});
+
+test('parseFullURLs', 3, function() {
+       equal(new tinymce.util.URI('http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI(), 'http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
+       ok(new tinymce.util.URI('http://a2bc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI() != 'http://abc:123@www.site.com:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
+       equal(new tinymce.util.URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890:8080/path/dir/file.ext?key1=val1&key2=val2#hash').getURI(), 'chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890:8080/path/dir/file.ext?key1=val1&key2=val2#hash');
+});
+
+test('relativeURLs', 29, function() {
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/file.html').toRelative('http://www.site.com/dir1/dir3/file.html'), '../dir3/file.html');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/file.html').toRelative('http://www.site.com/dir3/dir4/file.html'), '../../dir3/dir4/file.html');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/').toRelative('http://www.site.com/dir1/dir3/file.htm'), 'dir3/file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site2.com/dir1/dir3/file.htm'), 'http://www.site2.com/dir1/dir3/file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site.com:8080/dir1/dir3/file.htm'), 'http://www.site.com:8080/dir1/dir3/file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('https://www.site.com/dir1/dir3/file.htm'), 'https://www.site.com/dir1/dir3/file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('/file.htm'), '../../file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('/file.htm?id=1#a'), '../../file.htm?id=1#a');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('mailto:test@test.com'), 'mailto:test@test.com');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('news:test'), 'news:test');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('javascript:void(0);'), 'javascript:void(0);');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('about:blank'), 'about:blank');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('#test'), '#test');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('test.htm'), 'test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('http://www.site.com/dir1/dir2/test.htm'), 'test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('dir2/test.htm'), 'dir2/test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('../dir2/test.htm'), 'test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('../dir3/'), '../dir3/');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('../../../../../../test.htm'), '../../test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('//www.site.com/test.htm'), '../../test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('@@tinymce'), '@@tinymce'); // Zope 3 URL
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toRelative('../@@tinymce'), '../@@tinymce'); // Zope 3 URL
+       equal(new tinymce.util.URI('http://www.site.com/').toRelative('dir2/test.htm'), 'dir2/test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/').toRelative('./'), './');
+       equal(new tinymce.util.URI('http://www.site.com/test/').toRelative('../'), '../');
+       equal(new tinymce.util.URI('http://www.site.com/test/test/').toRelative('../'), '../');
+       equal(new tinymce.util.URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/').toRelative('/dir1', true), '../');
+       equal(new tinymce.util.URI('http://www.site.com/').toRelative('http://www.site.com/'), 'http://www.site.com/');
+       equal(new tinymce.util.URI('http://www.site.com/').toRelative('http://www.site.com'), 'http://www.site.com/');
+});
+
+test('absoluteURLs', 18, function() {
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('../dir3'), 'http://www.site.com/dir1/dir3');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('../dir3', 1), '/dir1/dir3');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('../../../../dir3'), 'http://www.site.com/dir3');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('../abc/def/../../abc/../dir3/file.htm'), 'http://www.site.com/dir1/dir3/file.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('http://www.site.com/dir2/dir3'), 'http://www.site.com/dir2/dir3');
+       equal(new tinymce.util.URI('http://www.site2.com/dir1/dir2/').toAbsolute('http://www.site2.com/dir2/dir3'), 'http://www.site2.com/dir2/dir3');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('mailto:test@test.com'), 'mailto:test@test.com');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('news:test'), 'news:test');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('javascript:void(0);'), 'javascript:void(0);');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('about:blank'), 'about:blank');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('#test'), '#test');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('test.htm'), 'http://www.site.com/dir1/dir2/test.htm');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('../@@tinymce'), 'http://www.site.com/dir1/@@tinymce'); // Zope 3 URL
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').getURI(), 'http://www.site.com/dir1/dir2/');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('/dir1/dir1/'), 'http://www.site.com/dir1/dir1/');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('https://www.site.com/dir1/dir2/', true), 'https://www.site.com/dir1/dir2/');
+       equal(new tinymce.util.URI('http://www.site.com/dir1/dir2/').toAbsolute('http://www.site.com/dir1/dir2/', true), '/dir1/dir2/');
+       equal(new tinymce.util.URI('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/').toAbsolute('chrome-extension://abcdefghijklmnopqrstuvwzyz1234567890/dir1/dir2/', true), '/dir1/dir2/');
+});
+
+test('strangeURLs', 6, function() {
+       equal(new tinymce.util.URI('//www.site.com').getURI(), '//www.site.com');
+       equal(new tinymce.util.URI('mailto:test@test.com').getURI(), 'mailto:test@test.com');
+       equal(new tinymce.util.URI('news:somegroup').getURI(), 'news:somegroup');
+       equal(new tinymce.util.URI('skype:somegroup').getURI(), 'skype:somegroup');
+       equal(new tinymce.util.URI('tel:somegroup').getURI(), 'tel:somegroup');
+       equal(new tinymce.util.URI('//www.site.com/a@b').getURI(), '//www.site.com/a@b');
+});
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/URI.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutilXHRhtml"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/XHR.html (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/XHR.html   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/XHR.html      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,53 +0,0 @@
</span><del>-<!DOCTYPE html>
-<html>
-<head>
-<title>tinymce.util.XHR 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.util.XHR");
-
-QUnit.config.reorder = false;
-
-asyncTest("Successful request", function() {
-       expect(3);
-
-       tinymce.util.XHR.send({
-               url : 'json_rpc_ok.js',
-               success: function(data, xhr, input) {
-                       equal(tinymce.trim(data), '{"result": "Hello JSON-RPC", "error": null, "id": 1}');
-                       ok(!!xhr.status);
-                       equal(input.url, 'json_rpc_ok.js');
-                       start();
-               }
-       });
-});
-
-asyncTest("Unsuccessful request", function() {
-       expect(3);
-
-       tinymce.util.XHR.send({
-               url : '404.js',
-               error: function(type, xhr, input) {
-                       equal(type, 'GENERAL');
-                       ok(!!xhr.status);
-                       equal(input.url, '404.js');
-                       start();
-               }
-       });
-});
-</script>
-</head>
-<body>
-       <h1 id="qunit-header">tinymce.util.XHR 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>
</del></span></pre></div>
<a id="trunktestsquniteditortinymceutilXHRjs"></a>
<div class="addfile"><h4>Added: trunk/tests/qunit/editor/tinymce/util/XHR.js (0 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/XHR.js                             (rev 0)
+++ trunk/tests/qunit/editor/tinymce/util/XHR.js        2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+if (location.protocol != "file:") {
+       module("tinymce.util.XHR");
+
+       asyncTest("Successful request", function() {
+               expect(3);
+
+               tinymce.util.XHR.send({
+                       url : 'tinymce/util/json_rpc_ok.js',
+                       success: function(data, xhr, input) {
+                               equal(tinymce.trim(data), '{"result": "Hello JSON-RPC", "error": null, "id": 1}');
+                               ok(!!xhr.status);
+                               equal(input.url, 'tinymce/util/json_rpc_ok.js');
+                               start();
+                       }
+               });
+       });
+
+       asyncTest("Unsuccessful request", function() {
+               expect(3);
+
+               tinymce.util.XHR.send({
+                       url : 'tinymce/util/404.js',
+                       error: function(type, xhr, input) {
+                               equal(type, 'GENERAL');
+                               ok(!!xhr.status);
+                               equal(input.url, 'tinymce/util/404.js');
+                               start();
+                       }
+               });
+       });
+}
</ins><span class="cx">Property changes on: trunk/tests/qunit/editor/tinymce/util/XHR.js
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<ins>+native
</ins><span class="cx">\ No newline at end of property
</span><a id="trunktestsquniteditortinymceutiltestsjs"></a>
<div class="delfile"><h4>Deleted: trunk/tests/qunit/editor/tinymce/util/tests.js (27678 => 27679)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/qunit/editor/tinymce/util/tests.js   2014-03-24 03:45:08 UTC (rev 27678)
+++ trunk/tests/qunit/editor/tinymce/util/tests.js      2014-03-24 05:59:45 UTC (rev 27679)
</span><span class="lines">@@ -1,16 +0,0 @@
</span><del>-{
-       "title": "tinymce.util",
-       "tests": [
-               {"title": "JSON", "url": "JSON.html"},
-               {"title": "JSONRequest", "url": "JSONRequest.html"},
-               {"title": "LocalStorage", "url": "LocalStorage.html"},
-               {"title": "URI", "url": "URI.html"},
-               {"title": "XHR", "url": "XHR.html"},
-               {"title": "All browser types", "url": "Quirks_all.html", "jsrobot": true},
-               {"title": "Quirks (Firefox)", "url": "Quirks_firefox.html", "jsrobot": true},
-               {"title": "Quirks (IE 8)", "url": "Quirks_ie8.html", "jsrobot": true},
-               {"title": "Quirks (Webkit)", "url": "Quirks_webkit.html"},
-               {"title": "Quirks JSRobot (Webkit)", "url": "Quirks_webkit_jsrobot.html", "jsrobot": true},
-               {"title": "Quirks (Remove)", "url": "Quirks_remove.html", "jsrobot": true}
-       ]
-}
</del></span></pre>
</div>
</div>

</body>
</html>