Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to click on the print button on a web page using Selenium

I want to click on the print button in this page :

https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en

enter image description here

and then save the PDF...

enter image description here

this is the code for click the button:

String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

WebDriver driver = new HtmlUnitDriver();
driver.get(url);

System.out.println(driver.getTitle());
System.out.println(driver.getCurrentUrl());

WebElement element = driver.findElement(By.xpath("//*[@id=\"text-mode-options-header\"]/div/div/div[2]/div[2]/div/button[1]"));
element.click();

System.out.println("Page title is: " + driver.getTitle());
driver.quit();

but I get the following error:

    Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate a node using //*[@id="text-mode-options-header"]/div/div/div[2]/div[2]/div/button[1]
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.43.1', revision: '5163bce', time: '2014-09-10 16:27:58'
Driver info: driver.version: HtmlUnitDriver
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElementByXPath(HtmlUnitDriver.java:1057)
    at org.openqa.selenium.By$ByXPath.findElement(By.java:357)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver$5.call(HtmlUnitDriver.java:1575)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver$5.call(HtmlUnitDriver.java:1)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.implicitlyWaitFor(HtmlUnitDriver.java:1251)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElement(HtmlUnitDriver.java:1572)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElement(HtmlUnitDriver.java:532)
    at com.controlstation.start.Main.main(Main.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

how can I do this using Selenium? is there another way? thanks.

EDIT:

enter image description here

like image 464
FaNaJ Avatar asked Oct 23 '14 06:10

FaNaJ


People also ask

How do I access a button in Selenium?

We can click a button with Selenium webdriver in Python using the click method. First, we have to identify the button to be clicked with the help of any locators like id, name, class, xpath, tagname or css. Then we have to apply the click method on it. A button in html code is represented by button tagname.


2 Answers

Here's my insight.

First of all, you need to wait for the page to load in order to interact with the Print button. The best way to go is to use built-in mechanism: selenium waits - wait for the Print button to be clickable:

// open print dropdown
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

// click print button
WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
printButton.click();

Okay, if you run it using ChromeDriver:

package com.company;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;


public class Main {
    public static void main(String[] args) {
        String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

        WebDriver driver = new ChromeDriver();
        driver.get(url);

        // open print dropdown
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

        // click print button
        WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
        printButton.click();

        // now what? 
    }
}

You'll see the Chrome Print Preview dialog, which is, unfortunately, out of scope for selenium:

enter image description here

But, there is a hope, if you examine available Chrome arguments, you would see that there is the relevant one:

--disable-print-preview - Disables print preview (For testing, and for users who don't like us. :[ )

Okay, let's try it out:

ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-print-preview");

WebDriver driver = new ChromeDriver(options);
driver.get(url);

Now, there is a system print dialog being shown:

enter image description here

Selenium cannot control it too. So, nope, there is no hope. Oh, wait!


Okay, if we are out of scope of selenium, let's use tools that can help us to click that Print button in the dialog - Robot class:

This class is used to generate native system input events for the purposes of test automation, self-running demos, and other applications where control of the mouse and keyboard is needed.

We'll initialize the Robot and will send Enter key when the print dialog would show up:

package com.company;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.awt.*;
import java.awt.event.KeyEvent;


public class Main {
    public static void main(String[] args) throws AWTException, InterruptedException {
        String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

        Robot r = new Robot();
        r.delay(1000);

        WebDriver driver = new ChromeDriver();
        driver.get(url);

        // open print dropdown
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

        // click print button
        WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
        printButton.click();

        Thread.sleep(2000);

        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
    }
}

Other options are to use:

  • sikuli - you would need an image of the print button in order for sikuli to locate it and click
  • autoit

Also see:

  • How to handle print dialog in Selenium?
like image 80
alecxe Avatar answered Oct 20 '22 10:10

alecxe


This way you can click the Print including maps-option (sorry, but it is in C#):

Actions builder = new Actions(Driver);
builder.MoveToElement(Driver.FindElement(By.ClassName("print-button"))).Click()
       .MoveToElement(Driver.FindElements(By.ClassName("print-popup-button"))[0]).Click().Build().Perform();            

But! In your question you had a picture of Chrome print preview window, which I think won't be available with HtmlUnitDriver, which your code is using. You can always run the test with chromedriver, but it seems like the print preview is out of scope for selenium, ie. you can't control it with webdriver. To my knowledge the same is true for system print dialog, which appears with firefox. If HtmlUnitDriver behaves differently in this case, then you'll be fine, but I'm afraid you are going to face a problem here.

like image 39
JoriO Avatar answered Oct 20 '22 11:10

JoriO