@planning-inspectorate/dynamic-forms 3.13.0 → 3.14.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/package.json +1 -1
- package/src/questions/question.js +1 -8
- package/src/questions/question.test.js +13 -0
- package/src/validator/base-validator.js +10 -0
- package/src/validator/date-validator.js +48 -24
- package/src/validator/date-validator.test.js +103 -0
- package/src/validator/required-validator.js +4 -0
- package/test/is-required.test.js +130 -0
- package/types/src/questions/question.d.ts.map +1 -1
- package/types/src/validator/address-validator.d.ts +0 -1
- package/types/src/validator/address-validator.d.ts.map +1 -1
- package/types/src/validator/base-validator.d.ts +7 -0
- package/types/src/validator/base-validator.d.ts.map +1 -1
- package/types/src/validator/date-validator.d.ts +6 -4
- package/types/src/validator/date-validator.d.ts.map +1 -1
- package/types/src/validator/multi-field-input-validator.d.ts +0 -1
- package/types/src/validator/multi-field-input-validator.d.ts.map +1 -1
- package/types/src/validator/required-validator.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import escape from 'escape-html';
|
|
2
|
-
import RequiredValidator from '../validator/required-validator.js';
|
|
3
2
|
import { capitalize, nl2br, trimTrailingSlash } from '../lib/utils.js';
|
|
4
|
-
import AddressValidator from '../validator/address-validator.js';
|
|
5
3
|
import MultiFieldInputValidator from '../validator/multi-field-input-validator.js';
|
|
6
4
|
import { answerObjectForManageList } from '#src/components/manage-list/utils.js';
|
|
7
5
|
|
|
@@ -454,12 +452,7 @@ export class Question {
|
|
|
454
452
|
* @returns {boolean}
|
|
455
453
|
*/
|
|
456
454
|
isRequired() {
|
|
457
|
-
return this.validators?.some(
|
|
458
|
-
(item) =>
|
|
459
|
-
item instanceof RequiredValidator ||
|
|
460
|
-
(item instanceof AddressValidator && item.isRequired()) ||
|
|
461
|
-
(item instanceof MultiFieldInputValidator && item.isRequired())
|
|
462
|
-
);
|
|
455
|
+
return this.validators?.some((validator) => validator.isRequired());
|
|
463
456
|
}
|
|
464
457
|
/**
|
|
465
458
|
* @param {string} inputField
|
|
@@ -437,4 +437,17 @@ describe('./src/dynamic-forms/question.js', () => {
|
|
|
437
437
|
});
|
|
438
438
|
});
|
|
439
439
|
});
|
|
440
|
+
|
|
441
|
+
describe('isRequired', () => {
|
|
442
|
+
it('should not be required if no validators', () => {
|
|
443
|
+
const q = getTestQuestion({ validators: [] });
|
|
444
|
+
assert.strictEqual(q.isRequired(), false);
|
|
445
|
+
});
|
|
446
|
+
it('should be required if any validator is required', () => {
|
|
447
|
+
const q = getTestQuestion({
|
|
448
|
+
validators: [{ isRequired: () => false }, { isRequired: () => true }]
|
|
449
|
+
});
|
|
450
|
+
assert.strictEqual(q.isRequired(), true);
|
|
451
|
+
});
|
|
452
|
+
});
|
|
440
453
|
});
|
|
@@ -26,6 +26,16 @@ export class BaseValidator {
|
|
|
26
26
|
validate(questionObj, journeyResponse) {
|
|
27
27
|
throw new Error('validate method must be implemented by subclass');
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Should the question that this validator is configured with be treated as a required question?
|
|
32
|
+
*
|
|
33
|
+
* Validators should override this method as appropriate, implementing any custom required logic.
|
|
34
|
+
* For example, the AddressValidator is configurable and is required if any one field is required.
|
|
35
|
+
*/
|
|
36
|
+
isRequired() {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
export default BaseValidator;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { body } from 'express-validator';
|
|
2
|
-
|
|
3
2
|
import { isAfter, isBefore, isValid, parse } from 'date-fns';
|
|
4
3
|
import { enGB } from 'date-fns/locale';
|
|
5
4
|
|
|
@@ -12,8 +11,9 @@ import { endOfDay, parseDateInput, startOfDay } from '../lib/date-utils.js';
|
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* @typedef {Object} DateValidationSettings
|
|
15
|
-
* @property {Boolean} ensureFuture
|
|
16
|
-
* @property {Boolean} ensurePast
|
|
14
|
+
* @property {Boolean} [ensureFuture]
|
|
15
|
+
* @property {Boolean} [ensurePast]
|
|
16
|
+
* @property {Boolean} [optional]
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -34,7 +34,8 @@ export class DateValidator extends BaseValidator {
|
|
|
34
34
|
inputLabel,
|
|
35
35
|
dateValidationSettings = {
|
|
36
36
|
ensureFuture: false,
|
|
37
|
-
ensurePast: false
|
|
37
|
+
ensurePast: false,
|
|
38
|
+
optional: false
|
|
38
39
|
},
|
|
39
40
|
errorMessages
|
|
40
41
|
) {
|
|
@@ -62,6 +63,10 @@ export class DateValidator extends BaseValidator {
|
|
|
62
63
|
this.dateValidationSettings = dateValidationSettings;
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
isRequired() {
|
|
67
|
+
return !this.dateValidationSettings.optional;
|
|
68
|
+
}
|
|
69
|
+
|
|
65
70
|
/**
|
|
66
71
|
* validates the response body, checking the values sent for the date are valid
|
|
67
72
|
* @param {DateQuestion} questionObj
|
|
@@ -72,9 +77,21 @@ export class DateValidator extends BaseValidator {
|
|
|
72
77
|
const monthInput = `${fieldName}_month`;
|
|
73
78
|
const yearInput = `${fieldName}_year`;
|
|
74
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Run before every check, if the correct param set then skip the validation
|
|
82
|
+
* when there is no data entered.
|
|
83
|
+
*/
|
|
84
|
+
const shouldValidate = (value, { req }) => {
|
|
85
|
+
if (this.dateValidationSettings.optional === true) {
|
|
86
|
+
return !!(req.body[dayInput] || req.body[monthInput] || req.body[yearInput]);
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
};
|
|
90
|
+
|
|
75
91
|
const rules = [
|
|
76
92
|
// check all or some date inputs are not empty
|
|
77
93
|
body(dayInput)
|
|
94
|
+
.if(shouldValidate)
|
|
78
95
|
.notEmpty()
|
|
79
96
|
.withMessage((_, { req }) => {
|
|
80
97
|
if (!req.body[monthInput] && !req.body[yearInput]) {
|
|
@@ -92,6 +109,7 @@ export class DateValidator extends BaseValidator {
|
|
|
92
109
|
return this.noDayErrorMessage;
|
|
93
110
|
}),
|
|
94
111
|
body(monthInput)
|
|
112
|
+
.if(shouldValidate)
|
|
95
113
|
.notEmpty()
|
|
96
114
|
.withMessage((_, { req }) => {
|
|
97
115
|
if (req.body[dayInput] && !req.body[yearInput]) {
|
|
@@ -104,6 +122,7 @@ export class DateValidator extends BaseValidator {
|
|
|
104
122
|
// empty error message returned
|
|
105
123
|
}),
|
|
106
124
|
body(yearInput)
|
|
125
|
+
.if(shouldValidate)
|
|
107
126
|
.notEmpty()
|
|
108
127
|
.withMessage((_, { req }) => {
|
|
109
128
|
if (req.body[dayInput] && req.body[monthInput]) return this.noYearErrorMessage;
|
|
@@ -113,6 +132,7 @@ export class DateValidator extends BaseValidator {
|
|
|
113
132
|
|
|
114
133
|
// check date values entered are within valid ranges
|
|
115
134
|
body(dayInput)
|
|
135
|
+
.if(shouldValidate)
|
|
116
136
|
.isInt({ min: 1, max: 31 })
|
|
117
137
|
.withMessage(this.invalidDateErrorMessage)
|
|
118
138
|
.bail()
|
|
@@ -131,38 +151,42 @@ export class DateValidator extends BaseValidator {
|
|
|
131
151
|
|
|
132
152
|
return true;
|
|
133
153
|
}),
|
|
134
|
-
body(monthInput).isInt({ min: 1, max: 12 }).withMessage(this.invalidMonthErrorMessage),
|
|
135
|
-
body(yearInput).isInt({ min: 1000, max: 9999 }).withMessage(this.invalidYearErrorMessage)
|
|
154
|
+
body(monthInput).if(shouldValidate).isInt({ min: 1, max: 12 }).withMessage(this.invalidMonthErrorMessage),
|
|
155
|
+
body(yearInput).if(shouldValidate).isInt({ min: 1000, max: 9999 }).withMessage(this.invalidYearErrorMessage)
|
|
136
156
|
];
|
|
137
157
|
|
|
138
158
|
if (this.dateValidationSettings.ensurePast === true) {
|
|
139
159
|
rules.push(
|
|
140
|
-
body(dayInput)
|
|
141
|
-
|
|
160
|
+
body(dayInput)
|
|
161
|
+
.if(shouldValidate)
|
|
162
|
+
.custom((value, { req }) => {
|
|
163
|
+
const inputDate = parseDateInput({ day: value, month: req.body[monthInput], year: req.body[yearInput] });
|
|
142
164
|
|
|
143
|
-
|
|
165
|
+
const today = endOfDay();
|
|
144
166
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
167
|
+
if (isAfter(inputDate, today)) {
|
|
168
|
+
throw new Error(this.futureDateErrorMessage);
|
|
169
|
+
}
|
|
148
170
|
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
return true;
|
|
172
|
+
})
|
|
151
173
|
);
|
|
152
174
|
}
|
|
153
175
|
|
|
154
176
|
if (this.dateValidationSettings.ensureFuture === true) {
|
|
155
177
|
rules.push(
|
|
156
|
-
body(dayInput)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
body(dayInput)
|
|
179
|
+
.if(shouldValidate)
|
|
180
|
+
.custom((value, { req }) => {
|
|
181
|
+
const inputDate = parseDateInput({ day: value, month: req.body[monthInput], year: req.body[yearInput] });
|
|
182
|
+
const today = startOfDay();
|
|
183
|
+
|
|
184
|
+
if (isBefore(inputDate, today)) {
|
|
185
|
+
throw new Error(this.pastDateErrorMessage);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return true;
|
|
189
|
+
})
|
|
166
190
|
);
|
|
167
191
|
}
|
|
168
192
|
|
|
@@ -389,6 +389,109 @@ describe('./src/dynamic-forms/validator/date-validator.js', () => {
|
|
|
389
389
|
assert.strictEqual(errors[`${question.fieldName}_month`].msg, errorMessages.invalidMonthErrorMessage);
|
|
390
390
|
assert.strictEqual(errors[`${question.fieldName}_year`].msg, errorMessages.invalidYearErrorMessage);
|
|
391
391
|
});
|
|
392
|
+
|
|
393
|
+
it('passes validation if optional is true and no fields are provided (undefined)', async () => {
|
|
394
|
+
const req = {
|
|
395
|
+
body: {
|
|
396
|
+
['date-question_day']: undefined,
|
|
397
|
+
['date-question_month']: undefined,
|
|
398
|
+
['date-question_year']: undefined
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const question = {
|
|
403
|
+
fieldName: 'date-question'
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const errors = await _validationMappedErrors(req, question, 'the required date', undefined, {
|
|
407
|
+
optional: true
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
assert.strictEqual(Object.keys(errors).length, 0);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('passes validation if optional is true and fields are empty strings', async () => {
|
|
414
|
+
const req = {
|
|
415
|
+
body: {
|
|
416
|
+
['date-question_day']: '',
|
|
417
|
+
['date-question_month']: '',
|
|
418
|
+
['date-question_year']: ''
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const question = {
|
|
423
|
+
fieldName: 'date-question'
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const errors = await _validationMappedErrors(req, question, 'the required date', undefined, {
|
|
427
|
+
optional: true
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
assert.strictEqual(Object.keys(errors).length, 0);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('throws error if optional is true but date is partially filled (missing day)', async () => {
|
|
434
|
+
const req = {
|
|
435
|
+
body: {
|
|
436
|
+
['date-question_day']: '',
|
|
437
|
+
['date-question_month']: '10',
|
|
438
|
+
['date-question_year']: '2023'
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const question = {
|
|
443
|
+
fieldName: 'date-question'
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const errors = await _validationMappedErrors(req, question, 'the required date', undefined, {
|
|
447
|
+
optional: true
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
assert.strictEqual(Object.keys(errors).length, 1);
|
|
451
|
+
assert.strictEqual(errors[`${question.fieldName}_day`].msg, 'The required date must include a day');
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it('throws error if optional is true but invalid values are provided', async () => {
|
|
455
|
+
const req = {
|
|
456
|
+
body: {
|
|
457
|
+
['date-question_day']: '35',
|
|
458
|
+
['date-question_month']: '10',
|
|
459
|
+
['date-question_year']: '2023'
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const question = {
|
|
464
|
+
fieldName: 'date-question'
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const errors = await _validationMappedErrors(req, question, 'the required date', undefined, {
|
|
468
|
+
optional: true
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
assert.strictEqual(Object.keys(errors).length, 1);
|
|
472
|
+
assert.strictEqual(errors[`${question.fieldName}_day`].msg, 'The required date day must be a real day');
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
it('throws error if an object is passed without the optional key (undefined) and nothing is entered', async () => {
|
|
476
|
+
const req = {
|
|
477
|
+
body: {
|
|
478
|
+
['date-question_day']: undefined,
|
|
479
|
+
['date-question_month']: undefined,
|
|
480
|
+
['date-question_year']: undefined
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const question = {
|
|
485
|
+
fieldName: 'date-question'
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
const errors = await _validationMappedErrors(req, question, 'the required date', undefined, {
|
|
489
|
+
randomKey: true
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
assert.strictEqual(Object.keys(errors).length, 3);
|
|
493
|
+
assert.strictEqual(errors[`${question.fieldName}_day`].msg, 'Enter the required date');
|
|
494
|
+
});
|
|
392
495
|
});
|
|
393
496
|
});
|
|
394
497
|
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import { COMPONENT_TYPES } from '#src/components/utils/component-types.js';
|
|
3
|
+
import { createQuestions } from '#src/questions/create-questions.js';
|
|
4
|
+
import { questionClasses } from '#src/questions/questions.js';
|
|
5
|
+
import { Section, SECTION_STATUS } from '#section';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
|
+
import { JourneyResponse } from '#journey-response';
|
|
8
|
+
import RequiredValidator from '#src/validator/required-validator.js';
|
|
9
|
+
import DateValidator from '#src/validator/date-validator.js';
|
|
10
|
+
import AddressValidator from '#src/validator/address-validator.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {import('../src/questions/question-props.js').QuestionProps} Props
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Check logic related to the question.isRequired method, which in turn drives the section status logic
|
|
18
|
+
*/
|
|
19
|
+
describe('is-required', () => {
|
|
20
|
+
/** @type {() => Record<string, Props>} */
|
|
21
|
+
const getQuestionProps = () => ({
|
|
22
|
+
holidayActivities: {
|
|
23
|
+
type: COMPONENT_TYPES.CHECKBOX,
|
|
24
|
+
title: 'Holiday Activities',
|
|
25
|
+
question: 'Which activities do you want to do on holiday?',
|
|
26
|
+
fieldName: 'holidayActivities',
|
|
27
|
+
url: 'holiday-activities',
|
|
28
|
+
label: 'Select all that apply',
|
|
29
|
+
options: [
|
|
30
|
+
{ value: 'swimming', text: 'Swimming' },
|
|
31
|
+
{ value: 'hiking', text: 'Hiking' },
|
|
32
|
+
{ value: 'sightseeing', text: 'Sightseeing' }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
addInsurance: {
|
|
36
|
+
type: COMPONENT_TYPES.BOOLEAN,
|
|
37
|
+
title: 'Travel Insurance',
|
|
38
|
+
question: 'Do you want to add travel insurance to your holiday?',
|
|
39
|
+
fieldName: 'addInsurance',
|
|
40
|
+
url: 'add-insurance',
|
|
41
|
+
label: 'Add insurance?'
|
|
42
|
+
},
|
|
43
|
+
travelInsuranceType: {
|
|
44
|
+
type: COMPONENT_TYPES.RADIO,
|
|
45
|
+
title: 'Travel Insurance Type',
|
|
46
|
+
question: 'Which type of travel insurance would you like?',
|
|
47
|
+
fieldName: 'travelInsuranceType',
|
|
48
|
+
url: 'travel-insurance-type',
|
|
49
|
+
label: 'Select an insurance type',
|
|
50
|
+
options: [
|
|
51
|
+
{ value: 'basic', text: 'Basic' },
|
|
52
|
+
{ value: 'comprehensive', text: 'Comprehensive' },
|
|
53
|
+
{ value: 'premium', text: 'Premium' }
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
holidayArrival: {
|
|
57
|
+
type: COMPONENT_TYPES.DATE_TIME,
|
|
58
|
+
title: 'Holiday Arrival',
|
|
59
|
+
question: 'When would you like to arrive at your destination?',
|
|
60
|
+
fieldName: 'holidayArrival',
|
|
61
|
+
url: 'holiday-arrival',
|
|
62
|
+
label: 'Enter your arrival time'
|
|
63
|
+
},
|
|
64
|
+
hotelAddress: {
|
|
65
|
+
type: COMPONENT_TYPES.ADDRESS,
|
|
66
|
+
title: 'Hotel Address',
|
|
67
|
+
question: 'What is the address of your hotel?',
|
|
68
|
+
fieldName: 'hotelAddress',
|
|
69
|
+
url: 'hotel-address',
|
|
70
|
+
label: 'Hotel address'
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const newSection = (questionProps) => {
|
|
75
|
+
const questions = createQuestions(questionProps, questionClasses, {});
|
|
76
|
+
|
|
77
|
+
return new Section('test', 'test')
|
|
78
|
+
.addQuestion(questions.holidayActivities)
|
|
79
|
+
.addQuestion(questions.addInsurance)
|
|
80
|
+
.addQuestion(questions.travelInsuranceType)
|
|
81
|
+
.addQuestion(questions.holidayArrival)
|
|
82
|
+
.addQuestion(questions.hotelAddress);
|
|
83
|
+
};
|
|
84
|
+
const sectionStatus = (questionProps, answers = {}) => {
|
|
85
|
+
const section = newSection(questionProps);
|
|
86
|
+
|
|
87
|
+
const jr = new JourneyResponse('id-1', '', answers);
|
|
88
|
+
return section.getStatus(jr);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
it('should be section=complete if no questions are required', () => {
|
|
92
|
+
const props = getQuestionProps();
|
|
93
|
+
assert.strictEqual(sectionStatus(props), SECTION_STATUS.COMPLETE);
|
|
94
|
+
});
|
|
95
|
+
it('should be section=not started if any question is required', () => {
|
|
96
|
+
const props = getQuestionProps();
|
|
97
|
+
|
|
98
|
+
// for each question, mark each one required one at a time
|
|
99
|
+
for (const key of Object.keys(props)) {
|
|
100
|
+
const copy = getQuestionProps();
|
|
101
|
+
copy[key].validators = [new RequiredValidator()];
|
|
102
|
+
assert.strictEqual(sectionStatus(copy), SECTION_STATUS.NOT_STARTED);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
it('should treat date validator as required', () => {
|
|
106
|
+
const props = getQuestionProps();
|
|
107
|
+
props.holidayArrival.validators = [new DateValidator('My Date')];
|
|
108
|
+
assert.strictEqual(sectionStatus(props, {}), SECTION_STATUS.NOT_STARTED);
|
|
109
|
+
});
|
|
110
|
+
it('should treat address validator as required if there are required fields', () => {
|
|
111
|
+
const props = getQuestionProps();
|
|
112
|
+
props.hotelAddress.validators = [
|
|
113
|
+
new AddressValidator({
|
|
114
|
+
requiredFields: {
|
|
115
|
+
addressLine1: true,
|
|
116
|
+
addressLine2: false,
|
|
117
|
+
county: false,
|
|
118
|
+
townCity: false,
|
|
119
|
+
postcode: true
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
];
|
|
123
|
+
assert.strictEqual(sectionStatus(props, {}), SECTION_STATUS.NOT_STARTED);
|
|
124
|
+
});
|
|
125
|
+
it('should not treat address validator as required if there are no required fields', () => {
|
|
126
|
+
const props = getQuestionProps();
|
|
127
|
+
props.hotelAddress.validators = [new AddressValidator()];
|
|
128
|
+
assert.strictEqual(sectionStatus(props, {}), SECTION_STATUS.COMPLETE);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../../src/questions/question.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../../src/questions/question.js"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"address-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/address-validator.js"],"names":[],"mappings":"AAIO,4EAQN;AAGD,oCAAqC,GAAG,CAAC;AACzC,oCAAqC,CAAC,CAAC;AACvC,oCAAqC,GAAG,CAAC;AACzC,oCAAqC,CAAC,CAAC;AACvC,gCAAiC,GAAG,CAAC;AACrC,gCAAiC,CAAC,CAAC;AACnC,8BAA+B,GAAG,CAAC;AACnC,8BAA+B,CAAC,CAAC;AACjC,gCAAiC,CAAC,CAAC;AACnC,gCAAiC,CAAC,CAAC;AAEnC;;;GAGG;AACH;IACC;;;;OAIG;IACH,mBAFG;QAAqH,cAAc;0BAA5G,OAAO;0BAAgB,OAAO;sBAAY,OAAO;oBAAU,OAAO;sBAAY,OAAO;;KAAwB,EAKtI;IADA;sBAJyB,OAAO;sBAAgB,OAAO;kBAAY,OAAO;gBAAU,OAAO;kBAAY,OAAO;kBAIpE;IAG3C;;;OAGG;IACH,sBAFW,QAAQ,iDAYlB
|
|
1
|
+
{"version":3,"file":"address-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/address-validator.js"],"names":[],"mappings":"AAIO,4EAQN;AAGD,oCAAqC,GAAG,CAAC;AACzC,oCAAqC,CAAC,CAAC;AACvC,oCAAqC,GAAG,CAAC;AACzC,oCAAqC,CAAC,CAAC;AACvC,gCAAiC,GAAG,CAAC;AACrC,gCAAiC,CAAC,CAAC;AACnC,8BAA+B,GAAG,CAAC;AACnC,8BAA+B,CAAC,CAAC;AACjC,gCAAiC,CAAC,CAAC;AACnC,gCAAiC,CAAC,CAAC;AAEnC;;;GAGG;AACH;IACC;;;;OAIG;IACH,mBAFG;QAAqH,cAAc;0BAA5G,OAAO;0BAAgB,OAAO;sBAAY,OAAO;oBAAU,OAAO;sBAAY,OAAO;;KAAwB,EAKtI;IADA;sBAJyB,OAAO;sBAAgB,OAAO;kBAAY,OAAO;gBAAU,OAAO;kBAAY,OAAO;kBAIpE;IAG3C;;;OAGG;IACH,sBAFW,QAAQ,iDAYlB;;CAqGD;;0BA1JyB,qBAAqB"}
|
|
@@ -16,6 +16,13 @@ export class BaseValidator {
|
|
|
16
16
|
* @returns {import('express-validator').ValidationChain | import('express-validator').ValidationChain[]}
|
|
17
17
|
*/
|
|
18
18
|
validate(questionObj: import("../questions/question-props.js").QuestionProps, journeyResponse?: import("../journey/journey-response.js").JourneyResponse): import("express-validator").ValidationChain | import("express-validator").ValidationChain[];
|
|
19
|
+
/**
|
|
20
|
+
* Should the question that this validator is configured with be treated as a required question?
|
|
21
|
+
*
|
|
22
|
+
* Validators should override this method as appropriate, implementing any custom required logic.
|
|
23
|
+
* For example, the AddressValidator is configurable and is required if any one field is required.
|
|
24
|
+
*/
|
|
25
|
+
isRequired(): boolean;
|
|
19
26
|
}
|
|
20
27
|
export default BaseValidator;
|
|
21
28
|
//# sourceMappingURL=base-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/base-validator.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH;IACC;;OAEG;IACH,cAFU,MAAM,CAEH;IAQb;;;;;;;OAOG;IAEH,sBALW,OAAO,gCAAgC,EAAE,aAAa,oBACtD,OAAO,gCAAgC,EAAE,eAAe,GACtD,OAAO,mBAAmB,EAAE,eAAe,GAAG,OAAO,mBAAmB,EAAE,eAAe,EAAE,CAKvG;CACD"}
|
|
1
|
+
{"version":3,"file":"base-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/base-validator.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH;IACC;;OAEG;IACH,cAFU,MAAM,CAEH;IAQb;;;;;;;OAOG;IAEH,sBALW,OAAO,gCAAgC,EAAE,aAAa,oBACtD,OAAO,gCAAgC,EAAE,eAAe,GACtD,OAAO,mBAAmB,EAAE,eAAe,GAAG,OAAO,mBAAmB,EAAE,eAAe,EAAE,CAKvG;IAED;;;;;OAKG;IACH,sBAEC;CACD"}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {Object} DateValidationSettings
|
|
6
|
-
* @property {Boolean} ensureFuture
|
|
7
|
-
* @property {Boolean} ensurePast
|
|
6
|
+
* @property {Boolean} [ensureFuture]
|
|
7
|
+
* @property {Boolean} [ensurePast]
|
|
8
|
+
* @property {Boolean} [optional]
|
|
8
9
|
*/
|
|
9
10
|
/**
|
|
10
11
|
* enforces a user has entered a valid date
|
|
@@ -42,8 +43,9 @@ export class DateValidator extends BaseValidator {
|
|
|
42
43
|
export default DateValidator;
|
|
43
44
|
export type DateQuestion = typeof import("../components/date/question.js");
|
|
44
45
|
export type DateValidationSettings = {
|
|
45
|
-
ensureFuture
|
|
46
|
-
ensurePast
|
|
46
|
+
ensureFuture?: boolean | undefined;
|
|
47
|
+
ensurePast?: boolean | undefined;
|
|
48
|
+
optional?: boolean | undefined;
|
|
47
49
|
};
|
|
48
50
|
import BaseValidator from './base-validator.js';
|
|
49
51
|
//# sourceMappingURL=date-validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/date-validator.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"date-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/date-validator.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH;;;;;GAKG;AAEH;;;GAGG;AACH;IAIC;;;;;OAKG;IACH,wBAJW,MAAM,2BACN,sBAAsB,kBACtB,MAAM,EAiChB;IAxCD,qCAAqC;IACrC,wBADW,sBAAsB,CACV;IAqBtB,uBAAmG;IACnG,uBAAmG;IACnG,yBAAyG;IACzG,wBAAsG;IACtG,4BAAkH;IAClH,2BAA+G;IAC/G,6BACuF;IACvF,6BACuF;IACvF,8BACyF;IACzF,6BACuF;IACvF,4BAAkH;IAClH,0BAA4G;IAS7G;;;OAGG;IACH,sBAFW,YAAY,iDA0HtB;;CA6BD;;;;;;;;0BA1NyB,qBAAqB"}
|
|
@@ -51,7 +51,6 @@ export class MultiFieldInputValidator extends BaseValidator {
|
|
|
51
51
|
* validates response body against question's required fields
|
|
52
52
|
*/
|
|
53
53
|
validate(): import("express-validator").ValidationChain[];
|
|
54
|
-
isRequired(): boolean;
|
|
55
54
|
/**
|
|
56
55
|
* checks if a field is required
|
|
57
56
|
* @param {string} fieldName
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-field-input-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/multi-field-input-validator.js"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;GAEG;AAEH;IACC;;;;OAIG;IACH,0CAHG;QAAyB,MAAM;QACP,eAAe;KAAC,EAQ1C;IAFA,gBAAoB;IACpB,wBAAwE;IAGzE;;OAEG;IAEH,0DA8BC;
|
|
1
|
+
{"version":3,"file":"multi-field-input-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/multi-field-input-validator.js"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;;;GAMG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;GAEG;AAEH;IACC;;;;OAIG;IACH,0CAHG;QAAyB,MAAM;QACP,eAAe;KAAC,EAQ1C;IAFA,gBAAoB;IACpB,wBAAwE;IAGzE;;OAEG;IAEH,0DA8BC;IAKD;;;;OAIG;IACH,gCAHW,MAAM,GACJ,OAAO,CAQnB;CACD;;;WA3Ga,SAAS,MAAM;;;;;;;;;;;;eAkBf,MAAM;;;;;4BAOP,SAAS,GAAG;IACpB,QAAQ,EAAE,IAAI,CAAC;IACf,YAAY,EAAE,MAAM,CAAA;CACrB;4BAIS,SAAS,GAAG;IACpB,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;oBAIS,aAAa,GAAG,aAAa;0BA1ChB,qBAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"required-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/required-validator.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;GAGG;AACH;IAMC;;;OAGG;IACH,2BAFW,MAAM,EAQhB;IAED;;;OAGG;IACH,sBAFW,QAAQ,+CAIlB;
|
|
1
|
+
{"version":3,"file":"required-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/required-validator.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;GAGG;AACH;IAMC;;;OAGG;IACH,2BAFW,MAAM,EAQhB;IAED;;;OAGG;IACH,sBAFW,QAAQ,+CAIlB;CAKD;;;0BAvCyB,qBAAqB"}
|