Checking status/event of icon - Selenium, Python 3.9 - python-3.x

With covid and online schooling, it's hard to keep up with my kid keeping up! I'm only a little familiar with Python and less familiar with webstuff and selenium, but I wanted to try to make it easier to check on whether he's finishing his assignments each day by writing a script that (1) goes to the class webpages, (2) looks for the 'Overdue' text in the outer HTML, and (3) does something (e.g., print 'There is an overdue assignment') if the find method succeeds.
I've completed 1 successfully and know how to do part 3, but can't figure out part 2.
I found what I think is the relevant part on the pages with the inspect element:
<i class="icon-minimize" aria-label="This assignment is overdue" title="This assignment is overdue"></i>
And I've tried the following code variations:
overDue = driver.find_element_by_tag_name("This assignment is overdue")
overDue = driver.find_element_by_name("This assignment is overdue")
And I've tried to copy the CSS Selector and use
overDue = driver.find_element_by_class_name("i.icon-minimize:nth-child(1)")
I also tried XPath, but I forget now exactly what my code was. Something like:
overDue = driver.find_element_by_xpath(//*[., text()="This assignment is overdue"])
But all of these return a NoSuchElement exception. Is there something wrong with my syntax or am I using the wrong methods?
Thanks.

overDue = driver.find_element_by_xpath('//*[#title="This assignment is overdue"]')
its title , use #title to validate the value of title attribute
xpath syntax is
//tagname[#attribute="attributevalue"]
so tag_name is i
driver.find_element_by_tag_name("i")
there is no name attribute so you cannot use
driver.find_element_by_name
class is 'icon-minimize' you should not mention tag there:
driver.find_element_by_class_name("icon-minimize")

Related

How to properly use .itemconfigure() in tkinter

I am trying to remove the underline from the items in my list box when i select it. I tried giving the entire list box the "activestyle=None" but i learned that you need to use the "itemconfigure". What i am lost on is what i should be putting for index. I have my .insert index as 'end' and it works properly but when i do that for the item configure it says its out of range. Here is the code if anyone can assist me here.
taskList = Listbox(setBox, bg="#1B2834",fg="white")
taskList.configure(width=183,height=39, activestyle=None, fg="#4299E9", selectbackground="#061523",
selectforeground="#4299E9")
taskList.itemconfigure('end', activestyle=None)
taskList.insert('end', taskIDnum)
You don't use itemconfigure to set the activestyle attribute. You should use the configure method of the listbox. The documented value to turn off the ring around active item (or underline, depending on platform) is the string "none", not the python value None.
taskList.configure(activestyle="none")

Selenium Select Input Box that Changes Name Every Session

I'm trying to access a search text box inside of our company's ERP system using Selenium. The screenshot shows the text box and the Xpath of the element.
This is a little tricky, because that Menu Search pop-up isn't really a pop-up. It somehow shows up when a user types Control + M.
By installing ChroPath and testing I've found the text-box always starts with the following string:
txtMenuSearch_Namespace_
I've tried to imitate what's described here, here and here with no luck.
The latest attempt in the snippet of my code looks like this:
menu_search_input_box_elements = driver.find_elements_by_xpath("//*[contains(#id, ‘txtMenuSearch_Namespace_’)]")
for item in menu_search_input_box_elements:
print(item)
I get the following error message:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(#id, ‘txtMenuSearch_Namespace_’)]' is not a valid XPath expression.
In all my attempts to get the syntax right I keep getting this message. Any help in figuring out how to .send_keys() to this field is greatly appreciated.
You get en error because of the ‘’ quotes, replace them with correct ones.
# id starts with txtMenuSearch_Namespace_
menu_search_input_box_elements = driver.find_elements_css_selector("[id^='txtMenuSearch_Namespace_']")
menu_search_input_box_elements = driver.find_elements_by_xpath("//*[contains(#id, 'txtMenuSearch_Namespace_')]")

Selenium - find element by link text

I am using selenium webdriver on Chrome; python 3 on Windows 10.
I want to scrape some reports from a database. I search with a company ID and a year, the results are a list of links formatted in a specific way: something like year_companyID_seeminglyRandomDateAndDoctype.extension, e.g. 2018_2330_20020713F04.pdf. I want to get all pdfs of a certain doctype. I can grab all links for a certain doctype using webdriver.find_elements_by_partial_link_text('F04') or all of that extension with '.pdf' instead of 'F04', but I cannot figure out a way to check for both at once. First I tried something like
links = webdriver.find_elements_by_partial_link_text('F04')
for l in links:
if l.find('.pdf') == -1:
continue
else:
#do some stuff
But unfortunately, the links are WebElements:
print(links[0])
>> <selenium.webdriver.remote.webelement.WebElement (session="78494f3527260607202e68f6d93668fe", element="0.8703868381417961-1")>
print(links[0].get_attribute('href'))
>> javascript:readfile2("F","2330","2015_2330_20160607F04.pdf")
so the conditional in the for loop above fails.
I see that I could probably access the necessary information in whatever that object is, but I would prefer to do the checks first when getting the links. Is there any way to check multiple conditions in the webdriver.find_elements_by_* methods?
You can try to use below code
links = [link.get_attribute('href') for link in webdriver.find_elements_by_partial_link_text('F04') if link.get_attribute('href').endswith('.pdf")')]
You can also try XPath as below
links = webdriver.find_elements_by_xpath('//a[contains(., "F04") and contains(#href, ".pdf")]')
Andersson's approach seems to work with a slight correction:
if link.get_attribute('href').endswith('.pdf')] rather than if link.get_attribute('href').endswith('.pdf")')], i.e. delete the ").

If certain thing is included in input use anything after it

Hello I am currently working on a script that goes onto a website and automatically adds an Item to cart and purchases it for you I have a script that works except the only problem is that It is only able to checkout a single Item Item. Here is an example fo the script:
Item_code = input('Item code: ')
Size = input('Size: ')
def BOT():
driver = webdriver.Chrome(executable path=
URL = .....
driver.get(URL)
while True:
try:
driver.find_element_by_css_selector(Item_code).click()
break
except NoSuchElementException:
driver.refresh()
select = Select(driver.find_element_by_id('s'))
select.select_by_visible_text(Size)
The script finds the item with the item code that I use and then selects the size from the users choice
I want to be able to write the code and the size but If I want to bot to cart two Items in different sizes I want it to type in a , and insert the next Item code and Size For example:
12345, 6789
Large, Medium
I want to somehow write that if a comma is included to read and use the code after it after it uses the first one and repeat that for every comma so If I wanted to get 3 or even 4 all I would have to do is this:
1234, 5678, 7890, etc...
Large, medium, Small, etc...
If anyone could Help me out I would really appreciate it I was thinking of something like
for , in BOT():
(something like this but Im not sure )
I know how to tell the script that if Item_code == (',') then do this but that would not work because it needs to be just the comma and I do not know how to tell it to repeat the BOT() a second time and use the second code and size
If someone could help me out I would really appreciate it thanks.
(I want to be able to share this bot since I have already made a GUI for it and all that)
(not sure if the executable path will work when sharing)
I have fixed this problem I created several custom functions and called them on special if statements
ex.
if Item.count(',') == (1):
Cart1()
Checkout()
etc.....

How do I get the HTML in an element using Capybara?

I’m writing a cucumber test where I want to get the HTML in an element.
For example:
within 'table' do
# this works
find('//tr[2]//td[7]').text.should == "these are the comments"
# I want something like this (there is no "html" method)
find('//tr[2]//td[7]').html.should == "these are the <b>comments</b>"
end
Anyone know how to do this?
You can call HTML DOM innerHTML Property:
find('//tr[2]//td[7]')['innerHTML']
Should work for any browser or driver.
You can check all available properties on w3schools
This post is old, but I think I found a way if you still need this.
To access the Nokogiri node from the Capybara element (using Capybara 1.0.0beta1, Nokogiri 1.4.4) try this:
elem = find('//tr[2]//td[10]')
node = elem.native
#This will give you a Nokogiri XML element
node.children[1].attributes["href"].value.should == "these are the <b>comments</b>"
The last part may vary for you, but you should be able to find the HTML somewhere in that node variable
In my environment, find returns a Capybara::Element - that responds to the :native method as Eric Hu mentioned above, which returns a Selenium::WebDriver::Element (for me). Then :text gets the contents, so it could be as simple as:
results = find(:xpath, "//td[#id='#{cell_id}']")
contents = results.native.text
if you're looking for the contents of a table cell. There's no content, inner_html, inner_text, or node methods on a Capybara::Element. Assuming people aren't just making things up, perhaps you get something different back from find depending on what else you have loaded with Capybara.
Looks like you can do (node).native.inner_html to get the HTML content, for example with HTML like this:
<div><strong>Some</strong> HTML</div>
You could do the following:
find('div').native.inner_html
=> '<strong>Some</strong> HTML'
I ran into the same issue as Cyril Duchon-Doris, and per https://github.com/teampoltergeist/poltergeist/issues/629 the way to access the HTML of an Capybara::Poltergeist::Node is via the outerHTML property, e.g.:
find('//tr[2]//td[7]')['outerHTML']
Most of the other answers work only in Racktest (as they use Racktest-specific features).
If your driver supports javascript evaluation (like Selenium) you can use innerHTML :
html = page.evaluate_script("document.getElementById('my_id').innerHTML")
If you're using the Poltergeist driver, these methods will allow you to inspect what matches:
http://www.rubydoc.info/gems/poltergeist/1.5.1/Capybara/Poltergeist/Node
For example:
page.find('[name="form-field"]').native.value == 'something'
try calling find('//tr[2]//td[10]').node on it to get at the actual nokogiri object
Well, Capybara uses Nokogiri to parse, so this page might be appropriate:
http://nokogiri.org/Nokogiri/XML/Node.html
I believe content is the method you are looking for.
You could also switch to capybara-ui and do the following:
# define your widget, in this case in your role
class User < Capybara::UI::Role
widget :seventh_cell, [:xpath, '//tr[2]//td[7]']
end
# then in your tests
role = User.new
expect(role.widget(:seventh_cell).html).to eq(<h1>My html</h1>)

Resources