bump
This commit is contained in:
369
client/client.go
369
client/client.go
@@ -3448,7 +3448,136 @@ type ContrastCheckElement struct {
|
||||
PassesAAA bool `json:"passes_aaa"`
|
||||
RequiredAA float64 `json:"required_aa"`
|
||||
RequiredAAA float64 `json:"required_aaa"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// PageAccessibilityReport represents a comprehensive accessibility assessment of a single page
|
||||
type PageAccessibilityReport struct {
|
||||
URL string `json:"url"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
ComplianceStatus string `json:"compliance_status"` // COMPLIANT, NON_COMPLIANT, PARTIAL
|
||||
OverallScore int `json:"overall_score"` // 0-100
|
||||
LegalRisk string `json:"legal_risk"` // LOW, MEDIUM, HIGH, CRITICAL
|
||||
CriticalIssues []AccessibilityIssue `json:"critical_issues"`
|
||||
SeriousIssues []AccessibilityIssue `json:"serious_issues"`
|
||||
HighIssues []AccessibilityIssue `json:"high_issues"`
|
||||
MediumIssues []AccessibilityIssue `json:"medium_issues"`
|
||||
SummaryByWCAG map[string]WCAGSummary `json:"summary_by_wcag"`
|
||||
ContrastSummary ContrastSummary `json:"contrast_summary"`
|
||||
KeyboardSummary KeyboardSummary `json:"keyboard_summary"`
|
||||
ARIASummary ARIASummary `json:"aria_summary"`
|
||||
FormSummary *FormSummary `json:"form_summary,omitempty"`
|
||||
Screenshots map[string]string `json:"screenshots,omitempty"`
|
||||
EstimatedHours int `json:"estimated_remediation_hours"`
|
||||
}
|
||||
|
||||
// AccessibilityIssue represents a single accessibility issue
|
||||
type AccessibilityIssue struct {
|
||||
WCAG string `json:"wcag"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Impact string `json:"impact"`
|
||||
Count int `json:"count"`
|
||||
Examples []string `json:"examples,omitempty"`
|
||||
Remediation string `json:"remediation"`
|
||||
}
|
||||
|
||||
// WCAGSummary represents violations grouped by WCAG principle
|
||||
type WCAGSummary struct {
|
||||
Violations int `json:"violations"`
|
||||
Severity string `json:"severity"`
|
||||
}
|
||||
|
||||
// ContrastSummary represents a summary of contrast check results
|
||||
type ContrastSummary struct {
|
||||
TotalChecked int `json:"total_checked"`
|
||||
Passed int `json:"passed"`
|
||||
Failed int `json:"failed"`
|
||||
PassRate string `json:"pass_rate"`
|
||||
CriticalFailures []ContrastFailure `json:"critical_failures"`
|
||||
FailurePatterns map[string]FailurePattern `json:"failure_patterns"`
|
||||
}
|
||||
|
||||
// ContrastFailure represents a critical contrast failure
|
||||
type ContrastFailure struct {
|
||||
Selector string `json:"selector"`
|
||||
Text string `json:"text"`
|
||||
Ratio float64 `json:"ratio"`
|
||||
Required float64 `json:"required"`
|
||||
FgColor string `json:"fg_color"`
|
||||
BgColor string `json:"bg_color"`
|
||||
Fix string `json:"fix"`
|
||||
}
|
||||
|
||||
// FailurePattern represents a pattern of similar failures
|
||||
type FailurePattern struct {
|
||||
Count int `json:"count"`
|
||||
Ratio float64 `json:"ratio"`
|
||||
Fix string `json:"fix"`
|
||||
}
|
||||
|
||||
// KeyboardSummary represents a summary of keyboard navigation results
|
||||
type KeyboardSummary struct {
|
||||
TotalInteractive int `json:"total_interactive"`
|
||||
Focusable int `json:"focusable"`
|
||||
MissingFocusIndicator int `json:"missing_focus_indicator"`
|
||||
KeyboardTraps int `json:"keyboard_traps"`
|
||||
TabOrderIssues int `json:"tab_order_issues"`
|
||||
Issues []KeyboardIssue `json:"issues"`
|
||||
}
|
||||
|
||||
// KeyboardIssue represents a keyboard accessibility issue
|
||||
type KeyboardIssue struct {
|
||||
Type string `json:"type"`
|
||||
Severity string `json:"severity"`
|
||||
Count int `json:"count"`
|
||||
Description string `json:"description"`
|
||||
Fix string `json:"fix"`
|
||||
Examples []string `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// ARIASummary represents a summary of ARIA validation results
|
||||
type ARIASummary struct {
|
||||
TotalViolations int `json:"total_violations"`
|
||||
MissingNames int `json:"missing_names"`
|
||||
InvalidAttributes int `json:"invalid_attributes"`
|
||||
HiddenInteractive int `json:"hidden_interactive"`
|
||||
Issues []ARIAIssue `json:"issues"`
|
||||
}
|
||||
|
||||
// ARIAIssue represents an ARIA accessibility issue
|
||||
type ARIAIssue struct {
|
||||
Type string `json:"type"`
|
||||
Severity string `json:"severity"`
|
||||
Count int `json:"count"`
|
||||
Description string `json:"description"`
|
||||
Fix string `json:"fix"`
|
||||
Examples []string `json:"examples,omitempty"`
|
||||
}
|
||||
|
||||
// FormSummary represents a summary of form accessibility
|
||||
type FormSummary struct {
|
||||
FormsFound int `json:"forms_found"`
|
||||
Forms []FormAudit `json:"forms"`
|
||||
}
|
||||
|
||||
// FormAudit represents accessibility audit of a single form
|
||||
type FormAudit struct {
|
||||
ID string `json:"id"`
|
||||
Fields int `json:"fields"`
|
||||
Issues []FormIssue `json:"issues"`
|
||||
ARIACompliance string `json:"aria_compliance"`
|
||||
KeyboardAccessible bool `json:"keyboard_accessible"`
|
||||
RequiredMarked bool `json:"required_fields_marked"`
|
||||
}
|
||||
|
||||
// FormIssue represents a form accessibility issue
|
||||
type FormIssue struct {
|
||||
Type string `json:"type"`
|
||||
Severity string `json:"severity"`
|
||||
Count int `json:"count,omitempty"`
|
||||
Description string `json:"description"`
|
||||
Fix string `json:"fix"`
|
||||
Ratio float64 `json:"ratio,omitempty"`
|
||||
}
|
||||
|
||||
// CheckContrast checks color contrast for text elements on the page
|
||||
@@ -4260,3 +4389,241 @@ func (c *Client) TestReflow(tabID string, widths []int, timeout int) (*ReflowTes
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetPageAccessibilityReport performs a comprehensive accessibility assessment of a page
|
||||
// and returns a summarized report with actionable findings
|
||||
// If tabID is empty, the current tab will be used
|
||||
// tests is an array of test types to run (e.g., ["wcag", "contrast", "keyboard", "forms"])
|
||||
// If empty, runs all tests
|
||||
// standard is the WCAG standard to test against (e.g., "WCAG21AA")
|
||||
// includeScreenshots determines whether to capture screenshots of violations
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetPageAccessibilityReport(tabID string, tests []string, standard string, includeScreenshots bool, timeout int) (*PageAccessibilityReport, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Include tests if provided
|
||||
if len(tests) > 0 {
|
||||
params["tests"] = strings.Join(tests, ",")
|
||||
} else {
|
||||
params["tests"] = "all"
|
||||
}
|
||||
|
||||
// Include standard if provided
|
||||
if standard != "" {
|
||||
params["standard"] = standard
|
||||
} else {
|
||||
params["standard"] = "WCAG21AA"
|
||||
}
|
||||
|
||||
// Include screenshot flag
|
||||
if includeScreenshots {
|
||||
params["include_screenshots"] = "true"
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("page-accessibility-report", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get page accessibility report: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result PageAccessibilityReport
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal page accessibility report: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// ContrastAuditResult represents a smart contrast audit with prioritized failures
|
||||
type ContrastAuditResult struct {
|
||||
TotalChecked int `json:"total_checked"`
|
||||
Passed int `json:"passed"`
|
||||
Failed int `json:"failed"`
|
||||
PassRate string `json:"pass_rate"`
|
||||
CriticalFailures []ContrastFailure `json:"critical_failures"`
|
||||
FailurePatterns map[string]FailurePattern `json:"failure_patterns"`
|
||||
}
|
||||
|
||||
// GetContrastAudit performs a smart contrast check with prioritized failures
|
||||
// If tabID is empty, the current tab will be used
|
||||
// prioritySelectors is an array of CSS selectors to prioritize (e.g., ["button", "a", "nav"])
|
||||
// threshold is the WCAG level to test against ("AA" or "AAA")
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetContrastAudit(tabID string, prioritySelectors []string, threshold string, timeout int) (*ContrastAuditResult, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Include priority selectors if provided
|
||||
if len(prioritySelectors) > 0 {
|
||||
params["priority_selectors"] = strings.Join(prioritySelectors, ",")
|
||||
}
|
||||
|
||||
// Include threshold if provided
|
||||
if threshold != "" {
|
||||
params["threshold"] = threshold
|
||||
} else {
|
||||
params["threshold"] = "AA"
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("contrast-audit", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get contrast audit: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result ContrastAuditResult
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal contrast audit: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// KeyboardAuditResult represents a keyboard navigation audit
|
||||
type KeyboardAuditResult struct {
|
||||
Status string `json:"status"` // PASS, FAIL, PARTIAL
|
||||
TotalInteractive int `json:"total_interactive"`
|
||||
Focusable int `json:"focusable"`
|
||||
Issues []KeyboardIssue `json:"issues"`
|
||||
TabOrderIssues []string `json:"tab_order_issues"`
|
||||
Recommendation string `json:"recommendation"`
|
||||
}
|
||||
|
||||
// GetKeyboardAudit performs a keyboard navigation assessment
|
||||
// If tabID is empty, the current tab will be used
|
||||
// checkFocusIndicators determines whether to check for visible focus indicators
|
||||
// checkTabOrder determines whether to check tab order
|
||||
// checkKeyboardTraps determines whether to check for keyboard traps
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetKeyboardAudit(tabID string, checkFocusIndicators, checkTabOrder, checkKeyboardTraps bool, timeout int) (*KeyboardAuditResult, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Include check flags
|
||||
if checkFocusIndicators {
|
||||
params["check_focus_indicators"] = "true"
|
||||
}
|
||||
if checkTabOrder {
|
||||
params["check_tab_order"] = "true"
|
||||
}
|
||||
if checkKeyboardTraps {
|
||||
params["check_keyboard_traps"] = "true"
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("keyboard-audit", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get keyboard audit: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result KeyboardAuditResult
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal keyboard audit: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetFormAccessibilityAudit performs a comprehensive form accessibility check
|
||||
// If tabID is empty, the current tab will be used
|
||||
// formSelector is an optional CSS selector for a specific form (defaults to all forms)
|
||||
// timeout is in seconds, 0 means no timeout
|
||||
func (c *Client) GetFormAccessibilityAudit(tabID, formSelector string, timeout int) (*FormSummary, error) {
|
||||
params := map[string]string{}
|
||||
|
||||
// Only include tab ID if it's provided
|
||||
if tabID != "" {
|
||||
params["tab"] = tabID
|
||||
}
|
||||
|
||||
// Only include form selector if it's provided
|
||||
if formSelector != "" {
|
||||
params["form_selector"] = formSelector
|
||||
}
|
||||
|
||||
// Add timeout if specified
|
||||
if timeout > 0 {
|
||||
params["timeout"] = strconv.Itoa(timeout)
|
||||
}
|
||||
|
||||
resp, err := c.SendCommand("form-accessibility-audit", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("failed to get form accessibility audit: %s", resp.Error)
|
||||
}
|
||||
|
||||
// Parse the response data
|
||||
var result FormSummary
|
||||
dataBytes, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal response data: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(dataBytes, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal form accessibility audit: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user