rails_accessibility_testing 1.4.2 → 1.5.0

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/ARCHITECTURE.md +212 -53
  3. data/CHANGELOG.md +135 -0
  4. data/GUIDES/getting_started.md +171 -9
  5. data/GUIDES/system_specs_for_accessibility.md +13 -12
  6. data/README.md +139 -36
  7. data/docs_site/getting_started.md +142 -18
  8. data/docs_site/index.md +1 -1
  9. data/exe/a11y_live_scanner +361 -0
  10. data/exe/rails_server_safe +18 -1
  11. data/lib/generators/rails_a11y/install/install_generator.rb +137 -0
  12. data/lib/rails_accessibility_testing/accessibility_helper.rb +547 -24
  13. data/lib/rails_accessibility_testing/change_detector.rb +17 -104
  14. data/lib/rails_accessibility_testing/checks/base_check.rb +56 -7
  15. data/lib/rails_accessibility_testing/checks/heading_check.rb +138 -0
  16. data/lib/rails_accessibility_testing/checks/image_alt_text_check.rb +7 -7
  17. data/lib/rails_accessibility_testing/checks/interactive_elements_check.rb +11 -1
  18. data/lib/rails_accessibility_testing/cli/command.rb +3 -1
  19. data/lib/rails_accessibility_testing/config/yaml_loader.rb +1 -1
  20. data/lib/rails_accessibility_testing/engine/rule_engine.rb +49 -5
  21. data/lib/rails_accessibility_testing/error_message_builder.rb +63 -7
  22. data/lib/rails_accessibility_testing/middleware/page_visit_logger.rb +81 -0
  23. data/lib/rails_accessibility_testing/railtie.rb +22 -0
  24. data/lib/rails_accessibility_testing/rspec_integration.rb +176 -10
  25. data/lib/rails_accessibility_testing/version.rb +1 -1
  26. data/lib/rails_accessibility_testing.rb +8 -3
  27. metadata +8 -4
  28. data/lib/generators/rails_a11y/install/generator.rb +0 -51
  29. data/lib/rails_accessibility_testing/checks/heading_hierarchy_check.rb +0 -53
@@ -15,10 +15,18 @@ Add to your `Gemfile`:
15
15
  ```ruby
16
16
  group :development, :test do
17
17
  gem 'rails_accessibility_testing'
18
+ gem 'rspec-rails', '~> 8.0' # Required for system specs
18
19
  gem 'axe-core-capybara', '~> 4.0'
20
+ gem 'capybara', '~> 3.40'
21
+ gem 'selenium-webdriver', '~> 4.0'
22
+ gem 'webdrivers', '~> 5.0' # Optional but recommended for automatic driver management
19
23
  end
20
24
  ```
21
25
 
26
+ **Important:**
27
+ - You must explicitly add `selenium-webdriver` to your Gemfile. It's not automatically included as a dependency.
28
+ - **RSpec Rails is required** - The generator creates system specs that require `rspec-rails`. If you're using Minitest, you'll need to manually create your accessibility tests.
29
+
22
30
  Then run:
23
31
 
24
32
  ```bash
@@ -36,7 +44,11 @@ rails generate rails_a11y:install
36
44
  This creates:
37
45
  - `config/initializers/rails_a11y.rb` - Configuration
38
46
  - `config/accessibility.yml` - Check settings
47
+ - `spec/system/all_pages_accessibility_spec.rb` - Comprehensive spec that tests all GET routes with smart change detection
39
48
  - Updates `spec/rails_helper.rb` (if using RSpec)
49
+ - Updates `Procfile.dev` - Adds accessibility watch command (optional)
50
+
51
+ **Note:** If you already have system tests set up in your Rails application, you can skip to Step 3. If you need help configuring Capybara or installing Chrome, see the [FAQ section](#troubleshooting) below.
40
52
 
41
53
  ### Step 3: Run Your Tests
42
54
 
@@ -52,7 +64,7 @@ Accessibility checks run automatically on every system test that visits a page.
52
64
 
53
65
  #### Option B: Run Continuously with Procfile (Recommended for Development)
54
66
 
55
- For continuous accessibility checking during development, add to your `Procfile.dev`:
67
+ The generator automatically adds an accessibility watch command to your `Procfile.dev`:
56
68
 
57
69
  ```procfile
58
70
  web: bin/rails server
@@ -73,6 +85,28 @@ This will:
73
85
 
74
86
  The accessibility checker will continuously monitor your pages and alert you to any issues as you develop!
75
87
 
88
+ #### Option C: All Pages Spec with Smart Change Detection
89
+
90
+ The generator creates `spec/system/all_pages_accessibility_spec.rb` which automatically tests all GET routes in your application. This spec includes **smart change detection**:
91
+
92
+ - **Only tests pages when their related files change** - Views, controllers, or helpers
93
+ - **Detects changes via Git** - Uncommitted changes in monitored directories (`app/views`, `app/controllers`, `app/helpers`)
94
+ - **File modification tracking** - Files changed in the last 5 minutes
95
+ - **Layout/helper changes** - Automatically tests all pages when layouts or helpers change (they affect everything)
96
+ - **First run** - Tests all pages on first run (when no changes detected)
97
+ - **Manual override** - Set `TEST_ALL_PAGES=true` to force testing all pages regardless of changes
98
+
99
+ This makes your test suite faster and more focused, only running checks when relevant code changes. The spec automatically:
100
+ - Skips routes that require authentication
101
+ - Handles routes with parameters
102
+ - Filters out API routes and Rails internal routes
103
+ - Provides clear skip messages when pages aren't affected by changes
104
+
105
+ Run it manually:
106
+ ```bash
107
+ bundle exec rspec spec/system/all_pages_accessibility_spec.rb
108
+ ```
109
+
76
110
  ## Your First Accessibility Check
77
111
 
78
112
  Let's see it in action. Create a simple system spec:
@@ -93,13 +127,12 @@ end
93
127
  While checks run automatically after each `visit`, you can also run comprehensive checks explicitly at any point in your test:
94
128
 
95
129
  ```ruby
96
- # spec/system/home_page_accessibility_spec.rb
130
+ # spec/system/my_page_accessibility_spec.rb
97
131
  require 'rails_helper'
98
132
 
99
- RSpec.describe 'Home Page Accessibility', type: :system do
133
+ RSpec.describe 'My Page Accessibility', type: :system do
100
134
  it 'loads the page and runs comprehensive accessibility checks' do
101
135
  visit root_path
102
- expect(page).to have_content('Welcome')
103
136
 
104
137
  # Run comprehensive accessibility checks explicitly
105
138
  # This will fail the test if any accessibility issues are found
@@ -160,14 +193,14 @@ Rails A11y runs **11 comprehensive checks** automatically. These checks are WCAG
160
193
 
161
194
  1. **Form Labels** - All form inputs have associated labels
162
195
  2. **Image Alt Text** - All images have descriptive alt attributes (including empty alt="" detection)
163
- 3. **Interactive Elements** - Buttons, links, and other interactive elements have accessible names
164
- 4. **Heading Hierarchy** - Proper h1-h6 structure without skipping levels
196
+ 3. **Interactive Elements** - Buttons, links, and other interactive elements have accessible names (including links with images that have alt text)
197
+ 4. **Heading Hierarchy** - Proper h1-h6 structure without skipping levels (detects missing h1, skipped levels, and h2+ without h1)
165
198
  5. **Keyboard Accessibility** - All interactive elements are keyboard accessible
166
199
  6. **ARIA Landmarks** - Proper use of ARIA landmark roles for page structure
167
200
  7. **Form Error Associations** - Form errors are properly linked to their form fields
168
201
  8. **Table Structure** - Tables have proper headers and structure
169
202
  9. **Duplicate IDs** - No duplicate ID attributes on the page
170
- 10. **Skip Links** - Skip navigation links are present for keyboard users
203
+ 10. **Skip Links** - Skip navigation links are present for keyboard users (detects various patterns: `skip-link`, `skiplink`, `href="#main"`, `href="#maincontent"`, etc.)
171
204
  11. **Color Contrast** - Text meets WCAG contrast requirements (optional, disabled by default for performance)
172
205
 
173
206
  ### What `check_comprehensive_accessibility` Does
@@ -250,6 +283,135 @@ end
250
283
  - **Check out [Writing Accessible Views](writing_accessible_views_in_rails.md)** for best practices
251
284
  - **See [Working with Designers](working_with_designers_and_content_authors.md)** for team collaboration
252
285
 
286
+ ## Troubleshooting
287
+
288
+ ### How do I configure Capybara for system tests?
289
+
290
+ If you don't already have system tests configured, you need to set up Capybara with a Selenium driver. Create `spec/support/driver.rb`:
291
+
292
+ ```ruby
293
+ # spec/support/driver.rb
294
+ require 'selenium-webdriver'
295
+ require 'capybara/rails'
296
+ require 'capybara/rspec'
297
+
298
+ # Configure Chrome options
299
+ browser_options = Selenium::WebDriver::Chrome::Options.new
300
+ browser_options.add_argument('--window-size=1920,1080')
301
+ browser_options.add_argument('--headless') unless ENV['SHOW_TEST_BROWSER']
302
+
303
+ # Register the driver
304
+ Capybara.register_driver :selenium_chrome_headless do |app|
305
+ Capybara::Selenium::Driver.new(
306
+ app,
307
+ browser: :chrome,
308
+ options: browser_options
309
+ )
310
+ end
311
+
312
+ # Set as default JavaScript driver
313
+ Capybara.javascript_driver = :selenium_chrome_headless
314
+
315
+ # Configure RSpec to use the driver for system tests
316
+ RSpec.configure do |config|
317
+ config.before(:each, type: :system) do
318
+ driven_by :selenium_chrome_headless
319
+ end
320
+ end
321
+ ```
322
+
323
+ **Note for Rails 8:** Rails 8 uses `driven_by` to configure system tests. Make sure your `spec/support/driver.rb` is loaded by `rails_helper.rb` (it should be automatically loaded if it's in the `spec/support/` directory).
324
+
325
+ ### How do I install Chrome/Chromium?
326
+
327
+ System tests require Chrome or Chromium to be installed on your system:
328
+
329
+ **macOS:**
330
+ ```bash
331
+ brew install --cask google-chrome
332
+ # or for Chromium:
333
+ brew install --cask chromium
334
+ ```
335
+
336
+ **Linux (Ubuntu/Debian):**
337
+ ```bash
338
+ sudo apt-get update
339
+ sudo apt-get install -y google-chrome-stable
340
+ # or for Chromium:
341
+ sudo apt-get install -y chromium-browser
342
+ ```
343
+
344
+ **Windows:**
345
+ Download and install Chrome from [google.com/chrome](https://www.google.com/chrome/)
346
+
347
+ The `webdrivers` gem will automatically download and manage the ChromeDriver binary for you.
348
+
349
+ ### Error: `uninitialized constant Selenium::WebDriver::DriverFinder`
350
+
351
+ This error typically occurs when:
352
+ 1. **Missing selenium-webdriver gem** - Make sure you've added `gem 'selenium-webdriver', '~> 4.0'` to your Gemfile
353
+ 2. **Version incompatibility** - Ensure you're using compatible versions:
354
+ - `selenium-webdriver` ~> 4.0 (4.6.0+ recommended for Rails 8)
355
+ - `webdrivers` ~> 5.0 (if using webdrivers)
356
+ - `capybara` ~> 3.40
357
+
358
+ **Solution:**
359
+ ```bash
360
+ # Update your Gemfile
361
+ gem 'selenium-webdriver', '~> 4.10'
362
+ gem 'webdrivers', '~> 5.3'
363
+ gem 'capybara', '~> 3.40'
364
+
365
+ # Then run
366
+ bundle update selenium-webdriver webdrivers capybara
367
+ ```
368
+
369
+ ### Error: Chrome/ChromeDriver not found
370
+
371
+ **Solution:**
372
+ 1. Make sure Chrome is installed (see Step 3 above)
373
+ 2. If using `webdrivers` gem, it should auto-download ChromeDriver. If not:
374
+ ```bash
375
+ bundle exec webdrivers chrome
376
+ ```
377
+ 3. For manual installation, download from [ChromeDriver downloads](https://chromedriver.chromium.org/downloads)
378
+
379
+ ### System tests not running
380
+
381
+ **Check:**
382
+ 1. Your spec has `type: :system` metadata
383
+ 2. `spec/support/driver.rb` exists and is properly configured
384
+ 3. `spec/rails_helper.rb` loads support files (should be automatic)
385
+ 4. Chrome is installed and accessible
386
+
387
+ ### Tests are slow
388
+
389
+ Disable expensive checks in development:
390
+ ```yaml
391
+ # config/accessibility.yml
392
+ development:
393
+ checks:
394
+ color_contrast: false # Disable expensive color contrast checks
395
+ ```
396
+
397
+ ## Version Compatibility
398
+
399
+ For best results, use these compatible versions:
400
+
401
+ | Component | Recommended Version | Minimum Version | Required |
402
+ |-----------|-------------------|-----------------|----------|
403
+ | Ruby | 3.1+ | 3.0+ | Yes |
404
+ | Rails | 7.1+ / 8.0+ | 6.0+ | Yes |
405
+ | **RSpec Rails** | **8.0+** | **6.0+** | **Yes (for system specs)** |
406
+ | Capybara | ~> 3.40 | 3.0+ | Yes |
407
+ | selenium-webdriver | ~> 4.10 | 4.0+ | Yes |
408
+ | webdrivers | ~> 5.3 | 5.0+ | Optional |
409
+
410
+ **Rails 8 Notes:**
411
+ - Rails 8 requires `selenium-webdriver` 4.6.0+ for `DriverFinder` support
412
+ - Make sure your `driven_by` configuration is in `spec/support/driver.rb`
413
+ - Rails 8 system tests use `driven_by` instead of direct Capybara configuration
414
+
253
415
  ## Common Questions
254
416
 
255
417
  ### Q: Do I need to change my existing tests?
@@ -271,8 +433,8 @@ end
271
433
  ## Getting Help
272
434
 
273
435
  - **Documentation:** See the main [README](../README.md)
274
- - **Issues:** [GitHub Issues](https://github.com/your-org/rails-a11y/issues)
275
- - **Email:** support@example.com
436
+ - **Issues:** [GitHub Issues](https://github.com/rayraycodes/rails-accessibility-testing/issues)
437
+ - **Email:** imregan@umich.edu
276
438
 
277
439
  ---
278
440
 
@@ -12,18 +12,19 @@ System specs are the **recommended and most reliable** way to run accessibility
12
12
 
13
13
  ## Quick Setup
14
14
 
15
- ### 1. Create System Specs
15
+ ### 1. Use the Generated Specs
16
16
 
17
- Create system specs for the pages you want to test. Name them with `_accessibility_spec.rb` suffix for clarity:
17
+ The generator creates `spec/system/all_pages_accessibility_spec.rb` which automatically tests all GET routes in your application with **smart change detection**. This spec only tests pages when their related files (views, controllers, helpers) have changed, making it fast and focused.
18
+
19
+ You can also create custom system specs for specific pages. Name them with `_accessibility_spec.rb` suffix for clarity:
18
20
 
19
21
  ```ruby
20
- # spec/system/home_page_accessibility_spec.rb
22
+ # spec/system/my_page_accessibility_spec.rb
21
23
  require 'rails_helper'
22
24
 
23
- RSpec.describe 'Home Page Accessibility', type: :system do
25
+ RSpec.describe 'My Page Accessibility', type: :system do
24
26
  it 'loads the page and runs comprehensive accessibility checks' do
25
27
  visit root_path
26
- expect(page).to have_content('Biorepository').or have_content('Welcome')
27
28
 
28
29
  # Run comprehensive accessibility checks
29
30
  # This will fail the test if any accessibility issues are found
@@ -37,27 +38,27 @@ end
37
38
 
38
39
  The gem automatically runs comprehensive accessibility checks after each `visit` in system specs. You don't need to call `check_comprehensive_accessibility` manually unless you want to run checks at a specific point in your test.
39
40
 
40
- ### 3. Add to Procfile.dev (Optional)
41
+ ### 3. Continuous Testing with Procfile (Optional)
41
42
 
42
- For continuous testing during development, add to your `Procfile.dev`:
43
+ The generator automatically adds an accessibility watch command to your `Procfile.dev`:
43
44
 
44
45
  ```ruby
45
- web: $(bundle show rails_accessibility_testing)/exe/rails_server_safe
46
+ web: bin/rails server
46
47
  css: bin/rails dartsass:watch
47
48
  a11y: while true; do bundle exec rspec spec/system/*_accessibility_spec.rb; sleep 30; done
48
49
  ```
49
50
 
50
- This will run your accessibility specs every 30 seconds while you develop.
51
+ This will run your accessibility specs every 30 seconds while you develop. The `all_pages_accessibility_spec.rb` uses smart change detection to only test pages when their related files change, making it fast and focused.
51
52
 
52
53
  ## Example Specs
53
54
 
54
55
  ### Basic Page Check
55
56
 
56
57
  ```ruby
57
- # spec/system/home_page_accessibility_spec.rb
58
+ # spec/system/my_page_accessibility_spec.rb
58
59
  require 'rails_helper'
59
60
 
60
- RSpec.describe 'Home Page Accessibility', type: :system do
61
+ RSpec.describe 'My Page Accessibility', type: :system do
61
62
  it 'runs accessibility checks on the home page' do
62
63
  visit root_path
63
64
  # ✅ Comprehensive accessibility checks run automatically after this test!
@@ -189,7 +190,7 @@ bundle exec rspec spec/system/*_accessibility_spec.rb
189
190
  ### Run Specific Spec
190
191
 
191
192
  ```bash
192
- bundle exec rspec spec/system/home_page_accessibility_spec.rb
193
+ bundle exec rspec spec/system/all_pages_accessibility_spec.rb
193
194
  ```
194
195
 
195
196
  ### Run with Documentation Format
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  **The RSpec + RuboCop of accessibility for Rails. Catch WCAG violations before they reach production.**
9
9
 
10
- **Current Version:** 1.4.2
10
+ **Current Version:** 1.5.0
11
11
 
12
12
  📖 **[📚 Full Documentation](https://rayraycodes.github.io/rails-accessibility-testing/)** | [💻 GitHub](https://github.com/rayraycodes/rails-accessibility-testing) | [💎 RubyGems](https://rubygems.org/gems/rails_accessibility_testing)
13
13
 
@@ -19,16 +19,40 @@ Rails Accessibility Testing fills a critical gap in the Rails testing ecosystem.
19
19
 
20
20
  ## ✨ Features
21
21
 
22
+ ### Core Capabilities
22
23
  - 🚀 **Zero Configuration** - Works out of the box with smart defaults
23
24
  - 🎯 **11+ Comprehensive Checks** - WCAG 2.1 AA aligned
24
- - 📍 **File Location Hints** - Know exactly which view file to fix
25
+ - 📍 **Precise File Location** - Know exactly which view file or partial to fix
25
26
  - 🔧 **Actionable Error Messages** - Code examples showing how to fix issues
26
- - ⚡ **Smart Change Detection** - Only runs when relevant code changes
27
27
  - 🎨 **Beautiful CLI** - Human-readable and JSON reports
28
28
  - 🔌 **Rails Generator** - One command setup
29
29
  - 🧪 **RSpec & Minitest** - Works with both test frameworks
30
30
  - ⚙️ **YAML Configuration** - Profile-based config (dev/test/CI)
31
- - 📚 **Comprehensive Guides** - Learn as you go
31
+
32
+ ### 🆕 Version 1.5.0 Highlights
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`)
36
+ - **Controller directory scanning**: Searches all view files to find the correct template
37
+ - **Fuzzy matching**: Handles variations and naming conventions
38
+
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
44
+
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
32
56
 
33
57
  ## 🚀 Quick Start
34
58
 
@@ -39,12 +63,17 @@ Add to your `Gemfile`:
39
63
  ```ruby
40
64
  group :development, :test do
41
65
  gem 'rails_accessibility_testing'
66
+ gem 'rspec-rails', '~> 8.0' # Required for system specs
42
67
  gem 'axe-core-capybara', '~> 4.0'
43
- # Your existing Capybara, selenium-webdriver, webdrivers gems
44
- # The gem has minimal dependencies - you control your own driver setup
68
+ gem 'capybara', '~> 3.40'
69
+ gem 'selenium-webdriver', '~> 4.0'
70
+ gem 'webdrivers', '~> 5.0' # Optional but recommended
71
+ gem 'csv' # Required for Ruby 3.3+ (CSV removed from standard library in Ruby 3.4)
45
72
  end
46
73
  ```
47
74
 
75
+ **Important:** You must explicitly add `selenium-webdriver` and `csv` (for Ruby 3.3+) to your Gemfile. The gem has minimal dependencies - you control your own driver setup.
76
+
48
77
  Then run:
49
78
 
50
79
  ```bash
@@ -62,7 +91,9 @@ rails generate rails_a11y:install
62
91
  This creates:
63
92
  - `config/initializers/rails_a11y.rb` - Configuration
64
93
  - `config/accessibility.yml` - Check settings
94
+ - `spec/system/all_pages_accessibility_spec.rb` - Comprehensive spec that dynamically tests all GET routes
65
95
  - Updates `spec/rails_helper.rb` (if using RSpec)
96
+ - Updates `Procfile.dev` with accessibility watch command (if present)
66
97
 
67
98
  ### Setup (Option 2: Manual)
68
99
 
@@ -97,7 +128,7 @@ require 'rails_helper'
97
128
  RSpec.describe 'Home Page Accessibility', type: :system do
98
129
  it 'loads successfully and passes comprehensive accessibility checks' do
99
130
  visit root_path
100
- expect(page).to have_content('Biorepository').or have_content('Welcome')
131
+ expect(page).to have_content('Welcome')
101
132
 
102
133
  # Run comprehensive accessibility checks
103
134
  check_comprehensive_accessibility
@@ -108,25 +139,22 @@ end
108
139
 
109
140
  **Accessibility checks run automatically after each `visit` in system specs!**
110
141
 
111
- #### Continuous Testing with Procfile (Recommended for Development)
112
-
113
- For continuous accessibility checking during development, add to your `Procfile.dev`:
114
-
115
- ```procfile
116
- web: bin/rails server
117
- css: bin/rails dartsass:watch
118
- a11y: while true; do bundle exec rspec spec/system/*_accessibility_spec.rb; sleep 30; done
119
- ```
120
-
121
- Then run:
142
+ ### All Pages Accessibility Spec
122
143
 
123
- ```bash
124
- bin/dev
125
- ```
144
+ The generator creates `spec/system/all_pages_accessibility_spec.rb` which automatically tests all GET routes in your application. The spec:
126
145
 
127
- This will automatically run accessibility checks every 30 seconds on all `*_accessibility_spec.rb` files, giving you continuous feedback as you develop!
146
+ - **Dynamically discovers routes** at runtime - works for any Rails app
147
+ - **Smart change detection** - Only tests pages when their related files (views, controllers, helpers, CSS/JS) have changed
148
+ - **First-run optimization** - Tests all pages on first run, then only changed files
149
+ - **Intelligent skipping** - Skips routes that require authentication, have errors, or aren't accessible
150
+ - **Friendly summaries** - Shows passed/failed/skipped counts with clear reasons
128
151
 
129
- 📖 **[See the full System Specs Guide](GUIDES/system_specs_for_accessibility.md)** for detailed examples and best practices.
152
+ The spec automatically:
153
+ - Tests all GET routes (filters out API, internal Rails routes)
154
+ - Handles routes with parameters by substituting test values
155
+ - Detects view files even when action names don't match
156
+ - Shows which files changed and which pages are affected
157
+ - Provides helpful tips and next steps
130
158
 
131
159
  ### Automatic Checks
132
160
 
@@ -166,6 +194,18 @@ it "meets all accessibility standards" do
166
194
  end
167
195
  ```
168
196
 
197
+ ### Continuous Development Testing
198
+
199
+ Add to your `Procfile.dev`:
200
+
201
+ ```ruby
202
+ web: $(bundle show rails_accessibility_testing)/exe/rails_server_safe
203
+ css: bin/rails dartsass:watch
204
+ a11y: while true; do bin/check_a11y_changes && (test -f bin/rspec && bin/rspec spec/system/*_accessibility_spec.rb --format progress --no-profile || bundle exec rspec spec/system/*_accessibility_spec.rb --format progress --no-profile) 2>&1 | grep -v "^[[:space:]]*[0-9]*)[[:space:]]*All Pages Accessibility checks accessibility" | grep -v "# Skipping" || echo '⏭️ No changes detected, skipping tests'; sleep 30; done
205
+ ```
206
+
207
+ This runs accessibility tests every 30 seconds, but only when files have changed!
208
+
169
209
  ### CLI Usage
170
210
 
171
211
  Run checks against URLs or Rails routes:
@@ -193,14 +233,14 @@ The gem automatically runs **11 comprehensive accessibility checks**:
193
233
 
194
234
  1. ✅ **Form Labels** - All form inputs have associated labels
195
235
  2. ✅ **Image Alt Text** - All images have descriptive alt attributes
196
- 3. ✅ **Interactive Elements** - Buttons, links have accessible names
197
- 4. ✅ **Heading Hierarchy** - Proper h1-h6 structure
236
+ 3. ✅ **Interactive Elements** - Buttons, links have accessible names (including links with images that have alt text)
237
+ 4. ✅ **Heading Hierarchy** - Proper h1-h6 structure (detects missing h1, multiple h1s, skipped levels, and h2+ without h1)
198
238
  5. ✅ **Keyboard Accessibility** - All interactive elements keyboard accessible
199
239
  6. ✅ **ARIA Landmarks** - Proper use of ARIA landmark roles
200
240
  7. ✅ **Form Error Associations** - Errors linked to form fields
201
241
  8. ✅ **Table Structure** - Tables have proper headers
202
242
  9. ✅ **Duplicate IDs** - No duplicate ID attributes
203
- 10. ✅ **Skip Links** - Skip navigation links present
243
+ 10. ✅ **Skip Links** - Skip navigation links present (detects various patterns)
204
244
  11. ✅ **Color Contrast** - Text meets contrast requirements (optional)
205
245
 
206
246
  ## ⚙️ Configuration
@@ -218,7 +258,7 @@ checks:
218
258
  form_labels: true
219
259
  image_alt_text: true
220
260
  interactive_elements: true
221
- heading_hierarchy: true
261
+ heading: true # Note: renamed from heading_hierarchy in 1.5.0
222
262
  keyboard_accessibility: true
223
263
  aria_landmarks: true
224
264
  form_errors: true
@@ -265,7 +305,7 @@ end
265
305
 
266
306
  ## 📋 Example Error Output
267
307
 
268
- When accessibility issues are found, you get detailed, actionable errors:
308
+ When accessibility issues are found, you get detailed, actionable errors with precise file locations:
269
309
 
270
310
  ```
271
311
  ======================================================================
@@ -273,9 +313,10 @@ When accessibility issues are found, you get detailed, actionable errors:
273
313
  ======================================================================
274
314
 
275
315
  📄 Page Being Tested:
276
- URL: http://localhost:3000/
277
- Path: /
278
- 📝 Likely View File: app/views/shared/_header.html.erb
316
+ URL: http://localhost:3000/items/search
317
+ Path: /items/search
318
+ 📝 View File: app/views/items/search_result.html.erb
319
+ 📝 Partial: app/views/layouts/_advance_search.html.erb
279
320
 
280
321
  📍 Element Details:
281
322
  Tag: <img>
@@ -295,10 +336,40 @@ When accessibility issues are found, you get detailed, actionable errors:
295
336
  💡 Best Practice: All images must have alt attribute.
296
337
  Use empty alt="" only for purely decorative images.
297
338
 
298
- 📖 WCAG Reference: https://www.w3.org/WAI/WCAG21/Understanding/
339
+ 📖 WCAG Reference: https://www.w3.org/WAI/WCAG21/Understanding/non-text-content.html
299
340
  ======================================================================
300
341
  ```
301
342
 
343
+ **Notice:** The error shows both the main view file (`search_result.html.erb`) and the partial where the issue actually occurs (`_advance_search.html.erb`). This makes fixing issues much faster!
344
+
345
+ ## 🚀 Performance Features
346
+
347
+ ### Smart Change Detection
348
+
349
+ The gem automatically detects when files change and only tests affected pages:
350
+
351
+ - **View files**: Tests pages when their view files change
352
+ - **Partials**: Tests pages that render changed partials
353
+ - **Controllers**: Tests all routes for a controller when the controller changes
354
+ - **Helpers**: Tests all pages when helpers change (they can affect any view)
355
+ - **Assets**: Tests all pages when CSS/JS changes (can affect accessibility globally)
356
+
357
+ ### Page Scanning Cache
358
+
359
+ Prevents duplicate scans of the same page during a test run:
360
+
361
+ - **Automatic caching**: Each page is scanned once per test suite execution
362
+ - **Efficient tracking**: Uses page path or URL as cache key
363
+ - **Silent skipping**: Already-scanned pages are skipped without output
364
+ - **Manual reset**: Use `reset_scanned_pages_cache` if needed
365
+
366
+ ### First-Run Optimization
367
+
368
+ - **Initial baseline**: Tests all pages on first run to establish baseline
369
+ - **Subsequent runs**: Only tests changed files for faster feedback
370
+ - **Marker file**: Creates `.rails_a11y_initialized` to track first run
371
+ - **Force all pages**: Set `TEST_ALL_PAGES=true` to test all pages anytime
372
+
302
373
  ## 📚 Documentation
303
374
 
304
375
  ### 🌐 Online Documentation
@@ -334,9 +405,12 @@ View at `doc/index.html`
334
405
 
335
406
  Rails Accessibility Testing is built with a clean, modular architecture:
336
407
 
337
- - **Rule Engine** - Evaluates accessibility checks
338
- - **Check Definitions** - WCAG-aligned check implementations
408
+ - **Rule Engine** - Evaluates accessibility checks with configurable profiles
409
+ - **Check Definitions** - WCAG-aligned check implementations (11+ checks)
339
410
  - **Violation Collector** - Aggregates and formats violations
411
+ - **View File Detection** - Intelligent detection of view files and partials
412
+ - **Change Detector** - Smart detection of file changes and their impact
413
+ - **Page Scanning Cache** - Prevents duplicate scans for performance
340
414
  - **Rails Integration** - Railtie, RSpec, Minitest helpers
341
415
  - **CLI** - Command-line interface for URL/route scanning
342
416
  - **Configuration** - YAML-based config with profiles
@@ -347,13 +421,42 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.
347
421
 
348
422
  - Ruby 3.0+ (3.1+ recommended)
349
423
  - Rails 6.0+ (7.1+ recommended)
350
- - RSpec Rails 6.0+ (for RSpec) or Minitest (for Minitest)
424
+ - **RSpec Rails 6.0+ (required for system specs)** or Minitest (for Minitest)
351
425
  - Capybara 3.0+ (provided by your project)
352
426
  - selenium-webdriver 4.0+ (provided by your project, for system specs)
353
427
  - webdrivers (optional, provided by your project, for automatic driver management)
428
+ - **csv gem** (required for Ruby 3.3+, as CSV is removed from standard library in Ruby 3.4)
354
429
  - Chrome/Chromium browser
355
430
 
356
- **Note:** As of version 1.2.0, the gem has minimal dependencies. You provide and configure Capybara, selenium-webdriver, and webdrivers in your own Gemfile, giving you full control over your test driver setup.
431
+ **Note:** The generator creates system specs that require `rspec-rails`. If you're using Minitest, you'll need to manually create your accessibility tests.
432
+
433
+ **Note:** As of version 1.2.0, the gem has minimal dependencies. You provide and configure Capybara, selenium-webdriver, webdrivers, and csv in your own Gemfile, giving you full control over your test driver setup.
434
+
435
+ ## 🆕 What's New in 1.5.0
436
+
437
+ ### Major Improvements
438
+
439
+ 1. **Smart View File Detection**
440
+ - Automatically finds view files even when action names don't match
441
+ - Scans controller directories intelligently
442
+ - Handles edge cases and naming variations
443
+
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**
450
+ - Page scanning cache prevents duplicate work
451
+ - Smart change detection only tests affected pages
452
+ - First-run optimization for faster initial setup
453
+
454
+ 4. **Enhanced Developer Experience**
455
+ - Friendly test summaries with clear counts and reasons
456
+ - Better error messages with precise file locations
457
+ - Cleaner output with suppressed verbose messages
458
+
459
+ See [CHANGELOG.md](CHANGELOG.md) for complete details.
357
460
 
358
461
  ## 🤝 Contributing
359
462