Frames
Introduction
A page has one main frame. Page-level interactions (such as click, type, locator) run in the main frame by default.
A page can also have additional frames created with the <iframe> element. To interact with elements inside an iframe, you get a browser scoped to that frame using frame(iframeSelector). The returned object has the same API as the page (e.g. locator, click, type), but all actions run inside that frame.
To go back to the main page, use the original browser reference for main-page actions. You do not need to "switch back"; you keep two references: one for the main page and one for the frame.
Locating elements inside a frame
Call browser.frame(iframeSelector) to get a CSTestingBrowser scoped to that iframe. Then use locator(), click(), type(), and other methods on that reference — they operate inside the frame.
browser.gotoUrl("https://example.com/page-with-iframe");
browser.waitForSelector("iframe", 10_000); // ensure iframe is in DOM
CSTestingBrowser frame = browser.frame("iframe");
frame.locator("#username-input").type("John");
frame.locator("button[type=submit]").click();
// Main page: use the original browser
browser.locator("body").click();
Selector formats inside the frame are the same as on the main page: CSS, XPath (//input[@name='user']), id=, name=, or any attr=value.
Frame access
CSTesting provides frame(String iframeSelector): you pass a selector that matches the iframe element in the main page (or in the current frame for nested frames). The selector targets the <iframe> DOM node, not the document inside it.
| Approach | CSTesting |
|---|---|
| By tag | browser.frame("iframe") |
| By id | browser.frame("iframe#my-frame") or browser.frame("#my-frame") |
| By name attribute | browser.frame("iframe[name='frame-login']") |
| By URL (src) | browser.frame("iframe[src*='domain']") or browser.frame("iframe[src^='https://auth.']") |
Get frame by the iframe's name attribute:
CSTestingBrowser frame = browser.frame("iframe[name='frame-login']");
frame.locator("#username-input").type("John");
Get frame by the iframe's URL (e.g. contains "domain"):
CSTestingBrowser frame = browser.frame("iframe[src*='domain']");
frame.locator("#username-input").type("John");
There is no separate frameByName(String) or frameByUrl(Pattern) API; use the same frame(iframeSelector) with an attribute selector (e.g. iframe[name='...'], iframe[src*='...']).
Interacting with the frame
The object returned by frame(iframeSelector) implements CSTestingBrowser. You can use the same methods as on the page:
frame.locator(selector)— create locators inside the frameframe.click(selector)/frame.locator(selector).click()frame.type(selector, text)/frame.locator(selector).type(text)frame.assertThat(locator)/frame.assertThat()— assertions inside the frameframe.gotoUrl(url)— navigate inside the frame (if allowed)frame.title(),frame.url()— frame document title/URL
Example:
CSTestingBrowser frame = browser.frame("iframe#login");
frame.locator("name=user").type("John");
frame.locator("name=pass").type("secret");
frame.locator("button[type=submit]").click();
Nested frames
An iframe can contain another iframe. To interact with a nested frame, call frame(iframeSelector) on the parent frame reference (not on the main browser). That returns a new browser scoped to the inner iframe.
// Outer iframe
CSTestingBrowser outer = browser.frame("iframe#outer");
// Inner iframe (inside the outer one)
CSTestingBrowser inner = outer.frame("iframe#inner");
inner.locator("button").click();
inner.locator("#input").type("hello");
// Still in outer frame
outer.locator("h1").getTextContent();
// Main page
browser.locator("body").click();
Selector for the inner iframe is evaluated in the context of the outer frame's document. So "iframe#inner" means an iframe with id="inner" inside the outer frame.
Summary
| Topic | CSTesting |
|---|---|
| Main frame | Default. Use the browser reference. |
| Single iframe | CSTestingBrowser frame = browser.frame("iframeSelector"); then use frame.locator(), frame.click(), etc. |
| By name | browser.frame("iframe[name='frame-login']") |
| By URL | browser.frame("iframe[src*='domain']") |
| Nested frame | outer = browser.frame("iframe#outer"); then inner = outer.frame("iframe#inner"); |
| Back to main | Use the original browser reference; no explicit "switch back". |
Note (CDP): The iframe must have loaded before calling frame(), so its execution context exists. Use browser.waitForSelector("iframe", timeoutMs) (and optionally a short waitForLoad() or waitForTime(...) for slow embeds) before frame(...).