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 @@
}
function button(div, id, gid, cb, tooltip) {
if (!div) {
if (!div || div.empty()) {
$log.warn('Button cannot append to div');
return null;
}
var btnDiv = createDiv(div, 'btn', id),
svg = btnDiv.append('svg'),
cbFnc = fs.isF(cb) || noop;
is.loadIcon(btnDiv, gid, btnSize);
......@@ -53,36 +52,81 @@
}
}
function toggle(div, id, gid, cb, tooltip) {
if (!div) {
function toggle(div, id, gid, initState, cb, tooltip) {
if (!div || div.empty()) {
$log.warn('Toggle cannot append to div');
return null;
}
var sel = false,
var sel = !!initState,
togDiv = createDiv(div, 'tog', id),
svg = togDiv.append('svg'),
cbFnc = fs.isF(cb) || noop;
is.loadIcon(togDiv, gid, btnSize);
function _toggle(b) {
if (b === undefined) {
sel = !sel;
} else {
sel = !!b;
}
cbFnc(sel);
}
togDiv.on('click', _toggle);
return {
id: id,
el: togDiv,
selected: function () { return sel; },
toggle: function (b) {
if (b === undefined) {
sel = !sel;
} else {
sel = !!b;
}
cbFnc(sel);
}
toggle: _toggle
}
}
function radioSet(div, id, rset) {
return {}
if (!div || div.empty()) {
$log.warn('Radio buttons cannot append to div');
return null;
}
if (!fs.isA(rset)) {
$log.warn('Radio button set is not an array');
return null;
}
if (rset.length === 0) {
$log.warn('Cannot create radio button set from empty array');
return null;
}
var rDiv = div.append('div').classed('rset', true),
sel = 0,
rads = [];
rset.forEach(function (btn, index) {
var rid = {id: id + '-' + index},
rbtn = angular.extend({}, btn, rid),
istate = (index === 0),
rtog = toggle(rDiv, rbtn.id, rbtn.gid, istate,
rbtn.cb, rbtn.tooltip);
rtog.el = (rtog.el).classed('tog', false).classed('rad', true);
rads.push(rtog);
});
return {
rads: rads,
selected: function (i) {
if (i === undefined) { return sel; }
else if (i < 0 || i >= rads.length) {
$log.error('Cannot select radio button of index ' + i);
}
else {
if (i !== sel) {
rads[sel].toggle(false);
rads[i].toggle(true);
sel = i;
}
}
}
}
}
angular.module('onosWidget')
......
......@@ -20,14 +20,20 @@
(function () {
'use strict';
var $log, ps;
var $log, fs, ps, bns;
var toolBtnIds = {},
toolbarPanel,
toolbarDiv;
var ids = [],
tbarId,
tbarPanel,
tbarDiv;
function init() {
toolBtnIds = {};
ids = [];
}
function addButton(btn) {
......@@ -90,6 +96,76 @@
};
}
function validId(id, caller) {
if (fs.inArray(id, ids) !== -1) {
$log.warn(caller + ': ID already exists');
return false;
}
return true;
}
function addButton1(id, gid, cb, tooltip) {
var btnId = tbarId + '-' + id;
if (!validId(btnId, 'addButton')) {
return null;
}
ids.push(btnId);
return bns.button(tbarDiv, btnId, gid, cb, tooltip);
}
function addToggle1(id, gid, initState, cb, tooltip) {
var togId = tbarId + '-' + id;
if (!validId(togId, 'addToggle')) {
return null;
}
ids.push(togId);
return bns.toggle(tbarDiv, togId, gid, initState, cb, tooltip);
}
function addRadioSet(id, rset) {
var radId = tbarId + '-' + id;
if (!validId(radId, 'addRadioSet')) {
return null;
}
ids.push(radId);
return bns.radioSet(tbarDiv, radId, rset);
}
// TODO: finish this and remove unneeded code
function addSeparator1() {
}
function createToolbar1(id, settings) {
if (!id) {
$log.warn('createToolbar: no ID given');
return null;
}
tbarId = 'tbar-' + id;
var opts = fs.isO(settings) || {}; // default settings should be put here
if (!validId(tbarId, 'createToolbar')) {
return null;
}
ids.push(tbarId);
tbarPanel = ps.createPanel(tbarId, opts);
tbarDiv = tbarPanel.classed('toolbar', true);
// TODO: change names of functions
return {
addButton1: addButton1,
addToggle1: addToggle1,
addRadioSet: addRadioSet,
addSeparator1: addSeparator1
}
}
// function currently not working
function destroyToolbar(id) {
ps.destroyPanel(id);
}
function createToolbar(tbarId, tools) {
var api;
......@@ -143,10 +219,13 @@
}
angular.module('onosWidget')
.factory('ToolbarService', ['$log', 'PanelService',
function (_$log_, _ps_) {
.factory('ToolbarService', ['$log', 'FnService',
'PanelService', 'ButtonService',
function (_$log_, _fs_, _ps_, _bns_) {
$log = _$log_;
fs = _fs_;
ps = _ps_;
bns = _bns_;
return {
init: init,
......@@ -154,7 +233,9 @@
makeToggle: makeToggle,
makeRadio: makeRadio,
separator: separator,
createToolbar: createToolbar
createToolbar: createToolbar,
createToolbar1: createToolbar1,
destroyToolbar: destroyToolbar
};
}]);
......
......@@ -83,8 +83,16 @@ describe('factory: fw/widget/button.js', function () {
expect(count).toBe(0);
});
it('should not append toggle to an undefined div', function () {
spyOn($log, 'warn');
expect(bns.toggle(undefined, 'id', 'gid', false,
function () {})).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Toggle cannot append to div');
});
it('should verify toggle glyph', function () {
var tog = bns.toggle(d3Elem, 'tbar0-tog-0', 'crown', function () {});
var tog = bns.toggle(d3Elem, 'tbar0-tog-0', 'crown',
false, function () {});
expect((tog.el).classed('tog')).toBeTruthy();
expect((tog.el).attr('id')).toBe('tbar0-tog-0');
expect((tog.el).select('svg')).toBeTruthy();
......@@ -116,10 +124,139 @@ describe('factory: fw/widget/button.js', function () {
expect(tog.selected()).toBe(false);
});
it('should not append toggle to an undefined div', function () {
it('should verity toggle initial state', function () {
var tog = bns.toggle(d3Elem, 'id', 'gid', true);
expect(tog.selected()).toBe(true);
tog = bns.toggle(d3Elem, 'id', 'gid', false);
expect(tog.selected()).toBe(false);
tog = bns.toggle(d3Elem, 'id', 'gid', '');
expect(tog.selected()).toBe(false);
tog = bns.toggle(d3Elem, 'id', 'gid', 'something');
expect(tog.selected()).toBe(true);
});
it('should not append radio button set to an undefined div', function () {
spyOn($log, 'warn');
expect(bns.toggle(undefined, 'id', 'gid', function () {})).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Toggle cannot append to div');
expect(bns.radioSet(undefined, 'id', [])).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Radio buttons cannot append ' +
'to div');
});
it('should not create radio button set from a non-array', function () {
var rads = {test: 'test'};
spyOn($log, 'warn');
expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
'an array');
rads = 'rads';
expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
'an array');
rads = {arr: [1, 2, 3]};
expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Radio button set is not ' +
'an array');
});
it('should not create radio button set from empty array', function () {
var rads = [];
spyOn($log, 'warn');
expect(bns.radioSet(d3Elem, 'test', rads)).toBeNull();
expect($log.warn).toHaveBeenCalledWith('Cannot create radio button ' +
'set from empty array');
});
it('should verify radio button glyph structure', function () {
var rads = [
{ gid: 'crown', cb: function () {}, tooltip: 'n/a'}
], rdiv;
spyOn($log, 'warn');
expect(bns.radioSet(d3Elem, 'test', rads)).toBeTruthy();
expect($log.warn).not.toHaveBeenCalled();
rdiv = d3Elem.select('div');
expect(rdiv.classed('rset')).toBe(true);
expect(rdiv.select('div').classed('rad')).toBe(true);
expect(rdiv.select('div').classed('tog')).toBe(false);
expect(rdiv.select('div').attr('id')).toBe('test-0');
expect(rdiv.select('div').select('svg')).toBeTruthy();
expect(rdiv.select('use').classed('glyph')).toBeTruthy();
expect(rdiv.select('use').attr('xlink:href')).toBe('#crown');
});
it('should verify more than one radio button glyph was added', function () {
var rads = [
{ gid: 'crown', cb: function () {}, tooltip: 'n/a'},
{ gid: 'router', cb: function () {}, tooltip: 'n/a'}
], rdiv;
expect(bns.radioSet(d3Elem, 'test', rads)).toBeTruthy();
rdiv = d3Elem.select('div');
expect(rdiv.select('#test-0')).toBeTruthy();
expect(rdiv.select('#test-1')).toBeTruthy();
expect(rdiv.select('#test-0')
.select('use')
.classed('glyph'))
.toBeTruthy();
expect(rdiv.select('#test-0')
.select('use')
.attr('xlink:href'))
.toBe('#crown');
expect(rdiv.select('#test-1')
.select('use')
.classed('glyph'))
.toBeTruthy();
expect(rdiv.select('#test-1')
.select('use')
.attr('xlink:href'))
.toBe('#router');
});
it('should select the correct radio button', function () {
var count0 = 0,
count1 = 9;
function cb0() { count0++; }
function cb1() { count1++; }
var rads = [
{ gid: 'crown', cb: cb0, tooltip: 'n/a'},
{ gid: 'router', cb: cb1, tooltip: 'n/a'}
],
rset = bns.radioSet(d3Elem, 'test', rads);
spyOn($log, 'error');
expect(rset.selected()).toBe(0);
expect(count0).toBe(0);
expect(count1).toBe(9);
rset.selected(0);
expect(rset.selected()).toBe(0);
expect(count0).toBe(0);
expect(count1).toBe(9);
rset.selected(1);
expect(rset.selected()).toBe(1);
expect(count0).toBe(1);
expect(count1).toBe(10);
rset.selected(-1);
expect($log.error).toHaveBeenCalledWith('Cannot select radio button ' +
'of index -1');
expect(rset.selected()).toBe(1);
expect(count0).toBe(1);
expect(count1).toBe(10);
rset.selected(66);
expect($log.error).toHaveBeenCalledWith('Cannot select radio button ' +
'of index 66');
expect(rset.selected()).toBe(1);
expect(count0).toBe(1);
expect(count1).toBe(10);
});
// TODO: figure out how to trigger d3 onclick for buttons and toggles
});
......
......@@ -18,19 +18,23 @@
ONOS GUI -- Widget -- Toolbar Service - Unit Tests
*/
describe('factory: fw/widget/toolbar.js', function () {
var $log, fs, tbs, ps,
var $log, fs, tbs, ps, bns, is,
d3Elem;
beforeEach(module('onosWidget', 'onosUtil', 'onosLayer'));
beforeEach(module('onosWidget', 'onosUtil', 'onosLayer', 'onosSvg'));
beforeEach(inject(function (_$log_, FnService,
ToolbarService, PanelService) {
beforeEach(inject(function (_$log_, FnService, ToolbarService,
PanelService, ButtonService, IconService) {
$log = _$log_;
fs = FnService;
tbs = ToolbarService;
ps = PanelService;
bns = ButtonService;
is = IconService;
}));
// TODO: figure out solution for calling tests with new info instead of calling init
beforeEach(function () {
d3Elem = d3.select('body').append('div').attr('id', 'floatpanels');
tbs.init();
......@@ -50,7 +54,7 @@ describe('factory: fw/widget/toolbar.js', function () {
it('should define api functions', function () {
expect(fs.areFunctions(tbs, [
'init', 'makeButton', 'makeToggle', 'makeRadio', 'separator',
'createToolbar'
'createToolbar', 'createToolbar1', 'destroyToolbar'
])).toBeTruthy();
});
......@@ -264,4 +268,86 @@ describe('factory: fw/widget/toolbar.js', function () {
expect(sepDiv.style('border-style')).toBe('solid');
});
// ==== new Toolbar Unit tests --------------------------------------------
it('should warn if createToolbar id is invalid', function () {
spyOn($log, 'warn');
expect(tbs.createToolbar1()).toBeNull();
expect($log.warn).toHaveBeenCalledWith('createToolbar: no ID given');
expect(tbs.createToolbar1('test')).toBeTruthy();
expect(tbs.createToolbar1('test')).toBeNull();
expect($log.warn).toHaveBeenCalledWith('createToolbar: ID already exists');
});
it('should create an unpopulated toolbar', function () {
spyOn($log, 'warn');
expect(tbs.createToolbar1('test')).toBeTruthy();
expect($log.warn).not.toHaveBeenCalled();
});
it('should create a button', function () {
spyOn($log, 'warn');
var toolbar = tbs.createToolbar1('test'),
btn = toolbar.addButton1('btn0', 'gid', function () {});
expect(btn).not.toBeNull();
expect(btn.id).toBe('tbar-test-btn0');
expect($log.warn).not.toHaveBeenCalled();
});
it('should not create a button with a duplicate id', function () {
spyOn($log, 'warn');
var toolbar = tbs.createToolbar1('test'),
btn = toolbar.addButton1('btn0', 'gid', function () {}),
btn1 = toolbar.addButton1('btn0', 'gid', function () {});
expect(btn).not.toBeNull();
expect(btn.id).toBe('tbar-test-btn0');
expect($log.warn).toHaveBeenCalledWith('addButton: ID already exists');
expect(btn1).toBeNull();
});
it('should create a toggle', function () {
spyOn($log, 'warn');
var toolbar = tbs.createToolbar1('test'),
tog = toolbar.addButton1('tog0', 'gid', false, function () {});
expect(tog).not.toBeNull();
expect(tog.id).toBe('tbar-test-tog0');
expect($log.warn).not.toHaveBeenCalled();
});
it('should not create a toggle with a duplicate id', function () {
spyOn($log, 'warn');
var toolbar = tbs.createToolbar1('test'),
tog = toolbar.addToggle1('tog0', 'gid', false, function () {}),
tog1 = toolbar.addToggle1('tog0', 'gid', true, function () {});
expect(tog).not.toBeNull();
expect(tog.id).toBe('tbar-test-tog0');
expect($log.warn).toHaveBeenCalledWith('addToggle: ID already exists');
expect(tog1).toBeNull();
});
it('should create a radio button set', function () {
spyOn($log, 'warn');
var toolbar = tbs.createToolbar1('test'),
rset = [
{ gid: 'crown', cb: function () {}, tooltip: 'nothing' },
{ gid: 'bird', cb: function () {}, tooltip: 'nothing' }
],
rad = toolbar.addRadioSet('rad0', rset);
expect(rad).not.toBeNull();
expect(rad.rads[0].id).toBe('tbar-test-rad0-0');
expect(rad.rads[1].id).toBe('tbar-test-rad0-1');
expect($log.warn).not.toHaveBeenCalled();
});
//it('should not append to a destroyed toolbar', function () {
// spyOn($log, 'warn');
// var toolbar = tbs.createToolbar1('test');
// expect(toolbar).not.toBeNull();
// tbs.destroyToolbar('tbar-test');
// expect(toolbar.addButton1('btn', 'gid', function () {})).toBeNull();
// expect($log.warn).toHaveBeenCalledWith('Button cannot append to div');
//});
});
......