diff --git a/Resources/public/js/views/ez-universaldiscoveryview.js b/Resources/public/js/views/ez-universaldiscoveryview.js index 25db37c58..37cc2a4ce 100644 --- a/Resources/public/js/views/ez-universaldiscoveryview.js +++ b/Resources/public/js/views/ez-universaldiscoveryview.js @@ -268,7 +268,9 @@ YUI.add('ez-universaldiscoveryview', function (Y) { */ _updateMethods: function () { var visibleMethod = this.get('visibleMethod'), - startingLocationId = this.get('startingLocationId'); + startingLocationId = this.get('startingLocationId'), + startingLocation = this.get('startingLocation'), + virtualRootLocation = this.get('virtualRootLocation'); /** * Stores a reference to the visible method view @@ -282,9 +284,11 @@ YUI.add('ez-universaldiscoveryview', function (Y) { var visible = (visibleMethod === method.get('identifier')); method.setAttrs({ + 'virtualRootLocation': virtualRootLocation, 'multiple': this.get('multiple'), 'loadContent': true, 'startingLocationId': startingLocationId, + 'startingLocation': startingLocation, 'visible': visible, 'isSelectable': Y.bind(this.get('isSelectable'), this), 'active': this.get('active'), @@ -502,16 +506,36 @@ YUI.add('ez-universaldiscoveryview', function (Y) { }, /** - * The location id that the UDW tree will select on start + * The id of a Location that should be considered as the starting + * point when discovering Content. + * * @attribute startingLocationId * @type {String} * @default false if there is no starting location - * */ startingLocationId: { value: false, }, + /** + * The Location that should be considered as the starting point when + * discovering Content. + * + * @attribute startingLocation + * @type {eZ.Location|false} + */ + startingLocation: { + value: false, + }, + + /** + * The virtual root Location object. + * + * @attribute virtualRootLocation + * @type {eZ.Location} + */ + virtualRootLocation: {}, + /** * Flag indicating whether the Content should be provided in the * selection. @@ -563,7 +587,9 @@ YUI.add('ez-universaldiscoveryview', function (Y) { multiple: this.get('multiple'), loadContent: true, isAlreadySelected: Y.bind(this._isAlreadySelected, this), - startingLocationId: this.get('startingLocationId') + startingLocationId: this.get('startingLocationId'), + startingLocation: this.get('startingLocation'), + virtualRootLocation: this.get('virtualRootLocation'), }), new Y.eZ.UniversalDiscoverySearchView({ bubbleTargets: this, @@ -571,7 +597,9 @@ YUI.add('ez-universaldiscoveryview', function (Y) { multiple: this.get('multiple'), loadContent: true, isAlreadySelected: Y.bind(this._isAlreadySelected, this), - startingLocationId: this.get('startingLocationId') + startingLocationId: this.get('startingLocationId'), + startingLocation: this.get('startingLocation'), + virtualRootLocation: this.get('virtualRootLocation'), }), ]; }, diff --git a/Resources/public/js/views/services/ez-universaldiscoveryviewservice.js b/Resources/public/js/views/services/ez-universaldiscoveryviewservice.js index 741c8c0c6..6ed077c02 100644 --- a/Resources/public/js/views/services/ez-universaldiscoveryviewservice.js +++ b/Resources/public/js/views/services/ez-universaldiscoveryviewservice.js @@ -21,6 +21,63 @@ YUI.add('ez-universaldiscoveryviewservice', function (Y) { * @extends eZ.ViewService */ Y.eZ.UniversalDiscoveryViewService = Y.Base.create('universalDiscoveryViewService', Y.eZ.ViewService, [Y.eZ.SideViewService], { + /** + * Loads the starting location of the UDW if there is a provided starting location id. + * Else starting location is set to false. + * + * @method _load + * @protected + * @param {Function} callback + */ + _load: function (callback) { + var startingLocation, + parameters = this.get('parameters'), + app = this.get('app'); + + if ( parameters.startingLocationId ) { + startingLocation = new Y.eZ.Location(); + startingLocation.set('id', parameters.startingLocationId); + app.set('loading', true); + + this._loadStartingLocationPath(startingLocation, Y.bind(function(startingLoc) { + this.set('startingLocation', startingLoc); + app.set('loading', false); + + callback(); + }, this)); + } else { + this.set('startingLocation', false); + callback(); + } + }, + + /** + * Loads the path of the UDW starting Location. + * + * @method _loadStartingLocationPath + * @protected + * @param {eZ.Location} startingLocation + * @param {Function} callback Executed after loading the path. Takes the + * location containing the path in parameter or false if loading error. + */ + _loadStartingLocationPath: function (startingLocation, callback) { + var options = {api: this.get('capi')}; + + startingLocation.load(options, function (error) { + if (!error) { + startingLocation.loadPath(options, function (error) { + if (!error) { + callback(startingLocation); + } else { + callback(false); + } + }); + } else { + callback(false); + } + }); + }, + /** * Returns the value of the `parameters` attribute. This attribute is set * when the app shows the universal discovery side view with the @@ -31,7 +88,47 @@ YUI.add('ez-universaldiscoveryviewservice', function (Y) { * @return mixed */ _getViewParameters: function () { - return this.get('parameters'); + var params = Y.merge(this.get('parameters')); + + params.virtualRootLocation = this.get('virtualRootLocation'); + params.startingLocation = this.get('startingLocation'); + return params; }, + }, { + ATTRS: { + + /** + * Holds the starting location where the UDW will start. + * False if no starting location defined + * + * @attribute startingLocation + * @default false + * @type {eZ.Location|False} + */ + startingLocation: { + value: false, + }, + + /** + * Holds the virtual root location + * + * @attribute virtualRootLocation + * @type {eZ.Location} + */ + virtualRootLocation: { + valueFn: function () { + return new Y.eZ.Location({ + id: '/api/ezp/v2/content/locations/1', + locationId: 1, + sortField: 'SECTION', + sortOrder: 'ASC', + // this is hardcoded but the actual value does not + // really matter, what matters is the fact the virtual + // root has at least a child. + childCount: 4, + }); + }, + }, + } }); }); diff --git a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.js b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.js index 7fb9f5b19..af89a17bc 100644 --- a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.js +++ b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.js @@ -65,16 +65,28 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview', function (Y) { container.plug(Y.Plugin.ScrollInfo); container.scrollInfo.on('scrollDown', this._handleScroll, this); - this.after('ownSelectedItemChange', function () { - if (!this.get('ownSelectedItem')) { - container.removeClass(HAS_SELECTED_ITEM); - } else { - container.addClass(HAS_SELECTED_ITEM); - } - }); + this.after('ownSelectedItemChange', this._uiOwnSelectedItem); + this._uiOwnSelectedItem(); this._addDOMEventHandlers(events); }, + /** + * Adds or removes the has selected item class on the container + * depending on the `ownSelectedItem` attribute value. + * + * @method _uiOwnSelectedItem + * @protected + */ + _uiOwnSelectedItem: function () { + var container = this.get('container'); + + if (!this.get('ownSelectedItem')) { + container.removeClass(HAS_SELECTED_ITEM); + } else { + container.addClass(HAS_SELECTED_ITEM); + } + }, + render: function () { var container = this.get('container'), itemsJSONified = []; diff --git a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerview.js b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerview.js index bcd581cbd..5764b597d 100644 --- a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerview.js +++ b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerview.js @@ -23,13 +23,55 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { Y.eZ.UniversalDiscoveryFinderExplorerView = Y.Base.create('universalDiscoveryFinderExplorerView', Y.eZ.TemplateBasedView, [], { initializer: function () { this.after('activeChange', function () { - if (this.get('active')) { + if ( this.get('active') ) { this.wakeUp(); } }); this.on('*:explorerNavigate', function(e) { this._handleLevelViews(e.target, e.depth, e.location); }); + this.after('startingLocationChange', function (e) { + if ( e.newVal === e.prevVal ) { + // This is to avoid rebuilding the level views when a + // starting location is set and when switching to another + // method and getting back to the finder. In that, case + // `startingLocationChange` is fired even if the very same + // Location object is set... + return; + } + this._removeLevels(); + this._getLevelViewPath().forEach(function (location, index, path) { + var next = path[index + 1]; + + if ( next ) { + this._addLevel(location, next.get('locationId')); + } else if ( location.get('childCount') !== 0 ) { + this._addLevel(location); + } + }, this); + }); + }, + + /** + * Returns a Location array representing the path to display. This path + * includes the virtual root Location, the starting Location path and + * the starting Location (if there's a starting Location). + * + * @method _getLevelViewPath + * @protected + * @return {Array} of Location. + */ + _getLevelViewPath: function () { + var startingLocation = this.get('startingLocation'), + path = []; + + if ( startingLocation ) { + path = startingLocation.get('path').concat(); + path.push(startingLocation); + } + + path.unshift(this.get('virtualRootLocation')); + return path; }, /** @@ -38,13 +80,8 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { * @method reset */ reset: function (name) { - var count; - if (name == 'levelViews') { - count = this.get('levelViews').length - 1; - - this._removeLevels(count); - this.get('levelViews')[0].reset(); + this._removeLevels(); } else { this.constructor.superclass.reset.apply(this, arguments); } @@ -72,7 +109,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { */ _handleLevelViews: function (levelView, depth, location) { var count; - + if (depth < this.get('levelViews').length) { count = this.get('levelViews').length - depth; this._removeLevels(count); @@ -121,12 +158,15 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { }, /** - * Removes and destroy the last level views from the levelViews attribute. + * Removes and destroy level views. * * @method _removeLevels - * @param {Number} count the number of levelviews to remove. + * @param {Number} [count] the number of level views to remove. If + * omitted, the complete list is removed. + * @protected */ _removeLevels: function (count) { + count = count || this.get('levelViews').length; for (var i=0; i < count; i++) { this.get('levelViews').pop().destroy({remove: true}); } @@ -138,11 +178,15 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { * * @method _addLevel * @param {Y.eZ.Location} location the parent location + * @param {Number} selectedLocationId the location id that should be + * selected in the level view + * @protected */ - _addLevel: function (location) { + _addLevel: function (location, selectedLocationId) { var LevelView = this.get('levelViewConstructor'), levelView = new LevelView({ parentLocation: location, + selectLocationId: selectedLocationId, depth: this.get('levelViews').length + 1, }); @@ -169,6 +213,26 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { }, }, + /** + * The starting Location if the UDW is configured with one. + * + * @attribute startingLocation + * @type {eZ.Location|false|Null} + * @default {Null} + */ + startingLocation: { + value: null, + }, + + /** + * The virtual root Location object + * + * @attribute virtualRootLocation + * @type {eZ.Location} + * @required + */ + virtualRootLocation: {}, + /** * The tab containing the universalDiscoveryFinderExplorerLevelViews to explore. * @@ -176,13 +240,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerview', function (Y) { * @type Array */ levelViews: { - valueFn: function () { - return [new Y.eZ.UniversalDiscoveryFinderExplorerLevelView({ - parentLocation: this.get('startingLocation'), - depth: 1, - bubbleTargets: this, - })]; - } + value: [], }, }, }); diff --git a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderview.js b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderview.js index 4dc58344f..b813fe5b7 100644 --- a/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderview.js +++ b/Resources/public/js/views/universaldiscovery/ez-universaldiscoveryfinderview.js @@ -150,20 +150,32 @@ YUI.add('ez-universaldiscoveryfinderview', function (Y) { }, /** - * Holds the virtual root location + * The starting Location if the UDW is configured with one. It is + * directly set on the finder explorer view. + * + * @attribute startingLocation + * @type {eZ.Location|false} + */ + startingLocation: { + setter: function (startingLocation) { + this.get('finderExplorerView').set('startingLocation', startingLocation); + return startingLocation; + } + }, + + /** + * The virtual root Location object. It is directly set on the + * finder explorer view. * * @attribute virtualRootLocation * @type {eZ.Location} + * @required */ virtualRootLocation: { - valueFn: function () { - return new Y.eZ.Location({ - id: '/api/ezp/v2/content/locations/1', - locationId: 1, - sortField: 'SECTION', - sortOrder: 'ASC', - }); - }, + setter: function (virtualRootLocation) { + this.get('finderExplorerView').set('virtualRootLocation', virtualRootLocation); + return virtualRootLocation; + } }, /** @@ -193,7 +205,6 @@ YUI.add('ez-universaldiscoveryfinderview', function (Y) { valueFn: function () { return new Y.eZ.UniversalDiscoveryFinderExplorerView({ bubbleTargets: this, - startingLocation: this.get('virtualRootLocation'), }); }, }, diff --git a/Resources/public/js/views/universaldiscovery/ez-universaldiscoverymethodbaseview.js b/Resources/public/js/views/universaldiscovery/ez-universaldiscoverymethodbaseview.js index 60d12d1d9..0fa480826 100644 --- a/Resources/public/js/views/universaldiscovery/ez-universaldiscoverymethodbaseview.js +++ b/Resources/public/js/views/universaldiscovery/ez-universaldiscoverymethodbaseview.js @@ -107,6 +107,23 @@ YUI.add('ez-universaldiscoverymethodbaseview', function (Y) { value: false, }, + /** + * The starting Location model if the UDW is configured with one. + * + * @attribute startingLocation + * @type {eZ.Location|false} + */ + startingLocation: {}, + + /** + * The virtual root Location object. + * + * @attribute virtualRootLocation + * @type {eZ.Location} + * @required + */ + virtualRootLocation: {}, + /** * Flag indicating whether the Content should be provided in the * selection. diff --git a/Tests/js/views/assets/ez-universaldiscoveryview-tests.js b/Tests/js/views/assets/ez-universaldiscoveryview-tests.js index cd75a2051..a9d8be3eb 100644 --- a/Tests/js/views/assets/ez-universaldiscoveryview-tests.js +++ b/Tests/js/views/assets/ez-universaldiscoveryview-tests.js @@ -514,6 +514,9 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { this.method2._set("identifier", "method2"); this.confirmedList = new Y.View(); + this.startingLocation = {}; + this.startingLocationId = '42'; + this.virtualRootLocation = {}; this.view = new Y.eZ.UniversalDiscoveryView({ container: '.container', @@ -563,6 +566,10 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { var method2 = this.method2, method1 = this.method1; + this.view.set('startingLocation', this.startingLocation); + this.view.set('startingLocationId', this.startingLocationId); + this.view.set('virtualRootLocation', this.virtualRootLocation); + this.view.set('active', true); this.view.set('visibleMethod', 'method2'); @@ -572,15 +579,31 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { ); Assert.isFalse( method1.get('visible'), - "The method2 should not be visible" + "The method1 should not be visible" + ); + + Assert.areSame( + method2.get('startingLocation'), this.startingLocation, + "method should have been updated with startingLocation" + ); + + Assert.areSame( + method2.get('startingLocationId'), this.startingLocationId, + "method should have been updated with startingLocationId" + ); + + Assert.areSame( + method2.get('virtualRootLocation'), this.virtualRootLocation, + "method should have been updated with virtualRootLocation" ); + Assert.isTrue( method2.get('multiple'), - "The method2 mutiple flag should be true" + "The method2 multiple flag should be true" ); Assert.isTrue( method1.get('multiple'), - "The method1 mutiple flag should be true" + "The method1 multiple flag should be true" ); }, @@ -619,6 +642,8 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { this.config = {}; this.multiple = true; this.startingLocationId = 'l/o/c/a/t/i/o/n/i/d'; + this.startingLocation = {}; + this.virtualRootLocation = {}; Y.eZ.UniversalDiscoveryFinderView = Y.Base.create( 'testFinderView', Y.eZ.UniversalDiscoveryMethodBaseView, [], {} @@ -630,7 +655,9 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { this.view = new Y.eZ.UniversalDiscoveryView({ multiple: this.multiple, confirmedListView: this.confirmedList, - startingLocationId: this.startingLocationId + startingLocationId: this.startingLocationId, + startingLocation: this.startingLocation, + virtualRootLocation: this.virtualRootLocation, }); }, @@ -669,6 +696,51 @@ YUI.add('ez-universaldiscoveryview-tests', function (Y) { this.startingLocationId, methods[0].get('startingLocationId'), "The startingLocationId should be passed to the method views" ); + Assert.areSame( + this.startingLocation, methods[0].get('startingLocation'), + "The startingLocation should be passed to the method views" + ); + Assert.areSame( + this.virtualRootLocation, methods[0].get('virtualRootLocation'), + "The virtualRootLocation should be passed to the method views" + ); + }, + + "Should instantiate the search method": function () { + var methods = this.view.get('methods'); + + Assert.isArray( + methods, + "The method list should be an array" + ); + Assert.areEqual( + 2, methods.length, + "The default method list should contain 2 elements" + ); + Assert.isInstanceOf( + Y.eZ.UniversalDiscoverySearchView, methods[1], + "The first element should be an instance of the search method" + ); + Assert.areSame( + this.multiple, methods[1].get('multiple'), + "The selection mode should be passed to the method views" + ); + Assert.isFunction( + methods[1].get('isAlreadySelected'), + "The isAlreadySelected function should be passed to the method views" + ); + Assert.areSame( + this.startingLocationId, methods[1].get('startingLocationId'), + "The startingLocationId should be passed to the method views" + ); + Assert.areSame( + this.startingLocation, methods[1].get('startingLocation'), + "The startingLocation should be passed to the method views" + ); + Assert.areSame( + this.virtualRootLocation, methods[1].get('virtualRootLocation'), + "The virtualRootLocation should be passed to the method views" + ); }, "Should add the universal discovery view as a bubble target": function () { diff --git a/Tests/js/views/services/assets/ez-universaldiscoveryviewservice-tests.js b/Tests/js/views/services/assets/ez-universaldiscoveryviewservice-tests.js index d66114d90..063cecb7e 100644 --- a/Tests/js/views/services/assets/ez-universaldiscoveryviewservice-tests.js +++ b/Tests/js/views/services/assets/ez-universaldiscoveryviewservice-tests.js @@ -3,14 +3,20 @@ * For full copyright and license information view LICENSE file distributed with this source code. */ YUI.add('ez-universaldiscoveryviewservice-tests', function (Y) { - var getViewParametersTest, - Assert = Y.Assert; + var getViewParametersTest, loadStartingLocationTest, + Assert = Y.Assert, Mock = Y.Mock; getViewParametersTest = new Y.Test.Case({ name: "eZ Universal Discovery View Service getViewParameters test", setUp: function () { - this.service = new Y.eZ.UniversalDiscoveryViewService(); + this.virtualRootLocation = {}; + this.startingLocation = {}; + this.service = new Y.eZ.UniversalDiscoveryViewService({ + virtualRootLocation: this.virtualRootLocation, + startingLocation: this.startingLocation, + + }); }, tearDown: function () { @@ -23,14 +29,120 @@ YUI.add('ez-universaldiscoveryviewservice-tests', function (Y) { this.service.set('parameters', parameters); Assert.isObject(this.service.getViewParameters()); - Assert.areEqual(1, Y.Object.keys(this.service.getViewParameters()).length); + Assert.areEqual(3, Y.Object.keys(this.service.getViewParameters()).length); Assert.areSame( parameters.some, this.service.getViewParameters().some, "The view parameters should be the parameters" ); + Y.Assert.areEqual( + this.service.virtualRootLocation, parameters.virtualRootLocation, + "getViewParameters() result should contain the virtual root location" + ); + Y.Assert.areEqual( + this.service.startingLocation, parameters.startingLocation, + "getViewParameters() result should contain the starting location" + ); + }, + }); + + loadStartingLocationTest = new Y.Test.Case({ + name: "eZ Universal Discovery View Service starting location test", + + setUp: function () { + var that = this; + this.virtualRootLocation = {}; + this.startingLocation = new Mock(); + this.loadError = false; + this.loadPathError = false; + this.capi = {}; + this.startingLocationId = 'startingLocId'; + this.app = new Y.Base(); + + Y.eZ.Location = Y.Base.create('locationModel', Y.Base, [], { + loadFromHash: function () {}, + loadPath: Y.bind(function (options, callback) { + callback(this.loadPathError); + }, this), + load: function (options, callback) { + if (!that.loadError) { + Assert.areSame( + that.startingLocationId, this.get('id'), + "The location id should be the one provided by the view" + ); + Assert.isTrue( + that.app.get('loading'), + "app should be loading" + ); + callback(that.loadError); + } else { + callback(that.loadError); + } + }, + }, {ATTRS: {id: {}, locationId: {}, contentInfo: {}}}); + + this.startingLocationId = 'locationId'; + this.service = new Y.eZ.UniversalDiscoveryViewService({ + parameters: {startingLocationId: this.startingLocationId}, + capi: this.capi = {}, + app: this.app, + }); + }, + + tearDown: function () { + this.service.destroy(); + delete this.service; + }, + + "Should set the starting Location to the service": function () { + this.service.load(Y.bind(function(){ + Assert.isFalse( + this.service.get('app').get('loading'), + "app should NOT be loading anymore" + ); + Assert.isInstanceOf( + Y.eZ.Location, this.service.get('startingLocation'), + "The service's startingLocation attribute value should an instance of eZ.Location" + ); + Assert.areSame( + this.service.get('startingLocation').get('id'), this.startingLocationId, + "The startingLocation must have the location Id" + ); + }, this)); + }, + + "Should NOT set the starting Location to the service on location loading error": function () { + this.loadError = true; + this.service.load(Y.bind(function(){ + Assert.isFalse( + this.service.get('startingLocation'), + "The service's startingLocation attribute value should be false" + ); + }, this)); + }, + + "Should NOT set the starting Location to the service on location path loading error": function () { + this.loadPathError = true; + this.service.load(Y.bind(function(){ + Assert.isFalse( + this.service.get('startingLocation'), + "The service's startingLocation attribute value should be false" + ); + }, this)); + }, + + "Should NOT set the starting Location to the service if no starting location Id is provided": function () { + this.service.get('parameters').startingLocationId = null; + + this.service.load(Y.bind(function(){ + Assert.isFalse( + this.service.get('startingLocation'), + "The service's startingLocation attribute value should be false" + ); + }, this)); }, }); Y.Test.Runner.setName("eZ Universal Discovery View Service tests"); Y.Test.Runner.add(getViewParametersTest); + Y.Test.Runner.add(loadStartingLocationTest); }, '', {requires: ['test', 'view', 'ez-universaldiscoveryviewservice']}); diff --git a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerlevelview-tests.js b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerlevelview-tests.js index 2e7455824..bf61f3620 100644 --- a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerlevelview-tests.js +++ b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerlevelview-tests.js @@ -149,7 +149,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview-tests', function (Y) { }, }); - var _fullLevelViewSetup = function (context) { + var _fullLevelViewSetup = function (context, ownSelectedItem) { context.contentInfo = new Mock(); context.location = new Mock(); context.contentType = new Mock(); @@ -203,6 +203,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview-tests', function (Y) { parentLocation: context.parentLocationMock, offset: context.offset, limit: context.limit, + ownSelectedItem: !!ownSelectedItem, }); }; @@ -364,7 +365,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview-tests', function (Y) { name: 'eZ Universal Discovery Finder Explorer highlight tests', setUp: function () { - _fullLevelViewSetup(this); + _fullLevelViewSetup(this, true); }, tearDown: function () { @@ -372,20 +373,30 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview-tests', function (Y) { delete this.view; }, - "Should add and remove has-selected-item class": function () { + "Should directly add the has selected item class": function () { + Assert.isTrue( + this.view.get('container').hasClass('has-selected-item'), + 'The container should have the has selected item class' + ); + }, + + "Should remove the has selected item class": function () { var container = this.view.get('container'); - this.view.set('ownSelectedItem', true); - Assert.isTrue( + this.view.set('ownSelectedItem', false); + Assert.isFalse( container.hasClass('has-selected-item'), - 'levelItem should have has-selected-item class' + 'The has selected item class should have been removed' ); + }, - this.view.set('ownSelectedItem', false); + "Should add the has selected item class": function () { + this["Should remove the has selected item class"](); - Assert.isFalse( - container.one('.ez-explorer-level-item').hasClass('has-selected-item'), - 'levelItem should NOT have has-selected-item class' + this.view.set('ownSelectedItem', true); + Assert.isTrue( + this.view.get('container').hasClass('has-selected-item'), + 'The has selected item class should have been added' ); }, }); @@ -465,7 +476,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerlevelview-tests', function (Y) { this.view.set('items', this.searchResult); Assert.isFalse(container.hasClass('is-loading'), 'Should NOT have the loading icon'); - + this.view.set('items', null); Assert.isTrue(container.hasClass('is-loading'), 'Should have the loading icon'); }, diff --git a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerview-tests.js b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerview-tests.js index 5026706d2..647e7b19e 100644 --- a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerview-tests.js +++ b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderexplorerview-tests.js @@ -3,7 +3,8 @@ * For full copyright and license information view LICENSE file distributed with this source code. */ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { - var resetTest, defaultSubViewTest, renderTest, activeTest, navigateTest, + var resetTest, renderTest, activeTest, navigateTest, + startingLocationChangeTest, Assert = Y.Assert, Mock = Y.Mock; resetTest = new Y.Test.Case({ @@ -14,7 +15,14 @@ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { this.levelView2 = new Mock(); this.levelViews = [this.levelView1, this.levelView2]; Mock.expect(this.levelView1, { - method: 'reset', + method: 'destroy', + args: [Mock.Value.Object], + run: function (arg) { + Assert.isTrue( + arg.remove, + "destroy method should be called with remove to true" + ); + } }); Mock.expect(this.levelView2, { method: 'destroy', @@ -22,7 +30,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { run: function (arg) { Assert.isTrue( arg.remove, - "destroy method should be called with remove to true" + "destroy method should be called with remove to true" ); } }); @@ -39,72 +47,40 @@ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { delete this.levelView2; }, - "Should keep the first levelViews and destroy the others": function () { + "Should keep destroy the level views": function () { this.view.reset(); Mock.verify(this.levelView1); + Mock.verify(this.levelView2); Assert.areSame( this.view.get('levelViews').length, - 1, - "There should remain only one levelView" + 0, + "The levelViews attribute should be empty" ); }, }); - defaultSubViewTest = new Y.Test.Case({ - name: 'eZ Universal Discovery Finder Explorer default sub views tests', - - setUp: function () { - Y.eZ.UniversalDiscoveryFinderExplorerLevelView = Y.Base.create('ExplorerLevelView', Y.View, [], {}); - this.view = new Y.eZ.UniversalDiscoveryFinderExplorerView(); - }, - - tearDown: function () { - this.view.destroy(); - delete this.view; - delete Y.eZ.UniversalDiscoveryFinderExplorerLevelView; - }, - - "levelView should have an instance of eZ.UniversalDiscoveryFinderExplorerLevelView": function () { - Y.Array.each(this.view.get('levelViews'), function (levelView) { - Assert.isInstanceOf( - Y.eZ.UniversalDiscoveryFinderExplorerLevelView, levelView, - "The levelViews attribute value should have an instance of eZ.UniversalDiscoveryFinderExplorerLevelView" - ); - }); - }, - - "Should be a bubble target of the levelViews": function () { - var bubble = false; - - this.view.on('*:whatever', function () { - bubble = true; - }); - this.view.get('levelViews')[0].fire('whatever'); - Assert.isTrue(bubble, "The event should bubble to the finder explorer view"); - }, - - }); - renderTest = new Y.Test.Case({ name: 'eZ Universal Discovery Finder Explorer render tests', setUp: function () { - var that = this; + var that = this, + LevelView; this.levelViewRendered = false; - Y.eZ.UniversalDiscoveryFinderExplorerLevelView = Y.Base.create('levelView', Y.View, [], { + LevelView = Y.Base.create('levelView', Y.View, [], { render: function () { that.levelViewRendered = true; return this; }, }); - this.view = new Y.eZ.UniversalDiscoveryFinderExplorerView(); + this.view = new Y.eZ.UniversalDiscoveryFinderExplorerView({ + levelViews: [new LevelView()], + }); }, tearDown: function () { this.view.destroy(); delete this.view; - delete Y.eZ.UniversalDiscoveryFinderExplorerLevelView; }, "Should use the template": function () { @@ -156,7 +132,7 @@ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { "Should activate the levelViews when the explorer view get active": function () { this.view.set('active', true); - + Y.Array.each(this.levelViews, function (levelView) { Assert.isTrue( levelView.get('active'), @@ -270,11 +246,212 @@ YUI.add('ez-universaldiscoveryfinderexplorerview-tests', function (Y) { }, }); + startingLocationChangeTest = new Y.Test.Case({ + name: 'eZ Universal Discovery Finder Explorer startingLocationChange tests', + + setUp: function () { + var LevelView; + + LevelView = Y.Base.create('levelView', Y.View, [], { + displayLevelView: function () { + }, + }); + this.initialLevelView = new Mock(new Y.View()); + this.virtualRootLocation = new Y.Base(); + this.virtualRootLocation.set('childCount', 4); + Mock.expect(this.initialLevelView, { + method: 'destroy', + args: [Mock.Value.Object], + run: function (option) { + Assert.isTrue( + option.remove, + "The remove option should be set to true" + ); + } + }); + this.view = new Y.eZ.UniversalDiscoveryFinderExplorerView({ + levelViews: [this.initialLevelView], + virtualRootLocation: this.virtualRootLocation, + levelViewConstructor: LevelView, + }); + this.view.render(); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + "Should destroy existing level views": function () { + this.view.set('startingLocation', false); + + Mock.verify(this.initialLevelView); + }, + + "Should create a level view for the virtualRoot children": function () { + var levelView; + + this.view.set('startingLocation', false); + + Assert.areEqual( + 1, this.view.get('levelViews').length, + "A level views should have been added" + ); + levelView = this.view.get('levelViews')[0]; + Assert.areNotSame( + this.initialLevelView, levelView, + "A new level view should have been created" + ); + Assert.areSame( + this.virtualRootLocation, levelView.get('parentLocation'), + "The parent Location of the level view should be the virtual root" + ); + Assert.isUndefined( + levelView.get('selectLocationId'), + "The selected Location id should be undefined" + ); + }, + + _getStartingLocation: function (locationId, childCount, path) { + var location = new Y.Base(); + + location.set('locationId', locationId); + location.set('childCount', childCount); + location.set('path', path); + + return location; + }, + + "Should create a levelView for the virtualRoot and select the starting Location": function () { + var levelView, + locationId = 42; + + this.view.set('startingLocation', this._getStartingLocation(locationId, 0, [])); + + Assert.areEqual( + 1, this.view.get('levelViews').length, + "A level views should have been added" + ); + levelView = this.view.get('levelViews')[0]; + Assert.areNotSame( + this.initialLevelView, levelView, + "A new level view should have been created" + ); + Assert.areSame( + this.virtualRootLocation, levelView.get('parentLocation'), + "The parent Location of the level view should be the virtual root" + ); + Assert.areEqual( + locationId, + levelView.get('selectLocationId'), + "The selected Location id should be the starting Location id" + ); + }, + + "Should create 2 level views": function () { + var rootLevelView, + locationLevelView, + locationId = 42, + location = this._getStartingLocation(locationId, 1, []); + + this.view.set('startingLocation', location); + + Assert.areEqual( + 2, this.view.get('levelViews').length, + "2 level views should have been created" + ); + rootLevelView = this.view.get('levelViews')[0]; + locationLevelView = this.view.get('levelViews')[1]; + Assert.areSame( + this.virtualRootLocation, rootLevelView.get('parentLocation'), + "The parent Location should be the virtual root" + ); + Assert.areEqual( + locationId, + rootLevelView.get('selectLocationId'), + "The selected Location id should be the id of the startingLocationId" + ); + Assert.areSame( + location, locationLevelView.get('parentLocation'), + "The parent Location should be the starting Location" + ); + Assert.isUndefined( + locationLevelView.get('selectLocationId'), + "The selected Location id should be undefined" + ); + }, + + "Should create 3 level views": function () { + var rootLevelView, + pathLevelView, + locationLevelView, + locationId = 42, + pathLocationId = 43, + pathLocation = this._getStartingLocation(pathLocationId, 1, []), + location = this._getStartingLocation(locationId, 1, [pathLocation]); + + this.view.set('startingLocation', location); + + Assert.areEqual( + 3, this.view.get('levelViews').length, + "3 level views should have been created" + ); + rootLevelView = this.view.get('levelViews')[0]; + pathLevelView = this.view.get('levelViews')[1]; + locationLevelView = this.view.get('levelViews')[2]; + Assert.areSame( + this.virtualRootLocation, rootLevelView.get('parentLocation'), + "The parent Location should be the virtual root" + ); + Assert.areEqual( + pathLocationId, + rootLevelView.get('selectLocationId'), + "The selected Location id should be the id of the location in the path" + ); + Assert.areSame( + pathLocation, pathLevelView.get('parentLocation'), + "The parent Location should be the path Location" + ); + Assert.areEqual( + locationId, pathLevelView.get('selectLocationId'), + "The selected Location id should the id of the starting Location" + ); + Assert.areSame( + location, locationLevelView.get('parentLocation'), + "The parent Location should be the starting Location" + ); + Assert.isUndefined( + locationLevelView.get('selectLocationId'), + "The selected Location id should be undefined" + ); + }, + + "Should prevent rebuilding the same level views": function () { + var rootLevelView, + locationLevelView, + locationId = 42, + location = this._getStartingLocation(locationId, 1, []); + + this.view.set('startingLocation', location); + rootLevelView = this.view.get('levelViews')[0]; + locationLevelView = this.view.get('levelViews')[1]; + this.view.set('startingLocation', location); + + Assert.areSame( + rootLevelView, this.view.get('levelViews')[0], + "The level views should have been kept" + ); + Assert.areSame( + locationLevelView, this.view.get('levelViews')[1], + "The level views should have been kept" + ); + }, + }); + Y.Test.Runner.setName("eZ Universal Discovery Finder Explorer View tests"); Y.Test.Runner.add(resetTest); - Y.Test.Runner.add(defaultSubViewTest); Y.Test.Runner.add(renderTest); Y.Test.Runner.add(activeTest); Y.Test.Runner.add(navigateTest); - -}, '', {requires: ['test', 'view', 'ez-universaldiscoveryfinderexplorerview']}); + Y.Test.Runner.add(startingLocationChangeTest); +}, '', {requires: ['test', 'base', 'view', 'ez-universaldiscoveryfinderexplorerview']}); diff --git a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderview-tests.js b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderview-tests.js index 34e1c2d7f..b14530a00 100644 --- a/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderview-tests.js +++ b/Tests/js/views/universaldiscovery/assets/ez-universaldiscoveryfinderview-tests.js @@ -5,28 +5,24 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { var resetTest, defaultSubViewTest, renderTest, unselectTest, multipleUpdateTest, onUnselectContentTest, selectContentTest, + settersTest, Assert = Y.Assert, Mock = Y.Mock; resetTest = new Y.Test.Case({ name: 'eZ Universal Discovery Finder reset tests', setUp: function () { - this.selectedView = new Mock(); - this.finderExplorerView = new Mock(); + this.selectedView = new Mock(new Y.View()); + this.finderExplorerView = new Mock(new Y.View()); Mock.expect(this.selectedView, { method: 'reset', }); - Mock.expect(this.selectedView, { - method: 'setAttrs', - args: [Mock.Value.Object] - }); Mock.expect(this.finderExplorerView, { method: 'reset', }); this.view = new Y.eZ.UniversalDiscoveryFinderView({ selectedView: this.selectedView, finderExplorerView: this.finderExplorerView, - virtualRootLocation: {} }); }, @@ -79,7 +75,6 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { setUp: function () { Y.eZ.UniversalDiscoverySelectedView = Y.Base.create('selectedView', Y.View, [], {}); Y.eZ.UniversalDiscoveryFinderExplorerView = Y.Base.create('finderExplorerView', Y.View, [], {}); - Y.eZ.Location = Y.Base.create('locationModel', Y.Model, [], {}); this.view = new Y.eZ.UniversalDiscoveryFinderView(); }, @@ -104,13 +99,6 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { ); }, - "finderExplorerView's startingLocation should be an instance of eZ.Location": function () { - Assert.isInstanceOf( - Y.eZ.Location, this.view.get('finderExplorerView').get('startingLocation'), - "The finderExplorerView's startingLocation attribute value should an instance of eZ.Location" - ); - }, - "Should be a bubble target of the selectedView": function () { var bubble = false; @@ -137,14 +125,6 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { "The selectedView's addConfirmButton flag should be false" ); }, - - "Should set the finderExplorerView's startingLocation": function () { - Assert.areSame( - this.view.get('finderExplorerView').get('startingLocation'), - this.view.get('virtualRootLocation'), - "The finderExplorerView's startingLocation should be set" - ); - }, }); renderTest = new Y.Test.Case({ @@ -442,6 +422,50 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { }, }); + settersTest = new Y.Test.Case({ + name: 'eZ Universal Discovery Finder startingLocation and virtualRootLocation setter tests', + + setUp: function () { + this.selectedView = new Y.View(); + this.finderExplorerView = new Y.View(); + this.view = new Y.eZ.UniversalDiscoveryFinderView({ + selectedView: this.selectedView, + finderExplorerView: this.finderExplorerView, + }); + }, + + tearDown: function () { + this.view.destroy(); + this.selectedView.destroy(); + this.finderExplorerView.destroy(); + delete this.view; + delete this.selectedView; + delete this.finderExplorerView; + }, + + "Should forward the virtualRootLocation to the finder explorer": function () { + var location = {}; + + this.view.set('virtualRootLocation', location); + + Assert.areSame( + location, this.finderExplorerView.get('virtualRootLocation'), + "The virtualRootLocation should be set on the finder explorer" + ); + }, + + "Should forward the startingLocation to the finder explorer": function () { + var location = {}; + + this.view.set('startingLocation', location); + + Assert.areSame( + location, this.finderExplorerView.get('startingLocation'), + "The startingLocation should be set on the finder explorer" + ); + }, + }); + Y.Test.Runner.setName("eZ Universal Discovery Finder View tests"); Y.Test.Runner.add(resetTest); Y.Test.Runner.add(defaultSubViewTest); @@ -450,4 +474,5 @@ YUI.add('ez-universaldiscoveryfinderview-tests', function (Y) { Y.Test.Runner.add(multipleUpdateTest); Y.Test.Runner.add(selectContentTest); Y.Test.Runner.add(onUnselectContentTest); -}, '', {requires: ['test', 'view', 'model', 'ez-universaldiscoveryfinderview']}); + Y.Test.Runner.add(settersTest); +}, '', {requires: ['test', 'view', 'ez-universaldiscoveryfinderview']}); diff --git a/Tests/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.html b/Tests/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.html index 653d3cc34..17991c602 100644 --- a/Tests/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.html +++ b/Tests/js/views/universaldiscovery/ez-universaldiscoveryfinderexplorerlevelview.html @@ -10,13 +10,12 @@