bbc-a11y 0.0.9 → 0.0.11

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 +4 -4
  2. data/CONTRIBUTING.md +3 -7
  3. data/README.md +7 -3
  4. data/Rakefile +1 -2
  5. data/bin/a11y +2 -1
  6. data/features/README.md +4 -0
  7. data/features/exit_status.feature +14 -0
  8. data/features/specify_url_via_cli.feature +10 -0
  9. data/features/specify_url_via_config.feature +16 -0
  10. data/features/step_definitions/steps.rb +13 -0
  11. data/features/support/env.rb +5 -0
  12. data/features/support/web_server.rb +30 -0
  13. data/features/support/web_server/missing_header.html +13 -0
  14. data/features/support/web_server/perfect.html +14 -0
  15. data/lib/bbc/a11y.rb +1 -0
  16. data/lib/bbc/a11y/cli.rb +19 -5
  17. data/lib/bbc/a11y/configuration.rb +6 -1
  18. data/lib/bbc/a11y/cucumber_runner.rb +25 -5
  19. data/lib/bbc/a11y/cucumber_support.rb +9 -2
  20. data/lib/bbc/a11y/cucumber_support/disabled_w3c.rb +37 -0
  21. data/lib/bbc/a11y/cucumber_support/matchers.rb +21 -0
  22. data/lib/bbc/a11y/cucumber_support/page.rb +16 -6
  23. data/lib/bbc/a11y/version +1 -1
  24. data/spec/bbc/a11y/cli_spec.rb +27 -0
  25. data/spec/bbc/a11y/configuration_spec.rb +15 -3
  26. data/spec/bbc/a11y/cucumber_support/matchers_spec.rb +52 -0
  27. data/spec/bbc/a11y/cucumber_support/page_spec.rb +34 -10
  28. data/{features → standards}/01_core-purpose.md +0 -0
  29. data/{features → standards}/02_validation.feature +0 -0
  30. data/{features → standards}/03_javascript.feature +0 -0
  31. data/{features → standards}/04_language.feature +0 -0
  32. data/{features → standards}/05_page_title.feature +0 -0
  33. data/{features → standards}/06_main_landmark.feature +0 -0
  34. data/{features → standards}/07_headings.feature +0 -0
  35. data/{features → standards}/08_title_attribute.feature +0 -0
  36. data/{features → standards}/09_tabindex.feature +8 -1
  37. data/standards/10_form_labels.feature +88 -0
  38. data/{features → standards}/11_visible-on-focus.md +0 -0
  39. data/{features → standards}/13_colour-contrast.md +0 -0
  40. data/{features → standards}/14_colour-meaning.md +0 -0
  41. data/{features → standards}/15_focusable-controls.md +0 -0
  42. data/{features → standards}/16_table.md +0 -0
  43. data/{features → standards}/17_control-styles.md +0 -0
  44. data/{features → standards}/18_focus-styles.md +0 -0
  45. data/{features → standards}/19_form-interactions.md +0 -0
  46. data/{features → standards}/20_image-alt.md +0 -0
  47. data/{features → standards}/21_min-font-sizes.md +0 -0
  48. data/{features → standards}/22_resize-zoom.md +0 -0
  49. data/{features → standards}/step_definitions/core_content_steps.rb +0 -0
  50. data/standards/step_definitions/form_steps.rb +6 -0
  51. data/{features → standards}/step_definitions/language_steps.rb +0 -0
  52. data/{features → standards}/step_definitions/page_steps.rb +6 -2
  53. data/{features → standards}/step_definitions/w3c_steps.rb +0 -0
  54. data/{features → standards}/support/capybara.rb +0 -0
  55. data/{features → standards}/support/skipper.rb +0 -0
  56. data/{features → standards}/support/world.rb +0 -0
  57. data/{features → standards}/support/world_extender.rb +0 -0
  58. metadata +82 -86
  59. data/features/10_form-labels.md +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e1a5f15fb23bfa023b502767ac8667ef7b3f27ce
4
- data.tar.gz: 48b3be883a67e39d68fd2c383c38b5e49af2d444
3
+ metadata.gz: 8697bc18c43d39bd843b0dfe9fda7a20ea761fc4
4
+ data.tar.gz: 4e709fc1f14853e37d2d00ed0453de4db887829a
5
5
  SHA512:
6
- metadata.gz: 8f936fb98eef71751d1730c3b7736352b38e4822a75dc8b97a1efadfc81b63caf1d352b8c41697a1a8d4b3492f2e319a99ccc30520de3e9d498edb1c05700c85
7
- data.tar.gz: f6452c73fd7f27d46a390be8d6054ffda5bc21af07b540c49fa60038a51d0491f459dc168b2e21f48dbc0847590fc040be5e647a7e03e71e1ff75246a26780cb
6
+ metadata.gz: 29063edb07ab6454f23b5a0b797e911e278b74ecb7bf4299e64700c8ab16f6c86508829727343fe7f35ded04f354ee9f1a61e4bce18d5ebdada70316c3f30541
7
+ data.tar.gz: a0da88c1f3e550ac193b7d9b87a15c00b8135d42dda11e76a809d0750831d28f32f969c147bf5c43e3ddc3b207399d57af21b589c13e0e22edf1f6dda8c09dfc
@@ -1,18 +1,14 @@
1
1
  # BBC A11y Contributing guidelines
2
2
 
3
- The standards are all stored in the `features` directory.
3
+ The standards are all stored in the `standards` directory.
4
4
 
5
5
  You can run a manual test of your development copy of a11y at any time just by running:
6
6
 
7
7
  bundle exec ./bin/a11y <url>
8
8
 
9
- You can also pick out a specific feature to run:
9
+ You can also use cucumber to run one specific test:
10
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
11
+ A11Y_URL=<url> bundle exec cucumber features/04_language.feature
16
12
 
17
13
  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
14
 
data/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ # WARNING - PROTOTYPE SOFTWARE
2
+
3
+ This project is still at an experimental / proof-of-concept stage. Please set your expectations appropriately, but *do* [give us as much feedback](https://github.com/cucumber-ltd/bbc-a11y/issues) as you can.
4
+
1
5
  #BBC Accessiblity Standards
2
6
 
3
7
  This tool runs a set of tests against a set of URLs to verify whether each one meets the [BBC accessibility standards](http://www.bbc.co.uk/guidelines/futuremedia/accessibility/).
@@ -41,7 +45,7 @@ Nobody's perfect. Use `skip_scenario` in the configuration to opt-out of certain
41
45
  ```
42
46
  BBC::A11y.configure do
43
47
  page "http://bbc.co.uk" do
44
- skip_scenario "W3C"
48
+ skip_scenario /W3C/
45
49
  end
46
50
 
47
51
  page "http://bbc.co.uk/news"
@@ -52,9 +56,9 @@ A11y will skip any scenarios from the specifications whose name contains that st
52
56
 
53
57
  ## Running it
54
58
 
55
- Once you're configured, you can run the tests using the `a11y` command:
59
+ Once you're configured, you can run the tests using the `a11y` command, from the directory where your `.a11y.rb` configuration file is stored:
56
60
 
57
61
  bundle exec a11y
58
62
 
59
- This will pick up your `.a11y.rb` configuration file and run the a11y features on each page specified in your configuration.
63
+ This will pick up your `.a11y.rb` configuration file and run the a11y features on each page specified in your configuration.
60
64
  Output is printed to the console.
data/Rakefile CHANGED
@@ -8,6 +8,5 @@ task :unit do
8
8
  end
9
9
 
10
10
  task :acceptance do
11
- sh "cd examples/local-web-app && rake"
12
- sh "cd examples/bbc-pages && rake"
11
+ sh "cucumber"
13
12
  end
data/bin/a11y CHANGED
@@ -2,4 +2,5 @@
2
2
  $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
3
3
 
4
4
  require 'bbc/a11y/cli'
5
- BBC::A11y::CLI.new($stdin, $stdout, $stderr, ARGV.dup).call
5
+ require 'bbc/a11y/cucumber_runner'
6
+ BBC::A11y::CLI.new($stdin, $stdout, $stderr, ARGV.dup).call(BBC::A11y::CucumberRunner)
@@ -0,0 +1,4 @@
1
+ These are the acceptance tests for the a11y tool itself.
2
+
3
+ To read the accessibility standards checks that this tool will run against your app,
4
+ you need to look in the `standards` directory.
@@ -0,0 +1,14 @@
1
+ @wip
2
+ Feature: Exit status
3
+
4
+ For CI, we need to make sure the process exits with a non-zero
5
+ status when there's been a failure.
6
+
7
+ Scenario: Passing tests
8
+ When all the tests pass
9
+ Then the exit status should be 0
10
+
11
+ Scenario: Failing test
12
+ Given a standards-compliant website running at http://localhost:54321
13
+ When I run `a11y http://localhost:54321/missing_header.html`
14
+ Then the exit status should be 1
@@ -0,0 +1,10 @@
1
+ Feature: Specify URL via the CLI
2
+
3
+ Scenario: No config, just pass page URL on command-line
4
+ Given a standards-compliant website running at http://localhost:54321
5
+ When I run `a11y http://localhost:54321/perfect.html`
6
+ Then it should pass with:
7
+ """
8
+ BBC Accesibility: http://localhost:54321/perfect.html
9
+ -----------------------------------------------------
10
+ """
@@ -0,0 +1,16 @@
1
+ Feature: Specify URL via config
2
+
3
+ Scenario: Specify a single page
4
+ Given a standards-compliant website running at http://localhost:54321
5
+ And a file named ".a11y.rb" with:
6
+ """
7
+ BBC::A11y.configure do
8
+ page "http://localhost:54321/perfect.html"
9
+ end
10
+ """
11
+ When I run `a11y`
12
+ Then it should pass with:
13
+ """
14
+ BBC Accesibility: http://localhost:54321/perfect.html
15
+ -----------------------------------------------------
16
+ """
@@ -0,0 +1,13 @@
1
+ Given(/^a standards-compliant website running at http:\/\/localhost:(\d+)$/) do |port|
2
+ WebServer.ensure_running_on(port)
3
+ end
4
+
5
+ Given(/^all the tests pass$/) do
6
+ WebServer.ensure_running_on(54321)
7
+ step "I run `a11y http://localhost:54321/perfect.html`"
8
+ end
9
+
10
+ Given(/^one test fails$/) do
11
+ WebServer.ensure_running_on(54321)
12
+ step "I run `a11y http://localhost:54321/missing_header.html`"
13
+ end
@@ -0,0 +1,5 @@
1
+ require 'aruba/cucumber'
2
+
3
+ Before do
4
+ @aruba_timeout_seconds = 10
5
+ end
@@ -0,0 +1,30 @@
1
+ require 'webrick'
2
+
3
+ class WebServer
4
+ DOCUMENT_ROOT = File.expand_path File.dirname(__FILE__) + '/web_server'
5
+ class << self
6
+ def ensure_running_on(port)
7
+ return if @running
8
+ server = WEBrick::HTTPServer.new options(port)
9
+ Thread.new { server.start }
10
+ at_exit { server.shutdown }
11
+ @running = true
12
+ end
13
+
14
+ def options(port)
15
+ default = {
16
+ :Port => port.to_i,
17
+ :DocumentRoot => DOCUMENT_ROOT,
18
+ }
19
+ disable_logging = {
20
+ :AccessLog => [],
21
+ :Logger => WEBrick::Log::new("/dev/null", 7)
22
+ }
23
+ unless ENV['DEBUG']
24
+ default.merge disable_logging
25
+ else
26
+ default
27
+ end
28
+ end
29
+ end
30
+ end
@@ -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>
@@ -1,4 +1,5 @@
1
1
  module BBC
2
2
  module A11y
3
+ TestsFailed = Class.new(StandardError)
3
4
  end
4
5
  end
@@ -1,5 +1,5 @@
1
- require 'bbc/a11y/cucumber_runner'
2
1
  require 'bbc/a11y/configuration'
2
+ require 'bbc/a11y'
3
3
 
4
4
  module BBC
5
5
  module A11y
@@ -14,9 +14,11 @@ module BBC
14
14
  @stdin, @stdout, @stderr, @args = stdin, stdout, stderr, args
15
15
  end
16
16
 
17
- def call
17
+ def call(runner)
18
18
  trap_interrupt
19
- CucumberRunner.new(settings, cucumber_args).call
19
+ runner.new(settings, cucumber_args).call
20
+ rescue TestsFailed
21
+ exit 1
20
22
  rescue MissingArgument => error
21
23
  stderr.puts "You missed an argument: #{error.message}"
22
24
  stderr.puts HELP
@@ -26,12 +28,24 @@ module BBC
26
28
  private
27
29
 
28
30
  def settings
29
- Configuration.parse(File.expand_path(".a11y.rb"))
31
+ if a11y_args.any?
32
+ Configuration.for_urls(a11y_args)
33
+ else
34
+ Configuration.parse(File.expand_path(".a11y.rb"))
35
+ end
36
+ end
37
+
38
+ def a11y_args
39
+ if args.find_index('--')
40
+ args[0..(args.find_index('--') - 1)]
41
+ else
42
+ args
43
+ end
30
44
  end
31
45
 
32
46
  def cucumber_args
33
47
  return [] unless args.include?('--')
34
- args[args.find_index('--')+1..-1]
48
+ args[(args.find_index('--') + 1)..-1]
35
49
  end
36
50
 
37
51
  def trap_interrupt
@@ -16,6 +16,11 @@ module BBC
16
16
  BBC::A11y.configuration
17
17
  end
18
18
 
19
+ def self.for_urls(urls)
20
+ page_settings = urls.map { |url| PageSettings.new(url) }
21
+ Settings.new.with_pages(page_settings)
22
+ end
23
+
19
24
  class Settings
20
25
  attr_reader :before_all_hooks,
21
26
  :after_all_hooks,
@@ -44,7 +49,7 @@ module BBC
44
49
  end
45
50
 
46
51
  def skip_test_case?(test_case)
47
- @scenarios_to_skip.any? { |pattern| pattern.match test_case.name }
52
+ @scenarios_to_skip.any? { |pattern| test_case.name.match pattern }
48
53
  end
49
54
 
50
55
  def merge(other)
@@ -51,6 +51,9 @@ module BBC
51
51
  end
52
52
  end
53
53
  puts
54
+ if result.failed?
55
+ CucumberRunner.test_case_failed
56
+ end
54
57
  end
55
58
 
56
59
  private
@@ -135,6 +138,21 @@ module BBC
135
138
 
136
139
  class CucumberRunner
137
140
  include ConsoleWriter
141
+ FEATURES_PATH = File.expand_path(File.dirname(__FILE__) + "/../../../standards")
142
+
143
+ class << self
144
+ # need to use a global stash-point for the formatter to talk back to use
145
+ # until Cucumber gives us a way to add formatter instances that we can
146
+ # share.
147
+ def failed_count
148
+ @failed_count ||= 0
149
+ end
150
+
151
+ def test_case_failed
152
+ @failed_count ||= 0
153
+ @failed_count += 1
154
+ end
155
+ end
138
156
 
139
157
  def initialize(settings, cucumber_args)
140
158
  @settings = settings
@@ -152,19 +170,21 @@ module BBC
152
170
  end
153
171
  ensure
154
172
  run_after_all_hooks
173
+ raise BBC::A11y::TestsFailed if self.class.failed_count > 0
155
174
  end
156
175
 
157
176
  private
158
177
 
159
178
  def configuration
160
179
  return @configuration if @configuration
161
- features_path = File.expand_path(File.dirname(__FILE__) + "/../../../features")
162
180
  @configuration = Cucumber::Cli::Configuration.new
181
+ if !@cucumber_args.any?
182
+ @cucumber_args = [FEATURES_PATH, "--require", FEATURES_PATH]
183
+ end
163
184
  # This is ugly, but until Cucumber offers a better API, we have to pass in our settings as though
164
185
  # they were CLI arguments
165
- @configuration.parse!(@cucumber_args + [
166
- features_path,
167
- "--format", "BBC::A11y::CucumberFormatter"])
186
+ @configuration.parse!(@cucumber_args +
187
+ ["--format", "BBC::A11y::CucumberFormatter"])
168
188
  @configuration
169
189
  end
170
190
 
@@ -179,7 +199,7 @@ module BBC
179
199
  def print_page_header(page_settings)
180
200
  puts
181
201
  puts
182
- underline("BBC Accesibility: #{page_settings.url}")
202
+ puts underline("BBC Accesibility: #{page_settings.url}")
183
203
  end
184
204
 
185
205
  end
@@ -1,7 +1,10 @@
1
+ require 'bbc/a11y/cucumber_support/disabled_w3c'
1
2
  require 'bbc/a11y/cucumber_support/language_detector'
3
+ require 'bbc/a11y/cucumber_support/matchers'
2
4
  require 'bbc/a11y/cucumber_support/page'
3
- require 'bbc/a11y/cucumber_support/w3c'
4
5
  require 'bbc/a11y/cucumber_support/per_page_checks'
6
+ require 'bbc/a11y/cucumber_support/w3c'
7
+ require 'bbc/a11y/configuration'
5
8
 
6
9
  module BBC
7
10
  module A11y
@@ -17,7 +20,7 @@ module BBC
17
20
 
18
21
  # Returns an object that can validate URLs
19
22
  def w3c
20
- @w3c ||= W3C.new
23
+ @w3c ||= DisabledW3C.new
21
24
  end
22
25
 
23
26
  # An object that represents the current page being viewed in the browser
@@ -43,7 +46,11 @@ module BBC
43
46
  end
44
47
 
45
48
  end
49
+
50
+ CucumberSupport.current_page_settings ||=
51
+ Configuration::PageSettings.new(ENV['A11Y_URL'])
46
52
  end
47
53
 
48
54
  end
49
55
 
56
+
@@ -0,0 +1,37 @@
1
+ module BBC
2
+ module A11y
3
+ module CucumberSupport
4
+
5
+ class DisabledW3C
6
+
7
+ def validate(url)
8
+ raise Cucumber::Core::Test::Result::Skipped.new <<-MESSAGE
9
+ W3C validation is disabled by default as it makes off-netowrk calls
10
+ to the W3C web service and can be slow and unreliable.
11
+
12
+ To enable these checks, include the following code in your .a11y.rb
13
+ config file:
14
+
15
+ BBC::A11y.configure do
16
+ page "my_page.html" do
17
+
18
+ customize_world do
19
+ def w3c
20
+ @w3c ||= BBC::A11y::CucumberSupport::W3C.new
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ MESSAGE
27
+ end
28
+
29
+ def errors
30
+ []
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ require 'rspec/matchers'
2
+ module BBC
3
+ module A11y
4
+ module CucumberSupport
5
+ RSpec::Matchers.define :have_title_attribute_or_associated_label_tag do
6
+ match do |element|
7
+ if !element['title'].nil?
8
+ return true
9
+ end
10
+ if id = element['id']
11
+ return true if element.find_xpath("//*[for=#{id}]")
12
+ end
13
+ if element.find_xpath("..")[0].name == "label"
14
+ return true
15
+ end
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end