WebDriver открыть новую вкладку
Я трахнул сеть и API WebDriver. Я не вижу способа открывать новые вкладки с помощью WebDriver/Selenium2.0 .
Может кто-нибудь подтвердить, если я прав?
Спасибо, Крис. PS: текущая альтернатива, которую я вижу, это либо загружать разные URL в одном и том же окне, либо открывать новые окна.
18 ответов
Существует полностью кросс-браузерный способ сделать это с помощью веб-драйвера, те, кто говорит, что вы не можете, просто слишком ленивы. Во-первых, вам нужно использовать WebDriver для вставки и привязки тега к странице, которая открывает нужную вкладку. Вот как я это делаю (примечание: драйвер - это экземпляр WebDriver):
/**
* Executes a script on an element
* @note Really should only be used when the web driver is sucking at exposing
* functionality natively
* @param script The script to execute
* @param element The target of the script, referenced as arguments[0]
*/
public void trigger(String script, WebElement element) {
((JavascriptExecutor)driver).executeScript(script, element);
}
/** Executes a script
* @note Really should only be used when the web driver is sucking at exposing
* functionality natively
* @param script The script to execute
*/
public Object trigger(String script) {
return ((JavascriptExecutor)driver).executeScript(script);
}
/**
* Opens a new tab for the given URL
* @param url The URL to
* @throws JavaScriptException If unable to open tab
*/
public void openTab(String url) {
String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
Object element = trigger(String.format(script, url));
if (element instanceof WebElement) {
WebElement anchor = (WebElement) element; anchor.click();
trigger("var a=arguments[0];a.parentNode.removeChild(a);", anchor);
} else {
throw new JavaScriptException(element, "Unable to open tab", 1);
}
}
Далее вам нужно указать webdriver, чтобы он переключал свой текущий дескриптор окна на новую вкладку. Вот как я это делаю:
/**
* Switches to the non-current window
*/
public void switchWindow() throws NoSuchWindowException, NoSuchWindowException {
Set<String> handles = driver.getWindowHandles();
String current = driver.getWindowHandle();
handles.remove(current);
String newTab = handles.iterator().next();
locator.window(newTab);
}
После этого вы можете взаимодействовать с элементами в новом контексте страницы, используя тот же экземпляр WebDriver. Когда вы закончите с этой вкладкой, вы всегда можете вернуться к контексту окна по умолчанию, используя механизм, аналогичный функции switchWindow выше. Я оставлю это как упражнение для вас, чтобы выяснить.
Selenium WebDriver API в настоящее время не поддерживает управление вкладками в браузере.
var windowHandles = webDriver.WindowHandles;
var script = string.Format("window.open('{0}', '_blank');", url);
scriptExecutor.ExecuteScript(script);
var newWindowHandles = webDriver.WindowHandles;
var openedWindowHandle = newWindowHandles.Except(windowHandles).Single();
webDriver.SwitchTo().Window(openedWindowHandle);
У меня была такая же проблема, и я нашел ответ. Попробуй.
Robot r = new Robot();
r.keyPress(KeyEvent.VK_CONTROL);
r.keyPress(KeyEvent.VK_T);
r.keyRelease(KeyEvent.VK_CONTROL);
r.keyRelease(KeyEvent.VK_T);
Откроется новая вкладка, вы можете выполнять свои действия в новой вкладке.
Хотя нет API для открытия новой вкладки, вы можете просто создать новый экземпляр WebDriver, назвав его чем-то немного другим и передавая нужный URL-адрес на новой вкладке. После того, как вы сделали все, что вам нужно, закройте эту вкладку и установите новый драйвер в NULL, чтобы он не мешал исходному экземпляру Webdriver. Если вам нужны обе вкладки, убедитесь, что вы ссылаетесь на соответствующий экземпляр WebDriver. Использовал это для автоматизации Sitecore CMS, и это сработало.
Мы не можем создавать новые вкладки или обрабатывать вкладки с помощью веб-драйвера / selenium 2.0.
Вместо этого вы можете открыть новое окно.
@Test
public void openTab() {
//Open tab 2 using CTRL + t keys.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
//Open URL In 2nd tab.
driver.get("http://www.qaautomated.com/p/contact.html");
//Call switchToTab() method to switch to 1st tab
switchToTab();
}
public void switchToTab() {
//Switching between tabs using CTRL + tab keys.
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
//Switch to current selected tab's content.
driver.switchTo().defaultContent();
}
мы можем использовать события клавиатуры и автоматизировать открытие и переключение между несколькими вкладками очень легко. На этот пример ссылаются ЗДЕСЬ
Привет, @Paul, и у кого когда-нибудь возникают проблемы с открытием второй вкладки в python. Вот решение
Я не уверен, является ли это ошибкой в веб-драйвере или потому что она еще не совместима с mutlitab, но она определенно работает неправильно, и я покажу, как ее исправить.
Проблема: хорошо, я вижу больше чем одну проблему.
Первая проблема заключается в том, что при открытии 2-й вкладки вы можете видеть только один дескриптор вместо двух.
2-й вопрос, и вот где приходит мое решение. Кажется, что, хотя значение дескриптора все еще сохраняется в драйвере, окно по какой-то причине потеряло синхронизацию с ним.
Вот решение, решающее 2-ю проблему:
elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2)
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #Will open a second tab
#solution for the 2nd issue is here
for handle in browser.window_handles:
print "Handle is:" + str(handle) #only one handle number
browser.switch_to_window(handle)
time.sleep(3)
#Switch the frame over. Even if you have switched it before you need to do it again
browser.switch_to_frame("Frame")
"""now this is how you handle closing the tab and working again with the original tab"""
#again switch window over
elem.send_keys(Keys.CONTROL + "w")
for handle in browser.window_handles:
print "HandleAgain is:" + str(handle) #same handle number as before
browser.switch_to_window(handle)
#again switch frame over if you are working with one
browser.switch_to_frame("Frame")
time.sleep(3)
#doing a second round/tab
elem = browser.find_element_by_xpath("/html/body/div[2]/div[4]/div/a") #href link
time.sleep(2)
elem.send_keys(Keys.CONTROL + Keys.RETURN + "2") #open a 2nd tab again
"""Got it? find the handle, switch over the window then switch the frame"""
Это отлично работает для меня. Я открыт для вопросов...
Спасибо за отличную идею @ Джонатан Азофф!
Вот как я это сделал в Ruby:
def open_new_window(url)
a = @driver.execute_script("var d=document,a=d.createElement('a');a.target='_blank';a.href=arguments[0];a.innerHTML='.';d.body.appendChild(a);return a", url)
a.click
@driver.switch_to.window(@driver.window_handles.last)
end
Сделай это
_webDriver.SwitchTo().Window(_webDriver.WindowHandles.Where(x => x != _webDriver.CurrentWindowHandle).First());
или Last() и т. д.
PS нет гарантии, что WindowHandles находятся в порядке, отображаемом в вашем браузере, поэтому я бы посоветовал вам сохранить историю текущих окон, прежде чем вы выполните команду, которая вызвала открытие новой вкладки. Затем вы можете сравнить сохраненные дескрипторы окон с текущим набором и переключиться на новый в списке, из которых должен быть только один.
Я бы предпочел открыть новое окно. Есть ли разница в открытии нового окна по сравнению с открытием новой вкладки с точки зрения автоматизированного решения?
Вы можете изменить свойство цели привязки, и после нажатия на целевую страницу откроется новое окно.
Тогда используйте driver.switchTo()
переключиться в новое окно. Используйте это, чтобы решить вашу проблему
Java Robot может использоваться для отправки Ctrl+t (или Cmd+t, если MAC OS X) следующим образом:
int vkControl = IS_OS_MAC ? KeyEvent.VK_META : KeyEvent.VK_CONTROL;
Robot robot = new Robot();
robot.keyPress(vkControl);
robot.keyPress(KeyEvent.VK_T);
robot.keyRelease(vkControl);
robot.keyRelease(KeyEvent.VK_T);
Полный пример использования Chrome в качестве браузера можно найти здесь.
Вы можете попробовать этот способ, так как есть action_chain
в новом вебдрайвере. Я использую Python, поэтому, пожалуйста, игнорируйте грамматику:
act = ActionChains(driver)
act.key_down(Keys.CONTROL)
act.click(link).perform()
act.key_up(Keys.CONTROL)
Должен сказать, что я тоже это попробовал, и хотя он, по-видимому, работает с некоторыми привязками (Java, насколько говорит Джонатан, и ruby, по-видимому, тоже), с другими это не так: привязки python для селена сообщают только один дескриптор на окно, даже если содержит несколько вкладок
Для MAC OS
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://google.com")
body = driver.find_element_by_tag_name("body")
body.send_keys(Keys.COMMAND + 't')
IJavaScriptExecutor - это очень полезный класс, который может манипулировать HTML DOM во время выполнения через JavaScript, ниже приведен пример кода о том, как открыть новую вкладку браузера в Selenium через IJavaScriptExecutor:
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
object linkObj = js.ExecuteScript("var link = document.createElement('a');link.target='_blank';link.href='http://www.gmail.com';link.innerHTML='Click Me';document.getElementById('social').appendChild(link);return link");
/*IWebElement link = (IWebElement)linkObj;
link.Click();*/
browser.Click("//*[@id='social']/a[3]");
Просто чтобы понять, в Selenium нет методов, которые позволили бы вам открыть новую вкладку, приведенный выше код динамически создал бы элемент привязки и направил бы его на открытие новой вкладки.
Вместо открытия новой вкладки вы можете открыть новое окно, используя приведенный ниже код.
for(String childTab : driver.getWindowHandles())
{
driver.switchTo().window(childTab);
}
package automationexamples;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openqa.selenium.WebDriver;
/**
*
* @author Nadir
*/
public class NavigateExample {
private WebDriver driver;
public static final int OPEN_IN_NEW_TAB=1;
NavigateExample(WebDriver driver){
if(driver!=null)
this.driver = driver;
else System.out.println("Driver is NULL (Not initialized)");
}
public void navigateUrls(String[] URLS)
{
for(String URL:URLS) showURL(URL);
}
private void showURL(String URL)
{
driver.get(URL);
}
void navigateUrls(String[] URLS, int OPTION) {
for(int i=0;i<URLS.length;i++)
{
if(i>0)showURL(URLS[i],OPTION);
else showURL(URLS[i]);
}
}
private void showURL(String URL, int OPTION) {
if(OPTION==OPEN_IN_NEW_TAB)
{
createTAB();
switchToNewTAB();
}
showURL(URL);
}
private void createTAB() {
try {
Robot r = new Robot();
r.keyPress(KeyEvent.VK_CONTROL);
r.keyPress(KeyEvent.VK_T);
r.keyRelease(KeyEvent.VK_CONTROL);
r.keyRelease(KeyEvent.VK_T);
} catch (AWTException ex) {
Logger.getLogger(NavigateExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void switchToNewTAB() {
Set set=driver.getWindowHandles();
for(Iterator<String> it=set.iterator();it.hasNext();)
if(it.hasNext()) driver.switchTo().window(it.next());
}
}