2013-12-02 3 views
1

У меня странная проблема. Когда я пытаюсь выбрать дату, функция select() выбирает неправильный вариант.select (name) .option (value) выбирает неправильный вариант?

Ng-модель:

days = ['01', '02', '03', '04', ..., '31']; 

Markup:

<select ng-model="day" id="day" name="day" ng-options="day for day in days"> 
    <option value="" disabled="disabled"></option> 
</select> 

тест e2e:

it('should select correct date', function() { 
    select('day').option('30'); 
    expect(element('#day option:selected').text()).toEqual('30'); 
}); 

Так что мой вопрос: Почему select('day').option('30') выбрать 31th день, когда select('day').option('02') работает как ожидается?


Так что мне было интересно, какое значение он нацеливается, поскольку он отлично работает в других местах. Документация очень редкая, так что либо это особенность, либо ошибка:

Я думаю, что это select() пытается выбрать значение в каком-то порядке. И.Е. сначала он пытается выбрать параметр по значению, затем пытается выбрать его по значению модели или что-то в этом направлении.

ответ

2

Так что я посмотрел на реализацию функции select.

От github:

/** 
* Usage: 
* select(name).option('value') select one option 
* select(name).options('value1', 'value2', ...) select options from a multi select 
*/ 
angular.scenario.dsl('select', function() { 
    var chain = {}; 

    chain.option = function(value) { 
    return this.addFutureAction("select '" + this.name + "' option '" + value + "'", 
     function($window, $document, done) { 
     var select = $document.elements('select[ng\\:model="$1"]', this.name); 
     var option = select.find('option[value="' + value + '"]'); 
     if (option.length) { 
      select.val(value); 
     } else { 
      option = select.find('option').filter(function(){ 
      return _jQuery(this).text() === value; 
      }); 
      if (!option.length) { 
      option = select.find('option:contains("' + value + '")'); 
      } 
      if (option.length) { 
      select.val(option.val()); 
      } else { 
       return done("option '" + value + "' not found"); 
      } 
     } 
     select.trigger('change'); 
     done(); 
    }); 
    }; 

    return function(name) { 
    this.name = name; 
    return chain; 
    }; 
}); 

Так что «проблема» в том, что select пытается выбрать из значений в элементе DOM, то есть <option value="THIS VALUE"> то он пытается найти значение на то, что отображается <option>THIS VALUE</option> и то он пытается сделать значение contains. Фактически он не использует значение модели в любой точке.

Так select('day').option('02') работал, потому что он соответствовал отображаемому тексту, где select('day').option('30') соответствовал значению параметра, имеющему смещение.

Имейте в виду, генерируемый HTML является:

<select ng-model="day" id="day" name="day" ng-options="day for day in days"> 
    <option value="" disabled="disabled"></option> 
    <option value="0">01</option> <-- note it starts at 0 not 1 
    <option value="1">02</option> <-- select('day').option('02') matches display text '02' as no value 02 exists. 
    <option value="2">03</option> 
    <option value="29">30</option> 
    <option value="30">31</option> <-- select('day').option('30') matches value 30 before display text 30 with value 29. 
</select> 

Чтобы «решить» этот вопрос новая функция должна быть создана (или изменить существующий).

angular.scenario.dsl('selectModel', function() { 
    var chain = {}; 

    chain.option = function(value) { 
     return this.addFutureAction("select '" + this.name + "' option '" + value + "'", 
      function($window, $document, done) { 
       var $ = $window.$; // jQuery inside the iframe 
       var select = $document.elements('select[ng\\:model="$1"]', this.name); 
       var option = select.find('option').filter(function(){ 
        return $(this).text() === value; 
       }); 
       if (!option.length) { 
        option = select.find('option:contains("' + value + '")'); 
       } 
       if (option.length) { 
        select.val(option.val()); 
       } else { 
        return done("option '" + value + "' not found"); 
       } 

       select.trigger('change'); 
       done(); 
      }); 
    }; 

    return function(name) { 
     this.name = name; 
     return chain; 
    }; 
}); 

Это делает трюк.

1

Угловое созданы option метки имеют индексы в качестве значения, когда исходная модель представляет собой список:

$scope.listItems = [ 
    "day 1", 
    "day 2", 
    "day 3", 
    "day 4", 
    "day 5" 
]; 

и

<select ng-model="listItem" ng-options="item for item in listItems"></select> 

создать следующий HTML:

<select ng-options="item for item in listItems" ng-model="listItem" 
class="ng-pristine ng-valid"> 
    <option value="?" selected="selected"></option> 
    <option value="0">day 1</option> 
    <option value="1">day 2</option> 
    <option value="2">day 3</option> 
    <option value="3">day 4</option> 
    <option value="4">day 5</option> 
</select> 

В то время как option метки имеют ключи в качестве значения, когда исходная модель является карта:

$scope.objItems = { 
    "day 1":"1", 
    "day 2":"2", 
    "day 3":"3", 
    "day 4":"4", 
    "day 5":"5" 
}; 

и

<select ng-model="objItem2" ng-options="value as key for (key, value) 
in objItems"></select> 

создать:

<select ng-options="value as key for (key, value) in objItems" 
ng-model="objItem2" class="ng-valid ng-dirty"> 
    <option value="day 1" selected="selected">day 1</option> 
    <option value="day 2">day 2</option> 
    <option value="day 3">day 3</option> 
    <option value="day 4">day 4</option> 
    <option value="day 5">day 5</option> 
</select> 

Однако это не представляет собой проблему, потому что, когда пользователь выбирает опцию. Угловой взгляд на индексированную позицию внутри источника и присваивает это значение модели.

Я не очень хорошо знаком с тестированием e2e, но я думаю, что причина, по которой вы получаете различное значение, каждый раз, когда вы выбираете опцию, заключается в том, что вы пытаетесь получить доступ к значению, хранящемуся в теге option, а не к тому, что Угловое хранило в модель для вас.

Fiddle

Смежные вопросы