How to Handle Print Dialog in Selenium

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



Leave a reply



Submit