octavia-dashboard/octavia_dashboard/static/dashboard/project/lbaasv2/widgets/filterselect/filter-select.component.spe...

294 lines
9.1 KiB
JavaScript

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
describe('Filter-Select', function() {
var mockOptions, mockColumns;
beforeEach(function() {
mockOptions = [{
text: 'Option 1'
}, {
text: 'Option 2'
}];
mockColumns = [{
label: 'Key column',
value: 'text'
}, {
label: 'Function Column',
value: function(option) {
return option.text + ' extended';
}
}];
});
describe('component', function() {
var component, ctrl, child, scope, otherElement,
filterSelect, element;
beforeEach(module('templates'));
beforeEach(module('horizon.dashboard.project.lbaasv2',
function($provide) {
$provide.decorator('filterSelectDirective', function($delegate) {
component = $delegate[0];
spyOn(component, 'templateUrl').and.callThrough();
return $delegate;
});
}
));
beforeEach(inject(function($compile, $rootScope) {
scope = $rootScope.$new();
scope.ngModel = null;
scope.onSelect = function() {};
scope.shorthand = function(option) {
return 'Shorthand: ' + option.text;
};
scope.disabled = true;
scope.columns = mockColumns;
scope.options = mockOptions;
var html = '<filter-select ' +
'onSelect="onSelect" ' +
'ng-model="ngModel" ' +
'shorthand="shorthand" ' +
'disabled="disabled" ' +
'columns="columns" ' +
'options="options" ' +
'></filter-select>';
var parentElement = angular.element('<div></div>');
otherElement = angular.element('<div id="otherElement"></div>');
filterSelect = angular.element(html);
parentElement.append(otherElement);
parentElement.append(filterSelect);
element = $compile(parentElement)(scope);
scope.$apply();
child = element.find('input');
ctrl = filterSelect.controller('filter-select');
spyOn(ctrl, 'onSelect').and.callThrough();
spyOn(ctrl, '_buildRows').and.callThrough();
spyOn(ctrl, 'shorthand').and.callThrough();
spyOn(ctrl, '_setOpenExternal').and.callThrough();
}));
it('should load the correct template', function() {
expect(component.templateUrl).toHaveBeenCalled();
expect(component.templateUrl()).toBe(
'/static/dashboard/project/lbaasv2/' +
'widgets/filterselect/filter-select.html'
);
});
it('should react to value change', function() {
// Change one way binding for 'value'
scope.ngModel = mockOptions[0];
scope.$apply();
expect(ctrl.textFilter).toBe('');
expect(ctrl.text).toBe('Shorthand: Option 1');
expect(ctrl._buildRows).toHaveBeenCalled();
expect(ctrl.shorthand).toHaveBeenCalledWith(mockOptions[0]);
});
it('should react to non-option value', function() {
// Set one way binding to an impossible value
var nonOption = {};
scope.ngModel = nonOption;
scope.$apply();
expect(ctrl._buildRows).toHaveBeenCalled();
expect(ctrl.shorthand).not.toHaveBeenCalled();
});
it('should react to non-value change', function() {
// Set non-value binding and trigger onChange, make sure value related
// changes aren't triggered
scope.disabled = false;
scope.$apply();
expect(ctrl._buildRows).toHaveBeenCalled();
expect(ctrl.shorthand).not.toHaveBeenCalled();
});
it('should react to outside clicks', function() {
var mockChildEvent = {
target: child
};
ctrl.externalClick(mockChildEvent);
expect(ctrl._setOpenExternal).not.toHaveBeenCalled();
var mockOutsideEvent = {
target: otherElement
};
ctrl.externalClick(mockOutsideEvent);
expect(ctrl._setOpenExternal).toHaveBeenCalledWith(false);
});
it('should build rows', function() {
var expectedRows = [
[['Option 1', '', ''], ['Option 1 extended', '', '']],
[['Option 2', '', ''], ['Option 2 extended', '', '']]
];
expect(ctrl.rows).toEqual(expectedRows);
// filtered by text
ctrl.textFilter = '1';
ctrl._buildRows();
var expectedFiltered = [
[['Option ', '1', ''], ['Option ', '1', ' extended']]
];
expect(ctrl.rows).toEqual(expectedFiltered);
});
it('should build cells', function() {
// Test that normal string values are used as keys against options
var option1text = ctrl._buildCell(ctrl.columns[0], ctrl.options[0]);
expect(option1text).toBe('Option 1');
// Test that column value callbacks are called
spyOn(ctrl.columns[1], 'value');
ctrl._buildCell(ctrl.columns[1], ctrl.options[0]);
expect(ctrl.columns[1].value).toHaveBeenCalledWith(ctrl.options[0]);
});
it('should handle text changes', function() {
// Test input text changes
var mockInput = 'mock input text';
ctrl.text = mockInput;
ctrl.onTextChange();
expect(ctrl.textFilter).toEqual(mockInput);
expect(ctrl._buildRows).toHaveBeenCalled();
});
it('should select options', function() {
ctrl.selectOption(1);
expect(ctrl.onSelect).toHaveBeenCalledWith({
option: mockOptions[1]
});
expect(ctrl.isOpen).toBe(false);
});
});
describe('controller', function() {
var scope, ctrl;
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(
inject(
function($rootScope, $componentController) {
scope = $rootScope.$new();
ctrl = $componentController('filterSelect', {
$scope: scope,
$element: angular.element('<span></span>')
});
ctrl.$onInit();
spyOn(scope, '$apply');
}
)
);
it('should initialize and remove listeners', function() {
var events = $._data(document, 'events');
expect(events.click).toBeDefined();
expect(events.click.length).toBe(1);
expect(events.click[0].handler).toBe(ctrl.externalClick);
ctrl.$onDestroy();
expect(events.click).not.toBeDefined();
});
it('should initialize state', function() {
// Initial component state; simply bound values needn't be checked,
// angular binding is trusted
expect(ctrl.textFilter).toBe('');
expect(ctrl.text).toBe('');
expect(ctrl.isOpen).toBe(false);
});
it('should open popup', function() {
var mockEvent = {
stopPropagation: function() {}
};
spyOn(mockEvent, 'stopPropagation');
ctrl.openPopup(mockEvent);
expect(mockEvent.stopPropagation).toHaveBeenCalled();
expect(ctrl.isOpen).toBe(true);
});
it('should toggle popup', function() {
// not much to tests here; utilizes bootstrap dropdown
ctrl.togglePopup();
expect(ctrl.isOpen).toBe(true);
ctrl.togglePopup();
expect(ctrl.isOpen).toBe(false);
});
it('should set open state from outside the digest', function() {
ctrl._setOpenExternal(true);
expect(ctrl.isOpen).toBe(true);
expect(scope.$apply).toHaveBeenCalled();
ctrl._setOpenExternal(false);
expect(ctrl.isOpen).toBe(false);
expect(scope.$apply).toHaveBeenCalled();
});
it('should check unset values', function() {
expect(ctrl._isUnset(null)).toBe(true);
expect(ctrl._isUnset(undefined)).toBe(true);
expect(ctrl._isUnset('defined_value')).toBe(false);
});
it('should set default values correctly', function() {
var defaultValue = 'default value';
var realValue = 'input value';
var firstResult = ctrl._setValue(null, defaultValue);
expect(firstResult).toBe(defaultValue);
var secondResult = ctrl._setValue(realValue, defaultValue);
expect(secondResult).toBe(realValue);
});
it('should split by filter', function() {
ctrl.textFilter = 'matched';
var notSplit = ctrl._splitByFilter('does not match');
expect(notSplit).toEqual({
values:['does not match', '', ''],
wasSplit: false
});
var split = ctrl._splitByFilter('this matched portion');
expect(split).toEqual({
values: ['this ', 'matched', ' portion'],
wasSplit: true
});
});
});
});
})();