Class: Guardrails::A11yDeep

Inherits:
Object
  • Object
show all
Defined in:
lib/guardrails/a11y_deep.rb

Overview

Consumes axe-core JSON output and folds the findings into Guardrails’ unified report. Distinct from ‘A11yAudit`, which runs static template checks (image_alt, button_name, etc.) without rendering.

Why parse-only, no run: bundling axe-core means bundling Capybara + headless Chrome as runtime deps of a static-analysis gem — too heavy for users who don’t run system tests. Instead, users run axe-core however they already do (axe-core-rspec, ‘npx @axe-core/cli`, a CDP-driven script) and pass the JSON output to Guardrails:

npx @axe-core/cli http://localhost:3000/ --save axe.json
AXE_JSON=axe.json bundle exec rake guardrails:audit

The result is a single unified report — static findings from A11yAudit plus runtime findings from axe — with the same exit-code semantics as the rest of the audit.

Defined Under Namespace

Classes: Finding

Constant Summary collapse

DEFAULT_FAILING_IMPACTS =

Impacts we treat as audit-failing. axe emits one of: minor, moderate, serious, critical (and sometimes nil for ‘incomplete` findings or custom rule packs). The 0.6.0 default is “any known non-nil impact fails” — covers axe’s full impact ladder and aligns with the static a11y rules which all fail unconditionally. Findings with a nil/ unknown impact do NOT fail by default; tighten per-call via ‘failing_impacts:` if your rule pack emits custom severities.

%w[minor moderate serious critical].freeze

Instance Method Summary collapse

Constructor Details

#initialize(input:, output: $stdout, failing_impacts: DEFAULT_FAILING_IMPACTS) ⇒ A11yDeep

Returns a new instance of A11yDeep.



40
41
42
43
44
# File 'lib/guardrails/a11y_deep.rb', line 40

def initialize(input:, output: $stdout, failing_impacts: DEFAULT_FAILING_IMPACTS)
  @input = input
  @output = output
  @failing_impacts = Set.new(failing_impacts.map(&:to_s))
end

Instance Method Details

#any_failing?(findings) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/guardrails/a11y_deep.rb', line 61

def any_failing?(findings)
  findings.any? { |f| @failing_impacts.include?(f.impact.to_s) }
end

#parse(payload) ⇒ Object

Parse axe-core JSON. Accepts either a single result object ‘{ “url”: “…”, “violations”: […] }` or an array of results (multi-page runs, what `axe-core/cli –save` produces). Returns a flat list of Finding structs.



56
57
58
59
# File 'lib/guardrails/a11y_deep.rb', line 56

def parse(payload)
  pages = payload.is_a?(Array) ? payload : [payload]
  pages.flat_map { |page| parse_page(page) }
end

#runObject



46
47
48
49
50
# File 'lib/guardrails/a11y_deep.rb', line 46

def run
  findings = parse_input
  print_report(findings)
  findings
end