From 5e6cfba35c12b8a25941bd88e92829fba4fc63dc Mon Sep 17 00:00:00 2001 From: Matheus Richard Date: Tue, 22 Sep 2026 15:01:33 -0300 Subject: [PATCH] Resolve the Capybara session when the audit runs The engine builds the auditor inside a `before` hook. It passes the session that is current at that moment. A host suite can select its driver with `driven_by` from a `before` hook of its own. That hook registers later, so it runs later. The auditor then holds the default `:rack_test` session while the example runs against a real browser. Every audit fails with `Capybara::NotSupportedByDriverError` on the first `visit`. This commit passes the test to the auditor instead of the session. The auditor asks the test for `page` when it audits, so it always uses the session that is current at that moment. The reporters already receive the test, so the two constructor arguments now match. The new spec calls `driven_by` from a plain `before` hook. It fails on `main` with the error above and passes with this change. The new test visits a page inside `using_session`. On `main`, the auditor audits the blank page of the first session, so the test fails. It passes with this change. --- CHANGELOG.md | 2 ++ lib/capybara_accessibility_audit/axe_auditor.rb | 14 +++++++++----- lib/capybara_accessibility_audit/engine.rb | 4 ++-- spec/system/driven_by_in_a_before_hook_spec.rb | 11 +++++++++++ test/system/audit_assertions_test.rb | 6 ++++++ 5 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 spec/system/driven_by_in_a_before_hook_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2bb95..dd26916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Resolve the Capybara session when the audit runs, so that a suite that calls + `driven_by` from its own `before` hook audits through the selected driver - Send the audit options to the browser as JSON values, so that the `:playwright` driver accepts `according_to` and `checking_only` - Add support for `:cuprite` and `:playwright` system test drivers diff --git a/lib/capybara_accessibility_audit/axe_auditor.rb b/lib/capybara_accessibility_audit/axe_auditor.rb index b6243b9..90d27b7 100644 --- a/lib/capybara_accessibility_audit/axe_auditor.rb +++ b/lib/capybara_accessibility_audit/axe_auditor.rb @@ -7,8 +7,8 @@ module CapybaraAccessibilityAudit class AxeAuditor class_attribute :source, instance_accessor: false, default: Axe::Configuration.instance.jslib - def initialize(page, reporter) - @page = page + def initialize(test, reporter) + @test = test @reporter = reporter end @@ -22,10 +22,14 @@ def audit(**options) private + def page + @test.page + end + def run(config) context, options = split(config) - @page.evaluate_async_script <<~JS, context.as_json, options.as_json + page.evaluate_async_script <<~JS, context.as_json, options.as_json const [ context, options, callback ] = arguments axe.run(context, options).then(callback) @@ -47,11 +51,11 @@ def split(config) end def install - @page.execute_script(self.class.source) unless installed? + page.execute_script(self.class.source) unless installed? end def installed? - @page.evaluate_script <<~JS + page.evaluate_script <<~JS "axe" in window && typeof axe.run === "function" JS end diff --git a/lib/capybara_accessibility_audit/engine.rb b/lib/capybara_accessibility_audit/engine.rb index 41adfdd..b4dea6e 100644 --- a/lib/capybara_accessibility_audit/engine.rb +++ b/lib/capybara_accessibility_audit/engine.rb @@ -25,7 +25,7 @@ class Engine < ::Rails::Engine auditor_class = app.config.capybara_accessibility_audit.auditor reporter_class = CapybaraAccessibilityAudit.reporter_class(accessibility_audit_reporter) - self.accessibility_audit_auditor = auditor_class.new(page, reporter_class.new(self)) + self.accessibility_audit_auditor = auditor_class.new(self, reporter_class.new(self)) end end end @@ -46,7 +46,7 @@ class Engine < ::Rails::Engine auditor_class = app.config.capybara_accessibility_audit.auditor reporter_class = CapybaraAccessibilityAudit.reporter_class(accessibility_audit_reporter) - self.accessibility_audit_auditor = auditor_class.new(page, reporter_class.new(self)) + self.accessibility_audit_auditor = auditor_class.new(self, reporter_class.new(self)) end config.before(type: :system, &configure) diff --git a/spec/system/driven_by_in_a_before_hook_spec.rb b/spec/system/driven_by_in_a_before_hook_spec.rb new file mode 100644 index 0000000..083bf86 --- /dev/null +++ b/spec/system/driven_by_in_a_before_hook_spec.rb @@ -0,0 +1,11 @@ +require "spec_helper" + +RSpec.describe "Audit assertions", type: :system do + before { driven_by Capybara.javascript_driver } + + it "audits with the session that is current when the audit runs" do + assert_rule_violation "label: Form elements must have labels" do + visit violations_path(rules: %w[label]) + end + end +end diff --git a/test/system/audit_assertions_test.rb b/test/system/audit_assertions_test.rb index 4c678b9..5854757 100644 --- a/test/system/audit_assertions_test.rb +++ b/test/system/audit_assertions_test.rb @@ -40,6 +40,12 @@ class AuditAssertionsTest < ApplicationSystemTestCase end end + test "flunks on violations detected within #using_session" do + assert_rule_violation "label: Form elements must have labels" do + using_session(:other) { visit violations_path(rules: %w[label]) } + end + end + test "ignores violations within a matching skip_accessibility_violations block" do skip_accessibility_violations("label") { visit violations_path(rules: %w[label]) } skip_accessibility_violations(%w[label]) { visit violations_path(rules: %w[label]) }