Uploading image using RobotFramework in hidden input element - selenium

Due to hidden="hidden" I cannot run automated test with Robot Framework.
Kindly suggest me some idea to resolve it.
HTML code:
<a _ngcontent-c8="" class="browse cursor-pointer" tabindex="0">Browse</a>
<input _ngcontent-c8="" id="file" style="border: 1px solid gray; cursor: pointer; margin: 5px; width: 300px;" accept=".png, .jpg, .jpeg, .gif, .tif, .tiff" type="file" hidden="hidden">

There's a workaround for that - make the element visible through javascript, just before interacting with it:
Execute Javascript document.getElementById('file'‌​).style.visibility='‌​visible'
UPDATE:
If you want to set an attribute different from style, like in this case a custom one called hidden, you use a different js method:
Execute Javascript document.getElementById('file'‌​).setAttribute('hidden') = 'new_value'
, where "new_value" is the one you know will make it visible.
And if you want to remove it altogether, the call is
Execute Javascript document.getElementById('file'‌​).removeAttribute('hidden')

If someone is still struggling with the SyntaxErrors like me, here is the correct syntax for setAttribute that works for me:
Execute Javascript document.getElementById('file'‌​).setAttribute('attributeName', 'attributeValue');
And if you don't have the id attribute:
Execute Javascript document.getElementsByClassName('file'‌​)[0].setAttribute('attributeName', 'attributeValue');
FYI:The method getElementsByClassName return an array of elements.

Related

How to get text value from strong tag

Iam unable to get the text value present under strong tag, as after a particular execution or task completion in browser tag gets change.
HTML Code before execution or task completion:
<div>
<strong>heizil</strong>:
<label id="check_label">
<em class="Highlight" style="padding: 1px; box-shadow: rgb(229, 229, 229) 1px 1px; border-radius: 3px; background-color: rgb(0, 191, 255); color: rgb(0, 0, 0); font-style: inherit;" match="test" loopnumber="385144110">Test</em> device testing - Android testing
</label>
HTML code after execution or task completion :
<a id="id_1008326" class="activity">
<strong>heizil</strong> :
<label id="check_label"> "device testing - Android testing"
</label>
using the following code line :
System.out.println(driver.findElement(By.xpath("//a[#class='activity'][contains(.,'Android testing')]/strong")).getText());
I'm getting desired result (heizil),but if i try to get strong tag text value before HTML execution or task completion iam getting no element exception.
Is there anyway we can print (heizil) text under strong tag using ' device testing - Android testing ' as this is the only text constant, irrespective of after execution or before execution.
Note : observed <div> tag before completion of task and after completion of task it changes to another HTML code, could you please help me getting textvalue inside strong tag using text ' device testing - Android testing '
Try with this xpath:
//label[#id='check_label']/preceding-sibling::strong
Or xpath with utilize contains function:
//label[contains(.,'Android testing')]/preceding-sibling::strong

Can I get specific "dl" i.e. at First or Second index out of many identified by a CSS Selector in my App

I'm trying to automate a functionality using selenium in my Application Chrome browser. It's an SVG graph based page and shows details upon mouse over it. And this is identifiable with a CSS selector which is returning more than one matching elements(i.e. 6-7 dl , these dls has few child tags then internally containing the values I need to verify -as attached), now my need to select them one by one at a time and verify text of them(which displayed on mouse over).
I got to know on google how to read nth-child from dl but not getting a way to select particular dl at first place.
For example-
my selector is: .d3-tip.n>dl
if I use -.d3-tip.n>dl>dt:nth-child(odd): its giving me all the attributes of dt.. ie 6 values but I nedd values only from fst dl.
Similarly.d3-tip.n>dl>dd:nth-child(even) returning the 6 values of respected dds..
In Actual my app has only one dl (on UI) but don't know why it displaying 6 in DOM...
Plz refer attachment and HTML for a clear understanding of DOM
<div class="d3-tip n" style="position: absolute; top: 44.5px; opacity: 0; pointer-events: none; box-sizing: border-box; left: 515px;">
<dl style="width:335px">
<dt>Space Name:</dt>
<dd>Space</dd>
<dt>Property Type:</dt>
<dd>Office</dd>
<dt>Quoted Area:</dt>
<dd>444 sf</dd>
<dt>Space Usage:</dt>
<dd>Business Park,Commercial School</dd>
<dt>Space Status:</dt>
<dd>For Lease</dd>
<dt>Possession Status:</dt>
<dd>Vacant</dd>
</dl>
<span class="d3-tip__pin"/>
</div>
<div class="d3-tip n" style="position: absolute; top: 44.5px; opacity: 0; pointer-events: none; box-sizing: border-box; left: 515px;">
<dl style="width:335px">
<dt>Space Name:</dt>
<dd>Space</dd>
<dt>Property Type:</dt>
<dd>Office</dd>
<dt>Quoted Area:</dt>
<dd>444 sf</dd>
<dt>Space Usage:</dt>
<dd>Business Park,Commercial School</dd>
<dt>Space Status:</dt>
<dd>For Lease</dd>
<dt>Possession Status:</dt>
<dd>Vacant</dd>
</dl>
<span class="d3-tip__pin"/>
</div>
<--! and so on up to 6 blocks of dl
nth-child is to find the nth-child of any immediate parent element. In your HTML DOM, dd is single child element of each div.d3-tip element. The repetitive child is actually your div.d3tip for it immediate parent element
So your selector has to be written as below to get the first set of dd,
div.d3-tip:nth-child(1)>dl>dd
Getting the second selector also works. This is most important while writing css selector. The second nth has to work. :).
Ok, so I am not sure which of the elements you want...
So... here is a snip that should give you help.
A) with hovering.
B) with looping through the elements.
C) Bonus learn about contains() functionality of XPath...
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
url = "http://your_url"
path_to_chromedriver = "C:\path_to_chromedriver"
chrome_options = Options()
#chrome_options.add_argument("--headless")
chrome_options.add_argument("--start-maximized")
browser = webdriver.Chrome(executable_path=path_to_chromedriver,
chrome_options=chrome_options)
browser.get(url)
# list_of_dt_elements_to_hover = browser.find_elements_by_xpath("//div[contains(#class,'d3-tip')]//dl/dt")
list_of_dt_elements_to_hover = browser.find_elements_by_xpath("//div[class='d3-tip n']//dl/dt")
list_of_dd_elements_to_hover = browser.find_elements_by_xpath("//div[contains(#class,'d3-tip')]//dl/dd")
hover = ActionChains(browser).move_to_element(list_of_dt_elements_to_hover[0])
hover.perform()
for dd_ele in list_of_dt_elements_to_hover:
hover = ActionChains(browser).move_to_element(dd_ele)
hover.perform()
print(dd_ele.text)
for dd_ele in list_of_dd_elements_to_hover:
hover = ActionChains(browser).move_to_element(dd_ele)
hover.perform()
print(dd_ele.text)
I hope you find this helpful!

Dealing with Multiple Capybara React-select dropdowns?

So I have a page with multiple dropdowns (with the same choices) when automating a webpage using Capybara and Chromedriver.
They are all react-select's (Which I have a helper file for). Sadly they ALL have the same label text (but not label ID....however I don't think page.select works for label ID).
I thought about doing a page.all on the react-selects? and then just going through the array? Is that possible?
the react-select looks pretty standard, I realize the span has an id but selecting by that doesn't work for react-selects from what i've been able to tell.:
<div class="Select-control">
<span class="Select-multi-value-wrapper" id="react-select-6--value">
<div class="Select-placeholder">Select...</div>
<div class="Select-input" style="display: inline-block;">
<input role="combobox" aria-expanded="false" aria-owns="" aria-haspopup="false" aria-activedescendant="react-select-6--value" value="" style="width: 5px; box-sizing: content-box;">
<div style="position: absolute; top: 0px; left: 0px; visibility: hidden; height: 0px; overflow: scroll; white-space: pre;"></div>
</div>
</span>
<span class="Select-arrow-zone"><span class="Select-arrow"></span></span>
</div>
Could I maybe just pull it in via page.all? The react helper I have does this:
module CapybaraReactHelper
def capybara_react_select(selector, label)
within selector do
find('.Select-control').click
expect(page).to have_css('.Select-menu-outer') # options should now be available
expect(page).to have_css('.Select-option', text: label)
find('.Select-option', text: label).click
end
end
end
Any ideas?
Thanks!
Selecting by the id on .Select-multi-value-wrapper isn't working because that span isn't the react-select component's top-level tag. Working with react-select and Capybara generally is difficult because the Capybara form helpers won't work with react-select's custom markup and behavior.
As you've mentioned, you can get around this by using a version of your existing helper with a scoping within block and page.all(). For example:
# helper
def react_select_capybara(selector, option)
within selector do
find('.Select-arrow-zone').click
expect(page).to have_css('.Select-menu-outer')
find('.Select-option', text: option).click
expect(page).to have_css('.Select-value-label', text: option)
end
end
# usage
given(:select_values) { ['Grace Hopper', 'Ada Lovelace'] }
...
react_selects = page.all('.Select')
select_values.each do |select_value, i|
react_select_capybara(react_selects[i], select_value)
end
While this will work, it is brittle - it relies on the implicit ordering of your react-selects on the page. A more robust setup would pass each react-select component a custom classname to uniquely identify it in your test. From the react-select docs on custom classnames:
You can provide a custom className prop to the component, which will be added to the base .Select className for the outer container.
Implementing this might look like:
# JSX
<ReactSelect className="js-select-user-form-1" ... />
<ReactSelect className="js-select-user-form-2" ... />
# Spec
react_select_capybara(".js-select-user-form-1", 'Grace Hopper')
react_select_capybara(".js-select-user-form-2", 'Ada Lovelace')
page.select doesn't work for this because it only works for HTML <select> elements. This is a JS driven widget, not an HTML <select> element.
If you are just automating a page (not testing an app) it'll probably be easier just to use JS (via execute_script) to set the value of the hidden <input>s.
If you are testing an app, then you can use page.all to gather all the react-selects and step through, as long as selecting from any react-select doesn't replace any of the others on the page (which would leave you with obsolete elements).
If that doesn't provide enough info to solve your problem, and your real issue is trying to pick a specific react-select to select from, then please add enough HTML to your question so we can see what actual differences exist between the widgets you're trying to choose from (2 different react-select elements for instance)

element not visible: Element is not currently visible and may not be manipulated - Selenium webdriver

Following is the html
<div id="form1:customertype" class="ui-selectonemenu ui-widget ui-state-default ui-corner-all ui-state-hover" style="width: 165px;">
<div class="ui-helper-hidden-accessible">
<select id="form1:customertype_input" name="form1:customertype_input" tabindex="-1">
<option value="S">Staff</option>
<option value="C">Customer</option>
<option value="N">New To Bank</option></select></div>
<div class="ui-helper-hidden-accessible"><input id="form1:customertype_focus" name="form1:customertype_focus" type="text" readonly="readonly"></div>
<label id="form1:customertype_label" class="ui-selectonemenu-label ui-inputfield ui-corner-all" style="width: 149px;">Staff</label>
<div class="ui-selectonemenu-trigger ui-state-default ui-corner-right ui-state-hover"><span class="ui-icon ui-icon-triangle-1-s ui-c"></span></div></div>
The stylesheet of class="ui-helper-hidden-accessible" is
ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 0px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 0px;
}
Following is my code
WebElement customerType = driver.findElement(By.id("form1:customertype_input"));
Select select = new Select(customerType);
select.selectByVisibleText("New To Bank");
When I try to select "New to Bank" from the dropdown I get exception
element not visible: Element is not currently visible and may not be manipulated - Selenium webdriver
I have tried WebDriverWait technique but of no use, any ideas ?
I don't believe the text for that option is actually visible before you attempt to select it. Try selecting by value instead.
WebElement customerType = driver.findElement(By.id("form1:customertype_input"));
Select select = new Select(customerType);
select.selectByValue("N");
You may need to actually click the selector before being able to select an option, though.
WebElement customerType = driver.findElement(By.id("form1:customertype_input"));
new WebDriverWait(driver, 15).until(
ExpectedConditions.elementToBeClickable(customerType));
customerType.click();
Select select = new Select(customerType);
select.selectByValue("N");
try performing click on customerType before you create object of Select
Well, I found a work around to solve my problem but I am not happy with this. anyways what I did is focused on the div element that controls the dropdown by clicking it and and then sending down arrows keys twice followed by enter key. This selects my desired option. I used the following method
driver.switchTo().activeElement()
I also had the same problem and after hours I realized the browser was trying to click in a element before the page load.
So I create a sleep to solved the problem:
sleep(1)
P.S. - This is a solution that I really don't like.
I'm just pointing you the reason for that.
The best you can do is to check the page that you have the problem and try to optimize the load time.
I encounter the same problem. I have tried many methods.
Finally, the following python code solved the error.
I use javascript code to make the element visible before selecting the option.
css = 'select#state' # css selector of the element
js = """const data_options = Array.from(document.querySelectorAll('{css}'));
data_options.forEach(a=>{{a.style='display:block;';}});""".format(css=css)
self.driver.execute_script(js)
Maybe it's helpful for you!

Input type="file" Localization [duplicate]

How can I internationalize the button text of the file picker? For example, what this code presents to the user:
<input type="file" .../>
It is normally provided by the browser and hard to change, so the only way around it will be a CSS/JavaScript hack,
See the following links for some approaches:
http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom
http://www.quirksmode.org/dom/inputfile.html
http://www.dreamincode.net/forums/showtopic15621.htm
Pure CSS solution:
.inputfile {
/* visibility: hidden etc. wont work */
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.inputfile:focus + label {
/* keyboard navigation */
outline: 1px dotted #000;
outline: -webkit-focus-ring-color auto 5px;
}
.inputfile + label * {
pointer-events: none;
}
<input type="file" name="file" id="file" class="inputfile">
<label for="file">Choose a file (Click me)</label>
source: http://tympanus.net/codrops
Take a step back! Firstly, you're assuming the user is using a foreign locale on their device, which is not a sound assumption for justifying taking over the button text of the file picker, and making it say what you want it to.
It is reasonable that you want to control every item of language visible on your page. The content of the File Upload control is not part of the HTML though. There is more content behind this control, for example, in WebKit, it also says "No file chosen" next to the button.
There are very hacky workarounds that attempt this (e.g. like those mentioned in #ChristopheD's answer), but none of them truly succeed:
To a screen reader, the file control will still say "Browse..." or "Choose File", and a custom file upload will not be announced as a file upload control, but just a button or a text input.
Many of them fail to display the chosen file, or to show that the user has no longer chosen a file
Many of them look nothing like the native control, so might look strange on non-standard devices.
Keyboard support is typically poor.
An author-created UI component can never be as fully functional as its native equivalent (and the closer you get it to behave to suppose IE10 on Windows 7, the more it will deviate from other Browser and Operating System combinations).
Modern browsers support drag & drop into the native file upload control.
Some techniques may trigger heuristics in security software as a potential ‘click-jacking’ attempt to trick the user into uploading file.
Deviating from the native controls is always a risky thing, there is a whole host of different devices your users could be using, and whatever workaround you choose, you will not have tested it in every one of those devices.
However, there is an even bigger reason why all attempts fail from a User Experience perspective: there is even more non-localized content behind this control, the file selection dialog itself. Once the user is subject to traversing their file system or what not to select a file to upload, they will be subjected to the host Operating System locale.
Are you sure you're doing your user any justice by deviating from the native control, just to localize the text, when as soon as they click it, they're just going to get the Operating System locale anyway?
The best you can do for your users is to ensure you have adequate localised guidance surrounding your file input control. (e.g. Form field label, hint text, tooltip text).
Sorry. :-(
--
This answer is for those looking for any justification not to localise the file upload control.
You get your browser's language for your button. There's no way to change it programmatically.
much easier use it
<input type="button" id="loadFileXml" value="Custom Button Name"onclick="document.getElementById('file').click();" />
<input type="file" style="display:none;" id="file" name="file"/>
I could achieve a button using jQueryMobile with following code:
<label for="ppt" data-role="button" data-inline="true" data-mini="true" data-corners="false">Upload</label>
<input id="ppt" type="file" name="ppt" multiple data-role="button" data-inline="true" data-mini="true" data-corners="false" style="opacity: 0;"/>
Above code creates a "Upload" button (custom text). On click of upload button, file browse is launched. Tested with Chrome 25 & IE9.
To make a custom "browse button" solution simply try making a hidden browse button, a custom button or element and some Jquery. This way I'm not modifying the actual "browse button" which is dependent on each browser/version. Here's an example.
HTML:
<div id="import" type="file">My Custom Button</div>
<input id="browser" class="hideMe" type="file"></input>
CSS:
#import {
margin: 0em 0em 0em .2em;
content: 'Import Settings';
display: inline-block;
border: 1px solid;
border-color: #ddd #bbb #999;
border-radius: 3px;
padding: 5px 8px;
outline: none;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
font-weight: 700;
font: bold 12px/1.2 Arial,sans-serif !important;
/* fallback */
background-color: #f9f9f9;
/* Safari 4-5, Chrome 1-9 */
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#C2C1C1), to(#2F2727));
}
.hideMe{
display: none;
}
JS:
$("#import").click(function() {
$("#browser").trigger("click");
$('#browser').change(function() {
alert($("#browser").val());
});
});
Actually, it is possible to customize the Upload File button with its pseudo selector: ::file-selector-button.
Check this for more info: MDN ::file-selector-button - CSS