I am trying to automate my mobile web app.Every time it loads, it will ask "___ would like to use your location". User can either hit "don't allow" or "OK."
I am using self.driver.switch_to.alert.accept(), but it is accepting the default, which is "don't allow." How can I accept the "OK" instead of "don't allow"?
That method currently doesn't work for me either.
Did you try to locate "OK" button with Appium Inspector maybe?
I have the same pop up for location, and for me either of these work (xpath or accessibility ID) on iOS.
Something like:
allow_access_to_location_ios = (MobileBy.ACCESSIBILITY_ID, 'OK')
or
allow_access_to_location_ios = (MobileBy.XPATH, '//XCUIElementTypeButton[#name="OK"]')
then you call method:
self.wait_for_and_accept_alert(*self.allow_access_to_location_ios)
and method will wait for the element 15 seconds and click on it if it finds it otherwise it will print an error message:
def wait_for_and_accept_alert(self, *locator):
try:
WebDriverWait(self.driver, 15).until(lambda s: self.driver.find_element(*locator))
self.driver.find_element(*locator).click()
except TimeoutException:
print('Unable to find element')
For Accepting system alert create a method:
def accept_notification_alert(self):
print('Accept alert')
try:
self.driver.switch_to.alert.accept()
except WebDriverException:
print('Webdriver error: %s' % WebDriverException.msg)
For dismissing system alert you can create method:
def dismiss_notification_alert(self):
print('Dismiss alert')
try:
self.driver.switch_to.alert.dismiss()
except WebDriverException:
print('Webdriver error: %s' % WebDriverException.msg)
If a default approach (switch_to.alert.accept()) desn't work, you may try mobile gestures:
driver.execute_script('mobile: alert', {'action': 'accept', 'buttonLabel': <your button label here>});
I understood that you are asking for the device location alert. You can identify and use the Xpath of OK button to click. I have used the following code (in java) for an alert appears in the app.
driver.findElement(By.xpath("//UIAApplication[1]/UIAWindow[7]/UIAAlert[1]/UIACollectionView[1]/UIACollectionCell[1]/UIAButton[1]")).click();
Related
I have the following code:
for button in buttons:
ActionChains(driver).move_to_element(button).perform()
time.sleep(2)
button.click()
time.sleep(2)
try:
wait_button.until(EC.presence_of_element_located((By.XPATH,'//div/h2')))
time.sleep(2)
name = driver.find_element_by_xpath('//div/h2').text
except:
wait_button.until(EC.presence_of_element_located((By.XPATH,'//span[#id="chat-header-title"]')))
time.sleep(2)
name = driver.find_element_by_xpath('//span[#id="chat-header-title"]').text
def pull_ul() -> list:
chat_frame = driver.find_element_by_xpath("//iframe[starts-with(#id, 'experience-container-')]")
driver.switch_to.frame(chat_frame)
wait_button.until(EC.presence_of_element_located((By.XPATH,'//ul[#aria-label="Chat content"]')))
the_ul =driver.find_element(By.XPATH,'//ul[#aria-label="Chat content"]')
new_lis =the_ul.find_elements(By.TAG_NAME,'li')
return new_lis
def pull_ul_again() -> list:
the_ul =driver.find_element(By.XPATH,'//ul[#aria-label="Chat content"]')
new_lis_2 =the_ul.find_elements(By.TAG_NAME,'li')
return new_lis_2
lis = pull_ul()
print(f"Archiving Chat with {name} ...\n")
print("this is len lis: ",len(lis), "for " + name)
And here is what the terminal shows:
As you can see, the code actually does run past the line that threw up the error, how is this possible? Also, why would this be happening , I successfully ran the code multiple times and suddenly it starts throwing the follwing error?
The loop that you're doing,
for button in buttons:
ActionChains(driver).move_to_element(button).perform()
...
is causing your StaleElementReferenceException because inside that you have driver.switch_to.frame(chat_frame), but you never switch back to default content or to the parent frame, which means that your buttons won't exist in that level, and so Selenium throws StaleElementReferenceException as a result. That could also happen if you navigate away from the page (which might also be happening depending on the button clicks).
If you ever switch frames or leave pages, you have to re-find elements in order to interact with them.
I am writing a simple sign in test using unittest and selenium.
I would like to know how does Unittest know if a test has failed or not? I want to print "Pass" in my terminal if the sign in was successful and "Fail" if there was an error, like incorrect password.
This is what I have at the moment.
class SignIn(unittest.TestCase):
def setUp(self):
self.driver = driver
self.driver.get('https://example')
def test_sign_in(self):
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
def tearDown(self):
self.driver.close()
if __name__ == '__main__':
unittest.main()
You can user Asserts,
Let's say once you are logged in, you will either see dashboard or welcome screen, right ?
You need to assert them like below :
try:
assert "Expected_message_here" in driver.find_element_by_xpath('welcome page xpath here').text
except:
print("looks like a failure")
pass
This links contains all the asserts click here
and I would suggest you to have a different function to validate fail scenarios.
you can refer here also
Method 1:
If there's any successful sign-in message once the user is logged in, you can use a simple if-else statement. You may use the below patch of code
def test_sign_in(self):
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
success_msg=find_element_by_xpath('{{xpath of the success message}}')
WebDriverWait(driver, 5).until(EC.element_to_be_clickable(By.XPATH,success_msg))
if success_msg:
print("Successfully logged in")
else:
print("Unsuccessful")
Method 2:
You may use a Try Except block.
def test_sign_in(self):
try:
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
print("Successfully logged in")
except:
print("An exception occurred")
The above samples are raw code. Correct the identation, typos etc. Try it out and let me know if it worked for you! Cheers.
Im trying to click the like button with selenium this is the exception error I'm getting:
[-] Passed One Message: Element <span class="glyphsSpriteHeart__filled__16__white u-__7"> is not clickable at point (1039,84) because another element <div class="_2dDPU CkGkG"> obscures it
I have tried solving it with a loop that clicks all of the aria label like elements with Xpath, see my code:
while count <= likes:
try:
likeopt = bot.find_elements_by_xpath("//*[#aria-label='Like'] ")
for likeopti in likeopt:
likeopti.click()
#bot.find_element_by_class_name("fr66n").click()
print("[+] Liked !", count)
count += 1
time.sleep(random.randint(8, 15))
bot.find_element_by_class_name("_65Bje").click()
time.sleep(random.randint(8, 15))
except Exception as e:
try:
bot.find_element_by_class_name("_65Bje").click()
time.sleep(random.randint(3, 7))
print("[-] Passed One", e)
except Exception as x:
bot.find_elements_by_xpath("//*[#aria-label='Close'] ")
continue
print(x,"[+]click on X, finished all posts")
How do you think can it can be solved?
Thanks
Watch your script running, and pay attention to the point where it fails. You will likely see that there's some sort of drop down menu, pop-up 'dialog', or even an advertisement, that has displayed over your target link. You'll need to close/dismiss this to be able to get at the target link.
Alternatively, you can hack it by instructing the driver to send a click command via Javascript. bot.execute_script("arguments[0].click();", likeopt) I typically save this approach as a last resort since it does not represent how a user would interact with the page.
I am using selenium with python for the website automation,and that includes navigation and file downloads.If the page is idle for around 15 mins(roughly,not exact),confirmation pop up appears warning the session timeout and it asks to click "OK" to continue.
I know I can use the following code to deal with the confirmation pop up
driver.switch_to.alert.accept()
But how can I click "OK"in the confirmation popup whenever it appears?Do I have hto keep checking every 30 seconds if the confirmation popup exists?
It looks like someone here had a similar question as you: How to check if an alert exists using WebDriver?
If you run driver.switch_to.alert when there is no alert actually present, you will receive a NoAlertPresentException. So, the basic idea is to write a method with a try / catch block that attempts driver.switch_to.alert, and returns true or false based on the presence of an exception.
Here's an example:
public boolean doesAlertExist()
{
try
{
driver.switch_to.alert();
return true;
}
catch (NoAlertPresentException e)
{
return false;
}
}
As far as your timing issue goes (alert pops up every 15ish minutes or so) -- you can try to write a wrapper method for driver.findElement() and element.click() that checks for the presence of the alert implicitly. Specific details about the method will depend on the project, but here's an example of something simple:
public IWebElement findElementWrapped(By by)
{
if (doesAlertExist())
{
driver.switch_to.alert().accept(); // accept the alert
return driver.findElement(by); // use selenium's standard findElement
}
else
{
// no alert exists, just find the element
return driver.findElement(by);
}
}
With this code, you can check for the alert every time you try to find an element on the page, but you only have to write the line of code once. You can use this method in action like this:
// check for alert, accept alert if it exists, get the desired web element
IWebElement myElement = driver.findElementWrapped(by);
I'm trying to create a program that signs up for instagram with a new account, I've got the emails and the rest generated, when I go ahead and send_keys to the appropriate fields, it does it just fine. I wanted to implement a retry function, which would clear the email field and try with a different mail. However this does not work, even though send_keys to it worked previously? Snippet of my code below.
driver.get('https://www.instagram.com')
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(namae+lastonamae+pamae2)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
This attempts to create a new account with the appropriate credentials, however when it fails, I want it to try to look for an element that is only present when it fails, and if it finds that, it should clear the email field and retry with a different one. Code below.
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span') #this looks for the element only present on the fail page
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
It doesn't clear the field, but doesn't raise an error either. It then proceeds to type the 2nd email with no problems. I appreciate any help on the matter.
EDIT: Posting a bigger chunk of the code.
def signup():
driver.get('https://www.instagram.com')
time.sleep(7)
if trycounter < 3: #this is almost always true, just a failsafe
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + ' ' + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(name+lastname+extension)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
try: #this only executes if a popup that wants you to confirm your age pops up
driver.find_element_by_xpath('//*[#id="igCoreRadioButtonageRadioabove_18"]').click()
driver.find_element_by_xpath('/html/body/div[3]/div/div[3]/div/button').click()
time.sleep(5)
except:
pass
try:
randomgen() #generates the mail,password and name
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span')
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(username)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
You can use following code as alternative for clear method:
from selenium.webdriver.common.keys import Keys
email_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]")
email_element.send_keys(Keys.CONTROL, 'a')
email_element.send_keys(mail1)
fullname_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]")
fullname_element.send_keys(Keys.CONTROL, 'a')
fullname_element.send_keys(name + ' ' + lastname)
# do it for other field as well
So this will definitely work as a workaround. I just tried it on instagram. Although there was no field with an aria label called Email for me. It was aria-label "Mobile Number or Email" for me.
driver.execute_script("$(\"input[aria-label='Email']"\").value = '';");
I will keep looking at it to see why the clear command didn't work though.
You can try something like this to delete mail1.
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.chord(Keys.CONTROL,"a"))
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.DELETE)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)