skip to content

In Selenium 4, what does driver.switchTo().newWindow(WindowType.TAB) do, and how does WindowType.WINDOW differ?

level: juniorimportance: nice to knowfreq 28%

answer

  1. Selenium 4 added a one-call opener
  2. The target locator does more than switch
  3. An enum names the kind of context
  4. Focus moves without any handle diff
  5. WindowType.TAB versus WindowType.WINDOW

basics

~20 s

Selenium 4 creates a fresh, blank browsing context and switches the driver to it in one call, so no handle diffing is needed. WindowType.TAB asks for a tab in the current window; WindowType.WINDOW asks for a separate browser window.

solid answer

~40 s

`switchTo().newWindow(WindowType)` was added in Selenium 4. It asks the browser for a new top-level browsing context and moves the driver's focus onto it before returning, so the next `get(...)` loads in the new context. `WindowType.TAB` requests a tab in the current window and `WindowType.WINDOW` requests a separate window, but both values are only a hint that the browser may not honour, so never assert on which kind you got. The new context starts blank, does not carry the old handle back for you, and shares the session and cookies with the one you left. Capture `getWindowHandle()` before the call so you can `switchTo().window(...)` back afterwards.

code

java · 25 lines
java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.chrome.ChromeDriver;

public class PermitFeeScheduleTab {

    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        try {
            driver.get("https://permits.example.gov/applications/BP-2026-0412");
            String applicationTab = driver.getWindowHandle();

            driver.switchTo().newWindow(WindowType.TAB);
            driver.get("https://permits.example.gov/fees/schedule");
            System.out.println(driver.getWindowHandle().equals(applicationTab));
            System.out.println(driver.getWindowHandles().size());

            driver.close();
            driver.switchTo().window(applicationTab);
            System.out.println(driver.getTitle());
        } finally {
            driver.quit();
        }
    }
}

go deeper

for a junior

Recall that the call both creates the context and moves focus to it, and that the enum has exactly two constants. Knowing you must save the current handle first to get back is the practical half.

for a middle

Explain that the type is a hint on the W3C New Window command, that the new context starts blank and shares the session, and why the deliberate open differs from finding a context the page itself created.

for a senior

Show where the deliberate open belongs in a suite: a scratch context your test owns and closes, always paired with a switch back, versus chasing whatever the application opened. Explain why tab-versus-window assertions are untestable.

for a principal

Own the convention: whether suites open their own contexts at all, or drive each flow in one context and read secondary pages by URL, and what the multi-context habit costs in readability and cleanup discipline.

## What `newWindow` is and where it lives `driver.switchTo()` returns a **`WebDriver.TargetLocator`**, the small interface that redirects every later command at a different **browsing context** — a frame, a native dialog, or, here, a whole window or tab. Selenium 4 added `newWindow(WindowType)` to that interface. One call asks the browser for a brand-new top-level browsing context and leaves the driver pointed at it, so the very next `driver.get(...)` loads inside the new context rather than the one you started from. Two things matter more than the signature: - The argument is the enum **`org.openqa.selenium.WindowType`**, whose only constants are `TAB` and `WINDOW`. - The call **switches focus as part of creating the context**. There is no follow-up `switchTo().window(...)` to make, and no handle arithmetic to perform. ## `WindowType.TAB` versus `WindowType.WINDOW` | | `WindowType.TAB` | `WindowType.WINDOW` | |---|---|---| | What you ask for | another tab inside the current browser window | a separate top-level browser window | | Focus when the call returns | the new context | the new context | | Starting page | blank; you navigate it yourself | blank; you navigate it yourself | | New handle appears in `getWindowHandles()` | yes | yes | | Guaranteed | no — the value is a hint | no — the value is a hint | The last row is the part candidates miss. The underlying W3C **New Window** command carries the type as a *hint*, and a remote end is allowed to create the other kind and say so in its response. The Java binding hands you back the `WebDriver` rather than that response, so you cannot assert on it. The practical rule: pick the constant that expresses your intent, and never write an assertion that depends on tab-ness versus window-ness. ## A worked step on the permit portal A clerk opening a building-permit application often needs the fee schedule side by side with the form. As automation that is four moves: 1. Record where you are: `String applicationTab = driver.getWindowHandle();`. 2. Ask for the extra context: `driver.switchTo().newWindow(WindowType.TAB);` — focus is now on a blank tab. 3. Drive it: `driver.get("https://permits.example.gov/fees/schedule");`, read the fee table, assert. 4. Come back: `driver.close()` disposes of the fee tab, then `driver.switchTo().window(applicationTab)` puts the driver back on the application form. Step 4 is not optional. Closing a context does **not** move the driver anywhere; without the explicit switch the next command is sent at a context that no longer exists. ## What the call does not do - **It does not navigate.** The new context starts blank; supplying a URL is a separate `get(...)`. - **It does not return the handle.** The Java signature returns `WebDriver`, so if you want the new handle as a string, read `driver.getWindowHandle()` immediately after the call. - **It does not remember where you were.** Capture the origin handle *before* the call, or you are back to diffing `getWindowHandles()` to find your way home. - **It does not model a context the page opened itself.** `newWindow` is for contexts your test deliberately creates; a tab that a portal link spawned has to be located by its handle instead. - **It is not a second session.** The new tab shares the session, the profile and the cookie jar with the one you left, so a clerk signed in on the application form is signed in on the fee tab too. ## Why Selenium 4 bothered Before this method existed, a test that wanted its own scratch tab had to inject a script that opens one and then diff the handle set to discover what appeared. That recipe works, but it mixes three concerns — scripting, discovery and switching — into one helper that every suite reimplemented slightly differently. `newWindow(WindowType.TAB)` collapses all three into a single, spec-backed command, and it makes the intent readable: *this* tab exists because the test wanted it, not because the application opened it. ## The sequence end to end ```java String applicationTab = driver.getWindowHandle(); driver.switchTo().newWindow(WindowType.TAB); driver.get("https://permits.example.gov/fees/schedule"); String feeTab = driver.getWindowHandle(); driver.close(); driver.switchTo().window(applicationTab); ``` Read it as a small stack discipline: push the current handle, open, work, close, pop. Handles are opaque strings with no ordering contract, so the variable you saved on the first line is the only reliable way back — and `feeTab` becomes worthless the moment `close()` runs, because a handle for a closed context is no longer in `getWindowHandles()` and passing it to `switchTo().window(...)` raises `NoSuchWindowException`.

  • After calling newWindow(WindowType.TAB), how do you get the new context's handle as a string?
    Call `driver.getWindowHandle()` immediately after the call. The Java signature returns the `WebDriver` rather than the handle, but focus is already on the new context, so the very next `getWindowHandle()` reports it. Capture the original handle before opening, since nothing gives it back to you afterwards.
  • Why should a test not assert that WindowType.WINDOW produced a real separate window?
    The value travels to the browser as a type hint on the W3C New Window command, and the remote end is free to create the other kind. The Java binding does not expose the type it actually made, so an assertion on tab-ness versus window-ness is both unsupported and pointless for the behaviour under test.

saying these in an interview costs you the question

  • Thinks newWindow creates the context without switching focus to it
  • Assumes WindowType.TAB is guaranteed to produce a tab
  • Forgets to capture the original handle before opening a new context
  • Believes newWindow returns the new handle as a String
  • Expects newWindow to take a URL and navigate there