Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ปิด Child Browser Window ใน Selenium WebDriver ด้วย Java

การปิด Child Window (popup/หน้าต่างใหม่) ต้องสลับ context ไปที่ child window ก่อน แล้วจึง close() และสลับกลับ parent

ขั้นตอนหลัก

  1. เก็บ parent window handle ไว้ก่อน
  2. ทำ action ที่เปิด child window
  3. ได้ all window handles มา iterate
  4. สลับไป child window → close()
  5. สลับกลับ parent window

ตัวอย่างโค้ดสมบูรณ์

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class CloseChildWindow {
    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", 
            "C:\\Users\\ghs6kor\\Desktop\\Java\\chromedriver.exe");

        WebDriver driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.manage().window().maximize();

        try {
            driver.get("https://secure.indeed.com/account/login");

            // 1. เก็บ parent handle
            String parentHandle = driver.getWindowHandle();
            System.out.println("Parent window: " + parentHandle);

            // 2. คลิกเปิด child window (Google login)
            driver.findElement(By.id("login-google-button")).click();

            // 3. รอ child window เปิด
            Thread.sleep(3000);

            // 4. ได้ handles ทั้งหมด
            Set handles = driver.getWindowHandles();
            System.out.println("Total windows: " + handles.size());

            // 5. Iterate หา child window (ใช้ Iterator)
            Iterator iterator = handles.iterator();
            String childHandle = null;
            
            while (iterator.hasNext()) {
                String handle = iterator.next();
                if (!handle.equals(parentHandle)) {
                    childHandle = handle;
                    break;
                }
            }

            // 6. สลับไป child และปิด
            if (childHandle != null) {
                driver.switchTo().window(childHandle);
                System.out.println("Child window title: " + driver.getTitle());
                driver.close(); // ปิด child window
                System.out.println("Child window closed");
            }

            // 7. สลับกลับ parent (สำคัญมาก!)
            driver.switchTo().window(parentHandle);
            System.out.println("Back to parent: " + driver.getTitle());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            driver.quit();
        }
    }
}

วิธีที่ 2: ใช้ Stream API (Java 8+) - สั้นกว่า

String parentHandle = driver.getWindowHandle();

// ... action ที่เปิด child window ...

// หา child handle และปิด
driver.getWindowHandles().stream()
    .filter(h -> !h.equals(parentHandle))
    .findFirst()
    .ifPresent(childHandle -> {
        driver.switchTo().window(childHandle);
        System.out.println("Closing: " + driver.getTitle());
        driver.close();
        driver.switchTo().window(parentHandle);
    });

วิธีที่ 3: ปิด Child Windows ทั้งหมด (ถ้ามีหลายตัว)

String parentHandle = driver.getWindowHandle();

for (String handle : driver.getWindowHandles()) {
    if (!handle.equals(parentHandle)) {
        driver.switchTo().window(handle);
        driver.close();
    }
}
driver.switchTo().window(parentHandle);

⚠️ ข้อผิดพลาดที่พบบ่อย

ผิดถูกต้อง
driver.close(); แล้วไม่ switch กลับต้อง driver.switchTo().window(parentHandle); หลัง close
Iterate getWindowHandles() ขณะกำลัง closeเก็บ handles ไว้ใน list ก่อน แล้วค่อย iterate
คิดว่า handle คงที่Handle สุ่มใหม่ทุก session ไม่ควร hardcode

ความแตกต่าง: close() vs quit()

  • close() - ปิดหน้าต่าง/แท็บ **ปัจจุบัน** เท่านั้น
  • quit() - ปิด **ทุกหน้าต่าง** และจบ WebDriver session

Best Practice: Wrapper Method

public void closeChildWindows(WebDriver driver) {
    String parent = driver.getWindowHandle();
    driver.getWindowHandles().stream()
        .filter(h -> !h.equals(parent))
        .forEach(h -> {
            driver.switchTo().window(h);
            driver.close();
        });
    driver.switchTo().window(parent);
}