738 lines
19 KiB
Markdown
738 lines
19 KiB
Markdown
# Advanced Examples
|
|
|
|
Complex workflows and advanced usage patterns for chrome-devtools.
|
|
|
|
## Table of Contents
|
|
|
|
- [E2E Testing Workflows](#e2e-testing-workflows)
|
|
- [Web Scraping Patterns](#web-scraping-patterns)
|
|
- [Performance Optimization](#performance-optimization)
|
|
- [CI/CD Integration](#cicd-integration)
|
|
- [Cross-Browser Testing Simulation](#cross-browser-testing-simulation)
|
|
- [Advanced JavaScript Extraction](#advanced-javascript-extraction)
|
|
|
|
---
|
|
|
|
## E2E Testing Workflows
|
|
|
|
### Complete User Registration Flow
|
|
|
|
Test full registration process with validation:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# test_registration.sh
|
|
|
|
echo "Starting registration flow test..."
|
|
|
|
# 1. Open registration page
|
|
node scripts/new_page.js --url https://example.com/register
|
|
|
|
# 2. Wait for page load
|
|
node scripts/wait_for.js --text "Create Account" --timeout 10000
|
|
|
|
# 3. Get form structure
|
|
node scripts/take_snapshot.js --filePath registration_form.txt
|
|
|
|
# 4. Fill registration form (update UIDs from snapshot)
|
|
node scripts/fill_form.js --elements '[
|
|
{"uid":"input_firstname","value":"John"},
|
|
{"uid":"input_lastname","value":"Doe"},
|
|
{"uid":"input_email","value":"john.doe@example.com"},
|
|
{"uid":"input_password","value":"SecurePass123!"},
|
|
{"uid":"input_password_confirm","value":"SecurePass123!"},
|
|
{"uid":"select_country","value":"United States"}
|
|
]'
|
|
|
|
# 5. Screenshot before submission
|
|
node scripts/take_screenshot.js --filePath before_submit.png
|
|
|
|
# 6. Accept terms checkbox
|
|
node scripts/click.js --uid checkbox_terms
|
|
|
|
# 7. Submit form
|
|
node scripts/click.js --uid button_register
|
|
|
|
# 8. Wait for success message
|
|
if node scripts/wait_for.js --text "Registration successful" --timeout 15000; then
|
|
echo "✓ Registration succeeded"
|
|
|
|
# 9. Capture success state
|
|
node scripts/take_screenshot.js --filePath registration_success.png
|
|
node scripts/take_snapshot.js --filePath success_page.txt
|
|
|
|
# 10. Check for welcome email notification
|
|
node scripts/wait_for.js --text "Verification email sent" --timeout 5000
|
|
|
|
echo "✓ Test passed: Registration flow complete"
|
|
exit 0
|
|
else
|
|
echo "✗ Registration failed"
|
|
|
|
# Capture error state
|
|
node scripts/take_screenshot.js --filePath registration_error.png
|
|
node scripts/list_console_messages.js --types error > console_errors.txt
|
|
|
|
echo "✗ Test failed: See error screenshots and logs"
|
|
exit 1
|
|
fi
|
|
```
|
|
|
|
### Shopping Cart Checkout Flow
|
|
|
|
Test complete e-commerce checkout:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# test_checkout.sh
|
|
|
|
echo "Testing checkout flow..."
|
|
|
|
# 1. Navigate to product page
|
|
node scripts/new_page.js --url https://example.com/products/widget-123
|
|
|
|
# 2. Wait and verify product loads
|
|
node scripts/wait_for.js --text "Add to Cart" --timeout 10000
|
|
node scripts/take_snapshot.js > product_page.txt
|
|
|
|
# 3. Add to cart
|
|
node scripts/click.js --uid button_add_to_cart
|
|
node scripts/wait_for.js --text "Added to cart" --timeout 5000
|
|
|
|
# 4. Go to cart
|
|
node scripts/click.js --uid link_view_cart
|
|
node scripts/wait_for.js --text "Shopping Cart" --timeout 5000
|
|
|
|
# 5. Verify cart contents
|
|
node scripts/take_snapshot.js --filePath cart_contents.txt
|
|
node scripts/evaluate_script.js --function "() => document.querySelector('.cart-total').textContent" > cart_total.txt
|
|
|
|
# 6. Proceed to checkout
|
|
node scripts/click.js --uid button_checkout
|
|
node scripts/wait_for.js --text "Shipping Information" --timeout 10000
|
|
|
|
# 7. Fill shipping info
|
|
node scripts/fill_form.js --elements '[
|
|
{"uid":"input_address","value":"123 Main Street"},
|
|
{"uid":"input_city","value":"San Francisco"},
|
|
{"uid":"input_state","value":"CA"},
|
|
{"uid":"input_zip","value":"94102"}
|
|
]'
|
|
|
|
# 8. Continue to payment
|
|
node scripts/click.js --uid button_continue
|
|
node scripts/wait_for.js --text "Payment Method" --timeout 10000
|
|
|
|
# 9. Select payment method
|
|
node scripts/click.js --uid radio_credit_card
|
|
|
|
# 10. Fill payment info (test mode)
|
|
node scripts/fill_form.js --elements '[
|
|
{"uid":"input_card_number","value":"4242424242424242"},
|
|
{"uid":"input_card_expiry","value":"12/25"},
|
|
{"uid":"input_card_cvc","value":"123"}
|
|
]'
|
|
|
|
# 11. Place order
|
|
node scripts/click.js --uid button_place_order
|
|
node scripts/wait_for.js --text "Order Confirmed" --timeout 20000
|
|
|
|
# 12. Capture confirmation
|
|
node scripts/take_screenshot.js --filePath order_confirmation.png
|
|
node scripts/evaluate_script.js --function "() => ({orderNumber: document.querySelector('.order-number').textContent, total: document.querySelector('.order-total').textContent})" > order_details.json
|
|
|
|
echo "✓ Checkout flow completed successfully"
|
|
```
|
|
|
|
---
|
|
|
|
## Web Scraping Patterns
|
|
|
|
### Multi-Page Data Extraction
|
|
|
|
Scrape data across paginated results:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# scrape_listings.sh
|
|
|
|
BASE_URL="https://example.com/listings"
|
|
OUTPUT_FILE="all_listings.json"
|
|
MAX_PAGES=10
|
|
|
|
echo "[" > $OUTPUT_FILE
|
|
|
|
for page in $(seq 1 $MAX_PAGES); do
|
|
echo "Scraping page $page..."
|
|
|
|
# Navigate to page
|
|
if [ $page -eq 1 ]; then
|
|
node scripts/new_page.js --url "$BASE_URL"
|
|
else
|
|
node scripts/navigate_page.js --url "$BASE_URL?page=$page"
|
|
fi
|
|
|
|
# Wait for listings to load
|
|
node scripts/wait_for.js --text "listings found" --timeout 10000
|
|
|
|
# Extract listings data
|
|
LISTINGS=$(node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.listing')).map(item => ({
|
|
title: item.querySelector('.title').textContent.trim(),
|
|
price: item.querySelector('.price').textContent.trim(),
|
|
location: item.querySelector('.location').textContent.trim(),
|
|
url: item.querySelector('a').href
|
|
}))")
|
|
|
|
# Append to output (remove outer brackets)
|
|
echo "$LISTINGS" | jq '.[]' >> $OUTPUT_FILE
|
|
|
|
# Check if there's a next page
|
|
HAS_NEXT=$(node scripts/evaluate_script.js --function "() => document.querySelector('.pagination .next') !== null")
|
|
|
|
if [ "$HAS_NEXT" != "true" ]; then
|
|
echo "Reached last page at page $page"
|
|
break
|
|
fi
|
|
|
|
# Add comma separator
|
|
if [ $page -lt $MAX_PAGES ]; then
|
|
echo "," >> $OUTPUT_FILE
|
|
fi
|
|
|
|
# Be polite: wait between requests
|
|
sleep 2
|
|
done
|
|
|
|
echo "]" >> $OUTPUT_FILE
|
|
|
|
echo "✓ Scraped listings saved to $OUTPUT_FILE"
|
|
|
|
# Summary statistics
|
|
TOTAL=$(cat $OUTPUT_FILE | jq 'length')
|
|
echo "Total listings extracted: $TOTAL"
|
|
```
|
|
|
|
### Dynamic Content Scraping with Infinite Scroll
|
|
|
|
Extract data from infinite scroll pages:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# scrape_infinite_scroll.sh
|
|
|
|
echo "Scraping infinite scroll content..."
|
|
|
|
# Open page
|
|
node scripts/new_page.js --url https://example.com/feed
|
|
|
|
# Wait for initial content
|
|
node scripts/wait_for.js --text "Post" --timeout 10000
|
|
|
|
# Initialize
|
|
PREVIOUS_COUNT=0
|
|
SCROLL_ATTEMPTS=0
|
|
MAX_SCROLLS=20
|
|
OUTPUT_FILE="feed_items.json"
|
|
|
|
while [ $SCROLL_ATTEMPTS -lt $MAX_SCROLLS ]; do
|
|
# Count current items
|
|
CURRENT_COUNT=$(node scripts/evaluate_script.js --function "() => document.querySelectorAll('.feed-item').length")
|
|
|
|
echo "Scroll $SCROLL_ATTEMPTS: Found $CURRENT_COUNT items"
|
|
|
|
# Check if we got new items
|
|
if [ "$CURRENT_COUNT" -eq "$PREVIOUS_COUNT" ]; then
|
|
echo "No new items loaded, reached end"
|
|
break
|
|
fi
|
|
|
|
PREVIOUS_COUNT=$CURRENT_COUNT
|
|
|
|
# Scroll to bottom
|
|
node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"
|
|
|
|
# Wait for new content to load
|
|
sleep 2
|
|
|
|
SCROLL_ATTEMPTS=$((SCROLL_ATTEMPTS + 1))
|
|
done
|
|
|
|
# Extract all items
|
|
echo "Extracting all $CURRENT_COUNT items..."
|
|
|
|
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.feed-item')).map(item => ({
|
|
author: item.querySelector('.author').textContent.trim(),
|
|
content: item.querySelector('.content').textContent.trim(),
|
|
timestamp: item.querySelector('.timestamp').textContent.trim(),
|
|
likes: item.querySelector('.likes').textContent.trim()
|
|
}))" > $OUTPUT_FILE
|
|
|
|
echo "✓ Extracted $CURRENT_COUNT items to $OUTPUT_FILE"
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Optimization
|
|
|
|
### Automated Performance Regression Testing
|
|
|
|
Compare performance across builds:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# performance_regression_test.sh
|
|
|
|
BASELINE_URL="https://staging.example.com"
|
|
CURRENT_URL="https://production.example.com"
|
|
|
|
echo "Running performance regression tests..."
|
|
|
|
# Test baseline (staging)
|
|
echo "Testing baseline: $BASELINE_URL"
|
|
|
|
node scripts/new_page.js --url "$BASELINE_URL"
|
|
node scripts/performance_start_trace.js --reload true --autoStop false
|
|
node scripts/wait_for.js --text "Ready" --timeout 30000
|
|
node scripts/performance_stop_trace.js > baseline_trace.json
|
|
|
|
BASELINE_LCP=$(cat baseline_trace.json | jq -r '.metrics.LCP.value')
|
|
BASELINE_FID=$(cat baseline_trace.json | jq -r '.metrics.FID.value')
|
|
BASELINE_CLS=$(cat baseline_trace.json | jq -r '.metrics.CLS.value')
|
|
|
|
echo "Baseline: LCP=$BASELINE_LCP, FID=$BASELINE_FID, CLS=$BASELINE_CLS"
|
|
|
|
# Test current (production)
|
|
echo "Testing current: $CURRENT_URL"
|
|
|
|
node scripts/navigate_page.js --url "$CURRENT_URL"
|
|
node scripts/performance_start_trace.js --reload true --autoStop false
|
|
node scripts/wait_for.js --text "Ready" --timeout 30000
|
|
node scripts/performance_stop_trace.js > current_trace.json
|
|
|
|
CURRENT_LCP=$(cat current_trace.json | jq -r '.metrics.LCP.value')
|
|
CURRENT_FID=$(cat current_trace.json | jq -r '.metrics.FID.value')
|
|
CURRENT_CLS=$(cat current_trace.json | jq -r '.metrics.CLS.value')
|
|
|
|
echo "Current: LCP=$CURRENT_LCP, FID=$CURRENT_FID, CLS=$CURRENT_CLS"
|
|
|
|
# Compare (allow 10% regression threshold)
|
|
THRESHOLD=1.1
|
|
FAILED=false
|
|
|
|
LCP_RATIO=$(echo "scale=2; $CURRENT_LCP / $BASELINE_LCP" | bc)
|
|
if (( $(echo "$LCP_RATIO > $THRESHOLD" | bc -l) )); then
|
|
echo "✗ LCP regression detected: ${CURRENT_LCP}ms vs ${BASELINE_LCP}ms"
|
|
FAILED=true
|
|
else
|
|
echo "✓ LCP within threshold"
|
|
fi
|
|
|
|
FID_RATIO=$(echo "scale=2; $CURRENT_FID / $BASELINE_FID" | bc)
|
|
if (( $(echo "$FID_RATIO > $THRESHOLD" | bc -l) )); then
|
|
echo "✗ FID regression detected: ${CURRENT_FID}ms vs ${BASELINE_FID}ms"
|
|
FAILED=true
|
|
else
|
|
echo "✓ FID within threshold"
|
|
fi
|
|
|
|
CLS_RATIO=$(echo "scale=2; $CURRENT_CLS / $BASELINE_CLS" | bc)
|
|
if (( $(echo "$CLS_RATIO > $THRESHOLD" | bc -l) )); then
|
|
echo "✗ CLS regression detected: ${CURRENT_CLS} vs ${BASELINE_CLS}"
|
|
FAILED=true
|
|
else
|
|
echo "✓ CLS within threshold"
|
|
fi
|
|
|
|
if [ "$FAILED" = true ]; then
|
|
echo "Performance regression test FAILED"
|
|
exit 1
|
|
else
|
|
echo "Performance regression test PASSED"
|
|
exit 0
|
|
fi
|
|
```
|
|
|
|
### Network Performance Testing Matrix
|
|
|
|
Test performance across network conditions:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# network_performance_matrix.sh
|
|
|
|
URL="https://example.com"
|
|
OUTPUT_DIR="performance_results"
|
|
|
|
mkdir -p $OUTPUT_DIR
|
|
|
|
# Define network profiles
|
|
declare -A NETWORKS
|
|
NETWORKS["fast"]='{"downloadThroughput":10000000,"uploadThroughput":10000000,"latency":10}'
|
|
NETWORKS["4g"]='{"downloadThroughput":1600000,"uploadThroughput":750000,"latency":150}'
|
|
NETWORKS["3g"]='{"downloadThroughput":180000,"uploadThroughput":84000,"latency":562}'
|
|
NETWORKS["slow-3g"]='{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
|
|
|
|
echo "Testing performance across network conditions..."
|
|
|
|
# Open page once
|
|
node scripts/new_page.js --url "$URL"
|
|
|
|
for profile in "${!NETWORKS[@]}"; do
|
|
echo "Testing network profile: $profile"
|
|
|
|
# Apply network emulation
|
|
node scripts/emulate.js --networkConditions "${NETWORKS[$profile]}"
|
|
|
|
# Run performance trace
|
|
node scripts/performance_start_trace.js --reload true --autoStop false
|
|
node scripts/wait_for.js --text "Ready" --timeout 60000
|
|
node scripts/performance_stop_trace.js > "$OUTPUT_DIR/${profile}_trace.json"
|
|
|
|
# Extract key metrics
|
|
LCP=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.LCP.value')
|
|
FID=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.FID.value')
|
|
CLS=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.CLS.value')
|
|
|
|
echo "$profile: LCP=${LCP}ms, FID=${FID}ms, CLS=$CLS"
|
|
|
|
# Capture screenshot
|
|
node scripts/take_screenshot.js --filePath "$OUTPUT_DIR/${profile}_loaded.png"
|
|
done
|
|
|
|
# Reset to normal
|
|
node scripts/emulate.js --cpuThrottlingRate 1
|
|
|
|
echo "✓ Performance testing complete. Results in $OUTPUT_DIR/"
|
|
```
|
|
|
|
---
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitHub Actions Workflow
|
|
|
|
```yaml
|
|
# .github/workflows/e2e-tests.yml
|
|
name: E2E Tests
|
|
|
|
on:
|
|
push:
|
|
branches: [ main, develop ]
|
|
pull_request:
|
|
branches: [ main ]
|
|
|
|
jobs:
|
|
e2e-tests:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v3
|
|
with:
|
|
node-version: '18'
|
|
|
|
- name: Install mcp2skill-tools
|
|
run: |
|
|
npm install -g mcp2skill-tools
|
|
|
|
- name: Start mcp2rest
|
|
run: |
|
|
mcp2rest start
|
|
mcp2rest add chrome-devtools
|
|
|
|
- name: Install skill dependencies
|
|
run: |
|
|
cd ~/.claude/skills/mcp-chrome-devtools/scripts
|
|
npm install
|
|
|
|
- name: Run E2E tests
|
|
run: |
|
|
cd tests
|
|
bash test_registration.sh
|
|
bash test_checkout.sh
|
|
bash test_search.sh
|
|
|
|
- name: Upload test artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: test-results
|
|
path: |
|
|
**/*.png
|
|
**/*.txt
|
|
**/*.json
|
|
|
|
- name: Stop mcp2rest
|
|
if: always()
|
|
run: mcp2rest stop
|
|
```
|
|
|
|
### Jenkins Pipeline
|
|
|
|
```groovy
|
|
// Jenkinsfile
|
|
pipeline {
|
|
agent any
|
|
|
|
environment {
|
|
NODE_VERSION = '18'
|
|
}
|
|
|
|
stages {
|
|
stage('Setup') {
|
|
steps {
|
|
sh 'npm install -g mcp2skill-tools'
|
|
sh 'mcp2rest start'
|
|
sh 'mcp2rest add chrome-devtools'
|
|
}
|
|
}
|
|
|
|
stage('Install Dependencies') {
|
|
steps {
|
|
dir('~/.claude/skills/mcp-chrome-devtools/scripts') {
|
|
sh 'npm install'
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('E2E Tests') {
|
|
parallel {
|
|
stage('Registration Flow') {
|
|
steps {
|
|
sh 'bash tests/test_registration.sh'
|
|
}
|
|
}
|
|
stage('Checkout Flow') {
|
|
steps {
|
|
sh 'bash tests/test_checkout.sh'
|
|
}
|
|
}
|
|
stage('Search Flow') {
|
|
steps {
|
|
sh 'bash tests/test_search.sh'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Performance Tests') {
|
|
steps {
|
|
sh 'bash tests/performance_regression_test.sh'
|
|
}
|
|
}
|
|
}
|
|
|
|
post {
|
|
always {
|
|
archiveArtifacts artifacts: '**/*.png,**/*.txt,**/*.json', allowEmptyArchive: true
|
|
sh 'mcp2rest stop'
|
|
}
|
|
failure {
|
|
emailext (
|
|
subject: "E2E Tests Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
|
|
body: "Check console output at ${env.BUILD_URL}",
|
|
to: "team@example.com"
|
|
)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Cross-Browser Testing Simulation
|
|
|
|
### Device Emulation Matrix
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# device_matrix_test.sh
|
|
|
|
URL="https://example.com"
|
|
OUTPUT_DIR="device_screenshots"
|
|
|
|
mkdir -p $OUTPUT_DIR
|
|
|
|
# Define device viewports
|
|
declare -A DEVICES
|
|
DEVICES["desktop_1080"]="1920 1080"
|
|
DEVICES["desktop_720"]="1280 720"
|
|
DEVICES["laptop"]="1366 768"
|
|
DEVICES["ipad_portrait"]="768 1024"
|
|
DEVICES["ipad_landscape"]="1024 768"
|
|
DEVICES["iphone_portrait"]="375 667"
|
|
DEVICES["iphone_landscape"]="667 375"
|
|
DEVICES["android_portrait"]="360 640"
|
|
DEVICES["android_landscape"]="640 360"
|
|
|
|
echo "Testing across device viewports..."
|
|
|
|
# Open page
|
|
node scripts/new_page.js --url "$URL"
|
|
|
|
for device in "${!DEVICES[@]}"; do
|
|
echo "Testing device: $device"
|
|
|
|
# Parse dimensions
|
|
read -r width height <<< "${DEVICES[$device]}"
|
|
|
|
# Resize window
|
|
node scripts/resize_page.js --width $width --height $height
|
|
|
|
# Wait for reflow
|
|
sleep 2
|
|
|
|
# Capture screenshot
|
|
node scripts/take_screenshot.js --fullPage true --filePath "$OUTPUT_DIR/${device}.png"
|
|
|
|
# Capture snapshot for debugging
|
|
node scripts/take_snapshot.js --filePath "$OUTPUT_DIR/${device}_snapshot.txt"
|
|
done
|
|
|
|
echo "✓ Device matrix testing complete. Screenshots in $OUTPUT_DIR/"
|
|
```
|
|
|
|
---
|
|
|
|
## Advanced JavaScript Extraction
|
|
|
|
### Extract Structured Data from SPA
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# extract_spa_data.sh
|
|
|
|
echo "Extracting data from Single Page Application..."
|
|
|
|
# Open SPA
|
|
node scripts/new_page.js --url https://example.com/dashboard
|
|
|
|
# Wait for app to initialize
|
|
node scripts/wait_for.js --text "Dashboard" --timeout 15000
|
|
|
|
# Wait for data to load (check for spinner to disappear)
|
|
node scripts/evaluate_script.js --function "() => new Promise(resolve => {
|
|
const checkSpinner = setInterval(() => {
|
|
if (!document.querySelector('.loading-spinner')) {
|
|
clearInterval(checkSpinner);
|
|
resolve(true);
|
|
}
|
|
}, 100);
|
|
})"
|
|
|
|
# Extract React/Vue component state
|
|
APP_STATE=$(node scripts/evaluate_script.js --function "() => {
|
|
// Try to access React DevTools state
|
|
const root = document.querySelector('#root');
|
|
const reactInternals = root._reactRootContainer || root._reactInternalFiber;
|
|
|
|
// Or access Vue instance
|
|
const vueInstance = root.__vue__;
|
|
|
|
// Extract data from global state (Redux, Vuex, etc.)
|
|
return {
|
|
redux: window.__REDUX_DEVTOOLS_EXTENSION__ ? window.store.getState() : null,
|
|
vuex: window.__VUEX_DEVTOOLS_GLOBAL_HOOK__ ? window.$store.state : null,
|
|
// Or extract directly from DOM
|
|
domData: Array.from(document.querySelectorAll('.data-item')).map(item => ({
|
|
id: item.dataset.id,
|
|
title: item.querySelector('.title').textContent,
|
|
value: item.querySelector('.value').textContent
|
|
}))
|
|
};
|
|
}")
|
|
|
|
echo "$APP_STATE" | jq '.' > app_state.json
|
|
|
|
echo "✓ Extracted application state to app_state.json"
|
|
```
|
|
|
|
### Monitor Real-Time Updates
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# monitor_realtime_updates.sh
|
|
|
|
echo "Monitoring real-time updates..."
|
|
|
|
# Open page with real-time data
|
|
node scripts/new_page.js --url https://example.com/live-feed
|
|
|
|
# Set up monitoring script
|
|
node scripts/evaluate_script.js --function "() => {
|
|
window.updates = [];
|
|
window.observer = new MutationObserver(mutations => {
|
|
mutations.forEach(mutation => {
|
|
if (mutation.type === 'childList') {
|
|
mutation.addedNodes.forEach(node => {
|
|
if (node.classList && node.classList.contains('update-item')) {
|
|
window.updates.push({
|
|
timestamp: new Date().toISOString(),
|
|
content: node.textContent,
|
|
type: node.dataset.type
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
const container = document.querySelector('.updates-container');
|
|
window.observer.observe(container, { childList: true, subtree: true });
|
|
|
|
return 'Monitoring started';
|
|
}"
|
|
|
|
# Wait for updates to accumulate
|
|
echo "Collecting updates for 60 seconds..."
|
|
sleep 60
|
|
|
|
# Retrieve collected updates
|
|
UPDATES=$(node scripts/evaluate_script.js --function "() => window.updates")
|
|
|
|
echo "$UPDATES" | jq '.' > realtime_updates.json
|
|
|
|
# Clean up
|
|
node scripts/evaluate_script.js --function "() => { window.observer.disconnect(); return 'Monitoring stopped'; }"
|
|
|
|
echo "✓ Collected updates saved to realtime_updates.json"
|
|
```
|
|
|
|
---
|
|
|
|
## Complex Workflow Orchestration
|
|
|
|
### Multi-User Simulation
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# simulate_multi_user.sh
|
|
|
|
echo "Simulating multi-user interactions..."
|
|
|
|
# User 1: Admin workflow
|
|
(
|
|
echo "User 1: Admin actions"
|
|
node scripts/new_page.js --url https://example.com/admin
|
|
node scripts/wait_for.js --text "Admin Panel" --timeout 10000
|
|
# ... admin actions ...
|
|
) &
|
|
|
|
# User 2: Customer workflow
|
|
(
|
|
echo "User 2: Customer actions"
|
|
node scripts/new_page.js --url https://example.com/shop
|
|
node scripts/wait_for.js --text "Products" --timeout 10000
|
|
# ... customer actions ...
|
|
) &
|
|
|
|
# Wait for both users to complete
|
|
wait
|
|
|
|
echo "✓ Multi-user simulation complete"
|
|
```
|
|
|
|
This advanced examples reference provides production-ready patterns for complex automation, testing, and data extraction workflows.
|