dynamicweb/cms/tests/frontend/unit/cms.toolbar.test.js

973 lines
35 KiB
JavaScript

'use strict';
import CMS, { Helpers, KEYS } from '../../../static/cms/js/modules/cms.base';
import Sideframe from '../../../static/cms/js/modules/cms.sideframe';
import Messages from '../../../static/cms/js/modules/cms.messages';
import $ from 'jquery';
import Toolbar from '../../../static/cms/js/modules/cms.toolbar';
import Modal from '../../../static/cms/js/modules/cms.modal';
import { rewire, resetRewire } from './helpers/rewire';
vi.mock('../../../static/cms/js/modules/loader', async () => {
const { lazyMock, registerActual } = await import('./helpers/rewire');
registerActual('loader', await vi.importActual('../../../static/cms/js/modules/loader'));
return lazyMock('loader', { showLoader: 'showLoader', hideLoader: 'hideLoader' });
});
vi.mock('../../../static/cms/js/modules/cms.modal', async () => {
const { lazyMock, registerActual } = await import('./helpers/rewire');
registerActual('cms.modal', await vi.importActual('../../../static/cms/js/modules/cms.modal'));
return lazyMock('cms.modal', { default: 'Modal' });
});
vi.mock('../../../static/cms/js/modules/cms.sideframe', async () => {
const { lazyMock, registerActual } = await import('./helpers/rewire');
registerActual('cms.sideframe', await vi.importActual('../../../static/cms/js/modules/cms.sideframe'));
return lazyMock('cms.sideframe', { default: 'Sideframe' });
});
vi.mock('../../../static/cms/js/modules/cms.navigation', async () => {
const { lazyMock, registerActual } = await import('./helpers/rewire');
registerActual('cms.navigation', await vi.importActual('../../../static/cms/js/modules/cms.navigation'));
return lazyMock('cms.navigation', { default: 'Navigation' });
});
vi.mock('../../../static/cms/js/modules/dom-diff', async () => {
const { lazyMock, registerActual } = await import('./helpers/rewire');
registerActual('dom-diff', await vi.importActual('../../../static/cms/js/modules/dom-diff'));
return lazyMock('dom-diff', { DiffDOM: 'DiffDOM', nodeToObj: 'nodeToObj' });
});
CMS.API = CMS.API || {};
CMS.API.Helpers = Helpers;
CMS.KEYS = KEYS;
window.CMS = CMS;
CMS.Toolbar = Toolbar;
CMS.Modal = Modal;
CMS.Sideframe = Sideframe;
CMS.Messages = Messages;
var showLoader;
var hideLoader;
class Navigation {}
describe('CMS.Toolbar', function () {
fixture.setBase('cms/tests/frontend/unit/fixtures');
beforeEach(() => {
showLoader = jasmine.createSpy();
hideLoader = jasmine.createSpy();
rewire('showLoader', showLoader);
rewire('hideLoader', hideLoader);
rewire('Navigation', Navigation);
});
afterEach(() => {
resetRewire('Navigation');
resetRewire('showLoader');
resetRewire('hideLoader');
});
it('creates a Toolbar class', function () {
expect(CMS.Toolbar).toBeDefined();
});
it('has public API', function () {
expect(CMS.Toolbar.prototype.showLoader).toEqual(jasmine.any(Function));
expect(CMS.Toolbar.prototype.hideLoader).toEqual(jasmine.any(Function));
expect(CMS.Toolbar.prototype.openAjax).toEqual(jasmine.any(Function));
});
describe('instance', function () {
var toolbar;
beforeEach(function (done) {
fixture.load('toolbar.html');
$(function () {
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
done();
});
});
afterEach(function () {
fixture.cleanup();
});
it('has ui', function () {
expect(toolbar.ui).toEqual(jasmine.any(Object));
expect(Object.keys(toolbar.ui)).toContain('container');
expect(Object.keys(toolbar.ui)).toContain('body');
expect(Object.keys(toolbar.ui)).toContain('window');
expect(Object.keys(toolbar.ui)).toContain('document');
expect(Object.keys(toolbar.ui)).toContain('toolbar');
expect(Object.keys(toolbar.ui)).toContain('navigations');
expect(Object.keys(toolbar.ui)).toContain('buttons');
expect(Object.keys(toolbar.ui)).toContain('messages');
expect(Object.keys(toolbar.ui)).toContain('structureBoard');
expect(Object.keys(toolbar.ui)).toContain('revert');
expect(Object.keys(toolbar.ui).length).toEqual(11);
});
it('has options', function () {
expect(toolbar.options).toEqual({
toolbarDuration: 200
});
var toolbar2 = new CMS.Toolbar({ toolbarDuration: 250, nonExistent: true });
expect(toolbar2.options).toEqual({
toolbarDuration: 250,
nonExistent: true
});
});
// this spec can be thoroughly expanded, but for the moment just checking for the
// class and event is sufficient
it('initializes the states', function (done) {
CMS.Toolbar.prototype._initialStates.and.callThrough();
CMS.Toolbar.prototype._initialStates.calls.reset();
CMS.settings = { sideframe_enabled: true, sideframe: {}, version: 'fake' };
CMS.config = { settings: { version: 'fake' }, auth: true };
toolbar.ui.document.on('cms-ready', function () {
// expect this to happen
done();
});
toolbar = new CMS.Toolbar();
expect(CMS.Toolbar.prototype._initialStates).toHaveBeenCalled();
expect(toolbar.ui.body).toHaveClass('cms-ready');
});
it('sets the "ready" data on the toolbar ui', function () {
expect(toolbar.ui.toolbar.data('ready')).toEqual(true);
toolbar.ui.toolbar.data('ready', false);
new CMS.Toolbar();
expect(toolbar.ui.toolbar.data('ready')).toEqual(true);
});
});
describe('.openAjax()', function () {
var toolbar;
beforeEach(function (done) {
// the module reaches for CMS.API.StructureBoard; karma had it left over
// from another spec file
CMS.API.StructureBoard = { invalidateState: jasmine.createSpy() };
fixture.load('toolbar.html');
CMS.config = {};
CMS.settings = $.extend(CMS.settings, {
toolbar: 'expanded'
});
jasmine.Ajax.install();
$(function () {
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
done();
});
});
afterEach(function () {
jasmine.Ajax.uninstall();
fixture.cleanup();
});
it('makes the request', function () {
expect(toolbar.openAjax({ url: '/url' })).toEqual(jasmine.any(Object));
var request = jasmine.Ajax.requests.mostRecent();
expect(request.url).toEqual('/url');
});
it('does not make the request if there is a confirmation that is not succeeded', function () {
spyOn(CMS.API.Helpers, 'secureConfirm').and.callFake(function (question) {
expect(question).toEqual('Are you sure?');
return false;
});
expect(toolbar.openAjax({ url: '/url', text: 'Are you sure?' })).toEqual(false);
});
it('shows the loader before making the request', function () {
expect(toolbar.openAjax({ url: '/url' })).toEqual(jasmine.any(Object));
expect(showLoader).toHaveBeenCalled();
});
it('uses custom callback after request succeeds and hides the loader', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('response');
return { fail: $.noop };
}
};
});
var callback = jasmine.createSpy();
toolbar.openAjax({
url: '/url',
callback: callback
});
expect(callback).toHaveBeenCalled();
expect(callback).toHaveBeenCalledWith(toolbar, 'response');
expect(hideLoader).toHaveBeenCalled();
});
it('does not hide the loader if no callback provided', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('response');
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
toolbar.openAjax({
url: '/url',
onSuccess: '/another-url'
});
expect(showLoader).toHaveBeenCalled();
expect(hideLoader).not.toHaveBeenCalled();
});
it('uses custom onSuccess url from request success', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback({ url: '/redirect-url' });
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
toolbar.openAjax({
url: '/url',
onSuccess: 'FOLLOW_REDIRECT'
});
expect(CMS.API.Helpers.reloadBrowser).toHaveBeenCalledWith('/redirect-url');
});
it('uses custom onSuccess url after request succeeds', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('response');
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
toolbar.openAjax({
url: '/url',
onSuccess: '/another-url'
});
expect(CMS.API.Helpers.reloadBrowser).toHaveBeenCalledWith('/another-url');
});
it('reloads the page if no callback or onSuccess passed', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('response');
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
toolbar.openAjax({
url: '/url'
});
expect(CMS.API.Helpers.reloadBrowser).toHaveBeenCalledWith();
});
it('evaluates a JSON data bridge from the response instead of reloading', function () {
var dataBridge = { action: 'edit', plugin_id: 1 };
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback(dataBridge);
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
spyOn(CMS.API.Helpers, 'onPluginSave');
toolbar.openAjax({ url: '/url' });
expect(CMS.API.StructureBoard.invalidateState).toHaveBeenCalled();
expect(CMS.API.Helpers.reloadBrowser).not.toHaveBeenCalled();
expect(hideLoader).toHaveBeenCalled();
});
it('evaluates an HTML data bridge from the response instead of reloading', function () {
var dataBridge = { action: 'delete', plugin_id: 2 };
var html = '<!DOCTYPE html><html><body class="cms-close-frame">' +
'<script id="data-bridge" type="application/json">' +
JSON.stringify(dataBridge) + '</script></body></html>';
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback(html);
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
spyOn(CMS.API.Helpers, 'onPluginSave');
toolbar.openAjax({ url: '/url' });
expect(CMS.API.StructureBoard.invalidateState).toHaveBeenCalled();
expect(CMS.API.Helpers.reloadBrowser).not.toHaveBeenCalled();
});
it('reloads if the response is a JSON object without a valid data bridge', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback({ foo: 'bar' });
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
spyOn(CMS.API.Helpers, 'onPluginSave');
toolbar.openAjax({ url: '/url' });
expect(CMS.API.Helpers.onPluginSave).not.toHaveBeenCalled();
expect(CMS.API.Helpers.reloadBrowser).toHaveBeenCalledWith();
});
it('reloads if the HTML response does not contain a data bridge', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('<html><body>no bridge here</body></html>');
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
spyOn(CMS.API.Helpers, 'onPluginSave');
toolbar.openAjax({ url: '/url' });
expect(CMS.API.Helpers.onPluginSave).not.toHaveBeenCalled();
expect(CMS.API.Helpers.reloadBrowser).toHaveBeenCalledWith();
});
it('handles parameters', function () {
spyOn($, 'ajax').and.callFake(function (param) {
expect(param.data).toEqual({ param1: true, param2: false, param3: 150, param4: 'alala' });
return {
done: function () {
return { fail: $.noop };
}
};
});
toolbar.openAjax({
url: '/whatever',
post: JSON.stringify({ param1: true, param2: false, param3: 150, param4: 'alala' })
});
});
it('opens an error message if request failed', function () {
CMS.API.Messages = new CMS.Messages();
spyOn(CMS.API.Messages, 'open');
spyOn($, 'ajax').and.callFake(function () {
return {
done: function () {
return {
fail: function (callback) {
callback({
responseText: 'An error occurred',
status: 418,
statusText: "I'm a teapot"
});
}
};
}
};
});
toolbar.openAjax({
url: '/whatever'
});
expect(CMS.API.Messages.open).toHaveBeenCalledWith({
message: "An error occurred | 418 I'm a teapot",
error: true
});
});
it('unlocks the toolbar if request succeeds', function () {
spyOn($, 'ajax').and.callFake(function () {
return {
done: function (callback) {
callback('response');
return { fail: $.noop };
}
};
});
spyOn(CMS.API.Helpers, 'reloadBrowser');
CMS.API.locked = true;
toolbar.openAjax({
url: '/url'
});
expect(CMS.API.locked).toEqual(false);
CMS.API.locked = true;
toolbar.openAjax({
url: '/url',
callback: $.noop
});
expect(CMS.API.locked).toEqual(false);
CMS.API.locked = true;
toolbar.openAjax({
url: '/url',
onSuccess: '/another-url'
});
expect(CMS.API.locked).toEqual(false);
});
it('unlocks the toolbar if request fails', function () {
CMS.API.Messages = new CMS.Messages();
spyOn(CMS.API.Messages, 'open');
spyOn($, 'ajax').and.callFake(function () {
return {
done: function () {
return {
fail: function (callback) {
callback({
responseText: 'An error occurred',
status: 418,
statusText: "I'm a teapot"
});
}
};
}
};
});
CMS.API.locked = true;
toolbar.openAjax({
url: '/whatever'
});
expect(CMS.API.locked).toEqual(false);
});
});
describe('._events()', function () {
var toolbar;
beforeEach(function (done) {
fixture.load('toolbar.html');
CMS.config = {
lang: {
publish: 'publish?'
}
};
CMS.settings = $.extend(CMS.settings, {
toolbar: 'expanded'
});
$(function () {
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
done();
});
});
afterEach(function () {
fixture.cleanup();
});
it('attaches event handlers to navigation menu links', function () {
spyOn(toolbar, '_delegate');
var emptyLink = $(toolbar.ui.navigations[0]).find('a').eq(0);
var pagesLink = $(toolbar.ui.navigations[0]).find('a').eq(1);
emptyLink.trigger('click');
expect(toolbar._delegate).not.toHaveBeenCalled();
pagesLink.trigger('click');
expect(toolbar._delegate).toHaveBeenCalledTimes(1);
expect(toolbar._delegate).toHaveBeenCalledWith(pagesLink);
});
it('attaches event handlers to navigation menu links (to open in new window)', function () {
var fakeWindow = {
open: jasmine.createSpy()
};
spyOn(toolbar, '_delegate');
spyOn(CMS.API.Helpers, '_getWindow').and.callFake(function () {
return fakeWindow;
});
var emptyLink = $(toolbar.ui.navigations[0]).find('a').eq(0);
var pagesLink = $(toolbar.ui.navigations[0]).find('a').eq(1);
emptyLink.trigger(new $.Event('keydown', { keyCode: CMS.KEYS.CTRL }));
emptyLink.trigger('click');
expect(toolbar._delegate).not.toHaveBeenCalled();
expect(fakeWindow.open).not.toHaveBeenCalled();
emptyLink.trigger(new $.Event('keydown', { keyCode: CMS.KEYS.CTRL }));
pagesLink.trigger('click');
expect(toolbar._delegate).not.toHaveBeenCalledTimes(1);
expect(fakeWindow.open).toHaveBeenCalledWith(jasmine.stringMatching('cms/page'), '_blank');
pagesLink.trigger('keyup');
});
it('attaches event handlers to navigation menu lists', function () {
var firstMenuItem = $(toolbar.ui.navigations.find('> li')[0]);
toolbar.ui.structureBoard = $('<div></div>');
expect(toolbar.ui.document).not.toHandle(toolbar.click);
expect(toolbar.ui.structureBoard).not.toHandle(toolbar.click);
expect(toolbar.ui.toolbar).not.toHandle(toolbar.click);
expect(toolbar.ui.window).not.toHandle(toolbar.resize + '.menu.reset');
firstMenuItem.trigger('click');
expect(toolbar.ui.document).toHandle(toolbar.click);
expect(toolbar.ui.structureBoard).toHandle(toolbar.click);
expect(toolbar.ui.toolbar).toHandle(toolbar.click);
expect(toolbar.ui.window).toHandle(toolbar.resize + '.menu.reset');
});
it('handles mousemove over top level toolbar items', function () {
var firstMenuItem = $(toolbar.ui.navigations.find('> li')[0]);
var secondMenuItem = $(toolbar.ui.navigations.find('> li')[1]);
var thirdMenuItem = $(toolbar.ui.navigations.find('> li')[2]);
firstMenuItem.trigger('click');
var clickFirstMenuItem = spyOnEvent(firstMenuItem, toolbar.click);
var clickSecondMenuItem = spyOnEvent(secondMenuItem, toolbar.click);
var clickThirdMenuItem = spyOnEvent(thirdMenuItem, toolbar.click);
firstMenuItem.trigger('mouseenter');
expect(clickFirstMenuItem).not.toHaveBeenTriggered();
secondMenuItem.trigger('mouseenter');
expect(clickSecondMenuItem).toHaveBeenTriggered();
thirdMenuItem.trigger('mouseenter');
expect(clickThirdMenuItem).toHaveBeenTriggered();
});
it('does not care for mouse over top level items if touch is enabled', function () {
var firstMenuItem = $(toolbar.ui.navigations.find('> li')[0]);
var secondMenuItem = $(toolbar.ui.navigations.find('> li')[1]);
firstMenuItem.find('a').trigger('touchstart');
firstMenuItem.trigger('click');
var clickFirstMenuItem = spyOnEvent(firstMenuItem, toolbar.click);
var clickSecondMenuItem = spyOnEvent(secondMenuItem, toolbar.click);
firstMenuItem.trigger('mouseenter');
expect(clickFirstMenuItem).not.toHaveBeenTriggered();
secondMenuItem.trigger('mouseenter');
expect(clickSecondMenuItem).not.toHaveBeenTriggered();
});
it('closes the menu item if it is open', function () {
var firstMenuItem = $(toolbar.ui.navigations.find('> li')[0]);
firstMenuItem.trigger('click');
expect(firstMenuItem).toHaveClass('cms-toolbar-item-navigation-hover');
firstMenuItem.trigger('click');
expect(firstMenuItem).not.toHaveClass('cms-toolbar-item-navigation-hover');
});
it('handles mousemove over nested toolbar items', function () {
var menuItem = $(toolbar.ui.navigations.find('> li')[1]);
var subMenu = menuItem.find('> ul');
var childrenSubMenuItem = subMenu.find('> li').eq(0);
spyOn($.fn, 'show').and.callThrough();
expect(childrenSubMenuItem.find('> ul')).not.toBeVisible();
childrenSubMenuItem.trigger('pointerover');
expect($.fn.show).toHaveBeenCalledTimes(1);
expect($.fn.show.calls.mostRecent().object).toEqual(childrenSubMenuItem.find('> ul'));
});
it('attaches event handlers to buttons with data-rel', function () {
spyOn(toolbar, '_delegate');
var createButton = toolbar.ui.buttons.eq(0).find('a');
createButton.trigger(toolbar.click);
expect(toolbar._delegate).toHaveBeenCalled();
});
it('attaches event handlers to buttons without data-rel', function () {
var createButton = toolbar.ui.buttons.eq(1).find('a:first');
spyOn($.Event.prototype, 'stopPropagation');
createButton.trigger(toolbar.click);
expect($.Event.prototype.stopPropagation).toHaveBeenCalled();
});
});
describe('._delegate()', function () {
var toolbar;
var fakeWindow;
class FakeModal {
constructor() {}
}
class FakeSideframe {
constructor(opts) {
this.constructorOpts = opts;
}
open() {}
}
beforeEach(function (done) {
fixture.load('toolbar.html');
CMS.config = {};
CMS.settings = $.extend(CMS.settings, {
toolbar: 'expanded'
});
fakeWindow = {
location: {
href: '',
pathname: '/context.html',
search: ''
}
};
$(function () {
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
rewire('Modal', FakeModal);
rewire('Sideframe', FakeSideframe);
spyOn(toolbar, 'openAjax');
spyOn(CMS.API.Helpers, '_getWindow').and.returnValue(fakeWindow);
spyOn(CMS.API.Messages, 'open');
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
done();
});
});
afterEach(function (done) {
resetRewire('Modal');
resetRewire('Sideframe');
fixture.cleanup();
setTimeout(function () {
done();
}, 200);
});
it('return false if item is disabled', function () {
expect(toolbar._delegate($('<div class="cms-btn-disabled"></div>'))).toEqual(false);
});
it('opens modal if item is "modal"', function () {
var modalOpen = jasmine.createSpy();
FakeModal.prototype.open = modalOpen;
toolbar._delegate($('<div href="href" data-name="modal" data-rel="modal" data-on-close="test"></div>'));
expect(modalOpen).toHaveBeenCalledWith({
url: 'href?cms_path=%2Fcontext.html&_popup=1',
title: 'modal'
});
});
it('opens sideframe if item is "sideframe"', function () {
var sideframeOpen = jasmine.createSpy();
spyOn(FakeSideframe.prototype, 'open').and.callFake(sideframeOpen);
toolbar._delegate(
$('<div href="href2" data-name="modal" data-rel="sideframe" data-on-close="test2"></div>')
);
// Check that a Sideframe was constructed with onClose option
// (we can't easily check this with the spy, but we can verify open was called)
expect(sideframeOpen).toHaveBeenCalledWith({
url: 'href2',
animate: true
});
});
it('sideframe disabled defaults to redirecting to the url', function () {
// Set the switch to disable the sideframe
CMS.settings = $.extend(true, CMS.settings, {
sideframe_enabled: false
});
expect(fakeWindow.location.href).toEqual('');
toolbar._delegate(
$('<div href="disabled-sideframe-href" data-rel="sideframe" ></div>')
);
expect(fakeWindow.location.href).toEqual('disabled-sideframe-href');
// Reset the switch to enable the sideframe for other tests
CMS.settings = $.extend(true, CMS.settings, {
sideframe_enabled: true
});
});
it('opens message if item is "message"', function () {
toolbar._delegate($('<div data-rel="message" data-text="message!"></div>'));
expect(CMS.API.Messages.open).toHaveBeenCalledWith({
message: 'message!'
});
});
it('opens ajax request if item is "ajax"', function () {
toolbar._delegate(
$('<div href="href" data-rel="ajax" ' +
'data-post=\'{ "test": "shmest" }\' data-text="text" data-on-success="REFRESH"></div>')
);
expect(toolbar.openAjax).toHaveBeenCalledWith({
url: 'href',
post: '{"test":"shmest"}',
text: 'text',
method: undefined,
onSuccess: 'REFRESH'
});
});
it('just redirects to the page if nothing else', function () {
expect(fakeWindow.location.href).toEqual('');
toolbar._delegate(
$('<div href="href"></div>')
);
expect(fakeWindow.location.href).toEqual('href');
});
describe('POST requests', function () {
var hostileToken = '"><img class="injected-token">';
var hostileHref = '/publish/"><img class="injected-href">';
beforeEach(function () {
fakeWindow.document = document;
CMS.config.csrf = 'fallback-token';
// Has to be the first form in the document so that the token
// lookup picks it up.
$('<form class="cms-post-request-test"><input name="csrfmiddlewaretoken"></form>')
.prependTo('body')
.find('input')
.val(hostileToken);
spyOn(window.HTMLFormElement.prototype, 'submit');
});
afterEach(function () {
$('form.cms-post-request-test').remove();
});
it('treats href and token as values, not as markup', function () {
toolbar._sendPostRequest($('<a class="cms-form-post-method"></a>').attr('href', hostileHref));
var form = $('body > form').last().addClass('cms-post-request-test');
expect(window.HTMLFormElement.prototype.submit).toHaveBeenCalled();
expect(form.attr('action')).toEqual(hostileHref);
expect(form.attr('method')).toEqual('POST');
expect(form.find('input[name="csrfmiddlewaretoken"]').val()).toEqual(hostileToken);
// Nothing was parsed as HTML, so no elements were injected.
expect(form.find('img').length).toEqual(0);
expect($('img.injected-href, img.injected-token').length).toEqual(0);
});
});
});
describe('._debug()', function () {
var toolbar;
beforeEach(function (done) {
fixture.load('toolbar.html');
CMS.config = {
lang: {
debug: 'DEBUG!'
}
};
CMS.settings = $.extend(CMS.settings, {
toolbar: 'expanded'
});
$(function () {
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
toolbar.ui.container.append('<div class="cms-debug-bar"></div>');
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
spyOn(CMS.API.Messages, 'open');
jasmine.clock().install();
done();
});
});
afterEach(function (done) {
jasmine.clock().uninstall();
fixture.cleanup();
setTimeout(function () {
done();
}, 200);
});
it('shows debug information after timeout', function () {
toolbar._debug();
toolbar.ui.container.find('.cms-debug-bar').trigger(toolbar.mouseEnter);
jasmine.clock().tick(10000);
expect(CMS.API.Messages.open).toHaveBeenCalledWith({
message: 'DEBUG!'
});
});
it('does not show debug information if not hovering after timeout', function () {
toolbar._debug();
toolbar.ui.container.find('.cms-debug-bar').trigger(toolbar.mouseEnter);
jasmine.clock().tick(500);
toolbar.ui.container.find('.cms-debug-bar').trigger(toolbar.mouseLeave);
jasmine.clock().tick(10000);
expect(CMS.API.Messages.open).not.toHaveBeenCalled();
});
});
describe('_refreshMarkup', () => {
const diffDOMConstructor = jasmine.createSpy();
const newToolbar = $('<div></div>');
let toolbar;
class DiffDOM {
constructor() {
diffDOMConstructor();
}
}
DiffDOM.prototype.diff = jasmine.createSpy();
DiffDOM.prototype.apply = jasmine.createSpy();
const trigger = jasmine.createSpy();
class FakeNavigation {
constructor() {
this.ui = {
window: {
trigger
}
};
}
}
beforeEach(function (done) {
fixture.load('toolbar.html');
CMS.config = {
lang: {
debug: 'DEBUG!'
}
};
CMS.settings = $.extend(CMS.settings, {
toolbar: 'expanded'
});
$(function () {
rewire('Navigation', FakeNavigation);
rewire('DiffDOM', DiffDOM);
spyOn(CMS.Toolbar.prototype, '_initialStates');
toolbar = new CMS.Toolbar();
spyOn(toolbar, 'setSettings').and.callFake(function (input) {
return $.extend(true, CMS.settings, input);
});
spyOn(toolbar, '_setupUI');
spyOn(toolbar, '_events');
CMS.API.Clipboard = {
ui: {},
_toolbarEvents: jasmine.createSpy()
};
jasmine.clock().install();
done();
});
});
afterEach(function (done) {
jasmine.clock().uninstall();
resetRewire('Navigation');
resetRewire('DiffDOM');
fixture.cleanup();
setTimeout(function () {
done();
}, 200);
});
it('refreshes markup', () => {
toolbar.navigation = null;
toolbar._refreshMarkup(newToolbar);
expect(toolbar._setupUI).toHaveBeenCalledTimes(1);
expect(toolbar._events).toHaveBeenCalledTimes(1);
expect(toolbar.navigation instanceof FakeNavigation).toEqual(true);
expect(trigger).toHaveBeenCalledWith('resize');
expect(CMS.API.Clipboard._toolbarEvents).toHaveBeenCalledTimes(1);
});
it('only takes markup from the first matched toolbar', () => {
// Callers search a whole refreshed page for .cms-toolbar, so the
// collection can contain an element authored in editable content.
const toolbars = $(
'<div class="cms-toolbar"><span class="official-item"></span></div>' +
'<div class="cms-toolbar"><span class="injected-item"></span></div>'
);
toolbar._refreshMarkup(toolbars);
expect(toolbar.ui.toolbar.find('.official-item').length).toEqual(1);
expect(toolbar.ui.toolbar.find('.injected-item').length).toEqual(0);
});
});
});