Skip to content

Commit

Permalink
Merge pull request #1151 from alphagov/a11y-testing
Browse files Browse the repository at this point in the history
Enable automated accessibility testing
  • Loading branch information
fofr committed Sep 25, 2017
2 parents ceca9a5 + fc66f42 commit f7fc777
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 34 deletions.
3 changes: 2 additions & 1 deletion Gemfile
Expand Up @@ -12,7 +12,7 @@ gem 'sass-rails', "5.0.6"
gem 'airbrake', github: 'alphagov/airbrake', branch: 'silence-dep-warnings-for-rails-5'
gem 'nokogiri', "~> 1.7"
gem 'redis', "~> 3.3.3"
gem 'govuk_publishing_components', '~> 1.9.0', require: false
gem 'govuk_publishing_components', '~> 1.10.0', require: false

group :development do
gem 'image_optim', '0.17.1'
Expand All @@ -21,6 +21,7 @@ group :development do
end

group :test do
gem 'poltergeist', require: false
gem 'capybara', '~> 2.5.0'
gem 'govuk-content-schema-test-helpers', '~> 1.4'
gem 'mocha', '~> 1.1.0', require: false
Expand Down
10 changes: 8 additions & 2 deletions Gemfile.lock
Expand Up @@ -69,6 +69,7 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
cliver (0.3.2)
coderay (1.1.0)
commander (4.4.3)
highline (~> 1.7.2)
Expand Down Expand Up @@ -110,7 +111,7 @@ GEM
govuk_frontend_toolkit (7.0.1)
railties (>= 3.1.0)
sass (>= 3.2.0)
govuk_publishing_components (1.9.0)
govuk_publishing_components (1.10.0)
govspeak (>= 5.0.3)
govuk_frontend_toolkit
rails (>= 5.0.0.1)
Expand Down Expand Up @@ -179,6 +180,10 @@ GEM
ast (~> 2.2)
phantomjs (2.1.1.0)
plek (1.11.0)
poltergeist (1.16.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
power_assert (0.2.4)
powerpack (0.1.1)
progress (3.1.0)
Expand Down Expand Up @@ -308,7 +313,7 @@ DEPENDENCIES
govuk-content-schema-test-helpers (~> 1.4)
govuk-lint (~> 0.6.0)
govuk_frontend_toolkit (~> 7.0.1)
govuk_publishing_components (~> 1.9.0)
govuk_publishing_components (~> 1.10.0)
govuk_template (= 0.22.2)
image_optim (= 0.17.1)
jasmine-rails (~> 0.14.1)
Expand All @@ -318,6 +323,7 @@ DEPENDENCIES
mocha (~> 1.1.0)
nokogiri (~> 1.7)
plek (= 1.11.0)
poltergeist
pry
rack_strip_client_ip (= 0.0.2)
rails (~> 5.1)
Expand Down
10 changes: 10 additions & 0 deletions app/assets/javascripts/govuk-component/option-select.js
Expand Up @@ -14,6 +14,7 @@
this.$optionsContainer = this.$optionSelect.find('.options-container');
this.$optionList = this.$optionsContainer.children('.js-auto-height-inner');

this.setCheckboxAriaControlsAttributes();
this.attachCheckedCounter();

// Performance in ie 6/7 is not good enough to support animating the opening/closing
Expand Down Expand Up @@ -70,6 +71,15 @@

};

OptionSelect.prototype.setCheckboxAriaControlsAttributes = function setCheckboxAriaControlsAttributes(){
var controls = this.$optionSelect.data('input-aria-controls');
if (typeof controls === "string" && $('#' + controls).length > 0) {
this.$optionSelect.find('input[type="checkbox"]').each(function() {
$(this).attr('aria-controls', controls);
});
}
};

OptionSelect.prototype.attachCheckedCounter = function attachCheckedCounter(){
this.$optionSelect.find('.js-container-head').append('<div class="js-selected-counter">'+this.checkedString()+'</div>');
};
Expand Down
Expand Up @@ -34,7 +34,7 @@
@import "colours"; // Cabinet Office colour palette (feel free to choose your own)
$chart-border: $white; // Chart border colour
$key-border: $white; // Key border colour
$bar-colours: $light-blue, $turquoise, $green, $grass-green, $yellow, $orange, $red, $mellow-red;
$bar-colours: $govuk-blue, $turquoise, $green, $grass-green, $yellow, $orange, $red, $mellow-red;

// HELPER MIXINS

Expand Down
@@ -1,30 +1,31 @@
$highlight-answer-bg-color: #28a197;
$highlight-answer-color: #fff;

.govuk-govspeak .highlight-answer {
.govuk-govspeak .highlight-answer {
background-color: $highlight-answer-bg-color;
color: $highlight-answer-color;
text-align: center;
padding: 0.1em 2em 0.2em;
padding: 1.75em 0.75em 1.25em;
margin: 0 -1em 1em;

p {
line-height: 2.3em;
@include bold-24;
color: $highlight-answer-color;

em {
font-size: 2.45em;
font-style: normal;
font-weight: 700;
@include bold-80;
display: block;
margin-bottom: 0.5em;
padding-top: 0.1em;
color: $highlight-answer-color;
}
}

p:last-child {
margin-bottom: 0;
}

@include media-down(mobile) {
margin: 0 0 1em;

@include core-48;

p {
Expand All @@ -33,6 +34,7 @@ $highlight-answer-color: #fff;

em {
font-size: 1em;
padding-top: 0;
display: inline;
}
}
Expand Down
13 changes: 13 additions & 0 deletions app/views/govuk_component/docs/govspeak.yml
Expand Up @@ -608,11 +608,24 @@ examples:
</li>
</ol>
highlight_answer:
description: |
Used on:
* [https://gov.uk/vat-rates](https://gov.uk/vat-rates)
* [https://gov.uk/junior-individual-savings-accounts](https://gov.uk/junior-individual-savings-accounts)
* [https://gov.uk/individual-savings-accounts](https://gov.uk/individual-savings-accounts)
* [https://gov.uk/corporation-tax-rates](https://gov.uk/corporation-tax-rates)
data:
content: |
<div class="highlight-answer">
<p>The VAT rate is <em>20%</em></p>
</div>
<div class="highlight-answer">
<p>In the 2017 to 2018 tax year, the savings limit for Junior <abbr title="Individual Savings Accounts">ISAs</abbr> is <em>£4,128</em></p>
</div>
<div class="highlight-answer">
<p>In the 2017 to 2018 tax year, the maximum you can save in <abbr title="Individual Savings Accounts">ISAs</abbr> is <em>£20,000</em></p>
</div>
place:
data:
content: |
Expand Down
10 changes: 9 additions & 1 deletion app/views/govuk_component/docs/option_select.yml
Expand Up @@ -2,7 +2,11 @@ name: Option select
description: A scrollable list of checkboxes to be displayed on a form where one might
otherwise use a multi-select
accessibility_criteria: |
Options on desktop should not be full width to let users interact with the scrollbar without accidentally clicking an option
The option select inputs must:
* have a space to the right when the box is scrollable so that users can interact with a scrollbar without accidentally clicking an option
* only include an `aria-controls` attribute if an element with the ID specified exists on the page
* be [grouped with a label](https://www.w3.org/WAI/GL/wiki/Using_grouping_roles_to_identify_related_form_controls)
examples:
default:
data:
Expand Down Expand Up @@ -69,6 +73,10 @@ examples:
label: Mash
id: mash
with_aria_controls:
description: |
aria_controls_id adds an [`aria-controls` attribute](https://tink.uk/using-the-aria-controls-attribute/) to each checkbox input. This makes it easier for users of assitive tech to jump from them to the part of the page they’re updating.
The aria_controls_id must be set to the ID of an element that’s on the page or it won’t be included.
data:
key: with_aria-control_set
title: List of options
Expand Down
26 changes: 12 additions & 14 deletions app/views/govuk_component/option_select.raw.html.erb
@@ -1,25 +1,23 @@
<div class="govuk-option-select" <% if local_assigns.include?(:closed_on_load) && closed_on_load %>data-closed-on-load="true"<% end %>>
<% title_id = "option-select-title-#{title.parameterize}" %>
<div class="govuk-option-select"
<% if local_assigns.include?(:closed_on_load) && closed_on_load %>data-closed-on-load="true"<% end %>
<% if local_assigns.include?(:aria_controls_id) %>data-input-aria-controls="<%= aria_controls_id %>"<% end %>
>
<div class="container-head js-container-head">
<div class='option-select-label'><%= title %></div>
<div class="option-select-label" id="<%= title_id %>">
<%= title %>
</div>
</div>
<div class='options-container' id='<%= options_container_id %>'>
<div class='js-auto-height-inner'>
<div role="group" aria-labelledby="<%= title_id %>" class="options-container" id="<%= options_container_id %>">
<div class="js-auto-height-inner">
<% options.each do | option |%>
<label for='<%= key %>-<%= option[:id] %>'>
<label for="<%= key %>-<%= option[:id] %>">
<input
name="<%= key %>[]"
value="<%= option[:value]%>"
id="<%= key %>-<%= option[:id]%>"
type="checkbox"

<% if local_assigns.include?(:aria_controls_id) %>
aria-controls="<%= aria_controls_id %>"
<% end %>
<% if option[:checked].present? %>
checked="checked"
<% end %>

<% if option[:checked].present? %>checked="checked"<% end %>
>
<%= option[:label] %>
</label>
Expand Down
29 changes: 29 additions & 0 deletions spec/javascripts/govuk-component/option-select-spec.js
Expand Up @@ -77,6 +77,35 @@ describe('GOVUK.OptionSelect', function() {
expect($closedOnLoadFixture.find('button').attr('aria-expanded')).toBe('false');
});

it('ignores aria-controls if the referenced element isn’t present', function(){
$fixture = $('<div class="govuk-option-select" data-input-aria-controls="element-missing">' +
'<input type="checkbox">' +
'<input type="checkbox">' +
'</div>');

$('body').append($fixture);
optionSelect = new GOVUK.OptionSelect({$el:$fixture});
expect($fixture.find('input[aria-controls]').length).toBe(0);

$fixture.remove();
});

it('adds aria-controls attributes to all checkboxes if the referenced element is on the page', function(){
$controls = $('<div id="element-present"></div>');
$fixture = $('<div class="govuk-option-select" data-input-aria-controls="element-present">' +
'<input type="checkbox">' +
'<input type="checkbox">' +
'</div>');

$('body').append($controls).append($fixture);
optionSelect = new GOVUK.OptionSelect({$el:$fixture});
expect($fixture.find('input[aria-controls]').length).toBe(2);
expect($fixture.find('input[aria-controls]').attr('aria-controls')).toBe('element-present');

$fixture.remove();
$controls.remove();
});

it('instantiates an open option-select if data-closed-on-load is false', function(){
openOnLoadFixture = '<div class="govuk-option-select" data-closed-on-load=false>' +
'<div class="container-head js-container-head"></div>' +
Expand Down
2 changes: 1 addition & 1 deletion test/govuk_component/option_select_test.rb
Expand Up @@ -61,7 +61,7 @@ def option_select_arguments
arguments[:aria_controls_id] = "aria-controls-id"
render_component(arguments)

assert_select 'input[aria-controls="aria-controls-id"]', count: 2
assert_select '[data-input-aria-controls="aria-controls-id"]', count: 1
end

test "can begin with the options box closed on load" do
Expand Down
20 changes: 14 additions & 6 deletions test/integration/component_guide_test.rb
@@ -1,6 +1,7 @@
require 'integration_test_helper'
require 'webmock/minitest'
require 'slimmer/test_helpers/govuk_components'
require 'govuk_publishing_components/minitest/component_guide_test'

module GovukPublishingComponentsSkipSlimmer
extend ActiveSupport::Concern
Expand All @@ -16,23 +17,30 @@ def skip_slimmer

GovukPublishingComponents::ApplicationController.include(GovukPublishingComponentsSkipSlimmer)

# Tests aren't going through Slimmer so we need to explicitly include styles
GovukPublishingComponents.configure do |c|
c.application_print_stylesheet = "core-layout-print"
c.application_stylesheet = "core-layout"
end

class ComponentGuideTest < ActionDispatch::IntegrationTest
include GovukPublishingComponents::Minitest::ComponentGuideTest
include Slimmer::TestHelpers::GovukComponents

def setup
WebMock.disable_net_connect!(allow_localhost: true)
Capybara.current_driver = Capybara.javascript_driver
stub_shared_component_locales
end

context "component guide" do
should "render an index" do
should "render govuk_components locally" do
visit "/component-guide"
assert page.has_selector? "title", text: 'Static Component Guide', visible: false
assert page.has_selector? '.pub-c-title', text: 'Static Component Guide'
end
end

should "render all component previews without erroring" do
visit '/component-guide'
all(:css, '.component-list a').map { |el| "#{el[:href]}/preview" }.each { |component| visit component }
end
def teardown
Capybara.use_default_driver
end
end
12 changes: 12 additions & 0 deletions test/integration_test_helper.rb
@@ -1,6 +1,18 @@
require_relative 'test_helper'
require 'rack/test'
require 'capybara/rails'
require 'capybara/poltergeist'
require 'phantomjs'

# TODO: Remove when PhantomJS updated on Puppet
# Use modern PhantomJS version via gem
# Based on: https://github.com/colszowka/phantomjs-gem/blob/master/lib/phantomjs/poltergeist.rb
Phantomjs.path
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, phantomjs: Phantomjs.path, timeout: 2.minutes)
end

Capybara.javascript_driver = :poltergeist

class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
include Rack::Test::Methods
Expand Down

0 comments on commit f7fc777

Please sign in to comment.