module('Data adapters - Array');

var ArrayData = require('select2/data/array'); var $ = require('jquery'); var Options = require('select2/options');

var arrayOptions = new Options({

data: [
  {
    id: 'default',
    text: 'Default'
  },
  {
    id: '1',
    text: 'One'
  },
  {
    id: '2',
    text: '2'
  }
]

});

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,
  3,
  '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(
  $select.find(':selected').data('data').extra,
  '<option> default should have new data'
);

data.select({
  id: 'One'
});

assert.ok(
  $select.find(':selected').data('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');

});