Selenium Python : Unable to get element by id/name/css selector - javascript

For a school project, I'm trying to create a Python Script which is able to fill in different forms, from different websites.
Here is the thing, for some kinds of website, I'm not able to catch the form elements which Selenium.
E.g. in this website : http://www.top-office.com/jeu
Where I inspect the page with firefox, the input "Name" box has the id "lastname", but Selenium is not able to get it. And when I display the html code of this page, the form looks like being included from another page or something.
I tried to getelementbyid, byname, bycssselector, etc.
I also tried to wait for the page to be entirely loaded by using WebDriverWait(driver, 5), but it still do not work.
Do you have any solutions or suggestions ?
PS : Even with javascript, I'm not able to get this element by id
Thanks

The element that you are trying to interact with is inside of an iframe. You need to use the driver.switch_to_frame() method in order to switch the driver to focus on that iframe. Only when it has switched into that iframe can it interact with its elements.
See this post on how to use it. You can locate the iframe using xpath, like this: //iframe[#src = 'https://adbx.me/grandjeuclubmed/']. Then, you can use the code mentioned in the post I gave you.

Related

How can I edit html inside an iframe using javascript

I am working on automating a process within my business, part of which is sending an email through SalesForce. We don't have access to the SF API and the email has to be sent through salesforce in order to keep the communication searchable for the coworkers.
I need to use a template which can be selected in SalesForce, however this function does not work in IE (which our RPA solution uses) so I need to build this email from scratch.
I see two options for this:
Use the HTML to recreate the format with the right variables. This entails inserting/injecting/manipulating HTML.
Copy the format into memory/the clipboard, edit it programatically and paste it into the SF interface
This question will be about option 1. I will post an additional question with regards to the second option separately and edit this question to include that link. EDIT: Here is the link to the other question!
Now on to the question:
We use the Blue Prism RPA software suite. It has a possibility to insert javascript fragments into a website and subsequently invoke them. I was hoping that I could create a javascript fragment that recreates the template, insert it and then invoke it. I have been working on this for the past week and have hardly gotten any further.
I now am able to add basic text into the required field, but have found that to be able to use the template structure I need to use a different, HTML based, field. This field I find lives inside an iframe.
I have had zero experience with javascript prior to this week (luckily it seems similar to c# in which I do have experience) and now this iframe has me stumped. Apparently when you use Selenium or similar you can switch the driver to the new iframe but I don't have that option, it needs to be done through surface automation. Within javascript as well as the console I can not get it to target the separate document within the iframe. Apparently the iframe contents are not incorporated in that way in the bigger webpage.
So my question is this: How can I "switch focus" to the iframe using javascript? How can I then edit the iframe contents through javascript? Any help, tips etc. would be highly appreciated!
If you go to developer tools in the browser (F12 or right-click inspect) you can use the inpsect tool to get the path you are looking for. an iframe is just another window inside the window and once you have the 'base path' you can then extend further into the window from the iframe base path.
You can access frames one of two ways I know of;
document.getElementById('the frame you are looking for goes here').contentWindow.targetFunction();
and/or
window.frames[0].otherfunctions
where 0 is the Nth order of frame on the window in case there are others.
once you find that path you can interact with sub-elements on that iframe by getting the path to it from within the iframe.
some things to watch out for. frames not loading yet so make sure the frame you want is loaded and no other frame is moving it around the screen at run time. Also make sure the child frame is in the same domain, I think calling javascript has issues when going cross-domain i.e. it doesn't work (stand to be corrected there though maybe it depends on group settings)
Supply some code or the layout of the page and could give you a code example but top of my head the format will look like this
var doc = window.frames[0]
var thing = getElementById(doc.getElementByPath('maybePath')
'perform some set operations like set innerhtml to thing you desire

Selenium - How to find and click element via xpath when page is rendered via javascript

Problem:
I am trying to find an element and then click it via xpath using selenium and python, on a web page that is rendered with JavaScript. The xpath has been confirmed to be correct, the issue is that the html isn't fully rendering due to only seeing the javascript "top level" (i think that's the right term).
I have seen methods of finding the full html code and saving it as a string, but that is not clickable via selenium
What I Am Looking For:
A method to just render all the javascript code, so that I can access the html elements I am looking for.
Code Would Look Like:
browser.render_javascript()
browser.find_element_by_xpath("//span[text()='Budget & Cost Management']/../preceding-sibling::img[2]").click()
Currently if I try to find the xpath above, it says it doesn't exist. However, if I inspect the page and search this xpath, it takes me right to the element. Obviously, selenium isn't seeing this element though because it isn't available to it (not rendered or executed, not sure which is the correct term).
I have also tried to just wait 30 seconds before searching for this element, but it doesn't look like any amount of time will render the page to selenium.
Is this possible? What kind of workarounds are available?

Python Selenium edit text content of specific javascript element in specific iframe

I am trying to use python selenium to change the text in a specific JS element.
I started out by attempting to simply execute the script using the following:
driver.execute_script("document.querySelector('#cssSelector').textContent='{}'".format(text))
However, unfortunately, this returns null
When looking into the JS the selector is in a specific iframe so I have tried to select the iframe but this has not yet worked:
driver.execute_script('''var element=window.frames['iframe'].document.querySelector("[id='cssselector']"); element.textContent='{}'".format(text))
This code also returns undefined as it cannot find the element.
Is there a better way to do this? thanks

Javascript bookmarklet to remove navbar?

I am trying to create a javascript bookmark that will remove a side navbar from a website that I use, but cannot seem to be able to remove it.
The navbar element id I would like to hide is is:
ul.nav.navbar-nav.side-nav.col-md-2
I have tried a few ways from researching online, but with no luck. How can I accomplish this?
Here is my attempt:
javascript:(function(){('ul.nav.navbar-nav.side-nav.col-md-2').hide()})();
This is an internal portal website that I use.
I am trying to modify/remove the menu once the site is loaded via the browser in the form of a javascript bookmarklet, and am not editing the site's code myself.
Without an example of the problem or website it won't be very clear/easy for anyone to help.
But one obvious issue I see is that you are not actually referring to an element directly, you just placed a CSS selector in brackets:
('ul.nav.navbar-nav.side-nav.col-md-2')
You probably want to use jQuery to get the element:
$('ul.nav.navbar-nav.side-nav.col-md-2')
Or if jQuery is not available:
document.querySelector('ul.nav.navbar-nav.side-nav.col-md-2').style.display = 'none';

How to use page-mod to modify element loaded by JavaScript

I'm creating firefox addon to add onclick event to the specific button. ("input" element)
The button is placed in http://example.com/welcome#_pg=compose
but when I open the page, following error occures:
TypeError: document.querySelector("#send_top") is null
#send_top is id of the button which I want to modify. So, the button is not found.
This error occurs because http://example.com/welcome and http://example.com/welcome#_pg=compose is completely different pages.
In this case, the addon seems loading http://example.com/welcome but there is no button whose '#send_top' ID.
When #_pg=compose anchor is added, the button is loaded by JavaScript.
How can I load http://example.com/welcome#_pg=compose to modify the button?
Three thoughts to help you debug this:
to correctly match the url you should consider using a regular expression instead of the page-match syntax - this might allow you to react to the anchors in a more predictable way
I've found that when using content scripts with pages that are heavily modified by JS, you can run into timing issues. A hacky workaround might be to look for the element you want and, if it isn' there, do a setTimeout for a 100 milliseconds or so and then re-check. Ugly, yes, but it worked for some example code I used with the new twitter UI, for example.
You can use the unsafeWindow variable in your content script to directly access the page's window object - this object will contain any changes JS has made to the page and is not proxied. You should use unsafeWindow with great caution however as its use represent a possible security problem. In particular, you should never trust any data coming from unsafeWindow, ever.

Categories

Resources