From 1eb1c2b029c7216c70becbf4cd0d9e6535deea96 Mon Sep 17 00:00:00 2001 From: Gorash Date: Tue, 13 Aug 2019 14:18:41 +0000 Subject: [PATCH] [REF] web_editor: adapt wysiwyg tests to older summernote version These modifications crystalize the behavior of the old editor, even if it makes less sense than the behavior of the saas-12.2 one. In some cases, the only reasonable adaptation we could do for 13.0 was to delete the tests, as these tests relied on mechanisms of the newer version of summernote introduced in saas-12.2 which cannot be easily replicated in the older version from 12.0 that we are reintroducing in this PR. It is sad to see these tests go, but we knew this was going to be something we would lose in reverting back to the older editor. That being said, since these tests were not present back in 12.0, we are simply back to the 12.0 state of things, not worse. Don't weep for them though, they will be back in Odoo 14. Part of PR 35677. Co-authored-by: Nicolas Bayet Co-authored-by: Antoine Guenet Co-authored-by: Christophe Matthieu Co-authored-by: David Monjoie --- .../static/tests/mass_mailing_html_tests.js | 88 +- .../static/tests/field_html_tests.js | 482 +- .../static/tests/wysiwyg_keyboard_tests.js | 4423 ----------------- .../static/tests/wysiwyg_snippets_tests.js | 413 -- .../web_editor/static/tests/wysiwyg_tests.js | 4182 ---------------- addons/web_editor/views/editor.xml | 3 - 6 files changed, 15 insertions(+), 9576 deletions(-) delete mode 100644 addons/web_editor/static/tests/wysiwyg_keyboard_tests.js delete mode 100644 addons/web_editor/static/tests/wysiwyg_snippets_tests.js delete mode 100644 addons/web_editor/static/tests/wysiwyg_tests.js diff --git a/addons/mass_mailing/static/tests/mass_mailing_html_tests.js b/addons/mass_mailing/static/tests/mass_mailing_html_tests.js index ee5b45c1b0d..e039fa14c86 100644 --- a/addons/mass_mailing/static/tests/mass_mailing_html_tests.js +++ b/addons/mass_mailing/static/tests/mass_mailing_html_tests.js @@ -64,7 +64,7 @@ QUnit.module('field html', { }, function () { QUnit.test('save arch and html', async function (assert) { - assert.expect(6); + assert.expect(4); var form = await testUtils.createView({ View: FormView, @@ -85,19 +85,6 @@ QUnit.test('save arch and html', async function (assert) { ' />'+ '', res_id: 1, - mockRPC: function (route, args) { - if (args.method === "write") { - var values = args.args[1]; - assert.strictEqual(values.body_html, - '

code to edit

', - "should save the content"); - assert.strictEqual(values.body_arch, - '

code to edit

', - "should save the content"); - - } - return this._super.apply(this, arguments); - }, }); var $fieldReadonly = form.$('.oe_form_field[name="body_html"]'); var $fieldEdit = form.$('.oe_form_field[name="body_arch"]'); @@ -113,79 +100,6 @@ QUnit.test('save arch and html', async function (assert) { assert.strictEqual($fieldReadonly.css('display'), 'none', "should hide the readonly mode"); assert.strictEqual($fieldEdit.css('display'), 'block', "should display the edit mode"); - var $iframe = $fieldEdit.find('iframe'); - await testUtils.nextTick(); - await $iframe.data('loadDef'); - await testUtils.nextTick(); - var doc = $iframe.contents()[0]; - var $content = $('#iframe_target', doc); - - // select the text - var pText = $content.find('.note-editable p').first().contents()[0]; - Wysiwyg.setRange(pText, 1, pText, 3); - // text is selected - await testUtils.nextTick(); - - await testUtils.dom.triggerEvents($content.find('.note-toolbar .note-font .note-btn-bold'),['mousedown','click']); - - await testUtils.dom.click(form.$buttons.find('.o_form_button_save')); - - form.destroy(); -}); - -QUnit.test('save and edit arch wysiwyg', async function (assert) { - assert.expect(4); - - testUtils.mock.patch(FieldHtml, { - commitChanges: function () { - assert.step("FieldHtml"); - return this._super.apply(this, arguments); - }, - }); - - testUtils.mock.patch(MassMailingFieldHtml, { - commitChanges: function () { - assert.step("MassMailingFieldHtml"); - return this._super.apply(this, arguments); - }, - }); - - var form = await testUtils.createView({ - View: FormView, - model: 'mailing.mailing', - data: this.data, - arch: '
' + - '
' + - '
' + - ' ' + - '', - res_id: 1, - intercepts: { - execute_action: function (event) { - event.data.on_success(); - }, - }, - }); - - await testUtils.dom.click($('[name=action_put_in_queue]')); - await testUtils.form.clickEdit(form); - var $fieldEdit = form.$('.oe_form_field[name="body_arch"]'); - var $iframe = $fieldEdit.find('iframe'); - - await $iframe.data('loadDef'); - await testUtils.nextTick(); - await testUtils.dom.click($('[name=action_put_in_queue]')); - assert.verifySteps(["MassMailingFieldHtml", "FieldHtml", "MassMailingFieldHtml"]); - - testUtils.mock.unpatch(FieldHtml); - testUtils.mock.unpatch(MassMailingFieldHtml); form.destroy(); }); diff --git a/addons/web_editor/static/tests/field_html_tests.js b/addons/web_editor/static/tests/field_html_tests.js index f9e08872bd3..b092604bd64 100644 --- a/addons/web_editor/static/tests/field_html_tests.js +++ b/addons/web_editor/static/tests/field_html_tests.js @@ -137,14 +137,14 @@ QUnit.module('web_editor', {}, function () { assert.strictEqual(range.sc, pText, "should select the text"); - $field.find('.note-toolbar .note-bg-color button:first').mousedown().click(); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first')); - assert.ok($field.find('.note-bg-color').hasClass('show') && $field.find('.note-bg-color .dropdown-menu').hasClass('show'), + assert.ok($field.find('.note-back-color-preview').hasClass('show'), "should display the color picker"); - $field.find('.note-toolbar .note-bg-color button[data-value="#00FFFF"]').mousedown().click(); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="#00FFFF"]')); - assert.ok(!$field.find('.note-bg-color').hasClass('show') && !$field.find('.note-bg-color .dropdown-menu').hasClass('show'), + assert.ok(!$field.find('.note-back-color-preview').hasClass('show'), "should close the color picker"); assert.strictEqual($field.find('.note-editable').html(), @@ -167,11 +167,11 @@ QUnit.module('web_editor', {}, function () { Wysiwyg.setRange(fontContent, 5, pText, 2); // text is selected - $field.find('.note-toolbar .note-bg-color button:first').mousedown().click(); - $field.find('.note-toolbar .note-bg-color button[data-value="bg-gamma"]').mousedown().click(); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first')); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="bg-gamma"]')); assert.strictEqual($field.find('.note-editable').html(), - '

toto toto toto

tata

', + '

toto toto toto

tata

', "should have rendered the field correctly in edit"); form.destroy(); @@ -215,7 +215,7 @@ QUnit.module('web_editor', {}, function () { var pText = $field.find('.note-editable p').first().contents()[0]; Wysiwyg.setRange(pText, 1); - $field.find('.note-toolbar .note-insert button:has(.fa-file-image-o)').mousedown().click(); + await testUtils.dom.click($field.find('.note-toolbar .note-insert button:has(.fa-file-image-o)')); // load static xml file (dialog, media dialog, unsplash image widget) await defMediaDialog; @@ -266,7 +266,7 @@ QUnit.module('web_editor', {}, function () { var pText = $field.find('.note-editable p').first().contents()[0]; Wysiwyg.setRange(pText, 1); - $field.find('.note-toolbar .note-insert button:has(.fa-file-image-o)').mousedown().click(); + await testUtils.dom.click($field.find('.note-toolbar .note-insert button:has(.fa-file-image-o)')); // load static xml file (dialog, media dialog, unsplash image widget) await defMediaDialog; @@ -315,82 +315,8 @@ QUnit.module('web_editor', {}, function () { Wysiwyg.setRange(pText, 1, pText, 10); // text is selected - await testUtils.dom.click($field.find('.note-toolbar .note-bg-color button:first').mousedown()); - await testUtils.dom.click($field.find('.note-toolbar .note-bg-color button[data-value="bg-gamma"]').mousedown()); - - await testUtils.form.clickSave(form); - - form.destroy(); - }); - - QUnit.module('inline-style'); - - QUnit.test('convert style to class on edit', async function (assert) { - assert.expect(5); - - this.data['note.note'].records[0].body = '

toto ' + - '' + - 'toto toto

tata

'; - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - mockRPC: function (route, args) { - if (args.method === "write") { - assert.strictEqual(args.args[1].body, - '

' + - 'toto ' + - '' + - 'toto toto' + - '

' + - '

' + - 'tata' + - '

', - "should save the content"); - } - if (route.indexOf("/web_editor/font_to_img/61445/rgb(") !== -1) { - assert.strictEqual(route, - '/web_editor/font_to_img/61445/rgb(255,0,0)/13', - "should use the image in function of the font and the color"); - return Promise.resolve('#'); - } - return this._super.apply(this, arguments); - }, - }); - var $field = form.$('.oe_form_field[name="body"]'); - - assert.strictEqual($field.children('.o_readonly').html(), - '

' + - 'toto ' + - '' + - 'toto toto' + - '

' + - '

tata

', - "should have rendered a div with correct content in readonly"); - - await testUtils.form.clickEdit(form); - - $field = form.$('.oe_form_field[name="body"]'); - assert.strictEqual($field.find('.note-editable').html(), - '

' + - 'toto ' + - '' + - 'toto toto' + - '

' + - '

tata

', - "should have rendered the field correctly in edit (remove inline style that used class)"); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first')); + await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="bg-gamma"]')); await testUtils.form.clickSave(form); @@ -433,96 +359,10 @@ QUnit.module('web_editor', {}, function () { form.destroy(); }); - QUnit.module('cssEdit'); - - QUnit.test('rendering with iframe for edit mode', async function (assert) { - assert.expect(4); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - var $field = form.$('.oe_form_field[name="body"]'); - assert.strictEqual($field.children('.o_readonly').html(), - '

toto toto toto

tata

', - "should have rendered a div with correct content in readonly"); - - await testUtils.form.clickEdit(form); - - $field = form.$('.oe_form_field[name="body"]'); - var $iframe = $field.find('iframe'); - await $iframe.data('loadDef'); - var doc = $iframe.contents()[0]; - var $content = $('#iframe_target', doc); - - await testUtils.nextTick(); - - assert.strictEqual($content.find('.note-editable').html(), - '

toto toto toto

tata

', - "should have rendered a div with correct content in edit mode"); - - assert.strictEqual(doc.defaultView.getComputedStyle(doc.body).backgroundColor, - 'rgb(255, 0, 0)', - "should load the asset css"); - - $content.find('.note-toolbar .note-bg-color button:first').mousedown().click(); - await testUtils.nextTick(); - - assert.ok($content.find('.note-bg-color').hasClass('show') && $content.find('.note-bg-color .dropdown-menu').hasClass('show'), - "should display toolbar dropdown menu in iframe"); - - form.destroy(); - }); - -QUnit.test('save immediately before iframe is rendered in edit mode', async function (assert) { - assert.expect(1); - - var form = await testUtils.createAsyncView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - testUtils.form.clickEdit(form); - await testUtils.nextTick(); - testUtils.form.clickSave(form); - await testUtils.nextTick(); - assert.ok(true, "No traceback encountered. The wysiwyg was cut while not loaded."); - form.destroy(); -}); - - QUnit.test('save immediately before iframe is rendered in edit mode with style-inline', async function (assert) { + QUnit.test('save immediately before iframe is rendered in edit mode', async function (assert) { assert.expect(1); var form = await testUtils.createAsyncView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - testUtils.form.clickEdit(form); - await testUtils.nextTick(); - testUtils.form.clickSave(form); - await testUtils.nextTick(); - assert.ok(true, "No traceback encountered. The wysiwyg was cut while not loaded."); - form.destroy(); - }); - - QUnit.test('use colorpicker and save', async function (assert) { - assert.expect(1); - - var form = await testUtils.createView({ View: FormView, model: 'note.note', data: this.data, @@ -530,268 +370,15 @@ QUnit.test('save immediately before iframe is rendered in edit mode', async func '' + '', res_id: 1, - mockRPC: function (route, args) { - if (args.method === "write") { - assert.strictEqual(args.args[1].body, - '

toto toto toto

tata

', - "should save the content"); - } - return this._super.apply(this, arguments); - }, }); await testUtils.form.clickEdit(form); - var $field = form.$('.oe_form_field[name="body"]'); - var $iframe = $field.find('iframe'); - - await $iframe.data('loadDef'); await testUtils.nextTick(); - - var doc = $iframe.contents()[0]; - var $content = $('#iframe_target', doc); - var $editable = $content.find('.note-editable'); - - // select the text - var pText = $editable.find('p').first().contents()[0]; - Wysiwyg.setRange(pText, 1, pText, 10); - // text is selected - - await testUtils.dom.click($content.find('.note-toolbar .note-bg-color button:first').mousedown()); - await testUtils.dom.click($content.find('.note-toolbar .note-bg-color button[data-value="bg-gamma"]').mousedown()); - await testUtils.form.clickSave(form); + await testUtils.nextTick(); + assert.ok(true, "No traceback encountered. The wysiwyg was cut while not loaded."); form.destroy(); }); - QUnit.module('wrapper'); - - // todo add test wrapper - - QUnit.module('snippet (without iframe)'); - - QUnit.test('rendering with snippet panel', async function (assert) { - var done = assert.async(); - assert.expect(1); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - testUtils.mock.intercept(form, "snippets_loaded", function () { - assert.strictEqual(form.$('.oe_form_field #oe_snippets').length, 1, - "should display the snippet panel"); - form.destroy(); - done(); - }); - await testUtils.form.clickEdit(form); - }); - - QUnit.test('drag&drop snippet', async function (assert) { - assert.expect(1); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - var defSnippets = testUtils.makeTestPromise(); - testUtils.mock.intercept(form, "snippets_loaded", function () { - defSnippets.resolve(); - }); - - await testUtils.form.clickEdit(form); - var $field = form.$('.oe_form_field[name="body"]'); - var $editable = $field.find('.note-editable'); - - await defSnippets; - var $hr = $field.find('.oe_snippet_thumbnail:first'); - testUtils.dom.dragAndDrop($hr, $editable.find('p')); - - assert.strictEqual($editable.data('wysiwyg').getValue().replace(/\s+/g, ' '), - '

toto toto toto

tata

', - "should drop the snippet"); - - form.destroy(); - }); - - // todo add test snippet + customize snippet - - QUnit.module('snippet & cssEdit'); - - QUnit.test('rendering with snippet panel', async function (assert) { - var done = assert.async(); - assert.expect(1); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - testUtils.mock.intercept(form, "snippets_loaded", function () { - var doc = form.$('iframe').contents()[0]; - var $content = $('#iframe_target', doc); - assert.strictEqual($content.find('#oe_snippets').length, 1, - "should display the snippet panel"); - form.destroy(); - done(); - }); - await testUtils.form.clickEdit(form); - }); - - QUnit.test('drag&drop snippet', async function (assert) { - assert.expect(1); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - var defSnippets = testUtils.makeTestPromise(); - testUtils.mock.intercept(form, "snippets_loaded", function () { - defSnippets.resolve(); - }); - await testUtils.form.clickEdit(form); - - await defSnippets; - var doc = form.$('iframe').contents()[0]; - var $content = $('#iframe_target', doc); - var $editable = $content.find('.note-editable'); - - var $hr = $content.find('.oe_snippet_thumbnail:first'); - var from = $hr.offset(); - var to = $editable.find('p').offset(); - - $hr.trigger($.Event("mousedown", { - which: 1, - pageX: from.left + 1, - pageY: from.top + 1 - })); - $hr.trigger($.Event("mousemove", { - which: 1, - pageX: to.left, - pageY: to.top - })); - $hr.trigger($.Event("mouseup", { - which: 1, - pageX: to.left, - pageY: to.top - })); - - assert.strictEqual($editable.data('wysiwyg').getValue().replace(/\s+/g, ' '), - '

toto toto toto

tata

', - "should drop the snippet"); - - form.destroy(); - }); - - QUnit.test('drag&drop snippet options', async function (assert) { - var done = assert.async(); - assert.expect(6); - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - }); - var defSnippets = testUtils.makeTestPromise(); - testUtils.mock.intercept(form, "snippets_loaded", function () { - defSnippets.resolve(); - }); - - var defActivateSnippet; - testUtils.mock.intercept(form, "snippet_focused", function (e) { - defActivateSnippet.resolve(e.target); - }); - - await testUtils.form.clickEdit(form); - - defSnippets.then(function () { - var doc = form.$('iframe').contents()[0]; - var $content = $('#iframe_target', doc); - var $editable = $content.find('.note-editable'); - - function dropSnippet() { - defActivateSnippet = testUtils.makeTestPromise(); - - var $hr = $content.find('.oe_snippet_thumbnail:first'); - var from = $hr.offset(); - var to = $editable.find('p').offset(); - - $hr.trigger($.Event("mousedown", { - which: 1, - pageX: from.left + 1, - pageY: from.top + 1 - })); - $hr.trigger($.Event("mousemove", { - which: 1, - pageX: to.left, - pageY: to.top - })); - $hr.trigger($.Event("mouseup", { - which: 1, - pageX: to.left, - pageY: to.top - })); - } - - dropSnippet(); - defActivateSnippet.then(function (snippet) { - assert.strictEqual($editable.data('wysiwyg').getValue().replace(/\s+/g, ' '), - '

toto toto toto

tata

', - "should drop the snippet"); - - assert.strictEqual(snippet.$target.index(), 0, - 'should show the snippet editor for the first dropped block'); - - dropSnippet(); - defActivateSnippet.then(function (snippet) { - assert.strictEqual($editable.data('wysiwyg').getValue().replace(/\s+/g, ' '), - '

' + - '

' + - '

toto toto toto

tata

', - "should drop the snippet"); - - assert.strictEqual(snippet.$target.index(), 1, - 'should show the snippet editor for the second dropped block'); - - assert.strictEqual($('.oe_active .oe_overlay_options .btn:visible', doc).length, 4, - 'should show the snippet editor buttons'); - - defActivateSnippet = testUtils.makeTestPromise(); - $editable.find('hr:first').trigger('click'); - defActivateSnippet.then(function (snippet) { - - assert.strictEqual(snippet.$target.index(), 0, - 'should show the snippet editor for the first dropped block'); - - form.destroy(); - done(); - }); - }); - }); - }); - }); - QUnit.module('translation'); QUnit.test('field html translatable', async function (assert) { @@ -824,47 +411,6 @@ QUnit.test('save immediately before iframe is rendered in edit mode', async func await testUtils.form.clickEdit(form); var $button = form.$('.oe_form_field_html .o_field_translate'); assert.strictEqual($button.length, 1, "should have a translate button"); - $button.click(); - - form.destroy(); - _t.database.multi_lang = multiLang; - }); - - QUnit.test('field html translatable in iframe', async function (assert) { - assert.expect(2); - - var multiLang = _t.database.multi_lang; - _t.database.multi_lang = true; - - this.data['note.note'].fields.body.translate = true; - - var form = await testUtils.createView({ - View: FormView, - model: 'note.note', - data: this.data, - arch: '
' + - '' + - '', - res_id: 1, - mockRPC: function (route, args) { - if (route === '/web/dataset/call_button' && args.method === 'translate_fields') { - assert.deepEqual(args.args, ['note.note', 1, 'body'], "should call 'call_button' route"); - return Promise.resolve(); - } - return this._super.apply(this, arguments); - }, - }); - await testUtils.form.clickEdit(form); - var $field = form.$('.oe_form_field[name="body"]'); - var $iframe = $field.find('iframe'); - - await $iframe.data('loadDef'); - await testUtils.nextTick(); - var doc = $iframe.contents()[0]; - var $content = $('#iframe_target', doc); - - var $button = $content.find('.o_field_translate'); - assert.strictEqual($button.length, 1, "should have a translate button"); await testUtils.dom.click($button); form.destroy(); diff --git a/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js b/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js deleted file mode 100644 index cba62aef1c6..00000000000 --- a/addons/web_editor/static/tests/wysiwyg_keyboard_tests.js +++ /dev/null @@ -1,4423 +0,0 @@ -odoo.define('web_editor.wysiwyg.keyboard_tests', function (require) { -"use strict"; - -var weTestUtils = require('web_editor.test_utils'); - -//-------------------------------------------------------------------------- -// tests -//-------------------------------------------------------------------------- - -QUnit.module('web_editor', {}, function () { -QUnit.module('wysiwyg', {}, function () { - -//-------------------------------------------------------------------------- -// Unbreakable tests -//-------------------------------------------------------------------------- -QUnit.module('Unbreakable'); - -var unbreakableTestDom = [ - ' ', - ' content_a_0', - ' content_b_0', - ' ', - ' content_c_0', - ' content_d_0', - ' ', - ' content_e_0', - ' content_f_0', - ' content_e_1', - ' ', - ' content_c_4', - ' ', - ' content_g_0', - ' ', - ' content_h_0', - ' content_i_0', - ' content_h_2', - ' ', - ' ', - ' content_j_0', - ' content_k_0', - ' content_l_0', - ' content_j_4', - ' ', - ' ', - ' content_m_0', - ' content_n_0', - '' -].join('\n'); -var UnbreakableTests = [{ - name: "nothing to do", - content: unbreakableTestDom, - steps: [{ - start: "#c:contents()[0]->13", - end: "#c:contents()[0]->15", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->13", - end: "#c:contents()[0]->15", - }, - }, - { - name: "nothing to do 2", - content: unbreakableTestDom, - steps: [{ - start: "#j:contents()[0]->13", - end: "#l:contents()[0]->5", - }], - test: { - content: unbreakableTestDom, - start: "#j:contents()[0]->13", - end: "#l:contents()[0]->5", - }, - }, - { - name: "nothing to do 3", - content: unbreakableTestDom, - steps: [{ - start: "#k:contents()[0]->3", - end: "#l:contents()[0]->5", - }], - test: { - content: unbreakableTestDom, - start: "#k:contents()[0]->3", - end: "#l:contents()[0]->5", - }, - }, - { - name: "find the first allowed node", - content: unbreakableTestDom, - steps: [{ - start: "#a:contents()[0]->13", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->0", - end: "#c:contents()[0]->0", - }, - }, - { - name: "find the first allowed node and collapse the selection", - content: unbreakableTestDom, - steps: [{ - start: "#a:contents()[0]->10", - end: "#b:contents()[0]->3", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->0", - end: "#c:contents()[0]->0", - }, - }, - { - name: "resize the range to the allowed end", - content: unbreakableTestDom, - steps: [{ - start: "#a:contents()[0]->10", - end: "#c:contents()[0]->14", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->0", - end: "#c:contents()[0]->14", - }, - }, - { - name: "resize the range to the allowed start", - content: unbreakableTestDom, - steps: [{ - start: "#c:contents()[0]->15", - end: "#d:contents()[0]->4", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->15", - end: "#c:contents()[0]->37", - }, - }, - { - name: "resize the range to the allowed node that contains unbreakable node", - content: unbreakableTestDom, - steps: [{ - start: "#g:contents()[0]->5", - end: "#h:contents()[2]->15", - }], - test: { - content: unbreakableTestDom, - start: "#h:contents()[0]->0", - end: "#h:contents()[2]->15", - }, - }, - { - name: "resize the range to the allowed node between the start and the end", - content: unbreakableTestDom, - steps: [{ - start: "#e:contents()[0]->15", - end: "#c:contents()[4]->15", - }], - test: { - content: unbreakableTestDom, - start: "#f:contents()[0]->0", - end: "#f:contents()[0]->11", - }, - }, - { - name: "resize the range to the allowed start with the entirety of the unbreakable node", - content: unbreakableTestDom, - steps: [{ - start: "#c:contents()[0]->15", - end: "#e:contents()[0]->15", - }], - test: { - content: unbreakableTestDom, - start: "#c:contents()[0]->15", - end: "#d->1", - }, - }, - { - name: "resize the range to the allowed start and delete content", - content: unbreakableTestDom, - steps: [{ - start: "#c:contents()[0]->15", - end: "#e:contents()[0]->15", - key: "DELETE", - }], - test: { - content: unbreakableTestDom - // when we remove, we clean the invisible space before and after the deleted area - .replace(/>[\s]+content_c_0[\s\S]+content_d_0<\/noteditable>\s+/, '>co') - .replace(/^\s+/, ''), // corner effect of the clean and normalize - start: "#c:contents()[0]->2", - end: "#c:contents()[0]->2", - }, - }, - { - name: "delete unbreakable nodes in a breakable", - content: unbreakableTestDom, - steps: [{ - start: "#c:contents()[0]->15", - end: "#c:contents()[4]->19", - key: "DELETE", - }], - test: { - content: unbreakableTestDom - // when we remove, we clean the invisible space before and after the deleted area - .replace(/>[\s]+content_c_0[\s\S]*content_c_4\s*/, '>cot_c_4') - .replace(/^\s+/, ''), // corner effect of the clean and normalize - start: "#c:contents()[0]->2", - end: "#c:contents()[0]->2", - }, - }, - { - name: "select range with 2 nodes on the root", - content: unbreakableTestDom, - steps: [{ - start: "#m:contents()[0]->5", - end: "#n:contents()[0]->5", - }], - test: { - content: unbreakableTestDom, - start: "#m:contents()[0]->5", - end: "#n:contents()[0]->5", - }, - }, - { - name: "ENTER in an unbreakable p", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:contents()[0]->1", - key: 'ENTER', - }], - test: { - content: '

d
om to edit

', - start: "p:contents()[2]->0", - }, - }, -]; - -QUnit.test('Unbreakable selection and edition', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - useOnlyTestUnbreakable: true, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, UnbreakableTests).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -//-------------------------------------------------------------------------- -// Keyboard integration -//-------------------------------------------------------------------------- - -QUnit.module('Keyboard'); - -var keyboardTestsChar = [{ - name: "visible char in a p tag", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->3", - keyCode: 66, - }], - test: { - content: "

domB to edit

", - start: "p:contents()[0]->4", - end: null, - check: function ($editable, assert) { - assert.ok(true); - }, - }, - }, - { - name: "visible char in a link tag entirely selected", - content: '', - steps: [{ - start: "a:contents()[0]->0", - end: "a:contents()[0]->11", - key: 'a', - }], - test: { - content: '', - start: "a:contents()[0]->2", - }, - }, - { - name: "'a' on a selection of all the contents of a complex dom", - content: "

dom

to
completely
remove

", - steps: [{ - start: "p:contents()[0]->0", - end: "i:contents()[0]->1", - key: 'a', - }], - test: { - content: "

a

", - start: "b:contents()[0]->1", - }, - }, - { - name: "'a' on a selection of all the contents of a complex dom (2)", - content: "

dom toedit

", - steps: [{ - start: "font:contents()[0]->0", - end: "font:contents()[1]->4", - key: 'a', - }], - test: { - content: "

a

", - start: "b:contents()[0]->1", - }, - }, - { - name: "'a' before an image", - content: '

xxx yyy

', - steps: [{ - start: "p:contents()[0]->4", - key: 'a', - }], - test: { - content: '

xxx a yyy

', - start: "p:contents()[0]->5", - }, - }, - { - name: "'a' before an image (2)", - content: '

xxx yyy

', - steps: [{ - start: "img->0", - key: 'a', - }], - test: { - content: '

xxx a yyy

', - start: "p:contents()[0]->5", - }, - }, - { - name: "'a' before an image in table", - content: '

xxx

yyy

', - steps: [{ - start: "img->0", - key: 'a', - }], - test: { - content: '

xxx

a

yyy

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' on invisible text before an image in table", - content: '

xxx

yyy

', - steps: [{ - start: "p:eq(1)->0", - key: 'a', - }], - test: { - content: '

xxx

a

yyy

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' before an image in table without spaces", - content: '

xxx

yyy

', - steps: [{ - start: "img->0", - key: 'a', - }], - test: { - content: '

xxx

a

yyy

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' before an image in table without spaces (2)", - content: '

xxx

yyy

', - steps: [{ - start: "td:eq(1)->0", - key: 'a', - }], - test: { - content: '

xxx

a

yyy

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' before an image in table with spaces", - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

\n' + - '
\n' + - '

yyy

\n' + - '
', - steps: [{ - start: "img->0", - key: 'a', - }], - test: { - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

a

\n' + - '
\n' + - '

yyy

\n' + - '
', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' before an image in table with spaces (2)", - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

\n' + - '
\n' + - '

yyy

\n' + - '
', - steps: [{ - start: "td:eq(1)->1", - key: 'a', - }], - test: { - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

a

\n' + - '
\n' + - '

yyy

\n' + - '
', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' before an image in table with spaces (3)", - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

\n' + - '
\n' + - '

yyy

\n' + - '
', - steps: [{ - start: "td:eq(1):contents()[0]->12", - key: 'a', - }], - test: { - content: - '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - '
\n' + - '

xxx

\n' + - '
\n' + - '

a

\n' + - '
\n' + - '

yyy

\n' + - '
', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "'a' on begin of a span with fake_editable", - content: - '
\n' + - '
\n' + - ' \n' + - '
\n' + - '
', - steps: [{ - start: "span:contents(0)->10", - key: 'a', - }], - test: { - content: - '
\n' + - '
\n' + - ' \n' + - '
\n' + - '
', - start: "span:contents(0)->11", - }, - }, - { - name: "'a' on all contents of p starting with an icon", - content: '

bbb

', - steps: [{ - start: "span->0", - end: 'p:contents(1)->3', - key: 'a', - }], - test: { - content: '

a

', - start: "p:contents()[0]->1", - }, - }, - { - name: "' ' at start of p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->0", - key: ' ', - }], - test: { - content: '

 dom to edit

', - start: "p:contents()[0]->1", - }, - }, - { - name: "' ' at end of p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->11", - key: ' ', - }], - test: { - content: '

dom to edit 

', - start: "p:contents()[0]->12", - }, - }, - { - name: "' ' within p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->2", - key: ' ', - }], - test: { - content: '

do m to edit

', - start: "p:contents()[0]->3", - }, - }, - { - name: "' ' before space within p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->3", - key: ' ', - }], - test: { - content: '

dom  to edit

', - start: "p:contents()[0]->4", - }, - }, - { - name: "' ' after space within p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->4", - key: ' ', - }], - test: { - content: '

dom  to edit

', - start: "p:contents()[0]->5", - }, - }, - { - name: "3x ' ' at start of p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->0", - key: ' ', - }, { - key: ' ', - }, { - key: ' ', - }], - test: { - content: '

   dom to edit

', - start: "p:contents()[0]->3", - }, - }, - { - name: "3x ' ' at end of p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->11", - key: ' ', - }, { - key: ' ', - }, { - key: ' ', - }], - test: { - content: '

dom to edit   

', - start: "p:contents()[0]->14", - }, - }, - { - name: "3x ' ' within p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->2", - key: ' ', - }, { - key: ' ', - }, { - key: ' ', - }], - test: { - content: '

do   m to edit

', - start: "p:contents()[0]->5", - }, - }, - { - name: "3x ' ' before space in p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->3", - key: ' ', - }, { - key: ' ', - }, { - key: ' ', - }], - test: { - content: '

dom    to edit

', - start: "p:contents()[0]->6", - }, - }, - { - name: "3x ' ' after space in p", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->4", - key: ' ', - }, { - key: ' ', - }, { - key: ' ', - }], - test: { - content: '

dom    to edit

', - start: "p:contents()[0]->7", - }, - }, - { - name: "'a' in unbreakable with font", - content: '
dom to edit
', - steps: [{ - start: "div:contents(2)->2", - key: 'a', - }], - test: { - content: '
dom toa edit
', - start: "div:contents(2)->3", - }, - }, - { - name: "'a' on begin of unbreakable inline node", - content: 'dom to edit', - steps: [{ - start: "strong:contents(0)->0", - key: 'a', - }], - test: { - content: 'dom ato edit', - start: "strong:contents(0)->1", - }, - }, - { - name: "'a' on end of unbreakable inline node", - content: '
dom to edit
', - steps: [{ - start: "strong:contents(0)->2", - key: 'a', - }], - test: { - content: '
dom toa edit
', - start: "strong:contents(0)->3", - }, - }, - { - name: "'1' on begin of value of a field currency", - content: - '\n' + - '$ 750.00\n' + - '', - steps: [{ - start: "span:contents(0)->0", - key: '1', - }], - test: { - content: - '\n' + - '$ 1750.00\n' + - '', - start: "span:contents(0)->1", - }, - }, - { - name: "'1' on end of value of a field currency", - content: - '\n' + - '$ 750.00\n' + - '', - steps: [{ - start: "span:contents(0)->6", - key: '1', - }], - test: { - content: - '\n' + - '$ 750.001\n' + - '', - start: "span:contents(0)->7", - }, - }, - { - name: "'1' on begin of editable in noteditable", - content: - '\n' + - '$ 750.00\n' + - '', - steps: [{ - start: "span:contents(0)->0", - key: '1', - }], - test: { - content: - '\n' + - '$ 1750.00\n' + - '', - start: "span:contents(0)->1", - }, - }, - { - name: "'1' on end of editable in noteditable", - content: - '\n' + - '$ 750.00\n' + - '', - steps: [{ - start: "span:contents(0)->6", - key: '1', - }], - test: { - content: - '\n' + - '$ 750.001\n' + - '', - start: "span:contents(0)->7", - }, - }, - { - name: "'a' on editable with before&after in noteditable", - content: - '\n' + - '\n' + - '\n' + - '', - steps: [{ - start: "b->0", - key: 'a', - }], - test: { - content: - '\n' + - '\n' + - 'a\n' + - '', - start: "b:contents(0)->1", - }, - }, - { - name: "'a' in empty li", - content: '

', - steps: [{ - start: "p->1", - key: 'a', - }], - test: { - content: '
  • a

', - start: "p:contents(0)->1", - }, - }, -]; - -QUnit.test('Char', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsChar).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -var keyboardTestsEnter = [{ - name: "in p: ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - }], - test: { - content: "

d

om to edit

", - start: "p:contents()[1]->0", - }, - }, - { - name: "in p: 2x ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - }, { - key: 'ENTER', - }], - test: { - content: "

d


om to edit

", - start: "p:contents()[2]->0", - }, - }, - { - name: "in p: SHIFT+ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

d
om to edit

", - start: "p:contents()[2]->0", - }, - }, - { - name: "in empty-p: SHIFT+ENTER", - content: "


", - steps: [{ - start: "p->1", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "



", - start: "br:eq(1)->0", - }, - }, - { - name: "in p: 2x SHIFT+ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

d

om to edit

", - start: "p:contents()[3]->0", - }, - }, - { - name: "in empty-p: 2x SHIFT+ENTER", - content: "


", - steps: [{ - start: "p->1", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "




", - start: "br:eq(2)->0", - }, - }, - { - name: "in p: ENTER -> SHIFT+ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - }, { - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

d


om to edit

", - start: "p:eq(1):contents()[1]->0", - }, - }, - { - name: "in p: ENTER on selection", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:contents()[0]->7", - key: 'ENTER', - }], - test: { - content: "

d

edit

", - start: "p:contents()[1]->0", - end: "p:contents()[1]->0", - }, - }, - { - name: "in p: SHIFT+ENTER on selection", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:contents()[0]->7", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

d
edit

", - start: "p:contents()[2]->0", - }, - }, - - // list UL / OL - - { - name: "in li: SHIFT+ENTER at start", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

  • dom to edit
", - start: "li:contents()[1]->0", - }, - }, - { - name: "in li: SHIFT+ENTER within contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->5", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "
  • dom t
    o edit
", - start: "li:contents()[2]->0", - }, - }, - { - name: "in empty-li: SHIFT+ENTER", - content: "

", - steps: [{ - start: "li:contents()[0]->0", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "


", - start: "br:eq(1)->0", - }, - }, - { - name: "in li: SHIFT+ENTER on selection", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:contents()[0]->7", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "
  • d
    edit
", - start: "li:contents()[2]->0", - }, - }, - { - name: "in li: ENTER at start", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'ENTER', - }], - test: { - content: "

  • dom to edit
", - start: "li:contents()[1]->0", - }, - }, - { - name: "in li: ENTER within contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->5", - key: 'ENTER', - }], - test: { - content: "
  • dom t
  • o edit
", - start: "li:eq(1):contents()[0]->0", - }, - }, - { - name: "in li: ENTER on selection", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:contents()[0]->7", - key: 'ENTER', - }], - test: { - content: "
  • d
  • edit
", - start: "li:eq(1):contents()[0]->0", - }, - }, - { - name: "in li: ENTER on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'ENTER', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in li: ENTER -> 'a' on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "across 2 li: ENTER on partial selection", - content: "
  • dom to edit
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:eq(1):contents()[0]->4", - key: 'ENTER', - }], - test: { - content: "
  • d
  • to edit
", - start: "li:eq(1):contents()[0]->0", // we are after the
, the carret is on the li with an offset equal to the node length - }, - }, - { - name: "in li: ENTER at end", - content: "
  • dom to edit

", - steps: [{ - start: "p:contents()[0]->11", - key: 'ENTER', - }], - test: { - content: "
  • dom to edit


", - start: "br->0", - }, - }, - { - name: "in li: 2x ENTER at end", - content: "
  • dom to edit

", - steps: [{ - start: "p:contents()[0]->11", - key: 'ENTER', - }, { - key: 'ENTER', - }], - test: { - content: "
  • dom to edit


", - start: "br->0", - }, - }, - { - name: "in ul.list-group > li: ENTER at end", - content: '
  • dom to edit

', - steps: [{ - start: "p:contents()[0]->11", - key: 'ENTER', - }, { - key: 'ENTER', - }], - test: { - content: '
  • dom to edit



', - start: "p:eq(2) br->0", - }, - }, - { - name: "in indented-li: 2x ENTER at end", - content: "
  • aaa

    • dom to edit

  • bbb

", - steps: [{ - start: "ul ul p:contents()[0]->11", - key: 'ENTER', - }, { - key: 'ENTER', - }], - test: { - content: "
  • aaa

    • dom to edit


  • bbb

", - start: "p:eq(2) br->0", - }, - }, - { - name: "in indented-li with font: 2x ENTER at end", - content: "
  • aaa

    • dom to edit

  • bbb

", - steps: [{ - start: "font:contents()[0]->11", - key: 'ENTER', - }, { - key: 'ENTER', - }], - test: { - content: "
  • aaa

    • dom to edit


  • bbb

", - start: "p:eq(2) br->0", - }, - }, - { - name: "in li > empty-p: ENTER", - content: "

", - steps: [{ - start: "p:contents()[0]->0", - key: 'ENTER', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in li > p > empty-b: ENTER", - content: "

", - steps: [{ - start: "b:contents()[0]->0", - key: 'ENTER', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in ul.o_checklist > li.o_checked > p: ENTER at end", - content: '
  • test

', - steps: [{ - start: "p:contents()[0]->4", - key: 'ENTER', - }], - test: { - content: '
  • test


', - start: "br->0", - }, - }, - { - name: "in ul.o_checklist > li.o_checked > p > b: ENTER within text", - content: '
  • test

', - steps: [{ - start: "b:contents()[0]->2", - key: 'ENTER', - }], - test: { - content: '
  • te

  • st

', - start: "b:eq(1):contents()[0]->0", - }, - }, - - // end list UL / OL - - { - name: "after p > b: SHIFT+ENTER", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[1]->0", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

dom
 to edit

", - start: "p:contents()[2]->0", - }, - }, - { - name: "in p > b: ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->2", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

do

am to edit

", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "after p > b: ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[1]->0", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom

a to edit

", - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "after p > b: SHIFT+ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[1]->0", - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "

dom
a to edit

", - start: "p:contents()[2]->1", - }, - }, - { - name: "in p (other-p > span.a before - p > span.b after): ENTER at beginning", - content: "

dom to

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'ENTER', - }], - test: { - content: "

dom to


edit

", - start: "span:eq(2):contents()[0]->0", - }, - }, - { - name: "in p (other-p > span.a before - p > span.b after): ENTER -> 'a' at beginning", - content: "

dom to

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom to


aedit

", - start: "span:eq(2):contents()[0]->1", - }, - }, - { - name: "in p (other-p > span.a before - p > span.b after): SHIFT+ENTER at beginning", - content: "

dom to

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

dom to


edit

", - start: "span:eq(1):contents()[1]->0", - }, - }, - { - name: "in p (other-p > span.a before - p > span.b after): SHIFT+ENTER -> 'a' at beginning", - content: "

dom to

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "

dom to


aedit

", - start: "span:eq(1):contents()[1]->1", - }, - }, - { - name: "in p: ENTER on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'ENTER', - }], - test: { - content: "



", - start: "p:eq(1) br->0", - }, - }, - { - name: "in p: ENTER -> 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "


a

", - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in p: SHIFT+ENTER on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "



", - start: "br:eq(1)->0", - }, - }, - { - name: "in p: SHIFT+ENTER -> 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "


a

", - start: "p:contents()[1]->1", - }, - }, - { - name: "in p: 2x ENTER -> 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->3", - key: 'ENTER', - }, { - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom


a to edit

", - start: "p:eq(2):contents()[0]->1", - }, - }, - { - name: "in p > b: ENTER at start", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->0", - key: 'ENTER', - }], - test: { - content: "


dom to edit

", - start: "b:eq(1):contents()[0]->0", - }, - }, - { - name: "in p > b: ENTER", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - }], - test: { - content: "

dom

 to edit

", - start: "b:eq(1):contents()[0]->0", - }, - }, - { - name: "in p > b: SHIFT+ENTER -> ENTER", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }], - test: { - content: "

dom
​

 to edit

", - start: "b:eq(1):contents()[0]->0", - }, - }, - { - name: "in p > b: ENTER -> a'", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom

a to edit

", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in p > b: SHIFT+ENTER", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

dom
 to edit

", - start: "b:contents()[2]->0", - }, - }, - { - name: "in p > b: SHIFT+ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "

dom
a to edit

", - start: "b:contents()[2]->1", - }, - }, - { - name: "in p > b: SHIFT+ENTER -> ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom
​

a to edit

", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in span > b: ENTER", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - }], - test: { - content: "dom
​ to edit", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in span > b: SHIFT+ENTER -> ENTER", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }], - test: { - content: "dom

​ to edit", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in span > b: ENTER -> a'", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "dom
a to edit", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in span > b: SHIFT+ENTER", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "dom
 to edit
", - start: "b:contents()[2]->0", - }, - }, - { - name: "in span > b: SHIFT+ENTER -> 'a'", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "dom
a to edit
", - start: "b:contents()[2]->1", - }, - }, - { - name: "in span > b: SHIFT+ENTER -> ENTER -> 'a'", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "dom

a to edit", - start: "b:eq(1):contents()[0]->1", - }, - }, - { - name: "in p: 2x SHIFT+ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "

dom

a to edit

", - start: "p:contents()[3]->1", - }, - }, - { - name: "in p: ENTER -> SHIFT+ENTER -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->3", - key: 'ENTER', - }, { - key: 'ENTER', - shiftKey: true, - }, { - key: 'a', - }], - test: { - content: "

dom


a to edit

", - start: "p:eq(1):contents()[1]->1", - }, - }, - { - name: "in empty-p (p before and after): ENTER -> 'a'", - content: "

dom


to edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "

dom


a

to edit

", - start: "p:eq(2):contents()[0]->1", - }, - }, - { - name: "in p: SHIFT+ENTER at end", - content: "

dom

to edit

", - steps: [{ - start: "p:first:contents()[0]->4", - key: 'ENTER', - shiftKey: true, - }], - test: { - content: "

dom
​

to edit

", - start: "p:first:contents()[2]->0", - }, - }, - { - name: "in p: SHIFT+ENTER at end -> '寺'", - content: "

dom

to edit

", - steps: [{ - start: "p:first:contents()[0]->4", - key: 'ENTER', - shiftKey: true, - }, { - keyCode: 23546, /*temple in chinese*/ - }], - test: { - content: "

dom
寺

to edit

", - start: "p:first:contents()[2]->1", - }, - }, - { - name: "in empty-p (div > a after): 3x SHIFT+ENTER -> 'a'", - content: "


", - steps: [{ - start: "p->1", - key: 'ENTER', - shiftKey: true, - }, - { - key: 'ENTER', - shiftKey: true, - }, - { - key: 'ENTER', - shiftKey: true, - }, - { - key: 'a', - } - ], - test: { - content: "




a

", - start: "p:contents()[3]->1", - }, - }, - - // Buttons - - { - name: "in div > a.btn: ENTER -> 'a' at start (before invisible space)", - content: "", - steps: [{ - start: "a:contents()[0]->0", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - // split button has no text so the placeholder text is selected then replaced by 'a' - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' at start (after invisible space)", - content: "", - steps: [{ - start: "a:contents()[0]->1", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - // split button has no text so the placeholder text is selected then replaced by 'a' - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' within contents", - content: "", - steps: [{ - start: "a:contents()[0]->6", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' at end (before invisible space)", - content: "", - steps: [{ - start: "a:contents()[0]->12", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' at end (after invisible space)", - content: "", - steps: [{ - start: "a:contents()[0]->13", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > button.btn: ENTER -> 'a' at end (after invisible space)", - content: "
", - steps: [{ - start: "button:contents()[0]->13", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "
", - start: "button:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' on partial selection", - content: "", - steps: [{ - start: "a:contents()[0]->4", - end: "a:contents()[0]->8", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "in div > a.btn: ENTER -> 'a' on selection of all visible text", - content: "", - steps: [{ - start: "a:contents()[0]->0", - end: "a:contents()[0]->11", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "", - // Removing all text in a link replaces that text with "Label" - start: "a:eq(1):contents()[0]->2", - }, - }, - { - name: "across 2 a.btn: ENTER on selection across two a.btn", - content: "", - steps: [{ - start: "a:contents()[0]->0", - end: "a:eq(1):contents()[0]->11", - key: 'ENTER', - }], - test: { - content: "", - start: "a:eq(1):contents()[0]->1", - }, - }, -]; - -QUnit.test('Enter', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsEnter).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -var keyboardTestsComplex = [{ - name: "in span > b: SHIFT+ENTER -> BACKSPACE -> 'a'", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "doma to edit", - start: "b:contents()[0]->4", - }, - }, - { - name: "in span > b: SHIFT+ENTER -> ENTER -> BACKSPACE", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }, { - key: 'BACKSPACE', - }], - test: { - content: "dom
 to edit
", - start: "b:contents(2)->0", - }, - }, - { - name: "in span > b: SHIFT+ENTER -> ENTER -> BACKSPACE -> 'a'", - content: "dom to edit", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "dom
a to edit
", - start: "b:contents()[2]->1", - }, - }, - { - name: "in p > b: 2x SHIFT+ENTER -> BACKSPACE", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - shiftKey: true, - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom
 to edit

", - start: "b:contents()[2]->0", - }, - }, - { - name: "in p > b: 2x ENTER -> 2x BACKSPACE", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: false - }, { - key: 'ENTER', - shiftKey: false - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "b:contents()[0]->3", - }, - }, - { - name: "in empty-p: 2x ENTER -> 2x BACKSPACE", - content: "


", - steps: [{ - start: "p->1", - key: 'ENTER', - shiftKey: false - }, { - key: 'ENTER', - shiftKey: false - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "


", - start: "p:contents()[0]->0", - }, - }, - { - name: "in empty-p (p before): ENTER -> 2x BACKSPACE", - content: "

dom not to edit


", - steps: [{ - start: "p:eq(1)->1", - key: 'ENTER', - shiftKey: false - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom not to edit

", - start: "p:first:contents()[0]->15", - }, - }, - { - name: "in p > b: 2x SHIFT+ENTER -> BACKSPACE -> 'a'", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'ENTER', - shiftKey: true, - }, { - key: 'ENTER', - shiftKey: true, - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "

dom
a to edit

", - start: "b:contents()[2]->1", - }, - }, - { - name: "in li -> ENTER before br -> 'a'", - content: "
  • dom
     to edit

", - steps: [{ - start: "p:contents()[0]->3", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "
  • dom

  • a
     to edit

", - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in li -> ENTER after br -> 'a'", - content: "
  • dom
     to edit

", - steps: [{ - start: "p:contents()[2]->0", - key: 'ENTER', - }, { - key: 'a', - }], - test: { - content: "
  • dom
    ​

  • a to edit

", - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "within p (p before and after): 3x SHIFT+ENTER -> 3x BACKSPACE", - content: "

dom not to edit

dom to edit

dom not to edit

", - steps: [{ - start: "p:eq(1):contents()[0]->5", - key: 'ENTER', - shiftKey: true, - }, - { - key: 'ENTER', - shiftKey: true, - }, - { - key: 'ENTER', - shiftKey: true, - }, - { - key: 'BACKSPACE', - }, - { - key: 'BACKSPACE', - }, - { - key: 'BACKSPACE', - } - ], - test: { - content: "

dom not to edit

dom to edit

dom not to edit

", - start: "p:eq(1):contents()[0]->5", - }, - }, - { - name: "in h1.a > font: 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "h1->0", - end: "h1->1", - key: 'a', - }], - test: { - content: "

a

", - start: "font:contents()[0]->1", - }, - }, - { - name: "in complex-dom: BACKSPACE on partial selection (requires merging non-similar blocks)", - content: "

pif

paf

  • pouf

", - steps: [{ - start: 'p:contents()[0]->2', - end: 'i:contents()[0]->2', - key: 'BACKSPACE', - }], - test: { - content: '

pif

', - start: "p:contents()[0]->2", - }, - }, - { - name: "in complex-dom: DELETE on partial selection (requires merging non-similar blocks)", - content: "

pif

paf

  • pouf

", - steps: [{ - start: 'p:contents()[0]->2', - end: 'i:contents()[0]->2', - key: 'DELETE', - }], - test: { - content: '

pif

', - start: "p:contents()[0]->2", - }, - }, - - // paragraph outdent - - { - name: "in p (h1 before): TAB -> BACKSPACE at start (must indent then outdent)", - content: "

dom not to edit

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'TAB', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom not to edit

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p (h1 before): TAB -> 2x BACKSPACE at start (must indent then outdent, then merge blocks)", - content: "

dom not to edit

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'TAB', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom not to editdom to edit

", - start: "h1:contents()[0]->15", - }, - }, - { - name: "in ul > li > ul > 1st li > empty p (other ul li ul before): BACKSPACE at start", - content: '
  • 1

    • 2


  • 3

', - steps: [{ - start: "p:eq(2)->0", - key: 'BACKSPACE', - }], - test: { - content: '
  • 1

    • 2

  • 3

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in ul > li > p > text (li > text before): BACKSPACE at start", - content: '
  • 1
  • 2

  • 3
', - steps: [{ - start: "p:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: '
  • 1
  • 2

  • 3
', - start: "p:contents()[0]->1", - }, - }, - { - name: "in ul > li > p > text (li > text before): 3x BACKSPACE after first character", - content: '
  • 1
  • 2
  • 34

  • 5
', - steps: [{ - start: "p:contents()[0]->1", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: '
  • 1
  • 4

  • 5
', - start: "p:contents()[0]->0", - }, - }, - { - name: "in ul > li > text (li > p > text before): BACKSPACE at start", - content: '
  • 1
  • 2

  • 3
  • 4
', - steps: [{ - start: "li:eq(2):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: '
  • 1
  • 23

  • 4
', - start: "p:contents()[0]->1", - }, - }, - { - name: "in ul > li > text (li > p > text before): 3x BACKSPACE after first character", - content: '
  • 1
  • 2

  • 34
  • 5
', - steps: [{ - start: "li:eq(2):contents()[0]->1", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: '
  • 1
  • 4

  • 5
', - start: "p:contents()[0]->0", - }, - }, - { - name: "in ul > li > p > text (li > text after): DELETE at end", - content: '
  • 1

  • 2
  • 3
', - steps: [{ - start: "p->0", - key: 'DELETE', - }], - test: { - content: '
  • 1
  • 2

  • 3
', - start: "p:contents()[0]->0", - }, - }, - { - name: "in ul > li > p > text (li > text after): 3x DELETE before last character", - content: '
  • 1
  • 23

  • 4
  • 5
', - steps: [{ - start: "p:contents()[0]->1", - key: 'DELETE', - }, { - key: 'DELETE', - }, { - key: 'DELETE', - }], - test: { - content: '
  • 1
  • 2

  • 5
', - start: "p:contents()[0]->1", - }, - }, - { - name: "in ul > li > text (li > p > text after): DELETE at end", - content: '
  • 1
  • 2
  • 3

  • 4
', - steps: [{ - start: "li:eq(1):contents()[0]->1", - key: 'DELETE', - }], - test: { - content: '
  • 1
  • 23

  • 4
', - start: "p:contents()[0]->1", - }, - }, - { - name: "in ul > li > text (li > p > text after): 3x DELETE before last character", - content: '
  • 1
  • 23
  • 4

  • 5
', - steps: [{ - start: "li:eq(1):contents()[0]->1", - key: 'DELETE', - }, { - key: 'DELETE', - }, { - key: 'DELETE', - }], - test: { - content: '
  • 1
  • 2

  • 5
', - start: "p:contents()[0]->1", - }, - }, - { - name: "in ul.list-group (div > p > text before): BACKSPACE at start", - content: '

1


', - steps: [{ - start: "p:eq(1)->0", - key: 'BACKSPACE', - }], - test: { - content: '

1


', - start: "p:eq(1)->0", - }, - }, - // List indent - { - name: "ENTER -> TAB -> a' at end of li > p (split -> indent -> write)", - content: '
  • a

', - steps: [{ - start: "p:contents()[0]->1", - key: 'ENTER', - }, - { - key: 'TAB', - }, - { - key: 'a', - }], - test: { - content: '
  • a

    • a

', - start: "p:eq(1):contents()[0]->1", - }, - }, -]; - -QUnit.test('Complex', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsComplex).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -var keyboardTestsTab = [{ - name: "in li: TAB at start", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'TAB', - }], - test: { - content: "
    • dom to edit
", - start: "ul ul li:contents()[0]->0", - }, - }, - { - name: "in indented-li: SHIFT+TAB at start", - content: "
    • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'TAB', - shiftKey: true, - }], - test: { - content: "
  • dom to edit
", - start: "li:contents()[0]->0", - }, - }, - { - name: "in li: TAB within contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->5", - key: 'TAB', - }], - test: { - content: "
  • dom t    o edit
", - start: "li:contents()[0]->9", - }, - }, - { - name: "in li: SHIFT+TAB within contents (should do nothing)", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->5", - key: 'TAB', - shiftKey: true, - }], - test: { - content: "
  • dom to edit
", - start: "li:contents()[0]->5", - }, - }, - { - name: "in td > p: TAB within contents", - content: "

dom to edit

node

", - steps: [{ - start: "p:contents()[0]->5", - key: 'TAB', - }], - test: { - content: "

dom to edit

node

", - start: "td:eq(1) p:contents(0)->0", - }, - }, - { - name: "in p: TAB at start", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'TAB', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in indented-p: SHIFT+TAB at start", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'TAB', - shiftKey: true, - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p: TAB -> BACKSPACE at start", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'TAB', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p > b: TAB at start", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->0", - key: 'TAB', - }], - test: { - content: "

dom     to edit

", - start: "b:contents()[0]->4", - }, - }, - { - name: "in p > b: TAB -> BACKSPACE at start", - content: "

dom to edit

", - steps: [{ - start: "b:contents()[0]->0", - key: 'TAB', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom    to edit

", - start: "b:contents()[0]->3", - }, - }, -]; - -QUnit.test('Tab', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsTab).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -var keyboardTestsBackspace = [{ - name: "in p: BACKSPACE after span.fa", - content: '

aaabbb

', - steps: [{ - start: "p:contents()[2]->0", - key: 'BACKSPACE', - }], - test: { - content: '

aaabbb

', - start: "p:contents()[0]->3", - }, - }, - { - name: "in empty-p (no br): BACKSPACE (must insert br)", - content: "

", - steps: [{ - start: "p->0", - key: 'BACKSPACE', - }], - test: { - content: "


", // The br is there to ensure the carret can enter the p tag - start: "br->0", - }, - }, - { - name: "in empty-p: BACKSPACE (must leave it unchanged)", - content: "


", - steps: [{ - start: "p->1", - key: 'BACKSPACE', - }], - test: { - content: "


", // The br is there to ensure the carret can enter the p tag - start: "br->0", - }, - }, - { - name: "in p (empty-p before): BACKSPACE", - content: "


dom to edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p (empty-p.a before): BACKSPACE", - content: "


dom to edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p: BACKSPACE within text", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: "

dom o edit

", // The br is there to ensure the carret can enter the p tag - start: "p:contents()[0]->4", - }, - }, - { - name: "in p: 2x BACKSPACE within text", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

domo edit

", // The br is there to ensure the carret can enter the p tag - start: "p:contents()[0]->3", - }, - }, - { - name: "in p (p > span.a before - span.b after): BACKSPACE at beginning (must attach them)", - content: "

dom to

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom toedit

", - start: "span:eq(0):contents()[0]->6", - }, - }, - { - name: "in p (p > span.a before - span.a after): BACKSPACE (must merge them)", - content: "

dom to 

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "span:contents()[0]->7", - }, - }, - { - name: "in p (b before): BACKSPACE", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[1]->0", - key: 'BACKSPACE', - }], - test: { - content: "

do to edit

", - start: "b:contents()[0]->2", - }, - }, - { - name: "in p (div > span.a before - span.a after): BACKSPACE at beginning (must do nothing)", - content: "
dom to 

edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
dom to 

edit

", - start: "span:eq(1):contents()[0]->0", - }, - }, - { - name: "in p: BACKSPACE on partial selection", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:contents()[0]->7", - key: 'BACKSPACE', - }], - test: { - content: "

dedit

", - start: "p:contents()[0]->1", - }, - }, - { - name: "across 2 p's: BACKSPACE on partial selection", - content: "

dom

to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:eq(1):contents()[0]->3", - key: 'BACKSPACE', - }], - test: { - content: "

dedit

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in p: BACKSPACE within text, with space at beginning", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->10", - key: 'BACKSPACE', - }], - test: { - content: "

dom o edit

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in p: BACKSPACE within text, with one space at beginning", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->6", - key: 'BACKSPACE', - }], - test: { - content: "

 dom o edit

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: BACKSPACE within text, with space at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: "

dom o edit

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in p: BACKSPACE within text, with one space at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: "

dom o edit 

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in p: BACKSPACE within text, with space at beginning and end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->10", - key: 'BACKSPACE', - }], - test: { - content: "

dom o edit

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in p: BACKSPACE within text, with one space at beginning and one at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->6", - key: 'BACKSPACE', - }], - test: { - content: "

 dom o edit 

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: BACKSPACE after \\w
\\w", - content: "

dom to edi
t

", - steps: [{ - start: "p:contents()[2]->1", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edi
​

", - start: "p:contents()[2]->1", - }, - }, - { - name: "in p: BACKSPACE -> 'a' within text, after \\s\\w", - content: "

dom t

", - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "

dom a

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in pre: BACKSPACE within text, with space at beginning", - content: "
     dom to edit
", - steps: [{ - start: "pre:contents()[0]->10", - key: 'BACKSPACE', - }], - test: { - content: "
     dom o edit
", - start: "pre:contents()[0]->9", - }, - }, - { - name: "in pre: BACKSPACE within text, with one space at beginning", - content: "
 dom to edit
", - steps: [{ - start: "pre:contents()[0]->6", - key: 'BACKSPACE', - }], - test: { - content: "
 dom o edit
", - start: "pre:contents()[0]->5", - }, - }, - { - name: "in pre: BACKSPACE within text, with space at end", - content: "
dom to edit     
", - steps: [{ - start: "pre:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: "
dom o edit     
", - start: "pre:contents()[0]->4", - }, - }, - { - name: "in pre: BACKSPACE within text, with one space at end", - content: "
dom to edit 
", - steps: [{ - start: "pre:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: "
dom o edit 
", - start: "pre:contents()[0]->4", - }, - }, - { - name: "in pre: BACKSPACE within text, with space at beginning and end", - content: "
     dom to edit     
", - steps: [{ - start: "pre:contents()[0]->10", - key: 'BACKSPACE', - }], - test: { - content: "
     dom o edit     
", - start: "pre:contents()[0]->9", - }, - }, - { - name: "in pre: BACKSPACE within text, with one space at beginning and one at end", - content: "
 dom to edit 
", - steps: [{ - start: "pre:contents()[0]->6", - key: 'BACKSPACE', - }], - test: { - content: "
 dom o edit 
", - start: "pre:contents()[0]->5", - }, - }, - - // list UL / OL - - { - name: "from p to ul > li: BACKSPACE on whole list", - content: "

dom not to edit

  • dom to edit

", - steps: [{ - start: "p:contents()[0]->15", - end: "p:eq(1):contents()[0)->11", - key: 'BACKSPACE', - }], - test: { - content: "

dom not to edit

", - start: "p:contents()[0]->15", - }, - }, - { - name: "in ul > second-li > p: BACKSPACE within text", - content: "
  • dom to

  • edit

", - steps: [{ - start: "p:eq(1):contents()[0]->4", - key: 'BACKSPACE', - }], - test: { - content: "
  • dom to

  • edi

", - start: "p:eq(1):contents()[0]->3", - }, - }, - { - name: "in ul > second-li > empty-p: BACKSPACE at beginning", - content: "


", - steps: [{ - start: "p:eq(1)->1", - key: 'BACKSPACE', - }], - test: { - content: "

", - start: "p:first:contents()[0]->0", - }, - }, - { - name: "in ul > indented-li (no other li - p before): BACKSPACE at beginning", - content: "

dom to

    • edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to

  • edit
", - start: "li:contents()[0]->0", - }, - }, - { - name: "in ul > indented-li (no other li - p before): BACKSPACE -> 'a' at beginning", - content: "

dom to

    • edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "

dom to

  • aedit
", - start: "li:contents()[0]->1", - }, - }, - { - name: "in ul > indented-li (no other li - none before): BACKSPACE at beginning", - content: "
    • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
  • dom to edit
", - start: "li:contents()[0]->0", - }, - }, - { - name: "in li: BACKSPACE on partial selection", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:contents()[0]->7", - key: 'BACKSPACE', - }], - test: { - content: "
  • dedit
", - start: "li:contents()[0]->1", - }, - }, - { - name: "across 2 li: BACKSPACE on partial selection", - content: "
  • dom to edit
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:eq(1):contents()[0]->7", - key: 'BACKSPACE', - }], - test: { - content: "
  • dedit
", - start: "li:contents()[0]->1", - }, - }, - { - name: "in li (no other li): BACKSPACE on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'BACKSPACE', - }], - test: { - content: "

", - start: "li->0", - }, - }, - { - name: "in li (no other li): BACKSPACE -> 'a' on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "
  • a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in empty-li: BACKSPACE (must remove list)", - content: "

", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in empty-li (no other li - empty-p before): BACKSPACE -> 'a'", - content: "



", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "


a

", - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in empty-li (no other li - p before): BACKSPACE", - content: "

toto


", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

toto


", - start: "br->0", - }, - }, - { - name: "in li (no other li - p before): BACKSPACE at start", - content: "

toto

  •  
", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

toto

 

", - start: "p:eq(1):contents()[0]->0", - }, - }, - { - name: "in empty-indented-li (other li - no other indented-li): BACKSPACE", - content: "
  • toto


  • tutu

", - steps: [{ - start: "ul ul li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
  • toto


  • tutu

", - start: "li:eq(1) br->0", - }, - }, - { - name: "in empty-indented-li (other li - other indented-li): BACKSPACE", - content: "
  • toto



  • tutu

", - steps: [{ - start: "ul ul li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
  • toto



  • tutu

", - start: "li:eq(1) br->0", - }, - }, - { - name: "in empty-indented-li (no other li, no other indented-li): BACKSPACE", - content: "

", - steps: [{ - start: "li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

", - start: "br->0", - }, - }, - { - name: "in indented-li (other li, other indented-li): BACKSPACE at start", - content: "
  • toto

    • xxx

    • yyy

  • tutu

", - steps: [{ - start: "ul ul li:contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
  • toto

  • xxx

    • yyy

  • tutu

", - start: "p:eq(1):contents()[0]->0", - }, - }, - { - name: "in li > second-p: BACKSPACE at start", - content: "
  • toto

  • xxx

    yyy

  • tutu

", - steps: [{ - start: "li:eq(1) p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "
  • toto

  • xxxyyy

  • tutu

", - start: "li:eq(1) p:contents()[0]->3", - }, - }, - { - name: "in li (li after): BACKSPACE at start, with spaces", - content: "

dom to edit 

  •   dom to edit

  • dom not to edit

", - steps: [{ - start: "p:eq(1):contents()[0]->6", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit dom to edit

  • dom not to edit

", - start: "p:contents()[0]->12", - }, - }, - { - name: "in li > p: BACKSPACE after single character", - content: "
  • a

", - steps: [{ - start: "p:contents()[0]->1", - key: 'BACKSPACE', - }], - test: { - content: "

", - start: "br->0", - }, - }, - { - name: "in li > p: BACKSPACE -> 'a' after single character", - content: "
  • a

", - steps: [{ - start: "p:contents()[0]->1", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "
  • a

", - start: "p:contents()[0]->1", - }, - }, - - // end list UL / OL - - { - name: "in p: BACKSPACE on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'BACKSPACE', - }], - test: { - content: "


", - start: "p->0", - }, - }, - { - name: "in p: BACKSPACE -> 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: "

a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in complex-dom: BACKSPACE on selection of most contents", - content: "

dom

to
partially
remove

", - steps: [{ - start: "b:contents()[0]->2", - end: "i:contents()[0]->1", - key: 'BACKSPACE', - }], - test: { - content: "

doove

", - start: "b:contents()[0]->2", - }, - }, - { - name: "in complex-dom: BACKSPACE on selection of all contents", - content: "

dom

to
completely
remove

", - steps: [{ - start: "p:contents()[0]->0", - end: "i:contents()[0]->1", - key: 'BACKSPACE', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in p: BACKSPACE after br", - content: "

dom
to edit

", - steps: [{ - start: "p:contents()[2]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in complex-dom (span > b -> ENTER in contents)", - content: "dom

 to edit", - steps: [{ - start: "b:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "dom
 to edit
", - start: "b:contents(2)->0", - }, - }, - { - name: "in complex-dom (span > b -> ENTER in contents): 2 x BACKSPACE", - content: "dom

a to edit", - steps: [{ - start: "b:eq(1):contents()[0]->1", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "dom
 to edit
", - start: "b:contents(2)->0", - }, - }, - { - name: "in p (hr before): BACKSPACE", - content: '

aaa


bbb

', - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: '

aaabbb

', - start: "p:contents()[0]->3", - }, - }, - { - name: "in p with multi br[id] (p before and after) (1)", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "p:eq(1)->2", - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit




dom not to edit

', - start: "p:eq(1)->1", - }, - }, - { - name: "in p with multi br[id] (p before and after) (2)", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "br:eq(2)->0", - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit




dom not to edit

', - start: "p:eq(1)->1", - }, - }, - { - name: "in p with multi br[id] (p before and after): 2x BACKSPACE", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "p:eq(1)->2", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit



dom not to edit

', - start: "p:eq(1)->0", - }, - }, - { - name: "in p with multi br (p before and after) (1)", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "p:eq(1)->2", - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit




dom not to edit

', - start: "p:eq(1)->1", - }, - }, - { - name: "in p with multi br (p before and after) (2)", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "br:eq(2)->0", - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit




dom not to edit

', - start: "p:eq(1)->1", - }, - }, - { - name: "in p with multi br (p before and after): 2x BACKSPACE", - content: '

dom not to edit





dom not to edit

', - steps: [{ - start: "p:eq(1)->2", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: '

dom not to edit



dom not to edit

', - start: "p:eq(1)->0", - }, - }, - { - name: "in p: BACKSPACE within text after \w+
", - content: '

dom to
edit

', - steps: [{ - start: "p:contents()[2]->3", - key: 'BACKSPACE', - }], - test: { - content: '

dom to
edt

', - start: "p:contents()[2]->2", - }, - }, - - // table - - { - name: "in empty-td (td before): BACKSPACE -> 'a' at start", - content: '



', - steps: [{ - start: "p:eq(1)->1", - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: '


a

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in td (td before): 2x BACKSPACE -> 'a' after first character", - content: '

dom not to edit

dom to edit

', - steps: [{ - start: "p:eq(1):contents()[0]->1", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: '

dom not to edit

aom to edit

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in td (no other td): BACKSPACE within text", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->5", - key: 'BACKSPACE', - }], - test: { - content: '

dom o edit

', - start: "p:contents()[0]->4", - }, - }, - { - name: "in complex-dom (empty-td (td before) -> 2x SHIFT-ENTER): 3x BACKSPACE -> 'a'", - content: '

dom not to edit




', - steps: [{ - start: 'p:eq(1)->3', - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: '

dom not to edit

a

', - start: "p:eq(1):contents()[0]->1", - }, - }, - { - name: "in h1: BACKSPACE on full selection -> 'a'", - content: '

dom to delete

', - steps: [{ - start: 'h1:contents()[0]->0', - end: 'h1:contents()[0]->13', - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: '

a

', - start: "h1:contents()[0]->1", - }, - }, - { - name: "in h1: BACKSPACE on full selection -> BACKSPACE -> 'a'", - content: '

dom to delete

', - steps: [{ - start: 'h1:contents()[0]->0', - end: 'h1:contents()[0]->13', - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }, { - key: 'a', - }], - test: { - content: '

a

', - start: "p:contents()[0]->1", - }, - }, - { - name: "in h1: BACKSPACE on full selection -> DELETE -> 'a'", - content: '

dom to delete

', - steps: [{ - start: 'h1:contents()[0]->0', - end: 'h1:contents()[0]->13', - key: 'BACKSPACE', - }, { - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: '

a

', - start: "h1:contents()[0]->1", - }, - }, - - // merging non-similar blocks - - { - name: "in p (h1 before): BACKSPACE at start", - content: '

node to merge with

node to merge

', - steps: [{ - start: 'p:contents()[0]->0', - key: 'BACKSPACE', - }], - test: { - content: '

node to merge withnode to merge

', - start: "h1:contents()[0]->18", - }, - }, - { - name: "in empty-p (h1 before): BACKSPACE", - content: "

dom to edit


", - steps: [{ - start: "p->1", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "h1:contents()[0]->11", - }, - }, - { - name: "in empty-p (h1 before): 2x BACKSPACE", - content: "

dom to edit


", - steps: [{ - start: "p->1", - key: 'BACKSPACE', - }, { - key: 'BACKSPACE', - }], - test: { - content: "

dom to edi

", - start: "h1:contents()[0]->10", - }, - }, - { - name: "in p (ul before): BACKSPACE at start", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'p:eq(1):contents()[0]->0', - key: 'BACKSPACE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "p:contents()[0]->18", - }, - }, - { - name: "in p > b (ul before, i after): BACKSPACE at start", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'b:contents()[0]->0', - key: 'BACKSPACE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "p:contents()[0]->18", - }, - }, - { - name: "in p > b (ul > i before, i after): BACKSPACE at start", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'b:contents()[0]->0', - key: 'BACKSPACE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "i:contents()[0]->18", - }, - }, - { - name: "in p.c (p.a > span.b before - span.b after): BACKSPACE at beginning", - content: "

dom to 

edit

", - steps: [{ - start: "p:eq(1):contents()[0]->0", - key: 'BACKSPACE', - }], - test: { - content: "

dom to edit

", - start: "span:eq(0):contents()[0]->7", - }, - }, - { - name: "from h1 to p: BACKSPACE", - content: '

node to merge with

node to merge

', - steps: [{ - start: 'h1:contents()[0]->5', - end: 'p:contents()[0]->2', - key: 'BACKSPACE', - }], - test: { - content: '

node de to merge

', - start: "h1:contents()[0]->5", - }, - }, - { - name: "from h1 to p: BACKSPACE at start", - content: '

node to merge with

node to merge

', - steps: [{ - start: 'b:contents()[0]->0', - end: 'p:contents()[0]->2', - key: 'BACKSPACE', - }], - test: { - content: '

de to merge

', - start: "p:contents()[0]->0", - }, - }, -]; - -QUnit.test('Backspace', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsBackspace).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -var keyboardTestsDelete = [{ - name: "in empty-p (no br): DELETE (must insert br)", - content: "

", - steps: [{ - start: "p->0", - key: 'DELETE', - }], - test: { - content: "


", // The br is there to ensure the carret can enter the p tag - start: "br->0", - }, - }, - { - name: "in empty-p: DELETE (must leave it unchanged)", - content: "


", - steps: [{ - start: "p->0", - key: 'DELETE', - }], - test: { - content: "


", // The br is there to ensure the carret can enter the p tag - start: "p->0", - }, - }, - { - name: "in empty-p: DELETE (must leave it unchanged) (2)", - content: "

\n
\n

", - steps: [{ - start: "p->1", - key: 'DELETE', - }], - test: { - content: "

\n
\n

", // The br is there to ensure the carret can enter the p tag - start: "p:contents()[1]->0", - }, - }, - { - name: "in empty-p (p after): DELETE", - content: "


dom to edit

", - steps: [{ - start: "p->0", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in empty-p (p after): DELETE (2)", - content: "

\n
\n

\n dom to edit

", - steps: [{ - start: "p:contents()[1]->0", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in empty-p.a (p after): DELETE", - content: "


dom to edit

", - steps: [{ - start: "p->0", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in empty-p.a (p after): DELETE (2)", - content: "


dom to edit

", - steps: [{ - start: "p->1", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->0", - }, - }, - { - name: "in p: DELETE at start", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'DELETE', - }], - test: { - content: "

om to edit

", // The br is there to ensure the carret can enter the p tag - start: "p:contents()[0]->0", - }, - }, - { - name: "in p: 2x DELETE at start", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - key: 'DELETE', - }, { - key: 'DELETE', - }], - test: { - content: "

m to edit

", // The br is there to ensure the carret can enter the p tag - start: "p:contents()[0]->0", - }, - }, - { - name: "in p: DELETE within text", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'DELETE', - }], - test: { - content: "

dom t edit

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: DELETE within text, with space at beginning", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->10", - key: 'DELETE', - }], - test: { - content: "

dom t edit

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: DELETE within text, with one space at beginning", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->6", - key: 'DELETE', - }], - test: { - content: "

 dom t edit

", - start: "p:contents()[0]->6", - }, - }, - { - name: "in p: DELETE within text, with space at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'DELETE', - }], - test: { - content: "

dom t edit

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: DELETE within text, with one space at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->5", - key: 'DELETE', - }], - test: { - content: "

dom t edit 

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: DELETE within text, with space at beginning and end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->10", - key: 'DELETE', - }], - test: { - content: "

dom t edit

", - start: "p:contents()[0]->5", - }, - }, - { - name: "in p: DELETE within text, with one space at beginning and one at end", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->6", - key: 'DELETE', - }], - test: { - content: "

 dom t edit 

", - start: "p:contents()[0]->6", - }, - }, - { - name: "in p: DELETE -> 'a' within text, before \\w\\s", - content: "

dom t

", - steps: [{ - start: "p:contents()[0]->2", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "

doa t

", - start: "p:contents()[0]->3", - }, - }, - { - name: "in pre: DELETE within text, with space at beginning", - content: "
     dom to edit
", - steps: [{ - start: "pre:contents()[0]->10", - key: 'DELETE', - }], - test: { - content: "
     dom t edit
", - start: "pre:contents()[0]->10", - }, - }, - { - name: "in pre: DELETE within text, with one space at beginning", - content: "
 dom to edit
", - steps: [{ - start: "pre:contents()[0]->6", - key: 'DELETE', - }], - test: { - content: "
 dom t edit
", - start: "pre:contents()[0]->6", - }, - }, - { - name: "in pre: DELETE within text, with space at end", - content: "
dom to edit     
", - steps: [{ - start: "pre:contents()[0]->5", - key: 'DELETE', - }], - test: { - content: "
dom t edit     
", - start: "pre:contents()[0]->5", - }, - }, - { - name: "in pre: DELETE within text, with one space at end", - content: "
dom to edit 
", - steps: [{ - start: "pre:contents()[0]->5", - key: 'DELETE', - }], - test: { - content: "
dom t edit 
", - start: "pre:contents()[0]->5", - }, - }, - { - name: "in pre: DELETE within text, with space at beginning and end", - content: "
     dom to edit     
", - steps: [{ - start: "pre:contents()[0]->10", - key: 'DELETE', - }], - test: { - content: "
     dom t edit     
", - start: "pre:contents()[0]->10", - }, - }, - { - name: "in pre: DELETE within text, with one space at beginning and one at end", - content: "
 dom to edit 
", - steps: [{ - start: "pre:contents()[0]->6", - key: 'DELETE', - }], - test: { - content: "
 dom t edit 
", - start: "pre:contents()[0]->6", - }, - }, - - // list UL / OL - - { - name: "in empty-li (no other li): DELETE (must do nothing)", - content: "

", - steps: [{ - start: "li:contents()[0]->0", - key: 'DELETE', - }], - test: { - content: "

", - start: "li->0", - }, - }, - { - name: "from p to li > p: DELETE on whole list", - content: "

dom not to edit

  • dom to edit

", - steps: [{ - start: "p:contents()[0]->15", - end: "p:eq(1):contents()[0)->11", - key: 'DELETE', - }], - test: { - content: "

dom not to edit

", - start: "p:contents()[0]->15", - }, - }, - { - name: "in empty-li (no other li): DELETE -> 'a' (must write into it)", - content: "

", - steps: [{ - start: "li:contents()[0]->0", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "
  • a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in li (li after): DELETE at end (must move contents of second li to carret)", - content: "
  • dom to 
  • edit
", - steps: [{ - start: "li:contents()[0]->7", - key: 'DELETE', - }], - test: { - content: "
  • dom to edit
", - start: "li:contents()[0]->7", - }, - }, - { - name: "in li (li after): DELETE -> 'a' at end (must move contents of second li to carret, then write)", - content: "
  • dom to 
  • edit
", - steps: [{ - start: "li:contents()[0]->7", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "
  • dom to aedit
", - start: "li:contents()[0]->8", - }, - }, - { - name: "in li > p: DELETE before single character", - content: "
  • a

", - steps: [{ - start: "p:contents()[0]->0", - key: 'DELETE', - }], - test: { - content: "

", - start: "br->0", - }, - }, - { - name: "in li > p: DELETE -> 'a' before single character", - content: "
  • a

", - steps: [{ - start: "p:contents()[0]->0", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "
  • a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in li > p (p after): DELETE at end", - content: "
  • toto

  • xxx

    yyy

  • tutu

", - steps: [{ - start: "li:eq(1) p:eq(0):contents()[0]->3", - key: 'DELETE', - }], - test: { - content: "
  • toto

  • xxxyyy

  • tutu

", - start: "li:eq(1) p:eq(0):contents()[0]->3", - }, - }, - { - name: "in li > p (b before - p after): DELETE at end", - content: "
  • toto

  • xxx

    yyy

  • tutu

", - steps: [{ - start: "li:eq(1) p:eq(0):contents()[1]->2", - key: 'DELETE', - }], - test: { - content: "
  • toto

  • xxxyyy

  • tutu

", - start: "li:eq(1) p:eq(0):contents()[1]->2", - }, - }, - { - name: "in li > p (p.o_default_snippet_text after): DELETE at end", - content: '
  • toto

  • xxx

    yyy

  • tutu

', - steps: [{ - start: "li:eq(1) p:eq(0):contents()[0]->3", - key: 'DELETE', - }], - test: { - content: "
  • toto

  • xxxyyy

  • tutu

", - start: "li:eq(1) p:eq(0):contents()[0]->3", - }, - }, - { - name: "in indented-ul > li: DELETE at end (must do nothing)", - content: "
    • dom to edit
", - steps: [{ - start: "li:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "
    • dom to edit
", - start: "li:contents()[0]->11", - }, - }, - { - name: "in indented-ul > li: DELETE at end -> 'a' at end (must write)", - content: "
    • dom to edit
", - steps: [{ - start: "li:contents()[0]->11", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "
    • dom to edita
", - start: "li:contents()[0]->12", - }, - }, - { - name: "in indented-ul > li (non-indented-li after): DELETE at end", - content: "
    • dom to edit
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "
    • dom to editdom to edit
", - start: "li:contents()[0]->11", - }, - }, - { - name: "in ul > li (indented-li after): DELETE at end", - content: "
  • dom to edit
    • dom to edit
", - steps: [{ - start: "li:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "
  • dom to editdom to edit
", - start: "li:contents()[0]->11", - }, - }, - { - name: "in li: DELETE on partial selection", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:contents()[0]->7", - key: 'DELETE', - }], - test: { - content: "
  • dedit
", - start: "li:contents()[0]->1", - }, - }, - { - name: "across 2 li: DELETE on partial selection", - content: "
  • dom to edit
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->1", - end: "li:eq(1):contents()[0]->7", - key: 'DELETE', - }], - test: { - content: "
  • dedit
", - start: "li:contents()[0]->1", - }, - }, - { - name: "in li: DELETE on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "

", - start: "li->0", - }, - }, - { - name: "in li: DELETE -> 'a' on selection of all contents", - content: "
  • dom to edit
", - steps: [{ - start: "li:contents()[0]->0", - end: "li:contents()[0]->11", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "
  • a

", - start: "p:contents()[0]->1", - }, - }, - - // end list UL / OL - - { - name: "in p (b before): DELETE", - content: "

domto edit

", - steps: [{ - start: "b:contents()[0]->3", - key: 'DELETE', - }], - test: { - content: "

domo edit

", - start: "p:contents(1)->0", - }, - }, - { - name: "in p > span.a (div > span.a after): DELETE at end (must do nothing)", - content: "

dom to

edit
", - steps: [{ - start: "span:contents()[0]->6", - key: 'DELETE', - }], - test: { - content: "

dom to

edit
", - start: "span:contents()[0]->6", - }, - }, - { - name: "in p: DELETE on partial selection", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:contents()[0]->7", - key: 'DELETE', - }], - test: { - content: "

dedit

", - start: "p:contents()[0]->1", - }, - }, - { - name: "across 2 p: DELETE on partial selection", - content: "

dom

to edit

", - steps: [{ - start: "p:contents()[0]->1", - end: "p:eq(1):contents()[0]->3", - key: 'DELETE', - }], - test: { - content: "

dedit

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in p: DELETE on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "


", - start: "p->0", - }, - }, - { - name: "in p: DELETE -> 'a' on selection of all contents", - content: "

dom to edit

", - steps: [{ - start: "p:contents()[0]->0", - end: "p:contents()[0]->11", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: "

a

", - start: "p:contents()[0]->1", - }, - }, - { - name: "in p: DELETE before br", - content: "

dom
to edit

", - steps: [{ - start: "p:contents()[0]->4", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "p:contents()[0]->4", - }, - }, - { - name: "in complex-dom: DELETE on selection of most contents", - content: "

dom

to
partially
remove

", - steps: [{ - start: "b:contents()[0]->2", - end: "i:contents()[0]->1", - key: 'DELETE', - }], - test: { - content: "

doove

", - start: "b:contents()[0]->2", - }, - }, - { - name: "in complex-dom: DELETE on selection of all contents", - content: "

dom

to
completely
remove

", - steps: [{ - start: "p:contents()[0]->0", - end: "i:contents()[0]->1", - key: 'DELETE', - }], - test: { - content: "


", - start: "br->0", - }, - }, - { - name: "in complex-dom (span > b -> ENTER): DELETE", - content: "dom
to edit", - steps: [{ - start: "b:eq(0):contents()[0]->3", - key: 'DELETE', - }], - test: { - content: "dom to edit", - start: "b:contents()[0]->3", - }, - }, - { - name: "in p (span.fa after): DELETE", - content: '

aaabbb

', - steps: [{ - start: "p:contents()[0]->3", - key: 'DELETE', - }], - test: { - content: '

aaabbb

', - start: "p:contents()[0]->3", - }, - }, - { - name: "in p (hr after): DELETE", - content: '

aaa


bbb

', - steps: [{ - start: "p:eq(0):contents()[0]->3", - key: 'DELETE', - }], - test: { - content: '

aaabbb

', - start: "p:contents()[0]->3", - }, - }, - - // table - - { - name: "in empty-td (td after): DELETE -> 'a' at start", - content: '



', - steps: [{ - start: "p->1", - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: '

a


', - start: "p:contents()[0]->1", - }, - }, - { - name: "in td (td after): 2x DELETE -> 'a' after first character", - content: '

dom to edit

dom not to edit

', - steps: [{ - start: "p:contents()[0]->1", - key: 'DELETE', - }, { - key: 'DELETE', - }, { - key: 'a', - }], - test: { - content: '

da to edit

dom not to edit

', - start: "p:contents()[0]->2", - }, - }, - { - name: "in td: DELETE within text", - content: '

dom to edit

', - steps: [{ - start: "p:contents()[0]->4", - key: 'DELETE', - }], - test: { - content: '

dom o edit

', - start: "p:contents()[0]->4", - }, - }, - - // merging non-similar blocks - - { - name: "in p (ul after, with spaces): DELETE at end (must bring contents of first li to end of p)", - content: "

dom to edit 

  •   dom to edit

  • dom not to edit

", - steps: [{ - start: "p:contents()[0]->11", - key: 'DELETE', - }, { - key: 'DELETE', - }, { - key: 'DELETE', - }, { - key: 'DELETE', - }], - test: { - content: "

dom to editdom to edit

  • dom not to edit

", - start: "p:contents()[0]->11", - }, - }, - { - name: "in h1 (p after): DELETE at end", - content: '

node to merge with

node to merge

', - steps: [{ - start: 'h1:contents()[0]->18', - key: 'DELETE', - }], - test: { - content: '

node to merge withnode to merge

', - start: "h1:contents()[0]->18", - }, - }, - { - name: "in h1 (empty-p after): DELETE at end", - content: "

dom to edit


", - steps: [{ - start: "h1:contents()[0]->11", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "h1:contents()[0]->11", - }, - }, - { - name: "in h1 (empty-p after): 2x DELETE at end", - content: "

dom to edit


", - steps: [{ - start: "h1:contents()[0]->11", - key: 'DELETE', - }, { - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "h1:contents()[0]->11", - }, - }, - { - name: "in li > p (p after): DELETE at end", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'p:contents()[0]->18', - key: 'DELETE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "p:contents()[0]->18", - }, - }, - { - name: "in li > p (i before - p > b after): DELETE at end", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'p:contents()[1]->5', - key: 'DELETE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "p:contents()[1]->5", - }, - }, - { - name: "in li > p > i (b before - p > b after): DELETE at end", - content: '
  • node to merge with

node to merge

', - steps: [{ - start: 'i:contents()[0]->10', - key: 'DELETE', - }], - test: { - content: '
  • node to merge withnode to merge

', - start: "i:contents()[0]->10", - }, - }, - { - name: "in p.a > span.b (p.c > span.b after): DELETE at end", - content: "

dom to 

edit

", - steps: [{ - start: "span:contents()[0]->7", - key: 'DELETE', - }], - test: { - content: "

dom to edit

", - start: "span:contents()[0]->7", - }, - }, -]; - -var keyboardTestsDeleteDOM = [ - '
', - '

', - ' Dear Ready Mat', - '

', - ' Here is', - ' the quotation SO003', - ' amounting in $ 1,127.50', - ' from YourCompany.', - '

', - ' Do not hesitate to contact us if you have any question.', - '

', - '

', - ' ', - ' ', - ' ', - ' ', - ' ', - '
', - ' Virtual Interior Design
On Site ', - '
', - ' 10 Hours', - '
', - '
', - ' ' -].join('\n'); -keyboardTestsDelete.push({ - name: "in complex-dom: DELETE text selection", - content: keyboardTestsDeleteDOM, - steps: [{ - start: "p:contents()[0]->20", - end: 'p:contents()[0]->23', - key: 'DELETE', - }, - { - start: "p:contents()[10]->55", - end: 'p:contents()[10]->63', - key: 'DELETE', - }, - ], - test: { - content: keyboardTestsDeleteDOM.replace('question', '').replace('Mat', ''), - start: "p:contents()[10]->55", - }, -}, { - name: "in complex-dom: DELETE br", - content: keyboardTestsDeleteDOM, - steps: [{ - start: "p->2", - key: 'DELETE', - }, ], - test: { - content: keyboardTestsDeleteDOM.replace('
', ''), - start: "p:contents()[2]->0", - }, -}, { - name: "in complex-dom: DELETE selection (all strong text content)", - content: keyboardTestsDeleteDOM, - steps: [{ - start: "strong:eq(0):contents()[0]->0", - end: 'strong:eq(0):contents()[0]->5', - key: 'DELETE', - }, ], - test: { - content: keyboardTestsDeleteDOM.replace(/SO003<\/strong>\s+/, ' '), - start: "p:contents()[3]->43", - }, -}, { - name: "in complex-dom: DELETE selection (in strong text content before br)", - content: keyboardTestsDeleteDOM, - steps: [{ - start: "strong:eq(2):contents()[0]->17", - end: 'strong:eq(2):contents()[0]->23', - key: 'DELETE', - }, ], - test: { - content: keyboardTestsDeleteDOM.replace(/Design/, ''), - start: "strong:eq(2):contents()[0]->17", - }, -}); - -QUnit.test('Delete', function (assert) { - var done = assert.async(); - weTestUtils.createWysiwyg({ - data: this.data, - wysiwygOptions: { - tooltip: false, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - weTestUtils.testKeyboard($editable, assert, keyboardTestsDelete).then(function () { - wysiwyg.destroy(); - done(); - }); - }); -}); - -}); -}); -}); diff --git a/addons/web_editor/static/tests/wysiwyg_snippets_tests.js b/addons/web_editor/static/tests/wysiwyg_snippets_tests.js deleted file mode 100644 index f708b76b016..00000000000 --- a/addons/web_editor/static/tests/wysiwyg_snippets_tests.js +++ /dev/null @@ -1,413 +0,0 @@ -odoo.define('web_editor.wysiwyg_snippets_tests', function (require) { -"use strict"; - -var testUtils = require('web.test_utils'); -var weTestUtils = require('web_editor.test_utils'); -var MediaDialog = require('wysiwyg.widgets.MediaDialog'); - - -QUnit.module('web_editor', {}, function () { -QUnit.module('wysiwyg', {}, function () { -QUnit.module('Snippets', {}, function () { - -QUnit.test('drag&drop', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

toto toto toto

tata

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - var $hr = wysiwyg.snippets.$('.oe_snippet_thumbnail:first'); - testUtils.dom.dragAndDrop($hr, $editable.find('p')); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

toto toto toto


tata

', - "should drop the snippet"); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

toto toto toto


tata

', - "should build and focus the snippet"); - - wysiwyg.destroy(); - done(); - }); - }); -}); - -QUnit.test('begin drag&drop must hide popovers', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: - '
' + - '
' + - ' ' + - '
' + - '

test

' + - '

test

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - $editable.find('.s_hr img').mousedown().click(); - assert.strictEqual($('.note-popover:visible').length, 1, "should display the image popover"); - - var $hr = wysiwyg.snippets.$('.oe_snippet_thumbnail:first'); - testUtils.dom.dragAndDrop($hr, $editable.find('h1'), { - disableDrop: true, - }); - assert.strictEqual($('.note-popover:visible').length, 0, "should hide the image popover"); - testUtils.dom.dragAndDrop($hr, $editable.find('h1'), { - continueMove: true, - }); - - wysiwyg.destroy(); - done(); - }); -}); - -QUnit.test('change size option must hide popovers', function (assert) { - var done = assert.async(); - assert.expect(4); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: - '
' + - '
' + - ' ' + - '
' + - '

test

' + - '

test

', - }, - }).then(async function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - await testUtils.dom.click($editable.find('.s_hr img').mousedown()); - assert.strictEqual($('.note-popover:visible').length, 1, "should display the image popover"); - - var $handle = $('#oe_manipulators .o_handle.s'); - testUtils.dom.dragAndDrop($handle, $editable.find('b'), { - disableDrop: true, - }); - assert.ok($handle.hasClass('o_active'), "should active the handle"); - assert.notOk($handle.hasClass('pb32'), "should change the padding bottom"); - assert.strictEqual($('.note-popover:visible').length, 0, "should hide the image popover"); - await testUtils.dom.dragAndDrop($handle, $editable.find('b'), { - continueMove: true, - }); - - wysiwyg.destroy(); - done(); - }); -}); - -QUnit.test('clean the dom before save, after drag&drop', function (assert) { - var done = assert.async(); - assert.expect(1); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

toto toto toto

tata

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - var $hr = wysiwyg.snippets.$('.oe_snippet_thumbnail:first'); - testUtils.dom.dragAndDrop($hr, $editable.find('p')); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - wysiwyg.save().then(function (result) { - var isDirty = result.isDirty; - var html = result.html; - assert.strictEqual(html.replace(/\s+/g, ' '), - '

toto toto toto


tata

', - "should clean the snippet"); - - wysiwyg.destroy(); - done(); - }); - }); - }); -}); - -QUnit.test('clean the dom before save', function (assert) { - var done = assert.async(); - assert.expect(1); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - // add dirty flag to remove warning because the cleaned dom is different of the initial value and no dirty flag - $editable.find('.s_hr').keydown(); - - // trigger change to avoid warning because the DOM change on clean without trigger onchange by snippet or edition - $editable.trigger('content_changed'); - - wysiwyg.save().then(function (result) { - assert.strictEqual(result.html.replace(/\s+/g, ' '), - '

', - "should clean the snippet"); - - wysiwyg.destroy(); - done(); - }); - }); - - $editable.find('.s_hr').mousedown().click(); - }); -}); - -QUnit.test('remove snippet', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - $('.note-btn-bold').removeClass('o_disabled'); - $('#oe_manipulators .oe_overlay_options .oe_snippet_remove').click(); - assert.ok($('.note-btn-bold').hasClass('o_disabled')); - - wysiwyg.save().then(function (result) { - assert.strictEqual(result.html.replace(/\s+/g, ' '), '', "should remove the snippet"); - - wysiwyg.destroy(); - done(); - }); - }); - - $editable.find('.s_hr').mousedown().click(); - }); -}); - -QUnit.test('move a snippet', function (assert) { - var done = assert.async(); - assert.expect(1); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

test

test

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - var first = true; - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - if (first) { - first = false; - var $hr = $('#oe_manipulators .oe_overlay_options .oe_snippet_move'); - testUtils.dom.dragAndDrop($hr, $editable.find('b')); - } else { - wysiwyg.save().then(function (result) { - assert.strictEqual(result.html.replace(/\s+/g, ' '), - '

test


test

', - "should move the snippet on the bottom"); - - wysiwyg.destroy(); - done(); - }); - } - }); - - $editable.find('.s_hr').mousedown().click(); - }); -}); - -QUnit.test('clone a snippet', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

test

test

', - }, - }).then(async function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", async function () { - await testUtils.dom.click($('#oe_manipulators .oe_overlay_options .oe_snippet_clone')); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '


test

test

', - "should duplicate the snippet"); - - wysiwyg.save().then(function (result) { - assert.strictEqual(result.html.replace(/\s+/g, ' '), - '


test

test

', - "should duplicate the snippet"); - - wysiwyg.destroy(); - done(); - }); - }); - - await testUtils.dom.click($editable.find('.s_hr').mousedown()); - }); -}); - -QUnit.test('customize snippet', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '

test


test

', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - $('#oe_manipulators .oe_overlay_options .oe_options a:first').click(); - var $option = $('#oe_manipulators .oe_overlay_options a[data-select-class="align-items-center"]'); - - // assert.strictEqual($option.size(), 1, "should display the snippet option"); - - $option.click(); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

test


test

', - "should customized the snippet"); - - $('#oe_manipulators .oe_overlay_options .oe_options a:first').click(); - $('#oe_manipulators .oe_overlay_options a[data-select-class="align-items-end"]').click(); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

test


test

', - "should twice customized the snippet"); - - wysiwyg.destroy(); - done(); - }); - - $editable.find('.s_hr').mousedown().click(); - }); -}); - -QUnit.test('background-image', function (assert) { - var done = assert.async(); - assert.expect(2); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: - '

Big Title

' + - '
' + - '
' + - '
' + - '
' + - '

Title

' + - '

Content

' + - '
' + - '
' + - '
' + - '
', - }, - mockRPC: function (route, args) { - if (route.indexOf('/web_editor/static/src/img/') === 0) { - return Promise.resolve(); - } - return this._super(route, args); - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - var defMediaDialogInit = testUtils.makeTestPromise(); - var defMediaDialogSave = testUtils.makeTestPromise(); - testUtils.mock.patch(MediaDialog, { - init: function () { - this._super.apply(this, arguments); - this.opened(defMediaDialogInit.resolve.bind(defMediaDialogInit)); - }, - save: function () { - Promise.resolve(this._super.apply(this, arguments)).then(function () { - defMediaDialogSave.resolve(); - }); - }, - }); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - $('#oe_manipulators .oe_overlay_options .oe_options a:first').click(); - $('#oe_manipulators .oe_overlay_options a.snippet-option-background[data-choose-image]').click(); - - defMediaDialogInit.then(function () { - $('.o_select_media_dialog .o_we_existing_attachments .o_existing_attachment_cell').click(); - $('.o_select_media_dialog .modal-footer .btn-primary').click(); - }); - - defMediaDialogSave.then(function () { - var $snippet = $editable.find('.test_option_all'); - assert.ok($snippet.hasClass('oe_custom_bg'), "should use custom background"); - var background = $snippet.css('background-image') || ''; - assert.strictEqual(background.replace(/[^(\("'\/]+\/\/[^\("'\/]+/, ''), - 'url("/web_editor/static/src/img/transparent.png")', - "should change the background image"); - - testUtils.mock.unpatch(MediaDialog); - wysiwyg.destroy(); - done(); - }); - }); - - $editable.find('h2').mousedown().click(); - }); -}); - -QUnit.test('update content', function (assert) { - var done = assert.async(); - assert.expect(1); - - return weTestUtils.createWysiwyg({ - wysiwygOptions: { - snippets: true, - value: '
' + - ' ' + - '
', - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - testUtils.mock.intercept(wysiwyg, "snippet_focused", function () { - var $snippetOption = $('#oe_manipulators .oe_overlay_options:visible'); - wysiwyg.$el.siblings('.note-image-popover').find('.note-media .note-icon-trash').mousedown().click(); - assert.ok($snippetOption.is(':hidden'), "should remove the snippet editor because the target are removed"); - - wysiwyg.destroy(); - done(); - }); - - $editable.find('img').mousedown().click(); - }); -}); - -}); -}); -}); -}); diff --git a/addons/web_editor/static/tests/wysiwyg_tests.js b/addons/web_editor/static/tests/wysiwyg_tests.js deleted file mode 100644 index 9a5fbb103cc..00000000000 --- a/addons/web_editor/static/tests/wysiwyg_tests.js +++ /dev/null @@ -1,4182 +0,0 @@ -odoo.define('web_editor.wysiwyg_tests', function (require) { -"use strict"; - -var testUtils = require('web.test_utils'); -var weTestUtils = require('web_editor.test_utils'); -var Wysiwyg = require('web_editor.wysiwyg'); -var AltDialog = require('wysiwyg.widgets.AltDialog'); -var CropDialog = require('wysiwyg.widgets.CropImageDialog'); - -var testName = ""; -var carretTestSuffix = " (carret position)"; - -QUnit.module('web_editor', { - afterEach: function () { - $('body').removeClass('modal-open'); - $('.note-popover, .modal, .modal-backdrop').remove(); - }, -}, function () { -QUnit.module('wysiwyg', {}, function () { -QUnit.module('toolbar', {}, function () { - -QUnit.test('Magic wand', async function (assert) { - assert.expect(8); - - var wysiwyg = await weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }); - var $editable = wysiwyg.$('.note-editable'); - - var $dropdownStyle = wysiwyg.$('.note-style .dropdown-toggle'); - var $btnsStyle = wysiwyg.$('.note-style .dropdown-menu .dropdown-item'); - - var wandTests = [{ - name: "Click H1: p -> h1", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownStyle, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsStyle.find('h1'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'h1:contents()[0]->0', - end: 'h1:contents()[0]->11', - }, - }, - { - name: "Click CODE: h1 -> pre", - content: '

dom not to edit

dom to edit

', - start: 'h1:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownStyle, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsStyle.find('pre'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit
', - start: 'pre:contents()[0]->0', - end: 'pre:contents()[0]->11', - }, - }, - { - name: "Click NORMAL: pre -> p", - content: '

dom not to edit

dom to edit
', - start: 'pre:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownStyle, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsStyle.find('p'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->0', - end: 'p:eq(1):contents()[0]->11', - }, - }, - { - name: "Click H1 in empty p: empty p -> empty h1", - content: '


', - start: 'p->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownStyle, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsStyle.find('h1'), ['mousedown', 'click']); - }, - test: { - content: '


', - start: 'h1:contents()[0]->0', - }, - }, - ]; - - var def = Promise.resolve(); - wandTests.forEach(function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await testUtils.nextTick(); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - }); - }); - - return def.then(function() { - wysiwyg.destroy(); - }); -}); - -QUnit.test('Font style', function (assert) { - assert.expect(58); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - generateOptions: function (options) { - options.toolbar[1][1] = ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear']; - }, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $btnBold = wysiwyg.$('.note-font .note-btn-bold'); - var $btnItalic = wysiwyg.$('.note-font .note-btn-italic'); - var $btnUnderline = wysiwyg.$('.note-font .note-btn-underline'); - var $strikethrough = wysiwyg.$('.note-font .note-icon-strikethrough'); - var $superscript = wysiwyg.$('.note-font .note-icon-superscript'); - var $subscript = wysiwyg.$('.note-font .note-icon-subscript'); - var $btnRemoveStyles = wysiwyg.$('.note-font .btn-sm .note-icon-eraser'); - - var styleTests = [ - /* BOLD */ - { - name: "Click BOLD: normal -> bold", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->0', - end: 'b:contents()[0]->4', - }, - }, - { - name: "Click BOLD then 'a': normal -> bold (empty p)", - content: '


', - start: 'p->1', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable); - }, - test: { - content: '

a

', - start: 'b:contents()[0]->1', - }, - }, - { - name: "Click BOLD: normal -> bold (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'b:contents()[0]->0', - end: 'b:eq(1):contents()[0]->5', - }, - }, - { - name: "Click BOLD then 'a': normal -> bold (no selection)", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->4', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable); - }, - test: { - content: '

dom not to edit

dom ato edit

', - start: 'b:contents()[0]->1', - }, - }, - { - name: "Click BOLD: bold -> normal", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->0', - end: 'b:contents()[0]->11', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->0', - end: 'p:eq(1):contents()[0]->11', - }, - }, - { - name: "Click BOLD: bold -> normal (partial selection)", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->4', - end: 'b:contents()[0]->6', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[1]->0', - end: 'p:eq(1):contents()[1]->2', - }, - }, - { - name: "Click BOLD: bold -> normal (no selection)", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->4', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom \u200Bto edit

', - start: 'p:eq(1):contents()[1]->1', - }, - }, - { - name: "Click BOLD: bold + normal -> normal", - content: '

dom to edit

', - start: 'b:contents()[0]->1', - end: 'p:contents()[1]->4', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->8', - }, - }, - { - name: "Click BOLD: normal -> bold (with fontawesome)", - content: '

aaabbb

', - start: 'p:contents()[0]->1', - end: 'p:contents()[2]->2', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

aaabbb

', - start: 'b:contents()[0]->0', - end: 'b:contents()[2]->2', - }, - }, - { - name: "Click BOLD + click BOLD: normal -> bold -> normal (with fontawesome)", - content: '

aaabbb

', - start: 'p:contents()[0]->1', - end: 'p:contents()[2]->2', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

aaabbb

', - start: 'p:contents()[0]->1', - end: 'p:contents()[2]->2', - }, - }, - { - name: "Click BOLD: bold -> normal (with fontawesome)", - content: '

aaabbb

', - start: 'b:contents()[0]->1', - end: 'b:contents()[2]->2', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

aaabbb

', - start: 'p:contents()[1]->0', - end: 'p:contents()[3]->2', - }, - }, - { - name: "Click BOLD: bold -> normal (at start of dom)", - content: '

abc

', - start: 'b:contents()[0]->0', - do: function () { - $btnBold.mousedown().click(); - }, - test: { - content: '

\u200Babc

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->1', - }, - }, - /* ITALIC */ - { - name: "Click ITALIC: bold -> bold + italic", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnItalic, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'i:contents()[0]->0', - end: 'i:contents()[0]->4', - }, - }, - { - name: "Click ITALIC: bold & normal -> italic & bold + italic (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnItalic, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'i:contents()[0]->0', - end: 'i:eq(1):contents()[0]->5', - }, - }, - /* UNDERLINE */ - { - name: "Click UNDERLINE: bold -> bold + underlined", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUnderline, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'u:contents()[0]->0', - end: 'u:contents()[0]->4', - }, - }, - { - name: "Click UNDERLINE: bold & normal -> underlined & bold + underlined (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUnderline, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'u:contents()[0]->0', - end: 'u:eq(1):contents()[0]->5', - }, - }, - /* strikethrough */ - { - name: "Click strikethrough: bold -> bold + strikethrough", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($strikethrough, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 's:contents()[0]->0', - end: 's:contents()[0]->4', - }, - }, - { - name: "Click strikethrough: bold & normal -> strikethrough & bold + strikethrough (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($strikethrough, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 's:contents()[0]->0', - end: 's:eq(1):contents()[0]->5', - }, - }, - /* superscript */ - { - name: "Click superscript: bold -> bold + superscript", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($superscript, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'sup:contents()[0]->0', - end: 'sup:contents()[0]->4', - }, - }, - { - name: "Click superscript: bold & normal -> superscript & bold + superscript (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($superscript, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'sup:contents()[0]->0', - end: 'sup:eq(1):contents()[0]->5', - }, - }, - /* subscript */ - { - name: "Click subscript: bold -> bold + subscript", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($subscript, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'sub:contents()[0]->0', - end: 'sub:contents()[0]->4', - }, - }, - { - name: "Click subscript: bold & normal -> subscript & bold + subscript (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($subscript, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'sub:contents()[0]->0', - end: 'sub:eq(1):contents()[0]->5', - }, - }, - /* REMOVE FONT STYLE */ - { - name: "Click REMOVE FONT STYLE: bold -> normal", - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->1', - end: 'b:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnRemoveStyles, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[1]->0', - end: 'p:eq(1):contents()[1]->4', - }, - }, - { - name: "Click REMOVE FONT STYLE: bold, italic, underlined & normal -> normal (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'u:eq(1):contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($btnRemoveStyles, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:eq(1):contents()[0]->3', - }, - }, - { - name: "Click REMOVE FONT STYLE: complex -> normal", - content: '

aaabbb

ccc

', - start: 'p:contents()[0]->1', - end: 'font:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($btnRemoveStyles, ['mousedown', 'click']); - }, - test: { - content: '

aaabbb

ccc

', - start: 'p:contents()[0]->1', - end: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click REMOVE FONT STYLE: complex -> normal (with icon)", - content: '

aaabbb

', - start: 'p:contents()[0]->0', - end: 'i:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($btnRemoveStyles, ['mousedown', 'click']); - }, - test: { - content: '

aaabbb

', - start: 'p:contents()[0]->0', - end: 'p:contents()[2]->2', - }, - }, - /* COMPLEX */ - { - name: "COMPLEX Click BOLD: italic -> italic bold (partial selection)", - content: '

dom not to edit

dom to edit

', - start: 'i:contents()[0]->1', - end: 'i:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'b:contents()[0]->0', - end: 'b:contents()[0]->4', - }, - }, - { - name: "COMPLEX Click BOLD then 'a': italic bold -> italic (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'i:contents()[0]->1', - end: 'b:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

dom to edit

dom tao edit

', - }, - }, - { - name: "COMPLEX Click BOLD then 'a': bold italic -> italic (no selection)", - content: '

dom to edit

', - start: 'i:contents()[0]->4', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

dom ato edit

', - }, - }, - { - name: "COMPLEX Click BOLD then 'a': underlined italic -> underlined italic bold (across paragraphs)", - content: '

dom to edit

dom to edit

', - start: 'i:contents()[0]->1', - end: 'u:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

dom to edit

dom tao edit

', - }, - }, - { - name: "COMPLEX Click BOLD then 'a': underlined italic -> underlined italic bold (no selection)", - content: '

dom to edit

', - start: 'i:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($btnBold, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

daom to edit

', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(styleTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - test.end = test.end || test.start; - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - $editable[0].normalize(); - if (test.test.start) { - test.test.end = test.test.end || test.test.start; - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - } - }); - }); - - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Font size', function (assert) { - assert.expect(10); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $dropdownFontSize = wysiwyg.$('.note-fontsize .dropdown-toggle'); - var $linksFontSize = wysiwyg.$('.note-fontsize .dropdown-menu .dropdown-item'); - - var sizeTests = [{ - name: "Click 18: default -> 18px", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownFontSize, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($linksFontSize.filter(':contains("18")'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click DEFAULT: 18px -> default", - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->1', - end: 'font:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownFontSize, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($linksFontSize.filter(':contains("Default")'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[1]->0', - end: 'p:eq(1):contents()[1]->4', - }, - }, - { - name: "Click 18: 26px -> 18px", - content: '

dom to edit

', - start: 'font:contents()[0]->1', - end: 'font:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownFontSize, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($linksFontSize.filter(':contains("18")'), ['mousedown', 'click']); - }, - test: { - content: '

' + - 'd' + - 'om t' + - 'o edit

', - start: 'font:eq(1):contents()[0]->0', - end: 'font:eq(1):contents()[0]->4', - }, - }, - { - name: "Click 18 then 'a' (no selection): default -> 18px", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownFontSize, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($linksFontSize.filter(':contains("18")'), ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

dom not to edit

daom to edit

', - start: 'font:contents()[0]->1', - }, - }, - { - name: "Click 18 then 'a' (no selection): 26px -> 18px", - content: '

dom to edit

', - start: 'font:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownFontSize, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($linksFontSize.filter(':contains("18")'), ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

' + - 'd' + - 'a' + - 'om to edit

', - start: 'font:eq(1):contents()[0]->1', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(sizeTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - }); - }); - - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Text forecolor', function (assert) { - assert.expect(40); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $dropdownForeColor = wysiwyg.$('.note-color .note-fore-color .dropdown-toggle'); - var $btnsForeColor = wysiwyg.$('.note-color .note-fore-color .dropdown-menu .note-palette .note-color-btn'); - var forecolorTests = [{ - name: "Click THEME COLORS - ALPHA: default -> alpha theme color", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('.bg-alpha'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click THEME COLORS - BLACK 25: alpha theme color & default -> black 25", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('.bg-black-25'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click COMMON COLORS - BLUE #0000FF: black 25 & default -> blue #0000FF", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click RESET TO DEFAULT: black 25 & default -> default", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('.note-color-reset'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click CUSTOM COLORS then CUSTOM COLOR: blue #0000FF & default -> #875A7B", - async: true, - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - var self = this; - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color'), ['mousedown', 'click']); - - $('.modal-dialog .o_hex_input').val('#875A7B').change(); - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color-btn:last'), ['mousedown', 'click']); - - assert.deepEqual(wysiwyg.getValue(), - '

dom not to edit

dom to edit

', - self.name); - var range = weTestUtils.select('font:contents()[0]->0', 'font:contents()[0]->4', $editable); - assert.deepEqual(Wysiwyg.getRange($editable[0]), range, self.name + carretTestSuffix); - }, - }, - { - name: "Click CUSTOM COLORS then CUSTOM COLOR: change blue input", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->6', - do: async function () { - var self = this; - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color'), ['mousedown', 'click']); - - $('.modal-dialog .o_blue_input').val('100').change(); - - assert.deepEqual($('.modal-dialog .o_hex_input').val(), '#ff0064', self.name + ' (hex)'); - assert.deepEqual($('.modal-dialog .o_hue_input').val(), '337', self.name + ' (hue)'); - - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color-btn:last'), ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->5', - }, - }, - { - name: "CUSTOM COLOR: change hue, saturation and lightness inputs", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->6', - do: async function () { - var self = this; - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color'), ['mousedown', 'click']); - - $('.modal-dialog .o_hue_input').val('337').change(); - $('.modal-dialog .o_saturation_input').val('50').change(); - $('.modal-dialog .o_lightness_input').val('40').change(); - - assert.deepEqual($('.modal-dialog .o_hex_input').val(), '#99335a', self.name + ' (hex)'); - assert.deepEqual($('.modal-dialog .o_green_input').val(), '51', self.name + ' (green)'); - - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color-btn:last'), ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->5', - }, - }, - { - name: "CUSTOM COLOR: mousedown on area", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->6', - do: async function () { - var self = this; - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color'), ['mousedown', 'click']); - - var $area = $('.modal-dialog .o_color_pick_area'); - var pos = $area.offset(); - $area.trigger($.Event("mousedown", { - which: 1, - pageX: pos.left + 50, - pageY: pos.top + 50 - })); - $area.trigger('mouseup'); - - assert.deepEqual($('.modal-dialog .o_hex_input').val(), '#cfafaf', self.name + ' (hex)'); - assert.deepEqual($('.modal-dialog .o_red_input').val(), '207', self.name + ' (red)'); - assert.deepEqual($('.modal-dialog .o_green_input').val(), '175', self.name + ' (green)'); - assert.deepEqual($('.modal-dialog .o_blue_input').val(), '175', self.name + ' (blue)'); - assert.deepEqual($('.modal-dialog .o_hue_input').val(), '0', self.name + ' (hue)'); - assert.deepEqual($('.modal-dialog .o_saturation_input').val(), '25', self.name + ' (saturation)'); - assert.deepEqual($('.modal-dialog .o_lightness_input').val(), '75', self.name + ' (lightness)'); - - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color-btn:last'), ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->5', - }, - }, - { - name: "CUSTOM COLOR: mousedow on sliders", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->6', - do: async function () { - var self = this; - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color'), ['mousedown', 'click']); - - var $slider1 = $('.modal-dialog .o_slider_pointer'); - var pos1 = $slider1.offset(); - $slider1.trigger($.Event("mousedown", { - which: 1, - pageX: pos1.left, - pageY: pos1.top + 50 - })); - $slider1.trigger('mouseup'); - - assert.deepEqual($('.modal-dialog .o_hex_input').val(), '#83ff00', self.name + ' (hex)'); - - var $slider2 = $('.modal-dialog .o_opacity_slider'); - var pos2 = $slider2.offset(); - $slider2.trigger($.Event("mousedown", { - which: 1, - pageX: pos2.left, - pageY: pos2.top + 80 - })); - $slider2.trigger('mouseup'); - - assert.deepEqual($('.modal-dialog .o_hue_input').val(), '89', self.name + ' (hue)'); - assert.deepEqual($('.modal-dialog .o_opacity_input').val(), '60', self.name + ' (opacity)'); - - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-fore-color .note-custom-color-btn:last'), ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->5', - }, - }, - { - name: "Apply a color on a fontawesome", - content: '

dom not to edit

', - start: 'i->0', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

', - start: 'p->2', - }, - }, - { - name: "Apply a color on a font with text", - content: '

dom not to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[2]->6', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

', - start: 'font:eq(0):contents()[0]->0', - end: 'font:eq(1):contents()[0]->6', - }, - }, - { - name: "Apply color, then 'a' (no selection)", - content: '

dom not to edit

', - start: 'p:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - weTestUtils.keydown('a', $editable, { - firstDeselect: true, - }); - }, - test: { - content: '

daom not to edit

', - start: 'font:contents()[0]->1', - }, - }, - { - name: "Apply color on two ranges with the same color", - content: '

do
m not to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[3]->4', - do: async function ($editable) { - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - - var range = weTestUtils.select('p:contents()[5]->3', 'p:contents()[5]->6', $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - await testUtils.dom.triggerEvents($dropdownForeColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsForeColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - }, - test: { - content: '

do
m not to edit

', - start: 'font:eq(2):contents()[0]->0', - end: 'font:eq(2):contents()[0]->3', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(forecolorTests, function (test) { - def = def.then(function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - return Promise.resolve(test.do($editable)).then(function () { - if (!test.async) { - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - } - }); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Text bgcolor', function (assert) { - assert.expect(10); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - var testName = ""; - var carretTestSuffix = " (carret position)"; - - var $dropdownBgColor = wysiwyg.$('.note-color .note-bg-color .dropdown-toggle'); - var $btnsBgColor = wysiwyg.$('.note-color .note-bg-color .dropdown-menu .note-palette .note-color-btn'); - - var bgcolorTests = [{ - name: "Click THEME COLORS - ALPHA: default -> alpha theme color", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownBgColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsBgColor.filter('.bg-alpha'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click THEME COLORS - BLACK 25: alpha theme color & default -> black 25", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownBgColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsBgColor.filter('.bg-black-25'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click COMMON COLORS - BLUE #0000FF: black 25 & default -> blue #0000FF", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownBgColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsBgColor.filter('[style="background-color:#0000FF"]'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'font:contents()[0]->0', - end: 'font:contents()[0]->4', - }, - }, - { - name: "Click RESET TO DEFAULT: black 25 & default -> default", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - do: async function () { - await testUtils.dom.triggerEvents($dropdownBgColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnsBgColor.filter('.note-color-reset'), ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click CUSTOM COLORS then CUSTOM COLOR: blue #0000FF & default -> #875A7B", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'font:contents()[0]->3', - async: true, - do: async function () { - testName = "Click CUSTOM COLORS then CUSTOM COLOR: blue #0000FF & default -> #875A7B"; - - await testUtils.dom.triggerEvents($dropdownBgColor, ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-bg-color .note-custom-color'), ['mousedown', 'click']); - await testUtils.fields.editAndTrigger($('.modal-dialog .o_hex_input'), '#875A7B', 'change'); - await testUtils.dom.triggerEvents($('.o_technical_modal .modal-footer .btn-primary:contains("Choose")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents(wysiwyg.$('.note-color .note-bg-color .note-custom-color-btn:last'), ['mousedown', 'click']); - - assert.deepEqual(wysiwyg.getValue(), - '

dom not to edit

dom to edit

', - testName); - var range = weTestUtils.select('font:contents()[0]->0', - 'font:contents()[0]->4', - $editable); - assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix); - }, - }, - ]; - - var def = Promise.resolve(); - _.each(bgcolorTests, function (test) { - def = def.then(async function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - if (!test.async) { - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - } - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Unordered list', function (assert) { - assert.expect(34); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $btnUL = wysiwyg.$('.note-para .note-icon-unorderedlist'); - - var ulTests = [{ - name: "Click UL: p -> ul", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click UL: p -> ul (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul -> p", - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click UL: p -> ul (across li's)", - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul -> p (from second li)", - content: '

dom not to edit

  • xxx

  • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnUL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

  • xxx

dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - // Conversion from OL - { - name: "Click UL: ol -> ul", - content: '

dom not to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click UL: ol -> ul (across li's)", - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ol -> ul (from second li)", - content: '

dom not to edit

  1. xxx

  2. dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. xxx

  • dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ol -> ul ul (from indented li)", - content: '

dom not to edit

  • xxx

    1. dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ol -> ul ul (across several indented li)", - content: '

dom not to edit

  • xxx

    1. dom to edit 1

    2. dom to edit 2

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom to edit 1

    • dom to edit 2

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ol -> ul ul (from second indented li)", - content: '

dom not to edit

  • xxx

    1. dom not to edit

    2. dom to edit

    3. dom not to edit

', - start: 'li:eq(2) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    1. dom not to edit

    • dom to edit

    1. dom not to edit

', - start: 'p:eq(3):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - // Conversion from Checklist - { - name: "Click UL: ul.o_checklist -> ul", - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click UL: ul.o_checklist -> ul (across li's)", - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul.o_checklist -> ul (from second li)", - content: '

dom not to edit

  • xxx

  • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

  • dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ul.o_checklist -> ul ul (from indented li)", - content: '

dom not to edit

  • xxx

    • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ul.o_checklist -> ul ul (across several indented li)", - content: '

dom not to edit

  • xxx

    • dom to edit 1

    • dom to edit 2

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom to edit 1

    • dom to edit 2

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - { - name: "Click UL: ul ul.o_checklist -> ul ul (from second indented li)", - content: '

dom not to edit

  • xxx

    • dom not to edit

    • dom to edit

    • dom not to edit

', - start: 'li:eq(2) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnUL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom not to edit

    • dom to edit

    • dom not to edit

', - start: 'p:eq(3):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(ulTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - }); - }); - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Ordered list', function (assert) { - assert.expect(56); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $btnOL = wysiwyg.$('.note-para .note-icon-orderedlist'); - - var olTests = [{ - name: "Click OL: p -> ol", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click OL: p -> ol (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ol -> p", - content: '

dom not to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click OL: p -> ol (across li's)", - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ol -> p (from second li) (2)", - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'li:eq(0) p:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click OL: ol -> p (from second li)", - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'li:eq(0) p:contents()[0]->1', - end: 'li:eq(0) p:contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click OL + Click OL: ul ul -> ul ol -> ul", - content: '

a

' + - '
    ' + - '
  • b

  • ' + - '
      ' + - '
    • c

    • ' + - '
    • d

    • ' + - '
    ' + - '
  • e

  • ' + - '
', - start: 'ul ul li:first:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

a

' + - '
    ' + - '
  • b

  • ' + - '
  • c

  • ' + - '
      ' + - '
    • d

    • ' + - '
    ' + - '
  • e

  • ' + - '
', - start: 'ul li:eq(1) p:contents()[0]->1', - }, - }, - { - name: "Click OL in empty table cell in div", - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1)->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1) br->0', - }, - }, - { - name: "Click OL in empty table cell in div (2)", - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1) br->0', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1) br->0', - }, - }, - { - name: "Click OL in empty table cell in div (3)", - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1)->0', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '






' + - '
', - start: 'tr:eq(0) td:eq(1) br->0', - }, - }, - { - name: "Click OL in table cell in div", - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '

aaa



' + - '
', - start: 'tr:eq(0) td:eq(1):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '

  1. aaa





' + - '
', - start: 'td li p:contents(0)->1', - }, - }, - { - name: "Click OL on image in table cell in div", - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '





' + - '
', - start: 'img->0', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
' + - '

a

' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '





' + - '
', - start: 'td li->1', - }, - }, - { - name: "Click OL with selected LI in OL", - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
  3. bbb

  4. ' + - '
  5. ccc

  6. ' + - '
  7. ddd

  8. ' + - '
' + - '

y

', - start: 'p:eq(2):contents(0)->1', - end: 'p:eq(3):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
' + - '

bbb

' + - '

ccc

' + - '
    ' + - '
  1. ddd

  2. ' + - '
' + - '

y

', - start: 'p:eq(2):contents(0)->1', - end: 'p:eq(3):contents(0)->1', - }, - }, - { - name: "Click OL with selected LI in UL", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • bbb

  • ' + - '
  • ccc

  • ' + - '
  • ddd

  • ' + - '
' + - '

y

', - start: 'p:eq(2):contents(0)->1', - end: 'p:eq(3):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
' + - '
    ' + - '
  1. bbb

  2. ' + - '
  3. ccc

  4. ' + - '
' + - '
    ' + - '
  • ddd

  • ' + - '
' + - '

y

', - start: 'p:eq(2):contents(0)->1', - end: 'p:eq(3):contents(0)->1', - }, - }, - { - name: "Click OL after ENTER in p > b", - content: "

dom to edit

", - start: 'b:contents(0)->11', - do: async function () { - weTestUtils.keydown(13, $editable); // ENTER - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - weTestUtils.keydown('a', $editable); // ENTER - }, - test: { - content: "

dom to edit

  1. a

", - start: 'b:eq(1):contents(0)->1', - }, - }, - { - name: "Click OL in font in H1 (with link) in div", - content: '

table of contents p23 (cfr: 34)

', - start: 'font:contents(0)->11', - do: async function () { - await testUtils.dom.triggerEvents($btnOL, ['mousedown', 'click']); - }, - test: { - content: '
  1. table of contents p23 (cfr: 34)

', - start: 'font:contents(0)->11', - }, - }, - // Conversion from UL - { - name: "Click OL: ul -> ol", - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click OL: ul -> ol (across li's)", - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ul -> ol (from second li)", - content: '

dom not to edit

  • xxx

  • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

  1. dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ol ul -> ol ol (from indented li)", - content: '

dom not to edit

  1. xxx

    • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. xxx

    1. dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ol ul -> ol ol (across several indented li)", - content: '

dom not to edit

  1. xxx

    • dom to edit 1

    • dom to edit 2

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. xxx

    1. dom to edit 1

    2. dom to edit 2

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - { - name: "Click OL: ol ul -> ol ol (from second indented li)", - content: '

dom not to edit

  1. xxx

    • dom not to edit

    • dom to edit

    • dom not to edit

', - start: 'li:eq(2) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. xxx

    • dom not to edit

    1. dom to edit

    • dom not to edit

', - start: 'p:eq(3):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - // Conversion from Checklist - { - name: "Click OL: ul.o_checklist -> ol", - content: '

dom not to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click OL: ul.o_checklist -> ol (across li's)", - content: '

dom not to edit

  • dom to edit

  • dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. dom to edit

  2. dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ul.o_checklist -> ol (from second li)", - content: '

dom not to edit

  • xxx

  • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

  1. dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ol ul.o_checklist -> ol ol (from indented li)", - content: '

dom not to edit

  1. xxx

    • dom to edit

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(1) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  1. xxx

    1. dom to edit

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - { - name: "Click OL: ul ul.o_checklist -> ul ol (across several indented li)", - content: '

dom not to edit

  • xxx

    • dom to edit 1

    • dom to edit 2

', - start: 'li:eq(1) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    1. dom to edit 1

    2. dom to edit 2

', - start: 'p:eq(2):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - { - name: "Click OL: ul ul.o_checklist -> ul ol (from second indented li)", - content: '

dom not to edit

  • xxx

    • dom not to edit

    • dom to edit

    • dom not to edit

', - start: 'li:eq(2) p:contents()[0]->1', - end: 'li:eq(2) p:contents()[0]->5', - do: function () { - $btnOL.mousedown().click(); - }, - test: { - content: '

dom not to edit

  • xxx

    • dom not to edit

    1. dom to edit

    • dom not to edit

', - start: 'p:eq(3):contents()[0]->1', - end: 'p:eq(3):contents()[0]->5', - }, - }, - ]; - - - var def = Promise.resolve(); - _.each(olTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - if (wysiwyg.getValue() === test.test.content) { - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - } else { - assert.notOk(true, testName + ' (Wrong DOM)'); - } - }); - }); - - return def.then(function(){ - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Align', function (assert) { - assert.expect(20); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $dropdownPara = wysiwyg.$('.note-para .dropdown-toggle'); - var $btnAlignLeft = wysiwyg.$('.note-align .note-icon-align-left'); - var $btnAlignCenter = wysiwyg.$('.note-align .note-icon-align-center'); - var $btnAlignRight = wysiwyg.$('.note-align .note-icon-align-right'); - var $btnAlignJustify = wysiwyg.$('.note-align .note-icon-align-justify'); - - var alignTests = [ - /* ALIGN LEFT */ - { - name: "Click ALIGN LEFT: p -> p align left (does nothing)", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignLeft, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click ALIGN LEFT: p (parent align right) -> p align left (does nothing)", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignLeft, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click ALIGN LEFT: p (parent align left) -> p align left (does nothing)", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignLeft, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(1):contents()[0]->5', - }, - }, - { - name: "Click ALIGN LEFT: p align justify & default -> p align right (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignRight, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - /* ALIGN CENTER */ - { - name: "Click ALIGN CENTER: p -> p align center", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignCenter, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click ALIGN CENTER: p align left & default -> p align center (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignCenter, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - /* ALIGN RIGHT */ - { - name: "Click ALIGN RIGHT: p align center -> p align right", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignRight, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click ALIGN RIGHT: p align center & default -> p align right (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignRight, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - /* ALIGN JUSTIFY */ - { - name: "Click ALIGN JUSTIFY: p align right -> p align justify", - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignJustify, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click ALIGN JUSTIFY: p align right & default -> p align justify (across paragraphs)", - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnAlignJustify, ['mousedown', 'click']); - }, - test: { - content: '

dom not to edit

dom to edit

dom to edit

', - start: 'p:eq(1):contents()[0]->1', - end: 'p:eq(2):contents()[0]->5', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(alignTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - }); - }); - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Indent/outdent', function (assert) { - assert.expect(20); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $dropdownPara = wysiwyg.$('.note-para .dropdown-toggle'); - var $btnIndent = wysiwyg.$('.note-list .note-btn:eq(1)'); - var $btnOutdent = wysiwyg.$('.note-list .note-btn:first'); - - var indentTests = [ - /* INDENT */ - { - name: "Click INDENT: p -> indented p", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnIndent, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'p:contents()[0]->1', - }, - }, - { - name: "Click INDENT: li -> indented li", - content: '
  • dom

  • to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnIndent, ['mousedown', 'click']); - }, - test: { - content: '
  • dom

    • to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click INDENT: li -> indented li", - content: '

aaa

bbb

ccc

ddd

', - start: 'p:eq(1):contents()[0]->0', - end: 'p:eq(3):contents()[0]->3', - do: function () { - $dropdownPara.mousedown().click(); - $btnIndent.mousedown().click(); - }, - test: { - content: '

aaa

bbb

ccc

ddd

', - start: 'p:eq(1):contents()[0]->0', - end: 'p:eq(3):contents()[0]->3', - }, - }, - /* OUTDENT */ - { - name: "Click OUTDENT: indented p -> p", - content: '

dom to edit

', - start: 'p:contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'p:contents()[0]->1', - }, - }, - { - name: "Click OUTDENT: indented li -> li", - content: '
  • dom

    • to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: '
  • dom

  • to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click OUTDENT: indented li -> li (2)", - content: '
  • dom

    • to edit

', - start: 'p:eq(1):contents()[0]->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: '
  • dom

  • to edit

', - start: 'p:eq(1):contents()[0]->1', - }, - }, - { - name: "Click OUTDENT on LI in OL in OL", - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
    1. ' + - '
    2. bbb

    3. ' + - '
    4. ccc

    5. ' + - '
    6. ddd

    7. ' + - '
  3. ' + - '
  4. eee

  5. ' + - '
' + - '

y

', - start: 'ol ol p:eq(1):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
    1. ' + - '
    2. bbb

    3. ' + - '
  3. ' + - '
  4. ccc

  5. ' + - '
    1. ' + - '
    2. ddd

    3. ' + - '
  6. ' + - '
  7. eee

  8. ' + - '
' + - '

y

', - start: 'ol:first > li:eq(2) p:contents(0)->1', - }, - }, - { - name: "Click OUTDENT on LI in OL in OL (2)", - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
      ' + - '
    1. bbb

    2. ' + - '
    3. ccc

    4. ' + - '
    5. ddd

    6. ' + - '
    ' + - '
  3. eee

  4. ' + - '
' + - '

y

', - start: 'ol ol p:eq(1):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: '

x

' + - '
    ' + - '
  1. aaa

  2. ' + - '
      ' + - '
    1. bbb

    2. ' + - '
    ' + - '
  3. ccc

  4. ' + - '
      ' + - '
    1. ddd

    2. ' + - '
    ' + - '
  5. eee

  6. ' + - '
' + - '

y

', - start: 'li:eq(2) p:contents(0)->1', - }, - }, - { - name: "Click OUTDENT on LI in OL", - content: - '
    ' + - '
  1. aaa

  2. ' + - '
  3. bbb

  4. ' + - '
  5. ccc

  6. ' + - '
', - start: 'p:eq(1):contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: - '
    ' + - '
  1. aaa

  2. ' + - '
' + - '

bbb

' + - '
    ' + - '
  1. ccc

  2. ' + - '
', - start: 'p:eq(1):contents(0)->1', - }, - }, - { - name: "Click OUTDENT on P with indent in a LI (must outdent the p)", - content: - '
    ' + - '
  • ' + - '
      ' + - '
    • ' + - '

      dom

      ' + - '
    • ' + - '
    ' + - '
  • ' + - '
', - start: 'p:contents(0)->1', - do: async function () { - await testUtils.dom.triggerEvents($dropdownPara, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($btnOutdent, ['mousedown', 'click']); - }, - test: { - content: - '
    ' + - '
  • ' + - '
      ' + - '
    • ' + - '

      dom

      ' + - '
    • ' + - '
    ' + - '
  • ' + - '
', - start: 'p:contents(0)->1', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(indentTests, function (test) { - def = def.then(async function() { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - assert.deepEqual(Wysiwyg.getRange($editable[0]), weTestUtils.select(test.test.start, test.test.end, $editable), testName + carretTestSuffix); - }); - }); - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('checklist', function (assert) { - assert.expect(11); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - generateOptions: function (options) { - options.toolbar[4][1] = ['ul', 'ol', 'checklist', 'paragraph']; - }, - }, - }).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $btnChecklist = wysiwyg.$('.note-para .fa-check-square'); - - var checklistTests = [ - { - name: "check checkbox in checklist with children", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('li:first'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "check checkbox in checklist with children (2)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('li:first'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "uncheck checkbox in checklist with children", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('li:first'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "uncheck checkbox in checklist with children (2)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('li:first'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "uncheck checkbox in checklist in checklist", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "uncheck checkbox in checklist in checklist (2)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "check checkbox in checklist in checklist", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "check checkbox in checklist in checklist (2)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "check checkbox in checklist in checklist (full)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "check checkbox in checklist in checklist (full) (2)", - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - do: async function () { - var $li = $editable.find('ul ul li:eq(1)'); - $li.trigger($.Event('mousedown', { - offsetX: -10, - })); - }, - test: { - content: '

x

' + - '
    ' + - '
  • aaa

  • ' + - '
      ' + - '
    • bbb

    • ' + - '
    • ccc

    • ' + - '
    • ddd

    • ' + - '
    ' + - '
  • eee

  • ' + - '
' + - '

y

', - }, - }, - { - name: "convert 2 ul li ul li into two ul li ul.o_checklist li", - content: '
    ' + - '
  • ' + - '

    1

    ' + - '
  • ' + - '
  • ' + - '
      ' + - '
    • ' + - '

      2

      ' + - '
    • ' + - '
    • ' + - '

      3

      ' + - '
    • ' + - '
    • ' + - '

      4

      ' + - '
    • ' + - '
    ' + - '
  • ' + - '
  • ' + - '

    5

    ' + - '
  • ' + - '
', - start: 'p:eq(2):contents()[0]->0', - end: 'p:eq(3):contents()[0]->1', - do: function () { - $btnChecklist.mousedown().click(); - }, - test: { - content: '
    ' + - '
  • ' + - '

    1

    ' + - '
  • ' + - '
  • ' + - '
      ' + - '
    • ' + - '

      2

      ' + - '
    • ' + - '
    ' + - '
      ' + - '
    • ' + - '

      3

      ' + - '
    • ' + - '
    • ' + - '

      4

      ' + - '
    • ' + - '
    ' + - '
  • ' + - '
  • ' + - '

    5

    ' + - '
  • ' + - '
', - }, - }, - ]; - - var def = Promise.resolve(); - - _.each(checklistTests, function (test) { - def = def.then(async function(){ - testName = test.name; - wysiwyg.setValue(test.content); - if (test.start) { - var range = weTestUtils.select(test.start, test.end || test.start, $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - } - await test.do(); - assert.deepEqual(wysiwyg.getValue(), test.test.content, testName); - }); - }); - - return def.then(function() { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Link', function (assert) { - assert.expect(19); - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - - }, - }).then(async function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var $btnLink = wysiwyg.$('.note-insert .note-icon-link'); - - var _clickLink = async function (callbackInit, test) { - await testUtils.dom.triggerEvents($btnLink, ['mousedown', 'click']); - await callbackInit(); - await testUtils.dom.triggerEvents($('.modal-dialog:visible .btn-primary:contains("Save")'), ['mousedown', 'click']); - - if (test.check) { - await test.check(); - } - if (test.content) { - assert.deepEqual(wysiwyg.getValue(), test.content, testName); - } - if (test.start) { - var range = weTestUtils.select(test.start, test.end, $editable); - assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix); - } - }; - - var linkTests = [{ - name: "Click LINK: p -> a in p (w/ URL)", - async: true, - content: '

dom to edit

', - start: "p:contents()[0]->1", - end: "p:contents()[0]->5", - do: async function () { - assert.strictEqual($('.modal-dialog:visible #o_link_dialog_label_input').val(), 'om t', testName + ' (label)'); - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'),'#'); - }, - test: { - content: '

dom to edit

', - start: 'a:contents()[0]->0', - end: 'a:contents()[0]->4', - }, - }, - { - name: "Click LINK: p -> a in p (w/ URL) (no selection)", - async: true, - content: '

do edit

', - start: 'p:contents()[0]->1', - do: async function () { - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_label_input'),'om t'); - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'),'#'); - }, - test: { - content: '

dom to edit

', - start: 'p->2', // link not selected, the user can continue to write - end: 'p->2', - }, - }, - { - name: "Click LINK: a.btn in div -> a.btn.btn-outline-alpha in div (edit) (no selection)", - content: '', - start: 'a:contents()[0]->5', - do: async function () { - assert.strictEqual($('.modal-dialog:visible #o_link_dialog_label_input').val(), 'dom to edit', testName + ' (label)'); - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'),'#newlink'); - }, - test: { - content: '', - start: 'a->0', - end: 'a->1', - }, - }, - { - name: "Click LINK: p -> a in p (w/ Email)", - async: true, - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->5', - do: async function () { - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'),'john.coltrane@example.com'); - }, - test: { - content: '

dom to edit

', - start: 'a:contents()[0]->0', - end: 'a:contents()[0]->4', - }, - }, - { - name: "Click LINK: p -> a in p (w/ URL & Size Large)", - async: true, - content: '

dom to edit

', - start: 'p:contents()[0]->1', - end: 'p:contents()[0]->5', - do: async function () { - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'),'#'); - await testUtils.fields.editInput($('.modal-dialog:visible [name="link_style_size"]'),"lg"); - }, - test: { - content: '

dom to edit

', - start: 'a:contents()[0]->0', - end: 'a:contents()[0]->4', - }, - }, - { - name: "Click LINK: a in p -> a.btn-outline-alpha in p with alpha color and target=\"_blank\"", - async: true, - content: '

dom to edit

', - start: 'a:contents()[0]->1', - do: async function () { - await testUtils.fields.editInput( $('.modal-dialog:visible #o_link_dialog_url_input'), '#'); - await testUtils.fields.editInput($('.modal-dialog:visible [name="link_style_shape"]'), "outline"); - await testUtils.dom.triggerEvents($('.modal-dialog:visible .o_link_dialog_color .o_link_dialog_color_item.btn-alpha'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.modal-dialog:visible .o_switch [name="is_new_window"]'), ['mousedown', 'click']); - }, - test: { - content: '

dom to edit

', - start: 'a->0', - end: 'a->1', - }, - }, - // POPOVER - { - name: "Click LINK in popover after adding link in p", - async: true, - content: '

dom to edit

', - start: "p:contents()[0]->1", - end: "p:contents()[0]->5", - do: async function () { - $('.modal-dialog:visible #o_link_dialog_url_input').val('/link'); - }, - test: { - check: async function () { - await testUtils.dom.triggerEvents($('.note-link-popover .note-btn .note-icon-link'), ['mousedown', 'click']); - - assert.strictEqual($('.modal-dialog:visible #o_link_dialog_label_input').val(), 'om t', testName + ' (label)'); - assert.strictEqual($('.modal-dialog:visible #o_link_dialog_url_input').val(), '/link', testName + ' (url)'); - await testUtils.fields.editInput($('.modal-dialog:visible #o_link_dialog_url_input'), '/newlink'); - await testUtils.dom.triggerEvents($('.modal-dialog:visible .modal-footer .btn.btn-primary:contains("Save")'), ['mousedown', 'click']); - assert.deepEqual(wysiwyg.getValue(), '

dom to edit

', testName); - }, - }, - }, - { - name: "Click UNLINK in popover after adding link in p", - async: true, - content: '

dom to edit

', - start: "p:contents()[0]->1", - end: "p:contents()[0]->5", - do: async function () { - $('.modal-dialog:visible #o_link_dialog_url_input').val('/link'); - }, - test: { - content: '

dom to edit

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-link-popover .note-btn .note-icon-chain-broken'), ['mousedown', 'click']); - - var range = weTestUtils.select('p:contents()[0]->1', 'p:contents()[0]->5', $editable); - assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix); - }, - }, - }, - ]; - - var def = Promise.resolve(); - _.each(linkTests, function (test) { - def = def.then(async function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await _clickLink(test.do, test.test); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Table', function (assert) { - assert.expect(13); - - async function createTable(wysiwyg) { - await testUtils.dom.triggerEvents(wysiwyg.$('.note-table button:first'), ['mousedown', 'click']); - - var $grid = wysiwyg.$('.note-table .note-dimension-picker-mousecatcher'); - var pos = $grid.offset(); - $grid.trigger($.Event('mousemove', { - pageX: pos.left + 40, - pageY: pos.top + 40, - })); - await testUtils.dom.triggerEvents($grid, ['mousedown', 'click']); - } - - return weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: {}, - }).then(async function (wysiwyg) { - var $editable = wysiwyg.getEditable(); - - // create a table in an empty dom - - wysiwyg.setValue('


'); - var range = weTestUtils.select('p->1', 'p->1', $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - await createTable(wysiwyg); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '


' + - '' + - '' + - '' + - '' + - '










' + - '


', - "should create a table in an empty dom (p > br)"); - - // create a table at start of p with content - - wysiwyg.setValue('

dom to edit

'); - range = weTestUtils.select('p:contents()[0]->0', 'p:contents()[0]->0', $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - await createTable(wysiwyg); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '


' + - '' + - '' + - '' + - '' + - '










' + - '

dom to edit

', - "should create a table at start of single p with content"); - - // create a table at end of p with content - - wysiwyg.setValue('

dom to edit

'); - range = weTestUtils.select('p:contents()[0]->11', 'p:contents()[0]->11', $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - await createTable(wysiwyg); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom to edit

' + - '' + - '' + - '' + - '' + - '










' + - '


', - "should create a table at end of single p with content"); - - // create a table within p - - wysiwyg.setValue('

dom to edit

'); - range = weTestUtils.select('p:contents()[0]->5', 'p:contents()[0]->5', $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - await createTable(wysiwyg); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '










' + - '

o edit

', - "should create a table"); - - // remove a table - - range = weTestUtils.select('td:first->0', 'td:first->0', $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - var $trash = $('.note-table-popover:visible button:has(.note-icon-trash)'); - - await testUtils.dom.triggerEvents($trash, ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom to edit

', - "should remove the table"); - - // re create a table and table in table - - await createTable(wysiwyg); - await createTable(wysiwyg); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '


' + - '' + - '' + - '' + - '' + - '










' + - '










' + - '

o edit

', - "should create a table inside the table"); - - // remove inner table - - range = weTestUtils.select('td td:eq(1)->0', 'td td:eq(1)->0', $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - - $trash = $('.note-table-popover:visible button:has(.note-icon-trash)'); - await testUtils.dom.triggerEvents($trash, ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '










' + - '

o edit

', - "should remove the inner table"); - - // use popover to change row and line - - wysiwyg.setValue('

dom t

' + - '' + - '' + - '' + - '' + - '

0-0

0-1

0-2

1-0

1-1

1-2

2-0

2-1

2-2

' + - '

o edit

'); - - // remove a row - - range = weTestUtils.select('td:eq(1)->0', 'td:eq(1)->0', $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-col-remove)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '

0-0

0-2

1-0

1-2

2-0

2-2

' + - '

o edit

', - "should remove a row"); - - // remove a line - - range = weTestUtils.select('tr:eq(1) td:eq(1)->0', 'tr:eq(1) td:eq(1)->0', $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-row-remove)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '

0-0

0-2

2-0

2-2

' + - '

o edit

', - "should remove a line"); - - // add a row after - - range = weTestUtils.select('tr:eq(1) td:first->0', 'tr:eq(1) td:first->0', $editable); - $(range.sc).mousedown(); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-col-after)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '

0-0


0-2

2-0


2-2

' + - '

o edit

', - "should add a row after"); - - // add a row before - - $(range.sc).mousedown(); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-col-before)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '


0-0


0-2


2-0


2-2

' + - '

o edit

', - "should add a row before"); - - // add a line after - - $(range.sc).mousedown(); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-row-below)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '


0-0


0-2


2-0


2-2





' + - '

o edit

', - "should add a line after"); - - // add a line before - - $(range.sc).mousedown(); - await testUtils.dom.triggerEvents($('.note-table-popover:visible button:has(.note-icon-row-above)'), ['mousedown', 'click']); - - assert.strictEqual($editable.html().replace(/\s+/g, ' '), - '

dom t

' + - '' + - '' + - '' + - '' + - '' + - '


0-0


0-2






2-0


2-2





' + - '

o edit

', - "should add a line before"); - - wysiwyg.destroy(); - }); -}); - -QUnit.test('CodeView', async function (assert) { - assert.expect(8); - - var wysiwyg = await weTestUtils.createWysiwyg({ - debug: false, - wysiwygOptions: { - codeview: true, - }, - }); - wysiwyg.setValue('

dom to edit

'); - - var $buttonCodeView = wysiwyg.$('button:has(.note-icon-code)'); - - // hide popover in CodeView mode and no range error when edit the content - var $editable = wysiwyg.getEditable(); - await testUtils.dom.triggerEvents($editable.find('img'), ['mousedown', 'click']); - assert.strictEqual($('.note-popover.note-image-popover:visible').length, 1, "should display the image popover"); - await testUtils.dom.triggerEvents($buttonCodeView, ['mousedown', 'click']); - assert.strictEqual($('textarea.note-codable:visible').length, 1, "should show the CodeView textarea"); - assert.strictEqual($editable.is(':visible'), false, "should hide the editable area"); - assert.strictEqual($('.note-popover:visible').length, 0, "should hide all popovers"); - assert.strictEqual($('.note-toolbar button:not(.disabled)').length, 1, "should disabled all buttons expect the codeview button"); - wysiwyg.$('textarea.note-codable').val('

dom to edit a

'); - await testUtils.dom.triggerEvents($buttonCodeView, ['mousedown', 'click']); - assert.strictEqual($('textarea.note-codable:visible').length, 0, "should hide the CodeView textarea"); - assert.strictEqual($editable.is(':visible'), true, "should show the editable area"); - assert.strictEqual($editable[0].style.height, '', "should reset the height (not auto or sizing)"); - // end - - wysiwyg.destroy(); -}); - -}); - -var imgWidth = 10; -var imgHeight = 10; - -var altDialogOpened; -var altDialogSaved; -var cropDialogOpened; -QUnit.module('Media', { - beforeEach: function () { - this.data = { - debug: false, - wysiwygOptions: { - - }, - mockRPC: function (route, args) { - if (route.indexOf('data:image/png;base64') === 0) { - return Promise.resolve(); - } - if (route.indexOf('youtube') !== -1) { - return Promise.resolve(); - } - if (route.indexOf('/web_editor/static/src/img/') === 0) { - return Promise.resolve(); - } - if (route === '/web_editor/attachment/add_url') { - return Promise.resolve({ - id: 1, - public: true, - name: 'image', - mimetype: 'image/png', - checksum: false, - url: '/web_editor/static/src/img/transparent.png', - image_src: '/web_editor/static/src/img/transparent.png', - type: 'url', - res_id: 0, - res_model: false, - access_token: false, - }); - } - return this._super(route, args); - }, - }; - - testUtils.mock.patch(AltDialog, { - init: function () { - this._super.apply(this, arguments); - altDialogOpened = this._opened; - }, - save: function () { - altDialogSaved = this._super.apply(this, arguments); - return altDialogSaved; - }, - }); - - testUtils.mock.patch(CropDialog, { - init: function () { - var self = this; - this._super.apply(this, arguments); - cropDialogOpened = new Promise (function (resolve) { - self.opened(function () { - var cropper = self.$cropperImage.data('cropper'); - cropper.clone(); - $.extend(cropper.image, { - naturalWidth: imgWidth, - naturalHeight: imgHeight, - aspectRatio: imgWidth / imgHeight, - }); - cropper.loaded = true; - cropper.build(); - cropper.render(); - resolve(); - }); - }); - }, - }); - }, - afterEach: function () { - testUtils.mock.unpatch(AltDialog); - testUtils.mock.unpatch(CropDialog); - $('body').off('submit.WysiwygTests'); - }, -}, function () { - - -var _clickMedia = async function (wysiwyg, assert, callbackInit, test) { - await testUtils.dom.triggerEvents(wysiwyg.$('.note-insert .fa-file-image-o'), ['mousedown', 'click']); - await callbackInit(); - - if (test.check) { - await test.check(); - } - if (test.content) { - assert.deepEqual(wysiwyg.getValue(), test.content, testName); - } - if (test.start) { - var range = weTestUtils.select(test.start, test.end, $editable); - assert.deepEqual(Wysiwyg.getRange($editable[0]), range, testName + carretTestSuffix); - } -}; - -var _uploadAndInsertImg = async function (url) { - $('.modal-dialog .o_we_url_input:first').val(url).trigger('input'); - await testUtils.nextTick(); - await testUtils.dom.triggerEvents($('.modal-dialog .o_upload_media_url_button:first'), ['mousedown', 'click']); -}; -var _insertVideo = async function (wysiwyg, assert, url, checkOptions) { - await testUtils.dom.triggerEvents($('.modal-dialog .nav-link:contains("Video")'), ['mousedown', 'click']); - $('.modal-dialog #o_video_text').val(url).trigger('change'); - if (checkOptions) { - assert.strictEqual($('.modal-dialog .o_yt_option').parent().css('display'), 'block', testName + ' (options)'); - } - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:visible'), ['mousedown', 'click']); -}; -var _insertPictogram = async function (className) { - await testUtils.dom.triggerEvents($('.modal-dialog .nav-link:contains("Pictogram")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.modal-dialog .font-icons-icons .font-icons-icon.fa.' + className), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:visible'), ['mousedown', 'click']); -}; -var _valueToRatio = function (value) { - return value < 0 ? 1 / (1 - value) : 1 + value; -}; - - -QUnit.test('Image', function (assert) { - assert.expect(22); - - return weTestUtils.createWysiwyg(this.data).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var mediaTests = [{ - name: "Click ADD AN IMAGE URL in empty p: p -> img in p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - assert.strictEqual($('.note-image-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - { - name: "add an image in a table", - async: true, - content: '
' + - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - '
' + - ' aaa' + - ' ' + - ' bbb' + - ' ' + - ' ccc' + - '
' + - '
', - start: "td:eq(1):contents()[0]->18", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '
' + - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - '
' + - ' aaa' + - ' ' + - ' bbb' + - ' ' + - ' ccc' + - '
' + - '
', - check: async function () { - assert.strictEqual($('.note-image-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - { - name: "add an image in an empty table", - async: true, - content: '
' + - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
', - start: "br:eq(1)->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '
' + - '' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
' + - '
', - check: async function () { - assert.strictEqual($('.note-image-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - /* IMAGE POPOVER */ - { - name: "Click PADDING XL in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-padding .dropdown-toggle'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.note-image-popover .note-padding .dropdown-item:contains("Xl")'), ['mousedown', 'click']); - }, - }, - }, - { - name: "Click IMAGE SIZE 25% in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-imagesize .note-btn:contains(25%)'), ['mousedown', 'click']); - }, - }, - }, - { - name: "Click FLOAT RIGHT in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-float .note-icon-align-right'), ['mousedown', 'click']); - }, - }, - }, - { - name: "Click FLOAT CENTER then FLOAT LEFT in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-float .note-icon-align-center'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.note-image-popover .note-float .note-icon-align-left'), ['mousedown', 'click']); - }, - }, - }, - { - name: "Click SHAPE ROUNDED in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-imageShape .note-btn:has(.fa-square)'), ['mousedown', 'click']); - }, - }, - }, - // Remove picture - { - name: "Click REMOVE in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - content: '


', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn .note-icon-trash'), ['mousedown', 'click']); - }, - }, - }, - // Describe picture - { - name: "Click DESCRIPTION in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - check: async function () { - await altDialogOpened; - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn:contains("Description")'), ['mousedown', 'click']); - $('.modal-dialog input#alt').val('Description'); - await testUtils.nextTick(); - $('.modal-dialog input#title').val('Title'); - await testUtils.nextTick(); - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")'), ['mousedown', 'click']); - await altDialogSaved; - var value = $(wysiwyg.getValue()); - // We can't simply compare the string result of getValue - // here, as the img tag has multiple attributes and the - // output order of the attributes is non-deterministic ! - assert.strictEqual(value.prop('tagName'), 'P', "should be a p"); - var contents = value.contents(); - assert.strictEqual(contents.length, 3, "should contain a text node, then an img, then another text node"); - var firstText = contents.eq(0); - assert.notOk(firstText.prop('tagName'), 'should not have a tag name since it is a pure text node'); - assert.strictEqual(firstText.text(), "\u200b"); - var img = contents.eq(1); - assert.strictEqual(img.prop('tagName'), "IMG", "second content should be an img"); - assert.strictEqual(img.prop('className'), "img-fluid o_we_custom_image", "img should have correct class"); - assert.strictEqual(img.data('src'), "/web_editor/static/src/img/transparent.png", "img should have correct data-src"); - assert.strictEqual(img.attr('alt'), "Description", "img should have correct alt"); - // FIXME The following assert fails about once every 100-120 builds. - // Given that the code is currently being refactored and given - // the fact that this assert only tests the title attribute, commenting - // the assert is the easiest "fix" - // assert.strictEqual(img.attr('title'), "Title", "img should have correct title"); - var secondText = contents.eq(2); - assert.notOk(secondText.prop('tagName'), 'should not have a tag name since it is a pure text node'); - assert.strictEqual(secondText.text(), "\u200b"); - }, - }, - }, - ]; - - var def = Promise.resolve(); - _.each(mediaTests, function (test) { - def = def.then(function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - return _clickMedia(wysiwyg, assert, test.do, test.test); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Image crop', function (assert) { - assert.expect(5); - - return weTestUtils.createWysiwyg(this.data).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var mediaTests = [{ - name: "Click CROP 16:9 + ZOOM IN in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - check: async function () { - var zoomRatio; - var $img = $editable.find('img'); - $img.attr('src', $img.data('src')); - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn:has(.fa-crop)'), ['mousedown', 'click']); - await cropDialogOpened; - await testUtils.dom.triggerEvents($('.o_crop_image_dialog .o_crop_options .btn:contains("16:9")'), ['mousedown', 'click']); - var $zoomBtn = $('.o_crop_image_dialog .o_crop_options .btn:has(.fa-search-plus)'); - zoomRatio = _valueToRatio(Number($zoomBtn.data('value'))); - await testUtils.dom.triggerEvents($zoomBtn, ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")'), ['mousedown', 'click']); - - var $img = $(wysiwyg.getValue()).find('img.o_cropped_img_to_save'); - assert.strictEqual($img.data('aspect-ratio'), '16/9', testName + " (aspect-ratio)"); - assert.strictEqual($img.data('width'), imgWidth / zoomRatio, testName + " (zoom)"); - }, - }, - }, - { - name: "Click CROP ROTATE LEFT + FLIP HORIZONTAL in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - check: async function () { - var $img = $editable.find('img'); - $img.attr('src', $img.data('src')); - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn:has(.fa-crop)'), ['mousedown', 'click']); - await cropDialogOpened; - await testUtils.dom.triggerEvents($('.o_crop_image_dialog .o_crop_options .btn:contains("16:9")'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.o_crop_image_dialog .o_crop_options .btn:has(.fa-rotate-left)'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.o_crop_image_dialog .o_crop_options .btn:has(.fa-arrows-h)'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")'), ['mousedown', 'click']); - - var $img = $(wysiwyg.getValue()).find('img.o_cropped_img_to_save'); - assert.strictEqual($img.data('rotate'), -45, testName + " (rotate)"); - assert.strictEqual($img.data('scale-x'), -1, testName + " (flip)"); - }, - }, - }, - { - name: "Click CROP FREE in popover after adding image in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _uploadAndInsertImg('https://www.odoo.com/logo.png'); - }, - test: { - check: async function () { - var cropFactor = 10; - var $img = $editable.find('img'); - $img.attr('src', $img.data('src')); - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn:has(.fa-crop)'), ['mousedown', 'click']); - await cropDialogOpened; - var $cropperPoints = $('.modal-dialog .cropper-crop-box .cropper-point'); - var $pointW = $cropperPoints.filter('.point-w'); - var pos1 = $pointW.offset(); - var cropperWidth = $cropperPoints.filter('.point-e').offset().left - pos1.left; - $pointW.trigger($.Event("pointerdown", { - pageX: pos1.left, - pageY: pos1.top, - })); - $pointW.trigger($.Event("pointermove", { - pageX: pos1.left + (cropperWidth / cropFactor), - pageY: pos1.top, - })); - $pointW.trigger('pointerup'); - await testUtils.dom.triggerEvents($('.modal-dialog .modal-footer .btn.btn-primary:contains("Save")'), ['mousedown', 'click']); - - var $img = $(wysiwyg.getValue()).find('img.o_cropped_img_to_save'); - assert.strictEqual(Math.round($img.data('width')), Math.round(imgWidth - (imgWidth / cropFactor)), testName + " (rotate)"); - }, - }, - }, - ]; - - var def = Promise.resolve(); - _.each(mediaTests, function (test) { - def = def.then(function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - return _clickMedia(wysiwyg, assert, test.do, test.test); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Pictogram (fontawesome)', function (assert) { - assert.expect(8); - - return weTestUtils.createWysiwyg(this.data).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var mediaTests = [{ - name: "Add PICTOGRAM in empty p: p -> span.fa in p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - assert.strictEqual($('.note-icon-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - // Remove font - { - name: "Click REMOVE in popover after adding font in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - content: '


', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn .note-icon-trash'), ['mousedown', 'click']); - }, - }, - }, - // Icon size - { - name: "Click ICON SIZE then 5X in popover after adding pictogram in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-icon-popover .note-faSize .dropdown-toggle'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.note-icon-popover .note-faSize .dropdown-item:contains("5x")'), ['mousedown', 'click']); - assert.ok($('.note-icon-popover .note-faSize .dropdown-item:contains("5x")').hasClass('active'), testName + ' (popover)'); - }, - }, - }, - // Spin - { - name: "Click SPIN in popover after adding pictogram in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - content: '

\u200B\u200B

', - check: async function () { - await testUtils.dom.triggerEvents($('.note-icon-popover .note-faSpin .note-btn'), ['mousedown', 'click']); - }, - }, - }, - // Replace pictogram - { - name: "Add PICTOGRAM in empty p then replace it", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - check: async function () { - return _clickMedia(wysiwyg, assert, async function () { - await _insertPictogram('fa-heart'); - }, { - content: '

\u200B\u200B

', - }); - }, - }, - }, - { - name: "Replace PICTOGRAM (i.fa => span.fa)", - async: true, - content: '
\n' + - '
\n' + - ' \n' + - '
Other content
\n' + - '
\n' + - '
', - start: "i->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - content: '
\n' + - '
\n' + - ' \n' + - '
Other content
\n' + - '
\n' + - '
', - }, - }, - ]; - - var def = Promise.resolve(); - _.each(mediaTests, function (test) { - def = def.then(async function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - await testUtils.dom.triggerEvents($(range.sc), ['mousedown', 'click']); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - return _clickMedia(wysiwyg, assert, test.do, test.test); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - -QUnit.test('Video', function (assert) { - assert.expect(10); - - return weTestUtils.createWysiwyg(this.data).then(function (wysiwyg) { - var $editable = wysiwyg.$('.note-editable'); - - var mediaTests = [{ - name: "Add VIDEO (youtube) in empty p: p -> div.media_iframe_video after p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertVideo(wysiwyg, assert, 'https://www.youtube.com/watch?v=xxxxxxxxxxx', true); - }, - test: { - content: '


 
 


', - check: async function () { - assert.strictEqual($('.note-video-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - { - name: "Add VIDEO (youtube) in p in breakable in unbreakable in breakable: p -> div.media_iframe_video after p", - async: true, - content: '

tata yoyo

', - start: "p:contents()[0]->4", - do: async function () { - await _insertVideo(wysiwyg, assert, 'https://www.youtube.com/watch?v=xxxxxxxxxxx'); - }, - test: { - content: '

tata

' + - '
 
 
' + - '

yoyo

', - check: async function () { - assert.strictEqual($('.note-video-popover').css('display'), 'block', testName + ' (popover)'); - }, - }, - }, - // Remove video - { - name: "Click REMOVE in popover after adding video in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertVideo(wysiwyg, assert, 'https://www.youtube.com/watch?v=xxxxxxxxxxx'); - }, - test: { - content: '


', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-btn .note-icon-trash'), ['mousedown', 'click']); - }, - }, - }, - /* VIDEO POPOVER */ - // Multiple clicks - { - name: "Click FLOAT CENTER then FLOAT LEFT in popover after adding youtube video in empty p", - async: true, - content: '


', - start: "p->0", - do: async function () { - await _insertVideo(wysiwyg, assert, 'https://www.youtube.com/watch?v=xxxxxxxxxxx'); - }, - test: { - content: '


 
 


', - check: async function () { - await testUtils.dom.triggerEvents($('.note-image-popover .note-float .note-icon-align-center'), ['mousedown', 'click']); - await testUtils.dom.triggerEvents($('.note-image-popover .note-float .note-icon-align-left'), ['mousedown', 'click']); - }, - }, - }, - // Replace picture - { - name: "replace picture with video", - async: true, - content: '

', - start: "img->0", - do: async function () { - await _insertVideo(wysiwyg, assert, 'https://www.youtube.com/watch?v=xxxxxxxxxxx'); - }, - test: { - check: async function () { - assert.deepEqual(wysiwyg.getValue(), - '


 
 


', - testName); - }, - }, - }, - // Replace video - { - name: "replace video by pictogram", - async: true, - content: '


 
 


', - start: "div->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - check: async function () { - assert.deepEqual(wysiwyg.getValue(), - '

\u200B\u200B

', - testName); - }, - }, - }, - { - name: "replace video by pictogram (2)", - async: true, - content: '

aaa

 
 

bbb

', - start: "div->0", - do: async function () { - await _insertPictogram('fa-glass'); - }, - test: { - check: async function () { - assert.deepEqual(wysiwyg.getValue(), - '

aaabbb

', - testName); - }, - }, - }, - ]; - - var def = Promise.resolve(); - _.each(mediaTests, function (test) { - def = def.then(async function () { - testName = test.name; - wysiwyg.setValue(test.content); - var range = weTestUtils.select(test.start, test.end, $editable); - await testUtils.dom.triggerEvents($(range.sc), ['mousedown', 'click']); - Wysiwyg.setRange(range.sc, range.so, range.ec, range.eo); - return _clickMedia(wysiwyg, assert, test.do, test.test); - }); - }); - return def.then(function () { - wysiwyg.destroy(); - }); - }); -}); - - -}); -}); -}); -}); diff --git a/addons/web_editor/views/editor.xml b/addons/web_editor/views/editor.xml index 38d56407dbe..1d425a684e3 100644 --- a/addons/web_editor/views/editor.xml +++ b/addons/web_editor/views/editor.xml @@ -183,9 +183,6 @@