![](/img/trans.png)
[英]How do i get the text of a dynamically created label , when i click from anchor tag using javascript
[英]How do I automate file selecting when the input is created by Javascript on click and never attached to the HTML document using Selenium?
例如,我有一個網頁的簡單復制(實際上代碼不是我的,我無法控制):
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<button>Click me!</button>
<script>
document.querySelector("button").addEventListener("click", () => {
const txt = document.createElement("input");
txt.type = "file";
txt.addEventListener("change", () => {
console.log(txt.files[0]);
});
txt.click();
});
</script>
</body>
</html>
如您所見,我們看到的只是一個按鈕。 單擊按鈕時,它會創建一個輸入並激活它,而無需將其附加到 HTML 文檔。
請告訴我在這種情況下如何自動化(即單擊按鈕,選擇一個文件)。 我正在使用 C# .NET 如果它是相關的,但我認為一般方向是可以的。
如果您的輸入被添加到 DOM,這將是一個簡單的問題,我相信您知道。 正常的過程如下所示:
<input type="file" id="uploadhere" />
IWebElement element = driver.FindElement(By.Id("uploadhere"));
element.SendKeys("C:\\Some_Folder\\MyFile.txt");
SendKeys
處理實際上傳的魔力,但它不是通過訪問文件上傳菜單,而是直接與輸入元素交互。
您的問題是輸入元素不在 DOM 中並且不可見。 WebDriver API旨在處理用戶可見的動態變化的 DOM 元素,模擬與 UI 的交互。 它可以單擊您的按鈕,因為它是可見的,但它看不到輸入元素,因為它不在 DOM 中或不可見。
您將在這里碰壁,無法直接使用 Selenium 解決此問題,但可能有一種解決方法。 .Net提供的Automation API可以為您提供一種監控FileDialog本身的方法。
像這樣的東西可能會提供一條路徑:
System.Windows.Forms.SendKeys.SendWait("pathToFile")
甚至是直接動作,但這很脆弱:
Actions action = new Actions(driver);
action.SendKeys(pObjElement, Keys.Space).Build().Perform();
Thread.Sleep(TimeSpan.FromSeconds(2));
var dialogHWnd = FindWindow(null, "Select a file to upload..."); // Here goes the title of the dialog window
var setFocus = SetForegroundWindow(dialogHWnd);
if (setFocus)
{
Thread.Sleep(TimeSpan.FromSeconds(2));
System.Windows.Forms.SendKeys.SendWait(pFile);
System.Windows.Forms.SendKeys.SendWait("{DOWN}");
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait("{TAB}");
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
}
通過腳本注入預先抑制單擊。 單擊時仍會創建文件輸入,但不會出現模式文件對話框。 您還必須在 DOM 中插入輸入,以便通過 Selenium 檢索它:
string JS_PREP_FILE_INPUT = @"
HTMLInputElement.prototype.click = function () {
if (!this.parentNode) {
this.style.display = 'none';
document.documentElement.appendChild(this);
this.addEventListener('change', () => this.remove());
}
}
";
driver.ExecuteScript(JS_PREP_FILE_INPUT);
driver.FindElement(By.CssSelector("button"))
.Click();
driver.FindElement(By.CssSelector("input[type=file]"))
.SendKeys("C:\\myfile.txt");
根據您共享的腳本:
<body>
<button>Click me!</button>
<script>
document.querySelector("button").addEventListener("click", () => {
const txt = document.createElement("input");
txt.type = "file";
txt.addEventListener("change", () => {
console.log(txt.files[0]);
});
txt.click();
});
</script>
</body>
將在DOM 樹中添加一個類型為<input>
且type
屬性值為file
的WebElement ,如下所示:
<input type="file" ...>
但是,一旦在HTML DOM中添加相同的<input>
標記,我看不到任何問題。 理想情況下,您應該能夠為element_to_be_clickable()
定位誘導WebDriverWait的元素,並且您可以使用以下任一定位器策略:
考慮到元素是 DOM 樹中唯一的<input>
元素,使用CssSelector :
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("input[type='file']"))).SendKeys("/filename/with/absolute/path");
考慮到元素是 DOM 樹中唯一的<input>
元素,使用XPath :
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//input[@type='file']"))).SendKeys("/filename/with/absolute/path");
考慮到 DOM 樹中存在多個<input>
元素,使用XPath :
new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//button[text()='Click me:']//following:.input[@type='file']")));SendKeys("/filename/with/absolute/path");
如果您需要SeleniumExtras.WaitHelpers
:
new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementToBeClickable(By.XPath("//input[@type='file']"))).SendKeys("/filename/with/absolute/path");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.