jodit
Version:
Jodit is awesome and usefully wysiwyg editor with filebrowser
1,555 lines (1,216 loc) • 38.9 kB
JavaScript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2020 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
describe('Toolbar', function() {
describe('Custom buttons', function() {
it('should create normal button in toolbar', function() {
const editor = getJodit({
toolbarAdaptive: false,
buttons: [
'image',
{
name: 'alert_some',
iconURL:
'https://xdsoft.net/jodit/build/images/icons/045-copy.png',
exec: function() {
alert('test');
}
}
]
});
const btns = Array.from(
editor.toolbar.container.querySelectorAll('[role="listitem"]')
);
expect(btns.length).equals(2);
btns.forEach(function(btn) {
const icon = btn.querySelector('.jodit-icon');
expect(icon).is.not.null;
const style = window.getComputedStyle(icon),
height = parseInt(style.height),
width = parseInt(style.width);
expect(width).to.be.above(5);
expect(height).to.be.above(5);
});
});
describe('Use controls', function() {
it('should create normal button in toolbar', function() {
const editor = getJodit({
toolbarAdaptive: false,
controls: {
alert_some: {
name: 'alert_some',
iconURL:
'https://xdsoft.net/jodit/build/images/icons/045-copy.png',
exec: function() {
editor.s.insertHTML(
'<p><span>indigo</span></p>'
);
}
}
},
buttons: ['image', 'alert_some']
});
expect(editor.toolbar.getButtonsNames().toString()).equals(
'image,alert_some'
);
clickButton('alert_some', editor);
expect(editor.value).equals(
'<p><span>indigo</span></p><p><br></p>'
);
});
});
});
describe('Set toolbar options to false', function() {
it('Should hide toolbar', function() {
const editor = getJodit({
toolbar: false
});
expect(null).equals(
editor.container.querySelector('.jodit_toolbar')
);
});
});
describe('Set toolbar options to css selector', function() {
it('Should render toolbar in different container', function() {
const div = appendTestDiv(),
editor = getJodit(
{
toolbar: div
},
appendTestArea()
);
const toolbar = document.querySelector(
'.jodit-toolbar-editor-collection'
);
const defaultContainer = editor.container.querySelector(
'.jodit-toolbar__box'
);
expect(toolbar).is.not.null;
expect(div).equals(toolbar.parentElement);
expect(defaultContainer).does.not.equal(toolbar.parentElement);
});
describe('After enable Fullsize mode', function() {
it('Should render toolbar in default container', function() {
const div = appendTestDiv(),
editor = Jodit.make(appendTestArea(), {
toolbar: div
});
const toolbar = editor.toolbar.container;
const defaultContainer = editor.defaultToolbarContainer;
editor.toggleFullSize(true);
expect(defaultContainer).equals(toolbar.parentElement);
editor.toggleFullSize(false);
expect(div).equals(toolbar.parentElement);
});
});
describe('Change toolbar container dynamically', function() {
it('Should render toolbar in different containers every call setPanel', function() {
const div1 = appendTestDiv(),
div2 = appendTestDiv(),
div3 = appendTestDiv(),
editor = getJodit();
const toolbar = editor.toolbar.container;
expect(toolbar).is.not.null;
const defaultContainer = editor.toolbarContainer;
expect(defaultContainer).is.not.null;
expect(defaultContainer).equals(toolbar.parentElement);
editor.setPanel(div1);
expect(defaultContainer).not.equals(toolbar.parentElement);
expect(div1).equals(toolbar.parentElement);
editor.setPanel(div2);
expect(div2).equals(toolbar.parentElement);
editor.setPanel(div3);
expect(div3).equals(toolbar.parentElement);
});
});
});
describe('Popups', function() {
describe('Click on dots buttons in mobile size', function() {
it('Should open popup with several buttons', function() {
getBox().style.width = '300px';
const editor = getJodit();
clickButton('dots', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
clickButton('video', popup);
const popup2 = getOpenedPopup(editor);
expect(popup2).is.not.null;
getBox().style.width = 'auto';
});
});
describe('Click on some link', function() {
describe('in the left side of editor', function() {
it('Should open inline popup with float by left editor side', function() {
const editor = getJodit({});
editor.value = 'asas <a href="#">test</a>';
simulateEvent('click', 0, editor.editor.querySelector('a'));
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
const positionPopup = offset(popup);
const positionContainer = offset(editor.container);
expect(true).equals(
positionPopup.left >= positionContainer.left
);
});
});
});
describe('Click on some button with defined popup field', function() {
it('Should open popup in toolbar', function() {
const editor = getJodit({
disablePlugins: 'mobile'
});
clickButton('video', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
});
describe('in the left side', function() {
it('Should open popup in toolbar with float by left editor side', function() {
const editor = getJodit({
buttons: ['video'],
disablePlugins: 'mobile'
});
clickButton('video', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
const positionPopup = offset(popup);
const positionContainer = offset(editor.container);
expect(true).equals(
positionPopup.left >= positionContainer.left
);
});
});
describe('in the right side', function() {
it('Should open popup in toolbar with float by left editor side', function() {
const editor = getJodit({
width: 306,
buttons: [
'video',
'video',
'video',
'video',
'video',
'video',
'video',
'video'
],
disablePlugins: 'mobile'
});
clickButton('video', editor, 'button', true);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
const positionPopup = offset(popup);
const positionContainer = offset(editor.container);
expect(
Math.abs(
positionPopup.left +
positionPopup.width -
(positionContainer.left +
positionContainer.width)
) < 10
).is.true;
});
});
});
getBox().style.width = 'auto';
it('Open and close popap after clicking in another place', function() {
const editor = getJodit({
disablePlugins: 'mobile'
});
clickButton('video', editor);
const popup = editor.ownerDocument.querySelector(
'[role="popup"][data-editor_id="' + editor.id + '"]'
);
expect(popup).is.not.null;
simulateEvent('mousedown', 0, window);
expect(popup && popup.parentNode === null).is.true;
});
describe('Open list', function() {
it('Should Open list in toolbar', function() {
const editor = getJodit({
toolbarAdaptive: false
});
clickTrigger('font', editor);
const list = getOpenedPopup(editor);
expect(
list &&
window.getComputedStyle(list).display === 'block' &&
list.parentNode !== null
).is.true;
});
describe('Change default list', function() {
it('Should change default FONT list in toolbar', function() {
const editor = getJodit({
toolbarAdaptive: false,
controls: {
font: {
list: {
'font-family: -apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,Ubuntu,Droid Sans,sans-serif;':
'Custom',
'Helvetica,sans-serif': 'Helvetica',
'Arial,Helvetica,sans-serif': 'Arial',
'Georgia,serif': 'Georgia',
'Impact,Charcoal,sans-serif': 'Impact',
'Tahoma,Geneva,sans-serif': 'Tahoma',
"'Times New Roman',Times,serif":
'Times New Roman',
'Verdana,Geneva,sans-serif': 'Verdana'
}
}
}
});
clickTrigger('font', editor);
const list = getOpenedPopup(editor);
expect(
list &&
window.getComputedStyle(list).display === 'block' &&
list.parentNode !== null
).is.true;
expect(list.textContent.match('Custom')).is.not.null;
});
it('Should change default FONT size list in toolbar', function() {
const editor = getJodit({
toolbarAdaptive: false,
controls: {
fontsize: {
list: Jodit.Array('8,9,10'.split(','))
}
}
});
clickTrigger('fontsize', editor);
const list = getOpenedPopup(editor);
expect(list.getElementsByTagName('button').length).equals(
3
);
});
});
});
it('Open and close list after clicking in another place', function() {
const editor = getJodit();
clickTrigger('fontsize', editor);
const list = getOpenedPopup(editor);
expect(list && window.getComputedStyle(list).display === 'block').is
.true;
simulateEvent('mousedown', 0, window);
expect(list && list.parentNode === null).is.true;
});
it('Open format list set H1 for current cursor position. Restore selection after that', function() {
const editor = getJodit();
editor.value = 'text2text';
const range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild, 3);
range.setEnd(editor.editor.firstChild.firstChild, 6);
editor.s.selectRange(range);
clickTrigger('paragraph', editor);
const list = getOpenedPopup(editor);
expect(window.getComputedStyle(list).display).equals('block');
clickButton('h1', list);
expect(editor.value).equals('<h1>text2text</h1>');
simulateEvent('mousedown', 0, editor.editor);
expect(list.parentNode).is.null;
editor.s.insertNode(editor.createInside.text(' a '));
expect(editor.value).equals('<h1>tex a ext</h1>');
});
it('Open video dialog and insert video by url from youtube.', function() {
const editor = getJodit({
disablePlugins: 'mobile'
});
editor.value = '';
clickButton('video', editor);
const popup = getOpenedPopup(editor);
popup.querySelector('input[name=code]').value =
'sddhttps://www.youtube.com/watch?v=7CcEYRfxUOQ'; // try wrong url
simulateEvent('submit', 0, popup.querySelector('.jodit-form'));
expect(
popup.querySelectorAll('input[name=code].jodit_error').length
).equals(1);
popup.querySelector('input[name=code]').value =
'https://www.youtube.com/watch?v=7CcEYRfxUOQ';
simulateEvent('submit', 0, popup.querySelector('.jodit-form'));
expect(sortAttributes(editor.value)).equals(
'<iframe allowfullscreen="" frameborder="0" height="345" src="https://www.youtube.com/embed/7CcEYRfxUOQ" width="400"></iframe>'
);
simulateEvent('mousedown', 0, editor.editor);
expect(popup.parentNode).is.null;
});
it('Open align list and choose Right align.', function() {
const editor = getJodit();
editor.value = 'Test';
clickTrigger('left', editor);
const list = getOpenedPopup(editor);
expect(window.getComputedStyle(list).display).equals('block');
clickButton('right', list);
expect(sortAttributes(editor.value)).equals(
'<p style="text-align:right">Test</p>'
);
simulateEvent('mousedown', 0, editor.editor);
expect(list.parentNode).is.null;
});
describe('Click inside the link', function() {
it('Should open link popup', function() {
const editor = getJodit({
observer: {
timeout: 0
}
});
editor.value = 'test test <a href="#">test</a>';
simulateEvent('click', editor.editor.querySelector('a'));
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
});
describe('Click on pencil', function() {
it('Should open edit link popup', function() {
const editor = getJodit({
observer: {
timeout: 0
}
});
editor.value = 'test test <a href="#">test</a>';
simulateEvent('click', 0, editor.editor.querySelector('a'));
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
const pencil = getButton('link', popup);
expect(pencil).is.not.null;
simulateEvent('click', pencil);
const subpopup = getOpenedPopup(editor);
expect(subpopup).is.not.null;
expect(window.getComputedStyle(subpopup).display).equals(
'block'
);
expect(popup.parentNode.parentNode.parentNode).is.not.null;
});
});
});
describe('Create table', function() {
describe('Mouse move', function() {
it('Should highlight cells in table-creator', function() {
const editor = getJodit();
clickButton('table', editor);
const list = getOpenedPopup(editor);
expect(window.getComputedStyle(list).display).equals(
'block'
);
simulateEvent(
'mousemove',
0,
list.querySelectorAll('.jodit-form__container span')[14]
);
expect(
list.querySelectorAll(
'.jodit-form__container span.jodit_hovered'
).length
).equals(10);
});
describe('In iframe mode', function() {
it('Should works same way', function() {
const editor = getJodit({
iframe: true
});
clickButton('table', editor);
const list = getOpenedPopup(editor);
expect(window.getComputedStyle(list).display).equals(
'block'
);
const divs = list.querySelectorAll(
'.jodit-form__container span'
);
expect(divs.length).to.be.above(10);
simulateEvent('mousemove', 0, divs[14]);
expect(
list.querySelectorAll(
'.jodit-form__container span.jodit_hovered'
).length
).equals(10);
});
});
});
});
});
describe('Buttons', function() {
describe('Text mode', function() {
it('Should work i18n', function() {
const editor = getJodit({
textIcons: true,
language: 'ru'
}),
editor2 = getJodit({
textIcons: true,
language: 'en'
});
const label1 = getButton('source', editor).textContent,
label2 = getButton('source', editor2).textContent;
expect(label1).does.not.equal(label2);
});
it('Should create buttons with text', function() {
const editor = getJodit({
textIcons: true
});
expect(getButton('source', editor)).is.not.null;
expect(
getButton('source', editor).querySelectorAll('svg').length
).equals(0);
});
it("Should add jodit_text_icons class to editor's container", function() {
const editor = getJodit({
textIcons: true
});
expect(
getButton(
'source',
editor
).parentElement.className.includes('text-icons_true')
).is.true;
});
it('Should set font-size more them 0', function() {
const editor = getJodit({
textIcons: true
});
expect(
parseInt(
editor.ownerWindow.getComputedStyle(
getButton('source', editor)
).fontSize,
10
)
).to.be.above(10);
});
describe('In tabs', function() {
it('Should be also only text', function() {
const editor = getJodit({
textIcons: true
});
clickButton('image', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
expect(popup.querySelectorAll('svg, img').length).equals(0);
});
});
describe('In video popup', function() {
it('Should be also only text', function() {
const editor = getJodit({
textIcons: true,
toolbarAdaptive: false
});
clickButton('video', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
expect(popup.querySelectorAll('svg, img').length).equals(0);
});
});
});
it('Remove default buttons functionality', function() {
const editor = getJodit();
expect(getButton('source', editor)).is.not.null;
editor.destruct();
const editor2 = getJodit({
removeButtons: ['source']
});
expect(getButton('source', editor2)).is.null;
});
it('Add own button', function() {
const editor = getJodit({
disablePlugins: ['mobile'],
buttons: Jodit.defaultOptions.buttons.concat([
{
name: 'insertDate',
iconURL: 'http://xdsoft.net/jodit/images/logo.png',
exec: function(editor) {
editor.s.insertHTML(
new Date('2016/03/16').toDateString()
);
}
}
])
});
const button = getButton('insertDate', editor);
expect(button).is.not.null;
editor.value = '';
simulateEvent('click', 0, button);
expect(editor.value).equals('<p>Wed Mar 16 2016</p>');
});
it('When cursor inside STRONG tag, Bold button should be selected', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
}
}),
bold = getButton('bold', editor),
italic = getButton('italic', editor);
editor.value =
'<strong>test</strong><em>test2</em><i>test3</i><b>test3</b>';
editor.s.focus();
const sel = editor.s.sel,
range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild.firstChild, 2);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
simulateEvent('mousedown', 0, editor.editor);
expect(bold.getAttribute('aria-pressed')).equals('true');
range.setStart(
editor.editor.firstChild.firstChild.nextSibling.firstChild,
2
);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
simulateEvent('mousedown', 0, editor.editor);
expect(bold.getAttribute('aria-pressed')).equals('false');
expect(italic.getAttribute('aria-pressed')).equals('true');
range.setStart(
editor.editor.firstChild.firstChild.nextSibling.nextSibling
.firstChild,
2
);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
simulateEvent('mousedown', 0, editor.editor);
expect(bold.getAttribute('aria-pressed')).equals('false');
expect(italic.getAttribute('aria-pressed')).equals('true');
range.setStart(
editor.editor.firstChild.firstChild.nextSibling.nextSibling
.nextSibling.firstChild,
2
);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
simulateEvent('mousedown', 0, editor.editor);
expect(bold.getAttribute('aria-pressed')).equals('true');
expect(italic.getAttribute('aria-pressed')).equals('false');
});
describe('Disable for mode', function() {
it('Should disable buttons which can not be used in that mode', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
}
});
editor.value =
'<strong>test</strong><em>test2</em><i>test3</i><b>test3</b>';
editor.setMode(Jodit.MODE_SOURCE);
expect(getButton('bold', editor).hasAttribute('disabled')).is
.true;
expect(getButton('source', editor).hasAttribute('disabled')).is
.false;
editor.setMode(Jodit.MODE_WYSIWYG);
expect(getButton('bold', editor).hasAttribute('disabled')).is
.false;
expect(getButton('source', editor).hasAttribute('disabled')).is
.false;
});
describe('For list', function() {
describe('enable', function() {
it('Should enable buttons which can be used in this mode', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
},
defaultMode: Jodit.MODE_SOURCE,
buttons: [
{
name: 'list_test',
mode: Jodit.MODE_SPLIT,
list: {
h1: 'insert Header 1',
h2: 'insert Header 2',
clear: 'Empty editor'
},
exec: function(editor) {
const key = this.args[0];
if (key === 'clear') {
this.val('');
return;
}
editor.s.insertHTML(
' {{test' + key + '}} '
);
},
childTemplate: function(key, value) {
return '<div>' + value + '</div>';
}
}
]
});
const btn = getButton('list_test', editor);
expect(btn).is.not.null;
expect(btn.hasAttribute('disabled')).to.be.false;
clickTrigger('list_test', editor);
const list = getOpenedPopup(editor);
expect(list).is.not.null;
expect(
list.querySelectorAll('.jodit_disabled').length
).equals(0);
});
});
describe('disable', function() {
it('Should disable buttons which can not be used in that mode', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
},
defaultMode: Jodit.MODE_SOURCE,
buttons: [
{
name: 'list_test',
mode: Jodit.MODE_WYSIWYG,
list: {
h1: 'insert Header 1',
h2: 'insert Header 2',
clear: 'Empty editor'
},
exec: function(editor) {
const key = this.args[0];
if (key === 'clear') {
this.val('');
return;
}
editor.s.insertHTML(
' {{test' + key + '}} '
);
},
childTemplate: function(key, value) {
return '<div>' + value + '</div>';
}
}
]
});
const btn = getButton('list_test', editor);
expect(btn).is.not.null;
expect(btn.hasAttribute('disabled')).to.be.true;
simulateEvent('mousedown', 0, btn);
const list = btn.querySelector('.jodit_toolbar_list');
expect(list).is.null;
});
});
});
});
describe('Set size', function() {
it('Should add modification to button', function() {
const editor = getJodit({
toolbarButtonSize: 'small'
});
expect(
getButton(
'source',
editor
).parentElement.classList.contains(
'jodit-toolbar-button_size_small'
)
).is.true;
});
describe('For list', function() {
describe('enable', function() {
it('Should enable buttons which can be used in this mode', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
},
defaultMode: Jodit.MODE_SOURCE,
buttons: [
{
name: 'list_test',
mode: Jodit.MODE_SPLIT,
list: {
h1: 'insert Header 1',
h2: 'insert Header 2',
clear: 'Empty editor'
},
exec: function(editor) {
const key = this.args[0];
if (key === 'clear') {
this.val('');
return;
}
editor.s.insertHTML(
' {{test' + key + '}} '
);
},
childTemplate: function(key, value) {
return '<div>' + value + '</div>';
}
}
]
});
const btn = getButton('list_test', editor);
expect(btn).is.not.null;
expect(btn.hasAttribute('disabled')).to.be.false;
clickTrigger('list_test', editor);
const list = getOpenedPopup(editor);
expect(list).is.not.null;
expect(
list.querySelectorAll('.jodit_disabled').length
).equals(0);
});
});
describe('disable', function() {
it('Should disable buttons which can not be used in that mode', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
},
defaultMode: Jodit.MODE_SOURCE,
buttons: [
{
name: 'list_test',
mode: Jodit.MODE_WYSIWYG,
list: {
h1: 'insert Header 1',
h2: 'insert Header 2',
clear: 'Empty editor'
},
exec: function(editor) {
const key = this.args[0];
if (key === 'clear') {
this.val('');
return;
}
editor.s.insertHTML(
' {{test' + key + '}} '
);
},
childTemplate: function(key, value) {
return '<div>' + value + '</div>';
}
}
]
});
const btn = getButton('list_test', editor);
expect(btn).is.not.null;
expect(btn.hasAttribute('disabled')).to.be.true;
simulateEvent('mousedown', 0, btn);
const list = btn.querySelector('.jodit_toolbar_list');
expect(list).is.null;
});
});
});
});
describe('Allow tab navigation', function() {
describe('Enable', function() {
it('Should set tabindex=0 for all buttons', function() {
const editor = getJodit({
allowTabNavigation: true
});
expect(
getButton(
'source',
editor
).getAttribute('tabindex')
).equals('0');
});
});
describe('Disable', function() {
it('Should set tabindex=-1 for all buttons', function() {
const editor = getJodit({
allowTabNavigation: false // default
});
expect(
getButton(
'source',
editor
).getAttribute('tabindex')
).equals('-1');
});
});
});
it('When cursor inside SPAN tag with style="font-weight: bold" or style="font-weight: 700", Bold button should be selected', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
}
}),
bold = getButton('bold', editor);
editor.value = '<span style="font-weight: bold">test</span>';
editor.s.focus();
const sel = editor.s.sel,
range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild.firstChild, 2);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
simulateEvent('mousedown', 0, editor.editor);
expect(bold.getAttribute('aria-pressed')).equals('true');
});
describe('Check Redo Undo functionality', function() {
it('Should change disable in icon then then can not be executed', function() {
const area = appendTestArea();
area.value = 'top';
const editor = new Jodit(area, {
observer: {
timeout: 0 // disable delay
}
});
editor.value = 'Test';
expect(getButton('undo', editor).hasAttribute('disabled')).is
.false;
expect(getButton('redo', editor).hasAttribute('disabled')).is
.true;
clickButton('undo', editor);
expect(getButton('undo', editor).hasAttribute('disabled')).is
.true;
expect(getButton('redo', editor).hasAttribute('disabled')).is
.false;
expect(editor.value).equals('<p>top</p>');
});
});
it('Full size button', function() {
const editor = getJodit({
observer: {
timeout: 0 // disable delay
}
});
clickButton('fullsize', editor);
let node = editor.container.parentNode;
while (node && node.nodeType !== Node.DOCUMENT_NODE) {
expect(node.classList.contains('jodit-fullsize_box')).equals(
true
);
node = node.parentNode;
}
});
describe('Extra buttons', function() {
describe('Options extraButtons', function() {
it('Should add extra buttons', function() {
const editor = getJodit({
extraButtons: [
{
name: 'adddate',
exec: function(editor) {
const a = editor.createInside.text('111');
editor.s.insertNode(a);
}
}
]
});
editor.value = '';
expect(getButton('adddate', editor)).is.not.null;
clickButton('adddate', editor);
expect(editor.value).equals('<p>111</p>');
});
describe('extraButtons always append in the end', function() {
it('Should add extra buttons on postion by buttons potions', function() {
const editor = getJodit({
buttons: [
'indent',
'outdent',
'bold',
'adddate',
'dots'
],
disablePlugins: 'mobile',
extraButtons: [
{
name: 'adddate',
exec: function(editor) {
const a = editor.createInside.text(
'111'
);
editor.s.insertNode(a);
}
}
]
});
expect(
editor.toolbar.getButtonsNames().toString()
).equals('indent,outdent,bold,adddate,dots,adddate');
});
});
});
});
describe('Add button', function() {
it('Should create buttons in toolbar', function() {
const editor = getJodit({
buttons: ['indent', 'outdent', 'bold', 'customxxx'],
disablePlugins: 'mobile'
});
expect(getButton('indent', editor)).is.not.null;
expect(getButton('outdent', editor)).is.not.null;
expect(getButton('bold', editor)).is.not.null;
expect(getButton('customxxx', editor)).is.not.null;
expect(getButton('source', editor)).is.null;
});
});
describe('Button Bold', function() {
describe('In collapsed selection', function() {
it('Should reactivate Bold button after second click and move cursor out of Strong element', function() {
const editor = getJodit({
buttons: ['bold']
});
editor.value = '<p>test</p>';
editor.s.setCursorAfter(
editor.editor.firstChild.firstChild
);
clickButton('bold', editor);
editor.s.insertHTML('text');
clickButton('bold', editor);
editor.s.insertHTML('text');
expect(editor.value).equals(
'<p>test<strong>text</strong>text</p>'
);
});
});
describe('Not collapsed selection', function() {
it('Should reactivate Bold button after second click and move cursor out of Strong element', function() {
const editor = getJodit({
buttons: ['bold']
});
editor.value = 'test test test';
const range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild, 0);
range.setEnd(editor.editor.firstChild.firstChild, 4);
editor.s.selectRange(range);
clickButton('bold', editor);
expect(editor.value).equals(
'<p><strong>test</strong> test test</p>'
);
});
});
});
describe('Active button', function() {
it('Should not be activated then element has default style', function() {
const editor = getJodit({
observer: {
timeout: 0
}
});
editor.value = '<p>test<strong>bold</strong></p>';
editor.s.focus();
const p = editor.editor.firstChild;
editor.s.setCursorAfter(p.firstChild);
simulateEvent('mousedown', 0, p);
const bold = getButton('bold', editor);
const align = getButton('left', editor);
expect(bold.getAttribute('aria-pressed')).equals('false');
expect(align.getAttribute('aria-pressed')).equals('false');
editor.s.setCursorIn(p.querySelector('strong').firstChild);
simulateEvent('mousedown', 0, p);
// editor.s.insertHTML('ddd');
expect(bold.getAttribute('aria-pressed')).equals('true');
expect(align.getAttribute('aria-pressed')).equals('false');
p.style.textAlign = 'right';
simulateEvent('mousedown', 0, p);
expect(bold.getAttribute('aria-pressed')).equals('true');
expect(align.getAttribute('aria-pressed')).equals('true');
});
describe('In list', function() {
describe('Format block button', function() {
it('Should be activated then element has some tagname', function() {
const editor = getJodit({
observer: {
timeout: 0
}
});
editor.value =
'<p>test</p><h1>test</h1><code>test</code>';
editor.s.focus();
const p = editor.editor.firstChild;
const paragraph = getButton('paragraph', editor);
expect(paragraph).is.not.null;
editor.s.setCursorAfter(p.firstChild);
simulateEvent('mousedown', 0, p);
expect(paragraph.getAttribute('aria-pressed')).equals(
'false'
);
editor.s.setCursorIn(editor.editor.childNodes[1]);
simulateEvent('mousedown', 0, p);
expect(paragraph.getAttribute('aria-pressed')).equals(
'true'
);
clickTrigger('paragraph', editor);
const header = getOpenedPopup(editor).querySelector(
'[class*=h1]'
);
expect(header.getAttribute('aria-pressed')).equals(
'true'
);
});
});
});
describe('Select text with several properties', function() {
it('Should select all buttons with conditions', function() {
const editor = getJodit({
observer: {
timeout: 0
}
});
editor.value = '<em><strong><u>bold</u></strong></em>';
editor.s.focus();
const range = editor.s.createRange();
range.setStartBefore(editor.editor.firstChild);
range.setEndAfter(editor.editor.firstChild);
editor.s.selectRange(range);
const bold = getButton('bold', editor);
const italic = getButton('italic', editor);
const underline = getButton('underline', editor);
expect(bold.getAttribute('aria-pressed')).equals('true');
expect(italic.getAttribute('aria-pressed')).equals('true');
expect(underline.getAttribute('aria-pressed')).equals(
'true'
);
});
});
});
describe('Disable button', function() {
describe('Cut and Copy', function() {
describe('Cut', function() {
it('Should be activated editor has some selected text', function() {
const editor = getJodit({
toolbarAdaptive: false,
observer: {
timeout: 0
}
});
const cut = getButton('cut', editor);
editor.value = '<p>test<strong>bold</strong></p>';
editor.s.focus();
expect(cut.hasAttribute('disabled')).is.true;
const p = editor.editor.firstChild;
editor.s.select(p.firstChild);
expect(cut.hasAttribute('disabled')).is.false;
});
});
describe('Copy', function() {
it('Should be activated editor has some selected text', function() {
const editor = getJodit({
toolbarAdaptive: false,
observer: {
timeout: 0
}
});
const copy = getButton('copy', editor);
editor.value = '<p>test<strong>bold</strong></p>';
editor.s.focus();
expect(copy.hasAttribute('disabled')).is.true;
const p = editor.editor.firstChild;
editor.s.select(p.firstChild);
expect(copy.hasAttribute('disabled')).is.false;
});
});
});
});
});
describe('Commands', function() {
it('Click on Source button should change current mode', function() {
const editor = getJodit();
clickButton('source', editor);
expect(editor.getMode()).equals(Jodit.MODE_SOURCE);
});
it('Click on Bold button should wrap current selection in <strong>', function() {
const editor = getJodit();
editor.value = 'Text to text';
editor.s.focus();
const range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild, 3);
range.setEnd(editor.editor.firstChild.firstChild, 10);
editor.s.selectRange(range);
clickButton('bold', editor);
expect(editor.value).equals('<p>Tex<strong>t to te</strong>xt</p>');
});
it('Click on Italic button when selection is collapsed should create new <em> element and set cursor into it', function() {
const editor = getJodit();
editor.value = 'Text to text';
editor.s.focus();
const range = editor.s.createRange();
range.setStart(editor.editor.firstChild.firstChild, 0);
range.collapse(true);
editor.s.selectRange(range);
clickButton('italic', editor);
editor.s.insertHTML('test');
expect(editor.value).equals('<p><em>test</em>Text to text</p>');
});
});
describe('In fileBrowser', function() {
describe('Hide buttons ', function() {
it('should hide toolbar buttons', function() {
const editor = getJodit({
filebrowser: {
buttons: Jodit.Array([
'filebrowser.list',
'filebrowser.tiles',
'filebrowser.sort'
]),
ajax: {
url: 'https://xdsoft.net/jodit/connector/index.php'
}
}
});
clickButton('image', editor);
const popup = getOpenedPopup(editor);
expect(popup).is.not.null;
simulateEvent('click', 0, popup.querySelector('button'));
const dialog = getOpenedDialog(editor);
expect(dialog).is.not.null;
expect(3).equals(
dialog.querySelectorAll(
'.jodit-dialog__header .jodit-dialog__header-title button,' +
'.jodit-dialog__header .jodit-dialog__header-title select'
).length
);
});
});
});
describe('One toolbar for several editors', function() {
it('Should create one Jodit instance but with several edit places', function() {
const toolbarBox = appendTestDiv(),
firstEditPlace = appendTestDiv('firstEditPlace'),
secondEditPlace = appendTestDiv('secondEditPlace'),
thirdEditPlace = appendTestDiv('thirdEditPlace'),
editor = Jodit.make(firstEditPlace);
editor.setPanel(toolbarBox);
editor.value = 'first';
editor.addPlace(secondEditPlace);
editor.value = 'second';
editor.addPlace(thirdEditPlace);
editor.value = 'third';
expect(Jodit.instances.firstEditPlace).equals(editor);
expect(Jodit.instances.secondEditPlace).equals(undefined);
expect(Jodit.instances.thirdEditPlace).equals(undefined);
editor.destruct();
expect(firstEditPlace.innerHTML).equals('<p>first</p>');
expect(secondEditPlace.innerHTML).equals('<p>second</p>');
expect(thirdEditPlace.innerHTML).equals('<p>third</p>');
});
describe('For all instances you can set self options', function() {
it('Should change options for all instances', function() {
const toolbarBox = appendTestDiv(),
firstEditPlace = appendTestDiv('firstEditPlace'),
secondEditPlace = appendTestDiv('secondEditPlace'),
thirdEditPlace = appendTestDiv('thirdEditPlace'),
editor = Jodit.make(firstEditPlace, {
disablePlugins: ['WrapTextNodes']
});
editor.setPanel(toolbarBox);
editor.value = 'first';
editor.addPlace(secondEditPlace, {
readonly: true,
showCharsCounter: false,
showWordsCounter: false,
showXPathInStatusbar: false
});
editor.value = 'second';
editor.addPlace(thirdEditPlace, {
readonly: false,
showCharsCounter: false,
showWordsCounter: false,
showXPathInStatusbar: false
});
editor.value = 'third';
const editPlaces = editor.ownerDocument.querySelectorAll(
'.jodit-wysiwyg'
);
expect(editPlaces.length).equals(3);
simulateEvent('focus', 0, editPlaces[0]);
expect(editor.options.readonly).is.false;
expect(editor.options.showCharsCounter).is.true;
simulateEvent('focus', 0, editPlaces[1]);
expect(editor.options.readonly).is.true;
expect(editor.options.showCharsCounter).is.false;
simulateEvent('focus', 0, editPlaces[2]);
expect(editor.options.readonly).is.false;
expect(editor.options.showCharsCounter).is.false;
});
});
});
});