UNPKG

umbrellamode

Version:

UmbrellaMode shared library

223 lines (161 loc) 6.25 kB
# Umbrella Mode Umbrella Mode is a powerful browser automation and DOM interaction library that provides a clean, type-safe API for programmatically controlling web pages. Built with TypeScript and designed for modern web applications, Umbrella Mode makes it easy to automate user interactions, test web interfaces, and build sophisticated browser-based workflows. ## What is Umbrella Mode? Umbrella Mode is built around the **Actor** class - a comprehensive DOM interaction library that provides methods for clicking, typing, scrolling, and element manipulation. The library uses native DOM APIs and properly handles React components by bypassing synthetic events, making it reliable across different web frameworks and applications. ## Key Features - 🎯 **Type-safe API** - Full TypeScript support with comprehensive type definitions - ⚡ **Framework agnostic** - Works with React, Vue, Angular, and vanilla JavaScript - 🚀 **Native DOM events** - Uses real browser events, not synthetic ones - 📱 **Comprehensive actions** - Click, type, scroll, focus, blur, clear, and element manipulation - 🔄 **Async/await support** - Modern JavaScript patterns for clean code - 🎭 **Human-like simulation** - Optional typing simulation for realistic user behavior - 📏 **Viewport awareness** - Built-in viewport detection and scroll management - ⏱️ **Element waiting** - Wait for elements to appear with configurable timeouts - 🎯 **Precise scrolling** - Multiple scroll methods for different use cases ## Installation ```bash # Install the director package pnpm add umbrellamode # Or if using npm npm install umbrellamode # Or if using yarn yarn add umbrellamode ``` ## Get Started ### Basic Usage The Actor class is the core of Umbrella Mode. It provides a comprehensive set of methods for interacting with web pages: ```typescript import { Actor } from "umbrellamode"; // Create an actor instance const actor = new Actor(); // Basic interactions await actor.click({ selector: '#submit-button' }); await actor.type({ selector: '#username', text: 'john.doe', simulateTyping: false }); await actor.clear({ selector: '#search-input' }); ``` ### Clicking Elements ```typescript // Click a button await actor.click({ selector: '#submit-button' }); // Click using data attributes await actor.click({ selector: '[data-testid="save-btn"]' }); // Click a link await actor.click({ selector: 'a[href="/dashboard"]' }); ``` ### Typing Text ```typescript // Fast typing (recommended for most cases) await actor.type({ selector: '#username', text: 'john.doe@example.com', simulateTyping: false }); // Simulated typing (slower, more human-like) await actor.type({ selector: '#message', text: 'Hello world!', simulateTyping: true }); // Convenience method for fast typing await actor.typeFast({ selector: '#password', text: 'secret123' }); ``` ### Scrolling ```typescript // Scroll to specific coordinates await actor.scrollTo({ x: 0, y: 500 }); // Scroll to an element await actor.scrollToElement({ selector: '#section-3' }); // Scroll by relative amounts await actor.scrollBy({ x: 0, y: 200 }); // Scroll page by viewport height await actor.scrollPageDown({}); await actor.scrollPageUp({}); // Scroll to top/bottom await actor.scrollToTop(); await actor.scrollToBottom(); ``` ### Element State and Visibility ```typescript // Wait for an element to appear await actor.waitForElement({ selector: '.loading-spinner' }); // Check if element is visible const isVisible = actor.isElementInViewport({ selector: '#hero-section' }); // Get current scroll position const position = actor.getScrollPosition({}); console.log(`Scrolled to: ${position.x}, ${position.y}`); ``` ### Focus Management ```typescript // Focus an element await actor.focus({ selector: '#email-input' }); // Remove focus (blur) await actor.blur({ selector: '#search-input' }); ``` ## Advanced Usage ### Working with Forms ```typescript // Fill out a complete form await actor.typeFast({ selector: '#firstName', text: 'John' }); await actor.typeFast({ selector: '#lastName', text: 'Doe' }); await actor.typeFast({ selector: '#email', text: 'john@example.com' }); await actor.click({ selector: '#submit' }); // Wait for success message await actor.waitForElement({ selector: '.success-message' }); ``` ### Dynamic Content Handling ```typescript // Wait for dynamically loaded content await actor.waitForElement({ selector: '[data-testid="dynamic-content"]', timeout: 10000 // 10 seconds }); // Check if content is visible before interacting if (actor.isElementInViewport({ selector: '.important-section' })) { await actor.click({ selector: '.cta-button' }); } ``` ### Scroll-based Interactions ```typescript // Scroll to find an element, then interact await actor.scrollToElement({ selector: '#hidden-section' }); await actor.click({ selector: '#action-button' }); // Scroll through a list for (let i = 0; i < 5; i++) { await actor.scrollPageDown({}); await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second } ``` ## Error Handling Umbrella Mode provides clear error messages for common issues: ```typescript try { await actor.click({ selector: '#non-existent-button' }); } catch (error) { console.error('Element not found:', error.message); // Output: "Element not found with selector: #non-existent-button" } ``` ## Best Practices 1. **Use specific selectors**: Prefer `data-testid` attributes over CSS classes 2. **Handle async operations**: Always use `await` with Actor methods 3. **Wait for elements**: Use `waitForElement` for dynamically loaded content 4. **Check visibility**: Use `isElementInViewport` before interacting with elements 5. **Use fast typing**: Set `simulateTyping: false` for better performance unless human-like behavior is needed ## Monorepo Structure This project uses a monorepo structure with the following packages: - `packages/director/` - Core Umbrella Mode library (Actor class) - `packages/ui/` - Shared UI components (shadcn/ui) - `apps/web/` - Example web application ## Development ```bash # Install dependencies pnpm install # Start development server pnpm dev # Build all packages pnpm build # Run linting pnpm lint ``` ## License Apache-2.0