Bri Prebilic Cole

GUI -- Removed onos-fixed-header redundancies, wrote unit tests for fixed-header…

… and sortable-header directives.

Change-Id: Iccf9348a4697f494a4234b024781fede0719491d
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
34 34
35 tHeaders = t.selectAll('th'); 35 tHeaders = t.selectAll('th');
36 numCols = tHeaders[0].length; 36 numCols = tHeaders[0].length;
37 - colWidth = Math.floor(winWidth/numCols); 37 + colWidth = Math.floor(winWidth / numCols);
38 38
39 tHeaders.each(function(thElement, index) { 39 tHeaders.each(function(thElement, index) {
40 thElement = d3.select(this); 40 thElement = d3.select(this);
...@@ -121,7 +121,9 @@ ...@@ -121,7 +121,9 @@
121 fs = _fs_; 121 fs = _fs_;
122 var w = angular.element($window), 122 var w = angular.element($window),
123 table = d3.select(element[0]), 123 table = d3.select(element[0]),
124 - shouldResize = false; 124 + thead = table.select('thead'),
125 + tbody = table.select('tbody'),
126 + canAdjust = false;
125 127
126 scope.$watch(function () { 128 scope.$watch(function () {
127 return { 129 return {
...@@ -129,31 +131,24 @@ ...@@ -129,31 +131,24 @@
129 w: window.innerWidth 131 w: window.innerWidth
130 }; 132 };
131 }, function (newVal) { 133 }, function (newVal) {
132 - var thead = table.select('thead'),
133 - tbody = table.select('tbody');
134 -
135 scope.windowHeight = newVal.h; 134 scope.windowHeight = newVal.h;
136 scope.windowWidth = newVal.w; 135 scope.windowWidth = newVal.w;
137 136
138 - scope.setTableHW = function () { 137 + scope.$on('LastElement', function () {
139 - scope.$on('LastElement', function (event) { 138 + // only adjust the table once it's completely loaded
140 - // only adjust the table once it's completely loaded 139 + fixTable(table, thead, tbody);
141 - fixTable(table, thead, tbody); 140 + canAdjust = true;
142 - shouldResize = true; 141 + });
143 - });
144 - };
145 142
146 - if (shouldResize) { 143 + if (canAdjust) {
147 fixTable(table, thead, tbody); 144 fixTable(table, thead, tbody);
148 } 145 }
149 -
150 }, true); 146 }, true);
151 147
152 w.bind('onos-fixed-header', function () { 148 w.bind('onos-fixed-header', function () {
153 scope.$apply(); 149 scope.$apply();
154 }); 150 });
155 }; 151 };
156 -
157 }]) 152 }])
158 153
159 .directive('onosSortableHeader', ['$log', 'IconService', 154 .directive('onosSortableHeader', ['$log', 'IconService',
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
3 <h2>Devices ({{ctrl.deviceData.length}} total)</h2> 3 <h2>Devices ({{ctrl.deviceData.length}} total)</h2>
4 <table class="summary-list" 4 <table class="summary-list"
5 onos-fixed-header 5 onos-fixed-header
6 - ng-style="setTableHW()"
7 onos-sortable-header 6 onos-sortable-header
8 sort-callback="sortCallback(urlSuffix)"> 7 sort-callback="sortCallback(urlSuffix)">
9 <thead> 8 <thead>
......
...@@ -20,11 +20,14 @@ ...@@ -20,11 +20,14 @@
20 describe('factory: fw/widget/table.js', function () { 20 describe('factory: fw/widget/table.js', function () {
21 var $log, $compile, $rootScope, 21 var $log, $compile, $rootScope,
22 fs, is, 22 fs, is,
23 - table; 23 + scope, compiled,
24 + table, thead, tbody,
25 + tableIconTdSize = 33,
26 + bottomMargin = 200,
27 + numTestElems = 4;
24 28
25 var onosFixedHeaderTags = '<table ' + 29 var onosFixedHeaderTags = '<table ' +
26 - 'onos-fixed-header ' + 30 + 'onos-fixed-header>' +
27 - 'ng-style="setTableHW()">' +
28 '<thead>' + 31 '<thead>' +
29 '<tr>' + 32 '<tr>' +
30 '<th></th>' + 33 '<th></th>' +
...@@ -35,7 +38,7 @@ describe('factory: fw/widget/table.js', function () { ...@@ -35,7 +38,7 @@ describe('factory: fw/widget/table.js', function () {
35 '</thead>' + 38 '</thead>' +
36 '<tbody>' + 39 '<tbody>' +
37 '<tr>' + 40 '<tr>' +
38 - '<td>' + 41 + '<td class="table-icon">' +
39 '<div icon icon-id="{{dev._iconid_available}}">' + 42 '<div icon icon-id="{{dev._iconid_available}}">' +
40 '</div>' + 43 '</div>' +
41 '</td>' + 44 '</td>' +
...@@ -46,7 +49,7 @@ describe('factory: fw/widget/table.js', function () { ...@@ -46,7 +49,7 @@ describe('factory: fw/widget/table.js', function () {
46 '</tbody>' + 49 '</tbody>' +
47 '</table>', 50 '</table>',
48 51
49 - onosSortableHeaderTags = '<table class="summary-list" ' + 52 + onosSortableHeaderTags = '<table ' +
50 'onos-sortable-header ' + 53 'onos-sortable-header ' +
51 'sort-callback="sortCallback(urlSuffix)">' + 54 'sort-callback="sortCallback(urlSuffix)">' +
52 '<thead>' + 55 '<thead>' +
...@@ -82,29 +85,149 @@ describe('factory: fw/widget/table.js', function () { ...@@ -82,29 +85,149 @@ describe('factory: fw/widget/table.js', function () {
82 })); 85 }));
83 86
84 beforeEach(function () { 87 beforeEach(function () {
88 + scope = $rootScope.$new();
85 }); 89 });
86 90
87 afterEach(function () { 91 afterEach(function () {
88 table = null; 92 table = null;
93 + thead = null;
94 + tbody = null;
89 }); 95 });
90 96
91 - it('should affirm that onos-fixed-header is working', function () { 97 + function compileTable() {
92 - table = $compile(onosFixedHeaderTags)($rootScope); 98 + compiled = $compile(table);
93 - $rootScope.$digest(); 99 + compiled(scope);
100 + scope.$digest();
101 + }
94 102
95 - table = d3.select(table); 103 + function verifyGivenTags(dirName) {
96 expect(table).toBeDefined(); 104 expect(table).toBeDefined();
105 + expect(table.attr(dirName)).toBe('');
106 +
107 + thead = table.find('thead');
108 + expect(thead).toBeDefined();
109 + tbody = table.find('tbody');
110 + expect(tbody).toBeDefined();
111 + }
112 +
113 + function verifyCssDisplay() {
114 + var winHeight = fs.windowSize().height;
115 +
116 + expect(thead.css('display')).toBe('block');
117 + expect(tbody.css('display')).toBe('block');
118 + expect(tbody.css('height')).toBe((winHeight - bottomMargin) + 'px');
119 + expect(tbody.css('overflow')).toBe('auto');
120 + }
121 +
122 + function verifyColWidth() {
123 + var winWidth = fs.windowSize().width,
124 + colWidth, thElems, tdElem;
125 +
126 + colWidth = Math.floor(winWidth / numTestElems);
127 +
128 + thElems = thead.find('th');
129 +
130 + angular.forEach(thElems, function (thElem, i) {
131 + thElem = angular.element(thElems[i]);
132 + tdElem = angular.element(tbody.find('td').eq(i));
133 +
134 + if (tdElem.attr('class') === 'table-icon') {
135 + expect(thElem.css('width')).toBe(tableIconTdSize + 'px');
136 + expect(tdElem.css('width')).toBe(tableIconTdSize + 'px');
137 + } else {
138 + expect(thElem.css('width')).toBe(colWidth + 'px');
139 + expect(tdElem.css('width')).toBe(colWidth + 'px');
140 + }
141 + });
142 + }
143 +
144 + function verifyCallbacks(thElems) {
145 + expect(scope.sortCallback).not.toHaveBeenCalled();
97 146
98 - //expect(table.select('thead').style('display')).toBe('block'); 147 + // first test header has no 'sortable' attr
148 + thElems[0].click();
149 + expect(scope.sortCallback).not.toHaveBeenCalled();
150 +
151 + // the other headers have 'sortable'
152 + for(var i = 1; i < numTestElems; i += 1) {
153 + thElems[i].click();
154 + expect(scope.sortCallback).toHaveBeenCalled();
155 + }
156 + }
157 +
158 + function verifyIcons(thElems) {
159 + var currentTh, div;
160 + // make sure it has the correct icon after clicking
161 + thElems[1].click();
162 + currentTh = angular.element(thElems[1]);
163 + div = currentTh.find('div');
164 + expect(div.html()).toBe('<svg class="embeddedIcon" ' +
165 + 'width="10" height="10" viewBox="0 0 50 50">' +
166 + '<g class="icon tableColSortAsc">' +
167 + '<rect width="50" height="50" rx="5"></rect>' +
168 + '<use width="50" height="50" class="glyph" ' +
169 + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
170 + 'xlink:href="#triangleUp">' +
171 + '</use>' +
172 + '</g></svg>');
173 + thElems[1].click();
174 + div = currentTh.find('div');
175 + expect(div.html()).toBe('<svg class="embeddedIcon" ' +
176 + 'width="10" height="10" viewBox="0 0 50 50">' +
177 + '<g class="icon tableColSortDesc">' +
178 + '<rect width="50" height="50" rx="5"></rect>' +
179 + '<use width="50" height="50" class="glyph" ' +
180 + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
181 + 'xlink:href="#triangleDown">' +
182 + '</use>' +
183 + '</g></svg>');
184 +
185 + thElems[2].click();
186 + div = currentTh.children();
187 + // clicked on a new element, so the previous icon should have been deleted
188 + expect(div.html()).toBeFalsy();
189 +
190 + // the new element should have the ascending icon
191 + currentTh = angular.element(thElems[2]);
192 + div = currentTh.children();
193 + expect(div.html()).toBe('<svg class="embeddedIcon" ' +
194 + 'width="10" height="10" viewBox="0 0 50 50">' +
195 + '<g class="icon tableColSortAsc">' +
196 + '<rect width="50" height="50" rx="5"></rect>' +
197 + '<use width="50" height="50" class="glyph" ' +
198 + 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
199 + 'xlink:href="#triangleUp">' +
200 + '</use>' +
201 + '</g></svg>');
202 + }
203 +
204 + it('should affirm that onos-fixed-header is working', function () {
205 + table = angular.element(onosFixedHeaderTags);
206 +
207 + compileTable();
208 + verifyGivenTags('onos-fixed-header');
209 +
210 + // table will not be fixed unless it receives the 'LastElement' event
211 + scope.$emit('LastElement');
212 + scope.$digest();
213 +
214 + verifyCssDisplay();
215 + verifyColWidth();
99 }); 216 });
100 217
101 it('should affirm that onos-sortable-header is working', function () { 218 it('should affirm that onos-sortable-header is working', function () {
102 - table = $compile(onosSortableHeaderTags)($rootScope); 219 + var thElems;
103 - $rootScope.$digest(); 220 + table = angular.element(onosSortableHeaderTags);
104 221
105 - table = d3.select(table); 222 + compileTable();
106 - expect(table).toBeDefined(); 223 + verifyGivenTags('onos-sortable-header');
224 + // ctrlCallback functionality is tested in device-spec
225 + // only checking that it has been called correctly in the directive
226 + scope.sortCallback = jasmine.createSpy('sortCallback');
227 +
228 + thElems = thead.find('th');
229 + verifyCallbacks(thElems);
230 + verifyIcons(thElems);
107 }); 231 });
108 232
109 - // TODO: write directive unit tests for table.js
110 }); 233 });
......