Issue
Whenever I reach a JavaScript alert and try to interact with it, the test fails with an AttributeError, 'WebDriver' (in this case, 'JsAlerts') object has no attribute switch_to. I am using selenium version 4.3.0 and Python 3.10. Here is what I've tried so far, with no success:
The "browsers" fixture just yields a WebDriver instance for Chrome.
switch_to.alert:
from objects.javascript_alerts import JsAlerts
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def test_regular_alert(browsers):
alerts = JsAlerts(browsers)
alerts.load()
alerts.click_go_to_js_alert()
alerts.click_alert()
WebDriverWait(alerts, 10).until(EC.alert_is_present())
alerts.switch_to.alert.accept()
importing Alert
from objects.javascript_alerts import JsAlerts
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.alert import Alert
def test_regular_alert(browsers):
alerts = JsAlerts(browsers)
alerts.load()
alerts.click_go_to_js_alert()
alerts.click_alert()
WebDriverWait(alerts, 10).until(EC.alert_is_present())
al = Alert(alerts)
al.accept()
I've also tried switch_to_alert()
Edit: Posting parts of the page object and fixture for more context.
Page object
class JsAlerts:
# URL
URL = 'https://the-internet.herokuapp.com/'
# Locators
add_js_alert_link = (By.LINK_TEXT, 'JavaScript Alerts')
js_alert = (By.CSS_SELECTOR, "li:nth-child(1) > button")
js_confirm = (By.CSS_SELECTOR, "li:nth-child(2) > button")
js_prompt = (By.CSS_SELECTOR, "li:nth-child(3) > button")
results = (By.ID, "result")
# Initializer
def __init__(self, browser):
self.browser = browser
# Interaction Methods
def load(self):
self.browser.get(self.URL)
def click_go_to_js_alert(self):
self.browser.find_element(*self.add_js_alert_link).click()
def click_alert(self):
self.browser.find_element(*self.js_alert).click()
Fixture (Chrome is set up in config)
@pytest.fixture
def browsers(config):
# Initialize the ChromeDriver instance
if config['browser'] == 'Firefox':
b = selenium.webdriver.Firefox()
elif config['browser'] == 'Chrome':
b = selenium.webdriver.Chrome()
elif config['browser'] == 'Headless Chrome':
opts = selenium.webdriver.ChromeOptions()
opts.add_argument('headless')
b = selenium.webdriver.Chrome(options=opts)
else:
raise Exception(f'Browser "{config["browser"]}" is not supported')
# Return the WebDriver instance for the setup
yield b
# Quit the Webdriver instance for the cleanup
b.quit()
Using browsers.switch_to.alert.accept() still returns the "'JsAlerts' object has no attribute switch_to " error.
Solution
Problem
The error is telling you that your JsAlerts
class does not have a method or property called switch_to
which is correct. However, you're treating JsAlerts
as if it is a WebDriver
object.
For example, your line that does the following won't work because Alert
expects a WebDriver
object and you're passing in a custom JsAlerts
object:
# change this:
al = Alert(alerts)
# to this:
al = Alert(browsers)
The same is true for your WebDriverWait
line:
# change this:
WebDriverWait(alerts, 10)
# to this:
WebDriverWait(browsers, 10)
Solutions
So, in your test, use the WebDriver
object which does have the switch_to
property you're looking for!
def test_regular_alert(browsers):
alerts = JsAlerts(browsers)
alerts.load()
alerts.click_go_to_js_alert()
alerts.click_alert()
WebDriverWait(browsers, 10).until(EC.alert_is_present())
al = Alert(browsers)
al.accept()
I tried the same exercise using Pylenium and this is what I came up with so you have a working example.
# test_alers.py
from selenium.webdriver.common.alert import Alert
from pylenium.driver import Pylenium
from tests.ui.page import Page
def test_accept_alert(py: Pylenium):
py.visit("https://the-internet.herokuapp.com/javascript_alerts")
py.get("[onclick='jsAlert()']").click()
alert: Alert = py.webdriver.switch_to.alert
alert.accept()
assert py.contains("You successfully clicked an alert")
def test_accept_alert_with_page_object(py: Pylenium):
page = Page(py).goto()
page.open_alert().accept()
assert py.contains("You successfully clicked an alert")
And the page object that goes along with the second test
# page.py
from selenium.webdriver.common.alert import Alert
from pylenium.driver import Pylenium
class Page:
def __init__(self, py: Pylenium):
self.py = py
self.driver = py.webdriver
def goto(self) -> "Page":
self.py.visit("https://the-internet.herokuapp.com/javascript_alerts")
return self
def open_alert(self) -> Alert:
self.py.get("[onclick='jsAlert()']").click()
return self.driver.switch_to.alert
Answered By - Carlos Kidman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.