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. Use await browser.FrameAsync(iframeSelector) to get an ICSTestingFrame (C:\CSTesting-DotNet). Call async methods on that frame; use the main browser again for the top document.

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 await browser.FrameAsync(iframeSelector) to get an ICSTestingFrame. Then use Locator, ClickAsync, TypeAsync, etc.

await browser.GotoAsync("https://example.com/page-with-iframe");
await browser.WaitForSelectorAsync("iframe", 10_000);

var frame = await browser.FrameAsync("iframe");
await frame.TypeAsync("#username-input", "John");
await frame.ClickAsync("button[type=submit]");

await browser.Locator("body").ClickAsync();

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

Pass a selector for the <iframe> element in the parent document. Nested frames: await outer.FrameAsync("iframe#inner").

Approach CSTesting .NET
By tagawait browser.FrameAsync("iframe")
By idawait browser.FrameAsync("iframe#my-frame")
By name attributeawait browser.FrameAsync("iframe[name='frame-login']")
By URL (src)await browser.FrameAsync("iframe[src*='domain']")

By name / URL:

var frame = await browser.FrameAsync("iframe[name='frame-login']");
await frame.TypeAsync("#username-input", "John");
var frame2 = await browser.FrameAsync("iframe[src*='domain']");
await frame2.TypeAsync("#username-input", "John");

Interacting with the frame

ICSTestingFrame provides ClickAsync, TypeAsync, Locator, EvaluateAsync, ContentAsync, WaitForSelectorAsync, nested FrameAsync, etc. (see ICSTestingFrame in the repo). Assertions use NUnit with values from await frame.GetTextContentAsync(selector) or locators.

Example:

var frame = await browser.FrameAsync("iframe#login");
await frame.TypeAsync("name=user", "John");
await frame.TypeAsync("name=pass", "secret");
await frame.ClickAsync("button[type=submit]");

Nested frames

var outer = await browser.FrameAsync("iframe#outer");
var inner = await outer.FrameAsync("iframe#inner");
await inner.ClickAsync("button");
await inner.TypeAsync("#input", "hello");

var h1 = await outer.GetTextContentAsync("h1");

await browser.Locator("body").ClickAsync();

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 frameDefault. Use the browser reference.
Single iframevar frame = await browser.FrameAsync("iframeSelector"); then await frame.ClickAsync(...), frame.Locator(...), etc.
By nameawait browser.FrameAsync("iframe[name='frame-login']")
By URLawait browser.FrameAsync("iframe[src*='domain']")
Nested frameawait outer.FrameAsync("iframe#inner")
Back to mainUse the original browser reference; no explicit "switch back".

Note: Wait until the iframe is attached, e.g. await browser.WaitForSelectorAsync("iframe", 10_000) before FrameAsync.