GUI -- Cleaned up table directives, device view, fixed flash-spec unit tests, st…
…arted unt tests for table.js. Change-Id: I3020fec5f3f57cebc237c1a6cbfd07deb3607189
Showing
7 changed files
with
101 additions
and
178 deletions
... | @@ -28,10 +28,6 @@ svg.embeddedIcon .icon .glyph { | ... | @@ -28,10 +28,6 @@ svg.embeddedIcon .icon .glyph { |
28 | fill-rule: evenodd; | 28 | fill-rule: evenodd; |
29 | } | 29 | } |
30 | 30 | ||
31 | -div.inline-icon { | ||
32 | - display: inline-block; | ||
33 | -} | ||
34 | - | ||
35 | .light svg.embeddedIcon .icon.deviceOnline, | 31 | .light svg.embeddedIcon .icon.deviceOnline, |
36 | .light svg.embeddedIcon .icon.deviceOffline { | 32 | .light svg.embeddedIcon .icon.deviceOffline { |
37 | fill: none; | 33 | fill: none; | ... | ... |
... | @@ -34,8 +34,7 @@ | ... | @@ -34,8 +34,7 @@ |
34 | devIcon_SWITCH: 'switch', | 34 | devIcon_SWITCH: 'switch', |
35 | 35 | ||
36 | tableColSortAsc: 'triangleUp', | 36 | tableColSortAsc: 'triangleUp', |
37 | - tableColSortDesc: 'triangleDown', | 37 | + tableColSortDesc: 'triangleDown' |
38 | - tableColSortNone: '-' | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | 40 | ||
... | @@ -86,15 +85,13 @@ | ... | @@ -86,15 +85,13 @@ |
86 | rx: cornerSize | 85 | rx: cornerSize |
87 | }); | 86 | }); |
88 | 87 | ||
89 | - if (gid !== '-') { | 88 | + g.append('use').attr({ |
90 | - g.append('use').attr({ | 89 | + width: vboxSize, |
91 | - width: vboxSize, | 90 | + height: vboxSize, |
92 | - height: vboxSize, | 91 | + 'class': 'glyph', |
93 | - 'class': 'glyph', | 92 | + 'xlink:href': '#' + gid |
94 | - 'xlink:href': '#' + gid | 93 | + }); |
95 | - }); | 94 | +} |
96 | - } | ||
97 | - } | ||
98 | 95 | ||
99 | function loadEmbeddedIcon(div, iconCls, size) { | 96 | function loadEmbeddedIcon(div, iconCls, size) { |
100 | loadIcon(div, iconCls, size, true); | 97 | loadIcon(div, iconCls, size, true); | ... | ... |
... | @@ -21,51 +21,11 @@ | ... | @@ -21,51 +21,11 @@ |
21 | 'use strict'; | 21 | 'use strict'; |
22 | 22 | ||
23 | var $log, $window, fs, is, | 23 | var $log, $window, fs, is, |
24 | - div, | ||
25 | currCol = {}, | 24 | currCol = {}, |
26 | prevCol = {}, | 25 | prevCol = {}, |
27 | - tableIconTdSize = 30, | 26 | + tableIconTdSize = 33, |
28 | bottomMargin = 200; | 27 | bottomMargin = 200; |
29 | 28 | ||
30 | - | ||
31 | - // Render a plain d3 table by giving it the div, a config file, and data | ||
32 | - | ||
33 | - function renderTable(div, config, data) { | ||
34 | - var table = div.append('table'), | ||
35 | - colIds = config.colIds, | ||
36 | - colText = config.colText, | ||
37 | - dataObjects = data[Object.keys(data)[0]], | ||
38 | - thead, tbody, tRows; | ||
39 | - | ||
40 | - thead = table.append('thead'); | ||
41 | - tbody = table.append('tbody'); | ||
42 | - | ||
43 | - thead.append('tr').selectAll('th') | ||
44 | - .data(colText) | ||
45 | - .enter() | ||
46 | - .append('th') | ||
47 | - .text(function(d) { return d }); | ||
48 | - | ||
49 | - tRows = tbody.selectAll('tr') | ||
50 | - .data(dataObjects) | ||
51 | - .enter() | ||
52 | - .append('tr'); | ||
53 | - | ||
54 | - tRows.selectAll('td') | ||
55 | - .data(function(row) { | ||
56 | - return colIds.map(function(headerId) { | ||
57 | - return { | ||
58 | - column: headerId, value: row[headerId] | ||
59 | - }; | ||
60 | - }); | ||
61 | - }) | ||
62 | - .enter() | ||
63 | - .append('td') | ||
64 | - .html(function(d) { return d.value }); | ||
65 | - | ||
66 | - return table; | ||
67 | - } | ||
68 | - | ||
69 | // Functions for creating a fixed header on a table (Angular Directive) | 29 | // Functions for creating a fixed header on a table (Angular Directive) |
70 | 30 | ||
71 | function setTableWidth(t) { | 31 | function setTableWidth(t) { |
... | @@ -106,7 +66,10 @@ | ... | @@ -106,7 +66,10 @@ |
106 | setTableHeight(th, tb); | 66 | setTableHeight(th, tb); |
107 | } | 67 | } |
108 | 68 | ||
69 | + // Functions for sorting table rows by header and choosing appropriate icon | ||
70 | + | ||
109 | function updateSortingIcons(thElem, api) { | 71 | function updateSortingIcons(thElem, api) { |
72 | + var div; | ||
110 | currCol.colId = thElem.attr('colId'); | 73 | currCol.colId = thElem.attr('colId'); |
111 | 74 | ||
112 | if (currCol.colId === prevCol.colId) { | 75 | if (currCol.colId === prevCol.colId) { |
... | @@ -120,7 +83,7 @@ | ... | @@ -120,7 +83,7 @@ |
120 | } | 83 | } |
121 | 84 | ||
122 | div = thElem.select('div'); | 85 | div = thElem.select('div'); |
123 | - div.remove(); | 86 | + api.sortNone(div); |
124 | div = thElem.append('div'); | 87 | div = thElem.append('div'); |
125 | 88 | ||
126 | if (currCol.icon === 'tableColSortAsc') { | 89 | if (currCol.icon === 'tableColSortAsc') { |
... | @@ -151,15 +114,8 @@ | ... | @@ -151,15 +114,8 @@ |
151 | } | 114 | } |
152 | 115 | ||
153 | angular.module('onosWidget') | 116 | angular.module('onosWidget') |
154 | - .factory('TableService', [function () { | 117 | + .directive('onosFixedHeader', ['$window', 'FnService', |
155 | - return { | 118 | + function (_$window_, _fs_) { |
156 | - renderTable: renderTable | ||
157 | - }; | ||
158 | - }]) | ||
159 | - | ||
160 | - .directive('onosFixedHeader', ['$window', '$timeout', | ||
161 | - 'MastService', 'FnService', | ||
162 | - function (_$window_, $timeout, mast, _fs_) { | ||
163 | return function (scope, element) { | 119 | return function (scope, element) { |
164 | $window = _$window_; | 120 | $window = _$window_; |
165 | fs = _fs_; | 121 | fs = _fs_; |
... | @@ -206,7 +162,7 @@ | ... | @@ -206,7 +162,7 @@ |
206 | scope: { | 162 | scope: { |
207 | ctrlCallback: '&sortCallback' | 163 | ctrlCallback: '&sortCallback' |
208 | }, | 164 | }, |
209 | - link: function (scope, element, attrs) { | 165 | + link: function (scope, element) { |
210 | $log = _$log_; | 166 | $log = _$log_; |
211 | is = _is_; | 167 | is = _is_; |
212 | var table = d3.select(element[0]), | 168 | var table = d3.select(element[0]), |
... | @@ -219,7 +175,6 @@ | ... | @@ -219,7 +175,6 @@ |
219 | 175 | ||
220 | if (thElem.attr('sortable') === '') { | 176 | if (thElem.attr('sortable') === '') { |
221 | updateSortingIcons(thElem, sortIconAPI); | 177 | updateSortingIcons(thElem, sortIconAPI); |
222 | - // call the ctrl's rest callback function | ||
223 | scope.ctrlCallback({ | 178 | scope.ctrlCallback({ |
224 | urlSuffix: generateQueryParams() | 179 | urlSuffix: generateQueryParams() |
225 | }); | 180 | }); | ... | ... |
... | @@ -27,20 +27,15 @@ | ... | @@ -27,20 +27,15 @@ |
27 | var self = this; | 27 | var self = this; |
28 | self.deviceData = []; | 28 | self.deviceData = []; |
29 | 29 | ||
30 | - // TODO: remove test code | ||
31 | - var testCase = $location.search().test; | ||
32 | - var url = testCase ? 'test/' + testCase : 'device'; | ||
33 | - | ||
34 | $scope.sortCallback = function (urlSuffix) { | 30 | $scope.sortCallback = function (urlSuffix) { |
35 | if (!urlSuffix) { | 31 | if (!urlSuffix) { |
36 | urlSuffix = ''; | 32 | urlSuffix = ''; |
37 | } | 33 | } |
38 | - url = 'device' + urlSuffix; | 34 | + var url = 'device' + urlSuffix; |
39 | rs.get(url, function (data) { | 35 | rs.get(url, function (data) { |
40 | self.deviceData = data.devices; | 36 | self.deviceData = data.devices; |
41 | }); | 37 | }); |
42 | }; | 38 | }; |
43 | - | ||
44 | $scope.sortCallback(); | 39 | $scope.sortCallback(); |
45 | 40 | ||
46 | $log.log('OvDeviceCtrl has been created'); | 41 | $log.log('OvDeviceCtrl has been created'); | ... | ... |
... | @@ -27,11 +27,13 @@ describe('factory: fw/layer/flash.js', function () { | ... | @@ -27,11 +27,13 @@ describe('factory: fw/layer/flash.js', function () { |
27 | $timeout = _$timeout_; | 27 | $timeout = _$timeout_; |
28 | fs = FnService; | 28 | fs = FnService; |
29 | flash = FlashService; | 29 | flash = FlashService; |
30 | + jasmine.clock().install(); | ||
30 | d3Elem = d3.select('body').append('div').attr('id', 'myflashdiv'); | 31 | d3Elem = d3.select('body').append('div').attr('id', 'myflashdiv'); |
31 | flash.initFlash(); | 32 | flash.initFlash(); |
32 | })); | 33 | })); |
33 | 34 | ||
34 | afterEach(function () { | 35 | afterEach(function () { |
36 | + jasmine.clock().uninstall(); | ||
35 | d3.select('#myflashdiv').remove(); | 37 | d3.select('#myflashdiv').remove(); |
36 | }); | 38 | }); |
37 | 39 | ||
... | @@ -56,6 +58,7 @@ describe('factory: fw/layer/flash.js', function () { | ... | @@ -56,6 +58,7 @@ describe('factory: fw/layer/flash.js', function () { |
56 | it('should flash the message Foo', function () { | 58 | it('should flash the message Foo', function () { |
57 | var item, rect, text; | 59 | var item, rect, text; |
58 | flash.flash('foo'); | 60 | flash.flash('foo'); |
61 | + jasmine.clock().tick(101); | ||
59 | setTimeout(function () { | 62 | setTimeout(function () { |
60 | item = flashItemSelection(); | 63 | item = flashItemSelection(); |
61 | expect(item.size()).toEqual(1); | 64 | expect(item.size()).toEqual(1); |
... | @@ -64,9 +67,6 @@ describe('factory: fw/layer/flash.js', function () { | ... | @@ -64,9 +67,6 @@ describe('factory: fw/layer/flash.js', function () { |
64 | text = item.select('text'); | 67 | text = item.select('text'); |
65 | expect(text.size()).toEqual(1); | 68 | expect(text.size()).toEqual(1); |
66 | expect(text.text()).toEqual('foo'); | 69 | expect(text.text()).toEqual('foo'); |
67 | - }, 2000); | 70 | + }, 100); |
68 | }); | 71 | }); |
69 | - | ||
70 | - // TODO: testing these time-sensitive behaviors is hard... | ||
71 | - // need to work on this some other time. | ||
72 | }); | 72 | }); | ... | ... |
... | @@ -17,116 +17,94 @@ | ... | @@ -17,116 +17,94 @@ |
17 | /* | 17 | /* |
18 | ONOS GUI -- Widget -- Table Service - Unit Tests | 18 | ONOS GUI -- Widget -- Table Service - Unit Tests |
19 | */ | 19 | */ |
20 | -describe('factory: fw/widget/table.js', function() { | 20 | +describe('factory: fw/widget/table.js', function () { |
21 | - var ts, $log, d3Elem; | 21 | + var $log, $compile, $rootScope, |
22 | + fs, is, | ||
23 | + table; | ||
22 | 24 | ||
23 | - var config = { | 25 | + var onosFixedHeaderTags = '<table ' + |
24 | - colIds: ['id', 'mfr', 'hw', 'sw', 'serial', 'annotations.protocol'], | 26 | + 'onos-fixed-header ' + |
25 | - colText: ['URI', 'Vendor', 'Hardware Version', 'Software Version', | 27 | + 'ng-style="setTableHW()">' + |
26 | - 'Serial Number', 'Protocol'] | 28 | + '<thead>' + |
27 | - }, | 29 | + '<tr>' + |
28 | - fakeData = { | 30 | + '<th></th>' + |
29 | - "devices": [{ | 31 | + '<th>Device ID </th>' + |
30 | - "id": "of:0000000000000001", | 32 | + '<th>H/W Version </th>' + |
31 | - "available": true, | 33 | + '<th>S/W Version </th>' + |
32 | - "_iconid_available": "deviceOnline", | 34 | + '</tr>' + |
33 | - "role": "MASTER", | 35 | + '</thead>' + |
34 | - "mfr": "Nicira, Inc.", | 36 | + '<tbody>' + |
35 | - "hw": "Open vSwitch", | 37 | + '<tr>' + |
36 | - "sw": "2.0.1", | 38 | + '<td>' + |
37 | - "serial": "None", | 39 | + '<div icon icon-id="{{dev._iconid_available}}">' + |
38 | - "annotations": { | 40 | + '</div>' + |
39 | - "protocol": "OF_10" | 41 | + '</td>' + |
40 | - } | 42 | + '<td>Some ID</td>' + |
41 | - }, | 43 | + '<td>Some HW</td>' + |
42 | - { | 44 | + '<td>Some Software</td>' + |
43 | - "id": "of:0000000000000004", | 45 | + '</tr>' + |
44 | - "available": false, | 46 | + '</tbody>' + |
45 | - "_iconid_available": "deviceOffline", | 47 | + '</table>', |
46 | - "role": "MASTER", | ||
47 | - "mfr": "Nicira, Inc.", | ||
48 | - "hw": "Open vSwitch", | ||
49 | - "sw": "2.0.1", | ||
50 | - "serial": "None", | ||
51 | - "annotations": { | ||
52 | - "protocol": "OF_10" | ||
53 | - } | ||
54 | - }, | ||
55 | - { | ||
56 | - "id": "of:0000000000000092", | ||
57 | - "available": false, | ||
58 | - "_iconid_available": "deviceOffline", | ||
59 | - "role": "MASTER", | ||
60 | - "mfr": "Nicira, Inc.", | ||
61 | - "hw": "Open vSwitch", | ||
62 | - "sw": "2.0.1", | ||
63 | - "serial": "None", | ||
64 | - "annotations": { | ||
65 | - "protocol": "OF_10" | ||
66 | - } | ||
67 | - }] | ||
68 | - }; | ||
69 | 48 | ||
70 | - beforeEach(module('onosWidget')); | 49 | + onosSortableHeaderTags = '<table class="summary-list" ' + |
50 | + 'onos-sortable-header ' + | ||
51 | + 'sort-callback="sortCallback(urlSuffix)">' + | ||
52 | + '<thead>' + | ||
53 | + '<tr>' + | ||
54 | + '<th colId="available"></th>' + | ||
55 | + '<th colId="id" sortable>Device ID </th>' + | ||
56 | + '<th colId="hw" sortable>H/W Version </th>' + | ||
57 | + '<th colId="sw" sortable>S/W Version </th>' + | ||
58 | + '</tr>' + | ||
59 | + '</thead>' + | ||
60 | + '<tbody>' + | ||
61 | + '<tr>' + | ||
62 | + '<td>' + | ||
63 | + '<div icon icon-id="{{dev._iconid_available}}">' + | ||
64 | + '</div>' + | ||
65 | + '</td>' + | ||
66 | + '<td>Some ID</td>' + | ||
67 | + '<td>Some HW</td>' + | ||
68 | + '<td>Some Software</td>' + | ||
69 | + '</tr>' + | ||
70 | + '</tbody>' + | ||
71 | + '</table>'; | ||
71 | 72 | ||
72 | - beforeEach(inject(function (TableService, _$log_) { | 73 | + beforeEach(module('onosWidget', 'onosUtil', 'onosSvg')); |
73 | - ts = TableService; | 74 | + |
75 | + beforeEach(inject(function (_$log_, _$compile_, _$rootScope_, | ||
76 | + FnService, IconService) { | ||
74 | $log = _$log_; | 77 | $log = _$log_; |
75 | - d3Elem = d3.select('body').append('div').attr('id', 'myDiv'); | 78 | + $compile = _$compile_; |
79 | + $rootScope = _$rootScope_; | ||
80 | + fs = FnService; | ||
81 | + is = IconService; | ||
76 | })); | 82 | })); |
77 | 83 | ||
78 | - afterEach(function () { | 84 | + beforeEach(function () { |
79 | - d3.select('#myDiv').remove(); | ||
80 | }); | 85 | }); |
81 | 86 | ||
82 | - it('should define TableService', function () { | 87 | + afterEach(function () { |
83 | - expect(ts).toBeDefined(); | 88 | + table = null; |
84 | }); | 89 | }); |
85 | 90 | ||
86 | - function verifyTableTags(div) { | 91 | + it('should affirm that onos-fixed-header is working', function () { |
87 | - var table = div.select('table'), | 92 | + table = $compile(onosFixedHeaderTags)($rootScope); |
88 | - tableHeaders; | 93 | + $rootScope.$digest(); |
89 | - expect(table).toBeTruthy(); | ||
90 | - expect(table.attr('fixed-header')).toBeFalsy(); | ||
91 | - expect(table.select('thead')).toBeTruthy(); | ||
92 | - expect(table.select('tbody')).toBeTruthy(); | ||
93 | 94 | ||
94 | - tableHeaders = table.select('thead').selectAll('th'); | 95 | + table = d3.select(table); |
95 | - tableHeaders.each(function(thElement, i) { | 96 | + expect(table).toBeDefined(); |
96 | - thElement = d3.select(this); | ||
97 | - expect(thElement).toBeTruthy(); | ||
98 | - expect(thElement.html()).toBe(config.colText[i]); | ||
99 | - }); | ||
100 | - } | ||
101 | 97 | ||
102 | - function verifyData(div) { | 98 | + //expect(table.select('thead').style('display')).toBe('block'); |
103 | - var tbody = div.select('tbody'), | 99 | + }); |
104 | - tableBoxes = tbody.selectAll('td'); | ||
105 | - expect(tbody).toBeTruthy(); | ||
106 | - expect(tbody.select('tr')).toBeTruthy(); | ||
107 | 100 | ||
108 | - tableBoxes.each(function(tdElement, i){ | 101 | + it('should affirm that onos-sortable-header is working', function () { |
109 | - tdElement = d3.select(this); | 102 | + table = $compile(onosSortableHeaderTags)($rootScope); |
110 | - if(i === 0) { | 103 | + $rootScope.$digest(); |
111 | - expect(tdElement.html()).toBe('of:0000000000000001'); | ||
112 | - } | ||
113 | - if(i === 1) { | ||
114 | - expect(tdElement.html()).toBe('Nicira, Inc.'); | ||
115 | - } | ||
116 | - if(i === 2) { | ||
117 | - expect(tdElement.html()).toBe('Open vSwitch'); | ||
118 | - } | ||
119 | - expect(tdElement).toBeTruthy(); | ||
120 | - }); | ||
121 | - } | ||
122 | 104 | ||
123 | - it('should create table tags', function () { | 105 | + table = d3.select(table); |
124 | - ts.renderTable(d3Elem, config, fakeData); | 106 | + expect(table).toBeDefined(); |
125 | - verifyTableTags(d3Elem); | ||
126 | }); | 107 | }); |
127 | 108 | ||
128 | - it('should load data into table', function () { | 109 | + // TODO: write directive unit tests for table.js |
129 | - ts.renderTable(d3Elem, config, fakeData); | ||
130 | - verifyData(d3Elem); | ||
131 | - }); | ||
132 | }); | 110 | }); | ... | ... |
... | @@ -45,14 +45,16 @@ describe('Controller: OvDeviceCtrl', function () { | ... | @@ -45,14 +45,16 @@ describe('Controller: OvDeviceCtrl', function () { |
45 | $scope = $rootScope.$new(); | 45 | $scope = $rootScope.$new(); |
46 | $controller = _$controller_; | 46 | $controller = _$controller_; |
47 | $mockHttp = $httpBackend; | 47 | $mockHttp = $httpBackend; |
48 | + })); | ||
48 | 49 | ||
50 | + beforeEach(function() { | ||
51 | + $scope = {}; | ||
52 | + ctrl = $controller('OvDeviceCtrl', { $scope: $scope }); | ||
49 | $mockHttp.whenGET(/\/device$/).respond(fakeData); | 53 | $mockHttp.whenGET(/\/device$/).respond(fakeData); |
50 | - })); | 54 | + }); |
55 | + | ||
51 | 56 | ||
52 | it('should be an empty array and then have device data', function () { | 57 | it('should be an empty array and then have device data', function () { |
53 | - ctrl = $controller('OvDeviceCtrl', { | ||
54 | - $scope: $scope | ||
55 | - }); | ||
56 | expect(ctrl.deviceData).toEqual([]); | 58 | expect(ctrl.deviceData).toEqual([]); |
57 | $scope.sortCallback(); | 59 | $scope.sortCallback(); |
58 | $mockHttp.flush(); | 60 | $mockHttp.flush(); | ... | ... |
-
Please register or login to post a comment