1704 lines
65 KiB
JavaScript
1704 lines
65 KiB
JavaScript
'use strict';
|
|
|
|
|
|
|
|
describe('ui-select tests', function() {
|
|
|
|
var scope, $rootScope, $compile, $timeout, $injector;
|
|
|
|
|
|
|
|
var Key = {
|
|
|
|
Enter: 13,
|
|
|
|
Tab: 9,
|
|
|
|
Up: 38,
|
|
|
|
Down: 40,
|
|
|
|
Left: 37,
|
|
|
|
Right: 39,
|
|
|
|
Backspace: 8,
|
|
|
|
Delete: 46,
|
|
|
|
Escape: 27
|
|
|
|
};
|
|
|
|
|
|
|
|
beforeEach(module('ngSanitize', 'ui.select'));
|
|
|
|
beforeEach(inject(function(_$rootScope_, _$compile_, _$timeout_, _$injector_) {
|
|
|
|
$rootScope = _$rootScope_;
|
|
|
|
scope = $rootScope.$new();
|
|
|
|
$compile = _$compile_;
|
|
|
|
$timeout = _$timeout_;
|
|
|
|
$injector = _$injector_;
|
|
|
|
scope.selection = {};
|
|
|
|
|
|
|
|
scope.getGroupLabel = function(person) {
|
|
|
|
return person.age % 2 ? 'even' : 'odd';
|
|
|
|
};
|
|
|
|
|
|
|
|
scope.people = [
|
|
|
|
{ name: 'Adam', email: 'adam@email.com', group: 'Foo', age: 12 },
|
|
|
|
{ name: 'Amalie', email: 'amalie@email.com', group: 'Foo', age: 12 },
|
|
|
|
{ name: 'Estefanía', email: 'estefanía@email.com', group: 'Foo', age: 21 },
|
|
|
|
{ name: 'Adrian', email: 'adrian@email.com', group: 'Foo', age: 21 },
|
|
|
|
{ name: 'Wladimir', email: 'wladimir@email.com', group: 'Foo', age: 30 },
|
|
|
|
{ name: 'Samantha', email: 'samantha@email.com', group: 'bar', age: 30 },
|
|
|
|
{ name: 'Nicole', email: 'nicole@email.com', group: 'bar', age: 43 },
|
|
|
|
{ name: 'Natasha', email: 'natasha@email.com', group: 'Baz', age: 54 }
|
|
|
|
];
|
|
|
|
|
|
|
|
scope.someObject = {};
|
|
|
|
scope.someObject.people = [
|
|
|
|
{ name: 'Adam', email: 'adam@email.com', group: 'Foo', age: 12 },
|
|
|
|
{ name: 'Amalie', email: 'amalie@email.com', group: 'Foo', age: 12 },
|
|
|
|
{ name: 'Estefanía', email: 'estefanía@email.com', group: 'Foo', age: 21 },
|
|
|
|
{ name: 'Adrian', email: 'adrian@email.com', group: 'Foo', age: 21 },
|
|
|
|
{ name: 'Wladimir', email: 'wladimir@email.com', group: 'Foo', age: 30 },
|
|
|
|
{ name: 'Samantha', email: 'samantha@email.com', group: 'bar', age: 30 },
|
|
|
|
{ name: 'Nicole', email: 'nicole@email.com', group: 'bar', age: 43 },
|
|
|
|
{ name: 'Natasha', email: 'natasha@email.com', group: 'Baz', age: 54 }
|
|
|
|
];
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
// DSL (domain-specific language)
|
|
|
|
|
|
|
|
function compileTemplate(template) {
|
|
|
|
var el = $compile(angular.element(template))(scope);
|
|
|
|
scope.$digest();
|
|
|
|
return el;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createUiSelect(attrs) {
|
|
|
|
var attrsHtml = '';
|
|
|
|
if (attrs !== undefined) {
|
|
|
|
if (attrs.disabled !== undefined) { attrsHtml += ' ng-disabled="' + attrs.disabled + '"'; }
|
|
|
|
if (attrs.required !== undefined) { attrsHtml += ' ng-required="' + attrs.required + '"'; }
|
|
|
|
if (attrs.theme !== undefined) { attrsHtml += ' theme="' + attrs.theme + '"'; }
|
|
|
|
if (attrs.tabindex !== undefined) { attrsHtml += ' tabindex="' + attrs.tabindex + '"'; }
|
|
|
|
if (attrs.tagging !== undefined) { attrsHtml += ' tagging="' + attrs.tagging + '"'; }
|
|
|
|
if (attrs.title !== undefined) { attrsHtml += ' title="' + attrs.title + '"'; }
|
|
|
|
}
|
|
|
|
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"' + attrsHtml + '> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMatchLabel(el) {
|
|
|
|
return $(el).find('.ui-select-match > button:first > span[ng-transclude]:not(.ng-hide)').text();
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickItem(el, text) {
|
|
|
|
|
|
|
|
if (!isDropdownOpened(el)){
|
|
|
|
openDropdown(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
$(el).find('.ui-select-choices-row div:contains("' + text + '")').click();
|
|
|
|
scope.$digest();
|
|
|
|
}
|
|
|
|
|
|
|
|
function clickMatch(el) {
|
|
|
|
$(el).find('.ui-select-match > button:first').click();
|
|
|
|
scope.$digest();
|
|
|
|
}
|
|
|
|
|
|
|
|
function isDropdownOpened(el) {
|
|
|
|
// Does not work with jQuery 2.*, have to use jQuery 1.11.*
|
|
|
|
// This will be fixed in AngularJS 1.3
|
|
|
|
// See issue with unit-testing directive using karma https://github.com/angular/angular.js/issues/4640#issuecomment-35002427
|
|
|
|
return el.scope().$select.open && el.hasClass('open');
|
|
|
|
}
|
|
|
|
|
|
|
|
function triggerKeydown(element, keyCode) {
|
|
|
|
var e = jQuery.Event("keydown");
|
|
|
|
e.which = keyCode;
|
|
|
|
e.keyCode = keyCode;
|
|
|
|
element.trigger(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setSearchText(el, text) {
|
|
|
|
el.scope().$select.search = text;
|
|
|
|
scope.$digest();
|
|
|
|
$timeout.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
function openDropdown(el) {
|
|
|
|
var $select = el.scope().$select;
|
|
|
|
$select.open = true;
|
|
|
|
scope.$digest();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Tests
|
|
|
|
|
|
|
|
it('should compile child directives', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
var searchEl = $(el).find('.ui-select-search');
|
|
|
|
expect(searchEl.length).toEqual(1);
|
|
|
|
|
|
|
|
var matchEl = $(el).find('.ui-select-match');
|
|
|
|
expect(matchEl.length).toEqual(1);
|
|
|
|
|
|
|
|
var choicesContentEl = $(el).find('.ui-select-choices-content');
|
|
|
|
expect(choicesContentEl.length).toEqual(1);
|
|
|
|
|
|
|
|
var choicesContainerEl = $(el).find('.ui-select-choices');
|
|
|
|
expect(choicesContainerEl.length).toEqual(1);
|
|
|
|
|
|
|
|
openDropdown(el);
|
|
|
|
var choicesEls = $(el).find('.ui-select-choices-row');
|
|
|
|
expect(choicesEls.length).toEqual(8);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should correctly render initial state', function() {
|
|
|
|
scope.selection.selected = scope.people[0];
|
|
|
|
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
expect(getMatchLabel(el)).toEqual('Adam');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should correctly render initial state with track by feature', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search track by person.name"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
scope.selection.selected = { name: 'Samantha', email: 'something different than array source', group: 'bar', age: 30 };
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should display the choices when activated', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
|
|
|
|
clickMatch(el);
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should select an item', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should select an item (controller)', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
el.scope().$select.select(scope.people[1]);
|
|
|
|
scope.$digest();
|
|
|
|
|
|
|
|
expect(getMatchLabel(el)).toEqual('Amalie');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not select a non existing item', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
clickItem(el, "I don't exist");
|
|
|
|
|
|
|
|
expect(getMatchLabel(el)).toEqual('');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should close the choices when an item is selected', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
clickMatch(el);
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('should open/close dropdown when clicking caret icon', function() {
|
|
|
|
|
|
|
|
var el = createUiSelect({theme : 'select2'});
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
var $select = el.scope().$select;
|
|
|
|
|
|
|
|
expect($select.open).toEqual(false);
|
|
|
|
|
|
|
|
el.find(".ui-select-toggle").click();
|
|
|
|
expect($select.open).toEqual(true);
|
|
|
|
|
|
|
|
|
|
|
|
el.find(".ui-select-toggle").click();
|
|
|
|
expect($select.open).toEqual(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should pass tabindex to focusser', function() {
|
|
|
|
var el = createUiSelect({tabindex: 5});
|
|
|
|
|
|
|
|
expect($(el).find('.ui-select-focusser').attr('tabindex')).toEqual('5');
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should pass tabindex to focusser when tabindex is an expression', function() {
|
|
|
|
scope.tabValue = 22;
|
|
|
|
var el = createUiSelect({tabindex: '{{tabValue + 10}}'});
|
|
|
|
|
|
|
|
expect($(el).find('.ui-select-focusser').attr('tabindex')).toEqual('32');
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not give focusser a tabindex when ui-select does not have one', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
|
|
|
|
expect($(el).find('.ui-select-focusser').attr('tabindex')).toEqual(undefined);
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be disabled if the attribute says so', function() {
|
|
|
|
var el1 = createUiSelect({disabled: true});
|
|
|
|
expect(el1.scope().$select.disabled).toEqual(true);
|
|
|
|
clickMatch(el1);
|
|
|
|
expect(isDropdownOpened(el1)).toEqual(false);
|
|
|
|
|
|
|
|
var el2 = createUiSelect({disabled: false});
|
|
|
|
expect(el2.scope().$select.disabled).toEqual(false);
|
|
|
|
clickMatch(el2);
|
|
|
|
expect(isDropdownOpened(el2)).toEqual(true);
|
|
|
|
|
|
|
|
var el3 = createUiSelect();
|
|
|
|
expect(el3.scope().$select.disabled).toBeFalsy();
|
|
|
|
clickMatch(el3);
|
|
|
|
expect(isDropdownOpened(el3)).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow tagging if the attribute says so', function() {
|
|
|
|
var el = createUiSelect({tagging: true});
|
|
|
|
clickMatch(el);
|
|
|
|
|
|
|
|
$(el).scope().$select.select("I don't exist");
|
|
|
|
|
|
|
|
expect($(el).scope().$select.selected).toEqual("I don't exist");
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format new items using the tagging function when the attribute is a function', function() {
|
|
|
|
scope.taggingFunc = function (name) {
|
|
|
|
return {
|
|
|
|
name: name,
|
|
|
|
email: name + '@email.com',
|
|
|
|
group: 'Foo',
|
|
|
|
age: 12
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
var el = createUiSelect({tagging: 'taggingFunc'});
|
|
|
|
clickMatch(el);
|
|
|
|
|
|
|
|
$(el).scope().$select.search = 'idontexist';
|
|
|
|
$(el).scope().$select.activeIndex = 0;
|
|
|
|
$(el).scope().$select.select('idontexist');
|
|
|
|
|
|
|
|
expect($(el).scope().$select.selected).toEqual({
|
|
|
|
name: 'idontexist',
|
|
|
|
email: 'idontexist@email.com',
|
|
|
|
group: 'Foo',
|
|
|
|
age: 12
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// See when an item that evaluates to false (such as "false" or "no") is selected, the placeholder is shown https://github.com/angular-ui/ui-select/pull/32
|
|
|
|
it('should not display the placeholder when item evaluates to false', function() {
|
|
|
|
scope.items = ['false'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match>{{$select.selected}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="item in items | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="item | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
expect(el.scope().$select.selected).toEqual(undefined);
|
|
|
|
|
|
|
|
clickItem(el, 'false');
|
|
|
|
|
|
|
|
expect(el.scope().$select.selected).toEqual('false');
|
|
|
|
expect(getMatchLabel(el)).toEqual('false');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should close an opened select when another one is opened', function() {
|
|
|
|
var el1 = createUiSelect();
|
|
|
|
var el2 = createUiSelect();
|
|
|
|
el1.appendTo(document.body);
|
|
|
|
el2.appendTo(document.body);
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el1)).toEqual(false);
|
|
|
|
expect(isDropdownOpened(el2)).toEqual(false);
|
|
|
|
clickMatch(el1);
|
|
|
|
expect(isDropdownOpened(el1)).toEqual(true);
|
|
|
|
expect(isDropdownOpened(el2)).toEqual(false);
|
|
|
|
clickMatch(el2);
|
|
|
|
expect(isDropdownOpened(el1)).toEqual(false);
|
|
|
|
expect(isDropdownOpened(el2)).toEqual(true);
|
|
|
|
|
|
|
|
el1.remove();
|
|
|
|
el2.remove();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('disabled options', function() {
|
|
|
|
function createUiSelect(attrs) {
|
|
|
|
var attrsDisabled = '';
|
|
|
|
if (attrs !== undefined) {
|
|
|
|
if (attrs.disabled !== undefined) {
|
|
|
|
attrsDisabled = ' ui-disable-choice="' + attrs.disabled + '"';
|
|
|
|
} else {
|
|
|
|
attrsDisabled = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"' + attrsDisabled + '> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function disablePerson(opts) {
|
|
|
|
opts = opts || {};
|
|
|
|
|
|
|
|
var key = opts.key || 'people',
|
|
|
|
disableAttr = opts.disableAttr || 'disabled',
|
|
|
|
disableBool = opts.disableBool === undefined ? true : opts.disableBool,
|
|
|
|
matchAttr = opts.match || 'name',
|
|
|
|
matchVal = opts.matchVal || 'Wladimir';
|
|
|
|
|
|
|
|
scope['_' + key] = angular.copy(scope[key]);
|
|
|
|
scope[key].map(function (model) {
|
|
|
|
if (model[matchAttr] == matchVal) {
|
|
|
|
model[disableAttr] = disableBool;
|
|
|
|
}
|
|
|
|
return model;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function resetScope(opts) {
|
|
|
|
opts = opts || {};
|
|
|
|
var key = opts.key || 'people';
|
|
|
|
scope[key] = angular.copy(scope['_' + key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('without disabling expression', function () {
|
|
|
|
beforeEach(function() {
|
|
|
|
disablePerson();
|
|
|
|
this.el = createUiSelect();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow disabled options to be selected', function() {
|
|
|
|
clickItem(this.el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(getMatchLabel(this.el)).toEqual('Wladimir');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set a disabled class on the option', function() {
|
|
|
|
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
|
|
|
|
var container = option.closest('.ui-select-choices-row');
|
|
|
|
|
|
|
|
expect(container.hasClass('disabled')).toBeFalsy();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('disable on truthy property', function () {
|
|
|
|
beforeEach(function() {
|
|
|
|
disablePerson({
|
|
|
|
disableAttr : 'inactive',
|
|
|
|
disableBool : true
|
|
|
|
});
|
|
|
|
this.el = createUiSelect({
|
|
|
|
disabled: 'person.inactive'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow the user to define the selected option', function () {
|
|
|
|
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('person.inactive');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow disabled options to be selected', function() {
|
|
|
|
clickItem(this.el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set a disabled class on the option', function() {
|
|
|
|
|
|
|
|
openDropdown(this.el);
|
|
|
|
|
|
|
|
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
|
|
|
|
var container = option.closest('.ui-select-choices-row');
|
|
|
|
|
|
|
|
expect(container.hasClass('disabled')).toBeTruthy();
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('disable on inverse property check', function () {
|
|
|
|
beforeEach(function() {
|
|
|
|
disablePerson({
|
|
|
|
disableAttr : 'active',
|
|
|
|
disableBool : false
|
|
|
|
});
|
|
|
|
this.el = createUiSelect({
|
|
|
|
disabled: '!person.active'
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow the user to define the selected option', function () {
|
|
|
|
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe('!person.active');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow disabled options to be selected', function() {
|
|
|
|
clickItem(this.el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set a disabled class on the option', function() {
|
|
|
|
openDropdown(this.el);
|
|
|
|
|
|
|
|
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
|
|
|
|
var container = option.closest('.ui-select-choices-row');
|
|
|
|
|
|
|
|
expect(container.hasClass('disabled')).toBeTruthy();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('disable on expression', function () {
|
|
|
|
beforeEach(function() {
|
|
|
|
disablePerson({
|
|
|
|
disableAttr : 'status',
|
|
|
|
disableBool : 'inactive'
|
|
|
|
});
|
|
|
|
this.el = createUiSelect({
|
|
|
|
disabled: "person.status == 'inactive'"
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should allow the user to define the selected option', function () {
|
|
|
|
expect($(this.el).find('.ui-select-choices').attr('ui-disable-choice')).toBe("person.status == 'inactive'");
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not allow disabled options to be selected', function() {
|
|
|
|
clickItem(this.el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(getMatchLabel(this.el)).not.toEqual('Wladimir');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set a disabled class on the option', function() {
|
|
|
|
openDropdown(this.el);
|
|
|
|
|
|
|
|
var option = $(this.el).find('.ui-select-choices-row div:contains("Wladimir")');
|
|
|
|
var container = option.closest('.ui-select-choices-row');
|
|
|
|
|
|
|
|
expect(container.hasClass('disabled')).toBeTruthy();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(function() {
|
|
|
|
resetScope();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('choices group', function() {
|
|
|
|
function getGroupLabel(item) {
|
|
|
|
return item.parent('.ui-select-choices-group').find('.ui-select-choices-group-label');
|
|
|
|
}
|
|
|
|
function createUiSelect() {
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices group-by="\'group\'" repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should create items group', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
expect(el.find('.ui-select-choices-group').length).toBe(3);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should show label before each group', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
expect(el.find('.ui-select-choices-group .ui-select-choices-group-label').map(function() {
|
|
|
|
return this.textContent;
|
|
|
|
}).toArray()).toEqual(['Foo', 'bar', 'Baz']);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should hide empty groups', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
el.scope().$select.search = 'd';
|
|
|
|
scope.$digest();
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-choices-group .ui-select-choices-group-label').map(function() {
|
|
|
|
return this.textContent;
|
|
|
|
}).toArray()).toEqual(['Foo']);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should change activeItem through groups', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
el.scope().$select.search = 't';
|
|
|
|
scope.$digest();
|
|
|
|
openDropdown(el);
|
|
|
|
var choices = el.find('.ui-select-choices-row');
|
|
|
|
|
|
|
|
expect(choices.eq(0)).toHaveClass('active');
|
|
|
|
expect(getGroupLabel(choices.eq(0)).text()).toBe('Foo');
|
|
|
|
|
|
|
|
triggerKeydown(el.find('input'), 40 /*Down*/);
|
|
|
|
scope.$digest();
|
|
|
|
expect(choices.eq(1)).toHaveClass('active');
|
|
|
|
expect(getGroupLabel(choices.eq(1)).text()).toBe('bar');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('choices group by function', function() {
|
|
|
|
function createUiSelect() {
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices group-by="getGroupLabel" repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
it("should extract group value through function", function () {
|
|
|
|
var el = createUiSelect();
|
|
|
|
expect(el.find('.ui-select-choices-group .ui-select-choices-group-label').map(function() {
|
|
|
|
return this.textContent;
|
|
|
|
}).toArray()).toEqual(['odd', 'even']);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw when no ui-select-choices found', function() {
|
|
|
|
expect(function() {
|
|
|
|
compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match></ui-select-match> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}).toThrow(new Error('[ui.select:transcluded] Expected 1 .ui-select-choices but got \'0\'.'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw when no repeat attribute is provided to ui-select-choices', function() {
|
|
|
|
expect(function() {
|
|
|
|
compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-choices></ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}).toThrow(new Error('[ui.select:repeat] Expected \'repeat\' expression.'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw when repeat attribute has incorrect format ', function() {
|
|
|
|
expect(function() {
|
|
|
|
compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="incorrect format people"></ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}).toThrow(new Error('[ui.select:iexp] Expected expression in form of \'_item_ in _collection_[ track by _id_]\' but got \'incorrect format people\'.'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw when no ui-select-match found', function() {
|
|
|
|
expect(function() {
|
|
|
|
compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-choices repeat="item in items"></ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}).toThrow(new Error('[ui.select:transcluded] Expected 1 .ui-select-match but got \'0\'.'));
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format the model correctly using alias', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.selection.selected).toBe(scope.people[5]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should parse the model correctly using alias', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
scope.selection.selected = scope.people[5];
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format the model correctly using property of alias', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.selection.selected).toBe('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should parse the model correctly using property of alias', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
scope.selection.selected = 'Samantha';
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should parse the model correctly using property of alias with async choices data', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in peopleAsync | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
$timeout(function() {
|
|
|
|
scope.peopleAsync = scope.people;
|
|
|
|
});
|
|
|
|
|
|
|
|
scope.selection.selected = 'Samantha';
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('');
|
|
|
|
|
|
|
|
$timeout.flush(); //After choices populated (async), it should show match correctly
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
//TODO Is this really something we should expect?
|
|
|
|
it('should parse the model correctly using property of alias but passed whole object', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
scope.selection.selected = scope.people[5];
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format the model correctly without alias', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.selection.selected).toBe(scope.people[5]);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should parse the model correctly without alias', function() {
|
|
|
|
var el = createUiSelect();
|
|
|
|
scope.selection.selected = scope.people[5];
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should display choices correctly with child array', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in someObject.people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
scope.selection.selected = scope.people[5];
|
|
|
|
scope.$digest();
|
|
|
|
expect(getMatchLabel(el)).toEqual('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format the model correctly using property of alias and when using child array for choices', function() {
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in someObject.people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.selection.selected).toBe('Samantha');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should invoke select callback on select', function () {
|
|
|
|
|
|
|
|
scope.onSelectFn = function ($item, $model, $label) {
|
|
|
|
scope.$item = $item;
|
|
|
|
scope.$model = $model;
|
|
|
|
};
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select on-select="onSelectFn($item, $model)" ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(scope.$item).toBeFalsy();
|
|
|
|
expect(scope.$model).toBeFalsy();
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
$timeout.flush();
|
|
|
|
|
|
|
|
|
|
|
|
expect(scope.selection.selected).toBe('Samantha');
|
|
|
|
|
|
|
|
expect(scope.$item).toEqual(scope.people[5]);
|
|
|
|
expect(scope.$model).toEqual('Samantha');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should invoke hover callback', function(){
|
|
|
|
|
|
|
|
var highlighted;
|
|
|
|
scope.onHighlightFn = function ($item) {
|
|
|
|
highlighted = $item;
|
|
|
|
};
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select on-select="onSelectFn($item, $model)" ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices on-highlight="onHighlightFn(person)" repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(highlighted).toBeFalsy();
|
|
|
|
|
|
|
|
if (!isDropdownOpened(el)){
|
|
|
|
openDropdown(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
$(el).find('.ui-select-choices-row div:contains("Samantha")').trigger('mouseover');
|
|
|
|
scope.$digest();
|
|
|
|
|
|
|
|
expect(highlighted).toBe(scope.people[5]);
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should set $item & $model correctly when invoking callback on select and no single prop. binding', function () {
|
|
|
|
|
|
|
|
scope.onSelectFn = function ($item, $model, $label) {
|
|
|
|
scope.$item = $item;
|
|
|
|
scope.$model = $model;
|
|
|
|
};
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select on-select="onSelectFn($item, $model)" ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(scope.$item).toBeFalsy();
|
|
|
|
expect(scope.$model).toBeFalsy();
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.$item).toEqual(scope.$model);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should invoke remove callback on remove', function () {
|
|
|
|
|
|
|
|
scope.onRemoveFn = function ($item, $model, $label) {
|
|
|
|
scope.$item = $item;
|
|
|
|
scope.$model = $model;
|
|
|
|
};
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple on-remove="onRemoveFn($item, $model)" ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name" | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(scope.$item).toBeFalsy();
|
|
|
|
expect(scope.$model).toBeFalsy();
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
clickItem(el, 'Adrian');
|
|
|
|
el.find('.ui-select-match-item').first().find('.ui-select-match-close').click();
|
|
|
|
$timeout.flush();
|
|
|
|
|
|
|
|
expect(scope.$item).toBe(scope.people[5]);
|
|
|
|
expect(scope.$model).toBe('Samantha');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set $item & $model correctly when invoking callback on remove and no single prop. binding', function () {
|
|
|
|
|
|
|
|
scope.onRemoveFn = function ($item, $model, $label) {
|
|
|
|
scope.$item = $item;
|
|
|
|
scope.$model = $model;
|
|
|
|
};
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple on-remove="onRemoveFn($item, $model)" ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name" | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(scope.$item).toBeFalsy();
|
|
|
|
expect(scope.$model).toBeFalsy();
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
clickItem(el, 'Adrian');
|
|
|
|
el.find('.ui-select-match-item').first().find('.ui-select-match-close').click();
|
|
|
|
$timeout.flush();
|
|
|
|
|
|
|
|
expect(scope.$item).toBe(scope.people[5]);
|
|
|
|
expect(scope.$model).toBe(scope.$item);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should append/transclude content (with correct scope) that users add at <match> tag', function () {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match> \
|
|
|
|
<span ng-if="$select.selected.name!==\'Wladimir\'">{{$select.selected.name}}</span>\
|
|
|
|
<span ng-if="$select.selected.name===\'Wladimir\'">{{$select.selected.name | uppercase}}</span>\
|
|
|
|
</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(getMatchLabel(el).trim()).toEqual('Samantha');
|
|
|
|
|
|
|
|
clickItem(el, 'Wladimir');
|
|
|
|
expect(getMatchLabel(el).trim()).not.toEqual('Wladimir');
|
|
|
|
expect(getMatchLabel(el).trim()).toEqual('WLADIMIR');
|
|
|
|
|
|
|
|
});
|
|
|
|
it('should append/transclude content (with correct scope) that users add at <choices> tag', function () {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match> \
|
|
|
|
</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-if="person.name==\'Wladimir\'"> \
|
|
|
|
<span class="only-once">I should appear only once</span>\
|
|
|
|
</div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
openDropdown(el);
|
|
|
|
expect($(el).find('.only-once').length).toEqual(1);
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call refresh function when search text changes', function () {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match> \
|
|
|
|
</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search" \
|
|
|
|
refresh="fetchFromServer($select.search)" refresh-delay="0"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-if="person.name==\'Wladimir\'"> \
|
|
|
|
<span class="only-once">I should appear only once</span>\
|
|
|
|
</div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
scope.fetchFromServer = function(){};
|
|
|
|
|
|
|
|
spyOn(scope, 'fetchFromServer');
|
|
|
|
|
|
|
|
el.scope().$select.search = 'r';
|
|
|
|
scope.$digest();
|
|
|
|
$timeout.flush();
|
|
|
|
|
|
|
|
expect(scope.fetchFromServer).toHaveBeenCalledWith('r');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should call refresh function when search text changes', function () {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match> \
|
|
|
|
</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search" \
|
|
|
|
refresh="fetchFromServer($select.search)" refresh-delay="0"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-if="person.name==\'Wladimir\'"> \
|
|
|
|
<span class="only-once">I should appear only once</span>\
|
|
|
|
</div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
scope.fetchFromServer = function(){};
|
|
|
|
|
|
|
|
spyOn(scope, 'fetchFromServer');
|
|
|
|
|
|
|
|
el.scope().$select.search = 'r';
|
|
|
|
scope.$digest();
|
|
|
|
$timeout.flush();
|
|
|
|
|
|
|
|
expect(scope.fetchFromServer).toHaveBeenCalledWith('r');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format view value correctly when using single property binding and refresh funcion', function () {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match>{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.name as person in people | filter: $select.search" \
|
|
|
|
refresh="fetchFromServer($select.search)" refresh-delay="0"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-if="person.name==\'Wladimir\'"> \
|
|
|
|
<span class="only-once">I should appear only once</span>\
|
|
|
|
</div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
scope.fetchFromServer = function(searching){
|
|
|
|
|
|
|
|
if (searching == 's')
|
|
|
|
return scope.people
|
|
|
|
|
|
|
|
if (searching == 'o'){
|
|
|
|
scope.people = []; //To simulate cases were previously selected item isnt in the list anymore
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
setSearchText(el, 'r')
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(getMatchLabel(el)).toBe('Samantha');
|
|
|
|
|
|
|
|
setSearchText(el, 'o')
|
|
|
|
expect(getMatchLabel(el)).toBe('Samantha');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('search-enabled option', function() {
|
|
|
|
|
|
|
|
var el;
|
|
|
|
|
|
|
|
function setupSelectComponent(searchEnabled, theme) {
|
|
|
|
el = compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected" theme="' + theme + '" search-enabled="' + searchEnabled + '"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
describe('selectize theme', function() {
|
|
|
|
|
|
|
|
it('should show search input when true', function() {
|
|
|
|
setupSelectComponent(true, 'selectize');
|
|
|
|
expect($(el).find('.ui-select-search')).not.toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should hide search input when false', function() {
|
|
|
|
setupSelectComponent(false, 'selectize');
|
|
|
|
expect($(el).find('.ui-select-search')).toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('select2 theme', function() {
|
|
|
|
|
|
|
|
it('should show search input when true', function() {
|
|
|
|
setupSelectComponent('true', 'select2');
|
|
|
|
expect($(el).find('.select2-search')).not.toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should hide search input when false', function() {
|
|
|
|
setupSelectComponent('false', 'select2');
|
|
|
|
expect($(el).find('.select2-search')).toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('bootstrap theme', function() {
|
|
|
|
|
|
|
|
it('should show search input when true', function() {
|
|
|
|
setupSelectComponent('true', 'bootstrap');
|
|
|
|
clickMatch(el);
|
|
|
|
expect($(el).find('.ui-select-search')).not.toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should hide search input when false', function() {
|
|
|
|
setupSelectComponent('false', 'bootstrap');
|
|
|
|
clickMatch(el);
|
|
|
|
expect($(el).find('.ui-select-search')).toHaveClass('ng-hide');
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
describe('multi selection', function() {
|
|
|
|
|
|
|
|
function createUiSelectMultiple(attrs) {
|
|
|
|
var attrsHtml = '';
|
|
|
|
if (attrs !== undefined) {
|
|
|
|
if (attrs.disabled !== undefined) { attrsHtml += ' ng-disabled="' + attrs.disabled + '"'; }
|
|
|
|
if (attrs.required !== undefined) { attrsHtml += ' ng-required="' + attrs.required + '"'; }
|
|
|
|
if (attrs.tabindex !== undefined) { attrsHtml += ' tabindex="' + attrs.tabindex + '"'; }
|
|
|
|
if (attrs.closeOnSelect !== undefined) { attrsHtml += ' close-on-select="' + attrs.closeOnSelect + '"'; }
|
|
|
|
}
|
|
|
|
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple"' + attrsHtml + ' theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should render initial state', function() {
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
expect(el).toHaveClass('ui-select-multiple');
|
|
|
|
expect(el.scope().$select.selected.length).toBe(0);
|
|
|
|
expect(el.find('.ui-select-match-item').length).toBe(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should set model as an empty array if ngModel isnt defined after an item is selected', function () {
|
|
|
|
|
|
|
|
// scope.selection.selectedMultiple = [];
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
expect(scope.selection.selectedMultiple instanceof Array).toBe(false);
|
|
|
|
clickItem(el, 'Samantha');
|
|
|
|
expect(scope.selection.selectedMultiple instanceof Array).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render initial selected items', function() {
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
expect(el.scope().$select.selected.length).toBe(2);
|
|
|
|
expect(el.find('.ui-select-match-item').length).toBe(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove item by pressing X icon', function() {
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
expect(el.scope().$select.selected.length).toBe(2);
|
|
|
|
el.find('.ui-select-match-item').first().find('.ui-select-match-close').click();
|
|
|
|
expect(el.scope().$select.selected.length).toBe(1);
|
|
|
|
// $timeout.flush();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should pass tabindex to searchInput', function() {
|
|
|
|
var el = createUiSelectMultiple({tabindex: 5});
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(searchInput.attr('tabindex')).toEqual('5');
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should pass tabindex to searchInput when tabindex is an expression', function() {
|
|
|
|
scope.tabValue = 22;
|
|
|
|
var el = createUiSelectMultiple({tabindex: '{{tabValue + 10}}'});
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(searchInput.attr('tabindex')).toEqual('32');
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not give searchInput a tabindex when ui-select does not have one', function() {
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(searchInput.attr('tabindex')).toEqual(undefined);
|
|
|
|
expect($(el).attr('tabindex')).toEqual(undefined);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should update size of search input after removing an item', function() {
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
|
|
|
|
spyOn(el.scope().$select, 'sizeSearchInput');
|
|
|
|
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
var oldWidth = searchInput.css('width');
|
|
|
|
|
|
|
|
el.find('.ui-select-match-item').first().find('.ui-select-match-close').click();
|
|
|
|
expect(el.scope().$select.sizeSearchInput).toHaveBeenCalled();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should move to last match when pressing BACKSPACE key from search', function() {
|
|
|
|
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Backspace);
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(el.scope().$select.selected.length - 1);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove hightlighted match when pressing BACKSPACE key from search and decrease activeMatchIndex', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Left);
|
|
|
|
triggerKeydown(searchInput, Key.Left);
|
|
|
|
triggerKeydown(searchInput, Key.Backspace);
|
|
|
|
expect(el.scope().$select.selected).toEqual([scope.people[4], scope.people[6]]); //Wladimir & Nicole
|
|
|
|
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(0);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove hightlighted match when pressing DELETE key from search and keep same activeMatchIndex', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Left);
|
|
|
|
triggerKeydown(searchInput, Key.Left);
|
|
|
|
triggerKeydown(searchInput, Key.Delete);
|
|
|
|
expect(el.scope().$select.selected).toEqual([scope.people[4], scope.people[6]]); //Wladimir & Nicole
|
|
|
|
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(1);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should move to last match when pressing LEFT key from search', function() {
|
|
|
|
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Left);
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(el.scope().$select.selected.length - 1);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should move between matches when pressing LEFT key from search', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(el.scope().$select.selected.length - 2);
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(0);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should decrease $select.activeMatchIndex when pressing LEFT key', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
el.scope().$select.activeMatchIndex = 3
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
triggerKeydown(searchInput, Key.Left)
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(1);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should increase $select.activeMatchIndex when pressing RIGHT key', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
el.scope().$select.activeMatchIndex = 0
|
|
|
|
triggerKeydown(searchInput, Key.Right)
|
|
|
|
triggerKeydown(searchInput, Key.Right)
|
|
|
|
expect(el.scope().$select.activeMatchIndex).toBe(2);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should open dropdown when pressing DOWN key', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should search/open dropdown when writing to search input', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
el.scope().$select.search = 'r';
|
|
|
|
scope.$digest();
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should add selected match to selection array', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[5]]; //Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
clickItem(el, 'Wladimir');
|
|
|
|
expect(scope.selection.selectedMultiple).toEqual([scope.people[5], scope.people[4]]); //Samantha & Wladimir
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should close dropdown after selecting', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[5]]; //Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
clickItem(el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not close dropdown after selecting if closeOnSelect=false', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[5]]; //Samantha
|
|
|
|
var el = createUiSelectMultiple({closeOnSelect: false});
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
clickItem(el, 'Wladimir');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should closes dropdown when pressing ESC key from search input', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5], scope.people[6]]; //Wladimir, Samantha & Nicole
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(true);
|
|
|
|
triggerKeydown(searchInput, Key.Escape)
|
|
|
|
expect(isDropdownOpened(el)).toEqual(false);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should select highlighted match when pressing ENTER key from dropdown', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = [scope.people[5]]; //Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
triggerKeydown(searchInput, Key.Enter)
|
|
|
|
expect(scope.selection.selectedMultiple.length).toEqual(2);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should increase $select.activeIndex when pressing DOWN key from dropdown', function() {
|
|
|
|
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
triggerKeydown(searchInput, Key.Down); //Open dropdown
|
|
|
|
|
|
|
|
el.scope().$select.activeIndex = 0
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
triggerKeydown(searchInput, Key.Down)
|
|
|
|
expect(el.scope().$select.activeIndex).toBe(2);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should decrease $select.activeIndex when pressing UP key from dropdown', function() {
|
|
|
|
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
triggerKeydown(searchInput, Key.Down); //Open dropdown
|
|
|
|
|
|
|
|
el.scope().$select.activeIndex = 5
|
|
|
|
triggerKeydown(searchInput, Key.Up)
|
|
|
|
triggerKeydown(searchInput, Key.Up)
|
|
|
|
expect(el.scope().$select.activeIndex).toBe(3);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render initial selected items', function() {
|
|
|
|
scope.selection.selectedMultiple = [scope.people[4], scope.people[5]]; //Wladimir & Samantha
|
|
|
|
var el = createUiSelectMultiple();
|
|
|
|
expect(el.scope().$select.selected.length).toBe(2);
|
|
|
|
expect(el.find('.ui-select-match-item').length).toBe(2);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should parse the items correctly using single property binding', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(el.scope().$select.selected).toEqual([scope.people[4], scope.people[5]]);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should add selected match to selection array using single property binding', function() {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
clickItem(el, 'Natasha');
|
|
|
|
|
|
|
|
expect(el.scope().$select.selected).toEqual([scope.people[4], scope.people[5], scope.people[7]]);
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com', 'natasha@email.com'];
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format view value correctly when using single property binding and refresh funcion', function () {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search" \
|
|
|
|
refresh="fetchFromServer($select.search)" refresh-delay="0"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
|
|
|
|
var searchInput = el.find('.ui-select-search');
|
|
|
|
|
|
|
|
scope.fetchFromServer = function(searching){
|
|
|
|
|
|
|
|
if (searching == 'n')
|
|
|
|
return scope.people
|
|
|
|
|
|
|
|
if (searching == 'o'){
|
|
|
|
scope.people = []; //To simulate cases were previously selected item isnt in the list anymore
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
setSearchText(el, 'n')
|
|
|
|
clickItem(el, 'Nicole');
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text())
|
|
|
|
.toBe("Wladimir <wladimir@email.com>Samantha <samantha@email.com>Nicole <nicole@email.com>");
|
|
|
|
|
|
|
|
setSearchText(el, 'o')
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text())
|
|
|
|
.toBe("Wladimir <wladimir@email.com>Samantha <samantha@email.com>Nicole <nicole@email.com>");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should watch changes for $select.selected and update formatted value correctly', function () {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select> \
|
|
|
|
'
|
|
|
|
);
|
|
|
|
|
|
|
|
var el2 = compileTemplate('<span class="resultDiv" ng-bind="selection.selectedMultiple"></span>');
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text())
|
|
|
|
.toBe("Wladimir <wladimir@email.com>Samantha <samantha@email.com>");
|
|
|
|
|
|
|
|
clickItem(el, 'Nicole');
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text())
|
|
|
|
.toBe("Wladimir <wladimir@email.com>Samantha <samantha@email.com>Nicole <nicole@email.com>");
|
|
|
|
|
|
|
|
expect(scope.selection.selectedMultiple.length).toBe(3);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should change viewvalue only once when updating modelvalue', function () {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select ng-change="onlyOnce()" multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select> \
|
|
|
|
'
|
|
|
|
);
|
|
|
|
|
|
|
|
scope.counter = 0;
|
|
|
|
scope.onlyOnce = function(){
|
|
|
|
scope.counter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
clickItem(el, 'Nicole');
|
|
|
|
|
|
|
|
expect(scope.counter).toBe(1);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('should run $formatters when changing model directly', function () {
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple = ['wladimir@email.com', 'samantha@email.com'];
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select> \
|
|
|
|
'
|
|
|
|
);
|
|
|
|
|
|
|
|
// var el2 = compileTemplate('<span class="resultDiv" ng-bind="selection.selectedMultiple"></span>');
|
|
|
|
|
|
|
|
scope.selection.selectedMultiple.push("nicole@email.com");
|
|
|
|
|
|
|
|
scope.$digest();
|
|
|
|
scope.$digest(); //2nd $digest needed when using angular 1.3.0-rc.1+, might be related with the fact that the value is an array
|
|
|
|
|
|
|
|
expect(el.find('.ui-select-match-item [uis-transclude-append]:not(.ng-hide)').text())
|
|
|
|
.toBe("Wladimir <wladimir@email.com>Samantha <samantha@email.com>Nicole <nicole@email.com>");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should support multiple="multiple" attribute', function() {
|
|
|
|
|
|
|
|
var el = compileTemplate(
|
|
|
|
'<ui-select multiple="multiple" ng-model="selection.selectedMultiple" theme="bootstrap" style="width: 800px;"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$item.name}} <{{$item.email}}></ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person.email as person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select> \
|
|
|
|
'
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(el.scope().$select.multiple).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('default configuration via uiSelectConfig', function() {
|
|
|
|
|
|
|
|
describe('searchEnabled option', function() {
|
|
|
|
|
|
|
|
function setupWithoutAttr(){
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setupWithAttr(searchEnabled){
|
|
|
|
return compileTemplate(
|
|
|
|
'<ui-select ng-model="selection.selected" search-enabled="'+searchEnabled+'"> \
|
|
|
|
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
|
|
|
|
<ui-select-choices repeat="person in people | filter: $select.search"> \
|
|
|
|
<div ng-bind-html="person.name | highlight: $select.search"></div> \
|
|
|
|
<div ng-bind-html="person.email | highlight: $select.search"></div> \
|
|
|
|
</ui-select-choices> \
|
|
|
|
</ui-select>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
it('should be true by default', function(){
|
|
|
|
var el = setupWithoutAttr();
|
|
|
|
expect(el.scope().$select.searchEnabled).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should disable search if default set to false', function(){
|
|
|
|
var uiSelectConfig = $injector.get('uiSelectConfig');
|
|
|
|
uiSelectConfig.searchEnabled = false;
|
|
|
|
|
|
|
|
var el = setupWithoutAttr();
|
|
|
|
expect(el.scope().$select.searchEnabled).not.toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be overridden by inline option search-enabled=true', function(){
|
|
|
|
var uiSelectConfig = $injector.get('uiSelectConfig');
|
|
|
|
uiSelectConfig.searchEnabled = false;
|
|
|
|
|
|
|
|
var el = setupWithAttr(true);
|
|
|
|
expect(el.scope().$select.searchEnabled).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should be overridden by inline option search-enabled=false', function(){
|
|
|
|
var uiSelectConfig = $injector.get('uiSelectConfig');
|
|
|
|
uiSelectConfig.searchEnabled = true;
|
|
|
|
|
|
|
|
var el = setupWithAttr(false);
|
|
|
|
expect(el.scope().$select.searchEnabled).not.toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('accessibility', function() {
|
|
|
|
it('should have baseTitle in scope', function() {
|
|
|
|
expect(createUiSelect().scope().$select.baseTitle).toBe('Select box');
|
|
|
|
expect(createUiSelect().scope().$select.focusserTitle).toBe('Select box focus');
|
|
|
|
expect(createUiSelect({ title: 'Choose a person' }).scope().$select.baseTitle).toBe('Choose a person');
|
|
|
|
expect(createUiSelect({ title: 'Choose a person' }).scope().$select.focusserTitle).toBe('Choose a person focus');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should have aria-label on all input and button elements', function() {
|
|
|
|
checkTheme();
|
|
|
|
checkTheme('select2');
|
|
|
|
checkTheme('selectize');
|
|
|
|
checkTheme('bootstrap');
|
|
|
|
|
|
|
|
function checkTheme(theme) {
|
|
|
|
var el = createUiSelect({ theme: theme});
|
|
|
|
checkElements(el.find('input'));
|
|
|
|
checkElements(el.find('button'));
|
|
|
|
|
|
|
|
function checkElements(els) {
|
|
|
|
for (var i = 0; i < els.length; i++) {
|
|
|
|
expect(els[i].attributes['aria-label']).toBeTruthy();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|