Selenium Python - working with dynamic iframe popups - python

I will try to explain this best i can. I am trying to automatically enter data onto a web page. This is the basic representation of it:
<html>
<head>
<body>
<div id="container">
<div id="'header"></div>
<div id="content"></div>
<div id="footer"></div>
</div>
<div id="control_window_11" class="simple_window" style="margin: 0px; position: absolute; z-index: 10008; display: none;"><div class="modalReportWindowClose"></div></div>
<iframe undefined="position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none" src="javascript:void(0);" frameborder="0" style="position: absolute; display: none;"></iframe>
</body>
</head>
</html>
`<div id="control_window_10"></div> and <iframe></iframe>`
are both generated dynamically when i click save. After saving, the popup will go away and <div id="control_window_10" will be changed too: <div id="control_window_11".
the issue appears after the first successful iteration of the program. When it clicks 'save' and id=control_window changes from 10 to 11 (keep in mind it will increase every iteration contril_window_12, 13, 14 and so on.). although every single iframe and div are generated the same, selenium will still be looking at control_window_10 and not be able to find elements. i have tried to index them by Xpath, id, class, ive even tried to dynamically change the numbers myself.

Related

Referencing a div title class with xpath selenium python

So I have started messing around with Selenium in python and I am just not able to figure this xpath out.
<div title class="popupBox" style="left: 0px; to p: 490px;">
<svg class="cp Drag" viewbox="0 0 24 24" style="height: 10px; width: 10px;">...</svg>
<div title class="eqBox">
<div title class="ib cp">
<img title src="src.svg">
<div title class="bred"></div>
<div title class="ds2">+1</div>
<div title class="ds3 IQ">TOP</div>
</div>
</div>
I need to be able to locate the TOP and get the result of TOP.
Hopefully that makes sense and I provided what is needed.
Try:
driver.find_element(By.XPATH, '//*[#class="ds3 IQ"]').text.splitlines[-1]

How to search for specific text within HTML cell event and click corresponding button within same cell?

Need some help with my first python project (also my first post on stackoverflow). Appreciate your time and help!
I am trying to automate regular booking on a website using selenium and chrome webdriver. The booking page is a timetable, with each cell corresponding to a timeslot and "Book" buttons within each cell/timeslot.
However, the XPATH for these buttons turns out to be dynamic.
E.g. //*[#id="root"]/div[4]/div/div[4]/div/div[3]/div[69]/div[3]/button
Each cell and button for the different timeslots has the same html class name and type. So would it be possible to search for the text in each cell (e.g. Class 1.10 7:30) and click the corresponding button within the same cell?
<div class="column">
<div class="cell even">
<span class="d-block d-sm-none">Sat, 17th Jul</span>
<span class="d-none d-sm-block">Saturday, 17th July</span></div>
<div class="cell event " style="color: rgb(255, 255, 255); top: 8rem; height: 6rem;">
<div>Class 1.1</div>
<div>07:30</div>
<div class="position-relative">
<button class="btn btn-warning" type="button">Book</button>
</div>
</div>
<div class="cell event " style="color: rgb(255, 255, 255); top: 16rem; height: 6rem;">
<div>Class 1.2</div>
<div>08:30</div>
<div class="position-relative">
<button class="btn btn-warning" type="button">Book</button>
</div>
</div>
Yes, it is possible.
If you want to match 2 texts in 2 elements as shown in the HTML you presented and I guess the texts are passed to the method as parameters, it will be something like this:
btn_xpath = ("//div[./div[contains(text(),'Class $class')] and (./div[contains(text(),'$time')])]//button[text()='Book']",(class=class, time=time))
driver.find_element_by_xpath(btn_xpath).click()
Here class and time are parameters passed from outside to select the desired class and time.
In case the selection can be unique by the time only it will be like this:
btn_xpath = ("//div[./div[contains(text(),'$time')]]//button[text()='Book']",(time=time))
driver.find_element_by_xpath(btn_xpath).click()

Difference in css outcome between static and jinja2 html

I am using Flask and therefore Jinja2 to dynamically create a web page.
When I use the render_template function the resulting web pages pick up my css styles normally and do as I expect with some strange exceptions.
For example, the following css and html code is working 100% as intended:
CSS:
.intro {
font-family: monospace;
font-size: 24px;
color: #455934;
padding-top: 30px;
padding-right: 50px;
padding-bottom: 5px;
padding-left: 50px;
}
HTML:
<p class ='intro'>
Hello
</p>
However when using a ``Jinja2``` template:
<p class ='intro'>
{{title}}
</p>
The css style for this class is ignored.
This is not true for any other styles in the same css file and template, for reference the whole template looks like this and the styles for div containers, background, etc. work as intended:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='gemuese_style.css') }}">
<title>{{title}}</title>
</head>
<body>
<div class="outer">
<div class="middle">
<div class="inner">
<p class ='intro'>
{{title}}
</p>
<ul>
<li>{{result}}</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
Edit:
Some testing has shown me that the style seems to work depending on the variable jinja renders. The template is rendered based on the output of different functions who generally return a list of a string and another list. The string is then used to fill in the {{title}} part where the css is failing.
For some functions it does work but I am not sure why because there is no difference in the return format.
Edit2:
Look at the difference between This rendered template and this one.

display: inline-block not working Outlook Email HTML

I want to set one table and one image in same line of email.
display: inline; is working fine in any browser but in outlook email everything is in one column, I need them to in same line. Please help me with solution.
<html>
<head>
<title></title>
<style>
img {
display: inline;
width: 100px;
height: 100px;
}
h1 {
display: inline;
}
</style>
</head>
<body> <img src="Image1.jpg">
<h1>afdsgdf dfgsdf dsfgf</h1> <img src="Image2.jpg">
</body>
</html>
Coding HTML for Email clients is completely different to coding for web browsers. And on top of that every email client will render your code differently. It is a far too extensive topic to go into here so I would advise doing some research online. However, to get you started, the most reliable way to write HTML for email is to use a table layout with HTML table tr td tags etc.
Also many email clients ignore style tags so you may want to write your CSS inline like this -
<img style="display: inline; width: 100px; height: 100px;" src="img1.jpg" />
<h1 style="display:inline"> Im a header </h1>
Hope this helps

Selenium wait for element to be clickable python

All, I'm needing a little assistance with Selenium waits. I can't seem to figure out how to wait for an element to be ready.
The element that I am needing to wait I can locate and click using my script via the code below...
CreateJob = driver.find_element_by_xpath(".//*[#id='line']/div[1]/a")
or
CreateJob = driver.find_element_by_partial_link_text("Create Activity")
I'm needing to wait for this element to be on the page and clickable before I try to click on the element.
I can use the sleep command, but I have to wait for 5 seconds or more and it seems to be unreliable and errors out 1 out of 8 times or so.
I can't seem to find the correct syntax to use.
the HTML code for this is below.
<document>
<html manifest="https://tddf/index.php?m=manifest&a=index">
<head>
<body class="my-own-class mozilla mozilla48 mq1280 lt1440 lt1680 lt1920 themered" touch-device="not">
<noscript style="text-align: center; display: block;">Please enable JavaScript in your browser settings.</noscript>
<div id="wait" style="display: none;">
<div id="processing" class="hidden" style="display: none;"/>
<div id="loading" class="hidden" style="display: none;"/>
<div id="loadingPartsCatalog" class="hidden"/>
<div id="panel">
<div id="top-toolbar" class="hidden" style="display: block;">
<div id="commands-line" class="hidden" style="display: block;">
<div id="line">
<div class="action-link">
<a class="tap-active" href="#m=activity/a=set" action_link_label="create_activity" component_gui="action" component_type="action">Create Activity</a>
</div>
<div class="action-link">
<div class="action-link">
<div class="action-link">
</div>
<div id="commands-more" style="display: none;">
<div id="commands-list" class="hidden">
</div>
<div id="provider-search-bar" class="hidden center"
Here is a link to the 'waiting' section of the Python Selenium docs: http://selenium-python.readthedocs.io/waits.html#explicit-waits
You wait should look like this:
element = WebDriverWait(driver, 10).until(
EC.visibility_of((By.XPATH, ".//*[#id='line']/div[1]/a"))
)
I find this to be the easiest:
driver.implicitly_wait(10)
Where it waits for up to 10 seconds before the script might crash if expected conditions aren't met. I think it's better than always checking for the visibility of, the clickability of, or whatever it is about the element. Less effective and more error prone, however. So it would depend more on why you use selenium.
It also lets me cut down on try/except statements in my selenium scripts, and since I've found out about this I've reduced many time.sleep() functions as well.

Categories