Components
The preferred import style is through the package-level API:
Component helpers encapsulate reusable Appian-specific interaction mechanics. Browser lifecycle belongs to robo-automation; Appian component interactions use AppianPage and AppianLocator.
Buttons
Radio and checkbox selections
Use page.checkbox(...) for true Appian checkbox fields. It returns an AppianCheckbox.
Use page.radio(...) for Appian radio groups. It returns an AppianRadioSelect.
Use the complete question text when possible so common option values such as Yes and No stay scoped to the correct group.
Displayed text
Use page.text(...) for read-only text a BA can see on the page.
message = page.text("Request submitted successfully")
assert message.value == "Request submitted successfully"
When the same text appears more than once, results stay in Appian display order:
Use exact=False only when partial matching is intentional. For structured business data such as Basic Information or Recent Activities, prefer page.dataset(...).
Text inputs
Dropdowns
Use page.dropdown(...) for semantic Appian dropdown fields. It returns an AppianDropdown.
page.dropdown(label="Status").select("Active")
assert page.dropdown(label="Status").is_selected("Active")
Appian links
Use page.link(name=...) for business actions presented as links. It returns an AppianLink.
page.link(name="View Details").click()
page.link(name="Item 1001").click()
page.link(name="Item Details").click()
page.link(name="Return").click()
For links inside a table cell, resolve the cell and use its Appian link component, for example table.cell(...).link(name="Open").click().
Appian tabs
Use page.tab(name=...) for Appian linked-card tabs. It returns an AppianTab.
Selecting an already active tab is safe; no additional action is performed.
Tables
Create a table component from AppianPage. At least one of label, header, row_name, or column_name is required.
Matching is consistent across Appian component factories: exact=True and visible=True are the defaults. Use exact=False for intentional partial name/label matching. visible=False targets hidden matches; visible=None, visible="", or whitespace removes visibility filtering. For tables, no visibility filter leaves both visible and hidden matches in the live locator.
Appian components accept an optional timeout in seconds. Leave it as None to use the configured default, or provide a positive value when a particular business action needs a different wait:
page.dropdown(label="Status", timeout=10).select(value="Active")
page.button(name="Submit", timeout=15).click()
This is useful when a dependent field needs extra time to become ready after an earlier business action.
AppianGrid is the single table component API. Legacy Table helpers are removed.
Common matching and indexing
Page and cell lookup methods use the same matching defaults. Plural collections choose components by position:
page.button(name="Save") # exact=True, visible=True
page.button(name="Sav", exact=False) # partial match
page.dropdown(label="Status", visible=None) # include visible/hidden matches
page.dropdowns[0].select(value="Active") # first dropdown on page
page.dropdown(label="Status").select(value="Active")
Component collection indexing is zero-based. The same indexing convention is available for components inside a table cell.
Input textbox
Use AppianPage.textbox(...) for text fields:
page.textbox(label="Description").fill("Example item")
page.textbox(placeholder="example@example.com").fill("user@example.com")
page.textbox(header="Item Description").fill("General details")
Searchable text-entry controls use the same textbox API. fill() can be chained into select(), or select() can receive search_text directly:
page.textbox("Employee").fill("John").select("John Smith")
page.textbox("Employee").fill("John").select(index=2)
page.textbox("Employee").select(
search_text="John",
value="John Smith",
)
page.textbox("Employee").select(
search_text="John",
index=2,
)
Suggestion indexes are 1-based. Textbox collection indexes such as page.textboxes[0] remain zero-based.
Waiting for an Appian component to become enabled
Use is_enabled() to check the current state, or provide a timeout when the business flow needs to wait briefly for the component to become enabled.
# Snapshot of the current state; no wait.
page.dropdown(label="Status").is_enabled()
# Wait up to a configured short timeout for an Appian dependency to enable it.
dropdown = page.dropdown(label="Status")
if dropdown.is_enabled(timeout=short_wait_seconds):
dropdown.select(value="Active")
An explicit timeout is expressed in seconds. is_enabled(timeout=...) returns True as soon as the live component becomes enabled and returns False if the timeout expires; the state-query timeout is not raised as an automation failure. This is useful for dependent Appian controls such as Status and Owner.
Structured data
Use page.dataset(...) for business data that can appear in three common patterns.
Summary/detail data:
basic_info = page.dataset(header="Basic Information", row_number=1)
status = basic_info.data(field="Workflow Status").value
Repeated/list data:
activity = page.dataset(header="Recent Activities", row_number=1)
action = activity.data(field="Action").value
Grid data:
fund = page.dataset(header="Funds Availability", row_number=1)
available = fund.data(field="Available Funds").value
Use page.grid(...) when the automation specifically needs an Appian grid and its row/cell operations. A dataset can also use the complete row/cell API when appropriate. row_number and column_number are 1-based business positions; [0], [1], and .first are normal result-collection selection.
See AppianDataSet for all dataset lookup and access patterns.
Appian linked cards
page.link(name="...") also supports Appian linked cards. robo-appian finds the requested visible business text using the normal exact rule, then resolves the nearest parent link component (role="link") and performs the action on that component. This lets a BA use the displayed card title even when Appian adds descriptive text to the card. exact=True remains an exact visible-text match; use exact=False only for intentional partial text matching.