'What does the exception NoSuchWindowException mean, when I try to access a submit button of a webpage with the webdriver module in Selenium?
I have written a webscraping script that automatically logs into my Email account and sends a message.
Code:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
myPassword = 'XXXXXXXXXXXXXX!'
browser = webdriver.Firefox() # Opens Firefox webbrowser
browser.get('https://protonmail.com/') # Go to protonmail website
loginButton = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.btn-ghost:nth-child(1)")))
loginButton.click()
usernameElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#username")))
usernameElem.send_keys("[email protected]")
passwordElem = browser.find_element_by_css_selector("#password")
passwordElem.send_keys(myPassword)
anmeldenButton = browser.find_element_by_css_selector(".button")
anmeldenButton.click()
newMessage = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.XPATH, "/html/body/div[1]/div[3]/div/div/div[1]/div[2]/button")))
newMessage.click()
addressElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[id^='to-composer']")))
addressElem.send_keys('[email protected]')
subjectElem = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input[id^='subject-composer']")))
subjectElem.send_keys('anySubject')
WebDriverWait(browser, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='Editor']")))
WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#squire"))).send_keys('Test message')
sendButton = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body > div.app-root > div.composer-container > div > div > div > footer > div > div.button-group.button-group-solid-norm.button-group-medium > button > span")))
sendButton.click()
browser.switch_to.default_content()
I wanted the browser to click the submit button after input of the message.
I have copied the CSS selector of the span element and tried this:
sendButton = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "body > div.app-root > div.composer-container > div > div > div > footer > div > div.button-group.button-group-solid-norm.button-group-medium > button > span")))
sendButton.click()
I get the following error:
selenium.common.exceptions.NoSuchWindowException: Message: Browsing context has been discarded
I am not sure, if I targeted the right element for what I want to achieve. I often struggle to find the right strategy to target an element. What is the best way if there is no id element oder a nice and short css selector? I checked the Selenium docs (https://selenium-python.readthedocs.io/locating-elements.html) but hesitated choosing one of the suggested methods.
This is an HTML snipped fo the submit button:
<footer data-testid="composer:footer" class="composer-actions flex-item-noshrink flex max-w100">
<div class="flex flex-row-reverse flex-align-self-center w100 ml0-5 mr1-5 pl1-25 pr0-25 mb1">
<div class="button-group button-group-solid-norm button-group-medium" data-testid="composer:send-actions"><button class="button button-group-item button-ghost-weak composer-send-button" aria-busy="false" type="button" data-testid="composer:send-button" aria-describedby="tooltip-19621"><svg viewBox="0 0 16 16" class="icon-16p no-desktop no-tablet on-mobile-flex" role="img" focusable="false"><use xlink:href="#ic-paper-plane"></use></svg><span class="pl1 pr1 no-mobile">Senden</span></button></div>
<div
class="flex flex-item-fluid">
<div class="flex"><button class="button button-for-icon button-ghost-weak mr0-5" aria-busy="false" type="button" data-testid="composer:delete-draft-button" aria-describedby="tooltip-19622"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-trash"></use></svg><span class="sr-only">Entwurf löschen</span></button>
<button
class="button button-for-icon button-ghost-weak mr0-5" aria-busy="false" type="button" data-testid="composer:password-button" aria-pressed="false" aria-describedby="tooltip-19623"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-lock"></use></svg><span class="sr-only">Verschlüsselung</span></button><button aria-expanded="false" aria-busy="false" data-testid="dropdown-button" class="editor-toolbar-button interactive composer-toolbar-fontDropDown max-w100 flex flex-align-items-center flex-nowrap button button-for-icon composer-more-dropdown"
type="button" tabindex="-1" title="Weitere Optionen" aria-describedby="tooltip-19625"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-ellipsis"></use></svg><span class="sr-only">Weitere Optionen</span></button></div>
<div
class="flex-item-fluid flex pr1"><span class="mr0-5 mauto no-mobile color-weak">Nicht gespeichert</span>
<div class="composer-attachments-button-wrapper flex flex-flex-align-items-center"><label class="button button-for-icon button-ghost-weak inline-block text-center inline-flex" aria-busy="false" role="button" data-testid="composer:attachment-button" aria-describedby="tooltip-19626"><svg viewBox="0 0 16 16" class="icon-16p" role="img" focusable="false"><use xlink:href="#ic-paperclip"></use></svg><input type="file" multiple="" class="composer-attachments-button" data-testid="composer-attachments-button"></label></div>
</div>
</div>
</div>
</footer>
Solution 1:[1]
The input field for the email address and the subject is in an iframe. After switching to the iframe
WebDriverWait(browser, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[title='Editor']")))
I need to switch back to default content
browser.switch_to.default_content()
before telling the browser to click on the submit button.
Solution 2:[2]
As per the screenshot:

to identify the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using
CSS_SELECTOR:WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.button-group.button-group-solid-norm.button-group-medium > button span"))).click()
Solution 3:[3]
I would try to select the button by xpath. I think its way more accurate. If your on chrome or fire fox
right click on the an element on the browser
right click and copy and copy by full xpath
//*[@id="hireme"]/div/ul/li[4]/div/a
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | aurumpurum |
| Solution 2 | undetected Selenium |
| Solution 3 | T_Rex-87 GaMing |

