GUI -- Removed onos-fixed-header redundancies, wrote unit tests for fixed-header and sortable-header directives.
Change-Id: Iccf9348a4697f494a4234b024781fede0719491d
diff --git a/web/gui/src/main/webapp/app/fw/widget/table.js b/web/gui/src/main/webapp/app/fw/widget/table.js
index 1b999ae..dbfcfed 100644
--- a/web/gui/src/main/webapp/app/fw/widget/table.js
+++ b/web/gui/src/main/webapp/app/fw/widget/table.js
@@ -34,7 +34,7 @@
tHeaders = t.selectAll('th');
numCols = tHeaders[0].length;
- colWidth = Math.floor(winWidth/numCols);
+ colWidth = Math.floor(winWidth / numCols);
tHeaders.each(function(thElement, index) {
thElement = d3.select(this);
@@ -121,7 +121,9 @@
fs = _fs_;
var w = angular.element($window),
table = d3.select(element[0]),
- shouldResize = false;
+ thead = table.select('thead'),
+ tbody = table.select('tbody'),
+ canAdjust = false;
scope.$watch(function () {
return {
@@ -129,31 +131,24 @@
w: window.innerWidth
};
}, function (newVal) {
- var thead = table.select('thead'),
- tbody = table.select('tbody');
-
scope.windowHeight = newVal.h;
scope.windowWidth = newVal.w;
- scope.setTableHW = function () {
- scope.$on('LastElement', function (event) {
- // only adjust the table once it's completely loaded
- fixTable(table, thead, tbody);
- shouldResize = true;
- });
- };
+ scope.$on('LastElement', function () {
+ // only adjust the table once it's completely loaded
+ fixTable(table, thead, tbody);
+ canAdjust = true;
+ });
- if (shouldResize) {
+ if (canAdjust) {
fixTable(table, thead, tbody);
}
-
}, true);
w.bind('onos-fixed-header', function () {
scope.$apply();
});
};
-
}])
.directive('onosSortableHeader', ['$log', 'IconService',
diff --git a/web/gui/src/main/webapp/app/view/device/device.html b/web/gui/src/main/webapp/app/view/device/device.html
index 5f7f5cc..cff0845 100644
--- a/web/gui/src/main/webapp/app/view/device/device.html
+++ b/web/gui/src/main/webapp/app/view/device/device.html
@@ -3,7 +3,6 @@
<h2>Devices ({{ctrl.deviceData.length}} total)</h2>
<table class="summary-list"
onos-fixed-header
- ng-style="setTableHW()"
onos-sortable-header
sort-callback="sortCallback(urlSuffix)">
<thead>
diff --git a/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js b/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
index 0a3fcb6..c0a317e 100644
--- a/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/widget/table-spec.js
@@ -20,11 +20,14 @@
describe('factory: fw/widget/table.js', function () {
var $log, $compile, $rootScope,
fs, is,
- table;
+ scope, compiled,
+ table, thead, tbody,
+ tableIconTdSize = 33,
+ bottomMargin = 200,
+ numTestElems = 4;
var onosFixedHeaderTags = '<table ' +
- 'onos-fixed-header ' +
- 'ng-style="setTableHW()">' +
+ 'onos-fixed-header>' +
'<thead>' +
'<tr>' +
'<th></th>' +
@@ -35,7 +38,7 @@
'</thead>' +
'<tbody>' +
'<tr>' +
- '<td>' +
+ '<td class="table-icon">' +
'<div icon icon-id="{{dev._iconid_available}}">' +
'</div>' +
'</td>' +
@@ -46,7 +49,7 @@
'</tbody>' +
'</table>',
- onosSortableHeaderTags = '<table class="summary-list" ' +
+ onosSortableHeaderTags = '<table ' +
'onos-sortable-header ' +
'sort-callback="sortCallback(urlSuffix)">' +
'<thead>' +
@@ -82,29 +85,149 @@
}));
beforeEach(function () {
+ scope = $rootScope.$new();
});
afterEach(function () {
table = null;
+ thead = null;
+ tbody = null;
});
- it('should affirm that onos-fixed-header is working', function () {
- table = $compile(onosFixedHeaderTags)($rootScope);
- $rootScope.$digest();
+ function compileTable() {
+ compiled = $compile(table);
+ compiled(scope);
+ scope.$digest();
+ }
- table = d3.select(table);
+ function verifyGivenTags(dirName) {
expect(table).toBeDefined();
+ expect(table.attr(dirName)).toBe('');
- //expect(table.select('thead').style('display')).toBe('block');
+ thead = table.find('thead');
+ expect(thead).toBeDefined();
+ tbody = table.find('tbody');
+ expect(tbody).toBeDefined();
+ }
+
+ function verifyCssDisplay() {
+ var winHeight = fs.windowSize().height;
+
+ expect(thead.css('display')).toBe('block');
+ expect(tbody.css('display')).toBe('block');
+ expect(tbody.css('height')).toBe((winHeight - bottomMargin) + 'px');
+ expect(tbody.css('overflow')).toBe('auto');
+ }
+
+ function verifyColWidth() {
+ var winWidth = fs.windowSize().width,
+ colWidth, thElems, tdElem;
+
+ colWidth = Math.floor(winWidth / numTestElems);
+
+ thElems = thead.find('th');
+
+ angular.forEach(thElems, function (thElem, i) {
+ thElem = angular.element(thElems[i]);
+ tdElem = angular.element(tbody.find('td').eq(i));
+
+ if (tdElem.attr('class') === 'table-icon') {
+ expect(thElem.css('width')).toBe(tableIconTdSize + 'px');
+ expect(tdElem.css('width')).toBe(tableIconTdSize + 'px');
+ } else {
+ expect(thElem.css('width')).toBe(colWidth + 'px');
+ expect(tdElem.css('width')).toBe(colWidth + 'px');
+ }
+ });
+ }
+
+ function verifyCallbacks(thElems) {
+ expect(scope.sortCallback).not.toHaveBeenCalled();
+
+ // first test header has no 'sortable' attr
+ thElems[0].click();
+ expect(scope.sortCallback).not.toHaveBeenCalled();
+
+ // the other headers have 'sortable'
+ for(var i = 1; i < numTestElems; i += 1) {
+ thElems[i].click();
+ expect(scope.sortCallback).toHaveBeenCalled();
+ }
+ }
+
+ function verifyIcons(thElems) {
+ var currentTh, div;
+ // make sure it has the correct icon after clicking
+ thElems[1].click();
+ currentTh = angular.element(thElems[1]);
+ div = currentTh.find('div');
+ expect(div.html()).toBe('<svg class="embeddedIcon" ' +
+ 'width="10" height="10" viewBox="0 0 50 50">' +
+ '<g class="icon tableColSortAsc">' +
+ '<rect width="50" height="50" rx="5"></rect>' +
+ '<use width="50" height="50" class="glyph" ' +
+ 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
+ 'xlink:href="#triangleUp">' +
+ '</use>' +
+ '</g></svg>');
+ thElems[1].click();
+ div = currentTh.find('div');
+ expect(div.html()).toBe('<svg class="embeddedIcon" ' +
+ 'width="10" height="10" viewBox="0 0 50 50">' +
+ '<g class="icon tableColSortDesc">' +
+ '<rect width="50" height="50" rx="5"></rect>' +
+ '<use width="50" height="50" class="glyph" ' +
+ 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
+ 'xlink:href="#triangleDown">' +
+ '</use>' +
+ '</g></svg>');
+
+ thElems[2].click();
+ div = currentTh.children();
+ // clicked on a new element, so the previous icon should have been deleted
+ expect(div.html()).toBeFalsy();
+
+ // the new element should have the ascending icon
+ currentTh = angular.element(thElems[2]);
+ div = currentTh.children();
+ expect(div.html()).toBe('<svg class="embeddedIcon" ' +
+ 'width="10" height="10" viewBox="0 0 50 50">' +
+ '<g class="icon tableColSortAsc">' +
+ '<rect width="50" height="50" rx="5"></rect>' +
+ '<use width="50" height="50" class="glyph" ' +
+ 'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
+ 'xlink:href="#triangleUp">' +
+ '</use>' +
+ '</g></svg>');
+ }
+
+ it('should affirm that onos-fixed-header is working', function () {
+ table = angular.element(onosFixedHeaderTags);
+
+ compileTable();
+ verifyGivenTags('onos-fixed-header');
+
+ // table will not be fixed unless it receives the 'LastElement' event
+ scope.$emit('LastElement');
+ scope.$digest();
+
+ verifyCssDisplay();
+ verifyColWidth();
});
it('should affirm that onos-sortable-header is working', function () {
- table = $compile(onosSortableHeaderTags)($rootScope);
- $rootScope.$digest();
+ var thElems;
+ table = angular.element(onosSortableHeaderTags);
- table = d3.select(table);
- expect(table).toBeDefined();
+ compileTable();
+ verifyGivenTags('onos-sortable-header');
+ // ctrlCallback functionality is tested in device-spec
+ // only checking that it has been called correctly in the directive
+ scope.sortCallback = jasmine.createSpy('sortCallback');
+
+ thElems = thead.find('th');
+ verifyCallbacks(thElems);
+ verifyIcons(thElems);
});
- // TODO: write directive unit tests for table.js
});