axe-cuprite 0.1.0 → 0.1.1
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/axe/cuprite/injector.rb +8 -13
- data/lib/axe/cuprite/rspec/matchers.rb +7 -7
- data/lib/axe/cuprite/rspec.rb +2 -2
- data/lib/axe/cuprite/runner.rb +1 -3
- data/lib/axe/cuprite/version.rb +1 -1
- metadata +71 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1005023d8e3178edd24de983e954208d297ee0ca720f33ba822f14c33861b17f
|
|
4
|
+
data.tar.gz: 5b0b13f67c92e8b89d1d4b4f2f9b4957ae71690d60eeb006edd2e9239bd89dd7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 439317e53b00d1f6a4f4c275f02b5caa9c6d0add981079b809a3363c937fab3431226db540f6163ad908a47b0869782db0b0bfd98f5b229bb121b45b9733acb6
|
|
7
|
+
data.tar.gz: 9ade47a886507d6349a680abd9446fc5191048172b1a40f660a694dc93afa0841528d73a5eb4e281d30960fa4fad4b72e87d359a969c3e15274f9213c76c9587
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.1] - 2026-06-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- GitHub Actions CI (`.github/workflows/ci.yml`): runs the RSpec suite under
|
|
14
|
+
Cuprite/headless Chrome across Ruby 3.0–3.4 and a RuboCop lint job, on every
|
|
15
|
+
push to `main` and all pull requests.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- `Injector#inject_source!` no longer appends a second `<script>` tag when a hard
|
|
19
|
+
injection failure occurs. The retry flow is now a single linear path
|
|
20
|
+
(`execute_script` → check → `add_script_tag` fallback → check → raise), so the
|
|
21
|
+
fallback runs at most once.
|
|
22
|
+
|
|
8
23
|
## [0.1.0] - 2026-06-06
|
|
9
24
|
|
|
10
25
|
### Added
|
data/lib/axe/cuprite/injector.rb
CHANGED
|
@@ -76,20 +76,17 @@ module AxeCuprite
|
|
|
76
76
|
|
|
77
77
|
begin
|
|
78
78
|
@page.execute_script(source)
|
|
79
|
-
rescue StandardError
|
|
80
|
-
|
|
79
|
+
rescue StandardError
|
|
80
|
+
nil
|
|
81
81
|
end
|
|
82
|
+
return true if injected?
|
|
82
83
|
|
|
84
|
+
try_add_script_tag(source)
|
|
83
85
|
return true if injected?
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
else
|
|
89
|
-
raise InjectionError,
|
|
90
|
-
"axe-core did not load after injection. A strict Content-Security-Policy " \
|
|
91
|
-
"may be blocking script injection on the page under test."
|
|
92
|
-
end
|
|
87
|
+
raise InjectionError,
|
|
88
|
+
"axe-core did not load after injection. The page may be blocking " \
|
|
89
|
+
"script injection (e.g. a strict Content-Security-Policy)."
|
|
93
90
|
end
|
|
94
91
|
|
|
95
92
|
# Run axe and return a Results object. Injects on demand if needed.
|
|
@@ -98,9 +95,7 @@ module AxeCuprite
|
|
|
98
95
|
ensure_present!
|
|
99
96
|
|
|
100
97
|
raw = evaluate_axe(context, options, timeout)
|
|
101
|
-
if raw.is_a?(Hash) && raw["error"]
|
|
102
|
-
raise AxeRunError, "axe.run failed: #{raw["error"]}"
|
|
103
|
-
end
|
|
98
|
+
raise AxeRunError, "axe.run failed: #{raw["error"]}" if raw.is_a?(Hash) && raw["error"]
|
|
104
99
|
|
|
105
100
|
Results.new(raw)
|
|
106
101
|
end
|
|
@@ -27,7 +27,7 @@ module AxeCuprite
|
|
|
27
27
|
@skip_rules = []
|
|
28
28
|
@tags = []
|
|
29
29
|
@run_options = {}
|
|
30
|
-
@timeout
|
|
30
|
+
@timeout = nil
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# --- chainable DSL ----------------------------------------------------
|
|
@@ -153,8 +153,8 @@ module AxeCuprite
|
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
unless @skip_rules.empty?
|
|
156
|
-
opts[:rules] = Normalize.rules(@skip_rules).
|
|
157
|
-
|
|
156
|
+
opts[:rules] = Normalize.rules(@skip_rules).to_h do |id|
|
|
157
|
+
[id, { enabled: false }]
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
160
|
|
|
@@ -167,8 +167,8 @@ module AxeCuprite
|
|
|
167
167
|
rule_count = @violations.length
|
|
168
168
|
node_count = @violations.sum { |v| v.nodes.length }
|
|
169
169
|
"expected page to be axe-clean, but found #{rule_count} " \
|
|
170
|
-
"#{pluralize(rule_count,
|
|
171
|
-
"#{pluralize(node_count,
|
|
170
|
+
"#{pluralize(rule_count, "violation")} across #{node_count} " \
|
|
171
|
+
"#{pluralize(node_count, "element")}:"
|
|
172
172
|
end
|
|
173
173
|
|
|
174
174
|
def details
|
|
@@ -179,7 +179,7 @@ module AxeCuprite
|
|
|
179
179
|
lines = []
|
|
180
180
|
impact = violation.impact || "n/a"
|
|
181
181
|
lines << " ● [#{impact}] #{violation.id} — #{violation.help} " \
|
|
182
|
-
"(#{violation.nodes.length} #{pluralize(violation.nodes.length,
|
|
182
|
+
"(#{violation.nodes.length} #{pluralize(violation.nodes.length, "element")})"
|
|
183
183
|
lines << " #{violation.help_url}" if violation.help_url
|
|
184
184
|
|
|
185
185
|
violation.nodes.first(MAX_NODES).each do |node|
|
|
@@ -187,7 +187,7 @@ module AxeCuprite
|
|
|
187
187
|
end
|
|
188
188
|
|
|
189
189
|
remaining = violation.nodes.length - MAX_NODES
|
|
190
|
-
lines << " … and #{remaining} more #{pluralize(remaining,
|
|
190
|
+
lines << " … and #{remaining} more #{pluralize(remaining, "element")}" if remaining.positive?
|
|
191
191
|
lines.join("\n")
|
|
192
192
|
end
|
|
193
193
|
|
data/lib/axe/cuprite/rspec.rb
CHANGED
|
@@ -20,8 +20,8 @@ module AxeCuprite
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
if defined?(
|
|
24
|
-
|
|
23
|
+
if defined?(RSpec) && RSpec.respond_to?(:configure)
|
|
24
|
+
RSpec.configure do |config|
|
|
25
25
|
config.include AxeCuprite::RSpec::DSL
|
|
26
26
|
end
|
|
27
27
|
end
|
data/lib/axe/cuprite/runner.rb
CHANGED
|
@@ -56,9 +56,7 @@ module AxeCuprite
|
|
|
56
56
|
# default_tags become a tag-based runOnly, but only if nothing already
|
|
57
57
|
# scopes runOnly (an explicit rule/tag selection takes precedence).
|
|
58
58
|
tags = Normalize.tags(@configuration.default_tags)
|
|
59
|
-
if !opts.key?("runOnly") && !tags.empty?
|
|
60
|
-
opts["runOnly"] = { "type" => "tag", "values" => tags }
|
|
61
|
-
end
|
|
59
|
+
opts["runOnly"] = { "type" => "tag", "values" => tags } if !opts.key?("runOnly") && !tags.empty?
|
|
62
60
|
|
|
63
61
|
# global skip_rules disable rules, without clobbering an explicit caller
|
|
64
62
|
# setting for the same rule.
|
data/lib/axe/cuprite/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: axe-cuprite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Abdullah Hashim
|
|
@@ -58,33 +58,25 @@ dependencies:
|
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
59
|
version: '0.17'
|
|
60
60
|
- !ruby/object:Gem::Dependency
|
|
61
|
-
name:
|
|
61
|
+
name: puma
|
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
|
-
- - "
|
|
65
|
-
- !ruby/object:Gem::Version
|
|
66
|
-
version: '3.0'
|
|
67
|
-
type: :development
|
|
68
|
-
prerelease: false
|
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
70
|
-
requirements:
|
|
71
|
-
- - "~>"
|
|
64
|
+
- - ">="
|
|
72
65
|
- !ruby/object:Gem::Version
|
|
73
|
-
version: '
|
|
74
|
-
-
|
|
75
|
-
name: rake
|
|
76
|
-
requirement: !ruby/object:Gem::Requirement
|
|
77
|
-
requirements:
|
|
78
|
-
- - "~>"
|
|
66
|
+
version: '5.0'
|
|
67
|
+
- - "<"
|
|
79
68
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '
|
|
69
|
+
version: '9.0'
|
|
81
70
|
type: :development
|
|
82
71
|
prerelease: false
|
|
83
72
|
version_requirements: !ruby/object:Gem::Requirement
|
|
84
73
|
requirements:
|
|
85
|
-
- - "
|
|
74
|
+
- - ">="
|
|
86
75
|
- !ruby/object:Gem::Version
|
|
87
|
-
version: '
|
|
76
|
+
version: '5.0'
|
|
77
|
+
- - "<"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '9.0'
|
|
88
80
|
- !ruby/object:Gem::Dependency
|
|
89
81
|
name: rack
|
|
90
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -120,33 +112,82 @@ dependencies:
|
|
|
120
112
|
- !ruby/object:Gem::Version
|
|
121
113
|
version: '2.0'
|
|
122
114
|
- !ruby/object:Gem::Dependency
|
|
123
|
-
name:
|
|
115
|
+
name: rake
|
|
124
116
|
requirement: !ruby/object:Gem::Requirement
|
|
125
117
|
requirements:
|
|
126
|
-
- - "
|
|
118
|
+
- - "~>"
|
|
127
119
|
- !ruby/object:Gem::Version
|
|
128
|
-
version: '
|
|
129
|
-
|
|
120
|
+
version: '13.0'
|
|
121
|
+
type: :development
|
|
122
|
+
prerelease: false
|
|
123
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
124
|
+
requirements:
|
|
125
|
+
- - "~>"
|
|
130
126
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '
|
|
127
|
+
version: '13.0'
|
|
128
|
+
- !ruby/object:Gem::Dependency
|
|
129
|
+
name: rspec
|
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - "~>"
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '3.0'
|
|
132
135
|
type: :development
|
|
133
136
|
prerelease: false
|
|
134
137
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
138
|
requirements:
|
|
136
|
-
- - "
|
|
139
|
+
- - "~>"
|
|
137
140
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
139
|
-
|
|
141
|
+
version: '3.0'
|
|
142
|
+
- !ruby/object:Gem::Dependency
|
|
143
|
+
name: rubocop
|
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
|
145
|
+
requirements:
|
|
146
|
+
- - "~>"
|
|
140
147
|
- !ruby/object:Gem::Version
|
|
141
|
-
version: '
|
|
148
|
+
version: '1.86'
|
|
149
|
+
type: :development
|
|
150
|
+
prerelease: false
|
|
151
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
152
|
+
requirements:
|
|
153
|
+
- - "~>"
|
|
154
|
+
- !ruby/object:Gem::Version
|
|
155
|
+
version: '1.86'
|
|
156
|
+
- !ruby/object:Gem::Dependency
|
|
157
|
+
name: rubocop-rake
|
|
158
|
+
requirement: !ruby/object:Gem::Requirement
|
|
159
|
+
requirements:
|
|
160
|
+
- - "~>"
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: '0.7'
|
|
163
|
+
type: :development
|
|
164
|
+
prerelease: false
|
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - "~>"
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '0.7'
|
|
170
|
+
- !ruby/object:Gem::Dependency
|
|
171
|
+
name: rubocop-rspec
|
|
172
|
+
requirement: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - "~>"
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '3.0'
|
|
177
|
+
type: :development
|
|
178
|
+
prerelease: false
|
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - "~>"
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: '3.0'
|
|
142
184
|
description: |
|
|
143
185
|
axe-cuprite runs the axe-core accessibility engine against pages rendered in
|
|
144
186
|
Capybara system/feature tests and exposes the results as RSpec matchers
|
|
145
187
|
(be_axe_clean / be_accessible). Unlike Deque's official axe-core-capybara gem,
|
|
146
188
|
it never touches Selenium-specific driver internals: axe is driven entirely
|
|
147
189
|
through Capybara's driver-neutral JavaScript API, so it works with Cuprite
|
|
148
|
-
|
|
149
|
-
The headline use case is catching WCAG color-contrast failures in CI.
|
|
190
|
+
and any other real-browser driver.
|
|
150
191
|
email:
|
|
151
192
|
- abdullah@guidedrails.com
|
|
152
193
|
executables: []
|