WebDriver открыть новую вкладку

Я просмотрел Интернет и API WebDriver. Я не вижу возможности открывать новые вкладки с помощью WebDriver/Selenium2.0.

Кто-нибудь может подтвердить, прав ли я?

Спасибо, Крис. P.S. Текущая альтернатива, которую я вижу, заключается в том, чтобы либо загружать разные URL-адреса в одном окне, либо открывать новые окна.


person ChrisOdney    schedule 21.06.2011    source источник
comment
Я добавил правильный ответ на ваш конкретный вопрос, но, учитывая ваше заявление об альтернативах, я подозреваю, что в вашем вопросе есть нечто большее. Если вы хотите предоставить больше контекста, можно дать более полный ответ.   -  person JimEvans    schedule 22.06.2011


Ответы (17)


Существует полностью кросс-браузерный способ сделать это с помощью веб-драйвера, те, кто говорит, что вы не можете, просто слишком ленивы. Во-первых, вам нужно использовать 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);
    }       
}

Затем вам нужно указать веб-драйверу переключить текущий дескриптор окна на новую вкладку. Вот как я это делаю:

/**
 * 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. Я оставлю это в качестве упражнения для вас, чтобы понять.

person Jonathan Azoff    schedule 03.02.2012
comment
что такое locator в последней строке switchWindow()? - person jamesfzhang; 13.03.2012
comment
Я полагаю, что в обычной неудаленной версии Webdriver локатором может быть просто driver.switchTo(), верно? - person djangofan; 02.04.2012
comment
Я согласен с тем, что приведенный здесь код откроет новую вкладку в любом окне браузера через WebDriver. Однако нет гарантии, что конкретный драйвер сможет управлять полученной новой вкладкой. - person JimEvans; 02.05.2012
comment
Хороший обходной путь ... просто я не могу поймать созданную новую вкладку. Я использую С#.net Любая помощь приветствуется - person sumit_programmer; 18.12.2012
comment
@Jonathan Azoff Как вы тогда управляете открытой вкладкой? Открытие вкладки выполнимо, но вызовет у вас бесконечное горе, если драйвер не может обрабатывать вкладки. - person AutomatedTester; 07.03.2013
comment
Я часами пытался открыть новую вкладку, отправив клавиши CONTROL 't', это единственное решение, которое сработало для меня. +1 - person maxenglander; 17.12.2014
comment
Это сообщение SO помогло с этим ответом для C#. Чтобы получить JavaScriptExectutor, создайте метод вроде public static IJavaScriptExecutor Scripts(this IWebDriver driver) { return (IJavaScriptExecutor)driver; } - person JabberwockyDecompiler; 27.05.2015

API Selenium WebDriver в настоящее время не поддерживает управление вкладками в браузере.

person JimEvans    schedule 22.06.2011
comment
Спасибо, Джим, я хотел убедиться, что нет возможности обрабатывать вкладки. Под альтернативами я подразумеваю только то, как еще я мог бы обрабатывать просмотр с вкладками, здесь нет особых случаев, поэтому открытие нескольких окон мне кажется нормальным. - person ChrisOdney; 23.06.2011
comment
Downvoters: Это ответ, который вы получите от самого проекта. То, что вам не нравится этот ответ, не означает, что он неправильный или некачественный. - person JimEvans; 02.05.2012
comment
@JimEvans, этот ответ плохого качества, потому что он не отвечает на вопрос. Ответы ниже, показывающие обходные пути, более полезны. Ответ, который гласит: «Вот неуклюжий способ сделать это», всегда будет более полезным, чем ответ, в котором говорится: «Вы не можете этого сделать». - person Ryan Lundy; 07.03.2014
comment
@Kyralessa С уважением, я не согласен. Правильный ответ иногда это, Вы не можете этого сделать. И это верно в данном случае. API этого не поддерживает и не будет поддерживать. Любой из так называемых обходных путей в других ответах может открыть новую вкладку, но нет гарантии, что WebDriver сможет открыть новую вкладку. На самом деле, я совершенно уверен, что по крайней мере один браузер не будет. Вместо того, чтобы давать ложную надежду на то, что любое решение будет работать в разных браузерах (одно из основных обещаний WebDriver), гораздо лучше четко понимать ограничения. - person JimEvans; 07.03.2014
comment
@JimEvans, я не говорю, что твой ответ неверен. Беда в том, что это не полезно. Нет способа сделать это, чтобы никому не помочь решить его/ее проблему. И на самом деле есть обходные пути; Я смог сделать это с помощью ChromeDriver, просто имитируя щелчок мышью по ссылке. Selenium распознает вкладки как отдельные окна. Редактирование вашего ответа с включением обходных путей такого рода сделает его полезным, а не просто правильным. - person Ryan Lundy; 07.03.2014
comment
@Kyralessa Вы смогли заставить его работать в Chrome. Здорово. Подскажите, в IE или Safari тоже работает? Да, и помните, что только потому, что он работает в Chrome сегодня, поскольку он явно не поддерживается API, нет абсолютно никакой гарантии, что он продолжит работать в будущих версиях. Рад, что вы смогли заставить его работать в некоторых случаях. - person JimEvans; 08.03.2014
comment
@JimEvans, позвольте мне попытаться объяснить это еще раз. Не все делают кроссбраузерную работу. Одним из примеров являются внутренние веб-приложения, где имеет смысл указать стандартный браузер, а не выполнять работу по поддержке нескольких браузеров. Таким образом, хорошим ответом было бы: официально это не поддерживается; но есть несколько не кросс-браузерных способов сделать это, например этот и этот, на случай, если это поможет в вашей конкретной ситуации. - person Ryan Lundy; 18.07.2014
comment
Нет необходимости повторять то, что вы уже сказали. Я полностью понимаю. Я просто не согласен с вами. Поскольку вы, похоже, полны решимости попытаться убедить людей в том, что ответ, предоставленный самим проектом, неверен или менее полезен, чем ответ, работа которого не может быть гарантирована авторами проекта, а также полны решимости сказать последнее слово по этому вопросу, я просто пусть это будет мой последний комментарий по этому вопросу. - person JimEvans; 19.07.2014

У меня была такая же проблема, и я нашел ответ. Попробуй.

Robot r = new Robot(); 
r.keyPress(KeyEvent.VK_CONTROL); 
r.keyPress(KeyEvent.VK_T); 
r.keyRelease(KeyEvent.VK_CONTROL); 
r.keyRelease(KeyEvent.VK_T);

Откроется новая вкладка, в которой вы сможете выполнять свои действия.

person deactivate    schedule 30.11.2012
comment
Интересная идея. Будет ли это работать через канал Selenium Grid? - person djangofan; 14.02.2014

Хотя API для открытия новой вкладки не существует, вы можете просто создать новый экземпляр WebDriver, назвав его немного другим и передав нужный URL-адрес в новой вкладке. После того, как вы сделали все, что нужно, закройте эту вкладку и сделайте новый драйвер NULL, чтобы он не мешал исходному экземпляру Webdriver. Если вам нужно открыть обе вкладки, убедитесь, что вы ссылаетесь на соответствующий экземпляр WebDriver. Использовал это для автоматизации Sitecore CMS, и это сработало.

person Ola Ajibode    schedule 05.12.2011

Спасибо за прекрасную идею @Jonathan Azoff!

Вот как я это сделал в 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
person bbbco    schedule 30.03.2012

Мы не можем создавать новые вкладки или обрабатывать вкладки с помощью веб-драйвера/селена 2.0.

Вместо этого вы можете открыть новое окно.

person Mayur Shah    schedule 19.12.2011

Привет, @Paul, и у кого когда-либо возникала проблема с открытием второй вкладки в python. Вот решение

Я не уверен, является ли это ошибкой в ​​​​веб-драйвере или потому, что он еще не совместим с mutlitab, но он определенно работает неправильно, и я покажу, как это исправить.

Проблема: я вижу более одной проблемы.

Первая проблема должна заключаться в том, что когда вы открываете вторую вкладку, вы видите только один дескриптор вместо двух.

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"""

Он отлично работает для меня. Я открыт для вопросов...

person Khaled Nakawa    schedule 29.04.2013

Сделай это

_webDriver.SwitchTo().Window(_webDriver.WindowHandles.Where(x => x != _webDriver.CurrentWindowHandle).First());

или Last() и т. д.

PS нет никакой гарантии, что WindowHandles находятся в порядке, отображаемом в вашем браузере, поэтому я бы посоветовал вам сохранить некоторую историю текущих окон, прежде чем выполнять команду, которая вызвала открытие новой вкладки. Затем вы можете сравнить свои сохраненные дескрипторы окон с текущим набором и переключиться на новый в списке, из которых должен быть только один.

person kernowcode    schedule 03.04.2014

@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();  
 } 

мы можем использовать события клавиатуры и очень легко автоматизировать открытие и переключение между несколькими вкладками. Этот пример взят из ЗДЕСЬ

person anuja jain    schedule 11.01.2017

Должен сказать, что я тоже пробовал это, и хотя это, по-видимому, работает с некоторыми привязками (Java, насколько говорит Джонатан, и ruby, по-видимому, тоже), с другими это не так: привязки selenium python сообщают только один дескриптор на окно, даже если содержащий несколько вкладок

person Pa_    schedule 15.02.2012

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 нет методов, которые позволили бы вам открыть новую вкладку, приведенный выше код динамически создает элемент привязки и направляет его на открытие новой вкладки.

person Anand    schedule 29.11.2012

Можно попробовать так, благо в новом вебдрайвере есть action_chain. Я использую Python, поэтому не обращайте внимания на грамматику:

act = ActionChains(driver)
act.key_down(Keys.CONTROL)
act.click(link).perform()
act.key_up(Keys.CONTROL)
person Li Liu    schedule 05.06.2013

Для MAC-ОС

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')
person Md. Nazmul Haque Sarker    schedule 13.02.2014

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 в качестве браузера можно разветвить здесь.

person Boni García    schedule 01.12.2016

Я бы предпочел открыть новое окно. Есть ли разница в открытии нового окна и открытии новой вкладки с точки зрения автоматизированного решения?

вы можете изменить целевое свойство привязки, и после щелчка целевая страница откроется в новом окне.

Затем используйте driver.switchTo() для переключения в новое окно. Используйте его для решения вашей проблемы

person Shrikant Khadilkar    schedule 30.09.2012

Вместо открытия новой вкладки вы можете открыть новое окно, используя приведенный ниже код.

for(String childTab : driver.getWindowHandles())
    {
        driver.switchTo().window(childTab);
    }
person bugCracker    schedule 14.06.2013

person    schedule
comment
Это решило мою проблему с открытием вкладок в chromedriver. - person janderson; 07.04.2015