A fluent testing and assertion framework for verifying page state with semantic queries. Perfect for end-to-end tests, validation, and quality assurance.
The Expect API provides a clean, readable syntax for making assertions about page elements using semantic queries. It's designed for:
Creates an assertion builder for fluent testing with semantic queries.
from sentience import expect
expect(browser, selector)"role=button text='Submit'")All assertion methods support an optional timeout parameter (default: 5.0 seconds).
.to_exist(timeout=5.0)Assert that an element matching the selector exists.
from sentience import SentienceBrowser, expect
browser = SentienceBrowser()
browser.start()
browser.page.goto("https://example.com")
# Assert button exists (waits up to 5 seconds)
expect(browser, "role=button text='Submit'").to_exist()
# Custom timeout (wait up to 10 seconds)
expect(browser, "role=button text='Submit'").to_exist(timeout=10.0)
browser.close().to_be_visible(timeout=5.0)Assert that an element is visible in the viewport.
# Assert element is visible
expect(browser, "role=heading").to_be_visible()
# Assert with custom timeout
expect(browser, "role=heading").to_be_visible(timeout=3.0).to_have_text(text, timeout=5.0)Assert that an element contains specific text.
# Assert button has exact text
expect(browser, "role=button").to_have_text("Submit")
# Assert with custom timeout
expect(browser, "role=button").to_have_text("Submit", timeout=10.0).to_have_count(n, timeout=5.0)Assert that a query returns exactly N elements.
# Assert exactly 10 links exist
expect(browser, "role=link").to_have_count(10)
# Assert with custom timeout
expect(browser, "role=link").to_have_count(10, timeout=8.0)from sentience import SentienceBrowser, expect
browser = SentienceBrowser()
browser.start()
browser.page.goto("https://example.com")
# Verify critical elements exist
expect(browser, "role=heading text='Welcome'").to_exist()
expect(browser, "role=button text='Get Started'").to_exist()
expect(browser, "role=link text='Learn More'").to_exist()
# Verify elements are visible
expect(browser, "role=heading").to_be_visible()
expect(browser, "role=button text='Sign Up'").to_be_visible()
browser.close()from sentience import SentienceBrowser, expect, click, find, snapshot
browser = SentienceBrowser()
browser.start()
browser.page.goto("https://example.com")
# Click a button
snap = snapshot(browser)
button = find(snap, "role=button text~'Load More'")
click(browser, button.id)
# Verify new content appears (wait up to 10 seconds)
expect(browser, "role=article").to_have_count(20, timeout=10.0)
# Verify success message
expect(browser, "role=alert text~'Success'").to_be_visible(timeout=5.0)
browser.close()Complete end-to-end test for a login flow:
from sentience import SentienceBrowser, expect, snapshot, find, type_text, click, press
def test_login_flow():
browser = SentienceBrowser()
browser.start()
# Navigate to login page
browser.page.goto("https://example.com/login")
# Verify login form elements exist
expect(browser, "role=textbox text~'email'").to_exist()
expect(browser, "role=textbox text~'password'").to_exist()
expect(browser, "role=button text~'Sign In'").to_exist()
# Fill in credentials
snap = snapshot(browser)
email_field = find(snap, "role=textbox text~'email'")
password_field = find(snap, "role=textbox text~'password'")
type_text(browser, email_field.id, "user@example.com")
type_text(browser, password_field.id, "password123")
# Submit form
submit_btn = find(snap, "role=button text~'Sign In'")
click(browser, submit_btn.id)
# Verify successful login (dashboard appears)
expect(browser, "role=heading text~'Dashboard'").to_exist(timeout=10.0)
expect(browser, "role=button text~'Logout'").to_be_visible()
# Verify user info is displayed
expect(browser, "text~'user@example.com'").to_exist()
browser.close()
print("✅ Login flow test passed!")
# Run test
test_login_flow()Assertions throw exceptions when they fail:
from sentience import SentienceBrowser, expect
browser = SentienceBrowser()
browser.start()
browser.page.goto("https://example.com")
try:
# This will timeout if button doesn't exist
expect(browser, "role=button text='NonExistent'").to_exist(timeout=3.0)
except AssertionError as e:
print(f"❌ Test failed: {e}")
# Continue with error handling or cleanup
browser.close()import pytest
from sentience import SentienceBrowser, expect
@pytest.fixture
def browser():
browser = SentienceBrowser()
browser.start()
yield browser
browser.close()
def test_homepage_elements(browser):
browser.page.goto("https://example.com")
# All assertions use pytest's assert mechanism
expect(browser, "role=heading text='Welcome'").to_exist()
expect(browser, "role=button text='Get Started'").to_be_visible()
expect(browser, "role=link").to_have_count(5)
def test_search_functionality(browser):
browser.page.goto("https://example.com")
# Verify search box exists
expect(browser, "role=textbox text~'search'").to_exist()
# ... rest of test# Not applicable for Python examplePrefer semantic queries over brittle CSS selectors:
# ✅ Good - semantic, resilient to HTML changes
expect(browser, "role=button text~'Submit'").to_exist()
# ❌ Bad - brittle CSS selector
# page.locator('#submit-btn-123').is_visible()
Adjust timeouts based on expected page behavior:
# Fast assertion for static content
expect(browser, "role=heading").to_exist(timeout=2.0)
# Longer timeout for dynamic content (AJAX, loading)
expect(browser, "role=article").to_have_count(10, timeout=15.0)
Use expect() alongside other Sentience APIs:
# Take snapshot first for complex queries
snap = snapshot(browser)
button = find(snap, "role=button importance>800")
# Then assert element is still visible
expect(browser, f"role=button id={button.id}").to_be_visible()
Focus on user-critical flows:
def test_checkout_flow():
# 1. Product page
expect(browser, "role=button text~'Add to Cart'").to_exist()
# 2. Cart page
expect(browser, "role=button text~'Checkout'").to_be_visible()
# 3. Payment page
expect(browser, "role=button text~'Place Order'").to_exist()
Verify UI elements don't disappear after code changes:
def test_navigation_menu():
browser.page.goto("https://example.com")
# Verify all navigation links exist
expect(browser, "role=link text='Home'").to_exist()
expect(browser, "role=link text='Products'").to_exist()
expect(browser, "role=link text='About'").to_exist()
expect(browser, "role=link text='Contact'").to_exist()
Check that ARIA roles are properly assigned:
# Verify button roles
expect(browser, "role=button").to_have_count(5)
# Verify heading hierarchy
expect(browser, "role=heading").to_be_visible()
Test form validation messages:
# Submit empty form
click(browser, submit_button.id)
# Verify error messages appear
expect(browser, "role=alert text~'required'").to_be_visible(timeout=3.0)
Test AJAX-loaded content:
# Click "Load More" button
click(browser, load_more_btn.id)
# Wait for new items to appear
expect(browser, "role=article").to_have_count(20, timeout=10.0)
wait_for()