Skip to content

Within Blocks

Basic syntax

Within blocks define a context for actions. The syntax requires the the keyword between Within and the block name:

Within the Browser (plugin: playwright-python, type: browser)
go to "https://example.com"

Blocks must be indented with consistent whitespace. All statements inside the block are scoped to that context.

Required modifiers

The root within block must specify:

  • plugin: - which plugin to use
  • type: - which type from that plugin
Within the Browser (plugin: playwright-python, type: browser)

Both modifiers are required at the root level. The plugin: modifier selects which plugin processes actions; the type: modifier selects the type definition within that plugin.

Available types

Each plugin defines its own set of types. Here are the types available in the built-in plugins:

playwright-python plugin

TypeDescriptionAllowed ChildrenKey Modifiers
browserRoot browser contextelement, failure_blockurl, headless
elementScoped DOM elementelement, failure_blockid, class, testid, label, role, name, text
failure_blockException-expected block(passthrough)-

python-requests plugin

TypeDescriptionAllowed ChildrenKey Modifiers
apiHTTP client sessionfailure_blockbase, timeout, headers
http_responseResponse context (from GET/POST)--
failure_blockException-expected block(passthrough)-

See the playwright-python and python-requests plugin pages for full details on patterns and modifiers.

Nested blocks

Blocks can be nested. Child blocks inherit the parent’s plugin. If the block name matches a type name (like element), the type is inferred automatically:

Within the Browser (plugin: playwright-python, type: browser)
go to "https://example.com"
# Type is inferred from block name "element"
Within the element (testid: 'login-form')
type "user@example.com" into input (label: 'Email')
# Custom names require explicit type
Within the Login Form (type: element, testid: 'login-form')
type "user@example.com" into input (label: 'Email')

Type inference: When the block name exactly matches a type name (e.g., element, api), the type: modifier is optional. This allows concise syntax like Within the element (testid: '...').

Nesting constraints

Not all types can be nested inside all other types. Each type in a plugin defines an allowed_children list that specifies which types can be nested within it.

For example, in the playwright-python plugin:

  • browser allows children: element, failure_block
  • element allows children: element, failure_block

Attempting to nest an invalid type results in an error:

Block 'invalid_type' cannot nest inside 'browser'

Modifier syntax

Two equivalent syntaxes are supported for modifiers:

Parentheses syntax:

Within the Browser (plugin: playwright-python, type: browser, url: 'http://localhost')

With syntax:

Within the Browser with plugin: playwright-python, type: browser, url: 'http://localhost'

Both syntaxes accept comma-separated key-value pairs. The with syntax is single-line only, while parentheses can span multiple lines (though this is discouraged).

Block names

Block names are freeform text between the and the opening parenthesis (or with keyword):

Within the My Custom Name Here (type: browser)

The name is used for:

  • Generating variable names in the output code
  • Diagnostic messages and error reporting
  • Documentation purposes in the test

Scope rules

Definitions created with Define and variables captured with Capture share a single flat scope across the entire script. This means:

  • A Define in one block is accessible in sibling and child blocks
  • A Capture in one block creates a variable usable in later blocks

To share a variable explicitly between blocks, use Export:

Within the Orders API (plugin: python-requests, type: api, base: 'http://orders.internal')
POST "/orders" body '{"item": "widget"}'
capture "$.id" as order_id
Export order_id
Within the Notifications API (plugin: python-requests, type: api, base: 'http://notifications.internal')
GET "/notifications/{order_id}"
expect status 200

Multi-plugin scripts

A single vanya file can use multiple plugins. Each root-level Within block specifies its own plugin:

Within the API (plugin: python-requests, type: api, base: 'http://api.local')
GET "/health"
expect status 200
Within the Browser (plugin: playwright-python, type: browser, url: 'http://localhost:3000')
go to "/login"
Within the Login Form (type: element, id: 'login_form')
type "user@example.com" into input (label: 'Email')
click button (testid: 'submit')

Case sensitivity

The Within keyword must be written with a capital W. This is consistent with other vanya keywords (Script, Define, Export, Capture).