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);
  });
});