首页 > 解决方案 > 如何使用applescript从chromedriver实例关闭上传对话框窗口?

问题描述

我有一个硒测试(准确地说是硒),该场景需要上传文件。我要上传文件的元素是一个隐藏的输入字段,它位于 DOM 的末尾;

<input type="file" style="height: 0; width: 0; visibility: hidden;" tabindex="-1" accept="*">

并且仅在单击文件应该被“拖放”或从系统加载的区域后出现;

<a class="browse" ref="fileBrowse" href="#">select files...</a>

这意味着我无法使用迄今为止我知道的任何方法,而无需先单击该元素 - 例如,sendKeys、uploadFile、uploadFromClassPath 等。但是,当我单击该元素时,会出现一个对话框窗口。加载文件后,窗口不会关闭,我还没有找到一个可靠的解决方案来关闭该窗口。

对话窗口在 macOS 和 chrome 设置中的外观

我正在使用 macOS 和 chrome,这意味着我无法使用“autoIT”,也无法运行“sikuliX”来创建简单的屏幕截图脚本。

但是,如果我们忽略了 Web 驱动程序的实例存在,我可以使用 Automator 打乱一个 AppleScript,它工作得很好。意义; 如果我从控制台运行脚本,将网站设置为与自动化测试完全一致 - 它可以工作......不幸的是,一旦测试实例化并在 webdriver 中运行,它就无法工作。

有两个问题希望有经验的大侠解答一下:

1)如何让applescript使用webdriver的实例而不是常规的chrome窗口——如果能以某种方式解决这个问题,这是一个非常巧妙的解决方案

2)关于如何关闭上传对话框窗口的任何其他想法?

小程序


on run {input, parameters}
    -- Click “Google Chrome” in the Dock.
    delay 6.006100
    set timeoutSeconds to 2.000000
    set uiScript to "click UI Element \"Google Chrome\" of list 1 of application process \"Dock\""
    my doWithTimeout( uiScript, timeoutSeconds )
    return input

    -- Click the ÒCancelÓ button.
    delay 3.763318
    set timeoutSeconds to 2.0
    set uiScript to "click UI Element \"Cancel\" of sheet 1 of window \"PowerFLOW portal - Google Chrome\" of application process \"Chrome\""
    my doWithTimeout(uiScript, timeoutSeconds)
    return input
end run

on doWithTimeout(uiScript, timeoutSeconds)
    set endDate to (current date) + timeoutSeconds
    repeat
        try
            run script "tell application \"System Events\"
" & uiScript & "
end tell"
            exit repeat
        on error errorMessage
            if ((current date) > endDate) then
                error "Can not " & uiScript
            end if
        end try
    end repeat
end doWithTimeout

用于在测试中运行脚本的代码

      try {
        new ProcessBuilder("/path/to/the/script").start();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

除了尝试使用 applescript,我还尝试了“java 机器人类”,但无法关闭对话框窗口。

使用下面的代码片段,未注释的部分会转义整个 chrome 窗口(窗口变为“灰色”/非活动状态)而不是对话框窗口,这真的让我感到惊讶,因为我认为对话框窗口是当时的主要工作窗口。

注释的部分有效,但正如您可以想象的那样,如果测试在任何其他机器上运行,它是无用的,因为坐标仅特定于我的机器。

try {
        Robot robot = new Robot();
        //robot.mouseMove(906, 526);
        //robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        //robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

        robot.keyPress(KeyEvent.VK_ESCAPE);
        robot.keyRelease(KeyEvent.VK_ESCAPE);
    } catch (AWTException e) {
        e.printStackTrace();
      }

该方法本身看起来就像这样

$$x("#ElementsCollection")
        .findBy("text1")
        .scrollIntoView(true)
        .find(byXpath("#xpath")).val("text2")
        .find(byXpath("#xpath") //this is the location of the <a> element mentioned above that needs to be clicked in order for <input type file> element to appear
        .click();

$x("//input[@type=\"file\"]").sendKeys("/path/to/the/uploadedFile");

标签: javamacosseleniumapplescriptselenide

解决方案


如我所见,实现目标的原始复杂性是

该文件是一个隐藏的输入字段

并且仅在单击文件应该被“拖放”或从系统加载的区域后出现;

即——隐藏文件。如果我错了,请纠正我:)

但这应该不是问题,因为 Selenium WebDriver 的 sendKeys 命令适用于 type=file 的输入标记的隐藏元素。所以只是简单的 sendKeys 应该通过。Selenide 的 uploadFromClassPath 命令基于原始的 sendKeys - 所以它也应该通过。

这是一个简单的测试,表明上传文件不依赖于输入元素的可见性:

import org.junit.jupiter.api.Test;

import static com.codeborne.selenide.Condition.hidden;
import static com.codeborne.selenide.Condition.text;
import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.Selenide.$;

public class TheInternetTest {
    @Test
    void fileUpload() {
        // GIVEN
        open("https://the-internet.herokuapp.com/upload");
        executeJavaScript(
                "document.getElementById('file-upload').style.display = 'none'"
        );
        $("#file-upload").shouldBe(hidden);

        // WHEN
        $("#file-upload").uploadFromClasspath("temp.txt");
        $("#file-submit").click();

        // THEN
        $("#uploaded-files").shouldHave(text("temp.txt"));
    }
}

在此处使用此代码检查完整的工作项目:https ://github.com/yashaka/selenide-file-upload-demo/blob/main/src/test/java/TheInternetTest.java

PS 编写 Web UI 测试时的常见最佳实践是“找到达到目标的简单方法,而不是在真实用户模拟的上下文中找到最佳方法”。这就是为什么我们试图绕过所有对被测应用程序失控的窗口。所以我的建议是——忘记苹果脚本,直接通过 selenium webdriver 处理输入文件。


推荐阅读