Como mudar para a nova janela do navegador, que se abre após clicar no botão?


86

Tenho situação, ao clicar no botão abre uma nova janela do navegador com os resultados da pesquisa.

Existe alguma maneira de conectar e focar na nova janela do navegador aberta?

E trabalhe com ele e, em seguida, volte à janela original (primeira).


Podemos fazer a troca automaticamente - verifique aqui o uso avançado - testautomationguru.com/…
vins

Respostas:


117

Você pode alternar entre as janelas conforme abaixo:

// Store the current window handle
String winHandleBefore = driver.getWindowHandle();

// Perform the click operation that opens new window

// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
    driver.switchTo().window(winHandle);
}

// Perform the actions on new window

// Close the new window, if that window no more required
driver.close();

// Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);

// Continue with original browser (first window)

3
Posso confirmar que a solução aceita funciona de forma consistente no Chrome, mas não no IE. O novo identificador de janela não é reconhecido no IE. @Elmue está incorreto porque getWindowHandles()retorna um Conjunto e um Conjunto não garante o pedido . O último elemento nem sempre é a última janela. Estou surpreso que seu comentário tenha muitos votos positivos.
prata de

@silver: Não tenho ideia do que você está falando. Em meu código, WindowHandles retorna um ReadOnlyCollection <string> para o qual posso garantir que a última entrada é sempre a última janela aberta. Eu testei isso. Se isso funcionar perfeitamente em C #, mas for implementado incorretamente em Java, você deve relatar isso como um bug.
Elmue

@Elmue Este é um encadeamento Java. Por favor, leia a resposta de Luke (desenvolvedor Selenium) a respeito getWindowHandles(). É um comportamento conhecido (não bug) do método e do Java Set <T> em particular. Portanto, switchTo().window(handles[handles.length-1])não é garantido em Java. A solução AC # não pode ser considerada correta.
prata de

5
@Elmue Pela 3ª (e última) vez, sua resposta é falsa para Java como suportado por docs e dev que podem ENGANAR pessoas. Poste uma resposta onde você diz que é para C #, sem problemas. Levante um cartão de problema no GitHub para Java, vá em frente. Simplesmente sua resposta não se aplica ao idioma TAGGED no tópico e as pessoas podem pensar o contrário. Se você não consegue fazer a distinção, falta sua compreensão.
prata de

3
@Elmue A propósito, você também está errado ao dizer que driver.close () fecha as duas janelas. Apenas fecha a corrente. driver.quit () mata todas as instâncias. Posso ver que alguém já apontou isso para você. Seu comentário está cheio de erros. Tenha um bom dia.
prata de

12

Só para adicionar ao conteúdo ...

Para voltar à janela principal (janela padrão).

usar driver.switchTo().defaultContent();


11

Este script ajuda você a mudar de uma janela pai para uma janela filho e voltar a usar o Ctrl para a janela pai

String parentWindow = driver.getWindowHandle();
Set<String> handles =  driver.getWindowHandles();
   for(String windowHandle  : handles)
       {
       if(!windowHandle.equals(parentWindow))
          {
          driver.switchTo().window(windowHandle);
         <!--Perform your operation here for new window-->
         driver.close(); //closing child window
         driver.switchTo().window(parentWindow); //cntrl to parent window
          }
       }

1
driver.close () funcionará em uma nova janela. Se for uma nova guia, use o código para fechar a nova guia: driver.findElement (By.cssSelector ("body")). SendKeys (Keys.CONTROL + "w");
Ripon Al Wasim

4

Surya, seu jeito não vai funcionar, por dois motivos:

  1. você não pode fechar o driver durante a avaliação do teste, pois ele perderá o foco , antes de alternar para o elemento ativo, e você obterá NoSuchWindowException.
  2. se o teste for executado no ChromeDriver você não obterá uma janela, mas sim uma aba ao clicar em seu aplicativo. Como o SeleniumDriver não pode atuar com as guias , apenas alterna entre as janelas, ele trava ao clicar onde a nova guia está sendo aberta e trava no tempo limite.

1
Na verdade, você pode usar a chamada para driver.close (), uma vez que está alternando os identificadores de janela no driver e chamando para fechar a janela que está no momento. Eu o uso regularmente em meu código ao lidar com várias janelas. driver.Quit () é a chamada que encerrará o teste. No Chromedriver, você ainda pode chamar getWindowHandles () para obter sua lista de janelas disponíveis. Não consigo pensar em um motivo para usar uma guia em um teste da web.
Ben

@Elmue A questão original afirmava que um clique abre uma segunda janela, criando várias alças de janela. Posso fazer a chamada driver.close (); e fechar minha janela que atualmente está em foco. Posso então mudar para qualquer outra janela ativa de minha escolha. driver.close () e driver.quit () não compartilham a mesma funcionalidade. Uma chamada para driver.quit () matará a instância do driver ativo, enquanto close apenas mata o identificador da janela atual. Além disso, ainda não vi nenhuma chamada que só abra uma guia depois que um clique for chamado quando o javascript no site cria uma nova janela.
Ben

Eu estava errado e apaguei meu comentário. Você também pode deletar sua resposta.
Elmue

3

Modifique o registro para o IE:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ Main
  2. Clique com o botão direito → Novo → Valor da string → Nome do valor: TabProcGrowth (crie se não existir)
  3. TabProcGrowth (clique com o botão direito) → Modificar ... → Dados do valor: 0

Fonte: Problema de troca de janelas Selenium WebDriver no Internet Explorer 8-10

No meu caso, o IE começou a detectar novos identificadores de janela após a edição do registro.

Retirado do Blog do MSDN:

Crescimento do processo de guia: define a taxa em que o IE cria processos de nova guia.

O algoritmo "Max-Number": especifica o número máximo de processos de guia que podem ser executados para uma única sessão de isolamento para um único processo de quadro em um nível de integridade obrigatório específico (MIC). Os valores relativos são:

  • TabProcGrowth = 0: tabs e frames rodam no mesmo processo; os quadros não são unificados nos níveis de MIC.
  • TabProcGrowth = 1: todas as guias para um determinado processo de quadro são executadas em um único processo de guia para um determinado nível de MIC.

Fonte: Abrir uma nova guia pode lançar um novo processo com o Internet Explorer 8.0


Opções de Internet:

  • Segurança → Desmarque Habilitar modo protegido para todas as zonas (Internet, intranet local, sites confiáveis, sites restritos)
  • Avançado → Segurança → Desmarque Habilitar Modo Protegido Aprimorado

Código:

Navegador: IE11 x64 (Zoom: 100%)
SO: Windows 7 x64
Selenium: 3.5.1
WebDriver: IEDriverServer x64 3.5.1

public static String openWindow(WebDriver driver, By by) throws IOException {
String parentHandle = driver.getWindowHandle(); // Save parent window
WebElement clickableElement = driver.findElement(by);
clickableElement.click(); // Open child window
WebDriverWait wait = new WebDriverWait(driver, 10); // Timeout in 10s
boolean isChildWindowOpen = wait.until(ExpectedConditions.numberOfWindowsToBe(2));
if (isChildWindowOpen) {
    Set<String> handles = driver.getWindowHandles();
    // Switch to child window
    for (String handle : handles) {
        driver.switchTo().window(handle);
        if (!parentHandle.equals(handle)) {
            break;
        }
    }
    driver.manage().window().maximize();
}
return parentHandle; // Returns parent window if need to switch back
}



/* How to use method */
String parentHandle = Selenium.openWindow(driver, by);

// Do things in child window
driver.close();

// Return to parent window
driver.switchTo().window(parentHandle);

O código acima inclui um if-check para garantir que você não está alternando para a janela pai, pois Set<T>não há ordenação garantida em Java .WebDriverWaitparece aumentar a chance de sucesso, conforme comprovado pela declaração abaixo.

Citado de Luke Inman-Semerau : (Desenvolvedor para Selenium)

O navegador pode demorar para reconhecer a nova janela, e você pode estar entrando no loop switchTo () antes que a janela pop-up apareça.

Você assume automaticamente que a última janela retornada por getWindowHandles () será a última aberta. Isso não é necessariamente verdade, pois não há garantia de que serão devolvidos em qualquer ordem.

Fonte: não é possível lidar com um pop-up no IE, o controle não está sendo transferido para a janela pop-up


Postagens relacionadas:


2

Você pode usar:

driver.SwitchTo().Window(WindowName);

Onde WindowName é uma string que representa o nome da janela para a qual você deseja mudar o foco. Chame essa função novamente com o nome da janela original para voltar a ela quando terminar.


1
obrigado pela sugestão, existe alguma maneira, como posso definir a máscara do nome da janela? Como "WinName *", onde * - qualquer símbolo.
Volodymyr Prysiazhniuk

1
Meu implicitamente é de 10 segundos, mas em 2 segundos me dá a exceção NoSuchWindowException.
Volodymyr Prysiazhniuk

2

Eu uso o iterador e um loop while para armazenar as várias alças de janela e, em seguida, alterno entre um e outro.

//Click your link
driver.findElement(By.xpath("xpath")).click();
//Get all the window handles in a set
Set <String> handles =driver.getWindowHandles();
Iterator<String> it = handles.iterator();
//iterate through your windows
while (it.hasNext()){
String parent = it.next();
String newwin = it.next();
driver.switchTo().window(newwin);
//perform actions on new window
driver.close();
driver.switchTo().window(parent);
            }

Ele está falhando ao alternar para novas guias, no entanto, executa cliques na nova guia desejada. Por quê?
paul

há algum motivo para esse código tornar o teste muito lento? Parece que após este trecho de código leva cerca de 10 minutos para realizar qualquer ação no newwin
Hugo

0
 main you can do :

 String mainTab = page.goToNewTab ();
 //do what you want
 page.backToMainPage(mainTab);  

 What you need to have in order to use the main   

        private static Set<String> windows;

            //get all open windows 
            //return current window
            public String initWindows() {
                windows = new HashSet<String>();
                driver.getWindowHandles().stream().forEach(n ->   windows.add(n));
                return driver.getWindowHandle();
            }

            public String getNewWindow() {
                List<String> newWindow = driver.getWindowHandles().stream().filter(n -> windows.contains(n) == false)
                        .collect(Collectors.toList());
                logger.info(newWindow.get(0));
                return newWindow.get(0);
            }


            public String goToNewTab() {
                String startWindow = driver.initWindows();
                driver.findElement(By.cssSelector("XX")).click();
                String newWindow = driver.getNewWindow();
                driver.switchTo().window(newWindow);
                return startWindow;
            }

            public void backToMainPage(String startWindow) {
                driver.close();
                driver.switchTo().window(startWindow);
            }

0

Portanto, o problema com muitas dessas soluções é que você está assumindo que a janela aparece instantaneamente (nada acontece instantaneamente, e as coisas acontecem significativamente menos instantaneamente no IE). Além disso, você está assumindo que haverá apenas uma janela antes de clicar no elemento, o que nem sempre é o caso. Além disso, o IE não retornará as alças das janelas em uma ordem previsível. Então, eu faria o seguinte.

 public String clickAndSwitchWindow(WebElement elementToClick, Duration 
    timeToWaitForWindowToAppear) {
    Set<String> priorHandles = _driver.getWindowHandles();

    elementToClick.click();
    try {
        new WebDriverWait(_driver,
                timeToWaitForWindowToAppear.getSeconds()).until(
                d -> {
                    Set<String> newHandles = d.getWindowHandles();
                    if (newHandles.size() > priorHandles.size()) {
                        for (String newHandle : newHandles) {
                            if (!priorHandles.contains(newHandle)) {
                                d.switchTo().window(newHandle);
                                return true;
                            }
                        }
                        return false;
                    } else {
                        return false;
                    }

                });
    } catch (Exception e) {
        Logging.log_AndFail("Encountered error while switching to new window after clicking element " + elementToClick.toString()
                + " seeing error: \n" + e.getMessage());
    }

    return _driver.getWindowHandle();
}

-1

Se você tiver mais de um navegador (usando java 8)

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class TestLink {

  private static Set<String> windows;

  public static void main(String[] args) {

    WebDriver driver = new FirefoxDriver();
    driver.get("file:///C:/Users/radler/Desktop/myLink.html");
    setWindows(driver);
    driver.findElement(By.xpath("//body/a")).click();
    // get new window
    String newWindow = getWindow(driver);
    driver.switchTo().window(newWindow);

    // Perform the actions on new window
    String text = driver.findElement(By.cssSelector(".active")).getText();
    System.out.println(text);

    driver.close();
    // Switch back
    driver.switchTo().window(windows.iterator().next());


    driver.findElement(By.xpath("//body/a")).click();

  }

  private static void setWindows(WebDriver driver) {
    windows = new HashSet<String>();
    driver.getWindowHandles().stream().forEach(n -> windows.add(n));
  }

  private static String getWindow(WebDriver driver) {
    List<String> newWindow = driver.getWindowHandles().stream()
        .filter(n -> windows.contains(n) == false).collect(Collectors.toList());
    System.out.println(newWindow.get(0));
    return newWindow.get(0);
  }

}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.