简体   繁体   English

如何处理 Selenium 中的打印对话框?

[英]How to handle print dialog in Selenium?

I have to handle print dialog (the same one that appears when clicking ctrl-p in browser).我必须处理打印对话框(与在浏览器中单击 ctrl-p 时出现的对话框相同)。 I tried with:我试过:

Alert printDialog = driver.switchTo().alert();
printDialog.dismiss();

but it didn't work.但它没有用。 Also I couldn't catch its window handle, because it's not a window...我也无法抓住它的窗口句柄,因为它不是一个窗口......

Is it possible to handle these objects and how?是否可以处理这些对象以及如何处理?

Unfortunately, WebDriver can't handle these (or any other browser or OS dialog).不幸的是,WebDriver 无法处理这些(或任何其他浏览器或操作系统对话框)。 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 .Robot类,它允许您以编程方式“按下”键盘上的任何内容(或盲目单击),因此通过按EnterEsc来摆脱对话框。 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.它是一个 Windows 程序,可用于处理任何系统级自动化。 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 .如果您可以避免打印对话框,请尝试截取页面的屏幕截图并使用标准 Java 工具打印它。

One CAN handle Print dialog with Selenium in Chrome.一个可以在 Chrome 中使用 Selenium 处理打印对话框。 Not sure about other browsers.不确定其他浏览器。

Access to Print dialog was added in ChromeDriver-2.17.在 ChromeDriver-2.17 中添加了对打印对话框的访问。 Details can be found here: https://bugs.chromium.org/p/chromedriver/issues/detail?id=1087可以在这里找到详细信息: https ://bugs.chromium.org/p/chromedriver/issues/detail?id=1087

Right-click on Print dialog -> Inspect Element.右键单击“打印对话框”->“检查元素”。 As a result, the DOM of Print dialog will open in a separate window.因此,打印对话框的 DOM 将在单独的窗口中打开。 Now you can produce locators for any element on the dialog and use them in your tests.现在您可以为对话框中的任何元素生成定位器并在您的测试中使用它们。

To close the Print dialog one can do the following:要关闭“打印”对话框,可以执行以下操作:

//Switch to Print dialog
Set<String> windowHandles = driver.getWindowHandles();
if (!windowHandles.isEmpty()) {
    driver.switchTo().window((String) windowHandles.toArray()[windowHandles.size() - 1]);
}
//Now work with the dialog as with an ordinary page:  
driver.findElement(By.className("cancel")).click();

I was able to resolve this issue by adding --kiosk-printing which bypasses the print dialog completely.我能够通过添加完全绕过打印对话框的--kiosk-printing来解决这个问题。 I have my default print set to pdf, so I end up with a pdf in my Downloads folder, but at least selenium doesn't hang.我将我的默认打印设置为 pdf,所以我最终在我的下载文件夹中得到了一个 pdf,但至少 selenium 没有挂起。 Here's what the code looks like:代码如下所示:

        ChromeOptions cOptions = new ChromeOptions();
        cOptions.addArguments("kiosk-printing");
        RemoteWebDriver driver = new RemoteWebDriver(hostUrl, cOptions);

Slanec's answer is correct - WebDriver doesn't have native capability for this. Slanec 的回答是正确的——WebDriver 没有这方面的本机功能。 The way I solved this in Windows is with the System.Windows.Forms.SendKeys object:我在 Windows 中解决这个问题的方法是使用 System.Windows.Forms.SendKeys 对象:

    SendKeys.SendWait("^p");
    System.Threading.Thread.Sleep(500);
    SendKeys.SendWait("~");

    // give it a minute to spool onto the printer
    System.Threading.Thread.Sleep(5000);

I've actually got this in a loop printing off a bunch of statements.我实际上已经在循环中打印了一堆语句。 Works like a charm.奇迹般有效。

You can simply close the browser after the print dialog has appeared.出现打印对话框后,您只需关闭浏览器即可。 This is admittedly a somewhat drastic measure, but the advantages are:诚然,这是一个有点过激的措施,但优点是:

  • it is simple很简单
  • it does not require any external tools它不需要任何外部工具
  • it works across OSes and browsers它适用于操作系统和浏览器

Just call:只需致电:

myWebDriver.quit();

Typically, you would run your test, and check elements on the page to be printed as usual.通常,您会运行测试,并照常检查要打印的页面上的元素。 WebDriver can check page elements even if the print dialog is open.即使打印对话框打开,WebDriver 也可以检查页面元素。

Once you are done, quit the browser (and fire up a new one for the next test).完成后,退出浏览器(并为下一次测试启动一个新浏览器)。


We have used this successfully on a project.我们已经在一个项目中成功地使用了它。 To make things easier, we wrote a wrapper class that keeps track of a "current WebDriver instance".为了使事情变得更容易,我们编写了一个包装类来跟踪“当前 WebDriver 实例”。 I has methods to retrieve this instance (creating one as required) and to close it.我有方法来检索这个实例(根据需要创建一个)并关闭它。 That way, you can always call getCurrentWebDriver() and get a valid instance (reused or freshly created).这样,您始终可以调用getCurrentWebDriver()并获取有效实例(重复使用或新创建的)。

Another option could be to edit Windows registry for Chrome to disable print window.另一种选择是为 Chrome 编辑 Windows 注册表以禁用打印窗口。

--disable-print-preview - flag that will tell Chrome to disable print preview --disable-print-preview - 告诉 Chrome 禁用打印预览的标志

  1. Go to Registry Editor转到注册表编辑器
  2. Navigate to "Computer\HKEY_CLASSES_ROOT\ChromeBHTML\shell\open\command"导航到“Computer\HKEY_CLASSES_ROOT\ChromeBHTML\shell\open\command”
  3. Set value to be: "C:\Program Files (x86)\Google\Chrome Beta\Application\chrome.exe" --disable-print-preview将值设置为:"C:\Program Files (x86)\Google\Chrome Beta\Application\chrome.exe" --disable-print-preview

This solution worked for my specific case.该解决方案适用于我的具体案例。

Using Selenium and Facebook WebDriver with Codeception, I had the same problem – the test scenario would stop running because the print dialog prevented any interaction with the page.使用带有 Codeception 的 Selenium 和 Facebook WebDriver,我遇到了同样的问题——测试场景将停止运行,因为打印对话框阻止了与页面的任何交互。

I ended up not opening the print dialog in the test environment (example using Symfony and Twig):我最终没有在test环境中打开打印对话框(使用 Symfony 和 Twig 的示例):

{# Selenium can't interact with the OS native print dialog. #}
{# Therefore, it's disabled in the test environment. #}
{% if app.environment != 'test' %}
    $(document).ready(function () {
        var orderShouldBePrinted = window.location.href.indexOf(
            'print=true'
        ) !== -1;

        if (orderShouldBePrinted) {
            window.print();
        }
    });
{% endif %}

This has the advantage of not stopping the test.这具有不停止测试的优点。 However, it doesn't allow testing that the print dialog actually appears.但是,它不允许测试打印对话框是否实际出现。

As a smoke test, I added $I->seeInCurrentUrl('print=true');作为冒烟测试,我添加了$I->seeInCurrentUrl('print=true'); (because this URL parameter triggers window.print() ). (因为此 URL 参数触发window.print() )。

I was trying to print 100+ pages from a patterned list on a website that did not allow for a 'print-all'.我试图从不允许“全部打印”的网站上的图案列表中打印 100 多页。 So selenium would help me with this automatically in theory.所以硒在理论上会自动帮助我。 I came up with a completely unorthodox solution to the print dialog window.我想出了一个完全非正统的打印对话框窗口解决方案。

##Python code
import time
import threading
from pynput.mouse import Button, Controller
mouse = Controller()

##selenium starting up website stuff here

def website_print_button():
    browser.find_element_by_id('printButton').click()

def push():
    time.sleep(4)    #4 second delay to give the computer time to open print dialog
    mouse.position = [1131, 733] #where my print button is located
    mouse.click(Button.left, 1)

def letsgo():

    for x in range(printing_amount):
        browser.find_element_by_xpath('/html/body/div[1]/form/table[4]/tbody/tr['+str(x+1)+']/td[1]/a/b').click()
        browser.find_element_by_css_selector('ul.light-green.button').click()
        browser.switch_to.window(browser.window_handles[1])
        t2 = threading.Thread(target=push)
        t2.start()
        t1 = threading.Thread(target=website_print_button)
        t1.start()
        time.sleep(5)
        browser.close()
        browser.switch_to.window(browser.window_handles[0])
        browser.find_element_by_class_name('c').click()

Selenium would usually get stuck waiting for something to happen when the print dialog window opened up.当打印对话窗口打开时,Selenium 通常会卡住等待发生某些事情。 I used something I recently learned called 'Threading' and this allowed me to do two things at once technically.我使用了我最近学到的称为“线程”的东西,这让我在技术上可以同时做两件事。 I would call for a click to initiate in 4 seconds (push function) and then immediately after, Selenium would click on the websites print button.我会要求点击在 4 秒内启动(推送功能),然后 Selenium 会立即点击网站打印按钮。 When Selenium opened up the print dialog window, it became stuck waiting around, but the delayed click was still running and waiting to click after 4 seconds of selenium opening the print window.当 Selenium 打开打印对话框窗口时,它卡住了等待,但延迟点击仍在运行,并在 selenium 打开打印窗口 4 秒后等待点击。 Then the click would execute, and selenium retook control because the print window was taken care of.然后单击将执行,并且 selenium 重新控制,因为打印窗口已得到处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM