Skip to content

Commit

Permalink
Merge pull request #3316 from NCI-Agency/fix-report-number-fields
Browse files Browse the repository at this point in the history
Fix report number fields' errors
  • Loading branch information
VassilIordanov committed Nov 26, 2020
2 parents cab4d29 + f0763a8 commit 964c942
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 14 deletions.
34 changes: 23 additions & 11 deletions client/src/components/CustomFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const SPECIAL_WIDGET_COMPONENTS = {
[SPECIAL_WIDGET_TYPES.LIKERT_SCALE]: LikertScale,
[SPECIAL_WIDGET_TYPES.RICH_TEXT_EDITOR]: RichTextEditor
}
const RENDERERS = {}

const SpecialField = ({ name, widget, formikProps, ...otherFieldProps }) => {
const WidgetComponent = SPECIAL_WIDGET_COMPONENTS[widget]
Expand Down Expand Up @@ -114,6 +113,19 @@ const TextField = fieldProps => {
)
}

const NumberField = fieldProps => {
const { onChange, onBlur, ...otherFieldProps } = fieldProps
return (
<FastField
onChange={value => onChange(value, false)} // do debounced validation
onWheelCapture={event => event.currentTarget.blur()} // Prevent scroll action on number input
component={FieldHelper.InputField}
inputType="number"
{...otherFieldProps}
/>
)
}

const ReadonlyTextField = fieldProps => {
const { name, label, vertical } = fieldProps
return (
Expand Down Expand Up @@ -210,11 +222,11 @@ ReadonlyJsonField.propTypes = {
}

const EnumField = fieldProps => {
const { choices, renderer, ...otherFieldProps } = fieldProps
const { choices, ...otherFieldProps } = fieldProps
return (
<FastField
buttons={FieldHelper.customEnumButtons(choices)}
component={RENDERERS[renderer] || FieldHelper.RadioButtonToggleGroupField}
component={FieldHelper.RadioButtonToggleGroupField}
{...otherFieldProps}
/>
)
Expand Down Expand Up @@ -243,13 +255,11 @@ const ReadonlyEnumField = fieldProps => {
}

const EnumSetField = fieldProps => {
const { choices, renderer, ...otherFieldProps } = fieldProps
const { choices, ...otherFieldProps } = fieldProps
return (
<FastField
buttons={FieldHelper.customEnumButtons(choices)}
component={
RENDERERS[renderer] || FieldHelper.CheckboxButtonToggleGroupField
}
component={FieldHelper.CheckboxButtonToggleGroupField}
{...otherFieldProps}
/>
)
Expand Down Expand Up @@ -611,7 +621,7 @@ ReadonlyArrayOfAnetObjectsField.propTypes = {

const FIELD_COMPONENTS = {
[CUSTOM_FIELD_TYPE.TEXT]: TextField,
[CUSTOM_FIELD_TYPE.NUMBER]: TextField,
[CUSTOM_FIELD_TYPE.NUMBER]: NumberField,
[CUSTOM_FIELD_TYPE.DATE]: DateField,
[CUSTOM_FIELD_TYPE.DATETIME]: DateTimeField,
[CUSTOM_FIELD_TYPE.JSON]: JsonField,
Expand Down Expand Up @@ -729,8 +739,10 @@ const CustomField = ({
) // with validateField it somehow doesn't work
const handleChange = useMemo(
() => (value, shouldValidate = true) => {
const val =
value?.target?.value !== undefined ? value.target.value : value
let val = value?.target?.value !== undefined ? value.target.value : value
if (type === "number" && val === "") {
val = null
}
const sv = shouldValidate === undefined ? true : shouldValidate
setFieldTouched(fieldName, true, false)
if (!_isEqual(val, prevVal.current)) {
Expand All @@ -741,7 +753,7 @@ const CustomField = ({
validateFormDebounced()
}
},
[fieldName, setFieldTouched, setFieldValue, validateFormDebounced]
[fieldName, setFieldTouched, setFieldValue, validateFormDebounced, type]
)
const FieldComponent = FIELD_COMPONENTS[type]
const extraProps = useMemo(() => {
Expand Down
5 changes: 4 additions & 1 deletion client/src/components/FieldHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export const InputField = ({
field, // { name, value, onChange, onBlur }
form, // contains, touched, errors, values, setXXXX, handleXXXX, dirty, isValid, status, etc.
label,
inputType,
children,
extraColElem,
addon,
Expand All @@ -152,12 +153,13 @@ export const InputField = ({
const widgetElem = useMemo(
() => (
<FormControl
type={inputType}
{...Object.without(field, "value")}
value={utils.isNullOrUndefined(field.value) ? "" : field.value}
{...otherProps}
/>
),
[field, otherProps]
[field, otherProps, inputType]
)
return (
<Field
Expand All @@ -177,6 +179,7 @@ InputField.propTypes = {
field: PropTypes.object,
form: PropTypes.object,
label: PropTypes.string,
inputType: PropTypes.string,
children: PropTypes.any,
extraColElem: PropTypes.object,
addon: PropTypes.object,
Expand Down
8 changes: 6 additions & 2 deletions client/src/pages/reports/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,10 +528,14 @@ const ReportForm = ({
name="duration"
label="Duration (minutes)"
component={FieldHelper.InputField}
inputType="number"
onWheelCapture={event => event.currentTarget.blur()} // Prevent scroll action on number input
onChange={event => {
const safeVal =
(event.target.value || "").replace(/[^0-9]+/g, "") ||
null
utils.preventNegativeAndLongDigits(
event.target.value,
4
) || null
setFieldTouched("duration", true, false)
setFieldValue("duration", safeVal, false)
validateFieldDebounced("duration")
Expand Down
13 changes: 13 additions & 0 deletions client/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,19 @@ export default {
arr &&
arr.filter(n => !isNaN(parseFloat(n)) && isFinite(n)).map(n => Number(n))
)
},

preventNegativeAndLongDigits: function(valueStr, maxLen) {
let safeVal
const dangerVal = Number(valueStr)
if (!isNaN(dangerVal) && dangerVal < 0) {
safeVal = "0"
} else {
const nonDigitsRemoved = valueStr.replace(/\D/g, "")
safeVal =
maxLen <= 0 ? nonDigitsRemoved : nonDigitsRemoved.slice(0, maxLen)
}
return safeVal
}
}

Expand Down
4 changes: 4 additions & 0 deletions client/tests/webdriver/pages/createReport.page.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export class CreateReport extends Page {
return browser.$(".alert")
}

get duration() {
return browser.$("#duration")
}

get engagementInformationTitle() {
return browser.$('//span[text()="Engagement information"]')
}
Expand Down
33 changes: 33 additions & 0 deletions client/tests/webdriver/specs/createReport.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ const REPORT = "Interior"
const REPORT_VALUE = "Talk to the Interior about things"
const REPORT_COMPLETE = `${REPORT_VALUE}`

const INVALID_ENGAGEMENT_DURATION_1 = "123456"
const INVALID_ENGAGEMENT_DURATION_2 = "-1"
// positive sliced at 4th digit, negative should turn into 0
const VALID_ENGAGEMENT_DURATION_1 = "1234"
const VALID_ENGAGEMENT_DURATION_2 = "0"

const PERSON = "EF 2.1"
const PERSON_VALUE_1 = "HENDERSON, Henry"
const PERSON_VALUE_2 = "JACKSON, Jack"
Expand All @@ -29,6 +35,33 @@ describe("Create report form page", () => {
CreateReport.form.waitForDisplayed()
})

it("Should be able to prevent invalid duration values", () => {
CreateReport.duration.setValue(INVALID_ENGAGEMENT_DURATION_1)
browser.waitUntil(
() => {
return (
CreateReport.duration.getValue() === VALID_ENGAGEMENT_DURATION_1
)
},
{
timeout: 3000,
timeoutMsg: "Large positive duration value was not sliced "
}
)
CreateReport.duration.setValue(INVALID_ENGAGEMENT_DURATION_2)
browser.waitUntil(
() => {
return (
CreateReport.duration.getValue() === VALID_ENGAGEMENT_DURATION_2
)
},
{
timeout: 3000,
timeoutMsg: "Negative duration value did not change to zero"
}
)
})

it("Should be able to select an ANET object reference", () => {
CreateReport.testReferenceFieldLabel.waitForExist()
CreateReport.testReferenceFieldLabel.waitForDisplayed()
Expand Down

0 comments on commit 964c942

Please sign in to comment.