cli/docs/mcp/angular-testing.md
Vi 27f8632867
feat: BugSETI app, WebSocket hub, browser automation, and MCP tools (#336)
* feat: add security logging and fix framework regressions

This commit implements comprehensive security event logging and resolves critical regressions in the core framework.

Security Logging:
- Enhanced `pkg/log` with a `Security` level and helper.
- Added `log.Username()` to consistently identify the executing user.
- Instrumented GitHub CLI auth, Agentic configuration, filesystem sandbox, MCP handlers, and MCP TCP transport with security logs.
- Added `SecurityStyle` to the CLI for consistent visual representation of security events.

UniFi Security (CodeQL):
- Refactored `pkg/unifi` to remove hardcoded `InsecureSkipVerify`, resolving a high-severity alert.
- Added a `--verify-tls` flag and configuration option to control TLS verification.
- Updated command handlers to support the new verification parameter.

Framework Fixes:
- Restored original signatures for `MustServiceFor`, `Config()`, and `Display()` in `pkg/framework/core`, which had been corrupted during a merge.
- Fixed `pkg/framework/framework.go` and `pkg/framework/core/runtime_pkg.go` to match the restored signatures.
- These fixes resolve project-wide compilation errors caused by the signature mismatches.

I encountered significant blockers due to a corrupted state of the `dev` branch after a merge, which introduced breaking changes in the core framework's DI system. I had to manually reconcile these signatures with the expected usage across the codebase to restore build stability.

* feat(mcp): add RAG tools (query, ingest, collections)

Add vector database tools to the MCP server for RAG operations:
- rag_query: Search for relevant documentation using semantic similarity
- rag_ingest: Ingest files or directories into the vector database
- rag_collections: List available collections

Uses existing internal/cmd/rag exports (QueryDocs, IngestDirectory, IngestFile)
and pkg/rag for Qdrant client access. Default collection is "hostuk-docs"
with topK=5 for queries.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(mcp): add metrics tools (record, query)

Add MCP tools for recording and querying AI/security metrics events.
The metrics_record tool writes events to daily JSONL files, and the
metrics_query tool provides aggregated statistics by type, repo, and agent.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add 'core mcp serve' command

Add CLI command to start the MCP server for AI tool integration.

- Create internal/cmd/mcpcmd package with serve subcommand
- Support --workspace flag for directory restriction
- Handle SIGINT/SIGTERM for clean shutdown
- Register in full.go build variant

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ws): add WebSocket hub package for real-time streaming

Add pkg/ws package implementing a hub pattern for WebSocket connections:
- Hub manages client connections, broadcasts, and channel subscriptions
- Client struct represents connected WebSocket clients
- Message types: process_output, process_status, event, error, ping/pong
- Channel-based subscription system (subscribe/unsubscribe)
- SendProcessOutput and SendProcessStatus for process streaming integration
- Full test coverage including concurrency tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(mcp): add process management and WebSocket MCP tools

Add MCP tools for process management:
- process_start: Start a new external process
- process_stop: Gracefully stop a running process
- process_kill: Force kill a process
- process_list: List all managed processes
- process_output: Get captured process output
- process_input: Send input to process stdin

Add MCP tools for WebSocket:
- ws_start: Start WebSocket server for real-time streaming
- ws_info: Get hub statistics (clients, channels)

Update Service struct with optional process.Service and ws.Hub fields,
new WithProcessService and WithWSHub options, getter methods, and
Shutdown method for cleanup.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(webview): add browser automation package via Chrome DevTools Protocol

Add pkg/webview package for browser automation:
- webview.go: Main interface with Connect, Navigate, Click, Type, QuerySelector, Screenshot, Evaluate
- cdp.go: Chrome DevTools Protocol WebSocket client implementation
- actions.go: DOM action types (Click, Type, Hover, Scroll, etc.) and ActionSequence builder
- console.go: Console message capture and filtering with ConsoleWatcher and ExceptionWatcher
- angular.go: Angular-specific helpers for router navigation, component access, and Zone.js stability

Add MCP tools for webview:
- webview_connect/disconnect: Connection management
- webview_navigate: Page navigation
- webview_click/type/query/wait: DOM interaction
- webview_console: Console output capture
- webview_eval: JavaScript execution
- webview_screenshot: Screenshot capture

Add documentation:
- docs/mcp/angular-testing.md: Guide for Angular application testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: document new packages and BugSETI application

- Update CLAUDE.md with documentation for:
  - pkg/ws (WebSocket hub for real-time streaming)
  - pkg/webview (Browser automation via CDP)
  - pkg/mcp (MCP server tools: process, ws, webview)
  - BugSETI application overview
- Add comprehensive README for BugSETI with:
  - Installation and configuration guide
  - Usage workflow documentation
  - Architecture overview
  - Contributing guidelines

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(bugseti): add BugSETI system tray app with auto-update

BugSETI - Distributed Bug Fixing like SETI@home but for code

Features:
- System tray app with Wails v3
- GitHub issue fetching with label filters
- Issue queue with priority management
- AI context seeding via seed-agent-developer skill
- Automated PR submission flow
- Stats tracking and leaderboard
- Cross-platform notifications
- Self-updating with stable/beta/nightly channels

Includes:
- cmd/bugseti: Main application with Angular frontend
- internal/bugseti: Core services (fetcher, queue, seeder, submit, config, stats, notify)
- internal/bugseti/updater: Auto-update system (checker, downloader, installer)
- .github/workflows/bugseti-release.yml: CI/CD for all platforms

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: resolve import cycle and code duplication

- Remove pkg/log import from pkg/io/local to break import cycle
  (pkg/log/rotation.go imports pkg/io, creating circular dependency)
- Use stderr logging for security events in sandbox escape detection
- Remove unused sync/atomic import from core.go
- Fix duplicate LogSecurity function declarations in cli/log.go
- Update workspace/service.go Crypt() call to match interface

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: update tests for new function signatures and format code

- Update core_test.go: Config(), Display() now panic instead of returning error
- Update runtime_pkg_test.go: sr.Config() now panics instead of returning error
- Update MustServiceFor tests to use assert.Panics
- Format BugSETI, MCP tools, and webview packages with gofmt

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Snider <631881+Snider@users.noreply.github.com>
Co-authored-by: Claude <developers@lethean.io>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:22:05 +00:00

9.3 KiB

Angular Testing with Webview MCP Tools

This guide explains how to use the webview MCP tools to automate testing of Angular applications via Chrome DevTools Protocol (CDP).

Prerequisites

  1. Chrome/Chromium Browser: Installed and accessible
  2. Remote Debugging Port: Chrome must be started with remote debugging enabled

Starting Chrome with Remote Debugging

# Linux
google-chrome --remote-debugging-port=9222

# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222

# Headless mode (no visible window)
google-chrome --headless --remote-debugging-port=9222

Available MCP Tools

Connection Management

webview_connect

Connect to Chrome DevTools.

{
  "tool": "webview_connect",
  "arguments": {
    "debug_url": "http://localhost:9222",
    "timeout": 30
  }
}

webview_disconnect

Disconnect from Chrome DevTools.

{
  "tool": "webview_disconnect",
  "arguments": {}
}

Navigation

webview_navigate

Navigate to a URL.

{
  "tool": "webview_navigate",
  "arguments": {
    "url": "http://localhost:4200"
  }
}

DOM Interaction

webview_click

Click an element by CSS selector.

{
  "tool": "webview_click",
  "arguments": {
    "selector": "#login-button"
  }
}

webview_type

Type text into an element.

{
  "tool": "webview_type",
  "arguments": {
    "selector": "#email-input",
    "text": "user@example.com"
  }
}

webview_query

Query DOM elements.

{
  "tool": "webview_query",
  "arguments": {
    "selector": ".error-message",
    "all": true
  }
}

webview_wait

Wait for an element to appear.

{
  "tool": "webview_wait",
  "arguments": {
    "selector": ".loading-spinner",
    "timeout": 10
  }
}

JavaScript Evaluation

webview_eval

Execute JavaScript in the browser context.

{
  "tool": "webview_eval",
  "arguments": {
    "script": "document.title"
  }
}

Console & Debugging

webview_console

Get browser console output.

{
  "tool": "webview_console",
  "arguments": {
    "clear": false
  }
}

webview_screenshot

Capture a screenshot.

{
  "tool": "webview_screenshot",
  "arguments": {
    "format": "png"
  }
}

Angular-Specific Testing Patterns

1. Waiting for Angular Zone Stability

Before interacting with Angular components, wait for Zone.js to become stable:

{
  "tool": "webview_eval",
  "arguments": {
    "script": "(function() { const roots = window.getAllAngularRootElements(); if (!roots.length) return true; const injector = window.ng.probe(roots[0]).injector; const zone = injector.get('NgZone'); return zone.isStable; })()"
  }
}

2. Navigating with Angular Router

Use the Angular Router for client-side navigation:

{
  "tool": "webview_eval",
  "arguments": {
    "script": "(function() { const roots = window.getAllAngularRootElements(); const injector = window.ng.probe(roots[0]).injector; const router = injector.get('Router'); router.navigateByUrl('/dashboard'); return true; })()"
  }
}

3. Accessing Component Properties

Read or modify component state:

{
  "tool": "webview_eval",
  "arguments": {
    "script": "(function() { const el = document.querySelector('app-user-profile'); const component = window.ng.probe(el).componentInstance; return component.user; })()"
  }
}

4. Triggering Change Detection

Force Angular to update the view:

{
  "tool": "webview_eval",
  "arguments": {
    "script": "(function() { const roots = window.getAllAngularRootElements(); const injector = window.ng.probe(roots[0]).injector; const appRef = injector.get('ApplicationRef'); appRef.tick(); return true; })()"
  }
}

5. Testing Form Validation

Check Angular form state:

{
  "tool": "webview_eval",
  "arguments": {
    "script": "(function() { const form = document.querySelector('form'); const component = window.ng.probe(form).componentInstance; return { valid: component.form.valid, errors: component.form.errors }; })()"
  }
}

Complete Test Flow Example

Here's a complete example testing an Angular login flow:

Step 1: Connect to Chrome

{"tool": "webview_connect", "arguments": {"debug_url": "http://localhost:9222"}}

Step 2: Navigate to the Application

{"tool": "webview_navigate", "arguments": {"url": "http://localhost:4200/login"}}

Step 3: Wait for Angular to Load

{"tool": "webview_wait", "arguments": {"selector": "app-login"}}

Step 4: Fill in Login Form

{"tool": "webview_type", "arguments": {"selector": "#email", "text": "test@example.com"}}
{"tool": "webview_type", "arguments": {"selector": "#password", "text": "password123"}}

Step 5: Submit the Form

{"tool": "webview_click", "arguments": {"selector": "button[type='submit']"}}

Step 6: Wait for Navigation

{"tool": "webview_wait", "arguments": {"selector": "app-dashboard", "timeout": 10}}

Step 7: Verify Success

{"tool": "webview_eval", "arguments": {"script": "window.location.pathname === '/dashboard'"}}

Step 8: Check Console for Errors

{"tool": "webview_console", "arguments": {"clear": true}}

Step 9: Disconnect

{"tool": "webview_disconnect", "arguments": {}}

Debugging Tips

1. Check for JavaScript Errors

Always check the console output after operations:

{"tool": "webview_console", "arguments": {}}

2. Take Screenshots on Failure

Capture the current state when something unexpected happens:

{"tool": "webview_screenshot", "arguments": {"format": "png"}}

3. Inspect Element State

Query elements to understand their current state:

{"tool": "webview_query", "arguments": {"selector": ".my-component", "all": false}}

4. Get Page Source

Retrieve the current HTML for debugging:

{"tool": "webview_eval", "arguments": {"script": "document.documentElement.outerHTML"}}

Common Issues

Element Not Found

If webview_click or webview_type fails with "element not found":

  1. Check the selector is correct
  2. Wait for the element to appear first
  3. Verify the element is visible (not hidden)

Angular Not Detected

If Angular-specific scripts fail:

  1. Ensure the Angular app has loaded completely
  2. Check that you're using Angular 2+ (not AngularJS)
  3. Verify the element has an Angular component attached

Timeout Errors

If operations timeout:

  1. Increase the timeout value
  2. Check for loading spinners or blocking operations
  3. Verify the network is working correctly

Best Practices

  1. Always wait for elements before interacting with them
  2. Check console for errors after each major step
  3. Use explicit selectors like IDs or data attributes
  4. Clear console at the start of each test
  5. Disconnect when done to free resources
  6. Take screenshots at key checkpoints
  7. Handle async operations by waiting for stability

Go API Usage

For direct Go integration, use the pkg/webview package:

package main

import (
    "log"
    "time"

    "github.com/host-uk/core/pkg/webview"
)

func main() {
    // Connect to Chrome
    wv, err := webview.New(
        webview.WithDebugURL("http://localhost:9222"),
        webview.WithTimeout(30*time.Second),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer wv.Close()

    // Navigate
    if err := wv.Navigate("http://localhost:4200"); err != nil {
        log.Fatal(err)
    }

    // Wait for element
    if err := wv.WaitForSelector("app-root"); err != nil {
        log.Fatal(err)
    }

    // Click button
    if err := wv.Click("#login-button"); err != nil {
        log.Fatal(err)
    }

    // Type text
    if err := wv.Type("#email", "test@example.com"); err != nil {
        log.Fatal(err)
    }

    // Get console output
    messages := wv.GetConsole()
    for _, msg := range messages {
        log.Printf("[%s] %s", msg.Type, msg.Text)
    }

    // Take screenshot
    data, err := wv.Screenshot()
    if err != nil {
        log.Fatal(err)
    }
    // Save data to file...
}

Using Angular Helper

For Angular-specific operations:

package main

import (
    "log"
    "time"

    "github.com/host-uk/core/pkg/webview"
)

func main() {
    wv, err := webview.New(webview.WithDebugURL("http://localhost:9222"))
    if err != nil {
        log.Fatal(err)
    }
    defer wv.Close()

    // Create Angular helper
    angular := webview.NewAngularHelper(wv)

    // Navigate using Angular Router
    if err := angular.NavigateByRouter("/dashboard"); err != nil {
        log.Fatal(err)
    }

    // Wait for Angular to stabilize
    if err := angular.WaitForAngular(); err != nil {
        log.Fatal(err)
    }

    // Get component property
    value, err := angular.GetComponentProperty("app-user-profile", "user")
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("User: %v", value)

    // Call component method
    result, err := angular.CallComponentMethod("app-counter", "increment", 5)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Result: %v", result)
}

See Also