I'm able to set an option in a dropdown list, but then I get an error message. I found an online site that will return the same error:
http://www.100candles.com/floating_candles.htm
irb(main):124:0> $ie = Watir::IE.attach(:url, /100candles/)
=> #<Watir::IE:0x..fd64f0146 url="http://www.100candles.com/t/Vessels?PN=1&SB=Updated" title="Vessels - 100 Candles">
irb(main):126:0> $ie.select_list(:name, "SB").flash
=> #<Watir::SelectList:0x4960ea5e located=true specifiers={:tag_name=>["select"], :name=>"SB"}>
irb(main):127:0> $ie.select_list(:name, "SB").select("Price")
Watir::Exception::ObjectDisabledException: object {:index=>0, :ole_object=>#<WIN32OLE:0x3759e58>} is disabled
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/element.rb:329:in `assert_enabled'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/element.rb:470:in `perform_action'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/input_elements.rb:117:in `select'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/input_elements.rb:46:in `each'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/input_elements.rb:46:in `block in select'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/element.rb:472:in `perform_action'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.4.0/lib/watir-classic/input_elements.rb:41:in `select'
from (irb):127
from C:/Ruby193/bin/irb:12:in `<main>'
irb(main):128:0>
Problem
The selection works for some options (ex Bulk Cost) but not others (ex Price). Looking at the watir code for SelectList#select:
def select(item)
matching_options = []
perform_action do
matching_options = matching_items_in_select_list(:text, item) +
matching_items_in_select_list(:label, item) +
matching_items_in_select_list(:value, item)
raise NoValueFoundException, "No option with :text, :label or :value of #{item.inspect} in this select element" if matching_options.empty?
matching_options.each(&:select)
end
matching_options.first.text
end
And the page html:
<select id="SB" onchange="document.location='/floating_candles.htm?PN=1&SB=' + this.value;" name="SB">
<optgroup style="font-style: normal;" label="Please Choose">
<option value="">-
<option value="PieceCost">Bulk Cost
<option value="Updated">New Arrivals
<option value="Popularity">Popularity
<option value="Price">Price
<option selected="" value="Relevance">Relevance
</option></optgroup>
</select>
The reason for the exception can be seen:
In SelectList#select, it gathers up all options with the text, label or value that matches the specified criteria. For "Price" (and the other options that fail), the option is collected (ie added to matching_options) twice - once for matching by text and once for matching by value. In contrast, the ones that work (ex Bulk Cost) only get matched once since their text and value is different.
SelectList#select will select each matching_option. In the case of "Price", this means two selections.
The select list on the page has an onchange event that refreshes the page. In the case of "Price", the first selection of the option works (as can be seen when watching the script). However, it is the second selection that fails. I assume that the selection attempts while the page is refreshing, resulting in the exception.
Solution
The solution is to directly select the option element. This ensures that the option only gets selected once:
$ie.select_list(:name, "SB").option(:text => "Price").select
Related
I'm trying to select an option in a drop-down menu using selenium's Select, but I can't get anything out of it. My code at the moment is like this
select = Select(driver.find_element_by_id("cmbTBC"))
select.select_by_value("172")
which presents me with the error selenium.common.exceptions.NoSuchElementException: Message: Cannot locate option with value: 172.
If I inspect the element I can see a list of options, including one with value '172', but going to the source code shows no options at all. Here's the part with the drop-down menu at the source.
<select Id="cmbTBC" class="form-control" data-val="true" data-val-number="The field TBC must be a number." data-val-required="The TBC field is required." id="IdTBC" name="IdTBC" onchange="CreateBC.DescriptionTBC(this.value)">
<option value=""></option>
</select>
What am I doing wrong?
The options are probably loaded by JavaScript, you can wait for them to appear with custom ExpectedCondition
def wait_for_options(self, select):
if select.options:
return True
return False
select = Select(driver.find_element_by_id("cmbTBC"))
wait = WebDriverWait(driver, 10)
wait.until(lambda x: self.wait_for_options(select))
select.select_by_value("172")
You should also notice there are to id attributes, one of them is with uppercase I, Id="cmbTBC" and id="IdTBC". You need the lowercase one, there might be another dropdown without options with id="cmbTBC", and this is what the driver locate
select = Select(driver.find_element_by_id("IdTBC"))
This question already has answers here:
How to select option in drop down protractorjs e2e tests
(34 answers)
Closed 5 years ago.
There's quite a few ways to do this and I've tried a good number of them but I can't select an item from a drop down menu when doing an automated test.
"Select" is the default choice that appears in the drop down menu, I want the automated test to pick one of the elements, doesn't matter which one
This is the HTML Code
<select class="form-control ng-pristine ng-invalid ng-invalid-required" ng-model="user.investmentAmount" required="" ng-class="{submitted:invalid}">
<option value="">Select</option>
<option value="<50"> 50K</option>
<option value="50-100">100K</option>
<option value="100-250">250K</option>
<option value="250-500">500K</option>
</select>
And this is my Protractor file
var selectDropdownbyNum = function ( element, optionNum ) {
if (optionNum){
var options = element(by.cssContainingText("Select"))
.then(function(options){
options[2].click();
});
}
};
browser.sleep(2000);
I've tried using by.cssElement, by.xpath etc.
When I run the above, I get no errors but it doesn't select any element either.
Thanks
Selects are an odd duck for sure. I generally just click the option by text (when possible). Eg. you should be able to do something like this...
var selectOptionByText = function(text) {
return element(by.cssContainingText('option', text)).click();
};
Once you clicked on //select[#ng-model='user.investmentAmount'] usng xpath,
Put some wait like "browser.sleep(2000)" then use //option[text()='100K'] to click.
It's because of you are selecting only one option containing 'Select' value and expecting array,
try below, first get the select box by model and get all options by
html tag name in array
browser.element(by.model('user.investmentAmount')).all(by.tagName('option')).
then(function(items){
items[2].click();
});
I have a problem with Poltergeist. I can’t get the driver to locate a field on a page. What I want to do is to execute some js to make sure that the input field is empty before I start adding new text. I have a field with a label os "Skill list" and id of "user_skill_list". In order to make the step more generic I want to find the field by the label name and then get the id.
And(/^I delete the content of "([^"]*)"$/) do |label|
field_id = page.find_field(label).native.attributes['id'].value
page.execute_script("$('#{field_id}').val('');")
end
Here's the error message:
#javascript
Scenario: Update user by removing # features/godmin/skills.feature:36
Given "Thomas" skills are "rspec, testing" # features/step_definitions/godmin_steps.rb:63
And I click on "Edit" for "Thomas" # features/step_definitions/godmin_steps.rb:43
And I delete the content of "Skill list" # features/step_definitions/godmin_steps.rb:69
Unable to find field "Skill list" (Capybara::ElementNotFound)
./features/step_definitions/godmin_steps.rb:70:in `/^I delete the content of "([^"]*)"$/'
features/godmin/skills.feature:39:in `And I delete the content of "Skill list"'
```
My cucumber set up is pretty basic.
# features/support/env.rb
...
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
Capybara.default_max_wait_time = 5
...
Thank you. Please let me know if I should clarify my question.
Assuming your html is something like
<label for="user_skill_list">Skill list</label>
<input id="user_skill_list"/>
Then
page.find_field('Skill list').set('')
should find the field and clear it. If it's not finding the element there are a couple of possibilities.
The element isn't visible on the page
There is CSS being applied that is changing the case of "Skill list"
There are typos in your html so the label isn't actually associated with the field. You can test this by just doing page.find_field('user_skill_list').set('') so the label isn't involved
Note: you can get the id by just doing page.find_field('Skill list')[:id] rather than having to resort to .native.xxxx - although it's not really needed for this use case
I am working with Position Absolute's Form validation engine.
I have a specific case for validation that I'm hoping this can solve for me. I need to be able to make one field required based on the value of another field.
For example:
If country.dropdown = "USA", then state.dropdown is required.
or
If country.dropdown <> 'USA" then state.dropdown is not required.
Do you think this is possible with JQuery Validation Engine? If so, can you point me in the right direction?
I have to say, first, that I have never used the Position Absolute's Form validation engine,
but I got interested in it reading your question.
From the documentation ( https://github.com/posabsolute/jQuery-Validation-Engine ), it appears that you have to create a custom validation function.
I created a working fiddle here: http://jsfiddle.net/5pKjW/6/
Even if it works, I am not completely satisfied with it, because a "sentinel value" is needed because of this condition in the validation engine at line 584.
// If the rules required is not added, an empty field is not validated
if(!required && field.val() == "" && !errorMsg) options.isError = false;
This is the markup of the select withe the custom function:
<select class="validate[funcCall[checkCountry]]" type="text" name="state" id="state">
<option value="none" ></option>
<option value="CALIFORNIA" >CALIFORNIA</option>
<option value="NEW ENGLAND" >NEW ENGLAND</option>
<option value="TEXAS" >TEXAS</option>
</select>
And this is the validator initialization:
jQuery("#formID").validationEngine({
'customFunctions': {
'checkCountry': function (field, rules, i, options){
if ($('#country').val() === 'USA' && field.val() === 'none') {
return options.allrules.required.alertText;
}
}
}
});
1) First, you have to define a validation function that can be global or can be passed as an argument of the plug-in (as I did above). A custom function accepts this inputs: field, rules, i, options.
You have no reference to the form, you only have reference to the current field.
So if you want to access another field, you have to select it as usual with jQuery (in the example: $('#country') ).
2) You check for the validation condition. In the example it fails if:
$('#country').val() === 'USA' && field.val() === 'none'
If the condition is not respected, the function must return a String. In the example, I returned the standard message in options.allrules.required. The documetation explains how to define custom messages for custom functions.
As you can see, because of the
if(!required && field.val() == "" && !errorMsg) options.isError = false;
line in the validation engine, the developer is forced to make the condition inside the if fail, and setting the required condition to true or the error message to a falsy value is not right. So, the only way is to make field.val() != ''.
For this reason, the first option element in the markup has the sentinel value none, instead of being empty. It is not a clean solution, and it may even not be possible to implement easily (I don't know if you generate the markup yourself (if you don't, things get more difficult and you need to manipulate the form via javascript, before the validation engine initialization)).
This is not a clean solution.
A nicer solution would have been using condRequired, if only it would have accepted a custom function, instead of only checking if one of its arguments had been populated.
I am using cucumber with capybara to automate the web application. i have to select a value from a drop down , but many time i am getting an error like; "wrong argument type String (expected Array) (TypeError)"
I tried with:
1.
second_option_xpath = ".//*[#id='selecttype']/option[2]"
second_option = find(:xpath, second_option_xpath).text
select(second_option, :from => 'selecttype')
2.
select "Selenium Core", :from => 'selecttype'
3.
page.find_and_select_option("selecttype", 2)
4.
select( "selecttype", {"Selenium Core" => 2})
PAGE SOURCE IS SOMETHING LIKE:
<select id="selecttype">
<option value="Selenium IDE">Selenium IDE</option>
<option value="Selenium Code">Selenium Core</option>
<option value="Selenium RC">Selenium RC</option>
<option value="Selenium Grid">Selenium Grid</option>
</select>"
Please suggest where i am doing wrong?
Thanks
Have you tried
page.select('Selenium Core', :from => 'selecttype')
As RobertH suggests, you should use something like page.select, where page is a Capybara::Session instance.
When you call select in your code, you are invoking a method of the Kernel module, which is mixed in the basic Object class, which every class inherits from.
This method expects 4 parameters, 3 of them are arrays of IO objects; that's the reason why it complains about wrong arguments.