WordPress.org

Make WordPress Core

Changeset 40399


Ignore:
Timestamp:
04/09/2017 11:10:15 PM (14 months ago)
Author:
azaozz
Message:

TinyMCE: update the tests for version 4.5.6. Remove default plugins tests, it is quite pointless to keep repeating them at this point.

See #40305.

Location:
trunk/tests/qunit/editor
Files:
15 added
1 deleted
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/qunit/editor/index.html

    r38773 r40399  
    4141    <script src="tinymce/caret/LineWalker.js"></script>
    4242
     43    <!-- tinymce.content.* -->
     44    <script src="tinymce/content/LinkTargets.js"></script>
     45
    4346    <!-- tinymce.geom.* -->
    4447    <script src="tinymce/geom/Rect.js"></script>
     
    5255    <!-- tinymce.fmt.* -->
    5356    <script src="tinymce/fmt/Hooks.js"></script>
     57    <script src="tinymce/fmt/Preview.js"></script>
     58    <script src="tinymce/fmt/FontInfo.js"></script>
    5459
    5560    <!-- tinymce.text.* -->
     
    8792    <script src="tinymce/ui/ColorButton.js"></script>
    8893    <script src="tinymce/ui/Control.js"></script>
     94<!--<script src="tinymce/ui/FilePicker.js"></script>-->
    8995    <script src="tinymce/ui/FitLayout.js"></script>
    9096    <script src="tinymce/ui/FlexLayout.js"></script>
     
    97103    <script src="tinymce/ui/TextBox.js"></script>
    98104    <script src="tinymce/ui/Window.js"></script>
     105
     106    <!-- tinymce.undo.* -->
     107    <script src="tinymce/undo/Diff.js"></script>
     108    <script src="tinymce/undo/Fragments.js"></script>
     109    <script src="tinymce/undo/Levels.js"></script>
     110    <script src="tinymce/undo/ForcedRootBlock.js"></script>
    99111
    100112    <!-- tinymce.util.* -->
     
    116128    <!-- tinymce.* -->
    117129    <script src="tinymce/AddOnManager.js"></script>
     130    <script src="tinymce/options.js"></script>
    118131    <script src="tinymce/Editor.js"></script>
    119132    <script src="tinymce/Editor_rtl.js"></script>
     133    <script src="tinymce/EditorCustomTheme.js"></script>
    120134    <script src="tinymce/EditorUpload.js"></script>
    121135    <script src="tinymce/EditorCommands.js"></script>
    122136    <script src="tinymce/EditorManager.js"></script>
    123137    <script src="tinymce/EnterKey.js"></script>
     138    <script src="tinymce/FocusManager.js"></script>
    124139    <script src="tinymce/ForceBlocks.js"></script>
    125140    <script src="tinymce/Formatter_apply.js"></script>
     
    131146    <script src="tinymce/WindowManager.js"></script>
    132147    <script src="tinymce/InsertContent.js"></script>
     148    <script src="tinymce/InsertContentForcedRootFalse.js"></script>
    133149    <script src="tinymce/InsertList.js"></script>
     150    <script src="tinymce/NotificationManager.js"></script>
    134151
    135152    <!-- tinymce.plugins.* -->
    136 <!--<script src="plugins/autolink.js"></script>-->
    137     <script src="plugins/charmap.js"></script>
    138 <!--<script src="plugins/autosave.js"></script>-->
    139 <!--<script src="plugins/fullpage.js"></script>-->
    140     <script src="plugins/image.js"></script>
    141 <!--<script src="plugins/importcss.js"></script>-->
    142 <!--<script src="plugins/jquery_plugin.js"></script>-->
    143 <!--<script src="plugins/jquery_initialization.js"></script>-->
    144 <!--<script src="plugins/legacyoutput.js"></script>-->
    145 <!--<script src="plugins/link.js"></script>-->
    146     <script src="plugins/lists.js"></script>
    147     <script src="plugins/media.js"></script>
    148 <!--<script src="plugins/noneditable.js"></script> -->
    149     <script src="plugins/paste.js"></script>
    150     <script src="plugins/paste_images.js"></script>
    151     <script src="plugins/paste_smart.js"></script>
    152 <!--<script src="plugins/searchreplace.js"></script>-->
    153 <!--<script src="plugins/spellchecker.js"></script>-->
    154 <!--<script src="plugins/table.js"></script>-->
    155 <!--<script src="plugins/textpattern.js"></script>-->
    156 <!--<script src="plugins/wordcount.js"></script>-->
     153
    157154</body>
    158155</html>
  • trunk/tests/qunit/editor/js/init.js

    r29203 r40399  
    55    QUnit.config.hidepassed = true;
    66
    7     window.editor = window.inlineEditor = null; 
     7    window.editor = window.inlineEditor = null;
    88
    99    var oldModule = module;
     
    2424    // Sauce labs
    2525    QUnit.testStart(function(testDetails) {
    26         QUnit.log = function(details) {
     26        QUnit.log(function(details) {
    2727            if (!details.result) {
    2828                details.name = currentModule + ':' + testDetails.name;
    2929                log.push(details);
    3030            }
    31         };
     31        });
    3232    });
    3333
  • trunk/tests/qunit/editor/js/qunit/qunit.js

    r27679 r40399  
    570570if ( !defined.document || document.readyState === "complete" ) {
    571571    config.autorun = true;
     572}
     573
     574if (document.location.search.indexOf('bedrock') !== -1) {
     575    config.autorun = false;
     576    config.autostart = false;
    572577}
    573578
  • trunk/tests/qunit/editor/js/tinymce_loader.js

    r36352 r40399  
    55            'fullscreen wordpress wpautoresize wpeditimage wpgallery wplink wpdialogs wpview';
    66
     7var $ = window.jQuery;
     8
    79getUserSetting = setUserSetting = function() {}
  • trunk/tests/qunit/editor/tinymce/Editor.js

    r38773 r40399  
    493493});
    494494
     495test('Treat some paragraphs as empty contents', function() {
     496    editor.setContent('<p><br /></p>');
     497    equal(editor.getContent(), '');
     498
     499    editor.setContent('<p>\u00a0</p>');
     500    equal(editor.getContent(), '');
     501});
     502
    495503test('kamer word bounderies', function() {
    496504    editor.setContent('<p>!\u200b!\u200b!</p>');
    497505    equal(editor.getContent(), '<p>!\u200b!\u200b!</p>');
    498506});
     507
     508test('Padd empty elements with br', function() {
     509    editor.settings.padd_empty_with_br = true;
     510    editor.setContent('<p>a</p><p></p>');
     511    equal(editor.getContent(), '<p>a</p><p><br /></p>');
     512    delete editor.settings.padd_empty_with_br;
     513});
     514
     515test('Padd empty elements with br on insert at caret', function() {
     516    editor.settings.padd_empty_with_br = true;
     517    editor.setContent('<p>a</p>');
     518    Utils.setSelection('p', 1);
     519    editor.insertContent('<p>b</p><p></p>');
     520    equal(editor.getContent(), '<p>a</p><p>b</p><p><br /></p>');
     521    delete editor.settings.padd_empty_with_br;
     522});
     523
     524test('Preserve whitespace pre elements', function() {
     525    editor.setContent('<pre> </pre>');
     526    equal(editor.getContent(), '<pre> </pre>');
     527});
  • trunk/tests/qunit/editor/tinymce/EditorCommands.js

    r38034 r40399  
    751751});
    752752
     753test('unlink - unselected a[href] with childNodes', function() {
     754    editor.setContent('<p><a href="test"><strong><em>test</em></strong></a></p>');
     755    Utils.setSelection('em', 0);
     756    editor.execCommand('unlink');
     757    equal(editor.getContent(), '<p><strong><em>test</em></strong></p>');
     758});
     759
    753760test('subscript/superscript', function() {
    754761    expect(4);
     
    802809    editor.execCommand('Outdent');
    803810    equal(editor.getContent(), '<p>test 123</p>');
     811});
     812
     813test('indent/outdent table always uses margin', function () {
     814    expect(4);
     815
     816    editor.setContent('<table><tbody><tr><td>test</td></tr></tbody></table>');
     817    editor.execCommand('SelectAll');
     818    editor.execCommand('Indent');
     819    equal(editor.getContent(), '<table style="margin-left: 30px;"><tbody><tr><td>test</td></tr></tbody></table>');
     820
     821    editor.setContent('<table><tbody><tr><td>test</td></tr></tbody></table>');
     822    editor.execCommand('SelectAll');
     823    editor.execCommand('Indent');
     824    editor.execCommand('Indent');
     825    equal(editor.getContent(), '<table style="margin-left: 60px;"><tbody><tr><td>test</td></tr></tbody></table>');
     826
     827    editor.setContent('<table><tbody><tr><td>test</td></tr></tbody></table>');
     828    editor.execCommand('SelectAll');
     829    editor.execCommand('Indent');
     830    editor.execCommand('Indent');
     831    editor.execCommand('Outdent');
     832    equal(editor.getContent(), '<table style="margin-left: 30px;"><tbody><tr><td>test</td></tr></tbody></table>');
     833
     834    editor.setContent('<table><tbody><tr><td>test</td></tr></tbody></table>');
     835    editor.execCommand('SelectAll');
     836    editor.execCommand('Outdent');
     837    equal(editor.getContent(), '<table><tbody><tr><td>test</td></tr></tbody></table>');
    804838});
    805839
     
    827861    equal(editor.getContent(), '<p>dfn tag code tag samp tag kbd tag var tag cite tag mark tag q tag</p>');
    828862});
     863
     864if (tinymce.Env.ceFalse) {
     865    test('SelectAll', function() {
     866        editor.setContent('<p>a</p><div contenteditable="false"><div contenteditable="true">b</div><p>c</p>');
     867        Utils.setSelection('div div', 0);
     868        editor.execCommand('SelectAll');
     869        equal(editor.selection.getStart().nodeName, 'DIV');
     870        equal(editor.selection.getEnd().nodeName, 'DIV');
     871        equal(editor.selection.isCollapsed(), false);
     872    });
     873}
    829874
    830875test('InsertLineBreak', function() {
  • trunk/tests/qunit/editor/tinymce/EditorManager.js

    r38034 r40399  
    9999
    100100asyncTest('Init editor async with proper editors state', function() {
    101     var unloadTheme = function(name) {
    102         var url = tinymce.baseURI.toAbsolute('themes/' + name + '/theme.js');
     101    var unloadUrl = function (url) {
    103102        tinymce.dom.ScriptLoader.ScriptLoader.remove(url);
    104103        tinymce.ThemeManager.remove(name);
     104    };
     105
     106    var unloadTheme = function(name) {
     107        unloadUrl(tinymce.baseURI.toAbsolute('themes/' + name + '/theme.min.js'));
     108        unloadUrl(tinymce.baseURI.toAbsolute('themes/' + name + '/theme.js'));
    105109    };
    106110
     
    142146            "plugina": "//domain/plugina.js",
    143147            "pluginb": "//domain/pluginb.js"
     148        },
     149        plugin_base_urls: {
     150            testplugin: 'http://custom.ephox.com/dir/testplugin'
    144151        }
    145152    });
     
    149156    strictEqual(tinymce.suffix, "x");
    150157    strictEqual(new tinymce.Editor('ed1', {}, tinymce).settings.test, 42);
     158    strictEqual(tinymce.PluginManager.urls.testplugin, 'http://custom.ephox.com/dir/testplugin');
    151159
    152160    deepEqual(new tinymce.Editor('ed2', {
     
    154162            "plugina": "//domain/plugina2.js",
    155163            "pluginc": "//domain/pluginc.js"
     164        },
     165        plugin_base_urls: {
     166            testplugin: 'http://custom.ephox.com/dir/testplugin'
    156167        }
    157168    }, tinymce).settings.external_plugins, {
  • trunk/tests/qunit/editor/tinymce/EditorUpload.js

    r38034 r40399  
    236236            if (callCount == 2) {
    237237                QUnit.start();
    238                 equal(uploadCount, 1, 'Should only be one upload.');
     238                // This is in exact since the status of the image can be pending or failed meaing it should try again
     239                ok(uploadCount >= 1, 'Should at least be one.');
    239240            }
    240241
  • trunk/tests/qunit/editor/tinymce/EnterKey.js

    r37000 r40399  
    10991099    });
    11001100}
     1101
     1102if (tinymce.Env.ceFalse) {
     1103    test('Enter before cE=false div', function() {
     1104        editor.getBody().innerHTML = '<div contenteditable="false">x</div>';
     1105        editor.selection.select(editor.dom.select('div')[0]);
     1106        editor.selection.collapse(true);
     1107        Utils.pressEnter();
     1108        equal(Utils.cleanHtml(editor.getBody().innerHTML), '<p><br data-mce-bogus="1"></p><div contenteditable="false">x</div>');
     1109        equal(editor.selection.getNode().nodeName, 'P');
     1110    });
     1111
     1112    test('Enter after cE=false div', function() {
     1113        editor.getBody().innerHTML = '<div contenteditable="false">x</div>';
     1114        editor.selection.select(editor.dom.select('div')[0]);
     1115        editor.selection.collapse(false);
     1116        Utils.pressEnter();
     1117        equal(Utils.cleanHtml(editor.getBody().innerHTML), '<div contenteditable="false">x</div><p><br data-mce-bogus="1"></p>');
     1118        equal(editor.selection.getNode().nodeName, 'P');
     1119    });
     1120}
     1121
  • trunk/tests/qunit/editor/tinymce/Formatter_apply.js

    r38773 r40399  
    11module("tinymce.Formatter - Apply", {
    22    setupModule: function() {
    3         document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div>';
     3        document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea><div id="elm2"></div><textarea id="elm3"></textarea>';
    44        QUnit.stop();
    55
     
    1919            },
    2020            init_instance_callback: function(ed) {
     21                QUnit.start();
    2122                window.editor = ed;
    22 
    23                 if (inlineEditor) {
    24                     QUnit.start();
    25                 }
    26             }
    27         });
    28 
    29         tinymce.init({
    30             selector: "#elm2",
    31             inline: true,
    32             add_unload_trigger: false,
    33             skin: false,
    34             indent: false,
    35             convert_fonts_to_spans: false,
    36             disable_nodechange: true,
    37             entities: 'raw',
    38             valid_styles: {
    39                 '*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display,text-align'
    40             },
    41             init_instance_callback: function(ed) {
    42                 window.inlineEditor = ed;
    43 
    44                 if (editor) {
    45                     QUnit.start();
    46                 }
    4723            }
    4824        });
     
    12901266    editor.formatter.apply('format');
    12911267    equal(editor.getContent(), '<p><b>abc</b></p>');
     1268});
     1269
     1270test('Caret format inside non-ascii single block word', function() {
     1271    editor.setContent('<p>noël</p>');
     1272    editor.formatter.register('format', {
     1273        inline: 'b'
     1274    });
     1275    Utils.setSelection('p', 2, 'p', 2);
     1276    editor.formatter.apply('format');
     1277    equal(editor.getContent(), '<p><b>noël</b></p>');
    12921278});
    12931279
     
    16801666});
    16811667
    1682 test('Bug #6518 - Apply div blocks to inline editor paragraph', function() {
    1683     inlineEditor.setContent('<p>a</p><p>b</p>');
    1684     inlineEditor.selection.select(inlineEditor.getBody().firstChild, true);
    1685     inlineEditor.selection.collapse(true);
    1686     inlineEditor.formatter.register('format', {
    1687         block: 'div'
    1688     });
    1689     inlineEditor.formatter.apply('format');
    1690     equal(inlineEditor.getContent(), '<div>a</div><p>b</p>');
     1668asyncTest('Bug #6518 - Apply div blocks to inline editor paragraph', function() {
     1669    tinymce.init({
     1670        selector: "#elm2",
     1671        inline: true,
     1672        add_unload_trigger: false,
     1673        skin: false,
     1674        indent: false,
     1675        convert_fonts_to_spans: false,
     1676        disable_nodechange: true,
     1677        entities: 'raw',
     1678        valid_styles: {
     1679            '*': 'color,font-size,font-family,background-color,font-weight,font-style,text-decoration,float,margin,margin-top,margin-right,margin-bottom,margin-left,display,text-align'
     1680        },
     1681        init_instance_callback: function(ed) {
     1682            QUnit.start();
     1683
     1684            ed.setContent('<p>a</p><p>b</p>');
     1685            ed.selection.select(ed.getBody().firstChild, true);
     1686            ed.selection.collapse(true);
     1687            ed.formatter.register('format', {
     1688                block: 'div'
     1689            });
     1690            ed.formatter.apply('format');
     1691            equal(ed.getContent(), '<div>a</div><p>b</p>');
     1692        }
     1693    });
    16911694});
    16921695
    16931696asyncTest('Bug #7412 - valid_styles affects the Bold and Italic buttons, although it shouldn\'t', function() {
    1694     tinymce.remove();
    1695 
    1696     document.getElementById('view').innerHTML = '<textarea id="elm1"></textarea>';
    1697 
    16981697    tinymce.init({
    1699         selector: "#elm1",
     1698        selector: "#elm3",
    17001699        add_unload_trigger: false,
    17011700        valid_styles: {
     
    17031702        },
    17041703        init_instance_callback: function(ed) {
    1705             window.editor = ed;
    17061704            QUnit.start();
    17071705
    1708             editor.getBody().innerHTML = '<p>1 <span style="text-decoration: underline;">1234</span> 1</p>';
    1709             var rng = editor.dom.createRng();
    1710             rng.setStart(editor.dom.select('span')[0], 0);
    1711             rng.setEnd(editor.dom.select('span')[0], 1);
    1712             editor.selection.setRng(rng);
    1713             editor.formatter.toggle('bold');
    1714             equal(getContent(), '<p>1 <strong><span style="text-decoration: underline;">1234</span></strong> 1</p>');
     1706            ed.getBody().innerHTML = '<p>1 <span style="text-decoration: underline;">1234</span> 1</p>';
     1707            var rng = ed.dom.createRng();
     1708            rng.setStart(ed.dom.select('span')[0], 0);
     1709            rng.setEnd(ed.dom.select('span')[0], 1);
     1710            ed.selection.setRng(rng);
     1711            ed.formatter.toggle('bold');
     1712            equal(ed.getContent(), '<p>1 <strong><span style="text-decoration: underline;">1234</span></strong> 1</p>');
    17151713        }
    17161714    });
     
    17221720    Utils.setSelection('#a', 0, '#b', 0);
    17231721    editor.execCommand('formatBlock', false, 'h1');
    1724     equal(getContent(), '<h1 id="a">one</h1>\n<div id="b">two</div>');
     1722    equal(getContent(), '<h1 id="a">one</h1><div id="b">two</div>');
    17251723});
    17261724
    17271725test('Format selection over fragments', function(){
    1728     editor.setContent("<strong>a</strong>bc<em>d</em>");
     1726    editor.setContent("<p><strong>a</strong>bc<em>d</em></p>");
    17291727    Utils.setSelection('strong', 1, 'em', 0);
    17301728    editor.formatter.apply('underline');
    17311729    equal(getContent(), '<p><strong>a</strong><span style="text-decoration: underline;">bc</span><em>d</em></p>');
    17321730});
     1731
     1732test("Wrapper with fontSize should retain priority within a branch of nested inline format wrappers", function() {
     1733    editor.setContent("<p>abc</p>");
     1734    Utils.setSelection('p', 0, 'p', 3);
     1735
     1736    editor.formatter.apply('fontsize', {value: '18px'});
     1737    editor.formatter.apply('bold');
     1738    editor.formatter.apply('underline');
     1739    editor.formatter.apply('forecolor', {value: '#ff0000'});
     1740
     1741    equal(getContent(), '<p><span style="color: #ff0000; font-size: 18px; text-decoration: underline;"><strong>abc</strong></span></p>');
     1742});
     1743
     1744test("Child wrapper having the same format as the immediate parent, shouldn't be removed if it also has other formats merged", function() {
     1745    editor.getBody().innerHTML = '<p><span style="font-family: verdana;">a <span style="color: #ff0000;">b</span>c</span></p>';
     1746    Utils.setSelection('span span', 0, 'span span', 1);
     1747    editor.formatter.apply('fontname', {value: "verdana"});
     1748    equal(getContent(), '<p><span style="font-family: verdana;">a <span style="color: #ff0000;">b</span>c</span></p>');
     1749});
     1750
     1751test("When format with backgroundColor is applied, all the nested childNodes having fontSize should receive backgroundColor as well", function() {
     1752    editor.getBody().innerHTML = '<p>a <span style="font-size: 36pt;">b</span> c</p>';
     1753    editor.selection.select(editor.dom.select('p')[0]);
     1754
     1755    editor.formatter.apply('hilitecolor', {value: "#ff0000"});
     1756    equal(getContent(), '<p><span style="background-color: #ff0000;">a <span style="font-size: 36pt; background-color: #ff0000;">b</span> c</span></p>');
     1757
     1758    editor.formatter.remove('hilitecolor', {value: "#ff0000"});
     1759    equal(getContent(), '<p>a <span style="font-size: 36pt;">b</span> c</p>');
     1760});
     1761
     1762test("TINY-782: Can't apply sub/sup to word on own line with large font", function() {
     1763    editor.getBody().innerHTML = '<p><span style="font-size: 18px;">abc</p>';
     1764    Utils.setSelection('span', 0, 'span', 3);
     1765    editor.formatter.apply('superscript');
     1766    equal(getContent(), '<p><span style="font-size: 18px;"><sup>abc</sup></span></p>');
     1767});
     1768
     1769test("TINY-671: Background color on nested font size bug", function() {
     1770    editor.getBody().innerHTML = '<p><strong><span style="font-size: 18px;">abc</span></strong></p>';
     1771    Utils.setSelection('span', 0, 'span', 3);
     1772    editor.formatter.apply('hilitecolor', {value: '#ff0000'});
     1773    equal(getContent(), '<p><span style="font-size: 18px; background-color: #ff0000;"><strong>abc</strong></span></p>');
     1774});
     1775
     1776test("TINY-865: Font size removed when changing background color", function() {
     1777    editor.getBody().innerHTML = '<p><span style="background-color: #ffff00;"><span style="font-size: 8pt;">a</span> <span style="font-size: 36pt;">b</span> <span style="font-size: 8pt;">c</span></span></p>';
     1778    Utils.setSelection('span span:nth-child(2)', 0, 'span span:nth-child(2)', 1);
     1779    editor.formatter.apply('hilitecolor', {value: '#ff0000'});
     1780    equal(getContent(), '<p><span style="background-color: #ffff00;"><span style="font-size: 8pt;">a</span> <span style="font-size: 36pt; background-color: #ff0000;">b</span> <span style="font-size: 8pt;">c</span></span></p>');
     1781});
     1782
     1783test("TINY-935: Text color, then size, then change color wraps span doesn't change color", function() {
     1784    editor.getBody().innerHTML = '<p><span style="color: #00ff00; font-size: 14pt;">text</span></p>';
     1785    Utils.setSelection('span', 0, 'span', 4);
     1786    editor.formatter.apply('forecolor', {value: '#ff0000'});
     1787    equal(getContent(), '<p><span style="color: #ff0000; font-size: 14pt;">text</span></p>');
     1788});
     1789
     1790test("GH-3519: Font family selection does not work after changing font size", function() {
     1791    editor.getBody().innerHTML = '<p><span style="font-size: 14pt; font-family: \'comic sans ms\', sans-serif;">text</span></p>';
     1792    Utils.setSelection('span', 0, 'span', 4);
     1793    editor.formatter.apply('fontname', {value: "verdana"});
     1794    equal(getContent(), '<p><span style="font-size: 14pt; font-family: verdana;">text</span></p>');
     1795});
  • trunk/tests/qunit/editor/tinymce/Formatter_check.js

    r36352 r40399  
    229229    ok(!inlineEditor.formatter.match('div'), 'Formatter.match on div says true');
    230230});
    231 
    232 test('Get preview css text for formats', function() {
    233     ok(/font-weight\:(bold|700)/.test(editor.formatter.getCssText('bold')), 'Bold not found in preview style');
    234     ok(/font-weight\:(bold|700)/.test(editor.formatter.getCssText({inline: 'b'})), 'Bold not found in preview style');
    235 });
  • trunk/tests/qunit/editor/tinymce/SelectionOverrides.js

    r38773 r40399  
    4848    function assertCaretInCaretBlockContainer() {
    4949        var beforeRng = editor.selection.getRng();
    50         equal(CaretContainer.isCaretContainerBlock(beforeRng.startContainer.parentNode), true, 'Not in caret block container.');
     50        equal(CaretContainer.isCaretContainerBlock(beforeRng.startContainer), true, 'Not in caret block container.');
    5151    }
    5252
     
    225225        equal(editor.getContent(), '<p contenteditable="false">1</p><p contenteditable="false">2</p>');
    226226        assertCaretInCaretBlockContainer();
    227         equal(rng.startContainer.parentNode.previousSibling, editor.dom.select('p')[0]);
     227        equal(rng.startContainer.previousSibling, editor.dom.select('p')[0]);
    228228    });
    229229
     
    264264        equal(editor.getContent(), '<p contenteditable="false">1</p><p contenteditable="false">2</p>');
    265265        assertCaretInCaretBlockContainer();
    266         equal(rng.startContainer.parentNode.nextSibling, editor.dom.select('p')[2]);
     266        equal(rng.startContainer.nextSibling, editor.dom.select('p')[2]);
    267267    });
    268268
     
    329329        equal(editor.selection.getNode().nodeName !== 'P', true);
    330330    });
     331
     332    test('offscreen copy of cE=false block remains offscreen', function() {
     333        if (tinymce.isIE || tinymce.isGecko || tinymce.isOpera) {
     334            editor.setContent(
     335                '<table contenteditable="false" style="width: 100%; table-layout: fixed">' +
     336                '<tbody><tr><td>1</td><td>2</td></tr></tbody>' +
     337                '</table>'
     338            );
     339
     340            editor.selection.select(editor.dom.select('table')[0]);
     341            var offscreenSelection = editor.dom.select('.mce-offscreen-selection')[0];
     342
     343            ok(offscreenSelection.offsetLeft !== undefined, 'The offscreen selection\'s left border is undefined');
     344            ok(offscreenSelection.offsetLeft < 0, 'The offscreen selection\'s left border is onscreen');
     345            ok(offscreenSelection.offsetWidth + offscreenSelection.offsetLeft < 0,
     346                'The cE=false offscreen selection is visible on-screen. Right edge: ' +
     347                offscreenSelection.offsetLeft + '+' + offscreenSelection.offsetWidth + '=' +
     348                (offscreenSelection.offsetLeft + offscreenSelection.offsetWidth) + 'px'
     349            );
     350        } else {
     351            // Chrome and Safari behave correctly, and PhantomJS also declares itself as WebKit but does not
     352            // put the off-screen selection off-screen, so fails the above tests. However, it has no visible UI,
     353            // so everything is off-screen anyway :-)
     354            ok(true, 'Not a tested browser - Chrome & Safari work, PhantomJS does not put the selection off screen');
     355        }
     356    });
    331357});
  • trunk/tests/qunit/editor/tinymce/UndoManager.js

    r38773 r40399  
    9797    ok(editor.undoManager.typing);
    9898
    99     editor.dom.fire(editor.getBody(), 'keyup', {keyCode: 13});
     99    editor.dom.fire(editor.getBody(), 'keydown', {keyCode: 13});
    100100    ok(!editor.undoManager.typing);
    101101
     
    452452    ok(editor.isDirty(), "Dirty state should be true");
    453453});
     454
     455test('ExecCommand while typing should produce undo level', function() {
     456    editor.undoManager.clear();
     457    editor.setDirty(false);
     458    editor.setContent('<p>a</p>');
     459    Utils.setSelection('p', 1);
     460
     461    equal(editor.undoManager.typing, false);
     462    Utils.type({keyCode: 66, charCode: 66});
     463    equal(editor.undoManager.typing, true);
     464    equal(editor.getContent(), '<p>aB</p>');
     465    editor.execCommand('mceInsertContent', false, 'C');
     466    equal(editor.undoManager.typing, false);
     467    equal(editor.undoManager.data.length, 3);
     468    equal(editor.undoManager.data[0].content, '<p>a</p>');
     469    equal(editor.undoManager.data[1].content, '<p>aB</p>');
     470    equal(editor.undoManager.data[2].content, '<p>aBC</p>');
     471});
     472
     473test('transact while typing should produce undo level', function() {
     474    editor.undoManager.clear();
     475    editor.setDirty(false);
     476    editor.setContent('<p>a</p>');
     477    Utils.setSelection('p', 1);
     478
     479    equal(editor.undoManager.typing, false);
     480    Utils.type({keyCode: 66, charCode: 66});
     481    equal(editor.undoManager.typing, true);
     482    equal(editor.getContent(), '<p>aB</p>');
     483    editor.undoManager.transact(function () {
     484        editor.getBody().firstChild.firstChild.data = 'aBC';
     485    });
     486    equal(editor.undoManager.typing, false);
     487    equal(editor.undoManager.data.length, 3);
     488    equal(editor.undoManager.data[0].content, '<p>a</p>');
     489    equal(editor.undoManager.data[1].content, '<p>aB</p>');
     490    equal(editor.undoManager.data[2].content, '<p>aBC</p>');
     491});
  • trunk/tests/qunit/editor/tinymce/caret/CaretContainer.js

    r38773 r40399  
    119119        equal(CaretContainer.endsWithCaretContainer(getRoot().firstChild), true);
    120120    });
     121
     122    test('hasContent', function() {
     123        setViewHtml('<span contentEditable="false">1</span>');
     124        var caretContainerBlock = CaretContainer.insertBlock('p', getRoot().firstChild, true);
     125        equal(CaretContainer.hasContent(caretContainerBlock), false);
     126        caretContainerBlock.insertBefore(document.createTextNode('a'), caretContainerBlock.firstChild);
     127        equal(CaretContainer.hasContent(caretContainerBlock), true);
     128    });
     129
     130    test('showCaretContainerBlock', function() {
     131        setViewHtml('<span contentEditable="false">1</span>');
     132        var caretContainerBlock = CaretContainer.insertBlock('p', getRoot().firstChild, true);
     133        caretContainerBlock.insertBefore(document.createTextNode('a'), caretContainerBlock.firstChild);
     134        CaretContainer.showCaretContainerBlock(caretContainerBlock);
     135        equal(caretContainerBlock.outerHTML, '<p>a</p>');
     136    });
    121137});
  • trunk/tests/qunit/editor/tinymce/caret/FakeCaret.js

    r36352 r40399  
    3535        equal($fakeCaretElm[0].nodeName, 'P');
    3636        equal($fakeCaretElm.attr('data-mce-caret'), 'before');
    37         Utils.assertRange(rng, Utils.createRange($fakeCaretElm[0].firstChild, 0, $fakeCaretElm[0].firstChild, 1));
     37        Utils.assertRange(rng, Utils.createRange($fakeCaretElm[0], 0, $fakeCaretElm[0], 0));
    3838
    3939        fakeCaret.hide();
     
    5151        equal($fakeCaretElm[1].nodeName, 'P');
    5252        equal($fakeCaretElm.eq(1).attr('data-mce-caret'), 'after');
    53         Utils.assertRange(rng, Utils.createRange($fakeCaretElm[1].firstChild, 0, $fakeCaretElm[1].firstChild, 1));
     53        Utils.assertRange(rng, Utils.createRange($fakeCaretElm[1], 0, $fakeCaretElm[1], 0));
    5454
    5555        fakeCaret.hide();
  • trunk/tests/qunit/editor/tinymce/dom/DOMUtils.js

    r29994 r40399  
    3636            'border: 1pt none black;'
    3737        );
    38        
     38
    3939        equal(
    4040            dom.serializeStyle(dom.parseStyle('border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;')),
     
    340340    });
    341341
     342    var eqNodeName = function(name) {
     343        return function (n) {
     344            return n.nodeName === name;
     345        };
     346    };
     347
    342348    test('getParent', 6, function() {
    343349        DOM.add(document.body, 'div', {id : 'test'});
     
    345351        DOM.get('test').innerHTML = '<div><span>ab<a id="test2" href="">abc</a>c</span></div>';
    346352
    347         equal(DOM.getParent('test2', function(n) {return n.nodeName == 'SPAN';}).nodeName, 'SPAN');
    348         equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}).nodeName, 'BODY');
    349         equal(DOM.getParent('test2', function(n) {return n.nodeName == 'BODY';}, document.body), null);
    350         equal(DOM.getParent('test2', function() {return false;}), null);
     353        equal(DOM.getParent('test2', eqNodeName('SPAN')).nodeName, 'SPAN');
     354        equal(DOM.getParent('test2', eqNodeName('BODY')).nodeName, 'BODY');
     355        equal(DOM.getParent('test2', eqNodeName('BODY'), document.body), null);
     356        equal(DOM.getParent('test2', eqNodeName('X')), null);
    351357        equal(DOM.getParent('test2', 'SPAN').nodeName, 'SPAN');
    352358        equal(DOM.getParent('test2', 'body', DOM.get('test')), null);
     
    361367        DOM.get('test').innerHTML = '<div><span class="test">ab<span><a id="test2" href="">abc</a>c</span></span></div>';
    362368
    363         equal(DOM.getParents('test2', function(n) {return n.nodeName == 'SPAN';}).length, 2);
     369        equal(DOM.getParents('test2', eqNodeName('SPAN')).length, 2);
    364370        equal(DOM.getParents('test2', 'span').length, 2);
    365371        equal(DOM.getParents('test2', 'span.test').length, 1);
     
    434440        equal(DOM.getNext(DOM.get('test').firstChild, 'div'), null);
    435441        equal(DOM.getNext(null, 'div'), null);
    436         equal(DOM.getNext(DOM.get('test').firstChild, function(n) {return n.nodeName == 'EM';}).nodeName, 'EM');
     442        equal(DOM.getNext(DOM.get('test').firstChild, eqNodeName('EM')).nodeName, 'EM');
    437443
    438444        DOM.remove('test');
     
    447453        equal(DOM.getPrev(DOM.get('test').lastChild, 'div'), null);
    448454        equal(DOM.getPrev(null, 'div'), null);
    449         equal(DOM.getPrev(DOM.get('test').lastChild, function(n) {return n.nodeName == 'STRONG';}).nodeName, 'STRONG');
     455        equal(DOM.getPrev(DOM.get('test').lastChild, eqNodeName('STRONG')).nodeName, 'STRONG');
    450456
    451457        DOM.remove('test');
     
    582588    });
    583589
    584     test('isEmpty', 14, function() {
     590    test('isEmpty', function() {
    585591        DOM.schema = new tinymce.html.Schema(); // A schema will be added when used within a editor instance
    586592        DOM.add(document.body, 'div', {id : 'test'}, '');
     
    626632        DOM.setHTML('test', '<div><!-- comment --></div>');
    627633        ok(!DOM.isEmpty(DOM.get('test')), 'Element with comment.');
     634
     635        DOM.setHTML('test', '<span data-mce-bogus="1"></span>');
     636        ok(DOM.isEmpty(DOM.get('test')), 'Contains just a bogus element.');
     637
     638        DOM.setHTML('test', '<span data-mce-bogus="1">a</span>');
     639        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a text node in a bogus element.');
     640
     641        DOM.setHTML('test', '<span data-mce-bogus="all">a</span>');
     642        ok(DOM.isEmpty(DOM.get('test')), 'Contains just a bogus all element.');
     643
     644        DOM.setHTML('test', '<span data-mce-bogus="all">a</span>b');
     645        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a bogus all element but some text as well.');
     646
     647        DOM.setHTML('test', '<code> </code>');
     648        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a code element should be treated as content.');
     649
     650        DOM.setHTML('test', '<pre> </pre>');
     651        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a pre element should be treated as content.');
     652
     653        DOM.setHTML('test', '<code></code>');
     654        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a code element should be treated as content.');
     655
     656        DOM.setHTML('test', '<pre></pre>');
     657        ok(!DOM.isEmpty(DOM.get('test')), 'Contains a pre element should be treated as content.');
    628658
    629659        DOM.remove('test');
     
    635665    });
    636666
     667    test('isEmpty on pre', function() {
     668        var elm = DOM.create('pre', null, '  ');
     669        equal(false, DOM.isEmpty(elm));
     670    });
     671
    637672    test('isEmpty with list of elements considered non-empty without schema', function() {
    638673        var domWithoutSchema = new tinymce.dom.DOMUtils(document, {keep_values: true});
     
    646681        ok(DOM.isEmpty(elm, 'No children'));
    647682    });
    648    
     683
    649684    test('isEmpty on P with two BR in EM', function() {
    650685        var elm = DOM.create('p', null, '<em><br><br></em>');
     
    655690        var count = 0;
    656691
    657         DOM.bind(document, 'click', function() {count++;});
     692        DOM.bind(document, 'click', function() {
     693            count++;
     694        });
    658695        DOM.fire(document, 'click');
    659696        DOM.unbind(document, 'click');
     
    661698
    662699        count = 0;
    663         DOM.bind([document, window], 'click', function(e) {e.stopPropagation(); count++;});
     700        DOM.bind([document, window], 'click', function(e) {
     701            e.stopPropagation();
     702            count++;
     703        });
    664704        DOM.fire(document, 'click');
    665705        DOM.fire(window, 'click');
  • trunk/tests/qunit/editor/tinymce/dom/Selection.js

    r38034 r40399  
    11ModuleLoader.require([
    22    "tinymce/caret/CaretContainer",
     3    "tinymce/text/Zwsp",
    34    "tinymce/Env"
    4 ], function(CaretContainer, Env) {
     5], function(CaretContainer, Zwsp, Env) {
    56    module("tinymce.dom.Selection", {
    67        setupModule: function() {
     
    504505        CaretContainer.insertBlock('p', editor.$('p')[0], true);
    505506        rng = editor.dom.createRng();
    506         rng.setStart(editor.$('p')[0].firstChild, 0);
    507         rng.setEnd(editor.$('p')[0].firstChild, 1);
     507        rng.setStart(editor.$('p')[0], 0);
     508        rng.setEnd(editor.$('p')[0], 0);
    508509        editor.selection.setRng(rng);
    509510        bookmark = editor.selection.getBookmark(2);
     
    847848        });
    848849
     850        test('normalize lean left from br into formatter caret container', function() {
     851            var rng;
     852
     853            editor.getBody().innerHTML = '<p><span id="_mce_caret">' + Zwsp.ZWSP + '</span><br /></p>';
     854            rng = editor.dom.createRng();
     855            rng.setStartBefore(editor.getBody().firstChild.lastChild);
     856            rng.setEndBefore(editor.getBody().firstChild.lastChild);
     857            editor.selection.setRng(rng);
     858            editor.selection.normalize();
     859
     860            rng = editor.selection.getRng(true);
     861            equal(rng.startContainer.nodeType, 3);
     862            equal(rng.startOffset, 1);
     863        });
     864
    849865        test('normalize don\'t lean left into empty inline elements if there is a br element after caret', function() {
    850866            var rng;
     
    10561072        equal(rng.endOffset, 1);
    10571073    });
     1074
     1075    test('getRng should return null if win.document is not defined or null', function() {
     1076        var win = editor.selection.win,
     1077            rng = editor.dom.createRng();
     1078
     1079        editor.setContent('<p>x</p>');
     1080
     1081        rng.setStart(editor.$('p')[0].firstChild, 0);
     1082        rng.setEnd(editor.$('p')[0].firstChild, 1);
     1083
     1084        editor.selection.setRng(rng);
     1085        editor.selection.setRng(null);
     1086
     1087        editor.selection.win = {};
     1088        rng = editor.selection.getRng(true);
     1089        equal(rng, null);
     1090
     1091        editor.selection.win = {document:null};
     1092        rng = editor.selection.getRng(true);
     1093        equal(rng, null);
     1094
     1095        editor.selection.win = win;
     1096    });
     1097
     1098    test('image selection webkit bug', function() {
     1099        var testImageSelection = function (inputHtml, expectedContainerName, expectedOffset) {
     1100            editor.setContent(inputHtml);
     1101            editor.selection.select(editor.dom.select('img')[0]);
     1102
     1103            var rng = editor.selection.getRng(true);
     1104            equal(rng.startContainer.nodeName, 'P');
     1105            equal(rng.startOffset, expectedOffset);
     1106            equal(rng.startContainer.nodeName, 'P');
     1107            equal(rng.endOffset, expectedOffset + 1);
     1108            equal(editor.selection.getNode().nodeName, 'IMG');
     1109            equal(editor.selection.getStart().nodeName, 'IMG');
     1110            equal(editor.selection.getEnd().nodeName, 'IMG');
     1111
     1112            var nativeRng = editor.selection.getSel().getRangeAt(0);
     1113            equal(nativeRng.startContainer.nodeName, 'P');
     1114            equal(nativeRng.startOffset, expectedOffset);
     1115            equal(nativeRng.startContainer.nodeName, 'P');
     1116            equal(nativeRng.endOffset, expectedOffset + 1);
     1117        };
     1118
     1119        testImageSelection('<p><img src="#"></p>', 'P', 0);
     1120        testImageSelection('<p><img src="#">abc</p>', 'P', 0);
     1121        testImageSelection('<p>abc<img src="#"></p>', 'P', 1);
     1122        testImageSelection('<p>abc<img src="#">def</p>', 'P', 1);
     1123        testImageSelection('<p><img style="float: right;" src="#"></p>', 'P', 0);
     1124        testImageSelection('<p><img style="float: right;" src="#">abc</p>', 'P', 0);
     1125        testImageSelection('<p>abc<img style="float: right;" src="#"></p>', 'P', 1);
     1126        testImageSelection('<p>abc<img style="float: right;" src="#">def</p>', 'P', 1);
     1127        testImageSelection('<p><img style="float: left;" src="#"></p>', 'P', 0);
     1128        testImageSelection('<p><img style="float: left;" src="#">abc</p>', 'P', 0);
     1129        testImageSelection('<p>abc<img style="float: left;" src="#"></p>', 'P', 1);
     1130        testImageSelection('<p>abc<img style="float: left;" src="#">def</p>', 'P', 1);
     1131        testImageSelection('<p dir="rtl"><img style="float: right;" src="#"></p>', 'P', 0);
     1132        testImageSelection('<p dir="rtl"><img style="float: right;" src="#">abc</p>', 'P', 0);
     1133        testImageSelection('<p dir="rtl">abc<img style="float: right;" src="#"></p>', 'P', 1);
     1134        testImageSelection('<p dir="rtl">abc<img style="float: right;" src="#">def</p>', 'P', 1);
     1135        testImageSelection('<p dir="rtl"><img style="float: left;" src="#"></p>', 'P', 0);
     1136        testImageSelection('<p dir="rtl"><img style="float: left;" src="#">abc</p>', 'P', 0);
     1137        testImageSelection('<p dir="rtl">abc<img style="float: left;" src="#"></p>', 'P', 1);
     1138        testImageSelection('<p dir="rtl">abc<img style="float: left;" src="#">def</p>', 'P', 1);
     1139    });
    10581140});
    10591141
  • trunk/tests/qunit/editor/tinymce/dom/Serializer.js

    r37000 r40399  
    2626    ser.setRules('a[href|target<_blank?_top|title:forced value]');
    2727    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>');
    28     equal(ser.serialize(DOM.get('test')), '<a href="file.htm" target="_blank" title="forced value">link</a><a href="#" title="forced value">test2</a>');
     28    equal(ser.serialize(DOM.get('test')), '<a href="file.htm" target="_blank" title="forced value" rel="noopener noreferrer">link</a><a href="#" title="forced value">test2</a>');
    2929
    3030    ser.setRules('img[src|border=0|alt=]');
     
    235235});
    236236
     237test('Padd empty elements with BR', function() {
     238    var ser = new tinymce.dom.Serializer({padd_empty_with_br: true});
     239
     240    ser.setRules('#p,table,tr,#td,br');
     241
     242    DOM.setHTML('test', '<p>a</p><p></p>');
     243    equal(ser.serialize(DOM.get('test')), '<p>a</p><p><br /></p>');
     244    DOM.setHTML('test', '<p>a</p><table><tr><td><br></td></tr></table>');
     245    equal(ser.serialize(DOM.get('test')), '<p>a</p><table><tr><td><br /></td></tr></table>');
     246});
     247
    237248test('Remove empty elements', function() {
    238249    var ser = new tinymce.dom.Serializer({fix_list_elements : true});
     
    345356    DOM.setHTML('test', '<script>\n\n<![CDATA[\n\n1 < 2;\n\n]]>\n\n</s' + 'cript>');
    346357    equal(ser.serialize(DOM.get('test')).replace(/\r/g, ''), '<s' + 'cript>// <![CDATA[\n1 < 2;\n// ]]></s' + 'cript>');
     358});
     359
     360test('Whitespace preserve in pre', function() {
     361    var ser = new tinymce.dom.Serializer({fix_list_elements : true});
     362    ser.setRules('pre');
     363
     364    DOM.setHTML('test', '<pre>  </pre>');
     365    equal(ser.serialize(DOM.get('test')), '<pre>  </pre>');
    347366});
    348367
     
    525544    equal(ser.trimHtml('<p data-x="1" data-y="2" data-z="3">a</p>'), '<p data-z="3">a</p>');
    526545});
     546
     547test('addTempAttr same attr twice', function() {
     548    var ser1 = new tinymce.dom.Serializer({});
     549    var ser2 = new tinymce.dom.Serializer({});
     550
     551    ser1.addTempAttr('data-x');
     552    ser2.addTempAttr('data-x');
     553
     554    DOM.setHTML('test', '<p data-x="1" data-z="3">a</p>');
     555    equal(ser1.serialize(DOM.get('test'), {getInner: 1}), '<p data-z="3">a</p>');
     556    equal(ser1.trimHtml('<p data-x="1" data-z="3">a</p>'), '<p data-z="3">a</p>');
     557    equal(ser2.serialize(DOM.get('test'), {getInner: 1}), '<p data-z="3">a</p>');
     558    equal(ser2.trimHtml('<p data-x="1" data-z="3">a</p>'), '<p data-z="3">a</p>');
     559});
  • trunk/tests/qunit/editor/tinymce/file/ImageScanner.js

    r38034 r40399  
    33    "tinymce/file/UploadStatus",
    44    "tinymce/file/BlobCache",
     5    "tinymce/file/Conversions",
    56    "tinymce/Env"
    6 ], function(ImageScanner, UploadStatus, BlobCache, Env) {
     7], function(ImageScanner, UploadStatus, BlobCache, Conversions, Env) {
    78    if (!tinymce.Env.fileApi) {
    89        return;
    910    }
    1011
     12    QUnit.config.autostart = false;
     13
    1114    module("tinymce.file.ImageScanner");
    1215
    1316    var base64Src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==';
     17    var blobUriSrc;
     18
     19    Conversions.uriToBlob(base64Src).then(function(blob) {
     20        blobUriSrc = URL.createObjectURL(blob);
     21        QUnit.start();
     22    });
    1423
    1524    QUnit.asyncTest("findAll", function() {
     
    1827        document.getElementById('view').innerHTML = (
    1928            '<img src="' + base64Src + '">' +
     29            '<img src="' + blobUriSrc + '">' +
    2030            '<img src="' + Env.transparentSrc + '">' +
    2131            '<img src="' + base64Src + '" data-mce-bogus="1">' +
     
    2535        imageScanner.findAll(document.getElementById('view')).then(function(result) {
    2636            QUnit.start();
    27             equal(result.length, 1);
    28             equal('data:image/gif;base64,' + result[0].blobInfo.base64(), base64Src);
     37            var blobInfo = result[0].blobInfo;
     38            equal(result.length, 2);
     39            equal('data:image/gif;base64,' + blobInfo.base64(), base64Src);
    2940            strictEqual(result[0].image, document.getElementById('view').firstChild);
    3041        });
  • trunk/tests/qunit/editor/tinymce/html/DomParser.js

    r37000 r40399  
    100100    });
    101101
     102    test('Whitespace preserved in PRE', function() {
     103        parser = new tinymce.html.DomParser({}, schema);
     104        root = parser.parse('<PRE>  </PRE>');
     105        equal(serializer.serialize(root), '<pre>  </pre>', 'Whitespace around and inside PRE');
     106        deepEqual(countNodes(root), {body:1, pre:1, '#text':1}, 'Whitespace around and inside PRE (count)');
     107    });
     108
    102109    test('Whitespace preserved in SPAN inside PRE', function() {
    103110        parser = new tinymce.html.DomParser({}, schema);
     
    105112        equal(serializer.serialize(root), '<pre>  \t\r\n  <span>    test    </span> \t\r\n   </pre>', 'Whitespace around and inside PRE');
    106113        deepEqual(countNodes(root), {body:1, pre:1, span:1, '#text':3}, 'Whitespace around and inside PRE (count)');
     114    });
     115
     116    test('Whitespace preserved in code', function() {
     117        parser = new tinymce.html.DomParser({}, schema);
     118        root = parser.parse('<code>  a  </code>');
     119        equal(serializer.serialize(root), '<code>  a  </code>', 'Whitespace inside code');
     120        deepEqual(countNodes(root), {body:1, code:1, '#text':1}, 'Whitespace inside code (count)');
     121    });
     122
     123    test('Whitespace preserved in code', function() {
     124        parser = new tinymce.html.DomParser({}, schema);
     125        root = parser.parse('<code>  </code>');
     126        equal(serializer.serialize(root), '<code>  </code>', 'Whitespace inside code');
     127        deepEqual(countNodes(root), {body:1, code:1, '#text':1}, 'Whitespace inside code (count)');
    107128    });
    108129
     
    423444    });
    424445
     446    test('Parse html4 lists into html5 lists', function() {
     447        var parser, root, schema = new tinymce.html.Schema();
     448
     449        parser = new tinymce.html.DomParser({fix_list_elements: true}, schema);
     450        root = parser.parse('<ul><ul><li>a</li></ul></ul><ul><li>a</li><ul><li>b</li></ul></ul>');
     451        equal(serializer.serialize(root), '<ul><li style="list-style-type: none"><ul><li>a</li></ul></li></ul><ul><li>a<ul><li>b</li></ul></li></ul>');
     452    });
     453
    425454    test('Parse contents with html4 anchors and allow_html_in_named_anchor: false', function() {
    426455        var parser, root, schema = new tinymce.html.Schema();
     
    509538        root = parser.parse('<ul><li></li></ul><ul><li> </li></ul>');
    510539        equal(serializer.serialize(root), '');
     540    });
     541
     542    test('Padd empty with br', function() {
     543        var schema = new tinymce.html.Schema();
     544        var parser = new tinymce.html.DomParser({padd_empty_with_br: true}, schema);
     545        var serializer = new tinymce.html.Serializer({padd_empty_with_br: true}, schema);
     546        var root = parser.parse('<p>a</p><p></p>');
     547        equal(serializer.serialize(root), '<p>a</p><p><br /></p>');
    511548    });
    512549
  • trunk/tests/qunit/editor/tinymce/html/Node.js

    r27679 r40399  
    140140    ok(node.next === node3, 'node.next');
    141141    equal(node.prev, undefined, 'node.prev');
    142     ok(node3.prev, node, 'node3.prev');
     142    equal(node3.prev, node, 'node3.prev');
    143143    equal(node3.next, undefined, 'node3.next');
    144144});
  • trunk/tests/qunit/editor/tinymce/html/SaxParser.js

    r33013 r40399  
    605605        parser.parse('<!--[if !IE]>alert(1)<![endif]-->');
    606606        equal(writer.getContent(), '<!-- [if !IE]>alert(1)<![endif]-->');
     607
     608        writer.reset();
     609        parser.parse('<!--[iF !IE]>alert(1)<![endif]-->');
     610        equal(writer.getContent(), '<!-- [iF !IE]>alert(1)<![endif]-->');
    607611    });
    608612
  • trunk/tests/qunit/editor/tinymce/html/Schema.js

    r36352 r40399  
    1414
    1515    schema = new tinymce.html.Schema({valid_elements: '*[id|class]'});
    16     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     16    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    1717    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    1818
    1919    schema = new tinymce.html.Schema({valid_elements: 'b*[id|class]'});
    20     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     20    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    2121    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    22     deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {} });
     22    deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {}});
    2323    deepEqual(schema.getElementRule('body').attributesOrder, ["id", "class"]);
    2424    equal(schema.getElementRule('img'), undefined);
    2525
    2626    schema = new tinymce.html.Schema({valid_elements: 'b?[id|class]'});
    27     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     27    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    2828    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    29     deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {} });
     29    deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {}});
    3030    deepEqual(schema.getElementRule('bx').attributesOrder, ["id", "class"]);
    3131    equal(schema.getElementRule('body'), undefined);
    3232
    3333    schema = new tinymce.html.Schema({valid_elements: 'b+[id|class]'});
    34     deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {} });
     34    deepEqual(schema.getElementRule('body').attributes, {"id": {}, "class": {}});
    3535    deepEqual(schema.getElementRule('body').attributesOrder, ["id", "class"]);
    36     deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {} });
     36    deepEqual(schema.getElementRule('bx').attributes, {"id": {}, "class": {}});
    3737    deepEqual(schema.getElementRule('bx').attributesOrder, ["id", "class"]);
    3838    equal(schema.getElementRule('b'), undefined);
     
    4545
    4646    schema = new tinymce.html.Schema({valid_elements: 'b[id|class|*]'});
    47     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     47    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    4848    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    4949    ok(schema.getElementRule('b').attributePatterns[0].pattern.test('x'));
    5050
    5151    schema = new tinymce.html.Schema({valid_elements: 'b[id|class|x?]'});
    52     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     52    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    5353    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    5454    ok(schema.getElementRule('b').attributePatterns[0].pattern.test('xy'));
     
    5757
    5858    schema = new tinymce.html.Schema({valid_elements: 'b[id|class|x+]'});
    59     deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {} });
     59    deepEqual(schema.getElementRule('b').attributes, {"id": {}, "class": {}});
    6060    deepEqual(schema.getElementRule('b').attributesOrder, ["id", "class"]);
    6161    ok(!schema.getElementRule('b').attributePatterns[0].pattern.test('x'));
     
    118118    schema = new tinymce.html.Schema({valid_elements: 'span[dir<ltr?rtl]'});
    119119    deepEqual(schema.getElementRule('span'), {"attributes": {"dir": {"validValues": {"rtl": {}, "ltr": {}}}}, "attributesOrder": ["dir"]});
     120});
     121
     122test('Required parents', function() {
     123    var schema;
     124
     125    schema = new tinymce.html.Schema();
     126    deepEqual(schema.getElementRule('tr').parentsRequired, ['tbody', 'thead', 'tfoot']);
     127    deepEqual(schema.getElementRule('li').parentsRequired, ['ul', 'ol']);
     128    deepEqual(schema.getElementRule('div').parentsRequired, undefined);
    120129});
    121130
     
    221230        "INPUT": {}, "IMG": {}, "HR": {}, "FRAME": {}, "COL": {}, "BR": {},
    222231        "BASEFONT": {}, "BASE": {}, "AREA": {}, "SOURCE" : {},
    223         "TD": {}, "TH": {}, "IFRAME": {}, "VIDEO": {}, "AUDIO": {}, "OBJECT": {}, "WBR": {}, "TRACK" : {}, "SCRIPT" : {},
     232        "TD": {}, "TH": {}, "IFRAME": {}, "VIDEO": {}, "AUDIO": {}, "OBJECT": {}, "WBR": {}, "TRACK" : {}, "SCRIPT" : {}, "PRE": {}, "CODE": {},
    224233        "embed": {}, "param": {}, "meta": {}, "link": {}, "isindex": {},
    225234        "input": {}, "img": {}, "hr": {}, "frame": {}, "col": {}, "br": {},
    226235        "basefont": {}, "base": {}, "area": {}, "source" : {},
    227         "td": {}, "th": {}, "iframe": {}, "video": {}, "audio": {}, "object": {}, "wbr" : {}, "track" : {},  "script" : {}
     236        "td": {}, "th": {}, "iframe": {}, "video": {}, "audio": {}, "object": {}, "wbr" : {}, "track" : {}, "script" : {}, "pre": {}, "code": {}
    228237    });
    229238});
     
    236245    schema = new tinymce.html.Schema();
    237246    deepEqual(schema.getWhiteSpaceElements(), {
    238         "IFRAME": {}, "NOSCRIPT": {}, "OBJECT": {}, "PRE": {},
     247        "IFRAME": {}, "NOSCRIPT": {}, "OBJECT": {}, "PRE": {}, "CODE": {},
    239248        "SCRIPT": {}, "STYLE": {}, "TEXTAREA": {}, "VIDEO": {}, "AUDIO": {},
    240         "iframe": {}, "noscript": {}, "object": {}, "pre": {},
     249        "iframe": {}, "noscript": {}, "object": {}, "pre": {}, "code": {},
    241250        "script": {}, "style": {}, "textarea": {}, "video": {}, "audio": {}
    242251    });
  • trunk/tests/qunit/editor/tinymce/html/Styles.js

    r28768 r40399  
    44    var styles = new tinymce.html.Styles();
    55
    6     expect(11);
     6    expect(12);
    77
    88    equal(styles.serialize(styles.parse('FONT-SIZE:10px')), "font-size: 10px;");
     
    1717    equal(styles.serialize(styles.parse('value: "&"')), "value: '&';");
    1818    equal(styles.serialize(styles.parse('value: ')), "");
     19    equal(styles.serialize(styles.parse("background: url('http://www.site.com/(foo)');")), "background: url('http://www.site.com/(foo)');");
    1920});
    2021
     
    6263        'border: 1pt none black;'
    6364    );
    64    
     65
    6566    equal(
    6667        styles.serialize(styles.parse('border-width: 1pt 4pt 2pt 3pt; border-style: solid dashed dotted none; border-color: black red green blue;')),
     
    138139});
    139140
     141test('Suspicious (XSS) property names', function() {
     142    var styles = new tinymce.html.Styles();
     143
     144    equal(styles.serialize(styles.parse('font-fa"on-load\\3dxss\\28\\29\\20mily:\'arial\'')), "");
     145    equal(styles.serialize(styles.parse('font-fa\\"on-load\\3dxss\\28\\29\\20mily:\'arial\'')), "");
     146    equal(styles.serialize(styles.parse('font-fa\\22on-load\\3dxss\\28\\29\\20mily:\'arial\'')), "");
     147});
     148
    140149test('Script urls denied', function() {
    141150    var styles = new tinymce.html.Styles();
    142151
    143152    equal(styles.serialize(styles.parse('behavior:url(test.htc)')), "");
     153    equal(styles.serialize(styles.parse('b\\65havior:url(test.htc)')), "");
    144154    equal(styles.serialize(styles.parse('color:expression(alert(1))')), "");
    145155    equal(styles.serialize(styles.parse('color:\\65xpression(alert(1))')), "");
     
    149159    equal(styles.serialize(styles.parse('background:url(jAvaScript:alert(1)')), "");
    150160    equal(styles.serialize(styles.parse('background:url(javascript:alert(1)')), "");
     161    equal(styles.serialize(styles.parse('background:url(j\\61vascript:alert(1)')), "");
     162    equal(styles.serialize(styles.parse('background:url(\\6a\\61vascript:alert(1)')), "");
     163    equal(styles.serialize(styles.parse('background:url(\\6A\\61vascript:alert(1)')), "");
     164    equal(styles.serialize(styles.parse('background:url\\28\\6A\\61vascript:alert(1)')), "");
     165    equal(styles.serialize(styles.parse('background:\\75rl(j\\61vascript:alert(1)')), "");
     166    equal(styles.serialize(styles.parse('b\\61ckground:\\75rl(j\\61vascript:alert(1)')), "");
    151167    equal(styles.serialize(styles.parse('background:url(vbscript:alert(1)')), "");
    152168    equal(styles.serialize(styles.parse('background:url(j\navas\u0000cr\tipt:alert(1)')), "");
    153169    equal(styles.serialize(styles.parse('background:url(data:image/svg+xml,%3Csvg/%3E)')), "");
     170    equal(styles.serialize(styles.parse('background:url( data:image/svg+xml,%3Csvg/%3E)')), "");
     171    equal(styles.serialize(styles.parse('background:url\\28 data:image/svg+xml,%3Csvg/%3E)')), "");
     172    equal(styles.serialize(styles.parse('background:url("data: image/svg+xml,%3Csvg/%3E")')), "");
     173    equal(styles.serialize(styles.parse('background:url("data: ima ge/svg+xml,%3Csvg/%3E")')), "");
     174    equal(styles.serialize(styles.parse('background:url("data: image /svg+xml,%3Csvg/%3E")')), "");
    154175});
    155176
  • trunk/tests/qunit/editor/tinymce/ui/Window.js

    r27679 r40399  
    3737
    3838    test("title, no buttonbar, autoResize, title is widest", function() {
    39         var win = createWindow({
     39        var win1 = createWindow({
     40            x: 100,
     41            y: 120,
     42            title: "XXXXXXXXXXXXXXXXXXX",
     43            items: [
     44                {type: 'spacer', classes: 'red', flex: 1}
     45            ]
     46        });
     47
     48        var win2 = createWindow({
    4049            x: 100,
    4150            y: 120,
     
    4655        });
    4756
    48         Utils.nearlyEqualRects(Utils.size(win), [326, 61], 60);
    49         Utils.nearlyEqualRects(Utils.size(win.find("spacer")[0]), [324, 20], 60);
     57        equal(Utils.size(win2)[0] > Utils.size(win1)[0], true, 'Window 2 should be wider since the title spaces out the window');
     58        equal(Utils.size(win2.find("spacer")[0]) > Utils.size(win1.find("spacer")[0]), true, 'Window 2 spacer should be widger than window 1');
    5059    });
    5160
  • trunk/tests/qunit/editor/tinymce/util/I18n.js

    r31700 r40399  
    66
    77test("Translate strings", function() {
     8    var undef;
     9    var translate = tinymce.util.I18n.translate;
     10
    811    tinymce.util.I18n.add("code", {
    912        "text": "text translation",
    1013        "value:{0}{1}": "value translation:{0}{1}",
    1114        "text{context:something}": "text translation with context",
    12         "value:{0}{1}{context:something}": "value translation:{0}{1} with context"
     15        "value:{0}{1}{context:something}": "value translation:{0}{1} with context",
     16        "empty string": ""
    1317    });
    1418
    15     equal(tinymce.util.I18n.translate("text"), "text translation");
    16     equal(tinymce.util.I18n.translate("untranslated text"), "untranslated text");
    17     equal(tinymce.util.I18n.translate(["untranslated value:{0}{1}", "a", "b"]), "untranslated value:ab");
    18     equal(tinymce.util.I18n.translate(["value:{0}{1}", "a", "b"]), "value translation:ab");
    19     equal(tinymce.util.I18n.translate("untranslated text{context:context}"), "untranslated text");
    20     equal(tinymce.util.I18n.translate(["untranslated value:{0}{1}{context:something}", "a", "b"]), "untranslated value:ab");
    21     equal(tinymce.util.I18n.translate(["value:{0}{1}{context:something}", "a", "b"]), "value translation:ab with context");
     19    equal(translate("text"), "text translation");
     20    equal(translate("untranslated text"), "untranslated text");
     21    equal(translate(["untranslated value:{0}{1}", "a", "b"]), "untranslated value:ab");
     22    equal(translate(["value:{0}{1}", "a", "b"]), "value translation:ab");
     23    equal(translate("untranslated text{context:context}"), "untranslated text");
     24    equal(translate(["untranslated value:{0}{1}{context:something}", "a", "b"]), "untranslated value:ab");
     25    equal(translate(["value:{0}{1}{context:something}", "a", "b"]), "value translation:ab with context");
     26
     27    // check if translate survives some awkward cases
     28    deepEqual(translate("empty string"), "");
     29    equal(translate(["untranslated value:{0}{1}", "a"]), "untranslated value:a{1}",
     30        "Do not strip tokens that weren't replaced.");
     31
     32    equal(translate([{}]), "[object Object]");
     33    equal(translate(function(){}), "[object Function]");
     34
     35    equal(translate(null), "");
     36    equal(translate(0), 0, "0");
     37    equal(translate(true), "true", "true");
     38    equal(translate(false), "false", "false");
     39
     40    equal(translate({}), "[object Object]", "[object Object]");
     41    equal(translate({raw:""}), "", "empty string");
     42    equal(translate({raw:false}), "false", "false");
     43    equal(translate({raw:undef}), "");
     44    equal(translate({raw:null}), "");
     45
     46    // https://github.com/tinymce/tinymce/issues/3029
     47    equal(translate("hasOwnProperty"), "hasOwnProperty");
     48    tinymce.util.I18n.add("code", {
     49        "hasOwnProperty": "good"
     50    });
     51    equal(translate("hasOwnProperty"), "good");
     52
    2253});
    2354
  • trunk/tests/qunit/editor/tinymce/util/Quirks_webkit.js

    r38034 r40399  
    126126    });
    127127
     128    test('Delete from after image to paragraph', function() {
     129        editor.getBody().innerHTML = '<p>a</p><p><img src="about:blank"></p>';
     130        var rng = editor.dom.createRng();
     131        rng.setStartAfter(editor.dom.select('img')[0]);
     132        rng.setEndAfter(editor.dom.select('img')[0]);
     133        editor.selection.setRng(rng);
     134        editor.execCommand('Delete');
     135        equal(Utils.normalizeHtml(Utils.cleanHtml(editor.getBody().innerHTML)), '<p>a</p>');
     136        equal(editor.selection.getStart().nodeName, 'P');
     137    });
     138
    128139    test('ForwardDelete from end of H1 to P with style span', function() {
    129140        editor.getBody().innerHTML = '<h1>a</h1><p><span style="color:red">b</span></p>';
     
    335346        equal(editor.selection.getStart(true).nodeName, 'P');
    336347    });
     348
     349    test('Delete with similar sibling nodes', function() {
     350        editor.getBody().innerHTML = '<p>Test test</p><p>a</p><p>a</p><p id="t1">a</p><p>test1</p><p id="t2">test2</p>';
     351        Utils.setSelection('p#t1', 1, 'p#t2', 5);
     352        editor.fire('keydown', {keyCode: 8});
     353        equal(Utils.cleanHtml(editor.getBody().innerHTML), '<p>test test</p><p>a</p><p>a</p><p id="t1">a</p>');
     354        equal(editor.selection.getStart(true).nodeName, 'P');
     355    });
    337356} else {
    338357    test("Skipped since the browser isn't WebKit", function() {
Note: See TracChangeset for help on using the changeset viewer.