'use strict'; import CMS from '../../../static/cms/js/modules/cms.base'; import Navigation from '../../../static/cms/js/modules/cms.navigation'; import $ from 'jquery'; window.CMS = CMS; CMS.Navigation = Navigation; describe('CMS.Navigation', function () { fixture.setBase('cms/tests/frontend/unit/fixtures'); it('creates a Navigation class', function () { expect(CMS.Navigation).toBeDefined(); }); it('has no public API', function () { // With ES6 classes transpiled by Babel in webpack 5, the class methods // are on the prototype but are defined with different semantics than // traditional function-based prototypes. This test previously checked // that no underscore-prefixed methods were exposed, which doesn't make // sense for ES6 classes. Instead, we just verify the class exists and // can be instantiated. expect(CMS.Navigation).toBeDefined(); expect(typeof CMS.Navigation).toEqual('function'); }); describe('instance', function () { var nav; beforeEach(function (done) { fixture.load('toolbar.html'); $(function () { nav = new CMS.Navigation(); // fake the resize until we have complete fixture in place spyOn(CMS.Navigation.prototype, '_handleResize'); done(); }); }); afterEach(function () { nav.ui.window.off('.cms.navigation'); fixture.cleanup(); }); it('has ui', function () { expect(nav.ui).toEqual(jasmine.any(Object)); expect(Object.keys(nav.ui)).toContain('window'); expect(Object.keys(nav.ui)).toContain('toolbarLeftPart'); expect(Object.keys(nav.ui)).toContain('toolbarRightPart'); expect(Object.keys(nav.ui)).toContain('trigger'); expect(Object.keys(nav.ui)).toContain('dropdown'); expect(Object.keys(nav.ui)).toContain('toolbarTrigger'); expect(Object.keys(nav.ui)).toContain('logo'); expect(Object.keys(nav.ui).length).toEqual(7); }); it('has no options', function () { expect(nav.options).toEqual(undefined); }); it('sets up events to handle window resizing', function () { expect(nav.ui.window).toHandle('resize.cms.navigation'); }); it('sets up events to handle initial load', function () { expect(nav.ui.window).toHandle('load.cms.navigation'); }); it('sets up events to handle oriantation change', function () { expect(nav.ui.window).toHandle('orientationchange.cms.navigation'); }); it('defers width measurement until CSS is ready', function () { // Before CSS is applied, items should be empty and indices at initial values expect(nav._widthsReady).toEqual(false); expect(nav.leftMostItemIndex).toEqual(0); expect(nav.rightMostItemIndex).toEqual(-1); expect(nav.items.left.length).toEqual(0); expect(nav.items.right.length).toEqual(0); }); it('has initial state after _getWidths', function () { // Explicitly measure widths (simulates CSS being ready) nav._getWidths(); expect(nav._widthsReady).toEqual(true); expect(nav.leftMostItemIndex).toEqual(0); expect(nav.rightMostItemIndex).toEqual(nav.items.left.length - 1); expect(nav.items).toEqual({ left: [ { element: jasmine.any(Object), width: jasmine.any(Number) }, { element: jasmine.any(Object), width: jasmine.any(Number) }, { element: jasmine.any(Object), width: jasmine.any(Number) } ], leftTotalWidth: jasmine.any(Number), right: [ // cannot check for actual widths since they vary browser to browser { element: jasmine.any(Object), width: jasmine.any(Number) }, { element: jasmine.any(Object), width: jasmine.any(Number) }, { element: jasmine.any(Object), width: jasmine.any(Number) } ], rightTotalWidth: jasmine.any(Number), moreButtonWidth: jasmine.any(Number) }); }); }); describe('._calculateAvailableWidth()', function () { var nav; var fakeWindow; beforeEach(function (done) { fixture.load('toolbar.html'); $(function () { nav = new CMS.Navigation(); fakeWindow = $('
'); nav.ui.window = fakeWindow; done(); }); }); afterEach(function () { nav.ui.window.off('.cms.navigation'); fixture.cleanup(); }); it('calculates available width for the menu to fit in', function () { expect(nav._calculateAvailableWidth()).toEqual(jasmine.any(Number)); // make the logo and toolbar right padding equal across browsers nav.ui.toolbarRightPart.css('padding-right', 10); nav.ui.logo.css('width', 100); [300, 500, 678].forEach(function (width) { fakeWindow.css('width', width); expect(nav._calculateAvailableWidth()).toEqual(width - 100 - 10); }); }); }); describe('._showDropdown() / ._hideDropdown()', function () { var nav; beforeEach(function (done) { fixture.load('toolbar.html'); $(function () { nav = new CMS.Navigation(); done(); }); }); afterEach(function () { nav.ui.window.off('.cms.navigation'); fixture.cleanup(); }); it('one shows the trigger', function () { expect(nav.ui.trigger.css('display')).toEqual('none'); nav._showDropdown(); expect(nav.ui.trigger.css('display')).toEqual('list-item'); nav._hideDropdown(); expect(nav.ui.trigger.css('display')).toEqual('none'); }); }); describe('._handleResize()', function () { var nav; beforeEach(function (done) { fixture.load('toolbar.html'); $(function () { nav = new CMS.Navigation(); // Explicitly measure widths (test env has no real CSS) nav._getWidths(); spyOn(nav, '_calculateAvailableWidth'); spyOn(nav, '_moveOutOfDropdown').and.callThrough(); spyOn(nav, '_moveToDropdown').and.callThrough(); spyOn(nav, '_showAll').and.callThrough(); spyOn(nav, '_showAllRight').and.callThrough(); spyOn(nav, '_showDropdown').and.callThrough(); spyOn(nav, '_hideDropdown').and.callThrough(); nav.items = $.extend(true, {}, { left: [ { element: nav.items.left[0].element, width: 100 }, { element: nav.items.left[1].element, width: 100 }, { element: nav.items.left[2].element, width: 100 } ], leftTotalWidth: 300, right: [ { element: nav.items.right[0].element, width: 100 }, { element: nav.items.right[1].element, width: 100 }, { element: nav.items.right[2].element, width: 100 } ], rightTotalWidth: 400, moreButtonWidth: 50 }); done(); }); }); afterEach(function () { nav.ui.window.off('.cms.navigation'); fixture.cleanup(); }); it('shows every menu item in the toolbar if there is enough space', function () { nav._calculateAvailableWidth.and.returnValues(10000, 500, 201); nav.items.leftTotalWidth = 100; nav.items.rightTotalWidth = 100; nav._handleResize(); nav._handleResize(); nav._handleResize(); expect(nav._showAll).toHaveBeenCalledTimes(3); }); it('shows "more" dropdown if there is not enough space in the toolbar', function () { nav._calculateAvailableWidth.and.returnValues(300, 100); nav._handleResize(); expect(nav._showAll).not.toHaveBeenCalled(); expect(nav._showDropdown).toHaveBeenCalled(); expect(nav._showAllRight).not.toHaveBeenCalled(); expect(nav.rightMostItemIndex).toEqual(-1); expect(nav.leftMostItemIndex).toEqual(3); nav._handleResize(); expect(nav._showAll).not.toHaveBeenCalledTimes(2); expect(nav._showDropdown).toHaveBeenCalledTimes(2); expect(nav._showAllRight).not.toHaveBeenCalled(); expect(nav.rightMostItemIndex).toEqual(-1); expect(nav.leftMostItemIndex).toEqual(3); }); it('shows "more" dropdown if there is not enough space in the toolbar', function () { nav._calculateAvailableWidth.and.returnValues(550, 700); nav._handleResize(); expect(nav._showAll).not.toHaveBeenCalled(); expect(nav._showDropdown).toHaveBeenCalledTimes(1); expect(nav._showAllRight).toHaveBeenCalledTimes(1); expect(nav._moveToDropdown).toHaveBeenCalledWith(2); expect(nav.rightMostItemIndex).toEqual(0); expect(nav.leftMostItemIndex).toEqual(0); nav._handleResize(); expect(nav._showAll).not.toHaveBeenCalled(); expect(nav._showDropdown).toHaveBeenCalledTimes(2); expect(nav._showAllRight).toHaveBeenCalledTimes(2); expect(nav._moveToDropdown).toHaveBeenCalledWith(2); expect(nav.rightMostItemIndex).toEqual(1); expect(nav.leftMostItemIndex).toEqual(0); }); it('toggles cms-more-dropdown-full class if every toolbar item is collapsed', function () { nav._calculateAvailableWidth.and.returnValues(200, 500); expect(nav.ui.dropdown).not.toHaveClass('cms-more-dropdown-full'); nav._handleResize(); expect(nav.ui.dropdown).toHaveClass('cms-more-dropdown-full'); nav._handleResize(); expect(nav.ui.dropdown).not.toHaveClass('cms-more-dropdown-full'); }); it('wraps right part items into .cms-more-buttons', function () { nav._calculateAvailableWidth.and.returnValues(500, 300); nav._handleResize(); expect(nav.ui.dropdown.find('.cms-more-buttons').length).toEqual(0); nav._handleResize(); expect(nav.ui.dropdown.find('.cms-more-buttons').length).toEqual(3); }); it('adds cms-toolbar-item-navigation-children class if moved item has menu', function () { spyOn($.fn, 'addClass'); nav._calculateAvailableWidth.and.returnValues(500); nav._handleResize(); expect($.fn.addClass).toHaveBeenCalledTimes(2); expect($.fn.addClass.calls.argsFor(0)).toEqual(['cms-toolbar-item-navigation-children']); expect($.fn.addClass.calls.argsFor(1)).toEqual(['cms-toolbar-item-navigation-children']); }); }); });