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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 231f4e05eaee81049ea4f72bf5ec1ced16026e3f
4
- data.tar.gz: f1564c8de553159a32af562e96dcca4931f2a554
3
+ metadata.gz: 8e46bcab548aa86ded198500c1ef47b6967a4405
4
+ data.tar.gz: b29345bd70ee782b127bbe8e5c5640a28dfe3649
5
5
  SHA512:
6
- metadata.gz: a32780c774231f52e107781140fa301643437b5ff976b63f7fc3f3e2b3a41ecbb786aa742c738039dac6bff514b770f1d7a70cd468e16b56be704ebd1ab04d81
7
- data.tar.gz: '0724197ba6f3f37e563bd7b24826d1fb9c8b1942b39332d3fe21d9b6c12d3a1751ebd2dcccba59c45bd248d3ae6777327299283554a6b25d47b725f9517ebbe9'
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
- ## Component generator
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
- ## Integration with Heroku
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
- 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.
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
- 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)):
104
+ #### Minitest
109
105
 
110
106
  ```ruby
111
- # Gemfile
112
- gem 'govuk_publishing_components', require: false
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
- Now we can manually require the gem ([example](https://github.com/alphagov/government-frontend/blob/5110d3d33f7a6b63f218b889a5afec90e6df810f/config/application.rb#L14)):
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
- # config/application.rb
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 errorText = _processViolations(results.violations, results.url)
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, errorText, incompleteWarningsObj)
43
+ callback(undefined, consoleErrorText, _processAxeResultsForPage(results))
46
44
  })
47
45
  }
48
46
 
49
- var _processViolations = function(violations, url) {
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 _processIncompleteWarnings = function(incompleteWarnings) {
72
- if (incompleteWarnings.length !== 0) {
73
- return (
74
- incompleteWarnings.map(function (incomplete) {
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 _renderIncompleteWarnings = function (incompleteWarnings) {
125
- incompleteWarnings.forEach(function (warning) {
126
- warning.selectors.forEach(function (selectorObj) {
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 warningWrapper = activeElParent.querySelector('[data-module="test-a11y-warning"]')
125
+ var wrapper = activeElParent.querySelector(resultContainerSelector)
130
126
 
131
- if (warningWrapper) {
132
- // Add warning to warnings box
133
- var warningsHTML = '<h3>' + warning.summary + ' <a href="' + warning.url + '">(see guidance)</a></h3>' +
134
- '<p>Reason: ' + selectorObj.reason + '</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
- warningWrapper.insertAdjacentHTML('beforeend', warningsHTML)
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 (err, violations, incompleteWarnings) {
160
- if (err) {
161
- _throwUncaughtError(err)
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
- border-color: $yellow;
144
+ @include core-19;
151
145
 
152
146
  &:empty {
153
147
  display: none;
154
148
  }
155
149
 
156
- &:before {
157
- background-color: $yellow;
150
+ h3 {
151
+ @include bold-19;
158
152
  }
159
153
 
154
+ p,
160
155
  h3 {
161
- @include bold-16;
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--warning" data-module="test-a11y-warning" data-content="Potential Accessibility Issues: Need Manual Check"></div>
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,3 +1,3 @@
1
1
  module GovukPublishingComponents
2
- VERSION = '1.10.0'.freeze
2
+ VERSION = '1.11.0'.freeze
3
3
  end
@@ -1,4 +1,22 @@
1
- # desc "Explaining what the task does"
2
- # task :govuk_publishing_components do
3
- # # Task goes here
4
- # end
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.10.0
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-21 00:00:00.000000000 Z
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.8
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