So I looked up the implementation of the select
function.
From 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;
};
});
So the "problem" is that select
tries to select from the values in the DOM element, that is the <option value="THIS VALUE">
then it tries to find the value by what's being displayed <option>THIS VALUE</option>
and then it tries to do a contains
on the value. It doesn't actually use the model value at any point.
So select('day').option('02')
worked because it was matching the displayed text, where as select('day').option('30')
was matching the option value which has an offset.
Keep in mind the generated HTML is:
<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>
To "solve" this issue a new function needs to be created (or alter the existing).
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;
};
});
This does the trick.