Bri Prebilic Cole
Committed by Gerrit Code Review

GUI -- Button and Toolbar Services with unit tests - finished implementing butto…

…n widget, started modifying toolbar to use ButtonService

Change-Id: I96078516d396951175fb8d9e69dd7796da9f114e
...@@ -33,13 +33,12 @@ ...@@ -33,13 +33,12 @@
33 } 33 }
34 34
35 function button(div, id, gid, cb, tooltip) { 35 function button(div, id, gid, cb, tooltip) {
36 - if (!div) { 36 + if (!div || div.empty()) {
37 $log.warn('Button cannot append to div'); 37 $log.warn('Button cannot append to div');
38 return null; 38 return null;
39 } 39 }
40 40
41 var btnDiv = createDiv(div, 'btn', id), 41 var btnDiv = createDiv(div, 'btn', id),
42 - svg = btnDiv.append('svg'),
43 cbFnc = fs.isF(cb) || noop; 42 cbFnc = fs.isF(cb) || noop;
44 43
45 is.loadIcon(btnDiv, gid, btnSize); 44 is.loadIcon(btnDiv, gid, btnSize);
...@@ -53,36 +52,81 @@ ...@@ -53,36 +52,81 @@
53 } 52 }
54 } 53 }
55 54
56 - function toggle(div, id, gid, cb, tooltip) { 55 + function toggle(div, id, gid, initState, cb, tooltip) {
57 - if (!div) { 56 + if (!div || div.empty()) {
58 $log.warn('Toggle cannot append to div'); 57 $log.warn('Toggle cannot append to div');
59 return null; 58 return null;
60 } 59 }
61 60
62 - var sel = false, 61 + var sel = !!initState,
63 togDiv = createDiv(div, 'tog', id), 62 togDiv = createDiv(div, 'tog', id),
64 - svg = togDiv.append('svg'),
65 cbFnc = fs.isF(cb) || noop; 63 cbFnc = fs.isF(cb) || noop;
66 64
67 is.loadIcon(togDiv, gid, btnSize); 65 is.loadIcon(togDiv, gid, btnSize);
68 66
67 + function _toggle(b) {
68 + if (b === undefined) {
69 + sel = !sel;
70 + } else {
71 + sel = !!b;
72 + }
73 + cbFnc(sel);
74 + }
75 +
76 + togDiv.on('click', _toggle);
77 +
69 return { 78 return {
70 id: id, 79 id: id,
71 el: togDiv, 80 el: togDiv,
72 selected: function () { return sel; }, 81 selected: function () { return sel; },
73 - toggle: function (b) { 82 + toggle: _toggle
74 - if (b === undefined) {
75 - sel = !sel;
76 - } else {
77 - sel = !!b;
78 - }
79 - cbFnc(sel);
80 - }
81 } 83 }
82 } 84 }
83 85
84 function radioSet(div, id, rset) { 86 function radioSet(div, id, rset) {
85 - return {} 87 + if (!div || div.empty()) {
88 + $log.warn('Radio buttons cannot append to div');
89 + return null;
90 + }
91 + if (!fs.isA(rset)) {
92 + $log.warn('Radio button set is not an array');
93 + return null;
94 + }
95 + if (rset.length === 0) {
96 + $log.warn('Cannot create radio button set from empty array');
97 + return null;
98 + }
99 + var rDiv = div.append('div').classed('rset', true),
100 + sel = 0,
101 + rads = [];
102 +
103 + rset.forEach(function (btn, index) {
104 + var rid = {id: id + '-' + index},
105 + rbtn = angular.extend({}, btn, rid),
106 + istate = (index === 0),
107 + rtog = toggle(rDiv, rbtn.id, rbtn.gid, istate,
108 + rbtn.cb, rbtn.tooltip);
109 +
110 + rtog.el = (rtog.el).classed('tog', false).classed('rad', true);
111 + rads.push(rtog);
112 + });
113 +
114 + return {
115 + rads: rads,
116 + selected: function (i) {
117 + if (i === undefined) { return sel; }
118 + else if (i < 0 || i >= rads.length) {
119 + $log.error('Cannot select radio button of index ' + i);
120 + }
121 + else {
122 + if (i !== sel) {
123 + rads[sel].toggle(false);
124 + rads[i].toggle(true);
125 + sel = i;
126 + }
127 + }
128 + }
129 + }
86 } 130 }
87 131
88 angular.module('onosWidget') 132 angular.module('onosWidget')
......
...@@ -20,14 +20,20 @@ ...@@ -20,14 +20,20 @@
20 (function () { 20 (function () {
21 'use strict'; 21 'use strict';
22 22
23 - var $log, ps; 23 + var $log, fs, ps, bns;
24 24
25 var toolBtnIds = {}, 25 var toolBtnIds = {},
26 toolbarPanel, 26 toolbarPanel,
27 toolbarDiv; 27 toolbarDiv;
28 28
29 + var ids = [],
30 + tbarId,
31 + tbarPanel,
32 + tbarDiv;
33 +
29 function init() { 34 function init() {
30 toolBtnIds = {}; 35 toolBtnIds = {};
36 + ids = [];
31 } 37 }
32 38
33 function addButton(btn) { 39 function addButton(btn) {
...@@ -90,6 +96,76 @@ ...@@ -90,6 +96,76 @@
90 }; 96 };
91 } 97 }
92 98
99 + function validId(id, caller) {
100 + if (fs.inArray(id, ids) !== -1) {
101 + $log.warn(caller + ': ID already exists');
102 + return false;
103 + }
104 + return true;
105 + }
106 +
107 + function addButton1(id, gid, cb, tooltip) {
108 + var btnId = tbarId + '-' + id;
109 + if (!validId(btnId, 'addButton')) {
110 + return null;
111 + }
112 + ids.push(btnId);
113 + return bns.button(tbarDiv, btnId, gid, cb, tooltip);
114 + }
115 +
116 + function addToggle1(id, gid, initState, cb, tooltip) {
117 + var togId = tbarId + '-' + id;
118 + if (!validId(togId, 'addToggle')) {
119 + return null;
120 + }
121 + ids.push(togId);
122 + return bns.toggle(tbarDiv, togId, gid, initState, cb, tooltip);
123 + }
124 +
125 + function addRadioSet(id, rset) {
126 + var radId = tbarId + '-' + id;
127 + if (!validId(radId, 'addRadioSet')) {
128 + return null;
129 + }
130 + ids.push(radId);
131 + return bns.radioSet(tbarDiv, radId, rset);
132 + }
133 +
134 + // TODO: finish this and remove unneeded code
135 + function addSeparator1() {
136 +
137 + }
138 +
139 + function createToolbar1(id, settings) {
140 + if (!id) {
141 + $log.warn('createToolbar: no ID given');
142 + return null;
143 + }
144 + tbarId = 'tbar-' + id;
145 + var opts = fs.isO(settings) || {}; // default settings should be put here
146 +
147 + if (!validId(tbarId, 'createToolbar')) {
148 + return null;
149 + }
150 + ids.push(tbarId);
151 +
152 + tbarPanel = ps.createPanel(tbarId, opts);
153 + tbarDiv = tbarPanel.classed('toolbar', true);
154 +
155 + // TODO: change names of functions
156 + return {
157 + addButton1: addButton1,
158 + addToggle1: addToggle1,
159 + addRadioSet: addRadioSet,
160 + addSeparator1: addSeparator1
161 + }
162 + }
163 +
164 + // function currently not working
165 + function destroyToolbar(id) {
166 + ps.destroyPanel(id);
167 + }
168 +
93 function createToolbar(tbarId, tools) { 169 function createToolbar(tbarId, tools) {
94 var api; 170 var api;
95 171
...@@ -143,10 +219,13 @@ ...@@ -143,10 +219,13 @@
143 } 219 }
144 220
145 angular.module('onosWidget') 221 angular.module('onosWidget')
146 - .factory('ToolbarService', ['$log', 'PanelService', 222 + .factory('ToolbarService', ['$log', 'FnService',
147 - function (_$log_, _ps_) { 223 + 'PanelService', 'ButtonService',
224 + function (_$log_, _fs_, _ps_, _bns_) {
148 $log = _$log_; 225 $log = _$log_;
226 + fs = _fs_;
149 ps = _ps_; 227 ps = _ps_;
228 + bns = _bns_;
150 229
151 return { 230 return {
152 init: init, 231 init: init,
...@@ -154,7 +233,9 @@ ...@@ -154,7 +233,9 @@
154 makeToggle: makeToggle, 233 makeToggle: makeToggle,
155 makeRadio: makeRadio, 234 makeRadio: makeRadio,
156 separator: separator, 235 separator: separator,
157 - createToolbar: createToolbar 236 + createToolbar: createToolbar,
237 + createToolbar1: createToolbar1,
238 + destroyToolbar: destroyToolbar
158 }; 239 };
159 }]); 240 }]);
160 241
......
...@@ -83,8 +83,16 @@ describe('factory: fw/widget/button.js', function () { ...@@ -83,8 +83,16 @@ describe('factory: fw/widget/button.js', function () {
83 expect(count).toBe(0); 83 expect(count).toBe(0);
84 }); 84 });
85 85
86 + it('should not append toggle to an undefined div', function () {
87 + spyOn($log, 'warn');
88 + expect(bns.toggle(undefined, 'id', 'gid', false,
89 + function () {})).toBeNull();
90 + expect($log.warn).toHaveBeenCalledWith('Toggle cannot append to div');
91 + });
92 +
86 it('should verify toggle glyph', function () { 93 it('should verify toggle glyph', function () {
87 - var tog = bns.toggle(d3Elem, 'tbar0-tog-0', 'crown', function () {}); 94 + var tog = bns.toggle(d3Elem, 'tbar0-tog-0', 'crown',
95 + false, function () {});
88 expect((tog.el).classed('tog')).toBeTruthy(); 96 expect((tog.el).classed('tog')).toBeTruthy();
89 expect((tog.el).attr('id')).toBe('tbar0-tog-0'); 97 expect((tog.el).attr('id')).toBe('tbar0-tog-0');
90 expect((tog.el).select('svg')).toBeTruthy(); 98 expect((tog.el).select('svg')).toBeTruthy();
...@@ -116,10 +124,139 @@ describe('factory: fw/widget/button.js', function () { ...@@ -116,10 +124,139 @@ describe('factory: fw/widget/button.js', function () {
116 expect(tog.selected()).toBe(false); 124 expect(tog.selected()).toBe(false);
117 }); 125 });
118 126
119 - it('should not append toggle to an undefined div', function () { 127 + it('should verity toggle initial state', function () {
128 + var tog = bns.toggle(d3Elem, 'id', 'gid', true);
129 + expect(tog.selected()).toBe(true);
130 + tog = bns.toggle(d3Elem, 'id', 'gid', false);
131 + expect(tog.selected()).toBe(false);
132 + tog = bns.toggle(d3Elem, 'id', 'gid', '');
133 + expect(tog.selected()).toBe(false);
134 + tog = bns.toggle(d3Elem, 'id', 'gid', 'something');
135 + expect(tog.selected()).toBe(true);
136 + });
137 +
138 + it('should not append radio button set to an undefined div', function () {
120 spyOn($log, 'warn'); 139 spyOn($log, 'warn');
121 - expect(bns.toggle(undefined, 'id', 'gid', function () {})).toBeNull(); 140 + expect(bns.radioSet(undefined, 'id', [])).toBeNull();
122 - expect($log.warn).toHaveBeenCalledWith('Toggle cannot append to div'); 141 + expect($log.warn).toHaveBeenCalledWith('Radio buttons cannot append ' +
142 + 'to div');
143 + });
144 +
145 + it('should not create radio button set from a non-array', function () {
146 + var rads = {test: 'test'};
147 + spyOn($log, 'warn');
148 +
149 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
150 + expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
151 + 'an array');
152 + rads = 'rads';
153 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
154 + expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
155 + 'an array');
156 + rads = {arr: [1, 2, 3]};
157 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
158 + expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
159 + 'an array');
160 + });
161 +
162 + it('should not create radio button set from empty array', function () {
163 + var rads = [];
164 + spyOn($log, 'warn');
165 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
166 + expect($log.warn).toHaveBeenCalledWith('Cannot create radio button ' +
167 + 'set from empty array');
168 + });
169 +
170 + it('should verify radio button glyph structure', function () {
171 + var rads = [
172 + { gid: 'crown', cb: function () {}, tooltip: 'n/a'}
173 + ], rdiv;
174 +
175 + spyOn($log, 'warn');
176 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeTruthy();
177 + expect($log.warn).not.toHaveBeenCalled();
178 +
179 + rdiv = d3Elem.select('div');
180 + expect(rdiv.classed('rset')).toBe(true);
181 + expect(rdiv.select('div').classed('rad')).toBe(true);
182 + expect(rdiv.select('div').classed('tog')).toBe(false);
183 + expect(rdiv.select('div').attr('id')).toBe('test-0');
184 + expect(rdiv.select('div').select('svg')).toBeTruthy();
185 + expect(rdiv.select('use').classed('glyph')).toBeTruthy();
186 + expect(rdiv.select('use').attr('xlink:href')).toBe('#crown');
123 }); 187 });
124 188
189 + it('should verify more than one radio button glyph was added', function () {
190 + var rads = [
191 + { gid: 'crown', cb: function () {}, tooltip: 'n/a'},
192 + { gid: 'router', cb: function () {}, tooltip: 'n/a'}
193 + ], rdiv;
194 +
195 + expect(bns.radioSet(d3Elem, 'test', rads)).toBeTruthy();
196 + rdiv = d3Elem.select('div');
197 + expect(rdiv.select('#test-0')).toBeTruthy();
198 + expect(rdiv.select('#test-1')).toBeTruthy();
199 +
200 + expect(rdiv.select('#test-0')
201 + .select('use')
202 + .classed('glyph'))
203 + .toBeTruthy();
204 + expect(rdiv.select('#test-0')
205 + .select('use')
206 + .attr('xlink:href'))
207 + .toBe('#crown');
208 +
209 + expect(rdiv.select('#test-1')
210 + .select('use')
211 + .classed('glyph'))
212 + .toBeTruthy();
213 + expect(rdiv.select('#test-1')
214 + .select('use')
215 + .attr('xlink:href'))
216 + .toBe('#router');
217 + });
218 +
219 + it('should select the correct radio button', function () {
220 + var count0 = 0,
221 + count1 = 9;
222 + function cb0() { count0++; }
223 + function cb1() { count1++; }
224 +
225 + var rads = [
226 + { gid: 'crown', cb: cb0, tooltip: 'n/a'},
227 + { gid: 'router', cb: cb1, tooltip: 'n/a'}
228 + ],
229 + rset = bns.radioSet(d3Elem, 'test', rads);
230 + spyOn($log, 'error');
231 +
232 + expect(rset.selected()).toBe(0);
233 + expect(count0).toBe(0);
234 + expect(count1).toBe(9);
235 + rset.selected(0);
236 + expect(rset.selected()).toBe(0);
237 + expect(count0).toBe(0);
238 + expect(count1).toBe(9);
239 +
240 + rset.selected(1);
241 + expect(rset.selected()).toBe(1);
242 + expect(count0).toBe(1);
243 + expect(count1).toBe(10);
244 +
245 + rset.selected(-1);
246 + expect($log.error).toHaveBeenCalledWith('Cannot select radio button ' +
247 + 'of index -1');
248 + expect(rset.selected()).toBe(1);
249 + expect(count0).toBe(1);
250 + expect(count1).toBe(10);
251 +
252 + rset.selected(66);
253 + expect($log.error).toHaveBeenCalledWith('Cannot select radio button ' +
254 + 'of index 66');
255 + expect(rset.selected()).toBe(1);
256 + expect(count0).toBe(1);
257 + expect(count1).toBe(10);
258 + });
259 +
260 + // TODO: figure out how to trigger d3 onclick for buttons and toggles
261 +
125 }); 262 });
......
...@@ -18,19 +18,23 @@ ...@@ -18,19 +18,23 @@
18 ONOS GUI -- Widget -- Toolbar Service - Unit Tests 18 ONOS GUI -- Widget -- Toolbar Service - Unit Tests
19 */ 19 */
20 describe('factory: fw/widget/toolbar.js', function () { 20 describe('factory: fw/widget/toolbar.js', function () {
21 - var $log, fs, tbs, ps, 21 + var $log, fs, tbs, ps, bns, is,
22 d3Elem; 22 d3Elem;
23 23
24 - beforeEach(module('onosWidget', 'onosUtil', 'onosLayer')); 24 + beforeEach(module('onosWidget', 'onosUtil', 'onosLayer', 'onosSvg'));
25 25
26 - beforeEach(inject(function (_$log_, FnService, 26 + beforeEach(inject(function (_$log_, FnService, ToolbarService,
27 - ToolbarService, PanelService) { 27 + PanelService, ButtonService, IconService) {
28 $log = _$log_; 28 $log = _$log_;
29 fs = FnService; 29 fs = FnService;
30 tbs = ToolbarService; 30 tbs = ToolbarService;
31 ps = PanelService; 31 ps = PanelService;
32 + bns = ButtonService;
33 + is = IconService;
32 })); 34 }));
33 35
36 + // TODO: figure out solution for calling tests with new info instead of calling init
37 +
34 beforeEach(function () { 38 beforeEach(function () {
35 d3Elem = d3.select('body').append('div').attr('id', 'floatpanels'); 39 d3Elem = d3.select('body').append('div').attr('id', 'floatpanels');
36 tbs.init(); 40 tbs.init();
...@@ -50,7 +54,7 @@ describe('factory: fw/widget/toolbar.js', function () { ...@@ -50,7 +54,7 @@ describe('factory: fw/widget/toolbar.js', function () {
50 it('should define api functions', function () { 54 it('should define api functions', function () {
51 expect(fs.areFunctions(tbs, [ 55 expect(fs.areFunctions(tbs, [
52 'init', 'makeButton', 'makeToggle', 'makeRadio', 'separator', 56 'init', 'makeButton', 'makeToggle', 'makeRadio', 'separator',
53 - 'createToolbar' 57 + 'createToolbar', 'createToolbar1', 'destroyToolbar'
54 ])).toBeTruthy(); 58 ])).toBeTruthy();
55 }); 59 });
56 60
...@@ -264,4 +268,86 @@ describe('factory: fw/widget/toolbar.js', function () { ...@@ -264,4 +268,86 @@ describe('factory: fw/widget/toolbar.js', function () {
264 expect(sepDiv.style('border-style')).toBe('solid'); 268 expect(sepDiv.style('border-style')).toBe('solid');
265 }); 269 });
266 270
271 + // ==== new Toolbar Unit tests --------------------------------------------
272 +
273 + it('should warn if createToolbar id is invalid', function () {
274 + spyOn($log, 'warn');
275 + expect(tbs.createToolbar1()).toBeNull();
276 + expect($log.warn).toHaveBeenCalledWith('createToolbar: no ID given');
277 +
278 + expect(tbs.createToolbar1('test')).toBeTruthy();
279 + expect(tbs.createToolbar1('test')).toBeNull();
280 + expect($log.warn).toHaveBeenCalledWith('createToolbar: ID already exists');
281 + });
282 +
283 + it('should create an unpopulated toolbar', function () {
284 + spyOn($log, 'warn');
285 + expect(tbs.createToolbar1('test')).toBeTruthy();
286 + expect($log.warn).not.toHaveBeenCalled();
287 + });
288 +
289 + it('should create a button', function () {
290 + spyOn($log, 'warn');
291 + var toolbar = tbs.createToolbar1('test'),
292 + btn = toolbar.addButton1('btn0', 'gid', function () {});
293 + expect(btn).not.toBeNull();
294 + expect(btn.id).toBe('tbar-test-btn0');
295 + expect($log.warn).not.toHaveBeenCalled();
296 + });
297 +
298 + it('should not create a button with a duplicate id', function () {
299 + spyOn($log, 'warn');
300 + var toolbar = tbs.createToolbar1('test'),
301 + btn = toolbar.addButton1('btn0', 'gid', function () {}),
302 + btn1 = toolbar.addButton1('btn0', 'gid', function () {});
303 + expect(btn).not.toBeNull();
304 + expect(btn.id).toBe('tbar-test-btn0');
305 + expect($log.warn).toHaveBeenCalledWith('addButton: ID already exists');
306 + expect(btn1).toBeNull();
307 + });
308 +
309 + it('should create a toggle', function () {
310 + spyOn($log, 'warn');
311 + var toolbar = tbs.createToolbar1('test'),
312 + tog = toolbar.addButton1('tog0', 'gid', false, function () {});
313 + expect(tog).not.toBeNull();
314 + expect(tog.id).toBe('tbar-test-tog0');
315 + expect($log.warn).not.toHaveBeenCalled();
316 + });
317 +
318 + it('should not create a toggle with a duplicate id', function () {
319 + spyOn($log, 'warn');
320 + var toolbar = tbs.createToolbar1('test'),
321 + tog = toolbar.addToggle1('tog0', 'gid', false, function () {}),
322 + tog1 = toolbar.addToggle1('tog0', 'gid', true, function () {});
323 + expect(tog).not.toBeNull();
324 + expect(tog.id).toBe('tbar-test-tog0');
325 + expect($log.warn).toHaveBeenCalledWith('addToggle: ID already exists');
326 + expect(tog1).toBeNull();
327 + });
328 +
329 +
330 + it('should create a radio button set', function () {
331 + spyOn($log, 'warn');
332 + var toolbar = tbs.createToolbar1('test'),
333 + rset = [
334 + { gid: 'crown', cb: function () {}, tooltip: 'nothing' },
335 + { gid: 'bird', cb: function () {}, tooltip: 'nothing' }
336 + ],
337 + rad = toolbar.addRadioSet('rad0', rset);
338 + expect(rad).not.toBeNull();
339 + expect(rad.rads[0].id).toBe('tbar-test-rad0-0');
340 + expect(rad.rads[1].id).toBe('tbar-test-rad0-1');
341 + expect($log.warn).not.toHaveBeenCalled();
342 + });
343 +
344 + //it('should not append to a destroyed toolbar', function () {
345 + // spyOn($log, 'warn');
346 + // var toolbar = tbs.createToolbar1('test');
347 + // expect(toolbar).not.toBeNull();
348 + // tbs.destroyToolbar('tbar-test');
349 + // expect(toolbar.addButton1('btn', 'gid', function () {})).toBeNull();
350 + // expect($log.warn).toHaveBeenCalledWith('Button cannot append to div');
351 + //});
352 +
267 }); 353 });
......