govuk_publishing_components 1.10.0 → 1.11.0
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/README.md +40 -39
- data/app/assets/javascripts/govuk_publishing_components/accessibility-test.js +46 -44
- data/app/assets/stylesheets/govuk_publishing_components/application.scss +23 -11
- data/app/views/govuk_publishing_components/component_guide/component_doc/_call.html.erb +1 -1
- data/app/views/govuk_publishing_components/component_guide/component_doc/_preview.html.erb +2 -1
- data/lib/govuk_publishing_components/version.rb +1 -1
- data/lib/tasks/govuk_publishing_components_tasks.rake +22 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e46bcab548aa86ded198500c1ef47b6967a4405
|
4
|
+
data.tar.gz: b29345bd70ee782b127bbe8e5c5640a28dfe3649
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f18566d1fc8338914133467e623d20b8a31adcec1cde09f20be989987952a6cd8fb925856930cbff7bc227088c2e2913e65330170ab956cc29cdce8096d623e
|
7
|
+
data.tar.gz: 8a32cd97cfcf7d34bdfb9d0fc056e686b6300b6bb18e3bfe6838719bdfdc80ce6e3e8e33276675a5a98886dd92bebe3192b67adb63259c7a4eb7630d72a11494
|
data/README.md
CHANGED
@@ -27,23 +27,6 @@ https://government-frontend.herokuapp.com/component-guide
|
|
27
27
|
|
28
28
|
The guide includes your application’s `application.scss` and `application.js` files by default. This is [configurable](#configuration).
|
29
29
|
|
30
|
-
## Test the component guide
|
31
|
-
|
32
|
-
The gem [includes integration tests](lib/govuk_publishing_components/minitest/component_guide_test.rb) to check that your component guide and examples are error free and that they meet basic accessibility needs.
|
33
|
-
|
34
|
-
Automated accessibility tests use [aXe](https://github.com/dequelabs/axe-core). Using our `AccessibilityTest` wrapper the gem runs the aXe suite against each example and throws JavaScript errors for any violations. These JavaScript errors can be used to fail a build in CI.
|
35
|
-
|
36
|
-
### Minitest
|
37
|
-
|
38
|
-
```ruby
|
39
|
-
# component_guide_test.rb
|
40
|
-
require 'govuk_publishing_components/minitest/component_guide_test'
|
41
|
-
|
42
|
-
class ComponentGuideTest < ActionDispatch::IntegrationTest
|
43
|
-
include GovukPublishingComponents::Minitest::ComponentGuideTest
|
44
|
-
end
|
45
|
-
```
|
46
|
-
|
47
30
|
### Install gem
|
48
31
|
|
49
32
|
Add this line to your application's Gemfile in the [development and test groups](http://bundler.io/v1.12/groups.html#grouping-your-dependencies):
|
@@ -57,6 +40,30 @@ And then execute:
|
|
57
40
|
$ bundle
|
58
41
|
```
|
59
42
|
|
43
|
+
#### Integration with Heroku
|
44
|
+
|
45
|
+
To make the best use of the component guide we use Heroku to serve the current `master` build and whenever a [pull request is added](https://devcenter.heroku.com/articles/github-integration-review-apps)
|
46
|
+
|
47
|
+
When an app is deployed to Heroku it will be in `production` mode, so only gems that are in the main group will be installed and made available.
|
48
|
+
To ensure that we only load the guide on Heroku and not when deployed to _production_ we need to have the gem included in the main bundle group in the Gemfile.
|
49
|
+
For this use case we need `require: false` so that it's not loaded in _production_ but then we can manually `require` the gem in our `application.rb` based on the more complex environmental logic that we've specified.
|
50
|
+
|
51
|
+
First move the gem outside of the `development`, `test` groups and set require to false. ([example](https://github.com/alphagov/government-frontend/blob/5110d3d33f7a6b63f218b889a5afec90e6df810f/Gemfile#L11)):
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
# Gemfile
|
55
|
+
gem 'govuk_publishing_components', require: false
|
56
|
+
```
|
57
|
+
|
58
|
+
Now we can manually require the gem ([example](https://github.com/alphagov/government-frontend/blob/5110d3d33f7a6b63f218b889a5afec90e6df810f/config/application.rb#L14)):
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
# config/application.rb
|
62
|
+
if !Rails.env.production? || ENV['HEROKU_APP_NAME'].present?
|
63
|
+
require 'govuk_publishing_components'
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
60
67
|
### Mount the component guide
|
61
68
|
|
62
69
|
Mount the component guide in your application:
|
@@ -88,39 +95,33 @@ if defined?(GovukPublishingComponents)
|
|
88
95
|
end
|
89
96
|
```
|
90
97
|
|
91
|
-
|
92
|
-
|
93
|
-
The gem includes a component generator to stub the minimal files required for a component.
|
94
|
-
|
95
|
-
```ruby
|
96
|
-
rails generate govuk_publishing_components:component [component_name]
|
97
|
-
```
|
98
|
-
|
99
|
-
This will create a template, scss file and yml documentation file for a new component. It will not create a test file as this cannot be reliably done automatically across applications, but a test file will be necessary.
|
98
|
+
### Test the component guide
|
100
99
|
|
101
|
-
|
102
|
-
To make the best use of the component guide we use Heroku to serve the current `master` build and whenever a [pull request is added](https://devcenter.heroku.com/articles/github-integration-review-apps)
|
100
|
+
The gem [includes integration tests](lib/govuk_publishing_components/minitest/component_guide_test.rb) to check that your component guide and examples are error free and that they meet basic accessibility needs.
|
103
101
|
|
104
|
-
|
105
|
-
To ensure that we only load the guide on Heroku and not when deployed to _production_ we need to have the gem included in the main bundle group in the Gemfile.
|
106
|
-
For this use case we need `require: false` so that it's not loaded in _production_ but then we can manually `require` the gem in our `application.rb` based on the more complex environmental logic that we've specified.
|
102
|
+
Automated accessibility tests use [aXe](https://github.com/dequelabs/axe-core). Using our `AccessibilityTest` wrapper the gem runs the aXe suite against each example and throws JavaScript errors for any violations. These JavaScript errors can be used to fail a build in CI.
|
107
103
|
|
108
|
-
|
104
|
+
#### Minitest
|
109
105
|
|
110
106
|
```ruby
|
111
|
-
#
|
112
|
-
|
107
|
+
# component_guide_test.rb
|
108
|
+
require 'govuk_publishing_components/minitest/component_guide_test'
|
109
|
+
|
110
|
+
class ComponentGuideTest < ActionDispatch::IntegrationTest
|
111
|
+
include GovukPublishingComponents::Minitest::ComponentGuideTest
|
112
|
+
end
|
113
113
|
```
|
114
114
|
|
115
|
-
|
115
|
+
## Component generator
|
116
|
+
|
117
|
+
The gem includes a component generator to stub the minimal files required for a component.
|
116
118
|
|
117
119
|
```ruby
|
118
|
-
|
119
|
-
if !Rails.env.production? || ENV['HEROKU_APP_NAME'].present?
|
120
|
-
require 'govuk_publishing_components'
|
121
|
-
end
|
120
|
+
rails generate govuk_publishing_components:component [component_name]
|
122
121
|
```
|
123
122
|
|
123
|
+
This will create a template, scss file and yml documentation file for a new component. It will not create a test file as this cannot be reliably done automatically across applications, but a test file will be necessary.
|
124
|
+
|
124
125
|
## Automated Testing
|
125
126
|
### Visual Diff Tool
|
126
127
|
The component guide includes a visual diff tool that should make it easier to spot when you are introducing visual regressions in your components.
|
@@ -35,18 +35,16 @@
|
|
35
35
|
return callback('aXe Error: Expected results but none returned')
|
36
36
|
}
|
37
37
|
|
38
|
-
var
|
39
|
-
var incompleteWarningsObj = _processIncompleteWarnings(results.incomplete)
|
40
|
-
|
38
|
+
var consoleErrorText = _consoleErrorText(results.violations, results.url)
|
41
39
|
var bodyClass = results.violations.length === 0 ? "js-test-a11y-success" : "js-test-a11y-failed"
|
42
40
|
document.body.classList.add(bodyClass);
|
43
41
|
document.body.classList.add("js-test-a11y-finished");
|
44
42
|
|
45
|
-
callback(undefined,
|
43
|
+
callback(undefined, consoleErrorText, _processAxeResultsForPage(results))
|
46
44
|
})
|
47
45
|
}
|
48
46
|
|
49
|
-
var
|
47
|
+
var _consoleErrorText = function(violations, url) {
|
50
48
|
if (violations.length !== 0) {
|
51
49
|
return (
|
52
50
|
'\n' + 'Accessibility issues at ' +
|
@@ -68,33 +66,31 @@
|
|
68
66
|
}
|
69
67
|
}
|
70
68
|
|
71
|
-
var
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
var help = incomplete.help
|
76
|
-
var helpUrl = _formatHelpUrl(incomplete.helpUrl)
|
77
|
-
var cssSelector = incomplete.nodes.map(function (node) {
|
78
|
-
return {
|
79
|
-
'selector': node.target,
|
80
|
-
'reason': node.any.map(function(item) {
|
81
|
-
return item.message
|
82
|
-
})
|
83
|
-
}
|
84
|
-
})
|
85
|
-
|
86
|
-
return {
|
87
|
-
'summary': help,
|
88
|
-
'selectors': cssSelector,
|
89
|
-
'url': helpUrl
|
90
|
-
}
|
91
|
-
})
|
92
|
-
)
|
93
|
-
} else {
|
94
|
-
return false
|
69
|
+
var _processAxeResultsForPage = function(results) {
|
70
|
+
return {
|
71
|
+
violations: _mapSummaryAndCause(results.violations),
|
72
|
+
incompleteWarnings: _mapSummaryAndCause(results.incomplete)
|
95
73
|
}
|
96
74
|
}
|
97
75
|
|
76
|
+
var _mapSummaryAndCause = function(resultsArray) {
|
77
|
+
return resultsArray.map(function (result) {
|
78
|
+
var cssSelector = result.nodes.map(function (node) {
|
79
|
+
return {
|
80
|
+
'selector': node.target,
|
81
|
+
'reasons': node.any.map(function(item) {
|
82
|
+
return item.message
|
83
|
+
})
|
84
|
+
}
|
85
|
+
})
|
86
|
+
return {
|
87
|
+
'summary': result.help,
|
88
|
+
'selectors': cssSelector,
|
89
|
+
'url': _formatHelpUrl(result.helpUrl)
|
90
|
+
}
|
91
|
+
})
|
92
|
+
}
|
93
|
+
|
98
94
|
var _formatHelpUrl = function (helpUrl) {
|
99
95
|
if (axe.version.indexOf('alpha') === -1) {
|
100
96
|
console.warn('Deprecation warning: helpUrl formatting is no longer needed so can be deleted')
|
@@ -121,22 +117,21 @@
|
|
121
117
|
}
|
122
118
|
}
|
123
119
|
|
124
|
-
var
|
125
|
-
|
126
|
-
|
120
|
+
var _renderAxeResultsInGuide = function (resultsGroup, resultContainerSelector) {
|
121
|
+
resultsGroup.forEach(function (result) {
|
122
|
+
result.selectors.forEach(function (selectorObj) {
|
127
123
|
var activeEl = document.querySelector(selectorObj.selector)
|
128
124
|
var activeElParent = _findParent(activeEl, '[data-module="test-a11y"]')
|
129
|
-
var
|
125
|
+
var wrapper = activeElParent.querySelector(resultContainerSelector)
|
130
126
|
|
131
|
-
if (
|
132
|
-
|
133
|
-
|
134
|
-
'<p>
|
135
|
-
'<p>Element can be found using the following CSS selector: <span class="selector">' +
|
127
|
+
if (wrapper) {
|
128
|
+
var resultHTML = '<h3>' + result.summary + ' <a href="' + result.url + '">(see guidance)</a></h3>' +
|
129
|
+
'<p>' + selectorObj.reasons.join('<br />') + '</p>' +
|
130
|
+
'<p>Element can be found using the selector:<br /><span class="selector">' +
|
136
131
|
selectorObj.selector +
|
137
132
|
'</span></p>'
|
138
133
|
|
139
|
-
|
134
|
+
wrapper.insertAdjacentHTML('beforeend', resultHTML)
|
140
135
|
}
|
141
136
|
})
|
142
137
|
})
|
@@ -156,12 +151,19 @@
|
|
156
151
|
// http://responsivenews.co.uk/post/18948466399/cutting-the-mustard
|
157
152
|
if (document.addEventListener) {
|
158
153
|
document.addEventListener('DOMContentLoaded', function () {
|
159
|
-
AccessibilityTest('[data-module="test-a11y"]', function (
|
160
|
-
if (
|
161
|
-
_throwUncaughtError(
|
154
|
+
AccessibilityTest('[data-module="test-a11y"]', function (axeError, consoleErrorText, pageResults) {
|
155
|
+
if (axeError) {
|
156
|
+
_throwUncaughtError(axeError)
|
157
|
+
}
|
158
|
+
|
159
|
+
if (pageResults) {
|
160
|
+
_renderAxeResultsInGuide(pageResults.incompleteWarnings, '[data-module="test-a11y-warning"]')
|
161
|
+
_renderAxeResultsInGuide(pageResults.violations, '[data-module="test-a11y-violation"]')
|
162
|
+
}
|
163
|
+
|
164
|
+
if (consoleErrorText) {
|
165
|
+
_throwUncaughtError(consoleErrorText)
|
162
166
|
}
|
163
|
-
if (incompleteWarnings) _renderIncompleteWarnings(incompleteWarnings)
|
164
|
-
if (violations) _throwUncaughtError(violations)
|
165
167
|
})
|
166
168
|
})
|
167
169
|
}
|
@@ -127,13 +127,6 @@ $border-color: #ccc;
|
|
127
127
|
color: $black;
|
128
128
|
font-weight: bold;
|
129
129
|
}
|
130
|
-
|
131
|
-
div[class^="govuk-"] {
|
132
|
-
&:hover {
|
133
|
-
outline: 1px solid $border-color;
|
134
|
-
box-shadow: 0 0 10px $border-color;
|
135
|
-
}
|
136
|
-
}
|
137
130
|
}
|
138
131
|
|
139
132
|
.component-guide-preview--simple {
|
@@ -145,20 +138,22 @@ $border-color: #ccc;
|
|
145
138
|
}
|
146
139
|
}
|
147
140
|
|
141
|
+
.component-guide-preview--violation,
|
148
142
|
.component-guide-preview--warning {
|
149
143
|
margin-top: $gutter-half;
|
150
|
-
|
144
|
+
@include core-19;
|
151
145
|
|
152
146
|
&:empty {
|
153
147
|
display: none;
|
154
148
|
}
|
155
149
|
|
156
|
-
|
157
|
-
|
150
|
+
h3 {
|
151
|
+
@include bold-19;
|
158
152
|
}
|
159
153
|
|
154
|
+
p,
|
160
155
|
h3 {
|
161
|
-
|
156
|
+
margin-bottom: $gutter / 2;
|
162
157
|
}
|
163
158
|
|
164
159
|
h3:not(:first-child) {
|
@@ -170,6 +165,23 @@ $border-color: #ccc;
|
|
170
165
|
}
|
171
166
|
}
|
172
167
|
|
168
|
+
.component-guide-preview--warning {
|
169
|
+
border-color: $yellow;
|
170
|
+
|
171
|
+
&:before {
|
172
|
+
background-color: $yellow;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
.component-guide-preview--violation {
|
177
|
+
border-color: $red;
|
178
|
+
|
179
|
+
&:before {
|
180
|
+
background-color: $red;
|
181
|
+
color: $white;
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
173
185
|
.examples {
|
174
186
|
.component-example {
|
175
187
|
margin: 0 0 $gutter * 1.5;
|
@@ -1,3 +1,3 @@
|
|
1
1
|
<div class="component-call component-highlight" contenteditable>
|
2
|
-
<pre><code><%= example.highlight_code("\<%= render \"#{@component_doc.partial_path}\" #{example.pretty_data} %\>") %></code></pre>
|
2
|
+
<pre><code><%= example.highlight_code("\<%= render \"#{@component_doc.partial_path}\", #{example.pretty_data} %\>") %></code></pre>
|
3
3
|
</div>
|
@@ -1,4 +1,5 @@
|
|
1
1
|
<div data-module="test-a11y">
|
2
2
|
<%= render "govuk_publishing_components/component_guide/component_doc/component", component_doc: @component_doc, example: example, preview_page: false %>
|
3
|
-
<div class="component-guide-preview component-guide-preview--
|
3
|
+
<div class="component-guide-preview component-guide-preview--violation" data-module="test-a11y-violation" data-content="Accessibility Issues"></div>
|
4
|
+
<div class="component-guide-preview component-guide-preview--warning" data-module="test-a11y-warning" data-content="Potential accessibility issues: need manual check"></div>
|
4
5
|
</div>
|
@@ -1,4 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
desc 'warns if component view files exist without corresponding documentation'
|
2
|
+
task :validate_component_documentation do
|
3
|
+
components_missing_docs = []
|
4
|
+
component_views = Dir["app/views/#{GovukPublishingComponents::Config.component_directory_name}/**/*.html.erb"]
|
5
|
+
|
6
|
+
component_views.each do |partial|
|
7
|
+
expected_component_docs_file = partial.split('/')[-1].gsub('html.erb', 'yml')
|
8
|
+
expected_component_docs_file.sub!(/^_/, '')
|
9
|
+
|
10
|
+
expected_component_docs_path = "app/views/#{GovukPublishingComponents::Config.component_directory_name}/docs/#{expected_component_docs_file}"
|
11
|
+
components_missing_docs << partial unless File.exist?(expected_component_docs_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
if components_missing_docs.any?
|
15
|
+
error = "You have components which are missing documentation. These components will not be displayed in the component guide:\n"
|
16
|
+
components_missing_docs.each { |component| error += "\t" + component + "\n" }
|
17
|
+
error += "\n"
|
18
|
+
raise NotImplementedError, error
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::Task["validate_component_documentation"].invoke
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_publishing_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -243,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
243
|
version: '0'
|
244
244
|
requirements: []
|
245
245
|
rubyforge_project:
|
246
|
-
rubygems_version: 2.6.
|
246
|
+
rubygems_version: 2.6.13
|
247
247
|
signing_key:
|
248
248
|
specification_version: 4
|
249
249
|
summary: A gem to document components in GOV.UK frontend applications
|