specialized

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package specialized provides specialized automated accessibility tests that go beyond what axe-core can detect.

These tests use browser automation to validate WCAG criteria that require dynamic interaction or visual comparison:

  • Keyboard accessibility (2.1.1, 2.1.2): Tab navigation, keyboard traps
  • Focus visibility (2.4.7, 2.4.3, 2.4.11, 3.2.1): Focus indicators, order, context
  • Content reflow (1.4.10): 320px viewport behavior
  • Target size (2.5.8): Touch target minimum dimensions
  • Text spacing (1.4.12): Content adaptation to increased spacing
  • Hover/focus content (1.4.13): Tooltips, dropdowns, dismissibility
  • Character shortcuts (2.1.4): Single-character keyboard shortcuts
  • Media (1.2.2, 1.2.4, 1.2.5, 1.4.2): Captions, audio controls
  • Flashing content (2.3.1): Flash rate detection
  • Responsive behavior (1.4.4, 1.3.4): Zoom, orientation

Package automated provides specialized automated accessibility tests beyond what axe-core can detect.

Index

Constants

View Source
const (
	LineHeight       = 1.5  // 1.5 times the font size
	ParagraphSpacing = 2.0  // 2 times the font size
	LetterSpacing    = 0.12 // 0.12 times the font size
	WordSpacing      = 0.16 // 0.16 times the font size
)

WCAG 1.4.12 required spacing values

Variables

This section is empty.

Functions

This section is empty.

Types

type AnimationResult

type AnimationResult struct {
	// HasMovingContent indicates moving, blinking, or scrolling content was found.
	HasMovingContent bool `json:"hasMovingContent"`

	// MovingElements lists elements with motion.
	MovingElements []MovingElement `json:"movingElements,omitempty"`

	// HasPauseControl indicates pause/stop mechanism exists.
	HasPauseControl bool `json:"hasPauseControl"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

AnimationResult contains results of animation/motion testing (WCAG 2.2.2).

func TestPauseStopHide

func TestPauseStopHide(ctx context.Context, vibe *vibium.Vibe) (*AnimationResult, error)

TestPauseStopHide tests for pause/stop mechanisms on moving content (WCAG 2.2.2).

type AudioControlResult

type AudioControlResult struct {
	// HasAutoplayAudio indicates if auto-playing audio was detected.
	HasAutoplayAudio bool `json:"hasAutoplayAudio"`

	// AutoplayElements lists elements with autoplay audio/video.
	AutoplayElements []AutoplayElement `json:"autoplayElements,omitempty"`

	// HasControlMechanism indicates if pause/stop/volume controls exist.
	HasControlMechanism bool `json:"hasControlMechanism"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

AudioControlResult contains results of audio control testing (WCAG 1.4.2).

func TestAudioControl

func TestAudioControl(ctx context.Context, vibe *vibium.Vibe) (*AudioControlResult, error)

TestAudioControl tests for auto-playing audio with controls (WCAG 1.4.2).

type AutoplayElement

type AutoplayElement struct {
	Selector string  `json:"selector"`
	TagName  string  `json:"tagName"`
	HasAudio bool    `json:"hasAudio"`
	Duration float64 `json:"duration"`
}

AutoplayElement represents an element with autoplay media.

type CharacterShortcutResult

type CharacterShortcutResult struct {
	// HasSingleCharShortcuts indicates single character shortcuts were detected.
	HasSingleCharShortcuts bool `json:"hasSingleCharShortcuts"`

	// DetectedShortcuts lists detected single-key shortcuts.
	DetectedShortcuts []string `json:"detectedShortcuts,omitempty"`

	// HasRemapOption indicates shortcuts can be remapped.
	HasRemapOption bool `json:"hasRemapOption"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

CharacterShortcutResult contains results of character key shortcut testing (WCAG 2.1.4).

func TestCharacterKeyShortcuts

func TestCharacterKeyShortcuts(ctx context.Context, vibe *vibium.Vibe) (*CharacterShortcutResult, error)

TestCharacterKeyShortcuts tests for single character key shortcuts (WCAG 2.1.4).

type ClipIssue

type ClipIssue struct {
	Selector       string  `json:"selector"`
	OriginalHeight float64 `json:"originalHeight"`
	NewHeight      float64 `json:"newHeight"`
	HasOverflow    bool    `json:"hasOverflow"`
}

ClipIssue represents an element with clipped text.

type Finding

type Finding struct {
	ID              string   `json:"id"`
	RuleID          string   `json:"ruleId"`
	Description     string   `json:"description"`
	Help            string   `json:"help"`
	SuccessCriteria []string `json:"successCriteria"`
	Level           string   `json:"level"`
	Impact          string   `json:"impact"`
	Selector        string   `json:"selector,omitempty"`
	HTML            string   `json:"html,omitempty"`
}

Finding represents a specialized test finding.

type FlashTestResult

type FlashTestResult struct {
	// HasPotentialFlashing indicates content that may flash was detected.
	HasPotentialFlashing bool `json:"hasPotentialFlashing"`

	// FlashingElements lists elements with potential flashing.
	FlashingElements []FlashingElement `json:"flashingElements,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

FlashTestResult contains results of flashing content testing (WCAG 2.3.1).

func TestThreeFlashes

func TestThreeFlashes(ctx context.Context, vibe *vibium.Vibe) (*FlashTestResult, error)

TestThreeFlashes tests for content that flashes more than 3 times per second (WCAG 2.3.1).

type FlashingElement

type FlashingElement struct {
	Selector  string `json:"selector"`
	Type      string `json:"type"`      // "gif", "video", "css-animation", "blink"
	RiskLevel string `json:"riskLevel"` // "high", "medium", "low"
}

FlashingElement represents an element with potential flashing content.

type FocusObscuredResult

type FocusObscuredResult struct {
	// TestedElements is the count of focusable elements tested.
	TestedElements int `json:"testedElements"`

	// HasStickyHeaders indicates sticky/fixed headers exist.
	HasStickyHeaders bool `json:"hasStickyHeaders"`

	// HasStickyFooters indicates sticky/fixed footers exist.
	HasStickyFooters bool `json:"hasStickyFooters"`

	// StickyElements lists sticky/fixed positioned elements.
	StickyElements []string `json:"stickyElements,omitempty"`

	// PotentiallyObscured lists elements that might be obscured.
	PotentiallyObscured []string `json:"potentiallyObscured,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

FocusObscuredResult contains results of focus obscured testing (WCAG 2.4.11).

func TestFocusNotObscured

func TestFocusNotObscured(ctx context.Context, vibe *vibium.Vibe) (*FocusObscuredResult, error)

TestFocusNotObscured tests that focused elements aren't hidden (WCAG 2.4.11).

type FocusOrderResult

type FocusOrderResult struct {
	// TotalFocusable is the count of focusable elements.
	TotalFocusable int `json:"totalFocusable"`

	// HasPositiveTabindex indicates elements with tabindex > 0 exist.
	HasPositiveTabindex bool `json:"hasPositiveTabindex"`

	// PositiveTabindexElements lists elements with tabindex > 0.
	PositiveTabindexElements []string `json:"positiveTabindexElements,omitempty"`

	// HasLogicalOrder indicates focus order follows visual/DOM order.
	HasLogicalOrder bool `json:"hasLogicalOrder"`

	// OutOfOrderElements lists elements that break logical order.
	OutOfOrderElements []string `json:"outOfOrderElements,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

FocusOrderResult contains results of focus order testing (WCAG 2.4.3).

func TestFocusOrder

func TestFocusOrder(ctx context.Context, vibe *vibium.Vibe) (*FocusOrderResult, error)

TestFocusOrder tests that focus order preserves meaning (WCAG 2.4.3).

type FocusVisibilityIssue

type FocusVisibilityIssue struct {
	Selector   string `json:"selector"`
	TagName    string `json:"tagName"`
	Role       string `json:"role,omitempty"`
	Screenshot string `json:"screenshot,omitempty"` // Base64 of focused state
}

FocusVisibilityIssue represents an element without visible focus.

type FocusVisibilityResult

type FocusVisibilityResult struct {
	// AllFocusVisible indicates all focused elements had visible indicators.
	AllFocusVisible bool `json:"allFocusVisible"`

	// ElementsWithoutVisibleFocus lists elements lacking focus indicators.
	ElementsWithoutVisibleFocus []FocusVisibilityIssue `json:"elementsWithoutVisibleFocus,omitempty"`

	// TestedElements is the count of elements tested.
	TestedElements int `json:"testedElements"`
}

FocusVisibilityResult contains results of focus visibility testing.

func TestFocusVisibility

func TestFocusVisibility(ctx context.Context, vibe *vibium.Vibe, maxElements int) (*FocusVisibilityResult, error)

TestFocusVisibility tests that focus indicators are visible (WCAG 2.4.7). It tabs through elements and compares screenshots to detect focus changes.

type FocusedElement

type FocusedElement struct {
	Index     int    `json:"index"`
	Selector  string `json:"selector"`
	TagName   string `json:"tagName"`
	Role      string `json:"role,omitempty"`
	Label     string `json:"label,omitempty"`
	TabIndex  int    `json:"tabIndex"`
	IsVisible bool   `json:"isVisible"`
}

FocusedElement records an element that received focus.

type HoverElement

type HoverElement struct {
	Selector    string `json:"selector"`
	ContentType string `json:"contentType"` // "tooltip", "dropdown", "popover", "custom"
}

HoverElement represents an element with hover-triggered content.

type HoverFocusResult

type HoverFocusResult struct {
	// HasHoverContent indicates elements show additional content on hover.
	HasHoverContent bool `json:"hasHoverContent"`

	// HasFocusContent indicates elements show additional content on focus.
	HasFocusContent bool `json:"hasFocusContent"`

	// HoverElements lists elements with hover-triggered content.
	HoverElements []HoverElement `json:"hoverElements,omitempty"`

	// IsDismissible indicates hover content can be dismissed.
	IsDismissible bool `json:"isDismissible"`

	// IsHoverable indicates hover content can be hovered.
	IsHoverable bool `json:"isHoverable"`

	// IsPersistent indicates hover content persists until dismissed.
	IsPersistent bool `json:"isPersistent"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

HoverFocusResult contains results of content on hover/focus testing (WCAG 1.4.13).

func TestContentOnHoverFocus

func TestContentOnHoverFocus(ctx context.Context, vibe *vibium.Vibe) (*HoverFocusResult, error)

TestContentOnHoverFocus tests hover/focus triggered content (WCAG 1.4.13).

type KeyboardTestResult

type KeyboardTestResult struct {
	// AllElementsReachable indicates all interactive elements can be tabbed to.
	AllElementsReachable bool `json:"allElementsReachable"`

	// TrapDetected indicates a keyboard trap was found.
	TrapDetected bool `json:"trapDetected"`

	// TrapLocation is the selector where the trap was detected.
	TrapLocation string `json:"trapLocation,omitempty"`

	// UnreachableElements lists elements that couldn't be reached via Tab.
	UnreachableElements []string `json:"unreachableElements,omitempty"`

	// FocusOrder records the order elements received focus.
	FocusOrder []FocusedElement `json:"focusOrder"`

	// TabCount is the number of Tab presses needed to traverse the page.
	TabCount int `json:"tabCount"`
}

KeyboardTestResult contains results of keyboard accessibility testing.

func TestKeyboardAccessibility

func TestKeyboardAccessibility(ctx context.Context, vibe *vibium.Vibe, maxTabs int) (*KeyboardTestResult, error)

TestKeyboardAccessibility tests keyboard navigation (WCAG 2.1.1, 2.1.2).

type MovingElement

type MovingElement struct {
	Selector      string `json:"selector"`
	AnimationType string `json:"animationType"` // "css-animation", "carousel", "marquee", "blink", "auto-scroll"
}

MovingElement represents an element with motion/animation.

type OnFocusResult

type OnFocusResult struct {
	// HasOnFocusHandlers indicates elements with onfocus handlers exist.
	HasOnFocusHandlers bool `json:"hasOnFocusHandlers"`

	// ProblematicElements lists elements that may cause context changes on focus.
	ProblematicElements []string `json:"problematicElements,omitempty"`

	// HasAutoFocus indicates autofocus attribute is used.
	HasAutoFocus bool `json:"hasAutoFocus"`

	// AutoFocusElement is the element with autofocus.
	AutoFocusElement string `json:"autoFocusElement,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

OnFocusResult contains results of on-focus context change testing (WCAG 3.2.1).

func TestOnFocus

func TestOnFocus(ctx context.Context, vibe *vibium.Vibe) (*OnFocusResult, error)

TestOnFocus tests that focus doesn't cause context changes (WCAG 3.2.1).

type OnInputResult

type OnInputResult struct {
	// HasAutoSubmit indicates forms with auto-submit on input change.
	HasAutoSubmit bool `json:"hasAutoSubmit"`

	// ProblematicFields lists fields that may cause context changes.
	ProblematicFields []string `json:"problematicFields,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

OnInputResult contains results of on-input context change testing (WCAG 3.2.2).

func TestOnInput

func TestOnInput(ctx context.Context, vibe *vibium.Vibe) (*OnInputResult, error)

TestOnInput tests that input changes don't cause unexpected context changes (WCAG 3.2.2).

type OverflowElement

type OverflowElement struct {
	Selector string  `json:"selector"`
	Width    float64 `json:"width"`
	Overflow float64 `json:"overflow"`
}

OverflowElement represents an element causing horizontal overflow.

type OverlapIssue

type OverlapIssue struct {
	Selector1 string `json:"selector1"`
	Selector2 string `json:"selector2"`
}

OverlapIssue represents elements that overlap after spacing change.

type PointerCancellationResult

type PointerCancellationResult struct {
	// HasMousedownActions indicates elements with mousedown-only actions.
	HasMousedownActions bool `json:"hasMousedownActions"`

	// ProblematicElements lists elements that may have cancellation issues.
	ProblematicElements []string `json:"problematicElements,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

PointerCancellationResult contains results of pointer cancellation testing (WCAG 2.5.2).

func TestPointerCancellation

func TestPointerCancellation(ctx context.Context, vibe *vibium.Vibe) (*PointerCancellationResult, error)

TestPointerCancellation tests that pointer actions can be cancelled (WCAG 2.5.2).

type RedundantEntryResult

type RedundantEntryResult struct {
	// HasMultiStepForm indicates multi-step forms exist.
	HasMultiStepForm bool `json:"hasMultiStepForm"`

	// HasAutocomplete indicates autocomplete is enabled.
	HasAutocomplete bool `json:"hasAutocomplete"`

	// FormsWithoutAutocomplete lists forms missing autocomplete.
	FormsWithoutAutocomplete int `json:"formsWithoutAutocomplete"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

RedundantEntryResult contains results of redundant entry testing (WCAG 3.3.7).

func TestRedundantEntry

func TestRedundantEntry(ctx context.Context, vibe *vibium.Vibe) (*RedundantEntryResult, error)

TestRedundantEntry tests that previously entered info is auto-populated (WCAG 3.3.7).

type ReflowTestResult

type ReflowTestResult struct {
	// NoHorizontalScroll indicates no horizontal scrolling at 320px width.
	NoHorizontalScroll bool `json:"noHorizontalScroll"`

	// HorizontalScrollWidth is the amount of horizontal overflow in pixels.
	HorizontalScrollWidth float64 `json:"horizontalScrollWidth,omitempty"`

	// ContentLoss indicates content was lost or hidden at 320px.
	ContentLoss bool `json:"contentLoss"`

	// LostElements lists elements that became hidden/invisible.
	LostElements []string `json:"lostElements,omitempty"`

	// OverflowingElements lists elements causing horizontal scroll.
	OverflowingElements []OverflowElement `json:"overflowingElements,omitempty"`

	// OriginalViewport is the viewport before testing.
	OriginalViewport Viewport `json:"originalViewport"`

	// TestedViewport is the narrow viewport used for testing.
	TestedViewport Viewport `json:"testedViewport"`
}

ReflowTestResult contains results of reflow testing.

func TestReflow

func TestReflow(ctx context.Context, vibe *vibium.Vibe) (*ReflowTestResult, error)

TestReflow tests content reflow at 320px width (WCAG 1.4.10).

type ResizeTextResult

type ResizeTextResult struct {
	// OriginalFontSizes captures font sizes before zoom.
	OriginalFontSizes int `json:"originalFontSizes"`

	// HasContentLoss indicates if content is lost at 200% zoom.
	HasContentLoss bool `json:"hasContentLoss"`

	// HasOverflow indicates if text overflows at 200% zoom.
	HasOverflow bool `json:"hasOverflow"`

	// ClippedElements lists elements with clipped text.
	ClippedElements []string `json:"clippedElements,omitempty"`

	// OverlappingElements lists elements that overlap at 200%.
	OverlappingElements []string `json:"overlappingElements,omitempty"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

ResizeTextResult contains results of text resize testing (WCAG 1.4.4).

func TestResizeText

func TestResizeText(ctx context.Context, vibe *vibium.Vibe) (*ResizeTextResult, error)

TestResizeText tests that text can be resized up to 200% without loss (WCAG 1.4.4).

type Results

type Results struct {
	Keyboard      *KeyboardTestResult    `json:"keyboard,omitempty"`
	FocusVisible  *FocusVisibilityResult `json:"focusVisible,omitempty"`
	FocusOrder    *FocusOrderResult      `json:"focusOrder,omitempty"`
	FocusObscured *FocusObscuredResult   `json:"focusObscured,omitempty"`
	OnFocus       *OnFocusResult         `json:"onFocus,omitempty"`
	Reflow        *ReflowTestResult      `json:"reflow,omitempty"`
	TargetSize    *TargetSizeTestResult  `json:"targetSize,omitempty"`
	TextSpacing   *SpacingTestResult     `json:"textSpacing,omitempty"`
	Findings      []Finding              `json:"findings"`
}

Results contains all specialized test results.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner executes specialized accessibility tests.

func NewRunner

func NewRunner(vibe *vibium.Vibe, logger *slog.Logger) *Runner

NewRunner creates a new specialized test runner.

func (*Runner) RunAll

func (r *Runner) RunAll(ctx context.Context) (*Results, error)

RunAll executes all specialized tests and returns findings.

type SmallTarget

type SmallTarget struct {
	Selector string  `json:"selector"`
	TagName  string  `json:"tagName"`
	Role     string  `json:"role,omitempty"`
	Width    float64 `json:"width"`
	Height   float64 `json:"height"`
	Area     float64 `json:"area"`
}

SmallTarget represents an interactive element below minimum size.

type SpacingTestResult

type SpacingTestResult struct {
	// PassesSpacingTest indicates content remains readable with increased spacing.
	PassesSpacingTest bool `json:"passesSpacingTest"`

	// ContentLoss indicates text was cut off or hidden.
	ContentLoss bool `json:"contentLoss"`

	// OverlappingElements lists elements that overlap after spacing change.
	OverlappingElements []OverlapIssue `json:"overlappingElements,omitempty"`

	// ClippedElements lists elements with text clipped after spacing change.
	ClippedElements []ClipIssue `json:"clippedElements,omitempty"`

	// TestedElements is the count of text elements tested.
	TestedElements int `json:"testedElements"`
}

SpacingTestResult contains results of text spacing testing.

func TestTextSpacing

func TestTextSpacing(ctx context.Context, vibe *vibium.Vibe) (*SpacingTestResult, error)

TestTextSpacing tests that content adapts to increased text spacing (WCAG 1.4.12).

type TargetSizeTestResult

type TargetSizeTestResult struct {
	// AllTargetsAdequate indicates all touch targets meet size requirements.
	AllTargetsAdequate bool `json:"allTargetsAdequate"`

	// SmallTargets lists elements below the minimum size.
	SmallTargets []SmallTarget `json:"smallTargets,omitempty"`

	// TestedElements is the count of interactive elements tested.
	TestedElements int `json:"testedElements"`

	// MinimumSize is the required minimum size (24x24 for WCAG 2.5.8).
	MinimumSize int `json:"minimumSize"`
}

TargetSizeTestResult contains results of target size testing.

func TestTargetSize

func TestTargetSize(ctx context.Context, vibe *vibium.Vibe, minimumSize int) (*TargetSizeTestResult, error)

TestTargetSize tests that touch targets are at least 24x24 CSS pixels (WCAG 2.5.8).

type TimingResult

type TimingResult struct {
	// HasMetaRefresh indicates a meta refresh redirect exists.
	HasMetaRefresh bool `json:"hasMetaRefresh"`

	// MetaRefreshDelay is the delay in seconds (0 = immediate).
	MetaRefreshDelay int `json:"metaRefreshDelay,omitempty"`

	// HasSessionTimeout indicates session timeout was detected.
	HasSessionTimeout bool `json:"hasSessionTimeout"`

	// PassesTest indicates the criterion is met.
	PassesTest bool `json:"passesTest"`
}

TimingResult contains results of timing testing (WCAG 2.2.1).

func TestTimingAdjustable

func TestTimingAdjustable(ctx context.Context, vibe *vibium.Vibe) (*TimingResult, error)

TestTimingAdjustable tests for adjustable time limits (WCAG 2.2.1).

type Viewport

type Viewport struct {
	Width  int `json:"width"`
	Height int `json:"height"`
}

Viewport represents viewport dimensions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL