bbc-a11y 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/CONTRIBUTING.md +19 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +21 -0
  6. data/README.md +54 -0
  7. data/Rakefile +12 -0
  8. data/bbc-a11y.gemspec +32 -0
  9. data/bin/a11y +5 -0
  10. data/example/.a11y.rb +64 -0
  11. data/example/Gemfile +4 -0
  12. data/example/Rakefile +3 -0
  13. data/example/config.ru +1 -0
  14. data/example/public/missing_header.html +13 -0
  15. data/example/public/perfect.html +14 -0
  16. data/example/readme.md +0 -0
  17. data/features/01_core-purpose.md +24 -0
  18. data/features/02_validation.feature +31 -0
  19. data/features/03_javascript.feature +40 -0
  20. data/features/04_language.feature +58 -0
  21. data/features/05_page_title.feature +45 -0
  22. data/features/06_main_landmark.feature +24 -0
  23. data/features/07_headings.feature +65 -0
  24. data/features/08_title_attribute.feature +71 -0
  25. data/features/09_tabindex.feature +38 -0
  26. data/features/10_form-labels.md +47 -0
  27. data/features/11_visible-on-focus.md +58 -0
  28. data/features/13_colour-contrast.md +27 -0
  29. data/features/14_colour-meaning.md +19 -0
  30. data/features/15_focusable-controls.md +45 -0
  31. data/features/16_table.md +109 -0
  32. data/features/17_control-styles.md +78 -0
  33. data/features/18_focus-styles.md +36 -0
  34. data/features/19_form-interactions.md +33 -0
  35. data/features/20_image-alt.md +34 -0
  36. data/features/21_min-font-sizes.md +64 -0
  37. data/features/22_resize-zoom.md +80 -0
  38. data/features/step_definitions/core_content_steps.rb +3 -0
  39. data/features/step_definitions/language_steps.rb +21 -0
  40. data/features/step_definitions/page_steps.rb +46 -0
  41. data/features/step_definitions/w3c_steps.rb +7 -0
  42. data/features/support/capybara.rb +38 -0
  43. data/features/support/skipper.rb +5 -0
  44. data/features/support/world.rb +3 -0
  45. data/features/support/world_extender.rb +5 -0
  46. data/lib/bbc/a11y/cli.rb +49 -0
  47. data/lib/bbc/a11y/configuration.rb +83 -0
  48. data/lib/bbc/a11y/cucumber_runner.rb +133 -0
  49. data/lib/bbc/a11y/cucumber_support/heading_hierarchy.rb +92 -0
  50. data/lib/bbc/a11y/cucumber_support/language_detector.rb +26 -0
  51. data/lib/bbc/a11y/cucumber_support/page.rb +81 -0
  52. data/lib/bbc/a11y/cucumber_support/per_page_checks.rb +28 -0
  53. data/lib/bbc/a11y/cucumber_support/w3c.rb +36 -0
  54. data/lib/bbc/a11y/cucumber_support.rb +49 -0
  55. data/lib/bbc/a11y/version +1 -0
  56. data/lib/bbc/a11y.rb +4 -0
  57. data/spec/bbc/a11y/cucumber_support/heading_hierarchy_spec.rb +123 -0
  58. data/spec/bbc/a11y/cucumber_support/page_spec.rb +130 -0
  59. metadata +274 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5bde1a661b1feea57cf80e9d0133ae553ca7297e
4
+ data.tar.gz: e4e4f896df1d9edff57dc0dbd1542b511f6c21e4
5
+ SHA512:
6
+ metadata.gz: 4b8a9d07f2f9622b08fd5f546010f0b2ca8a17f886bacedfba5f79f92a6067ffef8c2ca245d8fb7bd1d6d11ddc9d5d14b9475b6fa534dac55d5b17c12d4c675b
7
+ data.tar.gz: e0a91c494c3b23b79f83a8f54339823a72f3756334b9b837b6e703e443d1614e6dde93c1ca7ad1e010fad7ff1be51390a2baecb2bad2287457e4c702c746e3ff
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,19 @@
1
+ # BBC A11y Contributing guidelines
2
+
3
+ The standards are all stored in the `features` directory.
4
+
5
+ You can run a manual test of your development copy of a11y at any time just by running:
6
+
7
+ bundle exec ./bin/a11y <url>
8
+
9
+ You can also pick out a specific feature to run:
10
+
11
+ bundle exec ./bin/a11y <url> -- features/04_language.feature
12
+
13
+ Or you can short-cut a11y's command-line interface and just run Cucumber directly:
14
+
15
+ URL=<url> bundle exec cucumber features/04_language.feature
16
+
17
+ The step definitions behind these features are shallow wrappers that delegate to objects in `lib/bbc/a11y/`. Those objects are unit-tested to ensure they'll behave as expected when tests pass or fail.
18
+
19
+ To add new behaviour, test-drive changes to the objects in `lib`.
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 British Broadcasting Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # BBC Accessiblity Standards
2
+
3
+ This tool runs a set of tests against a given URL to verify whether it meets the BBC accessibility standards.
4
+
5
+ ## How to use
6
+
7
+ Run the `a11y` command, passing a URL:
8
+
9
+ e.g.
10
+
11
+ a11y http://bbc.co.uk
12
+
13
+ You can also pass arguments to Cucumber (which is used internally) by separating the arguments with `--`. Everything
14
+ after the `--` is passed directly to Cucumber. For example, to skip the tests that require manual interraction:
15
+
16
+ a11y http://bbc.co.uk -- -t ~@manual
17
+
18
+ ## How to install
19
+
20
+ A11y is packaged as a Ruby gem, but is not yet available on the public Rubygems server. To install it, you'll need to either build it by hand, or add a reference to the github source in your Gemfile.
21
+
22
+ ### Prerequisites
23
+
24
+ Install Ruby and `gem install bundler`.
25
+
26
+ ### Adding a11y to your project's Gemfile
27
+
28
+ Open your project's `Gemfile` and this line:
29
+
30
+ gem 'bbc-a11y`, git: 'git@github.com:mattwynne/bbc-a11y.git'
31
+
32
+ Now install the gem:
33
+
34
+ bundle install --binstubs
35
+
36
+ *Note:* You'll need to make sure every user who wants to run `bundle install` (including your continuous integration environment) has at least read access to this Github project.
37
+
38
+ ### Build and install the gem manually
39
+
40
+ This will install the `a11y` tool globally on your machine.
41
+
42
+ 1. Clone this repository
43
+ 2. Install dependencies
44
+
45
+ ~~~
46
+ cd bbc-a11y
47
+ bundle install
48
+ ~~~
49
+
50
+ 3. Install the gem
51
+
52
+ ~~~
53
+ bundle exec rake install
54
+ ~~~
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task default: [:unit, :acceptance]
5
+
6
+ task :unit do
7
+ sh "rspec"
8
+ end
9
+
10
+ task :acceptance do
11
+ sh "cd example && rake"
12
+ end
data/bbc-a11y.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'bbc-a11y'
6
+ s.version = File.read(File.expand_path("../lib/bbc/a11y/version", __FILE__))
7
+ s.authors = ["Matt Wynne", "Ian Pouncey"]
8
+ s.description = "A tool for testing the compliance of web URLs against the BBC's accessibilty guidelines"
9
+ s.summary = "bbc-a11y-#{s.version}"
10
+ s.email = "github@ipouncey.co.uk"
11
+ s.homepage = "https://cucumber.pro"
12
+ s.platform = Gem::Platform::RUBY
13
+ s.license = "MIT"
14
+ s.required_ruby_version = ">= 1.9.3"
15
+
16
+ s.add_dependency 'cucumber', '~> 2.0.0.rc'
17
+ s.add_dependency 'rspec', '~> 3.0'
18
+ s.add_dependency 'capybara'
19
+ s.add_dependency 'selenium-webdriver'
20
+ s.add_dependency 'w3c_validators'
21
+ s.add_dependency 'cld'
22
+ s.add_dependency 'colorize'
23
+ s.add_development_dependency 'aruba'
24
+ s.add_development_dependency 'pry'
25
+ s.add_development_dependency 'rake'
26
+
27
+ s.rubygems_version = ">= 1.6.1"
28
+ s.files = `git ls-files`.split("\n").reject {|path| path =~ /\.gitignore$/ }
29
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_path = "lib"
32
+ end
data/bin/a11y ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'bbc/a11y/cli'
5
+ BBC::A11y::CLI.new($stdin, $stdout, $stderr, ARGV.dup).call
data/example/.a11y.rb ADDED
@@ -0,0 +1,64 @@
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
+
40
+ BBC::A11y.configure do
41
+
42
+ before_all do
43
+ server.start
44
+ end
45
+
46
+ after_all do
47
+ server.stop
48
+ end
49
+
50
+ page "http://localhost:#{server.port}/perfect.html" do
51
+ skip_scenario "W3C"
52
+ end
53
+
54
+ page "http://localhost:#{server.port}/missing_header.html" do
55
+ skip_scenario "W3C"
56
+ skip_scenario "Check headings"
57
+
58
+ customize_world do
59
+ def Xassert_title_describes_primary_content_of_document(title, doc)
60
+ puts "TODO"
61
+ end
62
+ end
63
+ end
64
+ end
data/example/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rack'
4
+ gem 'bbc-a11y', path: '..'
data/example/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ task :default do
2
+ sh "bundle exec ../bin/a11y"
3
+ end
data/example/config.ru ADDED
@@ -0,0 +1 @@
1
+ run Rack::Directory.new("public")
@@ -0,0 +1,13 @@
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>
@@ -0,0 +1,14 @@
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>
data/example/readme.md ADDED
File without changes
@@ -0,0 +1,24 @@
1
+ # The core purpose of every document must be defined
2
+
3
+ Before design and implementation of a document or feature its core purpose **must** be defined.
4
+
5
+ ## Definitions
6
+
7
+ ### Core purpose
8
+
9
+ The functionality to inform, educate, and entertain without which there would be no purpose for site or document.
10
+
11
+ ## Rationale
12
+
13
+ While our aim is for all users to have access to all features of BBC apps and sites we recognise that technology both restricts and extends what is possible.
14
+
15
+ Additionally GEL is aimed providing the best experience to the broadest range of users, and while it should not discriminate against users with access needs nor does it give special privilege.
16
+
17
+ The aim of this guideline is to provide the most accessible base line experience for the core purpose across the broadest range of technology.
18
+
19
+ See the following standards for examples of when a defined core purpose is applicable:
20
+
21
+ - [Core experience must not rely on JavaScript or CSS]()
22
+ - [Minimum text size]()
23
+
24
+ It is **not** a reason to ignore accessibility for non-core page elements.
@@ -0,0 +1,31 @@
1
+ Feature: HTML Validation
2
+
3
+ All documents **must** have a [W3C recommended Doctype](http://www.w3.org/QA/2002/04/valid-dtd-list.html) and
4
+ all Markup **must** validate against that Doctype.
5
+
6
+ Rationale
7
+ =========
8
+
9
+ While assistive technologies such as screen readers generally do a good job of interpreting
10
+ invalid HTML there will be less risk of problems arising if the document follows a recognised
11
+ standard Doctype.
12
+
13
+ Techniques
14
+ ==========
15
+
16
+ Pass:
17
+
18
+ <!DOCTYPE html>
19
+ <html lang="en-GB">
20
+
21
+ Fail:
22
+
23
+ <html lang="en-GB">
24
+
25
+
26
+ Scenario: Submit to W3C validation Service
27
+
28
+ See http://validator.w3.org
29
+
30
+ When I submit the page to the W3C Markup Validation Service
31
+ Then there should be no errors
@@ -0,0 +1,40 @@
1
+ Feature: JavaScript
2
+
3
+ Core experience must not rely on JavaScript
4
+
5
+ The core purpose of every document **must** be defined.
6
+
7
+ The core content of every document must not require JavaScript to be added to the DOM
8
+
9
+ Rationale
10
+ =========
11
+
12
+ We aim to provide a core experience to as broad an audience as possible, allowing
13
+ users to choose the software and devices that work best for them in a broad range of circumstances.
14
+
15
+ Equally a robust site or application in the more traditional sense minimises its dependencies.
16
+ The minimum dependency for a web site should be an internet connection and the ability to parse HTML.
17
+
18
+ For this reason all BBC documents must enable their core purpose without relying on CSS or JavaScript.
19
+
20
+ CSS and JavaScript can, and should, be used to enhance the user experience beyond this basic level.
21
+ For example, a ‘live’ page has a core purpose to provide the latest content about an event to the user.
22
+ The core experience is the latest content at the time of the request. The experience enhanced with
23
+ JavaScript automatically updates this content without the user having to take action.
24
+
25
+ Definitions
26
+ ===========
27
+
28
+ *Core content* - The content that is provided to users without JavaScript.
29
+
30
+ Notes
31
+ =====
32
+
33
+ This is going to have to be a product specific test. Can we provide a template for this test,
34
+ perhaps looking for elements based on provided selectors and make sure they are in the document?
35
+
36
+ @manual
37
+ Scenario: View the page with JavaScript disabled
38
+ When I view the page with JavaScript disabled
39
+ Then all core content is available in the DOM
40
+
@@ -0,0 +1,58 @@
1
+ Feature: Specify content language
2
+
3
+ The main language of the page _must_ be specified.
4
+
5
+ Changes to language within the page **must** be indicated.
6
+
7
+ Rationale
8
+ =========
9
+
10
+ Assistive technologies such as screen readers have support for different languages,
11
+ allowing for appropriate pronunciation.
12
+
13
+ Techniques
14
+ ==========
15
+
16
+ Pass:
17
+
18
+ ```
19
+ <!DOCTYPE html>
20
+ <html lang="en-GB">
21
+ <head>
22
+ <title>Language techniques</title>
23
+ </head>
24
+ <body>
25
+ <h1>Techniques for language in HTML</h1>
26
+ <p><span lang="es">Cinco de Mayo</span> is Spanish for "fifth of May"</p>
27
+ </body>
28
+ </html>
29
+ ```
30
+
31
+ Fail:
32
+
33
+ ```
34
+ <!DOCTYPE html>
35
+ <html>
36
+ <head>
37
+ <title>Language techniques</title>
38
+ </head>
39
+ <body>
40
+ <h1>Techniques for language in HTML</h1>
41
+ <p>Cinco de Mayo is Spanish for "fifth of May"</p>
42
+ </body>
43
+ </html>
44
+ ```
45
+
46
+ Scenario: Check main body element lang attribute
47
+ When I visit the page
48
+ Then the <html> element must have a `lang` attribute
49
+ And the main natural language of the page must match that attribute
50
+
51
+ Scenario: Check for other elements with lang attributes
52
+ When I visit the page
53
+ Then all elements with `lang` attribute must have content in that natural language
54
+
55
+ @manual
56
+ Scenario: Check for areas of the page expressed in other languages, but missing a `lang` attribute
57
+ When I visit the page
58
+ Then any parts expressed in a natural language different to the main language of the page must have a matching `lang` attribute
@@ -0,0 +1,45 @@
1
+ Feature: Page title
2
+
3
+ A document **must** have a unique page `<title>` that identifies its main content.
4
+
5
+ Rationale
6
+ =========
7
+
8
+ Document titles help users orientate themselves within web sites and apps. The document `<title>` element
9
+ content is often the first thing a speech output user will hear and acts as a confirmation of what page they
10
+ have arrived at. Document titles commonly have the same content as the main `<h1>` element.
11
+
12
+ Techniques
13
+ ==========
14
+
15
+ Pass:
16
+
17
+ <title>BBC Weather</title>
18
+
19
+ Fail:
20
+
21
+ <title>BBC</title>
22
+
23
+ @manual
24
+ Scenario: Check the title
25
+
26
+ We can't easily test for the uniqueness of the title, but we can test for the presence of the element
27
+ and ensure it has content.
28
+
29
+ In terms of prompting for manual tests, could we compare the title element with the content of the first
30
+ `<h1>` element on the page, and if the former contains the latter then automatically pass the test.
31
+
32
+ For example:
33
+
34
+ <title>BBC Weather - Weather in London</title>
35
+
36
+ ~
37
+
38
+ <h1>Weather in London</h1>
39
+
40
+ ...would pass automatically, but a `<title>` element that does not contain the string 'Weather in London'
41
+ would be flagged for manual review.
42
+
43
+ When I visit the page
44
+ Then the document should have a title
45
+ And the title should describe the primary content of the document
@@ -0,0 +1,24 @@
1
+ Feature: Main landmark
2
+
3
+ A page **must** have exactly one element with `role="main"`
4
+
5
+ Rationale
6
+ =========
7
+
8
+ The WAI-ARIA `main` landmark role can be help keyboard users with assistive technologies such as screen readers (and in the future as native browser functionality) to skip directly to the main content of a page, bypassing navigation and other contents that might be before it.
9
+
10
+ Techniques
11
+ ==========
12
+
13
+ Pass:
14
+
15
+ <div role="main" id="main-content"></div>
16
+
17
+ Fail:
18
+
19
+ <div id="main-content"></div>
20
+
21
+ Scenario: Check for a single main element
22
+ When I visit the page
23
+ Then there should be exactly one element with `role="main"`
24
+
@@ -0,0 +1,65 @@
1
+ Feature: Correctly use 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
+ Techniques
22
+ ==========
23
+
24
+ Pass:
25
+
26
+ <div role="main">
27
+ <h1>Main page content</h1>
28
+ <p>Lorem ipsum…</p>
29
+ <h2>Secondary content</h2>
30
+ <h3>Tertiary content one</h2>
31
+ <ul>
32
+ <li>Lorem</li>
33
+ </ul>
34
+ <h3>Tertiary content two</h3>
35
+ <ul>
36
+ <li>Ipsum</li>
37
+ </ul>
38
+ </div>
39
+
40
+ Fail:
41
+
42
+ <div role="main">
43
+ <h3>Main content</h3>
44
+ <h2>Secondary content</h2>
45
+ <h2>Tertiary content</h2>
46
+ <p>Lorem ipsum…</p>
47
+ </div>
48
+
49
+ Notes
50
+ =====
51
+
52
+ For the second test, can we check the next text node after each heading and test that it is
53
+ either not part of a heading element, or is part of a heading level of one level higher?
54
+
55
+ Questions
56
+ =========
57
+
58
+ 1. Clarify the note, above!
59
+ 2. Presumably it's OK for the hierarchy to jump *up* by more than 1? e.g. h1, h2, h3, h4, h2 is ok?
60
+
61
+ Scenario: Check headings
62
+ When I visit the page
63
+ Then there must be exactly one h1 element
64
+ And each heading must be followed by content or a heading of one level deeper (h2-h6)
65
+
@@ -0,0 +1,71 @@
1
+ Feature: Correctly use `title` attributes
2
+
3
+ `title` attributes **must not** be used for critical information and **must not** repeat content that is already visible and associated with the same control or content.
4
+
5
+ Rationale
6
+ =========
7
+
8
+ `title` attributes are inaccessible to keyboard users without additional Assistive Technology. They are dependent on user settings in Screen Readers and similar Assistive Technology.
9
+
10
+ Additionally they suffer from discoverability problems: pointing device users are required to hover over page elements and pause before the title tooltip displays, usually with no indication that there is additional content to be displayed.
11
+
12
+ Repeating content in visible text and `title` attributes can lead to content clutter and repeated phrases.
13
+
14
+ Key recommendations are:
15
+
16
+ - Do not use the `title` attribute unless on a form input as title text is not well supported on links on mobile
17
+ - Do not use `title` attributes and explicit labels together on form fields
18
+
19
+ Techniques
20
+ ==========
21
+
22
+ Pass:
23
+
24
+ <label for="name">Name</label>
25
+ <input type="text" id="name" name="name" />
26
+ <label for="email">Email</label>
27
+
28
+ <input type="text" id="email" name="email" />
29
+
30
+ <button type="button"><img src="/path/to/image/close.png" alt="Close" /></button>
31
+
32
+ Fail:
33
+
34
+ <input type="text" name="name" title="Name" />
35
+ <input type="text" name="email" title="Email" />
36
+
37
+ <label for="name">Name</label>
38
+ <input type="text" id="name" name="name" title="Name" />
39
+
40
+ <button type="button" title="Close"></button>
41
+
42
+ <a href="/news" title="News">News</a>
43
+
44
+ Tests
45
+ =====
46
+
47
+ | Procedure | Expected Result | Type |
48
+ | --------- | --------------- | ---- |
49
+ | Search source for all uses of the `title` attribute | Ensure no instances contain content that would be required by all users or content that is repeated in associated content | Manual |
50
+ | Search source for all uses of the `title` attribute | Ensure no instances contain content that is repeated within the element | Automated |
51
+ | Search source for all '<label>' elements and their associated form fields | Ensure that the associated form field does not have a title attribute | Automated |
52
+
53
+ --
54
+
55
+ Notes
56
+ =====
57
+
58
+ The first test is non-automatable, and may well have to be removed as it is too ambiguous.
59
+
60
+ Scenario: Check the elements with title attributes
61
+
62
+ Examples of failure:
63
+
64
+ <label for="name">Name</label>
65
+ <input type="text" id="name" name="name" title="Name" />
66
+
67
+ <a href="/news" title="News">News</a>
68
+
69
+ When I visit the page
70
+ Then there must be no elements with a title attribute whose content is repeated within the element
71
+ And any form fields with associated labels do not have a title attribute