Beta Feature — Browser automation is currently in beta. Please report any issues to founders@morphllm.com .
Automatically test your preview deployments with Morph’s AI-powered browser automation. When a PR is opened, Morph tests your preview URL and posts results directly to the PR as a comment.
Quick Start
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.deploy.outputs.url }}
instructions : Test the checkout flow
Setup
Install the Morph GitHub App
Add secrets to your repository
Go to your repository’s Settings → Secrets and variables → Actions and add:
Input Required Description api-keyYes Your Morph API key preview-urlYes Preview deployment URL to test instructionsNo Custom testing instructions for the AI
Outputs
Output Description test-idThe ID of the triggered test statusThe status of the test (started)
Testing with Credentials
For apps that require login, pass credentials via GitHub secrets and reference them in your instructions using x_user and x_pass placeholders.
name : Preview Test
on : pull_request
jobs :
test :
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.deploy.outputs.url }}
instructions : |
1. Go to the login page
2. Log in with username x_user and password x_pass
3. Verify the dashboard loads successfully
4. Check that the user's profile shows the correct email
env :
TEST_USERNAME : ${{ secrets.TEST_USERNAME }}
TEST_PASSWORD : ${{ secrets.TEST_PASSWORD }}
Never hardcode credentials in your workflow file. Always use GitHub secrets and environment variables.
Setting Up Test Credentials
Go to Settings → Secrets and variables → Actions
Add repository secrets:
TEST_USERNAME - Test account email/username
TEST_PASSWORD - Test account password
ADMIN_USERNAME - Admin test account (if needed)
ADMIN_PASSWORD - Admin test password (if needed)
Testing Multiple User Roles
Test different user types by running parallel jobs with different credentials:
name : Preview Tests - All User Roles
on : pull_request
jobs :
test-regular-user :
runs-on : ubuntu-latest
steps :
- name : Wait for Preview
id : preview
run : echo "url=${{ github.event.deployment.payload.web_url }}" >> $GITHUB_OUTPUT
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.preview.outputs.url }}
instructions : |
Test as a regular user:
1. Log in with x_user / x_pass
2. Verify you can view the dashboard
3. Verify you CANNOT access /admin
4. Create a new post and verify it appears
5. Edit your profile settings
env :
TEST_USERNAME : ${{ secrets.USER_EMAIL }}
TEST_PASSWORD : ${{ secrets.USER_PASSWORD }}
test-admin-user :
runs-on : ubuntu-latest
steps :
- name : Wait for Preview
id : preview
run : echo "url=${{ github.event.deployment.payload.web_url }}" >> $GITHUB_OUTPUT
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.preview.outputs.url }}
instructions : |
Test as an admin user:
1. Log in with x_user / x_pass
2. Verify you can access /admin
3. Verify the user management table loads
4. Verify you can view analytics dashboard
5. Check that admin-only actions are visible
env :
TEST_USERNAME : ${{ secrets.ADMIN_EMAIL }}
TEST_PASSWORD : ${{ secrets.ADMIN_PASSWORD }}
test-guest-user :
runs-on : ubuntu-latest
steps :
- name : Wait for Preview
id : preview
run : echo "url=${{ github.event.deployment.payload.web_url }}" >> $GITHUB_OUTPUT
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.preview.outputs.url }}
instructions : |
Test as a guest (not logged in):
1. Verify the homepage loads
2. Verify you can browse public content
3. Verify /dashboard redirects to login
4. Verify the signup flow works
Testing Multiple Flows
Run comprehensive test suites by testing different user journeys:
name : Comprehensive Preview Tests
on : pull_request
jobs :
test-auth-flows :
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ needs.deploy.outputs.url }}
instructions : |
Test authentication flows:
1. Test signup with a new email
2. Verify email validation errors show for invalid emails
3. Test login with valid credentials (x_user / x_pass)
4. Test login with wrong password shows error
5. Test password reset flow (enter email, verify confirmation message)
6. Test logout and verify redirect to homepage
env :
TEST_USERNAME : ${{ secrets.TEST_EMAIL }}
TEST_PASSWORD : ${{ secrets.TEST_PASSWORD }}
test-checkout-flow :
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ needs.deploy.outputs.url }}
instructions : |
Test the complete checkout flow:
1. Browse to /products
2. Add the first product to cart
3. Add a second product to cart
4. Go to cart and verify both items appear
5. Apply discount code "TEST10" and verify discount applied
6. Proceed to checkout
7. Fill shipping form with test data
8. Verify order summary shows correct totals
test-responsive-design :
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ needs.deploy.outputs.url }}
instructions : |
Test responsive design:
1. Resize to mobile (375x667)
2. Verify hamburger menu appears
3. Open mobile menu and verify all links work
4. Resize to tablet (768x1024)
5. Verify layout adjusts appropriately
6. Resize back to desktop (1920x1080)
7. Verify full navigation is visible
Vercel
name : Test Vercel Preview
on :
pull_request :
deployment_status :
jobs :
test :
runs-on : ubuntu-latest
if : github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success'
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ github.event.deployment_status.target_url }}
instructions : |
Verify the deployment:
1. Check homepage loads without errors
2. Verify navigation works
3. Test the main CTA button
Netlify
name : Test Netlify Preview
on : pull_request
jobs :
test :
runs-on : ubuntu-latest
steps :
- name : Wait for Netlify
uses : jakepartusch/wait-for-netlify-action@v1.4
id : netlify
with :
site_name : your-site-name
max_timeout : 300
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.netlify.outputs.url }}
instructions : Verify homepage and navigation work correctly
Railway
name : Test Railway Preview
on : pull_request
jobs :
test :
runs-on : ubuntu-latest
steps :
- name : Get Railway Preview URL
id : railway
run : |
# Railway preview URLs follow this pattern
echo "url=https://your-app-pr-${{ github.event.pull_request.number }}.up.railway.app" >> $GITHUB_OUTPUT
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.railway.outputs.url }}
instructions : Test the application works correctly
Custom Infrastructure (EKS, GKE, Self-hosted)
name : Test Custom Preview
on : pull_request
jobs :
deploy-and-test :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v4
- name : Deploy Preview
id : deploy
run : |
# Your deployment script here
# Example: Deploy to Kubernetes with PR-specific namespace
kubectl apply -f k8s/ -n preview-pr-${{ github.event.pull_request.number }}
echo "url=https://pr-${{ github.event.pull_request.number }}.preview.yourdomain.com" >> $GITHUB_OUTPUT
- name : Wait for deployment
run : sleep 30 # Or use a proper health check
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.deploy.outputs.url }}
instructions : |
Verify the deployment is working:
1. Homepage loads successfully
2. API health check returns 200
3. Login flow works with test credentials
Handling Third-Party Auth (Clerk, Auth0, Supabase)
Third-party auth providers may block automated browsers. Solutions:
Option 1: Add Preview URL to Allowed Origins
Configure your auth provider to accept requests from preview URLs:
Clerk : Dashboard → API Keys → Allowed origins
Auth0 : Applications → Settings → Allowed Origins
Supabase : Authentication → URL Configuration
Add a wildcard pattern like https://*.vercel.app or your specific preview URL pattern.
Option 2: Use Test/Development Mode
Many auth providers have development modes that are more permissive:
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.deploy.outputs.url }}
instructions : |
Note: This preview uses development auth mode.
1. Log in with test credentials x_user / x_pass
2. Verify dashboard access
env :
TEST_USERNAME : ${{ secrets.DEV_TEST_EMAIL }}
TEST_PASSWORD : ${{ secrets.DEV_TEST_PASSWORD }}
Option 3: Test Public Pages Only
For previews, you may choose to only test unauthenticated flows:
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ steps.deploy.outputs.url }}
instructions : |
Test public pages only (auth tested separately):
1. Verify homepage loads
2. Check pricing page displays all tiers
3. Verify contact form appears
4. Test that /login page loads correctly
Writing Effective Test Instructions
Good Instructions
Be specific and actionable:
instructions : |
Test the user signup flow:
1. Click "Sign Up" in the header
2. Enter email "test@example.com" in the email field
3. Enter password "TestPass123!" in the password field
4. Click the "Create Account" button
5. Verify a success message appears
6. Verify the user is redirected to /dashboard
Bad Instructions
Avoid vague descriptions:
# Too vague - don't do this
instructions : Test the app and make sure it works
Tips for Better Tests
Number your steps - Makes it easier to identify where failures occur
Be explicit about expected outcomes - “Verify X appears” rather than “check X”
Use specific selectors when helpful - “Click the green ‘Submit’ button”
Include negative tests - “Verify error message appears for invalid input”
Conditional Testing
Only Test on Specific Files Changed
name : Smart Preview Tests
on : pull_request
jobs :
detect-changes :
runs-on : ubuntu-latest
outputs :
frontend : ${{ steps.changes.outputs.frontend }}
checkout : ${{ steps.changes.outputs.checkout }}
steps :
- uses : dorny/paths-filter@v2
id : changes
with :
filters : |
frontend:
- 'src/components/**'
- 'src/pages/**'
checkout:
- 'src/checkout/**'
- 'src/cart/**'
test-frontend :
needs : detect-changes
if : needs.detect-changes.outputs.frontend == 'true'
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ needs.deploy.outputs.url }}
instructions : Test homepage and navigation components
test-checkout :
needs : detect-changes
if : needs.detect-changes.outputs.checkout == 'true'
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ needs.deploy.outputs.url }}
instructions : Test complete checkout flow with cart
Skip Tests for Draft PRs
jobs :
test :
if : github.event.pull_request.draft == false
runs-on : ubuntu-latest
steps :
- uses : morphllm/preview-test-action@v1
# ...
Complete Production Example
A full workflow with all best practices:
name : Preview Deployment Tests
on :
pull_request :
types : [ opened , synchronize , reopened ]
deployment_status :
concurrency :
group : preview-test-${{ github.head_ref }}
cancel-in-progress : true
jobs :
# Only run when deployment succeeds
test-preview :
if : |
github.event_name == 'deployment_status' &&
github.event.deployment_status.state == 'success'
runs-on : ubuntu-latest
timeout-minutes : 10
steps :
- name : Run Core Flow Tests
uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ github.event.deployment_status.target_url }}
instructions : |
Test core user flows:
## Homepage
1. Verify homepage loads within 3 seconds
2. Check hero section displays correctly
3. Verify main CTA button is visible
## Navigation
4. Click each main nav link and verify page loads
5. Test mobile menu at 375px width
## Authentication
6. Go to /login
7. Log in with x_user / x_pass
8. Verify dashboard loads
9. Verify user email shows in header
10. Log out and verify redirect to homepage
env :
TEST_USERNAME : ${{ secrets.TEST_USER_EMAIL }}
TEST_PASSWORD : ${{ secrets.TEST_USER_PASSWORD }}
- name : Run Admin Tests
uses : morphllm/preview-test-action@v1
with :
api-key : ${{ secrets.MORPH_API_KEY }}
preview-url : ${{ github.event.deployment_status.target_url }}
instructions : |
Test admin functionality:
1. Log in with admin credentials x_user / x_pass
2. Navigate to /admin
3. Verify admin dashboard loads
4. Check user management table displays
5. Verify analytics charts render
env :
TEST_USERNAME : ${{ secrets.ADMIN_EMAIL }}
TEST_PASSWORD : ${{ secrets.ADMIN_PASSWORD }}
Troubleshooting
Test results not appearing on PR
Cause : Morph GitHub App not installed or lacks permissions.Fix :
Install the app at morphllm.com/dashboard/integrations/github
Ensure it has access to your repository
Check the app has “Pull requests: Read and write” permission
Cause : Invalid or missing API key.Fix :
Verify MORPH_API_KEY is set in repository secrets
Check the key is valid at morphllm.com/dashboard/api-keys
Ensure you have available credits
Preview URL not accessible
Cause : Preview not deployed yet or URL incorrect.Fix :
Add a wait/health check step before running tests
Verify the preview URL is publicly accessible
Check deployment logs for errors
- name : Wait for preview
run : |
for i in {1..30}; do
if curl -s -o /dev/null -w "%{http_code}" "${{ steps.deploy.outputs.url }}" | grep -q "200"; then
echo "Preview is ready"
exit 0
fi
sleep 10
done
echo "Preview not ready after 5 minutes"
exit 1
Cause : Third-party auth blocking automated browsers.Fix :
Add preview URL pattern to auth provider’s allowed origins
Use development/test mode credentials
Test only public pages in preview tests
See Handling Third-Party Auth for details.
Cause : Complex tests exceeding default timeout.Fix :
Break complex tests into smaller focused tests
Run tests in parallel jobs
Increase job timeout: timeout-minutes: 15
How It Works
Your CI/CD deploys to your infrastructure (Vercel, Netlify, EKS, etc.)
Action triggers and sends the preview URL to Morph
Morph’s AI browser executes your test instructions
Results posted directly to your PR as a comment
The action uses the same browser automation engine as the SDK, optimized for CI/CD workflows.
Requirements
Morph GitHub App installed on your repository
Valid Morph API key with available credits
Publicly accessible preview URL (cannot test localhost)
See Also