จะเปลี่ยนไปใช้หน้าต่างเบราว์เซอร์ใหม่ซึ่งจะเปิดขึ้นหลังจากคลิกที่ปุ่มได้อย่างไร?


86

ฉันมีสถานการณ์เมื่อคลิกที่ปุ่มเปิดหน้าต่างเบราว์เซอร์ใหม่พร้อมผลการค้นหา

มีวิธีใดบ้างในการเชื่อมต่อและโฟกัสไปที่หน้าต่างเบราว์เซอร์ที่เปิดใหม่

และใช้งานได้จากนั้นกลับไปที่หน้าต่างเดิม (แรก)


เราสามารถทำการเปลี่ยนได้โดยอัตโนมัติ - ตรวจสอบการใช้งานขั้นสูงที่นี่ - testautomationguru.com/…
วิน

คำตอบ:


118

คุณสามารถสลับไปมาระหว่างหน้าต่างดังต่อไปนี้:

// 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)

4
ฉันสามารถยืนยันได้ว่าโซลูชันที่ยอมรับทำงานได้อย่างสม่ำเสมอใน Chrome แต่ไม่ใช่ใน IE ไม่รู้จักที่จับหน้าต่างใหม่ใน IE @Elmue ไม่ถูกต้องเพราะgetWindowHandles()ผลตอบแทนชุดและชุดไม่ได้รับประกันการสั่งซื้อ องค์ประกอบสุดท้ายไม่ใช่หน้าต่างสุดท้ายเสมอไป ฉันรู้สึกประหลาดใจที่ความคิดเห็นของเขาได้รับคะแนนโหวตเพิ่มขึ้นมากมาย
เงิน

@silver: ฉันไม่รู้ว่าคุณกำลังพูดถึงอะไร ในโค้ดของฉัน WindowHandles ส่งคืน ReadOnlyCollection <string> ซึ่งฉันสามารถรับประกันได้ว่ารายการสุดท้ายจะเป็นหน้าต่างที่เปิดล่าสุดเสมอ ฉันทดสอบแล้ว หากสิ่งนี้ทำงานได้อย่างสมบูรณ์ใน C # แต่ถูกนำไปใช้อย่างไม่ถูกต้องใน Java คุณควรรายงานว่าเป็นบั๊ก
Elmue

1
@Elmue นี่คือเธรด Java โปรดอ่านลุค (นักพัฒนาซีลีเนียม) การตอบสนองgetWindowHandles()เกี่ยวกับ เป็นพฤติกรรมที่ทราบ (ไม่ใช่จุดบกพร่อง) ของเมธอดและ Java Set <T> โดยเฉพาะ ดังนั้นจึงswitchTo().window(handles[handles.length-1])ไม่รับประกันใน Java ไม่สามารถอ้างว่าโซลูชัน AC # ถูกต้อง
เงิน

6
@Elmue สำหรับครั้งที่ 3 (และครั้งสุดท้าย) คำตอบของคุณเป็นเท็จสำหรับ Java ซึ่งสนับสนุนโดยเอกสารและ dev ซึ่งอาจทำให้ผู้คนเข้าใจผิดได้ โพสต์คำตอบที่คุณบอกว่าสำหรับ C # ไม่มีปัญหา ยกการ์ดปัญหาใน GitHub สำหรับ Java ดำเนินการต่อ คำตอบของคุณใช้ไม่ได้กับภาษาที่ติดแท็กในชุดข้อความและผู้คนอาจคิดเป็นอย่างอื่น หากคุณไม่สามารถสร้างความแตกต่างได้แสดงว่าคุณไม่เข้าใจ
เงิน

3
@Elmue อย่างไรก็ตามคุณพูดผิดเช่นกันในการพูดว่า driver.close () ปิดทั้งสองหน้าต่าง มันปิดกระแสเท่านั้น driver.quit () ฆ่าอินสแตนซ์ทั้งหมด ฉันเห็นใครบางคนชี้เรื่องนี้กับคุณแล้ว ความคิดเห็นของคุณเต็มไปด้วยความผิดพลาด มีวันที่ดี.
เงิน


11

สคริปต์นี้ช่วยให้คุณสามารถเปลี่ยนจากหน้าต่างหลักเป็นหน้าต่างลูกและกลับ cntrl เป็นหน้าต่างหลัก

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 () จะทำงานสำหรับหน้าต่างใหม่ หากเป็นแท็บใหม่ให้ใช้รหัสเพื่อปิดแท็บใหม่: driver.findElement (By.cssSelector ("body")) sendKeys (Keys.CONTROL + "w");
Ripon Al Wasim

4

Surya วิธีของคุณไม่ได้ผลเนื่องจากเหตุผลสองประการ:

  1. คุณไม่สามารถปิดไดรเวอร์ระหว่างการประเมินผลการทดสอบได้เนื่องจากจะหลุดโฟกัสก่อนที่จะเปลี่ยนเป็นองค์ประกอบที่ใช้งานอยู่และคุณจะได้รับ NoSuchWindowException
  2. หากการทดสอบทำงานบน ChromeDriver คุณจะไม่ได้รับหน้าต่าง แต่แท็บคลิกในแอปพลิเคชัน เนื่องจากSeleniumDriver ไม่สามารถทำงานกับแท็บได้เพียง แต่สลับไปมาระหว่างหน้าต่างจึงค้างเมื่อคลิกที่แท็บใหม่กำลังเปิดและหยุดทำงานเมื่อหมดเวลา

1
คุณสามารถใช้การโทรหา driver.close () ได้จริงเนื่องจากคุณกำลังสลับที่จับหน้าต่างบนไดรเวอร์และเรียกให้หน้าต่างที่คุณกำลังปิดอยู่ ฉันใช้มันเป็นประจำในรหัสของฉันเมื่อต้องจัดการกับหลายหน้าต่าง driver.Quit () คือการโทรที่จะฆ่าการทดสอบ ใน Chromedriver คุณยังสามารถเรียก getWindowHandles () เพื่อรับรายการหน้าต่างที่มีอยู่ ฉันนึกเหตุผลไม่ออกที่จะใช้แท็บในการทดสอบเว็บ
เบ็น

@Elmue คำถามเดิมระบุว่าการคลิกจะเปิดหน้าต่างที่สองขึ้นมาเพื่อสร้างแฮนเดิลหลายหน้าต่าง ฉันสามารถเรียกคนขับรถได้. ปิด (); และให้หน้าต่างของฉันที่มีโฟกัสอยู่ใกล้ ๆ จากนั้นฉันสามารถเปลี่ยนไปใช้หน้าต่างอื่น ๆ ที่ฉันเลือกได้ driver.close () และ driver.quit () ไม่ใช้ฟังก์ชันการทำงานเดียวกัน การเรียก driver.quit () จะฆ่าอินสแตนซ์ไดรเวอร์ที่ใช้งานอยู่ในขณะที่การปิดจะฆ่าเฉพาะจุดจับหน้าต่างปัจจุบันเท่านั้น นอกจากนี้ฉันยังไม่เห็นการเรียกใด ๆ ที่เปิดแท็บเพียงอย่างเดียวหลังจากมีการเรียกคลิกเมื่อจาวาสคริปต์บนเว็บไซต์สร้างหน้าต่างใหม่
เบ็น

ฉันผิดและลบความคิดเห็นของฉัน คุณสามารถลบคำตอบของคุณได้เช่นกัน
Elmue

3

แก้ไขรีจิสทรีสำหรับ IE:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ Main
  2. คลิกขวา→ใหม่→ค่าสตริง→ชื่อค่า: TabProcGrowth (สร้างหากไม่มี)
  3. TabProcGrowth (คลิกขวา) →แก้ไข ... →ข้อมูลค่า: 0

ที่มา: ปัญหาการสลับหน้าต่าง Selenium WebDriver ใน Internet Explorer 8-10

ในกรณีของฉัน IE เริ่มตรวจพบตัวจัดการหน้าต่างใหม่หลังจากแก้ไขรีจิสทรี

นำมาจากบล็อก MSDN:

Tab Process Growth:กำหนดอัตราที่ IE สร้างกระบวนการ New Tab

อัลกอริทึม "Max-Number": ระบุจำนวนสูงสุดของกระบวนการแท็บที่อาจดำเนินการสำหรับเซสชันการแยกเดี่ยวสำหรับกระบวนการเฟรมเดียวที่ระดับความสมบูรณ์บังคับเฉพาะ (MIC) ค่าสัมพัทธ์คือ:

  • TabProcGrowth = 0: แท็บและเฟรมทำงานภายในกระบวนการเดียวกัน เฟรมไม่รวมกันในระดับ MIC
  • TabProcGrowth = 1: แท็บทั้งหมดสำหรับกระบวนการเฟรมที่กำหนดทำงานในกระบวนการแท็บเดียวสำหรับระดับ MIC ที่กำหนด

ที่มา: การ เปิดแท็บใหม่อาจทำให้เกิดกระบวนการใหม่ด้วย Internet Explorer 8.0


ตัวเลือกอินเทอร์เน็ต:

  • ความปลอดภัย→ยกเลิกการเลือกเปิดใช้งานโหมดป้องกันสำหรับทุกโซน (อินเทอร์เน็ตอินทราเน็ตเฉพาะที่ไซต์ที่เชื่อถือได้ไซต์ที่ถูก จำกัด )
  • ขั้นสูง→ความปลอดภัย→ยกเลิกการคลิกเปิดใช้งานโหมดป้องกันขั้นสูง

รหัส:

เบราว์เซอร์: IE11 x64 (ซูม: 100%)
OS: 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);

รหัสข้างต้นรวมถึงถ้าตรวจสอบให้แน่ใจว่าคุณจะไม่ได้เปลี่ยนไปยังหน้าต่างหลักเป็นได้รับประกันไม่มีการสั่งซื้อในชวาSet<T> WebDriverWaitดูเหมือนจะเพิ่มโอกาสในการประสบความสำเร็จตามที่ได้รับการสนับสนุนจากข้อความด้านล่าง

ยกมาจากLuke Inman-Semerau : (Developer for Selenium)

เบราว์เซอร์อาจใช้เวลาในการรับทราบหน้าต่างใหม่และคุณอาจตกอยู่ในลูป switchTo () ก่อนที่หน้าต่างป๊อปอัปจะปรากฏขึ้น

คุณจะถือว่าหน้าต่างสุดท้ายที่ส่งคืนโดย getWindowHandles () จะเป็นหน้าต่างสุดท้ายที่เปิดโดยอัตโนมัติ ไม่จำเป็นต้องเป็นจริงเนื่องจากไม่รับประกันว่าจะได้รับคืนตามลำดับ

ที่มา: ไม่สามารถจัดการกับป๊อปอัปใน IE การควบคุมไม่ได้ถ่ายโอนไปยังหน้าต่างป๊อปอัป


กระทู้ที่เกี่ยวข้อง:


2

คุณสามารถใช้:

driver.SwitchTo().Window(WindowName);

โดยที่ WindowName คือสตริงที่แสดงถึงชื่อของหน้าต่างที่คุณต้องการเปลี่ยนโฟกัส เรียกใช้ฟังก์ชันนี้อีกครั้งด้วยชื่อของหน้าต่างเดิมเพื่อกลับไปที่เมื่อคุณทำเสร็จแล้ว


1
ขอบคุณสำหรับคำแนะนำมีวิธีตั้งค่า window name mask ได้อย่างไร? เช่น "WinName *" โดยที่ * - สัญลักษณ์ใด ๆ
Volodymyr Prysiazhniuk

1
โดยปริยายของฉันคือ 10 วินาที แต่ใน 2 วินาทีมันทำให้ฉันมีข้อยกเว้น NoSuchWindowException
Volodymyr Prysiazhniuk

2

ฉันใช้ iterator และ while loop เพื่อจัดเก็บที่จับหน้าต่างต่างๆแล้วสลับไปมา

//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);
            }

ไม่สามารถเปลี่ยนไปใช้แท็บใหม่ได้ แต่จะคลิกบนแท็บใหม่ที่ต้องการ ทำไม?
พอล

มีสาเหตุใดที่รหัสนี้อาจทำให้การทดสอบช้ามาก? ดูเหมือนว่าหลังจากโค้ดนี้จะใช้เวลาประมาณ 10 นาทีในการดำเนินการใด ๆ ใน 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

ดังนั้นปัญหาในการแก้ปัญหาเหล่านี้จำนวนมากคือคุณสมมติว่าหน้าต่างปรากฏขึ้นทันที (ไม่มีอะไรเกิดขึ้นทันทีและสิ่งต่างๆเกิดขึ้นน้อยลงอย่างมากในทันทีใน IE) นอกจากนี้คุณกำลังสมมติว่าจะมีเพียงหน้าต่างเดียวก่อนที่จะคลิกองค์ประกอบซึ่งไม่ได้เป็นเช่นนั้นเสมอไป IE จะไม่ส่งคืนที่จับหน้าต่างตามลำดับที่คาดเดาได้ ดังนั้นฉันจะทำสิ่งต่อไปนี้

 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

หากคุณมีมากกว่าหนึ่งเบราว์เซอร์ (โดยใช้ 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);
  }

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.