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.
@@ -62,7 +62,7 @@ class SessionInjection {
62
62
  throw new Error('No express session is available in request');
63
63
  }
64
64
 
65
- options = _.extend({}, DEFAULTS, 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 = _.extend({}, flags);
84
+ req.session.featureFlags = Object.assign({}, flags);
85
85
  }
86
86
  }
87
87
 
@@ -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 url = require('url');
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 = _.extend(values, errorValues);
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
- let errorlist = _.reject(req.form.errors, (error, key) => error.errorGroup && error.errorGroup !== key);
206
+ const errorlist = _.reject(req.form.errors, (error, key) => error.errorGroup && error.errorGroup !== key);
205
207
 
206
- let pathname = url.parse(req.originalUrl).pathname;
208
+ const pathname = url(req).pathname;
207
209
 
208
- _.extend(res.locals, {
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
- _.extend(res.locals, this.locals(req, res));
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
- _.extend(res.locals, locals);
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
- let pathname = url.parse(req.originalUrl).pathname;
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
- let parsed = url.parse(req.originalUrl);
363
- if (parsed && parsed.search) nextStep += parsed.search;
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
- let fields = {};
33
+ const fields = Object.create(null);
34
34
 
35
- let getFieldNames = fieldName => {
35
+ const getFieldNames = fieldName => {
36
36
  if (typeof fieldName === 'string') {
37
37
  fields[fieldName] = fieldName;
38
38
  } else if (_.isArray(fieldName)) {
39
- _.each(fieldNames, getFieldNames);
39
+ fieldNames.forEach(getFieldNames);
40
40
  } else {
41
- _.extend(fields, fieldName);
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
- let fieldsUsed = [];
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
- let nextStep = this.getNextStepObject(req, res);
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
- let allErrorsHaveRedirects = _.every(err, error => error.redirect);
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: _.extend({}, req.form.options.allFields, req.form.options.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({}, options);
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
- _.extend(session[this.options.key], changes);
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
  }
@@ -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 _.extend({
36
+ return Object.assign({
37
37
  key: key,
38
38
  errorGroup: field.errorGroup
39
39
  }, _.omit(validator, 'fn'));
@@ -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 _.defaults(journeyData, wizardData, defaults);
45
+ ), _.isUndefined);
46
+ return Object.assign({}, defaults, wizardData, journeyData);
47
47
  }
48
48
 
49
49
  resetSessionData() {
50
50
  super.resetSessionData();
51
- // load in journey and defaults after reset
52
- this.attributes = this.getSessionData();
51
+ this._reload();
53
52
  }
54
53
 
55
54
  updateSessionData(changes) {
56
- let journeyKeys = this.getJourneyKeys();
57
- let journeyChanges = {};
58
- let wizardChanges = {};
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
- let journeyKey = journeyKeys[key];
62
- if (journeyKey) {
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 = _.extend({
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 (_.isArray(options.fields)) {
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": "11.11.0",
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": ">=8"
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.2",
29
- "deep-clone-merge": "^1.5.2",
30
- "hmpo-model": "^3.2.2",
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": "^7.31.0",
40
+ "eslint": "^8.3.0",
41
41
  "express": "^4.17.1",
42
- "mocha": "^9.0.2",
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": "^11.1.1",
46
+ "sinon": "^12.0.1",
47
47
  "sinon-chai": "^3.7.0"
48
48
  },
49
49
  "mocha": {
@@ -28,6 +28,7 @@ describe('Form Controller', () => {
28
28
  };
29
29
  req = request({
30
30
  method: 'GET',
31
+ protocol: 'http',
31
32
  originalUrl: '/base/route?this=is&a=query',
32
33
  url: '/route',
33
34
  baseUrl: '/base',
@@ -21,6 +21,7 @@ describe('Controller Lifecycle', () => {
21
21
  };
22
22
  req = request({
23
23
  method: 'GET',
24
+ protocol: 'http:',
24
25
  originalUrl: '/base/route',
25
26
  url: '/route',
26
27
  baseUrl: '/base',
@@ -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.should.eql({});
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', // from default
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', // from default
122
+ c: 'baz', // from default
123
123
  d: 'bam' // from default
124
124
  });
125
125
  });