first commit

This commit is contained in:
2024-04-19 14:04:41 +07:00
commit 014283036f
7282 changed files with 1324127 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
module('Accessibility - Search');
var MultipleSelection = require('select2/selection/multiple');
var InlineSearch = require('select2/selection/search');
var $ = require('jquery');
var Utils = require('select2/utils');
var Options = require('select2/options');
var options = new Options({});
test('aria-autocomplete attribute is present', function (assert) {
var $select = $('#qunit-fixture .multiple');
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var selection = new CustomSelection($select, options);
var $selection = selection.render();
// Update the selection so the search is rendered
selection.update([]);
assert.equal(
$selection.find('input').attr('aria-autocomplete'),
'list',
'The search box is marked as autocomplete'
);
});
test('aria-activedescendant should be removed when closed', function (assert) {
var $select = $('#qunit-fixture .multiple');
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var selection = new CustomSelection($select, options);
var $selection = selection.render();
var container = new MockContainer();
selection.bind(container, $('<span></span>'));
// Update the selection so the search is rendered
selection.update([]);
var $search = $selection.find('input');
$search.attr('aria-activedescendant', 'something');
container.trigger('close');
assert.ok(
!$search.attr('aria-activedescendant'),
'There is no active descendant when the dropdown is closed'
);
});

View File

@@ -0,0 +1,154 @@
module('Accessibility - All');
var BaseSelection = require('select2/selection/base');
var SingleSelection = require('select2/selection/single');
var MultipleSelection = require('select2/selection/multiple');
var $ = require('jquery');
var Options = require('select2/options');
var options = new Options({});
test('title is carried over from original element', function (assert) {
var $select = $('#qunit-fixture .single');
var selection = new BaseSelection($select, options);
var $selection = selection.render();
assert.equal(
$selection.attr('title'),
$select.attr('title'),
'The title should have been copied over from the original element'
);
});
test('aria-expanded reflects the state of the container', function (assert) {
var $select = $('#qunit-fixture .single');
var selection = new BaseSelection($select, options);
var $selection = selection.render();
var container = new MockContainer();
selection.bind(container, $('<span></span>'));
assert.equal(
$selection.attr('aria-expanded'),
'false',
'The container should not be expanded when it is closed'
);
container.trigger('open');
assert.equal(
$selection.attr('aria-expanded'),
'true',
'The container should be expanded when it is opened'
);
});
test('static aria attributes are present', function (assert) {
var $select = $('#qunit-fixture .single');
var selection = new BaseSelection($select, options);
var $selection = selection.render();
assert.equal(
$selection.attr('role'),
'combobox',
'The container should identify as a combobox'
);
assert.equal(
$selection.attr('aria-haspopup'),
'true',
'The dropdown is considered a popup of the container'
);
});
test('the container should be in the tab order', function (assert) {
var $select = $('#qunit-fixture .single');
var selection = new BaseSelection($select, options);
var $selection = selection.render();
var container = new MockContainer();
selection.bind(container, $('<span></span>'));
assert.equal(
$selection.attr('tabindex'),
'0',
'The tab index should allow it to fit in the natural tab order'
);
container.trigger('disable');
assert.equal(
$selection.attr('tabindex'),
'-1',
'The selection should be dropped out of the tab order when disabled'
);
container.trigger('enable');
assert.equal(
$selection.attr('tabindex'),
'0',
'The tab index should be restored when re-enabled'
);
});
test('a custom tabindex is copied', function (assert) {
var $select = $('#qunit-fixture .single');
$select.attr('tabindex', '999');
var selection = new BaseSelection($select, options);
var $selection = selection.render();
var container = new MockContainer();
selection.bind(container, $('<span></span>'));
assert.equal(
$selection.attr('tabindex'),
'999',
'The tab index should match the original tab index'
);
container.trigger('disable');
assert.equal(
$selection.attr('tabindex'),
'-1',
'The selection should be dropped out of the tab order when disabled'
);
container.trigger('enable');
assert.equal(
$selection.attr('tabindex'),
'999',
'The tab index should be restored when re-enabled'
);
});
module('Accessibility - Single');
test('aria-labelledby should match the rendered container', function (assert) {
var $select = $('#qunit-fixture .single');
var selection = new SingleSelection($select, options);
var $selection = selection.render();
var container = new MockContainer();
selection.bind(container, $('<span></span>'));
var $rendered = $selection.find('.select2-selection__rendered');
assert.equal(
$selection.attr('aria-labelledby'),
$rendered.attr('id'),
'The rendered selection should label the container'
);
});
module('Accessibility - Multiple');

View File

@@ -0,0 +1,329 @@
module('Data adapters - Array');
var ArrayData = require('select2/data/array');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var UserDefinedType = function (id, text) {
var self = this;
self.id = id;
self.text = text;
return self;
};
var arrayOptions = new Options({
data: [
{
id: 'default',
text: 'Default'
},
{
id: '1',
text: 'One'
},
{
id: '2',
text: '2'
},
new UserDefinedType(1, 'aaaaaa')
]
});
var extraOptions = new Options ({
data: [
{
id: 'default',
text: 'Default',
extra: true
},
{
id: 'One',
text: 'One',
extra: true
}
]
});
var nestedOptions = new Options({
data: [
{
text: 'Default',
children: [
{
text: 'Next',
children: [
{
id: 'a',
text: 'Option'
}
]
}
]
}
]
});
test('current gets default for single', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, arrayOptions);
data.current(function (val) {
assert.equal(
val.length,
1,
'There should always be a selected item for array data.'
);
var item = val[0];
assert.equal(
item.id,
'default',
'The first item should be selected'
);
});
});
test('current gets default for multiple', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new ArrayData($select, arrayOptions);
data.current(function (val) {
assert.equal(
val.length,
0,
'There should be no default selection.'
);
});
});
test('current works with existing selections', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new ArrayData($select, arrayOptions);
$select.val(['One']);
data.current(function (val) {
assert.equal(
val.length,
1,
'There should only be one existing selection.'
);
var option = val[0];
assert.equal(
option.id,
'One',
'The id should be equal to the value of the option tag.'
);
assert.equal(
option.text,
'One',
'The text should be equal to the text of the option tag.'
);
});
});
test('current works with selected data', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, arrayOptions);
data.select({
id: '2',
text: '2'
});
data.current(function (val) {
assert.equal(
val.length,
1,
'There should only be one option selected.'
);
var option = val[0];
assert.equal(
option.id,
'2',
'The id should match the original id from the array.'
);
assert.equal(
option.text,
'2',
'The text should match the original text from the array.'
);
});
});
test('select works for single', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, arrayOptions);
assert.equal(
$select.val(),
'default',
'There should already be a selection'
);
data.select({
id: '1',
text: 'One'
});
assert.equal(
$select.val(),
'1',
'The selected value should be the same as the selected id'
);
});
test('multiple sets the value', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new ArrayData($select, arrayOptions);
assert.equal($select.val(), null);
data.select({
id: 'default',
text: 'Default'
});
assert.deepEqual($select.val(), ['default']);
});
test('multiple adds to the old value', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new ArrayData($select, arrayOptions);
$select.val(['One']);
assert.deepEqual($select.val(), ['One']);
data.select({
id: 'default',
text: 'Default'
});
assert.deepEqual($select.val(), ['One', 'default']);
});
test('option tags are automatically generated', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, arrayOptions);
assert.equal(
$select.find('option').length,
4,
'An <option> element should be created for each object'
);
});
test('option tags can receive new data', function(assert) {
var $select = $('#qunit-fixture .single');
var data = new ArrayData($select, extraOptions);
assert.equal(
$select.find('option').length,
2,
'Only one more <option> element should be created'
);
data.select({
id: 'default'
});
assert.ok(
Utils.GetData($select.find(':selected')[0], 'data').extra,
'<option> default should have new data'
);
data.select({
id: 'One'
});
assert.ok(
Utils.GetData($select.find(':selected')[0], 'data').extra,
'<option> One should have new data'
);
});
test('optgroup tags can also be generated', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, nestedOptions);
assert.equal(
$select.find('option').length,
1,
'An <option> element should be created for the one selectable object'
);
assert.equal(
$select.find('optgroup').length,
2,
'An <optgroup> element should be created for the two with children'
);
});
test('optgroup tags have the right properties', function (assert) {
var $select = $('#qunit-fixture .single-empty');
var data = new ArrayData($select, nestedOptions);
var $group = $select.children('optgroup');
assert.equal(
$group.prop('label'),
'Default',
'An `<optgroup>` label should match the text property'
);
assert.equal(
$group.children().length,
1,
'The <optgroup> should have one child under it'
);
});
test('existing selections are respected on initialization', function (assert) {
var $select = $(
'<select>' +
'<option>First</option>' +
'<option selected>Second</option>' +
'</select>'
);
var options = new Options({
data: [
{
id: 'Second',
text: 'Second'
},
{
id: 'Third',
text: 'Third'
}
]
});
assert.equal($select.val(), 'Second');
var data = new ArrayData($select, options);
assert.equal($select.val(), 'Second');
});

View File

@@ -0,0 +1,29 @@
module('Data adapters - Base');
var BaseData = require('select2/data/base');
var $ = require('jquery');
var Options = require('select2/options');
var options = new Options({});
test('current is required', function (assert) {
var data = new BaseData($('#qunit-fixture select'), options);
assert.throws(
function () {
data.current(function () {});
},
'current has no default implementation'
);
});
test('query is required', function (assert) {
var data = new BaseData($('#qunit-fixture select'), options);
assert.throws(
function () {
data.query({}, function () {});
},
'query has no default implementation'
);
});

View File

@@ -0,0 +1,158 @@
module('Data adapters - <input> compatibility');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var ArrayData = require('select2/data/array');
var InputData = require('select2/compat/inputData');
var InputAdapter = Utils.Decorate(ArrayData, InputData);
test('test that options can be selected', function (assert) {
var options = new Options({
data: [
{
id: 'test',
text: 'Test'
}
]
});
var $element = $('<input />');
var adapter = new InputAdapter($element, options);
adapter.select({
id: 'test'
});
assert.equal(
$element.val(),
'test',
'The id of the item should be the value'
);
});
test('unselect the single selected option clears the value', function (assert) {
var options = new Options({
data: [
{
id: 'test',
text: 'Test',
selected: true
}
]
});
var $element = $('<input />');
var adapter = new InputAdapter($element, options);
adapter.unselect({
id: 'test'
});
assert.equal(
$element.val(),
'',
'The id should no longer be in the value'
);
});
test('options can be unselected individually', function (assert) {
var options = new Options({
data: [
{
id: 'test',
text: 'Test'
},
{
id: 'test2',
text: 'Test2'
},
{
id: 'test3',
text: 'Test3'
}
]
});
var $element = $('<input />');
$element.val('test,test2,test3');
var adapter = new InputAdapter($element, options);
adapter.unselect({
id: 'test2'
});
assert.equal(
$element.val(),
'test,test3',
'The value should contain all the still selected options'
);
});
test('default values can be set', function (assert) {
assert.expect(4);
var options = new Options({
data: [
{
id: 'test',
text: 'Test'
}
]
});
var $element = $('<input value="test" />');
var adapter = new InputAdapter($element, options);
adapter.current(function (data) {
assert.equal(
data.length,
1,
'There should only be a single selected option'
);
var item = data[0];
assert.equal(item.id, 'test');
assert.equal(item.text, 'Test');
});
assert.equal(
$element.val(),
'test',
'The value should not have been altered'
);
});
test('no default value', function (assert) {
assert.expect(2);
var options = new Options({
data: [
{
id: 'test',
text: 'Test'
}
]
});
var $element = $('<input />');
var adapter = new InputAdapter($element, options);
adapter.current(function (data) {
assert.equal(
data.length,
0,
'There should be no selected options'
);
});
assert.equal(
$element.val(),
'',
'The value should not have been altered'
);
});

View File

@@ -0,0 +1,138 @@
module('Data adapters - Maximum input length');
var MaximumInputLength = require('select2/data/maximumInputLength');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
function MaximumInputStub () {
this.called = false;
}
MaximumInputStub.prototype.query = function (params, callback) {
this.called = true;
};
var MaximumInputData = Utils.Decorate(MaximumInputStub, MaximumInputLength);
test('0 never displays the notice', function (assert) {
var zeroOptions = new Options({
maximumInputLength: 0
});
var data = new MaximumInputData(null, zeroOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumInputData(null, zeroOptions);
data.query({
term: 'test'
});
assert.ok(data.called);
});
test('< 0 never displays the notice', function (assert) {
var negativeOptions = new Options({
maximumInputLength: -1
});
var data = new MaximumInputData(null, negativeOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumInputData(null, negativeOptions);
data.query({
term: 'test'
});
assert.ok(data.called);
});
test('triggers when input is too long', function (assert) {
var options = new Options({
maximumInputLength: 1
});
var data = new MaximumInputData(null, options);
data.trigger = function () {
assert.ok(true, 'The event should be triggered.');
};
data.query({
term: 'no'
});
assert.ok(!data.called, 'The adapter should not be called');
});
test('does not trigger when equal', function (assert) {
var options = new Options({
maximumInputLength: 10
});
var data = new MaximumInputData(null, options);
data.trigger = function () {
assert.ok(false, 'The event should not be triggered.');
};
data.query({
term: '1234567890'
});
assert.ok(data.called);
});
test('does not trigger when less', function (assert) {
var options = new Options({
maximumInputLength: 10
});
var data = new MaximumInputData(null, options);
data.trigger = function () {
assert.ok(false, 'The event should not be triggered.');
};
data.query({
term: '123'
});
assert.ok(data.called);
});
test('works with null term', function (assert) {
var options = new Options({
maximumInputLength: 1
});
var data = new MaximumInputData(null, options);
data.trigger = function () {
assert.ok(false, 'The event should not be triggered');
};
data.query({});
assert.ok(data.called);
});

View File

@@ -0,0 +1,202 @@
module('Data adapters - Maximum selection length');
var MaximumSelectionLength = require('select2/data/maximumSelectionLength');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
function MaximumSelectionStub () {
this.called = false;
this.currentData = [];
}
MaximumSelectionStub.prototype.current = function (callback) {
callback(this.currentData);
};
MaximumSelectionStub.prototype.val = function (val) {
this.currentData.push(val);
};
MaximumSelectionStub.prototype.query = function (params, callback) {
this.called = true;
};
var MaximumSelectionData = Utils.Decorate(
MaximumSelectionStub,
MaximumSelectionLength
);
test('0 never displays the notice', function (assert) {
var zeroOptions = new Options({
maximumSelectionLength: 0
});
var data = new MaximumSelectionData(null, zeroOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, zeroOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.val('1');
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, zeroOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.val('1');
data.val('2');
data.query({
term: ''
});
assert.ok(data.called);
});
test('< 0 never displays the notice', function (assert) {
var negativeOptions = new Options({
maximumSelectionLength: -1
});
var data = new MaximumSelectionData(null, negativeOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, negativeOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.val('1');
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, negativeOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.val('1');
data.val('2');
data.query({
term: ''
});
assert.ok(data.called);
});
test('triggers when >= 1 selection' , function (assert) {
var maxOfOneOptions = new Options({
maximumSelectionLength: 1
});
var data = new MaximumSelectionData(null, maxOfOneOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, maxOfOneOptions);
data.trigger = function () {
assert.ok(true, 'The event should be triggered.');
};
data.val('1');
data.query({
term: ''
});
assert.ok(!data.called);
});
test('triggers when >= 2 selections' , function (assert) {
var maxOfTwoOptions = new Options({
maximumSelectionLength: 2
});
var data = new MaximumSelectionData(null, maxOfTwoOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, maxOfTwoOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.val('1');
data.query({
term: ''
});
assert.ok(data.called);
data = new MaximumSelectionData(null, maxOfTwoOptions);
data.trigger = function () {
assert.ok(true, 'The event should be triggered.');
};
data.val('1');
data.val('2');
data.query({
term: ''
});
assert.ok(!data.called);
});

View File

@@ -0,0 +1,138 @@
module('Data adapters - Minimum input length');
var MinimumInputLength = require('select2/data/minimumInputLength');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
function StubData () {
this.called = false;
}
StubData.prototype.query = function (params, callback) {
this.called = true;
};
var MinimumData = Utils.Decorate(StubData, MinimumInputLength);
test('0 never displays the notice', function (assert) {
var zeroOptions = new Options({
minimumInputLength: 0
});
var data = new MinimumData(null, zeroOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MinimumData(null, zeroOptions);
data.query({
term: 'test'
});
assert.ok(data.called);
});
test('< 0 never displays the notice', function (assert) {
var negativeOptions = new Options({
minimumInputLength: -1
});
var data = new MinimumData(null, negativeOptions);
data.trigger = function () {
assert.ok(false, 'No events should be triggered');
};
data.query({
term: ''
});
assert.ok(data.called);
data = new MinimumData(null, negativeOptions);
data.query({
term: 'test'
});
assert.ok(data.called);
});
test('triggers when input is not long enough', function (assert) {
var options = new Options({
minimumInputLength: 10
});
var data = new MinimumData(null, options);
data.trigger = function () {
assert.ok(true, 'The event should be triggered.');
};
data.query({
term: 'no'
});
assert.ok(!data.called);
});
test('does not trigger when equal', function (assert) {
var options = new Options({
minimumInputLength: 10
});
var data = new MinimumData(null, options);
data.trigger = function () {
assert.ok(false, 'The event should not be triggered.');
};
data.query({
term: '1234567890'
});
assert.ok(data.called);
});
test('does not trigger when greater', function (assert) {
var options = new Options({
minimumInputLength: 10
});
var data = new MinimumData(null, options);
data.trigger = function () {
assert.ok(false, 'The event should not be triggered.');
};
data.query({
term: '12345678901'
});
assert.ok(data.called);
});
test('works with null term', function (assert) {
var options = new Options({
minimumInputLength: 1
});
var data = new MinimumData(null, options);
data.trigger = function () {
assert.ok(true, 'The event should be triggered');
};
data.query({});
assert.ok(!data.called);
});

View File

@@ -0,0 +1,554 @@
module('Data adapters - Select - current');
var SelectData = require('select2/data/select');
var $ = require('jquery');
var Options = require('select2/options');
var selectOptions = new Options({});
test('current gets default for single', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
data.current(function (data) {
assert.equal(
data.length,
1,
'There should only be one selected option'
);
var option = data[0];
assert.equal(
option.id,
'One',
'The value of the option tag should be the id'
);
assert.equal(
option.text,
'One',
'The text within the option tag should be the text'
);
});
});
test('current gets default for multiple', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new SelectData($select, selectOptions);
data.current(function (data) {
assert.equal(
data.length,
0,
'Multiple selects have no default selection.'
);
});
});
test('current gets options with explicit value', function (assert) {
var $select = $('#qunit-fixture .single');
var $option = $('<option value="1">One</option>');
$select.append($option);
var data = new SelectData($select, selectOptions);
$select.val('1');
data.current(function (data) {
assert.equal(
data.length,
1,
'There should be one selected option'
);
var option = data[0];
assert.equal(
option.id,
'1',
'The option value should be the selected id'
);
assert.equal(
option.text,
'One',
'The text should match the text for the option tag'
);
});
});
test('current gets options with implicit value', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
$select.val('One');
data.current(function (val) {
assert.equal(
val.length,
1,
'There should only be one selected value'
);
var option = val[0];
assert.equal(
option.id,
'One',
'The id should be the same as the option text'
);
assert.equal(
option.text,
'One',
'The text should be the same as the option text'
);
});
});
test('select works for single', function (assert) {
var $select = $('#qunit-fixture .single-with-placeholder');
var data = new SelectData($select, selectOptions);
assert.equal($select.val(), 'placeholder');
data.select({
id: 'One',
text: 'One'
});
assert.equal($select.val(), 'One');
});
test('multiple sets the value', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new SelectData($select, selectOptions);
assert.equal($select.val(), null);
data.select({
id: 'Two',
text: 'Two'
});
assert.deepEqual($select.val(), ['Two']);
});
test('multiple adds to the old value', function (assert) {
var $select = $('#qunit-fixture .multiple');
var data = new SelectData($select, selectOptions);
$select.val(['Two']);
assert.deepEqual($select.val(), ['Two']);
data.select({
id: 'One',
text: 'One'
});
assert.deepEqual($select.val(), ['One', 'Two']);
});
test('duplicates - single - same id on select triggers change',
function (assert) {
var $select = $('#qunit-fixture .duplicates');
var data = new SelectData($select, data);
var second = $('#qunit-fixture .duplicates option')[2];
var changeTriggered = false;
assert.equal($select.val(), 'one');
$select.on('change', function () {
changeTriggered = true;
});
data.select({
id: 'one',
text: 'Uno',
element: second
});
assert.equal(
$select.val(),
'one',
'The value never changed'
);
assert.ok(
changeTriggered,
'The change event should be triggered'
);
assert.ok(
second.selected,
'The second duplicate is selected, not the first'
);
});
test('duplicates - single - different id on select triggers change',
function (assert) {
var $select = $('#qunit-fixture .duplicates');
var data = new SelectData($select, data);
var second = $('#qunit-fixture .duplicates option')[2];
var changeTriggered = false;
$select.val('two');
$select.on('change', function () {
changeTriggered = true;
});
data.select({
id: 'one',
text: 'Uno',
element: second
});
assert.equal(
$select.val(),
'one',
'The value changed to the duplicate id'
);
assert.ok(
changeTriggered,
'The change event should be triggered'
);
assert.ok(
second.selected,
'The second duplicate is selected, not the first'
);
});
test('duplicates - multiple - same id on select triggers change',
function (assert) {
var $select = $('#qunit-fixture .duplicates-multi');
var data = new SelectData($select, data);
var second = $('#qunit-fixture .duplicates-multi option')[2];
var changeTriggered = false;
$select.val(['one']);
$select.on('change', function () {
changeTriggered = true;
});
data.select({
id: 'one',
text: 'Uno',
element: second
});
assert.deepEqual(
$select.val(),
['one', 'one'],
'The value now has duplicates'
);
assert.ok(
changeTriggered,
'The change event should be triggered'
);
assert.ok(
second.selected,
'The second duplicate is selected, not the first'
);
});
test('duplicates - multiple - different id on select triggers change',
function (assert) {
var $select = $('#qunit-fixture .duplicates-multi');
var data = new SelectData($select, data);
var second = $('#qunit-fixture .duplicates-multi option')[2];
var changeTriggered = false;
$select.val(['two']);
$select.on('change', function () {
changeTriggered = true;
});
data.select({
id: 'one',
text: 'Uno',
element: second
});
assert.deepEqual(
$select.val(),
['two', 'one'],
'The value has the new id'
);
assert.ok(
changeTriggered,
'The change event should be triggered'
);
assert.ok(
second.selected,
'The second duplicate is selected, not the first'
);
});
module('Data adapter - Select - query');
test('all options are returned with no term', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
data.query({}, function (data) {
assert.equal(
data.results.length,
1,
'The number of items returned should be equal to the number of options'
);
});
});
test('the matcher checks the text', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
data.query({
term: 'One'
}, function (data) {
assert.equal(
data.results.length,
1,
'Only the "One" option should be found'
);
});
});
test('the matcher ignores case', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
data.query({
term: 'one'
}, function (data) {
assert.equal(
data.results.length,
1,
'The "One" option should still be found'
);
});
});
test('no options may be returned with no matches', function (assert) {
var $select = $('#qunit-fixture .single');
var data = new SelectData($select, selectOptions);
data.query({
term: 'qwerty'
}, function (data) {
assert.equal(
data.results.length,
0,
'Only matching items should be returned'
);
});
});
test('optgroup tags are marked with children', function (assert) {
var $select = $('#qunit-fixture .groups');
var data = new SelectData($select, selectOptions);
data.query({}, function (data) {
assert.ok(
'children' in data.results[0],
'The optgroup element should have children when queried'
);
});
});
test('empty optgroups are still shown when queried', function (assert) {
var $select = $('#qunit-fixture .groups');
var data = new SelectData($select, selectOptions);
data.query({}, function (data) {
assert.equal(
data.results.length,
2,
'The empty optgroup element should still be returned when queried'
);
var item = data.results[1];
assert.equal(
item.text,
'Empty',
'The text of the empty optgroup should match the label'
);
assert.equal(
item.children.length,
0,
'There should be no children in the empty opgroup'
);
});
});
test('multiple options with the same value are returned', function (assert) {
var $select = $('#qunit-fixture .duplicates');
var data = new SelectData($select, selectOptions);
data.query({}, function (data) {
assert.equal(
data.results.length,
3,
'The duplicate option should still be returned when queried'
);
var first = data.results[0];
var duplicate = data.results[2];
assert.equal(
first.id,
duplicate.id,
'The duplicates should have the same id'
);
assert.notEqual(
first.text,
duplicate.text,
'The duplicates do not have the same text'
);
});
});
test('data objects use the text of the option', function (assert) {
var $select = $('#qunit-fixture .duplicates');
var data = new SelectData($select, selectOptions);
var $option = $('<option>&amp;</option>');
var item = data.item($option);
assert.equal(item.id, '&');
assert.equal(item.text, '&');
});
test('select option construction accepts id=0 (zero) value', function (assert) {
var $select = $('#qunit-fixture .single');
var selectOptions = [{ id: 0, text: 'Zero Value'}];
var data = new SelectData($select, selectOptions);
var optionElem = data.option(selectOptions[0]);
// If was "Zero Value"", then it ignored id property
assert.equal(
optionElem[0].value,
'0',
'Built option value should be "0" (zero as a string).'
);
});
test('select option construction accepts id="" (empty string) value',
function (assert) {
var $select = $('#qunit-fixture .single');
var selectOptions = [{ id: '', text: 'Empty String'}];
var data = new SelectData($select, selectOptions);
var optionElem = data.option(selectOptions[0]);
assert.equal(
optionElem[0].value,
'',
'Built option value should be an empty string.'
);
});
test('user-defined types are normalized properly', function (assert) {
var $select = $('#qunit-fixture .user-defined'),
UserDefinedType = function (id, text) {
var self = this;
self.id = id;
self.text = text;
return self;
};
var testData = [
'Test',
{
id: 4,
text: 'item'
},
new UserDefinedType(1, 'aaaaaa')
];
var data = new SelectData($select, selectOptions);
var normalizedItem = data._normalizeItem(testData[0]);
var normalizedItem2 = data._normalizeItem(testData[1]);
var normalizedItem3 = data._normalizeItem(testData[2]);
assert.equal(
testData[0],
normalizedItem.id,
'id property should be equal to text after normalize'
);
assert.equal(
testData[0],
normalizedItem.text,
'text property should be equal after normalize'
);
assert.equal(
testData[1].id,
normalizedItem2.id,
'id property should be equal after normalize'
);
assert.equal(
testData[1].text,
normalizedItem2.text,
'text property should be equal after normalize'
);
assert.equal(
testData[2].id,
normalizedItem3.id,
'id property should be equal after normalize'
);
assert.equal(
testData[2].text,
normalizedItem3.text,
'text property should be equal after normalize'
);
});

276
library/select2/tests/data/tags-tests.js vendored Normal file
View File

@@ -0,0 +1,276 @@
module('Data adapters - Tags');
var SelectData = require('select2/data/select');
var Tags = require('select2/data/tags');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var SelectTags = Utils.Decorate(SelectData, Tags);
var options = new Options({
tags: true
});
test('does not trigger on blank or null terms', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: ''
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
data.query({
term: null
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
});
test('white space is trimmed by default', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: ' '
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
data.query({
term: ' One '
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
});
test('does not create option if text is same but lowercase', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'one'
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
});
test('does not trigger for additional pages', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
page: 2
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'One');
assert.equal(item.text, 'One');
});
});
test('creates tag at beginning', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'o'
}, function (data) {
assert.equal(data.results.length, 2);
var first = data.results[0];
assert.equal(first.id, 'o');
assert.equal(first.text, 'o');
});
});
test('tags can be the only result', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'test'
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'test');
assert.equal(item.text, 'test');
});
});
test('tags are injected as options', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'test'
}, function (data) {
assert.equal(data.results.length, 1);
var $children = $('#qunit-fixture .single option');
assert.equal($children.length, 2);
var $tag = $children.last();
assert.equal($tag.val(), 'test');
assert.equal($tag.text(), 'test');
});
});
test('old tags are removed automatically', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'first'
}, function (data) {
assert.equal(data.results.length, 1);
var $children = $('#qunit-fixture .single option');
assert.equal($children.length, 2);
});
data.query({
term: 'second'
}, function (data) {
assert.equal(data.results.length, 1);
var $children = $('#qunit-fixture .single option');
assert.equal($children.length, 2);
var $tag = $children.last();
assert.equal($tag.val(), 'second');
assert.equal($tag.text(), 'second');
});
});
test('insertTag controls the tag location', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.insertTag = function (data, tag) {
data.push(tag);
};
data.query({
term: 'o'
}, function (data) {
assert.equal(data.results.length, 2);
var item = data.results[1];
assert.equal(item.id, 'o');
assert.equal(item.text, 'o');
});
});
test('insertTag can be controlled through the options', function (assert) {
var options = new Options({
insertTag: function (data, tag) {
data.push(tag);
}
});
var data = new SelectTags($('#qunit-fixture .single'), options);
data.query({
term: 'o'
}, function (data) {
assert.equal(data.results.length, 2);
var item = data.results[1];
assert.equal(item.id, 'o');
assert.equal(item.text, 'o');
});
});
test('createTag controls the tag object', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.createTag = function (params) {
return {
id: 0,
text: params.term
};
};
data.query({
term: 'test'
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 0);
assert.equal(item.text, 'test');
});
});
test('createTag returns null for no tag', function (assert) {
var data = new SelectTags($('#qunit-fixture .single'), options);
data.createTag = function (params) {
return null;
};
data.query({
term: 'o'
}, function (data) {
assert.equal(data.results.length, 1);
});
});
test('the createTag options customizes the function', function (assert) {
var data = new SelectTags(
$('#qunit-fixture .single'),
new Options({
tags: true,
createTag: function (params) {
return {
id: params.term,
text: params.term,
tag: true
};
}
})
);
data.query({
term: 'test'
}, function (data) {
assert.equal(data.results.length, 1);
var item = data.results[0];
assert.equal(item.id, 'test');
assert.equal(item.text, 'test');
assert.equal(item.tag, true);
});
});

View File

@@ -0,0 +1,219 @@
module('Data adaptor - Tokenizer');
test('triggers the select event', function (assert) {
assert.expect(2);
var SelectData = require('select2/data/select');
var Tokenizer = require('select2/data/tokenizer');
var Tags = require('select2/data/tags');
var Options = require('select2/options');
var Utils = require('select2/utils');
var $ = require('jquery');
var TokenizedSelect = Utils.Decorate(
Utils.Decorate(SelectData, Tags),
Tokenizer
);
var $select = $('#qunit-fixture .single');
var options = new Options({
tags: true,
tokenSeparators: [',']
});
var container = new MockContainer();
container.dropdown = container.selection = {};
var $container = $('<div></div>');
var data = new TokenizedSelect($select, options);
data.bind(container, $container);
data.on('select', function () {
assert.ok(true, 'The select event should be triggered');
});
data.query({
term: 'first,second'
}, function () {
assert.ok(true, 'The callback should have succeeded');
});
});
test('createTag can return null', function (assert) {
assert.expect(3);
var SelectData = require('select2/data/select');
var Tokenizer = require('select2/data/tokenizer');
var Tags = require('select2/data/tags');
var Options = require('select2/options');
var Utils = require('select2/utils');
var $ = require('jquery');
var TokenizedSelect = Utils.Decorate(
Utils.Decorate(SelectData, Tags),
Tokenizer
);
var $select = $('#qunit-fixture .single');
var options = new Options({
tags: true,
tokenSeparators: [','],
createTag: function () {
assert.ok(true, 'createTag should have been called');
return null;
}
});
var container = new MockContainer();
container.dropdown = container.selection = {};
var $container = $('<div></div>');
var data = new TokenizedSelect($select, options);
data.bind(container, $container);
data.on('select', function (params) {
if (params.data == null) {
assert.ok(false, 'Null data should never be selected');
}
});
data.query({
term: 'first,second'
}, function () {
assert.ok(true, 'The callback should have succeeded');
});
});
test('createTag returning null does not cut the term', function (assert) {
assert.expect(4);
var SelectData = require('select2/data/select');
var Tokenizer = require('select2/data/tokenizer');
var Tags = require('select2/data/tags');
var Options = require('select2/options');
var Utils = require('select2/utils');
var $ = require('jquery');
var TokenizedSelect = Utils.Decorate(
Utils.Decorate(SelectData, Tags),
Tokenizer
);
var $select = $('#qunit-fixture .single');
var options = new Options({
tags: true,
tokenSeparators: [',', '"'],
createTag: function (params) {
var term = params.term;
// Ignore blanks
if (term.length === 0) {
return null;
}
// Ignore the leading quote
if (term === '"') {
return null;
}
// If there is a leading quote, check for a second one
if (term[0] === '"' && term[term.length - 1] !== '"') {
return null;
}
var text = term.substr(1, term.length - 2);
return {
id: term,
text: text
};
}
});
var container = new MockContainer();
container.dropdown = container.selection = {};
var $container = $('<div></div>');
var data = new TokenizedSelect($select, options);
data.bind(container, $container);
data.on('select', function (params) {
assert.ok(params.data, 'Data should not be null');
assert.equal(
params.data.id,
'"first, second"',
'The id should have the quotes'
);
assert.equal(
params.data.text,
'first, second',
'The text should not have the quotes'
);
});
data.query({
term: '"first, second",abc'
}, function () {
assert.ok(true, 'The callback should have succeeded');
});
});
test('works with multiple tokens given', function (assert) {
assert.expect(4);
var SelectData = require('select2/data/select');
var Tokenizer = require('select2/data/tokenizer');
var Tags = require('select2/data/tags');
var Options = require('select2/options');
var Utils = require('select2/utils');
var $ = require('jquery');
var TokenizedSelect = Utils.Decorate(
Utils.Decorate(SelectData, Tags),
Tokenizer
);
var $select = $('#qunit-fixture .multiple');
var options = new Options({
tags: true,
tokenSeparators: [',']
});
var container = new MockContainer();
container.dropdown = container.selection = {};
var $container = $('<div></div>');
var data = new TokenizedSelect($select, options);
data.bind(container, $container);
data.on('select', function () {
assert.ok(true, 'The select event should be triggered');
});
data.query({
term: 'first,second,third'
}, function () {
assert.ok(true, 'The callback should have succeeded');
});
assert.equal(
$select.children('option').length,
3,
'The two new tags should have been created'
);
});

View File

@@ -0,0 +1,104 @@
module('Dropdown - dropdownCssClass compatibility');
var $ = require('jquery');
var Utils = require('select2/utils');
var Options = require('select2/options');
var Dropdown = require('select2/dropdown');
var DropdownCSS = Utils.Decorate(
Dropdown,
require('select2/compat/dropdownCss')
);
test('all classes will be copied if :all: is used', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
dropdownCssClass: ':all:'
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok($dropdown.hasClass('test'));
assert.ok($dropdown.hasClass('copy'));
assert.ok($dropdown.hasClass('works'));
assert.ok(!$dropdown.hasClass(':all:'));
});
test(':all: can be used with other classes', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
dropdownCssClass: ':all: other'
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok($dropdown.hasClass('test'));
assert.ok($dropdown.hasClass('copy'));
assert.ok($dropdown.hasClass('works'));
assert.ok($dropdown.hasClass('other'));
assert.ok(!$dropdown.hasClass(':all:'));
});
test('classes can be passed in as a string', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
dropdownCssClass: 'other'
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok($dropdown.hasClass('other'));
});
test('a function can be used based on the element', function (assert){
var $element = $('<select class="test"></select>');
var options = new Options({
dropdownCssClass: function ($element) {
return 'function';
}
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok($dropdown.hasClass('function'));
assert.ok(!$dropdown.hasClass('test'));
});
test(':all: works around custom adapters', function (assert) {
var $element = $('<select class="test"></select>');
var options = new Options({
dropdownCssClass: ':all: something',
adaptDropdownCssClass: function (clazz) {
return clazz + '-modified';
}
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok($dropdown.hasClass('something'));
assert.ok($dropdown.hasClass('test'));
assert.ok($dropdown.hasClass('test-modified'));
});
module('Dropdown - adaptDropdownCss compatibility');
test('only return when adapted', function (assert) {
var $element = $('<select class="original"></select>');
var options = new Options({
adaptDropdownCssClass: function (clazz) {
return 'modified';
}
});
var select = new DropdownCSS($element, options);
var $dropdown = select.render();
assert.ok(!$dropdown.hasClass('original'));
assert.ok($dropdown.hasClass('modified'));
});

View File

@@ -0,0 +1,177 @@
module('Dropdown - attachBody - positioning');
test('appends to the dropdown parent', function (assert) {
assert.expect(4);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Dropdown = require('select2/dropdown');
var AttachBody = require('select2/dropdown/attachBody');
var DropdownAdapter = Utils.Decorate(Dropdown, AttachBody);
var dropdown = new DropdownAdapter($select, new Options({
dropdownParent: $parent
}));
assert.equal(
$parent.children().length,
1,
'Only the select should be in the container'
);
var $dropdown = dropdown.render();
dropdown.bind(container, $container);
dropdown.position($dropdown, $container);
assert.equal(
$parent.children().length,
1,
'The dropdown should not be placed until after it is opened'
);
dropdown._showDropdown();
assert.equal(
$parent.children().length,
2,
'The dropdown should now be in the container as well'
);
assert.ok(
$.contains($parent[0], $dropdown[0]),
'The dropdown should be contained within the parent container'
);
});
test('dropdown is positioned down with static margins', function (assert) {
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
$parent.css({
position: 'static',
marginTop: '5px',
marginLeft: '10px'
});
var $container = $('<span>test</span>');
var container = new MockContainer();
$('#qunit-fixture').empty();
$parent.appendTo($('#qunit-fixture'));
$container.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Dropdown = require('select2/dropdown');
var AttachBody = require('select2/dropdown/attachBody');
var DropdownAdapter = Utils.Decorate(Dropdown, AttachBody);
var dropdown = new DropdownAdapter($select, new Options({
dropdownParent: $parent
}));
var $dropdown = dropdown.render();
assert.equal(
$dropdown[0].style.top,
0,
'The drodpown should not have any offset before it is displayed'
);
dropdown.bind(container, $container);
dropdown.position($dropdown, $container);
dropdown._showDropdown();
assert.ok(
dropdown.$dropdown.hasClass('select2-dropdown--below'),
'The dropdown should be forced down'
);
assert.equal(
$dropdown.css('top').substring(0, 2),
$container.outerHeight() + 5,
'The offset should be 5px at the top'
);
assert.equal(
$dropdown.css('left'),
'10px',
'The offset should be 10px on the left'
);
});
test('dropdown is positioned down with absolute offsets', function (assert) {
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
$parent.css({
position: 'absolute',
top: '10px',
left: '5px'
});
var $container = $('<span>test</span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$container.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Dropdown = require('select2/dropdown');
var AttachBody = require('select2/dropdown/attachBody');
var DropdownAdapter = Utils.Decorate(Dropdown, AttachBody);
var dropdown = new DropdownAdapter($select, new Options({
dropdownParent: $parent
}));
var $dropdown = dropdown.render();
assert.equal(
$dropdown[0].style.top,
0,
'The drodpown should not have any offset before it is displayed'
);
dropdown.bind(container, $container);
dropdown.position($dropdown, $container);
dropdown._showDropdown();
assert.ok(
dropdown.$dropdown.hasClass('select2-dropdown--below'),
'The dropdown should be forced down'
);
assert.equal(
$dropdown.css('top').substring(0, 2),
$container.outerHeight(),
'There should not be an extra top offset'
);
assert.equal(
$dropdown.css('left'),
'0px',
'There should not be an extra left offset'
);
});

View File

@@ -0,0 +1,137 @@
module('Dropdown - selectOnClose');
var $ = require('jquery');
var Utils = require('select2/utils');
var Options = require('select2/options');
var SelectData = require('select2/data/select');
var Results = require('select2/results');
var SelectOnClose = require('select2/dropdown/selectOnClose');
var ModifiedResults = Utils.Decorate(Results, SelectOnClose);
var options = new Options({
selectOnClose: true
});
test('will not trigger if no results were given', function (assert) {
assert.expect(0);
var $element = $('<select></select>');
var select = new ModifiedResults($element, options, new SelectData($element));
var $dropdown = select.render();
var container = new MockContainer();
select.bind(container, $('<div></div>'));
select.on('select', function () {
assert.ok(false, 'The select event should not have been triggered');
});
container.trigger('close');
});
test('will not trigger if the results list is empty', function (assert) {
assert.expect(1);
var $element = $('<select></select>');
var select = new ModifiedResults($element, options, new SelectData($element));
var $dropdown = select.render();
var container = new MockContainer();
select.bind(container, $('<div></div>'));
select.on('select', function () {
assert.ok(false, 'The select event should not have been triggered');
});
select.append({
results: []
});
assert.equal(
$dropdown.find('li').length,
0,
'There should not be any results in the dropdown'
);
container.trigger('close');
});
test('will not trigger if no results here highlighted', function (assert) {
assert.expect(2);
var $element = $('<select></select>');
var select = new ModifiedResults($element, options, new SelectData($element));
var $dropdown = select.render();
var container = new MockContainer();
select.bind(container, $('<div></div>'));
select.on('select', function () {
assert.ok(false, 'The select event should not have been triggered');
});
select.append({
results: [
{
id: '1',
text: 'Test'
}
]
});
assert.equal(
$dropdown.find('li').length,
1,
'There should be one result in the dropdown'
);
assert.equal(
$.trim($dropdown.find('li').text()),
'Test',
'The result should be the same as the one we appended'
);
container.trigger('close');
});
test('will trigger if there is a highlighted result', function (assert) {
assert.expect(2);
var $element = $('<select></select>');
var select = new ModifiedResults($element, options, new SelectData($element));
var $dropdown = select.render();
var container = new MockContainer();
select.bind(container, $('<div></div>'));
select.on('select', function () {
assert.ok(true, 'The select event should have been triggered');
});
select.append({
results: [
{
id: '1',
text: 'Test'
}
]
});
assert.equal(
$dropdown.find('li').length,
1,
'There should be one result in the dropdown'
);
$dropdown.find('li').addClass('select2-results__option--highlighted');
container.trigger('close');
});

View File

@@ -0,0 +1,33 @@
module('Dropdown - Stoping event propagation');
var Dropdown = require('select2/dropdown');
var StopPropagation = require('select2/dropdown/stopPropagation');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var CustomDropdown = Utils.Decorate(Dropdown, StopPropagation);
var options = new Options();
test('click event does not propagate', function (assert) {
assert.expect(1);
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var dropdown = new CustomDropdown($('#qunit-fixture select'), options);
var $dropdown = dropdown.render();
dropdown.bind(container, $container);
$container.append($dropdown);
$container.on('click', function () {
assert.ok(false, 'The click event should have been stopped');
});
$dropdown.trigger('click');
assert.ok(true, 'Something went wrong if this failed');
});

46
library/select2/tests/helpers.js vendored Normal file
View File

@@ -0,0 +1,46 @@
// Restore the require/define
var require = $.fn.select2.amd.require;
var define = $.fn.select2.amd.define;
// Disable jQuery's binding to $
jQuery.noConflict();
var Utils = require('select2/utils');
function MockContainer () {
MockContainer.__super__.constructor.call(this);
}
Utils.Extend(MockContainer, Utils.Observable);
MockContainer.prototype.isOpen = function () {
return this.isOpen;
};
var log = [];
var testName;
QUnit.done(function (test_results) {
var tests = [];
for(var i = 0, len = log.length; i < len; i++) {
var details = log[i];
tests.push({
name: details.name,
result: details.result,
expected: details.expected,
actual: details.actual,
source: details.source
});
}
test_results.tests = tests;
window.global_test_results = test_results;
});
QUnit.testStart(function(testDetails){
QUnit.log(function(details){
if (!details.result) {
details.name = testDetails.name;
log.push(details);
}
});
});

View File

@@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="vendor/qunit-1.23.1.css" type="text/css" />
<link rel="stylesheet" href="../../dist/css/select2.css" type="text/css" />
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
<script src="vendor/qunit-1.23.1.js" type="text/javascript"></script>
<script src="vendor/jquery-1.7.2.js" type="text/javascript"></script>
<script src="../dist/js/select2.full.js" type="text/javascript"></script>
<script src="helpers.js" type="text/javascript"></script>
<script src="integration/dom-changes.js" type="text/javascript"></script>
<script src="integration/jquery-calls.js" type="text/javascript"></script>
<script src="integration/select2-methods.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -0,0 +1,257 @@
module('DOM integration');
test('adding a new unselected option changes nothing', function (assert) {
// Any browsers which support mutation observers will not trigger the event
var expected = 4;
if (window.MutationObserver) {
expected = 2;
} else if (!window.addEventListener) {
expected = 2;
}
assert.expect(expected);
var asyncDone = null;
var syncDone = assert.async();
if (expected != 2) {
asyncDone = assert.async();
}
var $ = require('jquery');
var Options = require('select2/options');
var Select2 = require('select2/core');
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'</select>'
);
$('#qunit-fixture').append($select);
var select = new Select2($select);
select.on('selection:update', function (args) {
assert.equal(
args.data.length,
1,
'There was more than one selection'
);
assert.equal(
args.data[0].id,
'One',
'The selection changed to something other than One'
);
if (expected != 2) {
asyncDone();
}
});
assert.equal(
$select.val(),
'One'
);
var $option = $('<option>Three</option>');
$select.append($option);
assert.equal(
$select.val(),
'One'
);
syncDone();
});
test('adding a new selected option changes the value', function (assert) {
// handle IE 8 not being supported
var expected = 4;
if (!window.MutationObserver && !window.addEventListener) {
expected = 2;
}
assert.expect(expected);
var asyncDone = null;
var syncDone = assert.async();
if (expected != 2) {
asyncDone = assert.async();
}
var $ = require('jquery');
var Options = require('select2/options');
var Select2 = require('select2/core');
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'</select>'
);
$('#qunit-fixture').append($select);
var select = new Select2($select);
select.on('selection:update', function (args) {
assert.equal(
args.data.length,
1,
'There was more than one selection'
);
assert.equal(
args.data[0].id,
'Three',
'The selection did not change to Three'
);
if (expected != 2) {
asyncDone();
}
});
assert.equal(
$select.val(),
'One'
);
var $option = $('<option selected>Three</option>');
$select.append($option);
assert.equal(
$select.val(),
'Three'
);
syncDone();
});
test('removing an unselected option changes nothing', function (assert) {
// Any browsers which support mutation observers will not trigger the event
var expected = 4;
if (!window.MutationObserver && !window.addEventListener) {
expected = 2;
}
assert.expect(expected);
var asyncDone = null;
var syncDone = assert.async();
if (expected != 2) {
asyncDone = assert.async();
}
var $ = require('jquery');
var Options = require('select2/options');
var Select2 = require('select2/core');
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'</select>'
);
$('#qunit-fixture').append($select);
var select = new Select2($select);
select.on('selection:update', function (args) {
assert.equal(
args.data.length,
1,
'There was more than one selection'
);
assert.equal(
args.data[0].id,
'One',
'The selection changed to something other than One'
);
if (expected != 2) {
asyncDone();
}
});
assert.equal(
$select.val(),
'One'
);
$select.children().eq(1).remove();
assert.equal(
$select.val(),
'One'
);
syncDone();
});
test('removing a selected option changes the value', function (assert) {
// handle IE 8 not being supported
var expected = 3;
if (!window.MutationObserver && !window.addEventListener) {
expected = 2;
}
assert.expect(expected);
var asyncDone = null;
var syncDone = assert.async();
if (expected != 2) {
asyncDone = assert.async();
}
var $ = require('jquery');
var Options = require('select2/options');
var Select2 = require('select2/core');
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'</select>'
);
$('#qunit-fixture').append($select);
var select = new Select2($select);
select.on('selection:update', function (args) {
assert.equal(
args.data.length,
1,
'There was more than one selection'
);
if (expected != 2) {
asyncDone();
}
});
assert.equal(
$select.val(),
'One'
);
$select.children().eq(0).remove();
assert.equal(
$select.val(),
'Two'
);
syncDone();
});

View File

@@ -0,0 +1,98 @@
module('select2(val)');
var Utils = require('select2/utils');
test('multiple elements with arguments works', function (assert) {
var $ = require('jquery');
require('jquery.select2');
var $first = $(
'<select>' +
'<option>1</option>' +
'<option>2</option>' +
'</select>'
);
var $second = $first.clone();
var $both = $first.add($second);
$both.select2();
$both.select2('val', '2');
assert.equal(
$first.val(),
'2',
'The call should change the value on the first element'
);
assert.equal(
$second.val(),
'2',
'The call should also change the value on the second element'
);
});
test('initializes when jQuery $.data contains' +
' cyclic reference', function (assert) {
var $ = require('jquery');
require('jquery.select2');
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
// Add a circular reference object using jQuery.
var recursiveObject = {};
recursiveObject.same = recursiveObject;
$select.data('same', recursiveObject);
$select.select2();
assert.equal(
$select.val(),
'3',
'The option value should be pulled correctly'
);
});
test('$element.data returns instance and options correctly',
function (assert) {
var $ = require('jquery');
require('jquery.select2');
var $select = $(
'<select>' +
'<option value="1">One</option>' +
'<option value="2">Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
// Initialize.
$select.select2({maximumSelectionLength: 2, multiple: true});
assert.equal(
$select.val(),
'3',
'Only 1 option should be pulled.'
);
// Try to resolve instance via .data('select2').
var $instance = $select.data('select2');
assert.ok($instance);
assert.ok($instance.options);
// Ensure $select.data('select2') is the same instance
// created by .select2()
assert.equal($instance, Utils.GetData($instance.$element[0],
'select2'));
// Ensure initialized property matches.
assert.equal($instance.options.options.maximumSelectionLength,
2);
});

View File

@@ -0,0 +1,139 @@
module('select2(data)');
var $ = require('jquery');
var Select2 = require('select2/core');
var Options = require('select2/options');
test('single default selection returned', function (assert) {
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
var options = new Options({});
var select = new Select2($select, options);
var items = select.data();
assert.equal(
items.length,
1,
'The one selected item should be returned'
);
var first = items[0];
assert.equal(
first.id,
'3',
'The first option was correct'
);
assert.equal(
first.text,
'Three',
'The first option was correct'
);
});
test('multiple default selections returned', function (assert) {
var $select = $(
'<select multiple>' +
'<option selected>One</option>' +
'<option>Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
var options = new Options({});
var select = new Select2($select, options);
var items = select.data();
assert.equal(
items.length,
2,
'The two selected items should be returned'
);
var first = items[0];
assert.equal(
first.id,
'One',
'The first option was correct'
);
var second = items[1];
assert.equal(
second.id,
'3',
'The option value should be pulled correctly'
);
});
module('select2(val)');
test('single value matches jquery value', function (assert) {
var $select = $(
'<select>' +
'<option>One</option>' +
'<option>Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
var options = new Options({});
var select = new Select2($select, options);
var value = select.val();
assert.equal(
value,
'3',
'The value should match the option tag attribute'
);
assert.equal(
value,
$select.val(),
'The value should match the jquery value'
);
});
test('multiple value matches the jquery value', function (assert) {
var $select = $(
'<select multiple>' +
'<option selected>One</option>' +
'<option>Two</option>' +
'<option value="3" selected>Three</option>' +
'</select>'
);
var options = new Options({});
var select = new Select2($select, options);
var value = select.val();
assert.equal(
value.length,
2,
'Two options should be selected'
);
assert.deepEqual(
value,
['One', '3'],
'The values should match the option tag attribute'
);
assert.deepEqual(
value,
$select.val(),
'The values should match the jquery values'
);
});

View File

@@ -0,0 +1,50 @@
module('Defaults - Ajax');
test('options are merged recursively with default options', function (assert) {
var defaults = require('select2/defaults');
var ajaxDelay = 250;
var ajaxUrl = 'http://www.test.com';
var mergedOptions;
defaults.set('ajax--delay', ajaxDelay);
mergedOptions = defaults.apply({
ajax: {
url: ajaxUrl
}
});
assert.equal(
mergedOptions.ajax.delay,
ajaxDelay,
'Ajax default options are present on the merged options'
);
assert.equal(
mergedOptions.ajax.url,
ajaxUrl,
'Ajax provided options are present on the merged options'
);
defaults.reset();
});
test('more than one default option can be changed via set()', function(assert) {
var defaults = require('select2/defaults');
var ajaxDelay = 123;
var dataDataType = 'xml';
defaults.set('ajax--delay', ajaxDelay);
defaults.set('ajax--data-type', dataDataType);
assert.equal(
defaults.defaults.ajax.delay,
ajaxDelay,
'Both ajax.delay and ajax.dataType present in defaults');
assert.equal(
defaults.defaults.ajax.dataType,
dataDataType,
'Both ajax.delay and ajax.dataType present in defaults');
defaults.reset();
});

View File

@@ -0,0 +1,44 @@
module('Options - Attributes');
var $ = require('jquery');
var Options = require('select2/options');
test('no nesting', function (assert) {
var $test = $('<select data-test="test"></select>');
var options = new Options({}, $test);
assert.equal(options.get('test'), 'test');
});
test('with nesting', function (assert) {
var $test = $('<select data-first--second="test"></select>');
if ($test[0].dataset == null) {
assert.ok(
true,
'We can not run this test with jQuery 1.x if dataset is not implemented'
);
return;
}
var options = new Options({}, $test);
assert.ok(!(options.get('first-Second')));
assert.equal(options.get('first').second, 'test');
});
test('overrides initialized data', function (assert) {
var $test = $('<select data-override="yes" data-data="yes"></select>');
var options = new Options({
options: 'yes',
override: 'no'
}, $test);
assert.equal(options.get('options'), 'yes');
assert.equal(options.get('override'), 'yes');
assert.equal(options.get('data'), 'yes');
});

View File

@@ -0,0 +1,250 @@
module('Options - Deprecated - initSelection');
var $ = require('jquery');
var Options = require('select2/options');
test('converted into dataAdapter.current', function (assert) {
assert.expect(5);
var $test = $('<select></select>');
var called = false;
var options = new Options({
initSelection: function ($element, callback) {
called = true;
callback([{
id: '1',
text: '2'
}]);
}
}, $test);
assert.ok(!called, 'initSelection should not have been called');
var DataAdapter = options.get('dataAdapter');
var data = new DataAdapter($test, options);
data.current(function (data) {
assert.equal(
data.length,
1,
'There should have only been one object selected'
);
var item = data[0];
assert.equal(
item.id,
'1',
'The id should have been set by initSelection'
);
assert.equal(
item.text,
'2',
'The text should have been set by initSelection'
);
});
assert.ok(called, 'initSelection should have been called');
});
test('single option converted to array automatically', function (assert) {
assert.expect(2);
var $test = $('<select></select>');
var called = false;
var options = new Options({
initSelection: function ($element, callback) {
called = true;
callback({
id: '1',
text: '2'
});
}
}, $test);
var DataAdapter = options.get('dataAdapter');
var data = new DataAdapter($test, options);
data.current(function (data) {
assert.ok(
$.isArray(data),
'The data should have been converted to an array'
);
});
assert.ok(called, 'initSelection should have been called');
});
test('only called once', function (assert) {
assert.expect(8);
var $test = $('<select><option value="3" selected>4</option></select>');
var called = 0;
var options = new Options({
initSelection: function ($element, callback) {
called++;
callback([{
id: '1',
text: '2'
}]);
}
}, $test);
var DataAdapter = options.get('dataAdapter');
var data = new DataAdapter($test, options);
data.current(function (data) {
assert.equal(
data.length,
1,
'There should have only been a single option'
);
var item = data[0];
assert.equal(
item.id,
'1',
'The id should match the one given by initSelection'
);
assert.equal(
item.text,
'2',
'The text should match the one given by initSelection'
);
});
assert.equal(
called,
1,
'initSelection should have been called'
);
data.current(function (data) {
assert.equal(
data.length,
1,
'There should have only been a single option'
);
var item = data[0];
assert.equal(
item.id,
'3',
'The id should match the value given in the DOM'
);
assert.equal(
item.text,
'4',
'The text should match the text given in the DOM'
);
});
assert.equal(
called,
1,
'initSelection should have only been called once'
);
});
module('Options - Deprecated - query');
test('converted into dataAdapter.query automatically', function (assert) {
assert.expect(6);
var $test = $('<select></select>');
var called = false;
var options = new Options({
query: function (params) {
called = true;
params.callback({
results: [
{
id: 'test',
text: params.term
}
]
});
}
}, $test);
assert.ok(!called, 'The query option should not have been called');
var DataAdapter = options.get('dataAdapter');
var data = new DataAdapter($test, options);
data.query({
term: 'term'
}, function (data) {
assert.ok(
'results' in data,
'It should have included the results key'
);
assert.equal(
data.results.length,
1,
'There should have only been a single result returned'
);
var item = data.results[0];
assert.equal(
item.id,
'test',
'The id should have been returned from the query function'
);
assert.equal(
item.text,
'term',
'The text should have matched the term that was passed in'
);
});
assert.ok(called, 'The query function should have been called');
});
module('Options - deprecated - data-ajax-url');
test('converted ajax-url to ajax--url automatically', function (assert) {
var $test = $('<select data-ajax-url="test://url"></select>');
var options = new Options({}, $test);
assert.ok(
options.get('ajax'),
'The `ajax` key was automatically created'
);
assert.equal(
options.get('ajax').url,
'test://url',
'The `url` property for the `ajax` option was filled in correctly'
);
});
test('converted select2-tags to data/tags automatically', function (assert) {
var $test = $('<select data-select2-tags="original data"></select>');
var options = new Options({}, $test);
assert.ok(
options.get('tags'),
'The `tags` key is automatically set to true'
);
assert.equal(
options.get('data'),
'original data',
'The `data` key is created with the original data'
);
});

View File

@@ -0,0 +1,28 @@
module('Options - Translations');
var $ = require('jquery');
var Options = require('select2/options');
test('partial dictionaries can be passed', function (assert) {
var options = new Options({
language: {
searching: function () {
return 'Something';
}
}
});
var translations = options.get('translations');
assert.equal(
translations.get('searching')(),
'Something',
'The partial dictionary still overrides translations'
);
assert.equal(
translations.get('noResults')(),
'No results found',
'You can still get English translations for keys not passed in'
);
});

View File

@@ -0,0 +1,66 @@
module('Options - Width');
var $ = require('jquery');
var Select2 = require('select2/core');
var select = new Select2($('<select></select>'));
test('string passed as width', function (assert) {
var $test = $('<select></select>');
var width = select._resolveWidth($test, '80%');
assert.equal(width, '80%');
});
test('width from style attribute', function (assert) {
var $test = $('<select style="width: 50%;"></selct>');
var width = select._resolveWidth($test, 'style');
assert.equal(width, '50%');
});
test('width from style returns null if nothing is found', function (assert) {
var $test = $('<select></selct>');
var width = select._resolveWidth($test, 'style');
assert.equal(width, null);
});
test('width from computed element width', function (assert) {
var $style = $(
'<style type="text/css">.css-set-width { width: 500px; }</style>'
);
var $test = $('<select class="css-set-width"></select>');
$('#qunit-fixture').append($style);
$('#qunit-fixture').append($test);
var width = select._resolveWidth($test, 'element');
assert.equal(width, '500px');
});
test('resolve gets the style if it is there', function (assert) {
var $test = $('<select style="width: 20%;"></selct>');
var width = select._resolveWidth($test, 'resolve');
assert.equal(width, '20%');
});
test('resolve falls back to element if there is no style', function (assert) {
var $style = $(
'<style type="text/css">.css-set-width { width: 500px; }</style>'
);
var $test = $('<select class="css-set-width"></select>');
$('#qunit-fixture').append($style);
$('#qunit-fixture').append($test);
var width = select._resolveWidth($test, 'resolve');
assert.equal(width, '500px');
});

View File

@@ -0,0 +1,241 @@
module('Results - highlighting results');
test('results:all with no data skips results:focus', function (assert) {
assert.expect(0);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Results = require('select2/results');
var results = new Results($select, new Options({}));
// Fake the data adapter for the `setClasses` method
results.data = {};
results.data.current = function (callback) {
callback([{ id: 'test' }]);
};
results.render();
results.bind(container, $container);
results.on('results:focus', function (params) {
assert.ok(false, 'The results:focus event was triggered');
});
container.trigger('results:all', {
data: {
results: []
}
});
});
test('results:all triggers results:focus on the first item', function (assert) {
assert.expect(2);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Results = require('select2/results');
var results = new Results($select, new Options({}));
// Fake the data adapter for the `setClasses` method
results.data = {};
results.data.current = function (callback) {
callback([{ id: 'test' }]);
};
results.render();
results.bind(container, $container);
results.on('results:focus', function (params) {
assert.equal(params.data.id, 'test');
assert.equal(params.data.text, 'Test');
});
container.trigger('results:all', {
data: {
results: [
{
id: 'test',
text: 'Test'
}
]
}
});
});
test('results:append does not trigger results:focus', function (assert) {
assert.expect(0);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Results = require('select2/results');
var results = new Results($select, new Options({}));
// Fake the data adapter for the `setClasses` method
results.data = {};
results.data.current = function (callback) {
callback([{ id: 'test' }]);
};
results.render();
results.bind(container, $container);
results.on('results:focus', function () {
assert.ok(false, 'The results:focus event was triggered');
});
container.trigger('results:append', {
data: {
results: [
{
id: 'test',
text: 'Test'
}
]
}
});
});
test('scrollAfterSelect triggers results:focus', function (assert) {
assert.expect(3);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Results = require('select2/results');
var options = new Options({ scrollAfterSelect: true });
var results = new Results($select, options);
// Fake the data adapter for the `setClasses` method
results.data = {};
results.data.current = function (callback) {
callback([{ id: 'test' }]);
};
results.render();
results.bind(container, $container);
// check that default for scrollAfterSelect is true
assert.equal(options.get('scrollAfterSelect'), true);
results.append({
results: [
{
id: 'test',
text: 'Test'
}
]
});
results.on('results:focus', function (params) {
assert.equal(params.data.id, 'test');
assert.equal(params.data.text, 'Test');
});
container.trigger('select', {});
});
test('!scrollAfterSelect does not trigger results:focus', function (assert) {
assert.expect(1);
var $ = require('jquery');
var $select = $('<select></select>');
var $parent = $('<div></div>');
var $container = $('<span></span>');
var container = new MockContainer();
$parent.appendTo($('#qunit-fixture'));
$select.appendTo($parent);
var Utils = require('select2/utils');
var Options = require('select2/options');
var Results = require('select2/results');
var options = new Options({ scrollAfterSelect: false });
var results = new Results($select, options);
// Fake the data adapter for the `setClasses` method
results.data = {};
results.data.current = function (callback) {
callback([{ id: 'test' }]);
};
results.render();
results.bind(container, $container);
// check that default for scrollAfterSelect is false
assert.equal(options.get('scrollAfterSelect'), false);
results.append({
results: [
{
id: 'test',
text: 'Test'
}
]
});
results.on('results:focus', function () {
assert.ok(false, 'The results:focus event was triggered');
});
container.trigger('select', {});
});

View File

@@ -0,0 +1,330 @@
module('Selection containers - Placeholders - Allow clear');
var Placeholder = require('select2/selection/placeholder');
var AllowClear = require('select2/selection/allowClear');
var SingleSelection = require('select2/selection/single');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var AllowClearPlaceholder = Utils.Decorate(
Utils.Decorate(SingleSelection, Placeholder),
AllowClear
);
var allowClearOptions = new Options({
placeholder: {
id: 'placeholder',
text: 'This is the placeholder'
},
allowClear: true
});
test('clear is not displayed for single placeholder', function (assert) {
var selection = new AllowClearPlaceholder(
$('#qunit-fixture .single-with-placeholder'),
allowClearOptions
);
var $selection = selection.render();
selection.update([{
id: 'placeholder'
}]);
assert.equal(
$selection.find('.select2-selection__clear').length,
0,
'The clear icon should not be displayed'
);
});
test('clear is not displayed for multiple placeholder', function (assert) {
var selection = new AllowClearPlaceholder(
$('#qunit-fixture .multiple'),
allowClearOptions
);
var $selection = selection.render();
selection.update([]);
assert.equal(
$selection.find('.select2-selection__clear').length,
0,
'The clear icon should not be displayed'
);
});
test('clear is displayed for placeholder', function (assert) {
var selection = new AllowClearPlaceholder(
$('#qunit-fixture .single-with-placeholder'),
allowClearOptions
);
var $selection = selection.render();
selection.update([{
id: 'one',
test: 'one'
}]);
assert.equal(
$selection.find('.select2-selection__clear').length,
1,
'The clear icon should be displayed'
);
});
test('clear icon should have title displayed', function (assert) {
var selection = new AllowClearPlaceholder(
$('#qunit-fixture .single-with-placeholder'),
allowClearOptions
);
var $selection = selection.render();
selection.update([{
id: 'one',
test: 'one'
}]);
assert.equal(
$selection.find('.select2-selection__clear').attr('title'),
'Remove all items',
'The clear icon should have title displayed'
);
});
test('clicking clear will set the placeholder value', function (assert) {
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
$element.val('One');
selection.update([{
id: 'One',
text: 'One'
}]);
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
assert.equal(
$element.val(),
'placeholder',
'The value should have been reset to the placeholder'
);
});
test('clicking clear will trigger the unselect event', function (assert) {
assert.expect(4);
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
$element.val('One');
selection.update([{
id: 'One',
text: 'One'
}]);
selection.on('unselect', function (ev) {
assert.ok(
'data' in ev && ev.data,
'The event should have been triggered with the data property'
);
assert.ok(
$.isPlainObject(ev.data),
'The data should be an object'
);
assert.equal(
ev.data.id,
'One',
'The data should be the unselected object'
);
assert.equal(
$element.val(),
'placeholder',
'The previous value should be unselected'
);
});
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
});
test('preventing the unselect event cancels the clearing', function (assert) {
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
$element.val('One');
selection.update([{
id: 'One',
text: 'One'
}]);
selection.on('unselect', function (ev) {
ev.prevented = true;
});
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
assert.equal(
$element.val(),
'One',
'The placeholder should not have been set'
);
});
test('clicking clear will trigger the clear event', function (assert) {
assert.expect(5);
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
$element.val('One');
selection.update([{
id: 'One',
text: 'One'
}]);
selection.on('clear', function (ev) {
assert.ok(
'data' in ev && ev.data,
'The event should have been triggered with the data property'
);
assert.ok(
$.isArray(ev.data),
'The data should be an array'
);
assert.equal(
ev.data.length,
1,
'The data should contain one item for each value'
);
assert.equal(
ev.data[0].id,
'One',
'The data should contain unselected objects'
);
assert.equal(
$element.val(),
'placeholder',
'The previous value should be unselected'
);
});
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
});
test('preventing the clear event cancels the clearing', function (assert) {
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
$element.val('One');
selection.update([{
id: 'One',
text: 'One'
}]);
selection.on('clear', function (ev) {
ev.prevented = true;
});
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
assert.equal(
$element.val(),
'One',
'The placeholder should not have been set'
);
});
test('clear does not work when disabled', function (assert) {
var $element = $('#qunit-fixture .single-with-placeholder');
var selection = new AllowClearPlaceholder(
$element,
allowClearOptions
);
var container = new MockContainer();
var $selection = selection.render();
selection.bind(container, $('<div></div>'));
selection.update([{
id: 'One',
text: 'One'
}]);
$element.val('One');
selection.options.set('disabled', true);
var $remove = $selection.find('.select2-selection__clear');
$remove.trigger('mousedown');
assert.equal(
$element.val(),
'One',
'The placeholder should not have been set'
);
});

View File

@@ -0,0 +1,104 @@
module('Dropdown - containerCssClass compatibility');
var $ = require('jquery');
var Utils = require('select2/utils');
var Options = require('select2/options');
var SingleSelection = require('select2/selection/single');
var ContainerCSS = Utils.Decorate(
SingleSelection,
require('select2/compat/containerCss')
);
test('all classes will be copied if :all: is used', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
containerCssClass: ':all:'
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok($container.hasClass('test'));
assert.ok($container.hasClass('copy'));
assert.ok($container.hasClass('works'));
assert.ok(!$container.hasClass(':all:'));
});
test(':all: can be used with other classes', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
containerCssClass: ':all: other'
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok($container.hasClass('test'));
assert.ok($container.hasClass('copy'));
assert.ok($container.hasClass('works'));
assert.ok($container.hasClass('other'));
assert.ok(!$container.hasClass(':all:'));
});
test('classes can be passed in as a string', function (assert) {
var $element = $('<select class="test copy works"></select>');
var options = new Options({
containerCssClass: 'other'
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok($container.hasClass('other'));
});
test('a function can be used based on the element', function (assert){
var $element = $('<select class="test"></select>');
var options = new Options({
containerCssClass: function ($element) {
return 'function';
}
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok($container.hasClass('function'));
assert.ok(!$container.hasClass('test'));
});
test(':all: works around custom adapters', function (assert) {
var $element = $('<select class="test"></select>');
var options = new Options({
containerCssClass: ':all: something',
adaptContainerCssClass: function (clazz) {
return clazz + '-modified';
}
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok($container.hasClass('something'));
assert.ok($container.hasClass('test'));
assert.ok($container.hasClass('test-modified'));
});
module('Selection - adaptContainerCss compatibility');
test('only return when adapted', function (assert) {
var $element = $('<select class="original"></select>');
var options = new Options({
adaptContainerCssClass: function (clazz) {
return 'modified';
}
});
var select = new ContainerCSS($element, options);
var $container = select.render();
assert.ok(!$container.hasClass('original'));
assert.ok($container.hasClass('modified'));
});

View File

@@ -0,0 +1,151 @@
module('Selection containers - Multiple');
var MultipleSelection = require('select2/selection/multiple');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var options = new Options({});
test('display uses templateSelection', function (assert) {
var called = false;
var templateOptions = new Options({
templateSelection: function (data) {
called = true;
return data.text;
}
});
var selection = new MultipleSelection(
$('#qunit-fixture .multiple'),
templateOptions
);
var out = selection.display({
text: 'test'
});
assert.ok(called);
assert.equal(out, 'test');
});
test('templateSelection can addClass', function (assert) {
var called = false;
var templateOptions = new Options({
templateSelection: function (data, container) {
called = true;
container.addClass('testclass');
return data.text;
}
});
var selection = new MultipleSelection(
$('#qunit-fixture .multiple'),
templateOptions
);
var $container = selection.selectionContainer();
var out = selection.display({
text: 'test'
}, $container);
assert.ok(called);
assert.equal(out, 'test');
assert.ok($container.hasClass('testclass'));
});
test('empty update clears the selection', function (assert) {
var selection = new MultipleSelection(
$('#qunit-fixture .multiple'),
options
);
var $selection = selection.render();
var $rendered = $selection.find('.select2-selection__rendered');
$rendered.text('testing');
$rendered.attr('title', 'testing');
selection.update([]);
assert.equal($rendered.text(), '');
assert.equal($rendered.attr('title'), undefined);
});
test('escapeMarkup is being used', function (assert) {
var selection = new MultipleSelection(
$('#qunit-fixture .multiple'),
options
);
var $selection = selection.render();
var $rendered = $selection.find('.select2-selection__rendered');
var unescapedText = '<script>bad("stuff");</script>';
selection.update([{
text: unescapedText
}]);
assert.equal(
$rendered.text().substr(1),
unescapedText,
'The text should be escaped by default to prevent injection'
);
});
test('clear button respects the disabled state', function (assert) {
var options = new Options({
disabled: true
});
var $select = $('#qunit-fixture .multiple');
var container = new MockContainer();
var $container = $('<div></div>');
var selection = new MultipleSelection(
$select,
options
);
var $selection = selection.render();
$container.append($selection);
selection.bind(container, $container);
// Select an option
selection.update([{
text: 'Test'
}]);
var $rendered = $selection.find('.select2-selection__rendered');
var $pill = $rendered.find('.select2-selection__choice');
assert.equal($pill.length, 1, 'There should only be one selection');
var $remove = $pill.find('.select2-selection__choice__remove');
assert.equal(
$remove.length,
1,
'The remove icon is displayed for the selection'
);
// Set up the unselect handler
selection.on('unselect', function (params) {
assert.ok(false, 'The unselect handler should not be triggered');
});
// Trigger the handler for the remove icon
$remove.trigger('click');
});

View File

@@ -0,0 +1,74 @@
module('Selection containers - Placeholders');
var Placeholder = require('select2/selection/placeholder');
var SingleSelection = require('select2/selection/single');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var SinglePlaceholder = Utils.Decorate(SingleSelection, Placeholder);
var placeholderOptions = new Options({
placeholder: {
id: 'placeholder',
text: 'This is the placeholder'
}
});
test('normalizing placeholder ignores objects', function (assert) {
var selection = new SinglePlaceholder(
$('#qunit-fixture .single'),
placeholderOptions
);
var original = {
id: 'test',
text: 'testing'
};
var normalized = selection.normalizePlaceholder(original);
assert.equal(original, normalized);
});
test('normalizing placeholder gives object for string', function (assert) {
var selection = new SinglePlaceholder(
$('#qunit-fixture .single'),
placeholderOptions
);
var normalized = selection.normalizePlaceholder('placeholder');
assert.equal(normalized.id, '');
assert.equal(normalized.text, 'placeholder');
});
test('text is shown for placeholder option on single', function (assert) {
var selection = new SinglePlaceholder(
$('#qunit-fixture .single'),
placeholderOptions
);
var $selection = selection.render();
selection.update([{
id: 'placeholder'
}]);
assert.equal($selection.text(), 'This is the placeholder');
});
test('placeholder is shown when no options are selected', function (assert) {
var selection = new SinglePlaceholder(
$('#qunit-fixture .multiple'),
placeholderOptions
);
var $selection = selection.render();
selection.update([]);
assert.equal($selection.text(), 'This is the placeholder');
});

View File

@@ -0,0 +1,191 @@
module('Selection containers - Inline search');
var MultipleSelection = require('select2/selection/multiple');
var InlineSearch = require('select2/selection/search');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var options = new Options({});
test('backspace will remove a choice', function (assert) {
assert.expect(3);
var KEYS = require('select2/keys');
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var $element = $('#qunit-fixture .multiple');
var selection = new CustomSelection($element, options);
var $selection = selection.render();
selection.bind(container, $container);
// The unselect event should be triggered at some point
selection.on('unselect', function () {
assert.ok(true, 'A choice was unselected');
});
// Add some selections and render the search
selection.update([
{
id: '1',
text: 'One'
}
]);
var $search = $selection.find('input');
var $choices = $selection.find('.select2-selection__choice');
assert.equal($search.length, 1, 'The search was visible');
assert.equal($choices.length, 1, 'The choice was rendered');
// Trigger the backspace on the search
var backspace = $.Event('keydown', {
which: KEYS.BACKSPACE
});
$search.trigger(backspace);
});
test('backspace will set the search text', function (assert) {
assert.expect(3);
var KEYS = require('select2/keys');
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var $element = $('#qunit-fixture .multiple');
var selection = new CustomSelection($element, options);
var $selection = selection.render();
selection.bind(container, $container);
// Add some selections and render the search
selection.update([
{
id: '1',
text: 'One'
}
]);
var $search = $selection.find('input');
var $choices = $selection.find('.select2-selection__choice');
assert.equal($search.length, 1, 'The search was visible');
assert.equal($choices.length, 1, 'The choice was rendered');
// Trigger the backspace on the search
var backspace = $.Event('keydown', {
which: KEYS.BACKSPACE
});
$search.trigger(backspace);
assert.equal($search.val(), 'One', 'The search text was set');
});
test('updating selection does not shift the focus', function (assert) {
// Check for IE 8, which triggers a false negative during testing
if (window.attachEvent && !window.addEventListener) {
// We must expect 0 assertions or the test will fail
assert.expect(0);
return;
}
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var $element = $('#qunit-fixture .multiple');
var selection = new CustomSelection($element, options);
var $selection = selection.render();
selection.bind(container, $container);
// Update the selection so the search is rendered
selection.update([]);
// Make it visible so the browser can place focus on the search
$container.append($selection);
var $search = $selection.find('input');
$search.trigger('focus');
assert.equal($search.length, 1, 'The search was not visible');
assert.equal(
document.activeElement,
$search[0],
'The search did not have focus originally'
);
// Trigger an update, this should redraw the search box
selection.update([]);
assert.equal($search.length, 1, 'The search box disappeared');
assert.equal(
document.activeElement,
$search[0],
'The search did not have focus after the selection was updated'
);
});
test('the focus event shifts the focus', function (assert) {
// Check for IE 8, which triggers a false negative during testing
if (window.attachEvent && !window.addEventListener) {
// We must expect 0 assertions or the test will fail
assert.expect(0);
return;
}
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var CustomSelection = Utils.Decorate(MultipleSelection, InlineSearch);
var $element = $('#qunit-fixture .multiple');
var selection = new CustomSelection($element, options);
var $selection = selection.render();
selection.bind(container, $container);
// Update the selection so the search is rendered
selection.update([]);
// Make it visible so the browser can place focus on the search
$container.append($selection);
// The search should not be automatically focused
var $search = $selection.find('input');
assert.notEqual(
document.activeElement,
$search[0],
'The search had focus originally'
);
assert.equal($search.length, 1, 'The search was not visible');
// Focus the container
container.trigger('focus');
// Make sure it focuses the search
assert.equal($search.length, 1, 'The search box disappeared');
assert.equal(
document.activeElement,
$search[0],
'The search did not have focus originally'
);
});

View File

@@ -0,0 +1,119 @@
module('Selection containers - Single');
var SingleSelection = require('select2/selection/single');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var options = new Options({});
test('display uses templateSelection', function (assert) {
var called = false;
var templateOptions = new Options({
templateSelection: function (data) {
called = true;
return data.text;
}
});
var selection = new SingleSelection(
$('#qunit-fixture .single'),
templateOptions
);
var out = selection.display({
text: 'test'
});
assert.ok(called);
assert.equal(out, 'test');
});
test('templateSelection can addClass', function (assert) {
var called = false;
var templateOptions = new Options({
templateSelection: function (data, container) {
called = true;
container.addClass('testclass');
return data.text;
}
});
var selection = new SingleSelection(
$('#qunit-fixture .single'),
templateOptions
);
var $container = selection.selectionContainer();
var out = selection.display({
text: 'test'
}, $container);
assert.ok(called);
assert.equal(out, 'test');
assert.ok($container.hasClass('testclass'));
});
test('empty update clears the selection', function (assert) {
var selection = new SingleSelection(
$('#qunit-fixture .single'),
options
);
var $selection = selection.render();
var $rendered = $selection.find('.select2-selection__rendered');
$rendered.text('testing');
$rendered.attr('title', 'testing');
selection.update([]);
assert.equal($rendered.text(), '');
assert.equal($rendered.attr('title'), undefined);
});
test('update renders the data text', function (assert) {
var selection = new SingleSelection(
$('#qunit-fixture .single'),
options
);
var $selection = selection.render();
var $rendered = $selection.find('.select2-selection__rendered');
selection.update([{
text: 'test'
}]);
assert.equal($rendered.text(), 'test');
});
test('escapeMarkup is being used', function (assert) {
var selection = new SingleSelection(
$('#qunit-fixture .single'),
options
);
var $selection = selection.render();
var $rendered = $selection.find('.select2-selection__rendered');
var unescapedText = '<script>bad("stuff");</script>';
selection.update([{
text: unescapedText
}]);
assert.equal(
$rendered.text(),
unescapedText,
'The text should be escaped by default to prevent injection'
);
});

View File

@@ -0,0 +1,33 @@
module('Selection containers - Stoping event propagation');
var SingleSelection = require('select2/selection/single');
var StopPropagation = require('select2/selection/stopPropagation');
var $ = require('jquery');
var Options = require('select2/options');
var Utils = require('select2/utils');
var CutomSelection = Utils.Decorate(SingleSelection, StopPropagation);
var options = new Options();
test('click event does not propagate', function (assert) {
assert.expect(1);
var $container = $('#qunit-fixture .event-container');
var container = new MockContainer();
var selection = new CutomSelection($('#qunit-fixture select'), options);
var $selection = selection.render();
selection.bind(container, $container);
$container.append($selection);
$container.on('click', function () {
assert.ok(false, 'The click event should have been stopped');
});
$selection.trigger('click');
assert.ok(true, 'Something went wrong if this failed');
});

View File

@@ -0,0 +1,97 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="vendor/qunit-1.23.1.css" type="text/css" />
<link rel="stylesheet" href="../../dist/css/select2.css" type="text/css" />
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture">
<div class="event-container">
<select></select>
</div>
<select class="single">
<option>One</option>
</select>
<select class="single-empty"></select>
<select class="single-with-placeholder">
<option>placeholder</option>
<option>One</option>
</select>
<select class="multiple" multiple="multiple">
<option>One</option>
<option>Two</option>
</select>
<select class="groups">
<optgroup label="Test">
<option value="one">One</option>
<option value="two">Two</option>
</optgroup>
<optgroup label="Empty"></optgroup>
</select>
<select class="duplicates">
<option value="one">One</option>
<option value="two">Two</option>
<option value="one">Uno</option>
</select>
<select class="duplicates-multi" multiple="multiple">
<option value="one">One</option>
<option value="two">Two</option>
<option value="one">Uno</option>
</select>
<select class="user-defined"></select>
</div>
<script src="vendor/qunit-1.23.1.js" type="text/javascript"></script>
<script src="vendor/jquery-1.7.2.js" type="text/javascript"></script>
<script src="../dist/js/select2.full.js" type="text/javascript"></script>
<script src="helpers.js" type="text/javascript"></script>
<script src="a11y/selection-tests.js" type="text/javascript"></script>
<script src="a11y/search-tests.js" type="text/javascript"></script>
<script src="data/array-tests.js" type="text/javascript"></script>
<script src="data/base-tests.js" type="text/javascript"></script>
<script src="data/inputData-tests.js" type="text/javascript"></script>
<script src="data/select-tests.js" type="text/javascript"></script>
<script src="data/tags-tests.js" type="text/javascript"></script>
<script src="data/tokenizer-tests.js" type="text/javascript"></script>
<script src="data/maximumInputLength-tests.js" type="text/javascript"></script>
<script src="data/maximumSelectionLength-tests.js" type="text/javascript"></script>
<script src="data/minimumInputLength-tests.js" type="text/javascript"></script>
<script src="dropdown/dropdownCss-tests.js" type="text/javascript"></script>
<script src="dropdown/positioning-tests.js" type="text/javascript"></script>
<script src="dropdown/selectOnClose-tests.js" type="text/javascript"></script>
<script src="dropdown/stopPropagation-tests.js" type="text/javascript"></script>
<script src="options/ajax-tests.js" type="text/javascript"></script>
<script src="options/data-tests.js" type="text/javascript"></script>
<script src="options/deprecated-tests.js" type="text/javascript"></script>
<script src="options/translation-tests.js" type="text/javascript"></script>
<script src="options/width-tests.js" type="text/javascript"></script>
<script src="results/focusing-tests.js" type="text/javascript"></script>
<script src="selection/allowClear-tests.js" type="text/javascript"></script>
<script src="selection/containerCss-tests.js" type="text/javascript"></script>
<script src="selection/multiple-tests.js" type="text/javascript"></script>
<script src="selection/placeholder-tests.js" type="text/javascript"></script>
<script src="selection/search-tests.js" type="text/javascript"></script>
<script src="selection/single-tests.js" type="text/javascript"></script>
<script src="selection/stopPropagation-tests.js" type="text/javascript"></script>
<script src="utils/decorator-tests.js" type="text/javascript"></script>
<script src="utils/escapeMarkup-tests.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -0,0 +1,189 @@
module('Decorators');
var Utils = require('select2/utils');
test('overridden - method', function (assert) {
function BaseClass () {}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass () {}
DecoratorClass.prototype.hello = function () {
return 'B';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.strictEqual(inst.hello(), 'B');
});
test('overridden - constructor', function (assert) {
function BaseClass () {
this.inherited = true;
}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass (decorated) {
this.called = true;
}
DecoratorClass.prototype.other = function () {
return 'B';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.ok(inst.called);
assert.ok(!inst.inherited);
});
test('not overridden - method', function (assert) {
function BaseClass () {}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass () {}
DecoratorClass.prototype.other = function () {
return 'B';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.strictEqual(inst.hello(), 'A');
});
test('not overridden - constructor', function (assert) {
function BaseClass () {
this.called = true;
}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass () {}
DecoratorClass.prototype.other = function () {
return 'B';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.ok(inst.called);
});
test('inherited - method', function (assert) {
function BaseClass () {}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass (decorated) {}
DecoratorClass.prototype.hello = function (decorated) {
return 'B' + decorated.call(this) + 'C';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.strictEqual(inst.hello(), 'BAC');
});
test('inherited - constructor', function (assert) {
function BaseClass () {
this.inherited = true;
}
BaseClass.prototype.hello = function () {
return 'A';
};
function DecoratorClass (decorated) {
this.called = true;
decorated.call(this);
}
DecoratorClass.prototype.other = function () {
return 'B';
};
var DecoratedClass = Utils.Decorate(BaseClass, DecoratorClass);
var inst = new DecoratedClass();
assert.ok(inst.called);
assert.ok(inst.inherited);
});
test('inherited - three levels', function (assert) {
function BaseClass (testArgument) {
this.baseCalled = true;
this.baseTestArgument = testArgument;
}
BaseClass.prototype.test = function (a) {
return a + 'c';
};
function MiddleClass (decorated, testArgument) {
this.middleCalled = true;
this.middleTestArgument = testArgument;
decorated.call(this, testArgument);
}
MiddleClass.prototype.test = function (decorated, a) {
return decorated.call(this, a + 'b');
};
function DecoratorClass (decorated, testArgument) {
this.decoratorCalled = true;
this.decoratorTestArgument = testArgument;
decorated.call(this, testArgument);
}
DecoratorClass.prototype.test = function (decorated, a) {
return decorated.call(this, a + 'a');
};
var DecoratedClass = Utils.Decorate(
Utils.Decorate(BaseClass, MiddleClass),
DecoratorClass
);
var inst = new DecoratedClass('test');
assert.ok(inst.baseCalled, 'The base class contructor was called');
assert.ok(inst.middleCalled, 'The middle class constructor was called');
assert.ok(inst.decoratorCalled, 'The decorator constructor was called');
assert.strictEqual(inst.baseTestArgument, 'test');
assert.strictEqual(inst.middleTestArgument, 'test');
assert.strictEqual(inst.decoratorTestArgument, 'test');
var out = inst.test('test');
assert.strictEqual(out, 'testabc');
});

View File

@@ -0,0 +1,36 @@
module('Utils - escapeMarkup');
var Utils = require('select2/utils');
test('text passes through', function (assert) {
var text = 'testing this';
var escaped = Utils.escapeMarkup(text);
assert.equal(text, escaped);
});
test('html tags are escaped', function (assert) {
var text = '<script>alert("bad");</script>';
var escaped = Utils.escapeMarkup(text);
assert.notEqual(text, escaped);
assert.equal(escaped.indexOf('<script>'), -1);
});
test('quotes are killed as well', function (assert) {
var text = 'testin\' these "quotes"';
var escaped = Utils.escapeMarkup(text);
assert.notEqual(text, escaped);
assert.equal(escaped.indexOf('\''), -1);
assert.equal(escaped.indexOf('"'), -1);
});
test('DocumentFragment options pass through', function (assert) {
var frag = document.createDocumentFragment();
frag.innerHTML = '<strong>test</strong>';
var escaped = Utils.escapeMarkup(frag);
assert.equal(frag, escaped);
});