Add C4A-Script support and documentation
- Generate OneShot js code geenrator - Introduced a new C4A-Script tutorial example for login flow using Blockly. - Updated index.html to include Blockly theme and event editor modal for script editing. - Created a test HTML file for testing Blockly integration. - Added comprehensive C4A-Script API reference documentation covering commands, syntax, and examples. - Developed core documentation for C4A-Script, detailing its features, commands, and real-world examples. - Updated mkdocs.yml to include new C4A-Script documentation in navigation.
This commit is contained in:
7
docs/examples/c4a_script/script_samples/add_to_cart.c4a
Normal file
7
docs/examples/c4a_script/script_samples/add_to_cart.c4a
Normal file
@@ -0,0 +1,7 @@
|
||||
GO https://store.example.com/product/laptop
|
||||
WAIT `.product-details` 8
|
||||
CLICK `button.add-to-cart`
|
||||
WAIT `.cart-notification` 3
|
||||
CLICK `.cart-icon`
|
||||
WAIT `.checkout-btn` 5
|
||||
CLICK `.checkout-btn`
|
||||
@@ -0,0 +1,43 @@
|
||||
# Advanced control flow with IF, EXISTS, and REPEAT
|
||||
|
||||
# Define reusable procedures
|
||||
PROC handle_cookie_banner
|
||||
IF (EXISTS `.cookie-banner`) THEN CLICK `.accept-cookies`
|
||||
IF (EXISTS `.privacy-notice`) THEN CLICK `.dismiss-privacy`
|
||||
ENDPROC
|
||||
|
||||
PROC scroll_to_load
|
||||
SCROLL DOWN 500
|
||||
WAIT 0.5
|
||||
ENDPROC
|
||||
|
||||
PROC try_login
|
||||
CLICK `#email`
|
||||
TYPE "user@example.com"
|
||||
CLICK `#password`
|
||||
TYPE "secure123"
|
||||
CLICK `button[type="submit"]`
|
||||
WAIT 2
|
||||
ENDPROC
|
||||
|
||||
# Main script
|
||||
GO https://example.com
|
||||
WAIT 2
|
||||
|
||||
# Handle popups
|
||||
handle_cookie_banner
|
||||
|
||||
# Conditional navigation based on login state
|
||||
IF (EXISTS `.user-menu`) THEN CLICK `.dashboard-link` ELSE try_login
|
||||
|
||||
# Repeat scrolling based on content count
|
||||
REPEAT (scroll_to_load, 5)
|
||||
|
||||
# Load more content while button exists
|
||||
REPEAT (CLICK `.load-more`, `document.querySelector('.load-more') && !document.querySelector('.no-more-content')`)
|
||||
|
||||
# Process items conditionally
|
||||
IF (`document.querySelectorAll('.item').length > 10`) THEN EVAL `console.log('Found ' + document.querySelectorAll('.item').length + ' items')`
|
||||
|
||||
# Complex condition with viewport check
|
||||
IF (`window.innerWidth < 768 && document.querySelector('.mobile-menu')`) THEN CLICK `.mobile-menu-toggle`
|
||||
@@ -0,0 +1,8 @@
|
||||
GO https://myapp.com
|
||||
WAIT 2
|
||||
IF (EXISTS `.user-avatar`) THEN CLICK `.logout` ELSE CLICK `.login`
|
||||
WAIT `#auth-form` 5
|
||||
IF (EXISTS `#auth-form`) THEN TYPE "user@example.com"
|
||||
IF (EXISTS `#auth-form`) THEN PRESS Tab
|
||||
IF (EXISTS `#auth-form`) THEN TYPE "password123"
|
||||
IF (EXISTS `#auth-form`) THEN CLICK `button[type="submit"]`
|
||||
56
docs/examples/c4a_script/script_samples/data_extraction.c4a
Normal file
56
docs/examples/c4a_script/script_samples/data_extraction.c4a
Normal file
@@ -0,0 +1,56 @@
|
||||
# Data extraction example
|
||||
# Scrapes product information from an e-commerce site
|
||||
|
||||
# Navigate to products page
|
||||
GO https://shop.example.com/products
|
||||
WAIT `.product-list` 10
|
||||
|
||||
# Scroll to load lazy-loaded content
|
||||
SCROLL DOWN 500
|
||||
WAIT 1
|
||||
SCROLL DOWN 500
|
||||
WAIT 1
|
||||
SCROLL DOWN 500
|
||||
WAIT 2
|
||||
|
||||
# Extract product data
|
||||
EVAL `
|
||||
// Extract all product information
|
||||
const products = Array.from(document.querySelectorAll('.product-card')).map((card, index) => {
|
||||
return {
|
||||
id: index + 1,
|
||||
name: card.querySelector('.product-title')?.textContent?.trim() || 'N/A',
|
||||
price: card.querySelector('.price')?.textContent?.trim() || 'N/A',
|
||||
rating: card.querySelector('.rating')?.textContent?.trim() || 'N/A',
|
||||
availability: card.querySelector('.in-stock') ? 'In Stock' : 'Out of Stock',
|
||||
image: card.querySelector('img')?.src || 'N/A'
|
||||
};
|
||||
});
|
||||
|
||||
// Log results
|
||||
console.log('=== Product Extraction Results ===');
|
||||
console.log('Total products found:', products.length);
|
||||
console.log(JSON.stringify(products, null, 2));
|
||||
|
||||
// Save to localStorage for retrieval
|
||||
localStorage.setItem('scraped_products', JSON.stringify(products));
|
||||
`
|
||||
|
||||
# Optional: Click on first product for details
|
||||
CLICK `.product-card:first-child`
|
||||
WAIT `.product-details` 5
|
||||
|
||||
# Extract detailed information
|
||||
EVAL `
|
||||
const details = {
|
||||
description: document.querySelector('.product-description')?.textContent?.trim(),
|
||||
specifications: Array.from(document.querySelectorAll('.spec-item')).map(spec => ({
|
||||
label: spec.querySelector('.spec-label')?.textContent,
|
||||
value: spec.querySelector('.spec-value')?.textContent
|
||||
})),
|
||||
reviews: document.querySelector('.review-count')?.textContent
|
||||
};
|
||||
|
||||
console.log('=== Product Details ===');
|
||||
console.log(JSON.stringify(details, null, 2));
|
||||
`
|
||||
8
docs/examples/c4a_script/script_samples/fill_contact.c4a
Normal file
8
docs/examples/c4a_script/script_samples/fill_contact.c4a
Normal file
@@ -0,0 +1,8 @@
|
||||
GO https://company.com/contact
|
||||
WAIT `form#contact` 10
|
||||
TYPE "John Smith"
|
||||
PRESS Tab
|
||||
TYPE "john@email.com"
|
||||
PRESS Tab
|
||||
TYPE "Need help with my order"
|
||||
CLICK `button[type="submit"]`
|
||||
@@ -0,0 +1,7 @@
|
||||
GO https://news.example.com
|
||||
WAIT `.article-list` 5
|
||||
REPEAT (SCROLL DOWN 500, 3)
|
||||
WAIT 1
|
||||
REPEAT (CLICK `.load-more`, `document.querySelector('.load-more') !== null`)
|
||||
WAIT 2
|
||||
IF (`document.querySelectorAll('.article').length > 20`) THEN EVAL `console.log('Loaded enough articles')`
|
||||
36
docs/examples/c4a_script/script_samples/login_flow.c4a
Normal file
36
docs/examples/c4a_script/script_samples/login_flow.c4a
Normal file
@@ -0,0 +1,36 @@
|
||||
# Login flow with error handling
|
||||
# Demonstrates procedures, variables, and conditional checks
|
||||
|
||||
# Define login procedure
|
||||
PROC perform_login
|
||||
CLICK `input#email`
|
||||
TYPE $email
|
||||
CLICK `input#password`
|
||||
TYPE $password
|
||||
CLICK `button.login-submit`
|
||||
ENDPROC
|
||||
|
||||
# Set credentials
|
||||
SET email = "user@example.com"
|
||||
SET password = "securePassword123"
|
||||
|
||||
# Navigate to login page
|
||||
GO https://app.example.com/login
|
||||
WAIT `.login-container` 15
|
||||
|
||||
# Attempt login
|
||||
perform_login
|
||||
|
||||
# Wait for page to load
|
||||
WAIT 3
|
||||
|
||||
# Check if login was successful
|
||||
EVAL `
|
||||
if (document.querySelector('.dashboard')) {
|
||||
console.log('Login successful - on dashboard');
|
||||
} else if (document.querySelector('.error-message')) {
|
||||
console.log('Login failed:', document.querySelector('.error-message').textContent);
|
||||
} else {
|
||||
console.log('Unknown state after login');
|
||||
}
|
||||
`
|
||||
106
docs/examples/c4a_script/script_samples/multi_step_workflow.c4a
Normal file
106
docs/examples/c4a_script/script_samples/multi_step_workflow.c4a
Normal file
@@ -0,0 +1,106 @@
|
||||
# Multi-step e-commerce workflow
|
||||
# Complete purchase flow with procedures and error handling
|
||||
|
||||
# Reusable procedures
|
||||
PROC search_product
|
||||
CLICK `input.search-bar`
|
||||
TYPE $search_term
|
||||
PRESS Enter
|
||||
WAIT `.search-results` 10
|
||||
ENDPROC
|
||||
|
||||
PROC add_first_item_to_cart
|
||||
CLICK `.product-item:first-child .add-to-cart`
|
||||
WAIT ".added-to-cart-notification" 3
|
||||
ENDPROC
|
||||
|
||||
PROC go_to_checkout
|
||||
CLICK `.cart-icon`
|
||||
WAIT `.cart-drawer` 5
|
||||
CLICK `button.proceed-to-checkout`
|
||||
WAIT `.checkout-page` 10
|
||||
ENDPROC
|
||||
|
||||
PROC fill_customer_info
|
||||
# Billing information
|
||||
CLICK `#billing-firstname`
|
||||
TYPE $first_name
|
||||
CLICK `#billing-lastname`
|
||||
TYPE $last_name
|
||||
CLICK `#billing-email`
|
||||
TYPE $email
|
||||
CLICK `#billing-phone`
|
||||
TYPE $phone
|
||||
|
||||
# Address
|
||||
CLICK `#billing-address`
|
||||
TYPE $address
|
||||
CLICK `#billing-city`
|
||||
TYPE $city
|
||||
CLICK `#billing-state`
|
||||
TYPE $state
|
||||
CLICK `#billing-zip`
|
||||
TYPE $zip
|
||||
ENDPROC
|
||||
|
||||
PROC select_shipping
|
||||
CLICK `input[value="standard"]`
|
||||
WAIT 1
|
||||
ENDPROC
|
||||
|
||||
# Set all required variables
|
||||
SET search_term = "wireless headphones"
|
||||
SET first_name = "John"
|
||||
SET last_name = "Doe"
|
||||
SET email = "john.doe@example.com"
|
||||
SET phone = "555-0123"
|
||||
SET address = "123 Main Street"
|
||||
SET city = "San Francisco"
|
||||
SET state = "CA"
|
||||
SET zip = "94105"
|
||||
|
||||
# Main workflow starts here
|
||||
GO https://shop.example.com
|
||||
WAIT `.homepage-loaded` 10
|
||||
|
||||
# Step 1: Search and add to cart
|
||||
search_product
|
||||
EVAL `console.log('Found', document.querySelectorAll('.product-item').length, 'products')`
|
||||
add_first_item_to_cart
|
||||
|
||||
# Add a second item
|
||||
CLICK `.product-item:nth-child(2) .add-to-cart`
|
||||
WAIT 2
|
||||
|
||||
# Step 2: Go to checkout
|
||||
go_to_checkout
|
||||
|
||||
# Step 3: Fill customer information
|
||||
fill_customer_info
|
||||
|
||||
# Step 4: Select shipping method
|
||||
select_shipping
|
||||
|
||||
# Step 5: Continue to payment
|
||||
CLICK `button.continue-to-payment`
|
||||
WAIT `.payment-section` 10
|
||||
|
||||
# Log order summary
|
||||
EVAL `
|
||||
const orderTotal = document.querySelector('.order-total')?.textContent;
|
||||
const itemCount = document.querySelectorAll('.order-item').length;
|
||||
console.log('=== Order Summary ===');
|
||||
console.log('Items:', itemCount);
|
||||
console.log('Total:', orderTotal);
|
||||
|
||||
// Get all items
|
||||
const items = Array.from(document.querySelectorAll('.order-item')).map(item => ({
|
||||
name: item.querySelector('.item-name')?.textContent,
|
||||
quantity: item.querySelector('.item-quantity')?.textContent,
|
||||
price: item.querySelector('.item-price')?.textContent
|
||||
}));
|
||||
console.log('Items:', JSON.stringify(items, null, 2));
|
||||
`
|
||||
|
||||
# Note: Stopping here before actual payment submission
|
||||
EVAL `console.log('Workflow completed - stopped before payment submission')`
|
||||
@@ -0,0 +1,8 @@
|
||||
GO https://app.example.com
|
||||
WAIT `.nav-menu` 8
|
||||
CLICK `a[href="/products"]`
|
||||
WAIT 2
|
||||
CLICK `a[href="/about"]`
|
||||
WAIT 2
|
||||
BACK
|
||||
WAIT 1
|
||||
8
docs/examples/c4a_script/script_samples/quick_login.c4a
Normal file
8
docs/examples/c4a_script/script_samples/quick_login.c4a
Normal file
@@ -0,0 +1,8 @@
|
||||
GO https://myapp.com/login
|
||||
WAIT `input#email` 5
|
||||
CLICK `input#email`
|
||||
TYPE "user@example.com"
|
||||
PRESS Tab
|
||||
TYPE "password123"
|
||||
CLICK `button.login-btn`
|
||||
WAIT `.dashboard` 10
|
||||
@@ -0,0 +1,7 @@
|
||||
GO https://responsive.site.com
|
||||
WAIT 2
|
||||
IF (`window.innerWidth < 768`) THEN CLICK `.mobile-menu`
|
||||
IF (`window.innerWidth < 768`) THEN WAIT `.mobile-nav` 3
|
||||
IF (`window.innerWidth >= 768`) THEN CLICK `.desktop-menu li:nth-child(2)`
|
||||
REPEAT (CLICK `.next-slide`, 5)
|
||||
IF (EXISTS `.cookie-banner`) THEN CLICK `.accept-cookies`
|
||||
@@ -0,0 +1,8 @@
|
||||
GO https://news.site.com
|
||||
WAIT `.article-list` 10
|
||||
SCROLL DOWN 500
|
||||
WAIT 1
|
||||
SCROLL DOWN 500
|
||||
WAIT 1
|
||||
CLICK `.article:nth-child(5)`
|
||||
WAIT `.article-content` 5
|
||||
@@ -0,0 +1,7 @@
|
||||
GO https://shop.example.com
|
||||
WAIT `.search-bar` 10
|
||||
CLICK `.search-bar`
|
||||
TYPE "wireless headphones"
|
||||
PRESS Enter
|
||||
WAIT `.results` 5
|
||||
CLICK `.product-card:first-child`
|
||||
19
docs/examples/c4a_script/script_samples/simple_form.c4a
Normal file
19
docs/examples/c4a_script/script_samples/simple_form.c4a
Normal file
@@ -0,0 +1,19 @@
|
||||
# Simple form submission example
|
||||
# This script fills out a contact form and submits it
|
||||
|
||||
GO https://example.com/contact
|
||||
WAIT `form#contact-form` 10
|
||||
|
||||
# Fill out the form fields
|
||||
CLICK `input[name="name"]`
|
||||
TYPE "Alice Smith"
|
||||
PRESS Tab
|
||||
TYPE "alice@example.com"
|
||||
PRESS Tab
|
||||
TYPE "I'd like to learn more about your services"
|
||||
|
||||
# Submit the form
|
||||
CLICK `button[type="submit"]`
|
||||
|
||||
# Wait for success message
|
||||
WAIT "Thank you for your message" 5
|
||||
11
docs/examples/c4a_script/script_samples/smart_form_fill.c4a
Normal file
11
docs/examples/c4a_script/script_samples/smart_form_fill.c4a
Normal file
@@ -0,0 +1,11 @@
|
||||
PROC fill_field
|
||||
TYPE "test@example.com"
|
||||
PRESS Tab
|
||||
ENDPROC
|
||||
|
||||
GO https://forms.example.com
|
||||
WAIT `form` 5
|
||||
IF (EXISTS `input[type="email"]`) THEN CLICK `input[type="email"]`
|
||||
IF (EXISTS `input[type="email"]`) THEN fill_field
|
||||
REPEAT (PRESS Tab, `document.activeElement.type !== 'submit'`)
|
||||
CLICK `button[type="submit"]`
|
||||
Reference in New Issue
Block a user