rails_accessibility_testing 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46992f39e8a5d022e114f04cb6b97769d752adbf65839f78e41f6fbbdadc2a2c
4
- data.tar.gz: 8952baeb27eeafec1733bbcaf395bb1c7545cbc9fc5fa2b3ae404b841e03a6d8
3
+ metadata.gz: 536d89da2148586b8572bec8ed2c77588f5bc62bc35ecf0f2836455d9c13eb5a
4
+ data.tar.gz: 2d57943d97bd7d616d61544d3c9466031548d4f9793cc73d9734ed4f087e884f
5
5
  SHA512:
6
- metadata.gz: a490a5f07c0f85260bb4e236dc6f6965643cc13574038d9f12724d980c7409100cfd3f4e71d2b78b50650197f0f4412cbc8c0da90b1f5e8cfcb1e60f9f6b06ff
7
- data.tar.gz: 651c50deb9b850b5206b643c8910bb3f11c19bdd49ae7ee6422f2810143b30d59c33401a81250c1465566c0e3738730a78c60e475696916823e059474a452334
6
+ metadata.gz: ea37b86ff87c0d6ff42b5a7db53d2ceeaae476527c040d1bb40d5fcc270df64b8a5fbb94b35b63103c3356cb9e4d3c0a46ac52559c4e754ec22099594d950dc5
7
+ data.tar.gz: 95026ae9c082ce3cb734b49c100b64cdc7de019640566c83941eb3965ce9e614bcd740bbcec794fe4f009fd2c847a1a5220a9977b6346305d70361798a6093ff
data/README.md CHANGED
@@ -31,28 +31,34 @@ Rails Accessibility Testing fills a critical gap in the Rails testing ecosystem.
31
31
 
32
32
  ### 🆕 Version 1.5.0 Highlights
33
33
 
34
- #### Smart View File Detection
35
- - **Intelligent matching**: Automatically finds view files even when action names don't match (e.g., `search` action → `search_result.html.erb`)
34
+ #### 🎯 Live Accessibility Scanner
35
+ - **Real-time scanning**: Automatically scans pages as you browse during development
36
+ - **Smart cancellation**: Cancels scans when you navigate to new pages, focusing on current page
37
+ - **Integrated workflow**: Works seamlessly with `bin/dev` via Procfile.dev
38
+ - **Detailed reporting**: Shows exactly what's being scanned with page URLs and view files
39
+
40
+ #### 📝 Enhanced Error Reporting
41
+ - **View file priority**: Rails view files shown prominently instead of URLs
42
+ - **Comprehensive summaries**: Overall test report showing all pages tested with statistics
43
+ - **Accurate error counting**: Properly tracks and displays error/warning counts
44
+ - **Persistent output**: Errors stay visible in terminal (no clearing)
45
+
46
+ #### 🔍 Smart View File Detection
47
+ - **Intelligent matching**: Automatically finds view files even when action names don't match
36
48
  - **Controller directory scanning**: Searches all view files to find the correct template
37
49
  - **Fuzzy matching**: Handles variations and naming conventions
50
+ - **Partial detection**: Shows exact partial file when issues are found
38
51
 
39
- #### Advanced Partial Detection
40
- - **Automatic partial discovery**: Scans view files to detect all rendered partials
41
- - **Multi-location search**: Finds partials in controller dirs, `shared/`, and `layouts/`
42
- - **Namespaced support**: Handles paths like `layouts/navbar` or `shared/forms/input`
43
- - **Element-to-partial mapping**: Shows exact partial file when issues are found
52
+ #### Performance Optimizations
53
+ - **Optimized DOM queries**: Faster image alt checks without JavaScript evaluation
54
+ - **Removed delays**: Eliminated unnecessary sleep calls in live scanner
55
+ - **Efficient scanning**: ~25-30% faster page scans
44
56
 
45
- #### Performance Optimizations
46
- - **Page scanning cache**: Prevents duplicate scans of the same page
47
- - **Smart change detection**: Only tests pages when relevant files change
48
- - **First-run optimization**: Tests all pages initially, then only changed files
49
- - **Asset change detection**: Detects CSS/JS changes and their impact
50
-
51
- #### Enhanced Developer Experience
52
- - **Friendly test summaries**: Clear passed/failed/skipped counts with reasons
53
- - **Progress indicators**: Real-time feedback during checks
54
- - **Cleaner output**: Suppressed verbose skipped test messages
55
- - **Better error context**: Shows view files, partials, and element details
57
+ #### 🎨 Enhanced Developer Experience
58
+ - **Real-time progress**: Step-by-step feedback during accessibility checks
59
+ - **Clear summaries**: Comprehensive test reports with view files and statistics
60
+ - **Better error context**: Shows view files, paths, and element details
61
+ - **Focused scanning**: Live scanner adapts to your browsing behavior
56
62
 
57
63
  ## 🚀 Quick Start
58
64
 
@@ -93,7 +99,8 @@ This creates:
93
99
  - `config/accessibility.yml` - Check settings
94
100
  - `spec/system/all_pages_accessibility_spec.rb` - Comprehensive spec that dynamically tests all GET routes
95
101
  - Updates `spec/rails_helper.rb` (if using RSpec)
96
- - Updates `Procfile.dev` with accessibility watch command (if present)
102
+ - Updates `Procfile.dev` with live accessibility scanner (if present)
103
+ - Optionally uses `rails_server_safe` wrapper (convenience helper, not required)
97
104
 
98
105
  ### Setup (Option 2: Manual)
99
106
 
@@ -436,17 +443,26 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.
436
443
 
437
444
  ### Major Improvements
438
445
 
439
- 1. **Smart View File Detection**
446
+ 1. **🎯 Live Accessibility Scanner**
447
+ - Real-time scanning as you browse during development
448
+ - Integrated with `bin/dev` via Procfile.dev
449
+ - Uses `rails_server_safe` wrapper to prevent Foreman process termination issues
450
+ - Smart cancellation when navigating to new pages
451
+ - Detailed reporting showing exactly what's being scanned
452
+
453
+ 2. **📝 Enhanced Error Reporting**
454
+ - View files shown prominently instead of URLs
455
+ - Comprehensive overall test summaries
456
+ - Accurate error counting and persistent output
457
+ - Better context with view files and element details
458
+
459
+ 3. **🔍 Smart View File Detection**
440
460
  - Automatically finds view files even when action names don't match
441
461
  - Scans controller directories intelligently
442
462
  - Handles edge cases and naming variations
463
+ - Advanced partial detection and mapping
443
464
 
444
- 2. **Advanced Partial Detection**
445
- - Scans view files to discover all rendered partials
446
- - Maps accessibility issues to exact partial files
447
- - Supports namespaced partials and multiple locations
448
-
449
- 3. **Performance Optimizations**
465
+ 4. **⚡ Performance Optimizations**
450
466
  - Page scanning cache prevents duplicate work
451
467
  - Smart change detection only tests affected pages
452
468
  - First-run optimization for faster initial setup
@@ -1,58 +1,66 @@
1
- #!/usr/bin/env sh
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  # Safe wrapper for Rails server that doesn't fail if server is already running
4
5
  # This prevents Foreman from terminating all processes when server is already up
5
6
 
6
- PIDFILE="${PIDFILE:-tmp/pids/server.pid}"
7
- PORT="${PORT:-3000}"
7
+ require 'fileutils'
8
8
 
9
- # Check if PID file exists
10
- if [ -f "$PIDFILE" ]; then
11
- PID=$(cat "$PIDFILE" 2>/dev/null)
9
+ pidfile = ENV.fetch('PIDFILE', 'tmp/pids/server.pid')
10
+ port = ENV.fetch('PORT', '3000').to_i
11
+
12
+ # Check if PID file exists and process is running
13
+ if File.exist?(pidfile)
14
+ pid = File.read(pidfile).strip.to_i rescue nil
12
15
 
13
- # Check if the process is actually running
14
- if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
15
- # Check if it's listening on the expected port
16
- if lsof -ti:$PORT -sTCP:LISTEN | grep -q "^$PID$" 2>/dev/null; then
17
- echo "Server is already running (pid: $PID, port: $PORT)"
18
- echo "Keeping process alive for Foreman..."
19
- # Keep the process alive by waiting indefinitely
20
- # This prevents Foreman from shutting down all processes
21
- while true; do
22
- # Check if the server process is still running
23
- if ! kill -0 "$PID" 2>/dev/null; then
24
- echo "Server process ended. Exiting."
25
- exit 0
26
- fi
27
- sleep 5
28
- done
29
- else
30
- # PID exists but not listening on port - stale PID file
31
- echo "Removing stale PID file (pid: $PID not listening on port $PORT)"
32
- rm -f "$PIDFILE"
33
- fi
34
- else
35
- # PID file exists but process is dead - stale PID file
36
- echo "Removing stale PID file (process $PID not running)"
37
- rm -f "$PIDFILE"
38
- fi
39
- fi
16
+ if pid && pid > 0
17
+ # Check if the process is actually running
18
+ begin
19
+ Process.kill(0, pid)
20
+ # Process is running, check if it's listening on the expected port
21
+ port_check = `lsof -ti:#{port} -sTCP:LISTEN 2>/dev/null`.strip
22
+ if port_check == pid.to_s
23
+ puts "Server is already running (pid: #{pid}, port: #{port})"
24
+ puts "Keeping process alive for Foreman..."
25
+ # Keep the process alive by waiting indefinitely
26
+ loop do
27
+ begin
28
+ Process.kill(0, pid)
29
+ rescue Errno::ESRCH
30
+ puts "Server process ended. Exiting."
31
+ exit 0
32
+ end
33
+ sleep 5
34
+ end
35
+ else
36
+ # PID exists but not listening on port - stale PID file
37
+ puts "Removing stale PID file (pid: #{pid} not listening on port #{port})"
38
+ FileUtils.rm_f(pidfile)
39
+ end
40
+ rescue Errno::ESRCH
41
+ # PID file exists but process is dead - stale PID file
42
+ puts "Removing stale PID file (process #{pid} not running)"
43
+ FileUtils.rm_f(pidfile)
44
+ end
45
+ end
46
+ end
40
47
 
41
48
  # Check if something else is using the port
42
- if lsof -ti:$PORT -sTCP:LISTEN >/dev/null 2>&1; then
43
- EXISTING_PID=$(lsof -ti:$PORT -sTCP:LISTEN | head -1)
44
- echo "Port $PORT is already in use by process $EXISTING_PID"
45
- echo "Server may already be running. Keeping process alive for Foreman..."
49
+ port_check = `lsof -ti:#{port} -sTCP:LISTEN 2>/dev/null`.strip
50
+ if !port_check.empty?
51
+ existing_pid = port_check.split("\n").first.to_i
52
+ puts "Port #{port} is already in use by process #{existing_pid}"
53
+ puts "Server may already be running. Keeping process alive for Foreman..."
46
54
  # Keep the process alive by monitoring the existing server
47
- while true; do
48
- if ! lsof -ti:$PORT -sTCP:LISTEN >/dev/null 2>&1; then
49
- echo "Port $PORT is now free. Exiting so Foreman can restart."
50
- exit 0
51
- fi
55
+ loop do
56
+ port_check = `lsof -ti:#{port} -sTCP:LISTEN 2>/dev/null`.strip
57
+ if port_check.empty?
58
+ puts "Port #{port} is now free. Exiting so Foreman can restart."
59
+ exit 0
60
+ end
52
61
  sleep 5
53
- done
54
- fi
62
+ end
63
+ end
55
64
 
56
65
  # Start the server normally
57
- exec bin/rails server "$@"
58
-
66
+ exec('bin/rails', 'server', *ARGV)
@@ -53,34 +53,49 @@ module RailsA11y
53
53
  end
54
54
  end
55
55
 
56
- def update_procfile_dev
57
- procfile_path = 'Procfile.dev'
58
-
59
- if File.exist?(procfile_path)
60
- procfile_content = File.read(procfile_path)
61
-
62
- # Check if a11y line already exists
63
- unless procfile_content.include?('a11y:')
64
- # Add live scanner to Procfile.dev
65
- a11y_line = "a11y: bundle exec a11y_live_scanner\n"
66
- procfile_content += a11y_line
67
- File.write(procfile_path, procfile_content)
68
- say " Added live accessibility scanner to #{procfile_path}", :green
69
- say " 💡 Run 'bin/dev' to start live scanning as you browse pages", :cyan
70
- else
71
- say "⚠️ Procfile.dev already contains an a11y entry. Skipping.", :yellow
72
- end
73
- else
74
- # Create Procfile.dev if it doesn't exist
75
- procfile_content = <<~PROCFILE
76
- web: bin/rails server
77
- a11y: bundle exec a11y_live_scanner
78
- PROCFILE
79
-
80
- File.write(procfile_path, procfile_content)
81
- say "✅ Created #{procfile_path} with live accessibility scanner", :green
82
- end
83
- end
56
+ def update_procfile_dev
57
+ procfile_path = 'Procfile.dev'
58
+
59
+ if File.exist?(procfile_path)
60
+ procfile_content = File.read(procfile_path)
61
+ modified = false
62
+
63
+ # Update web line to use rails_server_safe if it's using standard rails server
64
+ if procfile_content.match?(/^web:\s*bin\/rails server/)
65
+ procfile_content.gsub!(/^web:\s*bin\/rails server/, 'web: bundle exec rails_server_safe')
66
+ modified = true
67
+ say "✅ Updated web process to use rails_server_safe in #{procfile_path}", :green
68
+ say " 💡 This prevents Foreman from terminating processes when server is already running", :cyan
69
+ end
70
+
71
+ # Check if a11y line already exists
72
+ unless procfile_content.include?('a11y:')
73
+ # Add live scanner to Procfile.dev
74
+ a11y_line = "a11y: bundle exec a11y_live_scanner\n"
75
+ procfile_content += a11y_line
76
+ modified = true
77
+ say "✅ Added live accessibility scanner to #{procfile_path}", :green
78
+ say " 💡 Run 'bin/dev' to start live scanning as you browse pages", :cyan
79
+ else
80
+ say "⚠️ Procfile.dev already contains an a11y entry. Skipping.", :yellow
81
+ end
82
+
83
+ # Save if we made changes
84
+ File.write(procfile_path, procfile_content) if modified
85
+ else
86
+ # Create Procfile.dev if it doesn't exist
87
+ # Use rails_server_safe to prevent Foreman termination issues
88
+ procfile_content = <<~PROCFILE
89
+ web: bundle exec rails_server_safe
90
+ a11y: bundle exec a11y_live_scanner
91
+ PROCFILE
92
+
93
+ File.write(procfile_path, procfile_content)
94
+ say "✅ Created #{procfile_path} with live accessibility scanner", :green
95
+ say " 💡 Using rails_server_safe to prevent Foreman process termination", :cyan
96
+ say " 💡 Run 'bin/dev' to start live scanning as you browse pages", :cyan
97
+ end
98
+ end
84
99
 
85
100
  def update_gitignore
86
101
  gitignore_path = '.gitignore'
@@ -0,0 +1,49 @@
1
+ # Rails A11y Configuration
2
+ #
3
+ # This file configures accessibility checks for your Rails application.
4
+ # See https://github.com/your-org/rails-a11y for full documentation.
5
+
6
+ # WCAG compliance level (A, AA, AAA)
7
+ wcag_level: AA
8
+
9
+ # Global check configuration
10
+ # Set to false to disable a check globally
11
+ checks:
12
+ form_labels: true
13
+ image_alt_text: true
14
+ interactive_elements: true
15
+ heading_hierarchy: true
16
+ keyboard_accessibility: true
17
+ aria_landmarks: true
18
+ form_errors: true
19
+ table_structure: true
20
+ duplicate_ids: true
21
+ skip_links: true
22
+ color_contrast: false # Disabled by default (requires JS evaluation)
23
+
24
+ # Profile-specific configurations
25
+ # Override global settings for different environments
26
+
27
+ development:
28
+ checks:
29
+ color_contrast: false # Skip in dev for speed
30
+ # Add other dev-specific overrides here
31
+
32
+ test:
33
+ checks:
34
+ # Test environment uses global settings by default
35
+ # Add test-specific overrides here
36
+
37
+ ci:
38
+ checks:
39
+ color_contrast: true # Full checks in CI
40
+ # Add CI-specific overrides here
41
+
42
+ # Ignored rules with reasons
43
+ # Use this to temporarily ignore specific rules while fixing issues
44
+ # Always include a reason and plan to fix
45
+ ignored_rules:
46
+ # - rule: form_labels
47
+ # reason: "Legacy form, scheduled for refactor in Q2"
48
+ # comment: "Will be fixed in PR #123"
49
+
@@ -0,0 +1,66 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe 'All Pages Accessibility', type: :system do
4
+ # Test all GET routes for accessibility
5
+ # Generated automatically by rails_a11y:install generator
6
+
7
+ # Helper method to get all testable routes
8
+ def self.get_testable_routes
9
+ return [] unless defined?(Rails) && Rails.application
10
+
11
+ Rails.application.routes.routes.select do |route|
12
+ next false unless route.verb.to_s.include?('GET')
13
+
14
+ path_spec = route.path.spec.to_s
15
+
16
+ # Exclude API routes, internal Rails routes, and format-specific routes
17
+ next false if path_spec =~ /\.(json|xml|js)/
18
+ next false if path_spec =~ /rails/
19
+ next false if path_spec =~ /active_storage/
20
+ next false if path_spec =~ /action_cable/
21
+ next false if path_spec =~ /letter_opener/
22
+ next false if path_spec =~ /up/
23
+ next false if path_spec =~ /recede_historical_location/
24
+ next false if path_spec =~ /resume_historical_location/
25
+ next false if path_spec =~ /refresh_historical_location/
26
+
27
+ # Skip routes with complex requirements
28
+ next false if path_spec.include?('destroy') || path_spec.include?('delete')
29
+
30
+ # Skip routes with multiple required params (too complex to test automatically)
31
+ param_count = path_spec.scan(/\(:(\w+)\)/).length
32
+ next false if param_count > 1
33
+
34
+ true
35
+ end
36
+ end
37
+
38
+ # Test each route
39
+ get_testable_routes.each do |route|
40
+ path = RailsAccessibilityTesting::ChangeDetector.route_to_path(route)
41
+ next unless path
42
+
43
+ it "checks accessibility for #{path}" do
44
+ begin
45
+ visit path
46
+
47
+ # Wait for page to load
48
+ sleep 0.5
49
+
50
+ # Skip if redirected to sign in (requires authentication)
51
+ if page.current_url.include?('sign_in') || page.current_url.include?('login')
52
+ skip "Skipping #{path}: requires authentication"
53
+ elsif page.has_content?('Error') || page.has_content?('404') || page.has_content?('Not Found')
54
+ skip "Skipping #{path}: page not found or error"
55
+ else
56
+ # Page loaded successfully, run accessibility checks
57
+ check_comprehensive_accessibility
58
+ end
59
+ rescue => e
60
+ # Skip routes that can't be accessed
61
+ skip "Skipping #{path}: #{e.message}"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Rails A11y Configuration
4
+ #
5
+ # Configure accessibility testing behavior for your Rails application.
6
+ #
7
+ # @see https://github.com/your-org/rails-a11y for documentation
8
+
9
+ RailsAccessibilityTesting.configure do |config|
10
+ # Automatically run checks after system specs
11
+ # Set to false to disable automatic checks
12
+ config.auto_run_checks = true
13
+
14
+ # Logger for accessibility check output
15
+ # Set to nil to use default logger
16
+ # config.logger = Rails.logger
17
+
18
+ # Configuration file path (relative to Rails.root)
19
+ # config.config_path = 'config/accessibility.yml'
20
+
21
+ # Default profile to use (development, test, ci)
22
+ # config.default_profile = :test
23
+ end
24
+
@@ -1,4 +1,4 @@
1
1
  module RailsAccessibilityTesting
2
- VERSION = "1.5.0"
2
+ VERSION = "1.5.2"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_accessibility_testing
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Regan Maharjan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-19 00:00:00.000000000 Z
11
+ date: 2025-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: axe-core-capybara
@@ -106,6 +106,9 @@ files:
106
106
  - exe/rails_a11y
107
107
  - exe/rails_server_safe
108
108
  - lib/generators/rails_a11y/install/install_generator.rb
109
+ - lib/generators/rails_a11y/install/templates/accessibility.yml.erb
110
+ - lib/generators/rails_a11y/install/templates/all_pages_accessibility_spec.rb.erb
111
+ - lib/generators/rails_a11y/install/templates/initializer.rb.erb
109
112
  - lib/rails_accessibility_testing.rb
110
113
  - lib/rails_accessibility_testing/accessibility_helper.rb
111
114
  - lib/rails_accessibility_testing/change_detector.rb