bbc-a11y 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +9 -0
- data/CONTRIBUTING.md +70 -8
- data/GETTINGSTARTED.md +65 -0
- data/LICENSE +1 -1
- data/README.md +12 -55
- data/Rakefile +1 -1
- data/a11y.rb +1 -3
- data/bbc-a11y.gemspec +0 -1
- data/features/check_standards/01_core_purpose.feature +39 -0
- data/features/check_standards/02_validation.feature +1 -0
- data/features/check_standards/03_progressive_enhancement.feature +3 -0
- data/features/check_standards/{language.feature → 04_indicating_language.feature} +2 -2
- data/features/check_standards/05_page_titles.feature +1 -0
- data/features/check_standards/{main_landmark.feature → 06_main_landmark.feature} +6 -6
- data/features/check_standards/07_headings.feature +222 -0
- data/features/check_standards/{minimum_text_size.feature → 08_minimum_text_size.feature} +22 -2
- data/features/check_standards/09_resizable_text.feature +2 -0
- data/features/check_standards/{tab_index.feature → 10_tab_index.feature} +7 -7
- data/features/check_standards/{title_attribute.feature → 11_title_attributes.feature} +13 -5
- data/features/check_standards/{focusable_controls.feature → 12_focusable_controls.feature} +4 -4
- data/features/check_standards/13_visible_on_focus.feature +1 -0
- data/features/check_standards/14_control_styles.feature +1 -0
- data/features/check_standards/15_focus_styles.feature +1 -0
- data/features/check_standards/16_colour_contrast.feature +1 -0
- data/features/check_standards/17_colour_and_meaning.feature +1 -0
- data/features/check_standards/{image_alt.feature → 18_image_alternatives.feature} +5 -5
- data/features/check_standards/{form_labels.feature → 19_form_labels.feature} +7 -7
- data/features/check_standards/{form_interactions.feature → 20_form_interactions.feature} +6 -6
- data/features/check_standards/21_tables.feature +1 -0
- data/features/cli/display_failing_result.feature +14 -1
- data/features/cli/display_result_summary.feature +15 -1
- data/features/cli/provide_muting_tips.feature +1 -1
- data/features/cli/skipping_standards.feature +1 -1
- data/features/mute_errors.feature +2 -2
- data/features/step_definitions/steps.rb +10 -9
- data/features/support/web_server.rb +0 -11
- data/features/support/web_server/blank.html +7 -0
- data/features/support/web_server/two_headings_failures.html +11 -0
- data/karma.conf.js +1 -1
- data/lib/bbc/a11y/cli.rb +33 -6
- data/lib/bbc/a11y/js/bundle.js +139 -89
- data/lib/bbc/a11y/js/standards.js +67 -20
- data/lib/bbc/a11y/js/standards/{anchorsMustHaveHrefs.js → focusableControls/anchorsMustHaveHrefs.js} +0 -0
- data/lib/bbc/a11y/js/standards/{formsMustHaveSubmitButtons.js → formInteractions/formsMustHaveSubmitButtons.js} +0 -0
- data/lib/bbc/a11y/js/standards/{fieldsMustHaveLabelsOrTitles.js → formLabels/fieldsMustHaveLabelsOrTitles.js} +0 -0
- data/lib/bbc/a11y/js/standards/headings/contentMustFollowHeadings.js +18 -0
- data/lib/bbc/a11y/js/standards/{exactlyOneMainHeading.js → headings/exactlyOneMainHeading.js} +1 -1
- data/lib/bbc/a11y/js/standards/{headingsMustBeInAscendingOrder.js → headings/headingsMustBeInAscendingOrder.js} +0 -0
- data/lib/bbc/a11y/js/standards/{imagesMustHaveAltAttributes.js → imageAlternatives/imagesMustHaveAltAttributes.js} +0 -0
- data/lib/bbc/a11y/js/standards/{htmlMustHaveLangAttribute.js → indicatingLanguage/htmlMustHaveLangAttribute.js} +0 -0
- data/lib/bbc/a11y/js/standards/{exactlyOneMainLandmark.js → mainLandmark/exactlyOneMainLandmark.js} +0 -0
- data/lib/bbc/a11y/js/standards/{minimumTextSize.js → minimumTextSize/textCannotBeTooSmall.js} +3 -3
- data/lib/bbc/a11y/js/standards/{elementsWithZeroTabIndexMustBeFields.js → tabIndex/elementsWithZeroTabIndexMustBeFields.js} +0 -0
- data/lib/bbc/a11y/js/standards/{titleAttributesOnlyOnInputs.js → titleAttributes/titleAttributesOnlyOnInputs.js} +1 -1
- data/lib/bbc/a11y/linter.rb +16 -4
- data/lib/bbc/a11y/runner.rb +0 -1
- data/lib/bbc/a11y/string_colours.rb +15 -0
- data/lib/bbc/a11y/version +1 -1
- data/package.json +3 -0
- data/spec/bbc/a11y/js/a11ySpec.js +15 -6
- data/spec/bbc/a11y/js/minimumTextSizeStandardSpec.js +25 -0
- data/spec/bbc/a11y/js/standardsSpec.js +6 -6
- data/spec/bbc/a11y/string_colours_spec.rb +13 -0
- metadata +68 -102
- data/circle.yml +0 -3
- data/examples/bbc-pages/Gemfile +0 -3
- data/examples/bbc-pages/Rakefile +0 -3
- data/examples/bbc-pages/a11y.rb +0 -2
- data/examples/local-web-app/Gemfile +0 -4
- data/examples/local-web-app/Rakefile +0 -3
- data/examples/local-web-app/a11y.rb +0 -52
- data/examples/local-web-app/config.ru +0 -1
- data/examples/local-web-app/public/missing_header.html +0 -13
- data/examples/local-web-app/public/perfect.html +0 -14
- data/examples/local-web-app/readme.md +0 -0
- data/features/check_standards/headings.feature +0 -153
- data/lib/bbc/a11y/js/standards/contentMustFollowHeadings.js +0 -15
- data/lib/bbc/a11y/standards.rb +0 -45
- data/lib/bbc/a11y/standards/anchor_hrefs.rb +0 -18
- data/lib/bbc/a11y/standards/content_follows_headings.rb +0 -22
- data/lib/bbc/a11y/standards/exactly_one_main_heading.rb +0 -25
- data/lib/bbc/a11y/standards/exactly_one_main_landmark.rb +0 -20
- data/lib/bbc/a11y/standards/form_labels.rb +0 -39
- data/lib/bbc/a11y/standards/form_submit_buttons.rb +0 -21
- data/lib/bbc/a11y/standards/heading_hierarchy.rb +0 -34
- data/lib/bbc/a11y/standards/image_alt.rb +0 -18
- data/lib/bbc/a11y/standards/language_attribute.rb +0 -19
- data/lib/bbc/a11y/standards/tab_index.rb +0 -22
- data/lib/bbc/a11y/standards/title_attribute.rb +0 -31
- data/standards/01_core-purpose.md +0 -24
- data/standards/02_validation.feature +0 -31
- data/standards/03_javascript.feature +0 -40
- data/standards/04_language.feature +0 -58
- data/standards/05_page_title.feature +0 -45
- data/standards/06_main_landmark.feature +0 -24
- data/standards/07_headings.feature +0 -65
- data/standards/08_title_attribute.feature +0 -71
- data/standards/09_tabindex.feature +0 -51
- data/standards/10_form_labels.feature +0 -88
- data/standards/11_visible-on-focus.md +0 -58
- data/standards/13_colour-contrast.md +0 -27
- data/standards/14_colour-meaning.md +0 -19
- data/standards/15_focusable-controls.md +0 -45
- data/standards/16_table.md +0 -109
- data/standards/17_control-styles.md +0 -78
- data/standards/18_focus-styles.md +0 -36
- data/standards/19_form-interactions.md +0 -33
- data/standards/20_image-alt.md +0 -34
- data/standards/21_min-font-sizes.md +0 -64
- data/standards/22_resize-zoom.md +0 -80
- data/standards/step_definitions/core_content_steps.rb +0 -3
- data/standards/step_definitions/form_steps.rb +0 -6
- data/standards/step_definitions/language_steps.rb +0 -21
- data/standards/step_definitions/page_steps.rb +0 -50
- data/standards/step_definitions/w3c_steps.rb +0 -7
- data/standards/support/capybara.rb +0 -53
- data/standards/support/skipper.rb +0 -5
- data/standards/support/world.rb +0 -3
- data/standards/support/world_extender.rb +0 -5
data/circle.yml
DELETED
data/examples/bbc-pages/Gemfile
DELETED
data/examples/bbc-pages/Rakefile
DELETED
data/examples/bbc-pages/a11y.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
class Server
|
2
|
-
attr_reader :port
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
@pid = nil
|
6
|
-
@port = find_available_port
|
7
|
-
end
|
8
|
-
|
9
|
-
def start
|
10
|
-
@pid = fork { `rackup -p #{port} -q` }
|
11
|
-
@pid = @pid + 1 # because rackup starts a child process
|
12
|
-
sleep(0.1) until responsive?
|
13
|
-
end
|
14
|
-
|
15
|
-
def stop
|
16
|
-
return unless @pid
|
17
|
-
Process.kill("SIGKILL", @pid)
|
18
|
-
Process.wait(@pid)
|
19
|
-
rescue Errno::ECHILD
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def find_available_port
|
25
|
-
server = TCPServer.new('127.0.0.1', 0)
|
26
|
-
server.addr[1]
|
27
|
-
ensure
|
28
|
-
server.close if server
|
29
|
-
end
|
30
|
-
|
31
|
-
def responsive?
|
32
|
-
Net::HTTP.start('localhost', port) { |http| http.get("/perfect.html") }.is_a?(Net::HTTPSuccess)
|
33
|
-
rescue SystemCallError
|
34
|
-
false
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
server = Server.new
|
39
|
-
server.start
|
40
|
-
|
41
|
-
at_exit do
|
42
|
-
server.stop
|
43
|
-
end
|
44
|
-
|
45
|
-
page "http://localhost:#{server.port}/perfect.html" do
|
46
|
-
skip_standard "W3C"
|
47
|
-
end
|
48
|
-
|
49
|
-
page "http://localhost:#{server.port}/missing_header.html" do
|
50
|
-
skip_standard "W3C"
|
51
|
-
skip_standard "Check headings"
|
52
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
run Rack::Directory.new("public")
|
@@ -1,13 +0,0 @@
|
|
1
|
-
<html lang="en-gb">
|
2
|
-
<head>
|
3
|
-
<title>Missing header</title>
|
4
|
-
</head>
|
5
|
-
|
6
|
-
<body>
|
7
|
-
<p role="main">
|
8
|
-
Here is some text in British English. This is needed so that we can verify that
|
9
|
-
the lang attribute in the html element at the top, which specified en-gb, is
|
10
|
-
correct.
|
11
|
-
</p>
|
12
|
-
</body>
|
13
|
-
</html>
|
@@ -1,14 +0,0 @@
|
|
1
|
-
<html lang="en-gb">
|
2
|
-
<head>
|
3
|
-
<title>Perfect page - Main heading</title>
|
4
|
-
</head>
|
5
|
-
|
6
|
-
<body>
|
7
|
-
<h1>Main heading</h1>
|
8
|
-
<p role="main">
|
9
|
-
Here is some text in British English. This is needed so that we can verify that
|
10
|
-
the lang attribute in the html element at the top, which specified en-gb, is
|
11
|
-
correct.
|
12
|
-
</p>
|
13
|
-
</body>
|
14
|
-
</html>
|
File without changes
|
@@ -1,153 +0,0 @@
|
|
1
|
-
Feature: Headings
|
2
|
-
|
3
|
-
A document **must** have exactly one `<h1>` element.
|
4
|
-
|
5
|
-
Heading levels after the document `<h1>` element **must** be sequential and **must not** skip heading levels.
|
6
|
-
|
7
|
-
Heading elements **must** be followed by content.
|
8
|
-
|
9
|
-
Rationale
|
10
|
-
=========
|
11
|
-
|
12
|
-
A logical heading structure is invaluable for users of screen readers and similar assistive technologies to help navigate content.
|
13
|
-
|
14
|
-
Users should be able to use the document's `<h1>` identify its main content. Documents should have one main subject.
|
15
|
-
|
16
|
-
Heading levels should not be skipped as a predictable document outline is an important factor for understandability.
|
17
|
-
|
18
|
-
Headings should not be used for non-heading purposes, i.e. to identify blocks of content. A heading should always
|
19
|
-
be followed either by non-heading content or by a heading of one level deeper.
|
20
|
-
|
21
|
-
Scenario: No main heading
|
22
|
-
Given a page with the HTML:
|
23
|
-
"""
|
24
|
-
<h2>Heading 2</h2>
|
25
|
-
"""
|
26
|
-
When I validate the "exactly one main heading" standard
|
27
|
-
Then it fails with the message:
|
28
|
-
"""
|
29
|
-
Found 0 h1 elements.
|
30
|
-
"""
|
31
|
-
|
32
|
-
Scenario: More than one main heading
|
33
|
-
Given a page with the HTML:
|
34
|
-
"""
|
35
|
-
<h1>Heading 1</h1>
|
36
|
-
<h2>Heading 2</h2>
|
37
|
-
<h1>Heading 1</h1>
|
38
|
-
"""
|
39
|
-
When I validate the "exactly one main heading" standard
|
40
|
-
Then it fails with the message:
|
41
|
-
"""
|
42
|
-
Found 2 h1 elements: /html/body/h1[1] /html/body/h1[2]
|
43
|
-
"""
|
44
|
-
|
45
|
-
Scenario: Headings in ascending order
|
46
|
-
Given a page with the HTML:
|
47
|
-
"""
|
48
|
-
<h1>Heading 1</h1>
|
49
|
-
<h2>Heading 2</h2>
|
50
|
-
<h3>Heading 3</h3>
|
51
|
-
<h4>Heading 4</h4>
|
52
|
-
<h5>Heading 5</h5>
|
53
|
-
<h6>Heading 6</h6>
|
54
|
-
"""
|
55
|
-
When I validate the "headings must be in ascending order" standard
|
56
|
-
Then it passes
|
57
|
-
|
58
|
-
Scenario: Headings in invalid order
|
59
|
-
Given a page with the HTML:
|
60
|
-
"""
|
61
|
-
<h1>Heading 1</h1>
|
62
|
-
<h3>Heading 3</h3>
|
63
|
-
<h2>Heading 2</h2>
|
64
|
-
"""
|
65
|
-
When I validate the "headings must be in ascending order" standard
|
66
|
-
Then it fails with the message:
|
67
|
-
"""
|
68
|
-
Headings are not in order: /html/body/h1 /html/body/h3
|
69
|
-
"""
|
70
|
-
|
71
|
-
Scenario: Headings jump back up more than one level
|
72
|
-
Given a page with the HTML:
|
73
|
-
"""
|
74
|
-
<h1>Heading 1</h1>
|
75
|
-
<h2>Heading 2</h2>
|
76
|
-
<h3>Heading 3</h3>
|
77
|
-
<h4>Heading 4</h4>
|
78
|
-
<h2>Heading 2b</h2>
|
79
|
-
<h3>Heading 3b</h3>
|
80
|
-
"""
|
81
|
-
When I validate the "headings must be in ascending order" standard
|
82
|
-
Then it passes
|
83
|
-
|
84
|
-
Scenario: Heading is hidden
|
85
|
-
Given a page with the HTML:
|
86
|
-
"""
|
87
|
-
<h1>Heading 1</h1>
|
88
|
-
<h3 style="display:none">Heading 3</h3>
|
89
|
-
<h2>Heading 2</h2>
|
90
|
-
"""
|
91
|
-
When I validate the "headings must be in ascending order" standard
|
92
|
-
Then it fails with the message:
|
93
|
-
"""
|
94
|
-
Headings are not in order: /html/body/h1 /html/body/h3
|
95
|
-
"""
|
96
|
-
|
97
|
-
Scenario: Heading in a script tag
|
98
|
-
Given a page with the HTML:
|
99
|
-
"""
|
100
|
-
<h1>Heading 1</h1>
|
101
|
-
<script>
|
102
|
-
var stuff = "<h3>Heading 3</h3>";
|
103
|
-
</script>
|
104
|
-
<h2>Heading 2</h2>
|
105
|
-
"""
|
106
|
-
When I validate the "headings must be in ascending order" standard
|
107
|
-
Then it passes
|
108
|
-
|
109
|
-
Scenario: Subheading before the first main heading
|
110
|
-
Given a page with the HTML:
|
111
|
-
"""
|
112
|
-
<h3>Ignore me</h3>
|
113
|
-
<h1>Heading 1</h1>
|
114
|
-
<h2>Heading 2</h2>
|
115
|
-
"""
|
116
|
-
When I validate the "headings must be in ascending order" standard
|
117
|
-
Then it passes
|
118
|
-
|
119
|
-
Scenario: Content between headings
|
120
|
-
Given a page with the HTML:
|
121
|
-
"""
|
122
|
-
<div role="main">
|
123
|
-
<h1>Main heading</h1>
|
124
|
-
<p>non-heading content</p>
|
125
|
-
<h2>Another heading</h2>
|
126
|
-
<p>non-heading content</p>
|
127
|
-
<h3>Main content</h3>
|
128
|
-
non-heading content
|
129
|
-
<h2>Secondary content</h2>
|
130
|
-
<p>non-heading content</p>
|
131
|
-
<h2>Tertiary content</h2>
|
132
|
-
non-heading content
|
133
|
-
</div>
|
134
|
-
"""
|
135
|
-
When I validate the "content must follow headings" standard
|
136
|
-
Then it passes
|
137
|
-
|
138
|
-
Scenario: No content between headings
|
139
|
-
Given a page with the HTML:
|
140
|
-
"""
|
141
|
-
<div role="main">
|
142
|
-
<h1>Main heading</h1>
|
143
|
-
<p>non-heading content</p>
|
144
|
-
<h2>Secondary content</h2>
|
145
|
-
<h2>Tertiary content</h2>
|
146
|
-
<p>non-heading content</p>
|
147
|
-
</div>
|
148
|
-
"""
|
149
|
-
When I validate the "content must follow headings" standard
|
150
|
-
Then it fails with the message:
|
151
|
-
"""
|
152
|
-
No content follows: /html/body/div/h2[1]
|
153
|
-
"""
|
@@ -1,15 +0,0 @@
|
|
1
|
-
var headingSelector = 'h1, h2, h3, h4, h5, h6, h7, h8';
|
2
|
-
|
3
|
-
module.exports = {
|
4
|
-
name: 'Content must follow headings',
|
5
|
-
|
6
|
-
validate: function($, fail) {
|
7
|
-
$(headingSelector).each(function(index, heading) {
|
8
|
-
if ($(heading.nextSibling).is(headingSelector) ||
|
9
|
-
($(heading.nextSibling).text().trim() == '' &&
|
10
|
-
$(heading).next().is(headingSelector))) {
|
11
|
-
fail("No content follows:", heading);
|
12
|
-
}
|
13
|
-
});
|
14
|
-
}
|
15
|
-
}
|
data/lib/bbc/a11y/standards.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'bbc/a11y/standards/anchor_hrefs'
|
2
|
-
require 'bbc/a11y/standards/content_follows_headings'
|
3
|
-
require 'bbc/a11y/standards/exactly_one_main_heading'
|
4
|
-
require 'bbc/a11y/standards/exactly_one_main_landmark'
|
5
|
-
require 'bbc/a11y/standards/form_labels'
|
6
|
-
require 'bbc/a11y/standards/form_submit_buttons'
|
7
|
-
require 'bbc/a11y/standards/heading_hierarchy'
|
8
|
-
require 'bbc/a11y/standards/image_alt'
|
9
|
-
require 'bbc/a11y/standards/language_attribute'
|
10
|
-
require 'bbc/a11y/standards/tab_index'
|
11
|
-
require 'bbc/a11y/standards/title_attribute'
|
12
|
-
|
13
|
-
module BBC
|
14
|
-
module A11y
|
15
|
-
module Standards
|
16
|
-
def self.for(page_settings)
|
17
|
-
all.reject { |standard|
|
18
|
-
page_settings.skip_standard?(standard)
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.matching(name)
|
23
|
-
all.select { |standard|
|
24
|
-
name.match(standard.name)
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.all
|
29
|
-
[
|
30
|
-
AnchorHrefs,
|
31
|
-
ContentFollowsHeadings,
|
32
|
-
FormLabels,
|
33
|
-
FormSubmitButtons,
|
34
|
-
HeadingHierarchy,
|
35
|
-
ImageAlt,
|
36
|
-
ExactlyOneMainHeading,
|
37
|
-
ExactlyOneMainLandmark,
|
38
|
-
LanguageAttribute,
|
39
|
-
TabIndex,
|
40
|
-
TitleAttribute
|
41
|
-
]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module BBC
|
2
|
-
module A11y
|
3
|
-
module Standards
|
4
|
-
class AnchorHrefs
|
5
|
-
def initialize(page)
|
6
|
-
@page = page
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(errors)
|
10
|
-
@page.all("a:not([href])").each do |anchor|
|
11
|
-
errors << "Anchor has no href attribute: #{anchor.path}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module BBC
|
2
|
-
module A11y
|
3
|
-
module Standards
|
4
|
-
|
5
|
-
class ContentFollowsHeadings
|
6
|
-
def initialize(page)
|
7
|
-
@page = page
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(errors)
|
11
|
-
["h1", "h2", "h3", "h4", "h5", "h6"].each do |h|
|
12
|
-
if @page.all("#{h} + #{h}").any?
|
13
|
-
errors << "Heading elements must be followed by content. " +
|
14
|
-
"No content follows a #{h}."
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module BBC
|
2
|
-
module A11y
|
3
|
-
module Standards
|
4
|
-
class ExactlyOneMainHeading
|
5
|
-
def initialize(page)
|
6
|
-
@page = page
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(errors)
|
10
|
-
main_headings = @page.all('h1')
|
11
|
-
count = main_headings.size
|
12
|
-
if count == 0
|
13
|
-
errors << "A document must have exactly one main heading." +
|
14
|
-
" Found 0 h1 elements."
|
15
|
-
elsif count != 1
|
16
|
-
errors << "A document must have exactly one main heading." +
|
17
|
-
" Found #{count} h1 elements:\n" +
|
18
|
-
main_headings.map { |h1| "* #{h1.path}" }.join("\n")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module BBC
|
2
|
-
module A11y
|
3
|
-
module Standards
|
4
|
-
class ExactlyOneMainLandmark
|
5
|
-
def initialize(page)
|
6
|
-
@page = page
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(errors)
|
10
|
-
count = @page.all('*[role=main]').size
|
11
|
-
if count != 1
|
12
|
-
errors << "A document must have exactly one main landmark." +
|
13
|
-
" Found #{count} elements with role=\"main\"."
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module BBC
|
2
|
-
module A11y
|
3
|
-
module Standards
|
4
|
-
class FormLabels
|
5
|
-
def initialize(page)
|
6
|
-
@page = page
|
7
|
-
end
|
8
|
-
|
9
|
-
def call(errors)
|
10
|
-
fields = @page.all(potential_offenders)
|
11
|
-
fields.each do |field|
|
12
|
-
if offender? field
|
13
|
-
errors << "Field has no label or title attribute: #{field.path}"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def potential_offenders
|
21
|
-
"input:not([title]):not([type='hidden']), textarea:not([title]), select:not([title])"
|
22
|
-
end
|
23
|
-
|
24
|
-
def offender?(field)
|
25
|
-
(missing_id? field) or (missing_label? field)
|
26
|
-
end
|
27
|
-
|
28
|
-
def missing_id?(field)
|
29
|
-
field['id'] == nil or field['id'] == ''
|
30
|
-
end
|
31
|
-
|
32
|
-
def missing_label?(field)
|
33
|
-
@page.all("label[for='#{field['id']}']").empty?
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|