forked from ungleich-public/dynamicweb
552 lines
21 KiB
JavaScript
552 lines
21 KiB
JavaScript
/* global document */
|
|
import Clipboard from '../../../static/cms/js/modules/cms.clipboard';
|
|
import $ from 'jquery';
|
|
import ls from 'local-storage';
|
|
import CMS, { Helpers } from '../../../static/cms/js/modules/cms.base';
|
|
|
|
import { rewire, resetRewire, registerActual } from './helpers/rewire';
|
|
|
|
vi.mock('../../../static/cms/js/modules/cms.plugins', async () => {
|
|
const { lazyMock } = await import('./helpers/rewire');
|
|
|
|
return lazyMock('cms.plugins', { default: 'Plugin' });
|
|
});
|
|
|
|
// cms.plugins is part of the plugins/structureboard/clipboard import cycle, so
|
|
// the original cannot be loaded from inside the factory - it would deadlock
|
|
registerActual('cms.plugins', await vi.importActual('../../../static/cms/js/modules/cms.plugins'));
|
|
|
|
window.CMS = CMS;
|
|
CMS.$ = $;
|
|
CMS.API = CMS.API || {};
|
|
CMS.API.Helpers = Helpers;
|
|
CMS.Clipboard = Clipboard;
|
|
CMS._instances = [];
|
|
|
|
describe('CMS.Clipboard', function() {
|
|
fixture.setBase('cms/tests/frontend/unit/fixtures');
|
|
|
|
it('creates a Clipboard class', function() {
|
|
expect(CMS.Clipboard).toBeDefined();
|
|
});
|
|
|
|
it('has public API', function() {
|
|
expect(CMS.Clipboard.prototype.clear).toEqual(jasmine.any(Function));
|
|
});
|
|
|
|
describe('instance', function() {
|
|
var clipboard;
|
|
beforeEach(function(done) {
|
|
fixture.load('clipboard.html');
|
|
$(function() {
|
|
clipboard = new CMS.Clipboard();
|
|
spyOn(clipboard, 'populate');
|
|
spyOn(clipboard, '_handleExternalUpdate');
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
fixture.cleanup();
|
|
});
|
|
|
|
it('has no options', function() {
|
|
expect(clipboard.options).toEqual(undefined);
|
|
});
|
|
|
|
it('has ui', function() {
|
|
expect(clipboard.ui).toEqual(jasmine.any(Object));
|
|
expect(Object.keys(clipboard.ui)).toContain('clipboard');
|
|
expect(Object.keys(clipboard.ui)).toContain('triggers');
|
|
expect(Object.keys(clipboard.ui)).toContain('triggerRemove');
|
|
expect(Object.keys(clipboard.ui)).toContain('pluginsList');
|
|
expect(Object.keys(clipboard.ui)).toContain('document');
|
|
expect(Object.keys(clipboard.ui).length).toEqual(5);
|
|
});
|
|
|
|
it('has its own private modal instance', function() {
|
|
expect(clipboard.modal).toEqual(jasmine.any(Object));
|
|
// there's no reliable way to check if it's really modal,
|
|
// since Class.js has no instanceof, but this will suffice
|
|
expect(clipboard.modal.ui.modal).toEqual(jasmine.any(Object));
|
|
});
|
|
|
|
it('sets up events to open the modal (enabled)', function() {
|
|
expect(clipboard.ui.triggers).toHandle('click.cms.clipboard');
|
|
|
|
spyOn(clipboard.modal, 'open');
|
|
clipboard.ui.triggers.trigger('click.cms.clipboard');
|
|
expect(clipboard.modal.open).toHaveBeenCalledWith({
|
|
html: clipboard.ui.pluginsList,
|
|
title: 'Clipboard',
|
|
width: 400,
|
|
height: 117
|
|
});
|
|
});
|
|
|
|
it('sets up events to open the modal (disabled)', function() {
|
|
expect(clipboard.ui.triggers).toHandle('click.cms.clipboard');
|
|
spyOn(clipboard.modal, 'open');
|
|
clipboard.ui.triggers.parent().addClass('cms-toolbar-item-navigation-disabled');
|
|
clipboard.ui.triggers.trigger('click.cms.clipboard');
|
|
expect(clipboard.modal.open).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('sets up events to open the modal which trigger click on document', function(done) {
|
|
expect(clipboard.ui.triggers).toHandle('click.cms.clipboard');
|
|
spyOn(clipboard.modal, 'open');
|
|
$(document).on('click.cms.toolbar', function() {
|
|
$(this).off('click.cms.toolbar');
|
|
done();
|
|
});
|
|
|
|
clipboard.ui.triggers.trigger('click.cms.clipboard');
|
|
});
|
|
|
|
it('sets up events to clear the clipboard (enabled)', function() {
|
|
spyOn(clipboard, 'clear').and.callFake(function(callback) {
|
|
expect(callback).not.toBeDefined();
|
|
clipboard._cleanupDOM();
|
|
});
|
|
spyOn(clipboard.modal, 'close');
|
|
spyOn(clipboard, '_isClipboardModalOpen').and.returnValue(true);
|
|
expect(clipboard.ui.triggerRemove).toHandle('click.cms.clipboard');
|
|
expect(clipboard.ui.triggers.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(clipboard.ui.triggerRemove.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
var click = spyOnEvent(clipboard.ui.document, 'click.cms.toolbar');
|
|
|
|
clipboard.ui.triggerRemove.trigger('click');
|
|
expect(clipboard.clear).toHaveBeenCalled();
|
|
expect(clipboard.modal.close).toHaveBeenCalled();
|
|
expect(clipboard.ui.triggers.parent()).toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(clipboard.ui.triggerRemove.parent()).toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(click).toHaveBeenTriggered();
|
|
});
|
|
|
|
it('sets up events to clear the clipboard (enabled) 2', function() {
|
|
spyOn(clipboard, 'clear').and.callFake(function(callback) {
|
|
expect(callback).not.toBeDefined();
|
|
clipboard._cleanupDOM();
|
|
});
|
|
spyOn(clipboard.modal, 'close');
|
|
spyOn(clipboard, '_isClipboardModalOpen').and.returnValue(false);
|
|
expect(clipboard.ui.triggerRemove).toHandle('click.cms.clipboard');
|
|
expect(clipboard.ui.triggers.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(clipboard.ui.triggerRemove.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
var click = spyOnEvent(clipboard.ui.document, 'click.cms.toolbar');
|
|
|
|
clipboard.ui.triggerRemove.trigger('click');
|
|
expect(clipboard.clear).toHaveBeenCalled();
|
|
expect(clipboard.modal.close).not.toHaveBeenCalled();
|
|
expect(clipboard.ui.triggers.parent()).toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(clipboard.ui.triggerRemove.parent()).toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(click).toHaveBeenTriggered();
|
|
});
|
|
|
|
it('sets up events to clear the clipboard (disabled)', function() {
|
|
spyOn(clipboard, 'clear').and.callFake(function(callback) {
|
|
expect(callback).not.toBeDefined();
|
|
clipboard._cleanupDOM();
|
|
});
|
|
spyOn(clipboard.modal, 'close');
|
|
var click = spyOnEvent(clipboard.ui.document, 'click.cms.toolbar');
|
|
|
|
clipboard.ui.triggerRemove.parent().addClass('cms-toolbar-item-navigation-disabled');
|
|
|
|
clipboard.ui.triggerRemove.trigger('click');
|
|
expect(clipboard.clear).not.toHaveBeenCalled();
|
|
expect(clipboard.modal.close).not.toHaveBeenCalled();
|
|
expect(click).not.toHaveBeenTriggered();
|
|
});
|
|
|
|
it('sets up events to clear "add plugin" placeholder', function() {
|
|
$('<div class="cms-add-plugin-placeholder"></div>').prependTo('body');
|
|
CMS.API.Helpers.dispatchEvent('modal-loaded', { instance: clipboard.modal });
|
|
expect($('.cms-add-plugin-placeholder')).not.toExist();
|
|
|
|
$('<div class="cms-add-plugin-placeholder"></div>').prependTo('body');
|
|
CMS.API.Helpers.dispatchEvent('modal-closed', { instance: clipboard.modal });
|
|
expect($('.cms-add-plugin-placeholder')).not.toExist();
|
|
});
|
|
|
|
it('sets up events to move pluginList back to the modal', function() {
|
|
$('<div class="cms-modal"></div>').prependTo(fixture.el);
|
|
clipboard = new CMS.Clipboard();
|
|
|
|
CMS.API.Tooltip = {
|
|
hide: jasmine.createSpy()
|
|
};
|
|
|
|
clipboard.ui.triggers.trigger('click');
|
|
expect(clipboard.ui.clipboard).not.toContainElement(clipboard.ui.pluginList);
|
|
|
|
// modal is closed
|
|
CMS.API.Helpers.dispatchEvent('modal-closed', { instance: clipboard.modal });
|
|
expect(clipboard.ui.clipboard).toContainElement(clipboard.ui.pluginsList);
|
|
|
|
clipboard.ui.triggers.trigger('click');
|
|
expect(clipboard.ui.clipboard).not.toContainElement(clipboard.ui.pluginList);
|
|
|
|
// this modal instance is being opened again
|
|
CMS.API.Helpers.dispatchEvent('modal-load', { instance: clipboard.modal });
|
|
expect(clipboard.ui.clipboard).toContainElement(clipboard.ui.pluginsList);
|
|
|
|
clipboard.ui.triggers.trigger('click');
|
|
expect(clipboard.ui.clipboard).not.toContainElement(clipboard.ui.pluginList);
|
|
|
|
// new modal instance overtook and is opening
|
|
CMS.API.Helpers.dispatchEvent('modal-load', { instance: clipboard.modal });
|
|
expect(clipboard.ui.clipboard).toContainElement(clipboard.ui.pluginsList);
|
|
|
|
// manually cleaning up, otherwise PhantomJS fails
|
|
$('.cms-modal').remove();
|
|
});
|
|
|
|
it('sets up event to handle external updates', () => {
|
|
spyOn(ls, 'on').and.callFake(function(name) {
|
|
expect(name).toEqual('cms-clipboard');
|
|
});
|
|
spyOn(CMS.Clipboard.prototype, '_handleExternalUpdate');
|
|
|
|
clipboard = new CMS.Clipboard();
|
|
expect(CMS.Clipboard.prototype._handleExternalUpdate).not.toHaveBeenCalled();
|
|
|
|
ls.on.and.callFake(function(name, fn) {
|
|
expect(name).toEqual('cms-clipboard');
|
|
fn({ x: 1 });
|
|
});
|
|
clipboard = new CMS.Clipboard();
|
|
expect(CMS.Clipboard.prototype._handleExternalUpdate).toHaveBeenCalledWith({
|
|
x: 1
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('.clear()', function() {
|
|
var clipboard;
|
|
beforeEach(function(done) {
|
|
fixture.load('clipboard.html');
|
|
CMS.API.Toolbar = {
|
|
openAjax: jasmine.createSpy()
|
|
};
|
|
CMS.config = {
|
|
csrf: 'test_csrf',
|
|
clipboard: {
|
|
url: 'clear-clipboard'
|
|
}
|
|
};
|
|
$(function() {
|
|
clipboard = new CMS.Clipboard();
|
|
spyOn(clipboard, 'populate');
|
|
spyOn(clipboard, '_handleExternalUpdate');
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
fixture.cleanup();
|
|
});
|
|
|
|
it('makes a request to the API', function() {
|
|
clipboard.clear();
|
|
expect(CMS.API.Toolbar.openAjax).toHaveBeenCalledWith({
|
|
url: `clear-clipboard?cms_path=${CMS_PATH}`,
|
|
post: '{ "csrfmiddlewaretoken": "test_csrf" }',
|
|
callback: jasmine.any(Function)
|
|
});
|
|
|
|
spyOn($, 'noop');
|
|
clipboard.clear($.noop);
|
|
expect(CMS.API.Toolbar.openAjax).toHaveBeenCalledWith({
|
|
url: `clear-clipboard?cms_path=${CMS_PATH}`,
|
|
post: '{ "csrfmiddlewaretoken": "test_csrf" }',
|
|
callback: jasmine.any(Function)
|
|
});
|
|
CMS.API.Toolbar.openAjax.calls.mostRecent().args[0].callback();
|
|
expect($.noop).toHaveBeenCalled();
|
|
});
|
|
|
|
it('resets plugins "paste" menu item to show correct tooltip', function() {
|
|
var statesBefore = [
|
|
{
|
|
empty: 'none',
|
|
restricted: 'block',
|
|
disabled: 'none'
|
|
},
|
|
{
|
|
empty: 'none',
|
|
restricted: 'none',
|
|
disabled: 'block'
|
|
},
|
|
{
|
|
empty: 'block',
|
|
restricted: 'none',
|
|
disabled: 'none'
|
|
},
|
|
{
|
|
empty: 'none',
|
|
restricted: 'none',
|
|
disabled: 'none'
|
|
}
|
|
];
|
|
|
|
var stateAfter = {
|
|
empty: 'block',
|
|
restricted: 'none',
|
|
disabled: 'none'
|
|
};
|
|
|
|
statesBefore.forEach(function(obj, index) {
|
|
var el = $('#submenu-item-' + (index + 1));
|
|
Object.keys(obj).forEach(function(key) {
|
|
var value = obj[key];
|
|
expect(el.find('.cms-submenu-item-paste-tooltip-' + key)).toHaveCss({
|
|
display: value
|
|
});
|
|
});
|
|
});
|
|
|
|
clipboard.clear();
|
|
|
|
statesBefore.forEach(function(obj, index) {
|
|
var el = $('#submenu-item-' + (index + 1));
|
|
Object.keys(stateAfter).forEach(function(key) {
|
|
var value = stateAfter[key];
|
|
expect(el.find('.cms-submenu-item-paste-tooltip-' + key)).toHaveCss({
|
|
display: value
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('_isClipboardModalOpen()', function() {
|
|
var clipboard;
|
|
beforeEach(function(done) {
|
|
fixture.load('clipboard.html');
|
|
CMS.API.Toolbar = {
|
|
openAjax: jasmine.createSpy()
|
|
};
|
|
CMS.config = {
|
|
csrf: 'test_csrf',
|
|
clipboard: {
|
|
url: 'clear-clipboard'
|
|
}
|
|
};
|
|
$(function() {
|
|
$('<div class="cms-modal"><div class="cms-modal-body"></div></div>').prependTo(fixture.el);
|
|
clipboard = new CMS.Clipboard();
|
|
spyOn(clipboard, 'populate');
|
|
spyOn(clipboard, '_handleExternalUpdate');
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
$('.cms-modal').remove();
|
|
fixture.cleanup();
|
|
});
|
|
|
|
it('returns true if modal is open', function() {
|
|
clipboard.modal.ui.modalBody.append('<div class="cms-clipboard-containers"></div>');
|
|
expect(clipboard._isClipboardModalOpen()).toEqual(true);
|
|
});
|
|
|
|
it('returns false if modal is closed', function() {
|
|
expect(clipboard._isClipboardModalOpen()).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('_handleExternalUpdate()', function() {
|
|
var clipboard;
|
|
const pluginConstructor = jasmine.createSpy();
|
|
class FakePlugin {
|
|
constructor(...args) {
|
|
pluginConstructor(...args);
|
|
}
|
|
}
|
|
FakePlugin._updateClipboard = jasmine.createSpy();
|
|
beforeEach(function(done) {
|
|
fixture.load('clipboard.html');
|
|
$(function() {
|
|
clipboard = new CMS.Clipboard();
|
|
spyOn(clipboard, 'populate');
|
|
spyOn(clipboard, '_cleanupDOM');
|
|
spyOn(clipboard, '_enableTriggers');
|
|
rewire('Plugin', FakePlugin);
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
pluginConstructor.calls.reset();
|
|
FakePlugin._updateClipboard.calls.reset();
|
|
resetRewire('Plugin');
|
|
fixture.cleanup();
|
|
});
|
|
|
|
it('does not do anything if the timestamp is lower', function() {
|
|
clipboard.currentClipboardData = {
|
|
html: 'no matter',
|
|
data: {},
|
|
timestamp: 10
|
|
};
|
|
|
|
expect(
|
|
clipboard._handleExternalUpdate(
|
|
JSON.stringify({
|
|
timestamp: 1
|
|
})
|
|
)
|
|
).not.toBeDefined();
|
|
|
|
expect(pluginConstructor).not.toHaveBeenCalled();
|
|
expect(FakePlugin._updateClipboard).not.toHaveBeenCalled();
|
|
expect(clipboard._cleanupDOM).not.toHaveBeenCalled();
|
|
expect(clipboard._enableTriggers).not.toHaveBeenCalled();
|
|
expect(clipboard.currentClipboardData).toEqual({
|
|
timestamp: 1
|
|
});
|
|
});
|
|
|
|
it('does not do anything if the plugin id is the same as it currently was', function() {
|
|
clipboard.currentClipboardData = {
|
|
html: 'no matter',
|
|
data: { plugin_id: 1 },
|
|
timestamp: 10
|
|
};
|
|
|
|
expect(
|
|
clipboard._handleExternalUpdate(
|
|
JSON.stringify({
|
|
timestamp: 15,
|
|
data: {
|
|
plugin_id: 1
|
|
}
|
|
})
|
|
)
|
|
).not.toBeDefined();
|
|
|
|
expect(pluginConstructor).not.toHaveBeenCalled();
|
|
expect(FakePlugin._updateClipboard).not.toHaveBeenCalled();
|
|
expect(clipboard._cleanupDOM).not.toHaveBeenCalled();
|
|
expect(clipboard._enableTriggers).not.toHaveBeenCalled();
|
|
expect(clipboard.currentClipboardData).toEqual({
|
|
timestamp: 15,
|
|
data: {
|
|
plugin_id: 1
|
|
}
|
|
});
|
|
});
|
|
|
|
it('cleans up the dom if the clipboard was cleared on external update', function() {
|
|
clipboard.currentClipboardData = {
|
|
html: 'no matter',
|
|
data: { plugin_id: 1 },
|
|
timestamp: 10
|
|
};
|
|
|
|
expect(
|
|
clipboard._handleExternalUpdate(
|
|
JSON.stringify({
|
|
timestamp: 15,
|
|
data: {},
|
|
html: ''
|
|
})
|
|
)
|
|
).not.toBeDefined();
|
|
|
|
expect(pluginConstructor).not.toHaveBeenCalled();
|
|
expect(FakePlugin._updateClipboard).not.toHaveBeenCalled();
|
|
expect(clipboard._cleanupDOM).toHaveBeenCalledTimes(1);
|
|
expect(clipboard._enableTriggers).not.toHaveBeenCalled();
|
|
expect(clipboard.currentClipboardData).toEqual({
|
|
timestamp: 15,
|
|
data: {},
|
|
html: ''
|
|
});
|
|
});
|
|
|
|
it('enables the clipboard menu items if the clipboard was updated externally', function() {
|
|
clipboard.currentClipboardData = {
|
|
html: '',
|
|
data: {},
|
|
timestamp: 10
|
|
};
|
|
|
|
expect(
|
|
clipboard._handleExternalUpdate(
|
|
JSON.stringify({
|
|
timestamp: 15,
|
|
data: { plugin_id: 1 },
|
|
html: '<div></div>'
|
|
})
|
|
)
|
|
).not.toBeDefined();
|
|
|
|
expect(pluginConstructor).toHaveBeenCalled();
|
|
expect(FakePlugin._updateClipboard).toHaveBeenCalled();
|
|
expect(clipboard._cleanupDOM).not.toHaveBeenCalled();
|
|
expect(clipboard._enableTriggers).toHaveBeenCalled();
|
|
expect(clipboard.currentClipboardData).toEqual({
|
|
timestamp: 15,
|
|
data: { plugin_id: 1 },
|
|
html: '<div></div>'
|
|
});
|
|
});
|
|
|
|
it('updates the clipboard with the new plugin', function() {
|
|
clipboard.currentClipboardData = {
|
|
html: '<span></span>',
|
|
data: { plugin_id: 10 },
|
|
timestamp: 10
|
|
};
|
|
|
|
expect(
|
|
clipboard._handleExternalUpdate(
|
|
JSON.stringify({
|
|
timestamp: 15,
|
|
data: { plugin_id: 11 },
|
|
html: '<div></div>'
|
|
})
|
|
)
|
|
).not.toBeDefined();
|
|
|
|
expect(pluginConstructor).toHaveBeenCalled();
|
|
expect(FakePlugin._updateClipboard).toHaveBeenCalled();
|
|
expect(clipboard._cleanupDOM).not.toHaveBeenCalled();
|
|
expect(clipboard._enableTriggers).not.toHaveBeenCalled();
|
|
expect(clipboard.currentClipboardData).toEqual({
|
|
timestamp: 15,
|
|
data: { plugin_id: 11 },
|
|
html: '<div></div>'
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('_enableTriggers()', function() {
|
|
var clipboard;
|
|
beforeEach(function(done) {
|
|
fixture.load('clipboard.html');
|
|
$(function() {
|
|
clipboard = new CMS.Clipboard();
|
|
spyOn(clipboard, 'populate');
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function() {
|
|
fixture.cleanup();
|
|
});
|
|
|
|
it('removes disabled classes from menu items', function() {
|
|
clipboard.ui.triggers.parent().addClass('cms-toolbar-item-navigation-disabled');
|
|
clipboard.ui.triggerRemove.parent().addClass('cms-toolbar-item-navigation-disabled');
|
|
|
|
clipboard._enableTriggers();
|
|
|
|
expect(clipboard.ui.triggers.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
expect(clipboard.ui.triggerRemove.parent()).not.toHaveClass('cms-toolbar-item-navigation-disabled');
|
|
});
|
|
});
|
|
});
|