2 * Copyright (c) 2014 DataTorrent, Inc. ALL Rights Reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 describe('Directive: dashboard-layouts', function () {
21 var $rootScope, element, options, childScope, DashboardState, LayoutStorage, $mockModal, $mockTimeout, toFn;
24 beforeEach(function () {
25 angular.module('ui.sortable', []);
28 // load the directive's module
29 beforeEach(module('ui.dashboard', function($provide) {
33 $mockTimeout = function(fn, delay) {
36 $provide.value('$uibModal', $mockModal);
37 $provide.value('$timeout', $mockTimeout);
40 beforeEach(inject(function ($compile, _$rootScope_, _DashboardState_, _LayoutStorage_) {
42 $rootScope = _$rootScope_;
43 DashboardState = _DashboardState_;
44 LayoutStorage = _LayoutStorage_;
47 var widgetDefinitions = [
50 template: '<div class="wt-one-value">{{2 + 2}}</div>'
54 template: '<span class="wt-two-value">{{value}}</span>'
57 var defaultWidgets = _.clone(widgetDefinitions);
58 $rootScope.dashboardOptions = options = {
60 widgetDefinitions: widgetDefinitions,
65 defaultWidgets: defaultWidgets
70 defaultWidgets: defaultWidgets
73 defaultWidgets: defaultWidgets,
75 setItem: function(key, val) {
78 getItem: function(key) {
81 removeItem: function(key) {
86 $rootScope.value = 10;
89 element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
91 childScope = element.scope();
94 it('should not require storage', inject(function($compile) {
95 delete $rootScope.dashboardOptions.storage;
97 var noStorageEl = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
103 it('should be able to use a different dashboard-layouts template', inject(function($compile, $templateCache) {
105 'myCustomTemplate.html',
106 '<ul class="my-custom-tabs layout-tabs">' +
107 '<li ng-repeat="layout in layouts" ng-class="{ active: layout.active }">' +
108 '<a ng-click="makeLayoutActive(layout)">' +
109 '<span ng-dblclick="editTitle(layout)" ng-show="!layout.editingTitle">{{layout.title}}</span>' +
110 '<form action="" class="layout-title" ng-show="layout.editingTitle" ng-submit="saveTitleEdit(layout)">' +
111 '<input type="text" ng-model="layout.title" class="form-control" data-layout="{{layout.id}}">' +
113 '<span ng-click="removeLayout(layout)" class="glyphicon glyphicon-remove icon-erase"></span>' +
114 '<!-- <span class="glyphicon glyphicon-pencil"></span> -->' +
115 '<!-- <span class="glyphicon glyphicon-remove"></span> -->' +
119 '<a ng-click="createNewLayout()">' +
120 '<span class="glyphicon glyphicon-plus"></span>' +
124 '<div ng-repeat="layout in layouts | filter:isActive" dashboard="layout.dashboard" templateUrl="template/dashboard.html"></div>'
126 var customElement = $compile('<div dashboard-layouts="dashboardOptions" template-url="myCustomTemplate.html"></div>')($rootScope);
127 $rootScope.$digest();
128 expect(customElement.find('ul.my-custom-tabs').length).toEqual(1);
132 it('should set the first dashboard to active if there is not one already active', inject(function($compile) {
133 options.defaultLayouts[0].active = options.defaultLayouts[1].active = false;
134 element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
135 $rootScope.$digest();
136 childScope = element.scope();
138 var layouts = childScope.layouts;
140 for (var i = 0; i < layouts.length; i++) {
141 if (layouts[i].active) {
146 expect(active).not.toBeUndefined();
149 describe('the createNewLayout method', function() {
151 it('should call the add and save methods of LayoutStorage', function() {
152 spyOn(LayoutStorage.prototype, 'add');
153 spyOn(LayoutStorage.prototype, 'save');
155 childScope.createNewLayout();
156 expect(LayoutStorage.prototype.add).toHaveBeenCalled();
157 expect(LayoutStorage.prototype.save).toHaveBeenCalled();
160 it('should return the newly created layout object', function() {
161 var result = childScope.createNewLayout();
162 expect(typeof result).toEqual('object');
165 it('should set active=true on the newly created layout', function() {
166 var result = childScope.createNewLayout();
167 expect(result.active).toEqual(true);
170 it('should set defaultWidgets to dashboardOptions.defaultWidgets if it is present', function() {
171 var result = childScope.createNewLayout();
172 expect(result.defaultWidgets === options.defaultWidgets).toEqual(true);
175 it('should set defaultWidgets to an empty array if dashboardOptions.defaultWidgets is not present', inject(function($compile) {
176 delete options.defaultWidgets;
177 element = $compile('<div dashboard-layouts="dashboardOptions"></div>')($rootScope);
178 $rootScope.$digest();
179 childScope = element.scope();
180 var result = childScope.createNewLayout();
181 expect(result.defaultWidgets).toEqual([]);
186 describe('the removeLayout method', function() {
188 it('should call the remove and save methods of LayoutStorage', function() {
189 spyOn(LayoutStorage.prototype, 'remove');
190 spyOn(LayoutStorage.prototype, 'save');
192 childScope.removeLayout(childScope.layouts[0]);
193 expect(LayoutStorage.prototype.remove).toHaveBeenCalled();
194 expect(LayoutStorage.prototype.save).toHaveBeenCalled();
197 it('should call remove with the layout it was passed', function() {
198 spyOn(LayoutStorage.prototype, 'remove');
199 var layout = childScope.layouts[0];
200 childScope.removeLayout(layout);
201 expect(LayoutStorage.prototype.remove.calls.argsFor(0)[0]).toEqual(layout);
206 describe('the makeLayoutActive method', function() {
208 it('should call _makeLayoutActive if there is not a currently active dashboard with unsaved changes', function() {
209 spyOn(childScope, '_makeLayoutActive');
210 var layout = childScope.layouts[1];
211 childScope.makeLayoutActive(layout);
212 expect(childScope._makeLayoutActive).toHaveBeenCalled();
215 describe('when there are unsaved changes on the current dashboard', function() {
217 var current, options, successCb, errorCb, layout;
219 beforeEach(function() {
220 current = childScope.layouts[0];
221 current.dashboard.unsavedChangeCount = 1;
223 spyOn($mockModal, 'open').and.callFake(function(arg) {
227 then: function(success, error) {
235 layout = childScope.layouts[1];
236 childScope.makeLayoutActive(layout);
239 it('should create a modal', function() {
240 expect($mockModal.open).toHaveBeenCalled();
243 it('should resolve layout to the layout to be made active', function() {
244 expect(options.resolve.layout()).toEqual(layout);
247 it('should provide a success callback that saves the current dashboard and then calls _makeLayoutActive', function() {
248 spyOn(current.dashboard, 'saveDashboard');
249 spyOn(childScope, '_makeLayoutActive');
251 expect(current.dashboard.saveDashboard).toHaveBeenCalled();
252 expect(childScope._makeLayoutActive).toHaveBeenCalled();
253 expect(childScope._makeLayoutActive.calls.argsFor(0)[0]).toEqual(layout);
256 it('should provide an error callback that only calls _makeLayoutActive', function() {
257 spyOn(current.dashboard, 'saveDashboard');
258 spyOn(childScope, '_makeLayoutActive');
260 expect(current.dashboard.saveDashboard).not.toHaveBeenCalled();
261 expect(childScope._makeLayoutActive).toHaveBeenCalled();
262 expect(childScope._makeLayoutActive.calls.argsFor(0)[0]).toEqual(layout);
269 describe('the editTitle method', function() {
271 it('should set the editingTitle attribute to true on the layout it is passed', function() {
272 var layout = { id: '1' };
273 childScope.editTitle(layout);
274 $rootScope.$digest();
275 expect(layout.editingTitle).toEqual(true);
281 describe('the saveTitleEdit method', function() {
283 it('should set editingTitle to false', function() {
284 var layout = { id: '1' };
285 childScope.saveTitleEdit(layout);
286 expect(layout.editingTitle).toEqual(false);
289 it('should call layoutStorage.save', function() {
290 var layout = { id: '1' };
291 spyOn(LayoutStorage.prototype, 'save').and.callThrough();
292 childScope.saveTitleEdit(layout);
293 expect(LayoutStorage.prototype.save).toHaveBeenCalled();
298 describe('the saveLayouts method', function() {
300 it('should call LayoutStorage.save', function() {
301 spyOn(LayoutStorage.prototype, 'save').and.callThrough();
302 $rootScope.dashboardOptions.saveLayouts();
303 expect(LayoutStorage.prototype.save).toHaveBeenCalled();
306 it('should call LayoutStorage.save with true as the first arg', function() {
307 spyOn(LayoutStorage.prototype, 'save').and.callThrough();
308 $rootScope.dashboardOptions.saveLayouts();
309 expect(LayoutStorage.prototype.save.calls.argsFor(0)[0]).toEqual(true);
313 describe('the proxy methods to active layout', function() {
315 var mockDash, galSpy;
317 beforeEach(function() {
321 addWidget: function() {},
322 loadWidgets: function() {},
323 saveDashboard: function() {}
326 spyOn(mockDash.dashboard, 'addWidget');
327 spyOn(mockDash.dashboard, 'loadWidgets');
328 spyOn(mockDash.dashboard, 'saveDashboard');
329 galSpy = spyOn(LayoutStorage.prototype, 'getActiveLayout').and;
330 galSpy.returnValue(mockDash);
333 describe('the addWidget method', function() {
335 it('should call dashboard.addWidget method of the active layout', function() {
336 options.addWidget(1,2,3);
337 expect(mockDash.dashboard.addWidget).toHaveBeenCalled();
338 var firstCall = mockDash.dashboard.addWidget.calls.first();
339 expect(firstCall.object).toEqual(mockDash.dashboard);
340 expect(firstCall.args).toEqual([1,2,3]);
343 it('should do nothing if there is no active layout', function() {
344 galSpy.returnValue(null);
352 describe('the loadWidgets method', function() {
354 it('should call dashboard.loadWidgets of the current layout', function() {
355 options.loadWidgets(1,2,3);
356 expect(mockDash.dashboard.loadWidgets).toHaveBeenCalled();
357 var firstCall = mockDash.dashboard.loadWidgets.calls.first();
358 expect(firstCall.object).toEqual(mockDash.dashboard);
359 expect(firstCall.args).toEqual([1,2,3]);
362 it('should do nothing if there is no active layout', function() {
363 galSpy.returnValue(null);
365 options.loadWidgets();
371 describe('the saveDashboard method', function() {
373 it('should call dashboard.saveDashboard of the current layout', function() {
374 options.saveDashboard(1,2,3);
375 expect(mockDash.dashboard.saveDashboard).toHaveBeenCalled();
376 var firstCall = mockDash.dashboard.saveDashboard.calls.first();
377 expect(firstCall.object).toEqual(mockDash.dashboard);
378 expect(firstCall.args).toEqual([1,2,3]);
381 it('should do nothing if there is no active layout', function() {
382 galSpy.returnValue(null);
384 options.saveDashboard();