hof 21.0.0-instrumentation-beta.0 → 21.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. package/.github/workflows/automate-publish.yml +1 -1
  2. package/.github/workflows/automate-tag.yml +4 -4
  3. package/.nyc_output/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  4. package/.nyc_output/processinfo/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/CHANGELOG.md +21 -0
  7. package/README.md +340 -256
  8. package/build/tasks/sass/index.js +3 -1
  9. package/build/tasks/watch/index.js +1 -1
  10. package/codeReviewChecklist.md +22 -0
  11. package/components/combine-and-loop-fields/Readme.md +42 -0
  12. package/components/combine-and-loop-fields/index.js +156 -0
  13. package/components/date/index.js +3 -1
  14. package/components/date/templates/date.html +15 -12
  15. package/components/homeoffice-countries/index.js +22 -0
  16. package/components/index.js +2 -0
  17. package/components/notify/notify.js +2 -2
  18. package/components/summary/index.js +3 -2
  19. package/config/builder-defaults.js +3 -1
  20. package/config/component-defaults.js +13 -0
  21. package/config/hof-defaults.js +8 -0
  22. package/controller/controller.js +57 -1
  23. package/controller/formatting/formatters.js +12 -0
  24. package/controller/validation/index.js +2 -1
  25. package/controller/validation/validators.js +4 -0
  26. package/frontend/govuk-template/build/config.js +2 -2
  27. package/frontend/govuk-template/build/govuk_template.html +102 -0
  28. package/frontend/govuk-template/build/index.js +2 -2
  29. package/frontend/govuk-template/govuk_template_generated.html +102 -0
  30. package/frontend/govuk-template/index.js +4 -4
  31. package/frontend/template-mixins/mixins/template-mixins.js +40 -11
  32. package/frontend/template-mixins/partials/forms/checkbox-group.html +47 -0
  33. package/frontend/template-mixins/partials/forms/checkbox.html +9 -4
  34. package/frontend/template-mixins/partials/forms/input-submit.html +1 -1
  35. package/frontend/template-mixins/partials/forms/input-text-date.html +37 -0
  36. package/frontend/template-mixins/partials/forms/input-text-group.html +15 -10
  37. package/frontend/template-mixins/partials/forms/option-group.html +42 -26
  38. package/frontend/template-mixins/partials/forms/select.html +10 -5
  39. package/frontend/template-mixins/partials/forms/textarea-group.html +37 -23
  40. package/frontend/template-mixins/partials/mixins/panel.html +3 -4
  41. package/frontend/template-partials/views/accessibility.html +4 -4
  42. package/frontend/template-partials/views/cookies.html +1 -1
  43. package/frontend/template-partials/views/layout.html +24 -17
  44. package/frontend/template-partials/views/partials/back.html +1 -1
  45. package/frontend/template-partials/views/partials/bullet-list.html +1 -1
  46. package/frontend/template-partials/views/partials/confirmation-alert.html +4 -3
  47. package/frontend/template-partials/views/partials/continue.html +1 -1
  48. package/frontend/template-partials/views/partials/cookie-banner.html +27 -24
  49. package/frontend/template-partials/views/partials/cookie-settings-radio.html +6 -6
  50. package/frontend/template-partials/views/partials/external-link.html +1 -1
  51. package/frontend/template-partials/views/partials/form.html +2 -1
  52. package/frontend/template-partials/views/partials/gatag.html +0 -1
  53. package/frontend/template-partials/views/partials/head.html +23 -0
  54. package/frontend/template-partials/views/partials/maincontent-left.html +4 -4
  55. package/frontend/template-partials/views/partials/navigation.html +7 -6
  56. package/frontend/template-partials/views/partials/session-cookies-table.html +6 -6
  57. package/frontend/template-partials/views/partials/summary-table-row.html +2 -2
  58. package/frontend/template-partials/views/partials/table.html +7 -7
  59. package/frontend/template-partials/views/partials/validation-list.html +2 -2
  60. package/frontend/template-partials/views/partials/validation-summary.html +14 -13
  61. package/frontend/template-partials/views/partials/warn.html +7 -0
  62. package/frontend/template-partials/views/session-timeout.html +3 -2
  63. package/frontend/themes/gov-uk/client-js/cookieSettings.js +1 -1
  64. package/frontend/themes/gov-uk/client-js/govuk-cookies.js +121 -0
  65. package/frontend/themes/gov-uk/client-js/index.js +6 -1
  66. package/frontend/themes/gov-uk/client-js/skip-to-main.js +19 -0
  67. package/frontend/themes/gov-uk/styles/_cookie-banner.scss +51 -1
  68. package/frontend/themes/gov-uk/styles/govuk.scss +4 -0
  69. package/frontend/themes/gov-uk/styles/modules/_validation.scss +5 -5
  70. package/frontend/toolkit/assets/javascript/character-count.js +4 -4
  71. package/frontend/toolkit/assets/javascript/progressive-reveal.js +3 -1
  72. package/frontend/toolkit/assets/javascript/validation.js +5 -1
  73. package/frontend/toolkit/assets/stylesheets/modules/_validation.scss +3 -3
  74. package/index.js +15 -2
  75. package/lib/ga-tag.js +33 -7
  76. package/lib/settings.js +18 -2
  77. package/middleware/cookies.js +2 -0
  78. package/middleware/errors.js +2 -3
  79. package/middleware/not-found.js +0 -3
  80. package/middleware/rate-limiter.js +1 -0
  81. package/model/apis/axios-settings.js +21 -0
  82. package/model/apis/html-to-pdf-converter.js +10 -8
  83. package/model/index.js +102 -87
  84. package/package.json +18 -17
  85. package/pull_request.md +16 -0
  86. package/sandbox/README.md +3 -3
  87. package/sandbox/apps/sandbox/fields.js +33 -11
  88. package/sandbox/apps/sandbox/index.js +4 -0
  89. package/sandbox/apps/sandbox/sections/summary-data-sections.js +3 -0
  90. package/sandbox/apps/sandbox/translations/en/default.json +220 -0
  91. package/sandbox/apps/sandbox/translations/src/en/fields.json +11 -4
  92. package/sandbox/apps/sandbox/translations/src/en/journey.json +4 -1
  93. package/sandbox/apps/sandbox/translations/src/en/pages.json +7 -25
  94. package/sandbox/apps/sandbox/translations/src/en/validation.json +5 -1
  95. package/sandbox/assets/js/index.js +1 -1
  96. package/sandbox/assets/scss/app.scss +16 -16
  97. package/sandbox/package.json +7 -2
  98. package/sandbox/public/css/app.css +9632 -0
  99. package/sandbox/public/images/icons/icon-caret-left.png +0 -0
  100. package/sandbox/public/images/icons/icon-complete.png +0 -0
  101. package/sandbox/public/images/icons/icon-cross-remove-sign.png +0 -0
  102. package/sandbox/public/js/bundle.js +46721 -0
  103. package/sandbox/server.js +2 -1
  104. package/sandbox/yarn.lock +249 -2
  105. package/wizard/index.js +0 -13
  106. package/wizard/middleware/check-progress.js +36 -1
  107. package/.nyc_output/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  108. package/.nyc_output/processinfo/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  109. package/frontend/govuk-template/govuk_template.html +0 -109
  110. package/frontend/themes/gov-uk/views/partials/form.html +0 -9
  111. package/frontend/themes/gov-uk/views/partials/forms/option-group.html +0 -28
  112. package/frontend/themes/gov-uk/views/partials/mixins/panel.html +0 -3
  113. package/frontend/themes/gov-uk/views/partials/validation-summary.html +0 -24
  114. package/middleware/monitor.js +0 -20
  115. package/sandbox/apps/sandbox/views/confirmation.html +0 -15
package/model/index.js CHANGED
@@ -2,10 +2,10 @@
2
2
  'use strict';
3
3
 
4
4
  const _ = require('lodash');
5
- const request = require('request');
5
+ const axios = require('axios').default;
6
6
  const url = require('url');
7
7
  const EventEmitter = require('events').EventEmitter;
8
-
8
+ const axiosSetting = require('./apis/axios-settings');
9
9
  const REFERENCE = /^\$ref:/;
10
10
 
11
11
  function timeDiff(from, to, d) {
@@ -27,10 +27,10 @@ module.exports = class Model extends EventEmitter {
27
27
  this.set(attributes, {
28
28
  silent: true
29
29
  });
30
- this._request = request;
30
+ this._request = axios;
31
31
  }
32
32
 
33
- save(options, callback) {
33
+ async save(options, callback) {
34
34
  if (typeof options === 'function' && arguments.length === 1) {
35
35
  callback = options;
36
36
  options = {};
@@ -38,21 +38,18 @@ module.exports = class Model extends EventEmitter {
38
38
  options = {};
39
39
  }
40
40
 
41
- return this.prepare().then(data => {
42
- data = JSON.stringify(data);
43
- const reqConf = this.requestConfig(options);
44
- reqConf.method = options.method || 'POST';
45
-
46
- reqConf.headers = Object.assign({
47
- 'Content-Type': 'application/json',
48
- 'Content-Length': Buffer.byteLength(data)
49
- }, reqConf.headers || {});
50
-
51
- return this.request(reqConf, data, callback);
52
- });
41
+ let data = await this.prepare();
42
+ data = JSON.stringify(data);
43
+ const reqConf = this.requestConfig(options);
44
+ reqConf.method = options.method || 'POST';
45
+ reqConf.headers = Object.assign({
46
+ 'Content-Type': 'application/json',
47
+ 'Content-Length': Buffer.byteLength(data)
48
+ }, reqConf.headers || {});
49
+ return await this.request(reqConf, data, callback);
53
50
  }
54
51
 
55
- fetch(options, callback) {
52
+ async fetch(options, callback) {
56
53
  if (typeof options === 'function' && arguments.length === 1) {
57
54
  callback = options;
58
55
  options = {};
@@ -61,10 +58,10 @@ module.exports = class Model extends EventEmitter {
61
58
  }
62
59
  const reqConf = this.requestConfig(options);
63
60
  reqConf.method = options.method || 'GET';
64
- return this.request(reqConf, callback);
61
+ return await this.request(reqConf, callback);
65
62
  }
66
63
 
67
- delete(options, callback) {
64
+ async delete(options, callback) {
68
65
  if (typeof options === 'function' && arguments.length === 1) {
69
66
  callback = options;
70
67
  options = {};
@@ -73,7 +70,7 @@ module.exports = class Model extends EventEmitter {
73
70
  }
74
71
  const reqConf = this.requestConfig(options);
75
72
  reqConf.method = options.method || 'DELETE';
76
- return this.request(reqConf, callback);
73
+ return await this.request(reqConf, callback);
77
74
  }
78
75
 
79
76
  requestConfig(options) {
@@ -86,7 +83,7 @@ module.exports = class Model extends EventEmitter {
86
83
  });
87
84
  }
88
85
 
89
- request(originalSettings, body, callback) {
86
+ async request(originalSettings, body, callback) {
90
87
  if (typeof body === 'function' && arguments.length === 2) {
91
88
  callback = body;
92
89
  body = undefined;
@@ -94,96 +91,114 @@ module.exports = class Model extends EventEmitter {
94
91
 
95
92
  let settings = Object.assign({}, originalSettings);
96
93
  settings.timeout = settings.timeout || this.options.timeout;
97
- settings.uri = settings.uri || settings.url || url.format(settings);
98
- settings.body = settings.body || body || settings.data;
99
-
100
- settings = _.omit(settings, urlKeys, 'data', 'url');
94
+ settings = axiosSetting(settings, body);
95
+ settings = _.omit(settings, urlKeys);
101
96
  this.emit('sync', originalSettings);
102
97
 
103
- const promise = Promise.resolve().then(() => this.auth()).then(authData => {
104
- settings.auth = authData;
105
- if (typeof settings.auth === 'string') {
106
- const auth = settings.auth.split(':');
107
- settings.auth = {
108
- user: auth.shift(),
109
- pass: auth.join(':'),
98
+ try {
99
+ const authData = await this.auth();
100
+ let authVal = authData;
101
+ if (typeof authVal === 'string') {
102
+ const [user, ...rest] = authVal.split(':');
103
+ authVal = {
104
+ user,
105
+ pass: rest.join(':'),
110
106
  sendImmediately: true
111
107
  };
112
108
  }
113
- })
114
- .then(() => {
115
- const startTime = process.hrtime();
116
- let timeoutTimer;
117
-
118
- return new Promise((resolve, reject) => {
119
- const _callback = (err, data, statusCode) => {
120
- if (timeoutTimer) {
121
- clearTimeout(timeoutTimer);
122
- timeoutTimer = null;
123
- }
109
+ if (authVal) {
110
+ settings.headers = {
111
+ ...settings.headers,
112
+ Authorization: `Bearer ${authVal.bearer}`
113
+ };
114
+ }
124
115
 
125
- const endTime = process.hrtime();
126
- const responseTime = timeDiff(startTime, endTime);
116
+ const startTime = process.hrtime();
117
+ let timeoutTimer;
127
118
 
128
- if (err) {
129
- this.emit('fail', err, data, originalSettings, statusCode, responseTime);
130
- } else {
131
- this.emit('success', data, originalSettings, statusCode, responseTime);
132
- }
133
- if (err) {
134
- reject(err);
135
- } else {
136
- resolve(data);
137
- }
138
- };
139
-
140
- this._request(settings, (err, response) => {
141
- if (err) {
142
- if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
143
- err.message = 'Connection timed out';
144
- err.status = 504;
145
- }
146
- err.status = err.status || (response && response.statusCode) || 503;
147
- return _callback(err, null, err.status);
148
- }
149
- return this.handleResponse(response, (error, data, status) => {
150
- if (error) {
119
+ if (timeoutTimer) {
120
+ clearTimeout(timeoutTimer);
121
+ timeoutTimer = null;
122
+ }
123
+
124
+ const data = await new Promise((resolve, reject) => {
125
+ const _callback = (err, responseData, statusCode) => {
126
+ if (timeoutTimer) {
127
+ clearTimeout(timeoutTimer);
128
+ timeoutTimer = null;
129
+ }
130
+
131
+ const endTime = process.hrtime();
132
+ const responseTime = timeDiff(startTime, endTime);
133
+ if (err) {
134
+ this.emit('fail', err, responseData, originalSettings, statusCode, responseTime);
135
+ reject(err);
136
+ } else {
137
+ this.emit('success', responseData, originalSettings, statusCode, responseTime);
138
+ resolve(responseData);
139
+ }
140
+ };
141
+
142
+ this._request(settings)
143
+ .then(response => {
144
+ return this.handleResponse(response)
145
+ .then(responseData => _callback(null, responseData, response.status))
146
+ .catch(error => {
151
147
  error.headers = response.headers;
152
- }
153
- _callback(error, data, status);
154
- });
148
+ _callback(error, null, response.status);
149
+ });
150
+ })
151
+ .catch(err => {
152
+ if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
153
+ err.message = 'Connection timed out';
154
+ err.status = 504;
155
+ }
156
+ err.status = err.status || 503;
157
+ return _callback(err, null, err.status);
155
158
  });
156
- });
157
159
  });
158
160
 
159
- if (typeof callback === 'function') {
160
- return promise.then(data => callback(null, data), callback);
161
+ if (typeof callback === 'function') {
162
+ callback(null, data);
163
+ }
164
+ return data;
165
+ } catch (error) {
166
+ if (typeof callback === 'function') {
167
+ callback(error);
168
+ }
169
+ return error;
161
170
  }
162
- return promise;
163
171
  }
164
172
 
165
- handleResponse(response, callback) {
166
- let data = {};
173
+ async handleResponse(response) {
174
+ let data = null;
167
175
  try {
168
- data = JSON.parse(response.body || '{}');
176
+ if (typeof response.data === 'object') {
177
+ data = response.data;
178
+ } else if (typeof response.data === 'string' && response.data.trim() !== '') {
179
+ data = JSON.parse(response.data);
180
+ } else {
181
+ data = {};
182
+ }
169
183
  } catch (err) {
170
- err.status = response.statusCode;
171
- err.body = response.body;
172
- return callback(err, null, response.statusCode);
184
+ err.message = 'Failed to parse response data';
185
+ err.status = response.status;
186
+ err.body = response.data;
187
+ throw err;
173
188
  }
174
- return this.parseResponse(response.statusCode, data, callback);
189
+ return await this.parseResponse(response.status, data);
175
190
  }
176
191
 
177
- parseResponse(statusCode, data, callback) {
192
+ async parseResponse(statusCode, data) {
178
193
  if (statusCode < 400) {
179
194
  try {
180
- data = this.parse(data);
181
- callback(null, data, statusCode);
195
+ data = await this.parse(data);
196
+ return data;
182
197
  } catch (err) {
183
- callback(err, null, statusCode);
198
+ throw err;
184
199
  }
185
200
  } else {
186
- callback(this.parseError(statusCode, data), data, statusCode);
201
+ throw this.parseError(statusCode, data);
187
202
  }
188
203
  }
189
204
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hof",
3
3
  "description": "A bootstrap for HOF projects",
4
- "version": "21.0.0-instrumentation-beta.0",
4
+ "version": "21.0.0",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
7
7
  "author": "HomeOffice",
@@ -23,9 +23,9 @@
23
23
  "scripts": {
24
24
  "test": "yarn run unit && yarn run test:cookie-banner && yarn run test:functional && yarn run test:client && yarn run test:lint",
25
25
  "unit": "LOG_LEVEL=error nyc _mocha \"test/**/*.spec.js\" \"sandbox/test/**/*.spec.js\"",
26
- "unit:nocov": "LOG_LEVEL=error mocha",
26
+ "unit:nocov": "LOG_LEVEL=error mocha \"test/**/*.spec.js\" \"sandbox/test/**/*.spec.js\"",
27
27
  "test:lint": "eslint . --config ./node_modules/eslint-config-hof/default.js",
28
- "test:functional": "funkie mocha ./test/functional-tests --exit",
28
+ "test:functional": "funkie mocha ./test/functional-tests --timeout 20000 --exit",
29
29
  "test:client": "karma start test/frontend/toolkit/karma.conf.js",
30
30
  "test:cookie-banner": "jest test/frontend/jest",
31
31
  "test:acceptance": "TAGS=\"${TAGS:=@feature}\" yarn run test:cucumber",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "aliasify": "^2.1.0",
39
+ "axios": "^1.5.1",
39
40
  "bluebird": "^3.7.2",
40
41
  "body-parser": "^1.15.1",
41
42
  "browserify": "^17.0.0",
@@ -45,7 +46,7 @@
45
46
  "connect-redis": "^5.2.0",
46
47
  "cookie-parser": "^1.4.6",
47
48
  "cp": "^0.2.0",
48
- "csrf": "^3.0.2",
49
+ "csrf": "^3.1.0",
49
50
  "debug": "^4.3.1",
50
51
  "deprecate": "^1.0.0",
51
52
  "dotenv": "^4.0.0",
@@ -57,6 +58,7 @@
57
58
  "findup": "^0.1.5",
58
59
  "glob": "^7.2.0",
59
60
  "govuk-elements-sass": "^3.1.3",
61
+ "govuk-frontend": "3.15",
60
62
  "govuk_template_mustache": "^0.26.0",
61
63
  "helmet": "^3.22.0",
62
64
  "hogan-express-strict": "^0.5.4",
@@ -65,36 +67,36 @@
65
67
  "i18n-future": "^2.0.0",
66
68
  "i18n-lookup": "^0.1.0",
67
69
  "is-pdf": "^1.0.0",
68
- "libphonenumber-js": "^1.9.37",
70
+ "libphonenumber-js": "^1.9.44",
69
71
  "lodash": "^4.17.21",
70
72
  "markdown-it": "^12.3.2",
71
- "minimatch": "^3.0.3",
73
+ "minimatch": "^3.0.7",
72
74
  "minimist": "^1.2.6",
73
75
  "mixwith": "^0.1.1",
74
76
  "moment": "^2.29.4",
75
77
  "morgan": "^1.10.0",
76
- "mustache": "^2.3.0",
78
+ "mustache": "^4.2.0",
77
79
  "nodemailer": "^6.6.3",
78
- "nodemailer-ses-transport": "^1.5.0",
80
+ "nodemailer-ses-transport": "^1.5.1",
79
81
  "nodemailer-smtp-transport": "^2.7.4",
80
82
  "nodemailer-stub-transport": "^1.1.0",
81
- "notifications-node-client": "^5.1.1",
82
- "prom-client": "^14.0.1",
83
+ "notifications-node-client": "^6.0.0",
83
84
  "redis": "^3.1.2",
84
85
  "reqres": "^3.0.1",
85
- "request": "^2.79.0",
86
86
  "rimraf": "^3.0.2",
87
- "sass": "^1.35.2",
87
+ "sass": "^1.56.2",
88
88
  "serve-static": "^1.14.1",
89
89
  "uglify-js": "^3.14.3",
90
- "underscore": "^1.12.1",
90
+ "underscore": "^1.13.6",
91
91
  "urijs": "^1.19.11",
92
+ "uuid": "^8.3.2",
92
93
  "winston": "^3.7.2"
93
94
  },
94
95
  "devDependencies": {
95
96
  "@cucumber/cucumber": "^7.3.0",
96
97
  "@cucumber/pretty-formatter": "^1.0.0-alpha.1",
97
98
  "@types/jest": "^26.0.14",
99
+ "@xmldom/xmldom": "~0.8.4",
98
100
  "chai": "^3.5.0",
99
101
  "chai-as-promised": "^7.1.1",
100
102
  "chai-subset": "^1.6.0",
@@ -121,20 +123,19 @@
121
123
  "playwright": "^1.16.3",
122
124
  "postcode": "0.2.2",
123
125
  "proxyquire": "^1.7.11",
124
- "release-it": "^14.10.0",
126
+ "release-it": "^16.2.1",
125
127
  "sinon": "^11.1.1",
126
128
  "sinon-chai": "^3.7.0",
127
129
  "supertest": "^3.0.0",
128
130
  "travis-conditions": "0.0.0",
129
131
  "watchify": "^4.0.0",
130
- "webdriverio": "^4.14.4",
131
- "xmldom": "^0.6.0"
132
+ "webdriverio": "^4.14.4"
132
133
  },
133
134
  "mocha": {
134
135
  "reporter": "spec",
135
136
  "require": "test/common.js",
136
137
  "recursive": "true",
137
- "timeout": "6000",
138
+ "timeout": "9000",
138
139
  "exit": "true"
139
140
  },
140
141
  "resolutions": {
@@ -0,0 +1,16 @@
1
+ ## What?
2
+ ## Why?
3
+ ## How?
4
+ ## Testing?
5
+ ## Screenshots (optional)
6
+ ## Anything Else? (optional)
7
+ ## Check list
8
+
9
+ - [ ] I have reviewed my own pull request for linting issues (e.g. adding new lines)
10
+ - [ ] I have written tests (if relevant)
11
+ - [ ] I have created a JIRA number for my branch
12
+ - [ ] I have created a JIRA number for my commit
13
+ - [ ] I have followed the chris beams method for my commit https://cbea.ms/git-commit/
14
+ here is an [example commit](https://github.com/UKHomeOfficeForms/hof/commit/810959f391187c7c4af6db262bcd143b50093a6e)
15
+ - [ ] Ensure drone builds are green especially tests
16
+ - [ ] I will squash the commits before merging
package/sandbox/README.md CHANGED
@@ -45,10 +45,10 @@ Install the dependencies
45
45
  yarn
46
46
  ```
47
47
 
48
- Move into the example folder
48
+ Move into the sandbox folder
49
49
 
50
50
  ```bash
51
- cd example
51
+ cd sandbox
52
52
  ```
53
53
 
54
54
  Install any example app specific dependencies
@@ -63,4 +63,4 @@ Run in development mode
63
63
  yarn start:dev
64
64
  ```
65
65
 
66
- go to http://localhost:8080/
66
+ go to http://localhost:8082/
@@ -8,16 +8,23 @@ module.exports = {
8
8
  'landing-page-radio': {
9
9
  mixin: 'radio-group',
10
10
  validate: ['required'],
11
- legend: {
12
- className: 'visuallyhidden'
13
- },
11
+ isPageHeading: true,
12
+ // Design system says to avoid in-line unless it's two options,
13
+ // so just added as an example below but by default it isn't
14
+ className: ['govuk-radios--inline'],
14
15
  options: ['basic-form', 'complex-form', 'build-your-own-form']
15
16
  },
16
17
  name: {
17
18
  validate: ['required', 'notUrl', { type: 'maxlength', arguments: 200 }],
18
19
  },
19
- dateOfBirth: dateComponent('dateOfBirth', {
20
- validate: ['required', 'before', { type: 'after', arguments: ['1900'] }]
20
+ 'dateOfBirth': dateComponent('dateOfBirth', {
21
+ mixin: 'input-date',
22
+ isPageHeading: 'true',
23
+ validate: [
24
+ 'required',
25
+ 'date',
26
+ { type: 'after', arguments: ['1900'] }
27
+ ]
21
28
  }),
22
29
  building: {
23
30
  validate: ['required', 'notUrl', { type: 'maxlength', arguments: 100 }]
@@ -37,6 +44,7 @@ module.exports = {
37
44
  formatter: ['removespaces', 'uppercase']
38
45
  },
39
46
  incomeTypes: {
47
+ isPageHeading: 'true',
40
48
  mixin: 'checkbox-group',
41
49
  labelClassName: 'visuallyhidden',
42
50
  validate: ['required'],
@@ -49,11 +57,9 @@ module.exports = {
49
57
  ]
50
58
  },
51
59
  countryOfHearing: {
60
+ isPageHeading: 'true',
52
61
  mixin: 'radio-group',
53
62
  validate: ['required'],
54
- legend: {
55
- className: 'visuallyhidden'
56
- },
57
63
  options: [
58
64
  'englandAndWales',
59
65
  'scotland',
@@ -72,6 +78,7 @@ module.exports = {
72
78
  },
73
79
  countrySelect: {
74
80
  mixin: 'select',
81
+ isPageHeading: 'true',
75
82
  className: ['typeahead'],
76
83
  options:[''].concat(require('homeoffice-countries').allCountries),
77
84
  legend: {
@@ -81,14 +88,29 @@ module.exports = {
81
88
  },
82
89
  complaintDetails: {
83
90
  mixin: 'textarea',
84
- labelClassName: 'visuallyhidden',
85
91
  // we want to ignore default formatters as we want
86
92
  // to preserve white space
87
93
  'ignore-defaults': true,
88
94
  // apply the other default formatters
89
95
  formatter: ['trim', 'hyphens'],
96
+ isPageHeading: 'true',
90
97
  // attributes here are passed to the field element
91
- validate: ['required', { type: 'maxlength', arguments: 5000 }],
98
+ validate: ['required', { type: 'maxlength', arguments: 10 }],
99
+ attributes: [{
100
+ attribute: 'rows',
101
+ value: 8
102
+ }]
103
+ },
104
+ whatHappened: {
105
+ mixin: 'textarea',
106
+ // we want to ignore default formatters as we want
107
+ // to preserve white space
108
+ 'ignore-defaults': true,
109
+ // apply the other default formatters
110
+ formatter: ['trim', 'hyphens'],
111
+ isPageHeading: 'true',
112
+ // attributes here are passed to the field element
113
+ validate: ['required', { type: 'maxword', arguments: 10 }],
92
114
  attributes: [{
93
115
  attribute: 'rows',
94
116
  value: 8
@@ -96,7 +118,7 @@ module.exports = {
96
118
  },
97
119
  appealStages: {
98
120
  mixin: 'select',
99
- labelClassName: 'visuallyhidden',
121
+ isPageHeading: 'true',
100
122
  validate: ['required'],
101
123
  options: [{
102
124
  value: '',
@@ -66,6 +66,10 @@ module.exports = {
66
66
  },
67
67
  '/text-input-area': {
68
68
  fields: ['complaintDetails'],
69
+ next: '/word-count'
70
+ },
71
+ '/word-count': {
72
+ fields: ['whatHappened'],
69
73
  next: '/select'
70
74
  },
71
75
  '/select':{
@@ -36,5 +36,8 @@ module.exports = {
36
36
  ],
37
37
  complaintDetails: [
38
38
  'complaintDetails'
39
+ ],
40
+ whatHappened: [
41
+ 'whatHappened'
39
42
  ]
40
43
  };