Creating Test Flows
Learn how to create powerful test automation flows using natural language and YAML.
Two Ways to Create Flows
🤖 AI-Generated (Recommended)
Describe what you want to test in plain English, and your AI assistant will generate the YAML flow automatically.
"Create a login test that fills email and password, clicks submit, and checks for dashboard"📝 Manual YAML
Write flows directly in YAML for precise control over every action and condition.
Perfect for complex scenarios and reusable test patternsQuick Start Examples
Login Test
Natural Language:
"Test login functionality by filling the email field with test@example.com, password field with password123, clicking the submit button, and verifying the user lands on the dashboard page"
Generated YAML:
name: Login Test
url: https://myapp.com/login
steps:
- action: fill
selector: '[name="email"]'
value: test@example.com
- action: fill
selector: '[name="password"]'
value: password123
- action: click
selector: 'button[type="submit"]'
- action: expect
selector: '.dashboard'
condition: visibleE-commerce Checkout
Natural Language:
"Test the checkout process by adding a product to cart, going to checkout, filling shipping information, and completing the purchase"
Generated YAML:
name: Checkout Flow
url: https://shop.example.com
steps:
- action: click
selector: '.add-to-cart'
- action: click
selector: '.cart-icon'
- action: click
selector: '.checkout-btn'
- action: fill
selector: '[name="firstName"]'
value: John
- action: fill
selector: '[name="lastName"]'
value: Doe
- action: click
selector: '.complete-order'
- action: expect
selector: '.order-success'
condition: visibleYAML Flow Structure
Basic Structure
name: "Flow Name"
url: "https://example.com"
viewport:
width: 1920
height: 1080
steps:
- action: navigate
url: "https://example.com"
- action: click
selector: "#button"
- action: expect
selector: ".result"
condition: visibleRequired Fields
- name - Descriptive test name
- url - Starting URL for the test
- steps - Array of actions to perform
Optional Fields
- viewport - Browser window size
- timeout - Global timeout (default: 30s)
- device - Mobile device emulation
Available Actions
🧭 Navigation
navigate
Go to a specific URL
action: navigate
url: "https://example.com"reload
Refresh the current page
action: reloadback
Go back in browser history
action: back🖱️ Interaction
click
Click on an element
action: click
selector: ".button"fill
Fill an input field
action: fill
selector: "[name='email']"
value: "test@example.com"select
Select dropdown option
action: select
selector: "select"
value: "option1"✅ Verification
expect
Assert element state
action: expect
selector: ".success"
condition: visibleexpectText
Verify text content
action: expectText
selector: "h1"
text: "Welcome"expectUrl
Check current URL
action: expectUrl
url: "/dashboard"⏱️ Utility
wait
Wait for time or element
action: wait
time: 2000 # milliseconds
# OR
selector: ".loading"screenshot
Take a screenshot
action: screenshot
name: "checkout-page"scroll
Scroll the page
action: scroll
direction: down
amount: 500Selector Best Practices
✅ Recommended
- Data attributes:
[data-testid="login-button"] - IDs:
#submit-form - Semantic attributes:
[name="email"] - ARIA labels:
[aria-label="Close dialog"]
❌ Avoid
- Generic classes:
.btn .btn-primary - Complex CSS paths:
div > ul > li:nth-child(3) - Text-based selectors:
:contains("Click here") - Position-dependent:
table tr:first-child td:last-child
Testing Local Development
Test Your Localhost Apps
When creating flows for local development, CassFlow automatically detects localhost URLs and provides tunnel setup instructions.
Example: Testing Local React App
name: Local Development Test
url: http://localhost:3000
steps:
- action: click
selector: '[data-testid="nav-login"]'
- action: fill
selector: '[name="email"]'
value: test@example.com
- action: fill
selector: '[name="password"]'
value: password123
- action: click
selector: 'button[type="submit"]'
- action: expect
selector: '[data-testid="dashboard"]'
condition: visibleSmart Tunnel Detection
When you use localhost URLs, CassFlow will show you the exact tunnel command to run with your API key and project ID pre-filled.
Advanced Patterns
Conditional Logic
steps:
- action: click
selector: '.login-button'
- action: if
condition:
selector: '.error-message'
exists: true
then:
- action: fill
selector: '[name="email"]'
value: different@email.com
- action: click
selector: '.retry-button'
else:
- action: expect
selector: '.dashboard'
condition: visibleData-Driven Testing
name: Login Test with Multiple Users
url: https://myapp.com/login
data:
users:
- email: admin@example.com
password: admin123
expectedUrl: /admin
- email: user@example.com
password: user123
expectedUrl: /dashboard
steps:
- action: forEach
data: users
steps:
- action: fill
selector: '[name="email"]'
value: "{{email}}"
- action: fill
selector: '[name="password"]'
value: "{{password}}"
- action: click
selector: 'button[type="submit"]'
- action: expectUrl
url: "{{expectedUrl}}"
- action: click
selector: '.logout'Best Practices
💡 Flow Design
- • Keep flows focused on single user journeys
- • Use descriptive names and comments
- • Add assertions at key checkpoints
- • Include cleanup steps when needed
🔧 Maintenance
- • Use stable selectors (data-testid)
- • Avoid hardcoded wait times
- • Test with different viewport sizes
- • Regular review and updates
🚀 Performance
- • Minimize unnecessary navigation
- • Use efficient selectors
- • Batch related actions together
- • Consider parallel execution
🐛 Debugging
- • Add screenshots at failure points
- • Use descriptive step names
- • Check network conditions
- • Verify element timing
Ready to Create Your First Flow?
Start by describing what you want to test in natural language to your AI assistant.