hmpo-form-wizard 11.11.0 → 12.0.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.
- package/injection/session-injection.js +2 -2
- package/lib/controller/index.js +12 -10
- package/lib/controller/mixins/next-step.js +7 -7
- package/lib/controller/mixins/session-model.js +1 -2
- package/lib/model.js +3 -4
- package/lib/validation/index.js +1 -1
- package/lib/wizard-model.js +9 -11
- package/lib/wizard.js +2 -2
- package/package.json +8 -8
- package/test/controller/spec.index.js +1 -0
- package/test/controller/spec.lifecycle.js +1 -0
- package/test/spec.model.js +1 -1
- package/test/spec.wizard-model.js +2 -2
|
@@ -62,7 +62,7 @@ class SessionInjection {
|
|
|
62
62
|
throw new Error('No express session is available in request');
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
options =
|
|
65
|
+
options = Object.assign({}, DEFAULTS, options);
|
|
66
66
|
|
|
67
67
|
req.session.exists = options.sessionExists;
|
|
68
68
|
|
|
@@ -81,7 +81,7 @@ class SessionInjection {
|
|
|
81
81
|
setFeatureFlags(req, flags) {
|
|
82
82
|
debug('setFeatureFlags', flags);
|
|
83
83
|
if (flags) {
|
|
84
|
-
req.session.featureFlags =
|
|
84
|
+
req.session.featureFlags = Object.assign({}, flags);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
package/lib/controller/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const debug = require('debug')('hmpo:controller');
|
|
4
4
|
const _ = require('underscore');
|
|
5
5
|
const path = require('path');
|
|
6
|
-
const
|
|
6
|
+
const { URL } = require('url');
|
|
7
7
|
const ErrorClass = require('../error');
|
|
8
8
|
const deepCloneMerge = require('deep-clone-merge');
|
|
9
9
|
const express = require('express');
|
|
@@ -11,6 +11,8 @@ const express = require('express');
|
|
|
11
11
|
const formatting = require('../formatting');
|
|
12
12
|
const validation = require('../validation');
|
|
13
13
|
|
|
14
|
+
const url = req => new URL(req.originalUrl, 'http://hostname');
|
|
15
|
+
|
|
14
16
|
class BaseController {
|
|
15
17
|
constructor(options) {
|
|
16
18
|
if (!options) {
|
|
@@ -194,18 +196,18 @@ class BaseController {
|
|
|
194
196
|
// pick errorValues that were generated on the same url
|
|
195
197
|
errorValues = _.pick(errorValues, (e, k) => !errs || !errs[k] || !errs[k].url || errs[k].url === req.path);
|
|
196
198
|
|
|
197
|
-
values =
|
|
199
|
+
values = Object.assign(values, errorValues);
|
|
198
200
|
callback(null, values);
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
_locals(req, res, next) {
|
|
202
204
|
debug('%s #_locals', req.originalUrl);
|
|
203
205
|
|
|
204
|
-
|
|
206
|
+
const errorlist = _.reject(req.form.errors, (error, key) => error.errorGroup && error.errorGroup !== key);
|
|
205
207
|
|
|
206
|
-
|
|
208
|
+
const pathname = url(req).pathname;
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
Object.assign(res.locals, {
|
|
209
211
|
errors: req.form.errors,
|
|
210
212
|
errorlist,
|
|
211
213
|
values: req.form.values,
|
|
@@ -215,12 +217,12 @@ class BaseController {
|
|
|
215
217
|
});
|
|
216
218
|
|
|
217
219
|
if (this.locals.length < 3) {
|
|
218
|
-
|
|
220
|
+
Object.assign(res.locals, this.locals(req, res));
|
|
219
221
|
return next();
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
this.locals(req, res, (err, locals) => {
|
|
223
|
-
|
|
225
|
+
Object.assign(res.locals, locals);
|
|
224
226
|
next(err);
|
|
225
227
|
});
|
|
226
228
|
}
|
|
@@ -239,7 +241,7 @@ class BaseController {
|
|
|
239
241
|
return this.successHandler(req, res, next);
|
|
240
242
|
}
|
|
241
243
|
|
|
242
|
-
|
|
244
|
+
const pathname = url(req).pathname;
|
|
243
245
|
if (typeof this.post !== 'function' && res.locals.nextPage !== pathname && req.form.options.checkJourney) {
|
|
244
246
|
this.setStepComplete(req, res);
|
|
245
247
|
}
|
|
@@ -359,8 +361,8 @@ class BaseController {
|
|
|
359
361
|
}
|
|
360
362
|
let nextStep = this.getNextStep(req, res);
|
|
361
363
|
if (req.form.options.forwardQuery) {
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
+
const search = url(req).search;
|
|
365
|
+
if (search) nextStep += search;
|
|
364
366
|
}
|
|
365
367
|
res.redirect(nextStep);
|
|
366
368
|
}
|
|
@@ -30,15 +30,15 @@ module.exports = Controller => class extends Controller {
|
|
|
30
30
|
|
|
31
31
|
_getConditionFieldNames(fieldNames) {
|
|
32
32
|
if (typeof fieldNames == 'string') return fieldNames;
|
|
33
|
-
|
|
33
|
+
const fields = Object.create(null);
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const getFieldNames = fieldName => {
|
|
36
36
|
if (typeof fieldName === 'string') {
|
|
37
37
|
fields[fieldName] = fieldName;
|
|
38
38
|
} else if (_.isArray(fieldName)) {
|
|
39
|
-
|
|
39
|
+
fieldNames.forEach(getFieldNames);
|
|
40
40
|
} else {
|
|
41
|
-
|
|
41
|
+
Object.assign(fields, fieldName);
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -103,7 +103,7 @@ module.exports = Controller => class extends Controller {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
decodeConditions(req, res, nextStep) {
|
|
106
|
-
|
|
106
|
+
const fieldsUsed = [];
|
|
107
107
|
let successfulCondition = null;
|
|
108
108
|
while (_.isArray(nextStep)) {
|
|
109
109
|
let conditions = nextStep;
|
|
@@ -157,7 +157,7 @@ module.exports = Controller => class extends Controller {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
getNextStep(req, res) {
|
|
160
|
-
|
|
160
|
+
const nextStep = this.getNextStepObject(req, res);
|
|
161
161
|
|
|
162
162
|
if (nextStep.url) {
|
|
163
163
|
return this.resolvePath(req.baseUrl, nextStep.url);
|
|
@@ -167,7 +167,7 @@ module.exports = Controller => class extends Controller {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
getErrorStep(err, req, res) {
|
|
170
|
-
|
|
170
|
+
const allErrorsHaveRedirects = _.every(err, error => error.redirect);
|
|
171
171
|
|
|
172
172
|
if (allErrorsHaveRedirects) {
|
|
173
173
|
let redirect = _.find(err, error => error.redirect).redirect;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const WizardModel = require('../../wizard-model');
|
|
4
|
-
const _ = require('underscore');
|
|
5
4
|
|
|
6
5
|
module.exports = Controller => class extends Controller {
|
|
7
6
|
|
|
@@ -23,7 +22,7 @@ module.exports = Controller => class extends Controller {
|
|
|
23
22
|
req,
|
|
24
23
|
key: 'hmpo-wizard-' + req.form.options.name,
|
|
25
24
|
journeyModel: req.journeyModel,
|
|
26
|
-
fields:
|
|
25
|
+
fields: Object.assign({}, req.form.options.allFields, req.form.options.fields)
|
|
27
26
|
});
|
|
28
27
|
|
|
29
28
|
next();
|
package/lib/model.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const LocalModel = require('hmpo-model').Local;
|
|
4
|
-
const _ = require('underscore');
|
|
5
4
|
|
|
6
5
|
class SessionModel extends LocalModel {
|
|
7
6
|
constructor(attrs, options) {
|
|
@@ -19,7 +18,7 @@ class SessionModel extends LocalModel {
|
|
|
19
18
|
throw new Error('session-model - key must be defined');
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
super(
|
|
21
|
+
super(null, options);
|
|
23
22
|
|
|
24
23
|
let initialValues = this.getSessionData();
|
|
25
24
|
this.set(initialValues, { silent: true });
|
|
@@ -41,7 +40,7 @@ class SessionModel extends LocalModel {
|
|
|
41
40
|
|
|
42
41
|
updateSessionData(changes) {
|
|
43
42
|
let session = this.options.req.session;
|
|
44
|
-
|
|
43
|
+
Object.assign(session[this.options.key], changes);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
resetSessionData() {
|
|
@@ -62,7 +61,7 @@ class SessionModel extends LocalModel {
|
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
_reload() {
|
|
65
|
-
this.attributes =
|
|
64
|
+
this.attributes = Object.create(null);
|
|
66
65
|
let data = this.getSessionData();
|
|
67
66
|
this.set(data, { silent: true });
|
|
68
67
|
}
|
package/lib/validation/index.js
CHANGED
|
@@ -33,7 +33,7 @@ function applyValidator(validator, key, value, field, context) {
|
|
|
33
33
|
let result = validator.fn.apply(context, [value].concat(validator.arguments));
|
|
34
34
|
|
|
35
35
|
if (!result) {
|
|
36
|
-
return
|
|
36
|
+
return Object.assign({
|
|
37
37
|
key: key,
|
|
38
38
|
errorGroup: field.errorGroup
|
|
39
39
|
}, _.omit(validator, 'fn'));
|
package/lib/wizard-model.js
CHANGED
|
@@ -39,28 +39,26 @@ class WizardModel extends SessionModel {
|
|
|
39
39
|
getSessionData() {
|
|
40
40
|
let defaults = this.getDefaults();
|
|
41
41
|
let wizardData = super.getSessionData();
|
|
42
|
-
let journeyData = _.mapObject(
|
|
42
|
+
let journeyData = _.omit(_.mapObject(
|
|
43
43
|
this.getJourneyKeys(),
|
|
44
44
|
journeyKey => this.options.journeyModel.get(journeyKey)
|
|
45
|
-
);
|
|
46
|
-
return
|
|
45
|
+
), _.isUndefined);
|
|
46
|
+
return Object.assign({}, defaults, wizardData, journeyData);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
resetSessionData() {
|
|
50
50
|
super.resetSessionData();
|
|
51
|
-
|
|
52
|
-
this.attributes = this.getSessionData();
|
|
51
|
+
this._reload();
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
updateSessionData(changes) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
const journeyKeys = this.getJourneyKeys();
|
|
56
|
+
const journeyChanges = Object.create(null);
|
|
57
|
+
const wizardChanges = Object.create(null);
|
|
59
58
|
|
|
60
59
|
_.each(changes, (value, key) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
journeyChanges[journeyKey] = value;
|
|
60
|
+
if (Object.prototype.hasOwnProperty.call(journeyKeys, key)) {
|
|
61
|
+
journeyChanges[journeyKeys[key]] = value;
|
|
64
62
|
} else {
|
|
65
63
|
wizardChanges[key] = value;
|
|
66
64
|
}
|
package/lib/wizard.js
CHANGED
|
@@ -16,7 +16,7 @@ let wizard = function (steps, fields, wizardOptions) {
|
|
|
16
16
|
|
|
17
17
|
// process step options and merge with wizard options
|
|
18
18
|
let processedSteps = _.mapObject(steps, (options, route) => {
|
|
19
|
-
options =
|
|
19
|
+
options = Object.assign({
|
|
20
20
|
route,
|
|
21
21
|
params: '',
|
|
22
22
|
controller: Controller,
|
|
@@ -35,7 +35,7 @@ let wizard = function (steps, fields, wizardOptions) {
|
|
|
35
35
|
}, wizardOptions, options);
|
|
36
36
|
|
|
37
37
|
// convert field list to field definitions
|
|
38
|
-
if (
|
|
38
|
+
if (Array.isArray(options.fields)) {
|
|
39
39
|
options.fields = _.object(
|
|
40
40
|
options.fields,
|
|
41
41
|
_.map(options.fields, f => fields[f] || {} )
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hmpo-form-wizard",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Routing and request handling for a multi-step form processes",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"author": "HMPO",
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=
|
|
19
|
+
"node": ">=10"
|
|
20
20
|
},
|
|
21
21
|
"bugs": {
|
|
22
22
|
"url": "https://github.com/UKHomeOffice/passports-form-wizard/issues"
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"body-parser": "^1.19.0",
|
|
27
27
|
"csrf": "^3.1.0",
|
|
28
|
-
"debug": "^4.3.
|
|
29
|
-
"deep-clone-merge": "^1.5.
|
|
30
|
-
"hmpo-model": "^
|
|
28
|
+
"debug": "^4.3.3",
|
|
29
|
+
"deep-clone-merge": "^1.5.3",
|
|
30
|
+
"hmpo-model": "^4.0.1",
|
|
31
31
|
"json5": "^2.2.0",
|
|
32
32
|
"moment": "^2.29.1",
|
|
33
33
|
"underscore": "^1.13.1"
|
|
@@ -37,13 +37,13 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"chai": "^4.3.4",
|
|
40
|
-
"eslint": "^
|
|
40
|
+
"eslint": "^8.3.0",
|
|
41
41
|
"express": "^4.17.1",
|
|
42
|
-
"mocha": "^9.
|
|
42
|
+
"mocha": "^9.1.3",
|
|
43
43
|
"nyc": "^15.1.0",
|
|
44
44
|
"proxyquire": "^2.1.3",
|
|
45
45
|
"reqres": "^3.0.1",
|
|
46
|
-
"sinon": "^
|
|
46
|
+
"sinon": "^12.0.1",
|
|
47
47
|
"sinon-chai": "^3.7.0"
|
|
48
48
|
},
|
|
49
49
|
"mocha": {
|
package/test/spec.model.js
CHANGED
|
@@ -149,7 +149,7 @@ describe('session model', () => {
|
|
|
149
149
|
it('should reset the sessionModel attributes', () => {
|
|
150
150
|
sessionModel.attributes = { foo: 'bar '};
|
|
151
151
|
sessionModel._reload();
|
|
152
|
-
sessionModel.attributes.
|
|
152
|
+
expect(sessionModel.attributes).to.eql({});
|
|
153
153
|
});
|
|
154
154
|
|
|
155
155
|
it('should silently set the sessionModel with session data', () => {
|
|
@@ -104,7 +104,7 @@ describe('wizard model', () => {
|
|
|
104
104
|
wizardModel.getSessionData().should.deep.equal({
|
|
105
105
|
a: 'val1', // from wizard data
|
|
106
106
|
b: 'bar', // from journey data
|
|
107
|
-
c: 'baz',
|
|
107
|
+
c: 'baz', // from default
|
|
108
108
|
d: 'bam' // from default
|
|
109
109
|
});
|
|
110
110
|
});
|
|
@@ -119,7 +119,7 @@ describe('wizard model', () => {
|
|
|
119
119
|
wizardModel.reset();
|
|
120
120
|
wizardModel.toJSON().should.deep.equal({
|
|
121
121
|
b: 'bar', // from journey data
|
|
122
|
-
c: 'baz',
|
|
122
|
+
c: 'baz', // from default
|
|
123
123
|
d: 'bam' // from default
|
|
124
124
|
});
|
|
125
125
|
});
|