mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-20 02:15:12 +00:00
Add a new cookbook recipe that generates WCAG accessibility reports using the Playwright MCP server. Includes streaming output, structured report formatting, and optional Playwright test generation. - C#, TypeScript, Python, and Go implementations - Markdown documentation for each language - Updated cookbook.yml, copilot-sdk README, and package.json
214 lines
6.9 KiB
Go
214 lines
6.9 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"context"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
"strings"
|
||
|
||
copilot "github.com/github/copilot-sdk/go"
|
||
)
|
||
|
||
func main() {
|
||
ctx := context.Background()
|
||
reader := bufio.NewReader(os.Stdin)
|
||
|
||
fmt.Println("=== Accessibility Report Generator ===")
|
||
fmt.Println()
|
||
|
||
fmt.Print("Enter URL to analyze: ")
|
||
url, _ := reader.ReadString('\n')
|
||
url = strings.TrimSpace(url)
|
||
|
||
if url == "" {
|
||
fmt.Println("No URL provided. Exiting.")
|
||
return
|
||
}
|
||
|
||
// Ensure URL has a scheme
|
||
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
||
url = "https://" + url
|
||
}
|
||
|
||
fmt.Printf("\nAnalyzing: %s\n", url)
|
||
fmt.Println("Please wait...\n")
|
||
|
||
// Create Copilot client with Playwright MCP server
|
||
client := copilot.NewClient(nil)
|
||
|
||
if err := client.Start(ctx); err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer client.Stop()
|
||
|
||
streaming := true
|
||
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
|
||
Model: "claude-opus-4.6",
|
||
Streaming: &streaming,
|
||
McpServers: map[string]interface{}{
|
||
"playwright": map[string]interface{}{
|
||
"type": "local",
|
||
"command": "npx",
|
||
"args": []string{"@playwright/mcp@latest"},
|
||
"tools": []string{"*"},
|
||
},
|
||
},
|
||
})
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer session.Destroy()
|
||
|
||
// Set up streaming event handling
|
||
done := make(chan struct{}, 1)
|
||
|
||
session.On(func(event copilot.SessionEvent) {
|
||
switch event.Type {
|
||
case "assistant.message.delta":
|
||
if event.Data.DeltaContent != nil {
|
||
fmt.Print(*event.Data.DeltaContent)
|
||
}
|
||
case "session.idle":
|
||
select {
|
||
case done <- struct{}{}:
|
||
default:
|
||
}
|
||
case "session.error":
|
||
if event.Data.Message != nil {
|
||
fmt.Printf("\nError: %s\n", *event.Data.Message)
|
||
}
|
||
select {
|
||
case done <- struct{}{}:
|
||
default:
|
||
}
|
||
}
|
||
})
|
||
|
||
prompt := fmt.Sprintf(`
|
||
Use the Playwright MCP server to analyze the accessibility of this webpage: %s
|
||
|
||
Please:
|
||
1. Navigate to the URL using playwright-browser_navigate
|
||
2. Take an accessibility snapshot using playwright-browser_snapshot
|
||
3. Analyze the snapshot and provide a detailed accessibility report
|
||
|
||
Format the report EXACTLY like this structure with emoji indicators:
|
||
|
||
📊 Accessibility Report: [Page Title] (domain.com)
|
||
|
||
✅ What's Working Well
|
||
| Category | Status | Details |
|
||
|----------|--------|---------|
|
||
| Language | ✅ Pass | lang="en-US" properly set |
|
||
| Page Title | ✅ Pass | "[Title]" is descriptive |
|
||
| Heading Hierarchy | ✅ Pass | Single H1, proper H2/H3 structure |
|
||
| Images | ✅ Pass | All X images have alt text |
|
||
| Viewport | ✅ Pass | Allows pinch-zoom (no user-scalable=no) |
|
||
| Links | ✅ Pass | No ambiguous "click here" links |
|
||
| Reduced Motion | ✅ Pass | Supports prefers-reduced-motion |
|
||
| Autoplay Media | ✅ Pass | No autoplay audio/video |
|
||
|
||
⚠️ Issues Found
|
||
| Severity | Issue | WCAG Criterion | Recommendation |
|
||
|----------|-------|----------------|----------------|
|
||
| 🔴 High | No <main> landmark | 1.3.1, 2.4.1 | Wrap main content in <main> element |
|
||
| 🔴 High | No skip navigation link | 2.4.1 | Add "Skip to content" link at top |
|
||
| 🟡 Medium | Focus outlines disabled | 2.4.7 | Default outline is none - ensure visible :focus styles exist |
|
||
| 🟡 Medium | Small touch targets | 2.5.8 | Navigation links are 37px tall (below 44px minimum) |
|
||
|
||
📋 Stats Summary
|
||
- Total Links: X
|
||
- Total Headings: X (1× H1, proper hierarchy)
|
||
- Focusable Elements: X
|
||
- Landmarks Found: banner ✅, navigation ✅, main ❌, footer ✅
|
||
|
||
⚙️ Priority Recommendations
|
||
- Add <main> landmark - Wrap page content in <main role="main"> for screen reader navigation
|
||
- Add skip link - Hidden link at start: <a href="#main-content" class="skip-link">Skip to content</a>
|
||
- Increase touch targets - Add padding to nav links and tags to meet 44×44px minimum
|
||
- Verify focus styles - Test keyboard navigation; add visible :focus or :focus-visible outlines
|
||
|
||
Use ✅ for pass, 🔴 for high severity issues, 🟡 for medium severity, ❌ for missing items.
|
||
Include actual findings from the page analysis - don't just copy the example.
|
||
`, url)
|
||
|
||
if _, err := session.Send(ctx, copilot.MessageOptions{Prompt: prompt}); err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
<-done
|
||
|
||
fmt.Println("\n\n=== Report Complete ===\n")
|
||
|
||
// Prompt user for test generation
|
||
fmt.Print("Would you like to generate Playwright accessibility tests? (y/n): ")
|
||
generateTests, _ := reader.ReadString('\n')
|
||
generateTests = strings.TrimSpace(strings.ToLower(generateTests))
|
||
|
||
if generateTests == "y" || generateTests == "yes" {
|
||
detectLanguagePrompt := `
|
||
Analyze the current working directory to detect the primary programming language used in this project.
|
||
Look for project files like package.json, *.csproj, pom.xml, requirements.txt, go.mod, etc.
|
||
|
||
Respond with ONLY the detected language name (e.g., "TypeScript", "JavaScript", "C#", "Python", "Java")
|
||
and a brief explanation of why you detected it.
|
||
If no project is detected, suggest "TypeScript" as the default for Playwright tests.
|
||
`
|
||
|
||
fmt.Println("\nDetecting project language...\n")
|
||
// Drain the previous done signal
|
||
select {
|
||
case <-done:
|
||
default:
|
||
}
|
||
if _, err := session.Send(ctx, copilot.MessageOptions{Prompt: detectLanguagePrompt}); err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
<-done
|
||
|
||
fmt.Print("\n\nConfirm language for tests (or enter a different one): ")
|
||
language, _ := reader.ReadString('\n')
|
||
language = strings.TrimSpace(language)
|
||
if language == "" {
|
||
language = "TypeScript"
|
||
}
|
||
|
||
testGenerationPrompt := fmt.Sprintf(`
|
||
Based on the accessibility report you just generated for %s, create Playwright accessibility tests in %s.
|
||
|
||
The tests should:
|
||
1. Verify all the accessibility checks from the report
|
||
2. Test for the issues that were found (to ensure they get fixed)
|
||
3. Include tests for:
|
||
- Page has proper lang attribute
|
||
- Page has descriptive title
|
||
- Heading hierarchy is correct (single H1, proper nesting)
|
||
- All images have alt text
|
||
- No autoplay media
|
||
- Landmark regions exist (banner, nav, main, footer)
|
||
- Skip navigation link exists and works
|
||
- Focus indicators are visible
|
||
- Touch targets meet minimum size requirements
|
||
4. Use Playwright's accessibility testing features
|
||
5. Include helpful comments explaining each test
|
||
|
||
Output the complete test file that can be saved and run.
|
||
Use the Playwright MCP server tools if you need to verify any page details.
|
||
`, url, language)
|
||
|
||
fmt.Println("\nGenerating accessibility tests...\n")
|
||
// Drain the previous done signal
|
||
select {
|
||
case <-done:
|
||
default:
|
||
}
|
||
if _, err := session.Send(ctx, copilot.MessageOptions{Prompt: testGenerationPrompt}); err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
<-done
|
||
|
||
fmt.Println("\n\n=== Tests Generated ===")
|
||
}
|
||
}
|