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());
  }
}
Другие вопросы по тегам