How to handle print dialog in Selenium?
Unfortunately, WebDriver can't handle these (or any other browser or OS dialog). Moreover, they tend to look differently across browsers / systems / language settings, so there's probably no definite answer. You'll need to detect and handle every possible case in order to make it work everywhere. Your options include:
The
Robot
class, it allows you to "press" programatically anything on the keyboard (or clicking blindly) and therefore getting rid of the dialog by, say, pressing Enter or Esc. However, as told above, any advanced interaction is dependant on OS / language / printer.// press Escape programatically - the print dialog must have focus, obviously
Robot r = new Robot();
r.keyPress(KeyEvent.VK_ESCAPE);
r.keyRelease(KeyEvent.VK_ESCAPE);AutoIt. It's a Windows program useful for handling any system-level automation. Same dependancy as above.
That's more or less it. If you can avoid the print dialog, try to take screenshot of the page and print it using standard Java tools.
How can I tell Selenium to press cancel on a print popup?
I would simply disable the print dialog by overriding the print method :
((JavascriptExecutor)driver).executeScript("window.print=function(){};");
But if you goal is to test that the printing is called then :
// get the print button
WebElement print_button = driver.findElement(By.cssSelector("..."));
// click on the print button and wait for print to be called
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);
((JavascriptExecutor)driver).executeAsyncScript(
"var callback = arguments[1];" +
"window.print = function(){callback();};" +
"arguments[0].click();"
, print_button);
Selenium ChromeDriver not interacting with Chrome Print Dialog
Problem Explanation
You do not need to switch to Print Modal pop up
. Because it is not a new windows/tab
neither it is in frame
. So switching is the culprit here.
Solution
I would recommend you to use WebDriverWait
which is an explicit waits in Selenium
library.
to click
on Print
which is in top right corner use this xpath
and code
:
wait = WebDriverWait(driver, 20)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
Once this is clicked you'd see a new pop up
with Print
and Cancel
button
.
to click on Print in the pop up, the below code should help you past the issue that you've been facing.
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(@class,'action')]"))).click()
Imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Update 1 :
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.implicitly_wait(50)
driver.get("https://outlook.live.com/owa/?state=1&redirectTo=aHR0cHM6Ly9vdXRsb29rLmxpdmUuY29tL2NhbGVuZGFyLw&nlp=1")
wait = WebDriverWait(driver, 20)
#User Must place Email:
USER_EMAIL = 'user name should be given here'
USER_PASSWORD = 'password should be here'
emailField = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='email']")))
emailField.clear()
emailField.send_keys(USER_EMAIL)
submitEmail= WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
#Dismiss "It looks like this email is used with more than one account from Microsoft" screen
#personalAccount = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[id='msaTile']"))).click()
#Enter Password
passwordField = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='password']")))
passwordField.clear()
passwordField.send_keys(USER_PASSWORD)
submitPassword = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[type='submit']"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.table-row"))).click()
time.sleep(30)
wait.until(EC.element_to_be_clickable((By.ID, "idSubmit_SAOTCC_Continue"))).click()
#Dismiss StaySignedIn
staySignedIn = WebDriverWait(driver,40).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"input[id='idBtn_Back']"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[title='Calendar']"))).click()
printBtn1 = WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Print']/ancestor::button[contains(@role,'menuitem')=false]"))).click()
Handle Print Preview window using selenium in chrome latest version
Here is the solution in python. You can convert this method to java.
def cancelPrintPreview():
# get the current time and add 180 seconds to wait for the print preview cancel button
endTime = time.time() + 180
# switch to print preview window
driver.switch_to.window(driver.window_handles[-1])
while True:
try:
# get the cancel button
cancelButton = driver.execute_script(
"return document.querySelector('print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('print-preview-header#header').shadowRoot.querySelector('paper-button.cancel-button')")
if cancelButton:
# click on cancel
cancelButton.click()
# switch back to main window
driver.switch_to.window(driver.window_handles[0])
return True
except:
pass
time.sleep(1)
if time.time() > endTime:
driver.switch_to.window(driver.window_handles[0])
break
You can check my answer here for more information on working with shadow-root elements.
How to handle Firefox print dialog box in Selenium
Both the solutions below are designed NOT to launch the print dialog.
These solutions will either print the active webpage to your local printer or to a PDF file without having to deal with the dialog.
UPDATED POST 08-19-2021
I wanted to save the output to PDF vs printing to paper. I was shocked how hard it was to print to a PDF using the geckodriver
and selenium
. With the 'chromedriver' you can call the function 'execute_cdp_cmd' and pass Page.printToPDF
. The geckodriver
doesn't have 'execute_cdp_cmd'.
When I looked through Stack Overflow
for inspiration, I discover multiple open question on printing pdf using the geckodriver
with selenium
. After seeing that this was a problem, I looked through the issues in selenium
and the bug reports for mozilla
. Again this was a problem that others had.
Some of the bug reports mentioned that certain switches used in the print process no longer worked.
profile.set_preference("print.print_to_file", True)
profile.set_preference("print.print_to_filename", "/tmp/file.pdf")
I decided to look at the source code for mozilla gecko-dev for a potential solution. After hours of research I found that the switches above were replaced with new ones and that another printer variable had also been replaced. After some testing, I was able to get your webpage to save as PDF.
The code below will print a webpage to a PDF with all the links enabled. I would recommend adding some error handling to the code. One part of the code that I need to improve on the filename part. You should be able to add a function that will rename the file, which would allow you to print as many files as you want in a single session.
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.options import FirefoxProfile
firefox_options = Options()
firefox_options.add_argument("--disable-infobars")
firefox_options.add_argument("--disable-extensions")
firefox_options.add_argument("--disable-popup-blocking")
profile_options = FirefoxProfile()
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11.5; rv:90.0) Gecko/20100101 Firefox/90.0'
profile_options.set_preference('profile_options = FirefoxProfile()', user_agent)
profile_options.set_preference("print_printer", "Mozilla Save to PDF")
profile_options.set_preference("print.always_print_silent", True)
profile_options.set_preference("print.show_print_progress", False)
profile_options.set_preference('print.save_as_pdf.links.enabled', True)
profile_options.set_preference("print.printer_Mozilla_Save_to_PDF.print_to_file", True)
# set your own file path
profile_options.set_preference('print.printer_Mozilla_Save_to_PDF.print_to_filename',
"tmp/testprint.pdf")
driver = webdriver.Firefox(executable_path='/usr/local/bin/geckodriver', options=firefox_options,
firefox_profile=profile_options)
URL = 'https://finance.yahoo.com/'
driver.get(URL)
sleep(10)
search_field_id = 'yfin-usr-qry'
element_search_field = driver.find_element_by_id(search_field_id)
element_search_field.clear()
element_search_field.send_keys('TSLA')
element_search_field.send_keys(Keys.ENTER)
sleep(10)
driver.execute_script("window.print()")
sleep(20)
driver.quit()
ORIGINAL POST 08-18-2021
I decided to look at your issue, because I'm interested in selenium
functionality.
I looked through the source code of the geckodriver
and found printUtils.js, which provides details on the switches used in the print process, such as these:
firefox_options.set_preference("print.always_print_silent", True)
firefox_options.set_preference("print.show_print_progress", False)
After removing some of your code and adding some, I was able to print to my HP printer with the code below without dealing with a print dialog box:
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.options import FirefoxProfile
firefox_options = Options()
firefox_options.add_argument("--disable-infobars")
firefox_options.add_argument("--disable-extensions")
firefox_options.add_argument("--disable-popup-blocking")
profile_options = FirefoxProfile()
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11.5; rv:90.0) Gecko/20100101 Firefox/90.0'
firefox_options.set_preference('profile_options = FirefoxProfile()', user_agent)
firefox_options.set_preference("print.always_print_silent", True)
firefox_options.set_preference("print.show_print_progress", False)
firefox_options.set_preference("pdfjs.disabled", True)
driver = webdriver.Firefox(executable_path='/usr/local/bin/geckodriver', options=firefox_options)
URL = 'https://finance.yahoo.com/'
driver.get(URL)
sleep(10)
search_field_id = 'yfin-usr-qry'
element_search_field = driver.find_element_by_id(search_field_id)
element_search_field.clear()
element_search_field.send_keys('TSLA')
element_search_field.send_keys(Keys.ENTER)
sleep(10)
driver.execute_script("window.print()")
----------------------------------------
My system information
----------------------------------------
Platform: Apple
OS: 10.15.7
Python: 3.9
Selenium: 3.141
Firefox: 90.0.2
Geckodriver: 0.29.0
----------------------------------------
Related Topics
How to Avoid a Lot of If Else Conditions
How to Do a Soap Web Service Call from Java Class
Should Getters and Setters Be Synchronized
Getting Database Connection in Pure JPA Setup
Singleton Design Pattern: Pitfalls
Converting Decimal to Binary Java
Parallel Streams, Collectors and Thread Safety
Compare One String with Multiple Values in One Expression
Why Do == Comparisons with Integer.Valueof(String) Give Different Results for 127 and 128
Differencebetween 'Super' and 'Extends' in Java Generics
Gradle to Execute Java Class (Without Modifying Build.Gradle)
What Is the Purpose of Defining a Package in a Java File
Java: Convert String to Timestamp
Java's Date(...) Constructor Is Deprecated; What Does That Mean
How to Wait Until an Element Is Present in Selenium
Cannot Find Firefox Binary in Path. Make Sure Firefox Is Installed