• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 1350829378

27 Jun 2024 01:46PM UTC coverage: 83.494% (-16.5%) from 99.965%
1350829378

Pull #4465

gitlab-ci

mzedel
chore: test fixes

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #4465: MEN-7169 - feat: added multi sorting capabilities to devices view

4506 of 6430 branches covered (70.08%)

81 of 100 new or added lines in 14 files covered. (81.0%)

1661 existing lines in 163 files now uncovered.

8574 of 10269 relevant lines covered (83.49%)

160.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.21
/src/js/components/common/forms/form.js
1
// Copyright 2016 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import React, { useEffect } from 'react';
15
import { FormProvider, useForm } from 'react-hook-form';
16

17
import { Button } from '@mui/material';
18

19
import validator from 'validator';
20

21
const getErrorMsg = (validateMethod, args) => {
17✔
22
  switch (validateMethod) {
197!
23
    case 'isLength':
24
      if (args[0] === 1) {
47!
UNCOV
25
        return 'This field is required';
×
26
      } else if (args[0] > 1) {
47!
27
        return `Must be at least ${args[0]} characters long`;
47✔
28
      }
UNCOV
29
      break;
×
30
    case 'isAlpha':
UNCOV
31
      return 'This field must contain only letters';
×
32
    case 'isAlphanumeric':
UNCOV
33
      return 'This field must contain only letters or numbers';
×
34
    case 'isNumeric':
UNCOV
35
      return 'Please enter a valid code';
×
36
    case 'isEmail':
37
      return 'Please enter a valid email address';
97✔
38
    case 'isUUID':
39
      return 'Please enter a valid ID';
21✔
40
    case 'isNot':
41
      if (args[0] === args[1]) {
32!
UNCOV
42
        return `This field should have a value other than ${args[0]}`;
×
43
      }
44
      break;
32✔
45
    default:
UNCOV
46
      return 'There is an error with this field';
×
47
  }
48
};
49

50
const tryApplyValidationEntry = (value, validations = [], validationResults = []) => {
17!
51
  const validation = validations.shift();
847✔
52
  if (!validation) {
847✔
53
    return validationResults.pop();
176✔
54
  }
55
  let args = validation.split(':');
671✔
56
  const validateMethod = args.shift();
671✔
57
  // We use JSON.parse to convert the string values passed to the
58
  // correct type. Ex. 'isLength:1' will make '1' actually a number
59
  args = args.map(arg => JSON.parse(JSON.stringify(arg)));
671✔
60

61
  const tmpArgs = args;
671✔
62
  // We then merge two arrays, ending up with the value
63
  // to pass first, then options, if any. ['valueFromInput', 5]
64
  args = [value].concat(args);
671✔
65
  try {
671✔
66
    // So the next line of code is actually:
67
    // validator.isLength('valueFromInput', 5)
68
    if (!validator[validateMethod].apply(validator, args)) {
671✔
69
      return tryApplyValidationEntry(value, validations, [...validationResults, { errortext: getErrorMsg(validateMethod, tmpArgs), isValid: false }]);
165✔
70
    }
71
  } catch {
72
    const errortext = getErrorMsg(validateMethod, args) || '';
32✔
73
    return tryApplyValidationEntry(value, validations, [...validationResults, { errortext, isValid: !errortext }]);
32✔
74
  }
75
  return { errortext: '', isValid: true };
474✔
76
};
77

78
const tryApplyValidations = (value, validations, initialValidationResult) =>
17✔
79
  validations.split(',').reduce((accu, validation) => {
408✔
80
    if (!accu.isValid || !validation) {
824✔
81
      return accu;
174✔
82
    }
83
    const alternatives = validation.split('||');
650✔
84
    return tryApplyValidationEntry(value, alternatives, [accu]);
650✔
85
  }, initialValidationResult);
86

87
const runPasswordValidations = ({ required, value, validations, isValid, errortext }) => {
17✔
88
  if (required && !value) {
223!
UNCOV
89
    return { isValid: false, errortext: 'Password is required' };
×
90
  } else if (required || value) {
223✔
91
    isValid = tryApplyValidations(value, validations, { isValid, errortext }).isValid;
209✔
92
    return { isValid, errortext: !isValid ? 'Password too weak' : errortext };
209✔
93
  }
94
  return { isValid, errortext };
14✔
95
};
96

97
export const runValidations = ({ required, value, id, validations }) => {
17✔
98
  let isValid = true;
454✔
99
  let errortext = '';
454✔
100
  if (id && id.includes('password')) {
454✔
101
    return runPasswordValidations({ required, value, validations, isValid, errortext });
223✔
102
  } else {
103
    if (value || required) {
231✔
104
      return tryApplyValidations(validations.includes('trim') ? value.trim() : value, validations, { isValid, errortext });
199✔
105
    }
106
  }
107
  return { isValid, errortext };
32✔
108
};
109

110
export const Form = ({
17✔
111
  autocomplete,
112
  buttonColor,
113
  children,
114
  className = '',
306✔
115
  defaultValues = {},
328✔
116
  handleCancel,
117
  id,
118
  initialValues = {},
349✔
119
  onSubmit,
120
  showButtons,
121
  submitLabel
122
}) => {
123
  const methods = useForm({ mode: 'onChange', defaultValues });
434✔
124
  const {
125
    handleSubmit,
126
    formState: { isValid },
127
    setValue
128
  } = methods;
434✔
129

130
  useEffect(() => {
434✔
131
    Object.entries(initialValues).map(([key, value]) => setValue(key, value));
25✔
132
    // eslint-disable-next-line react-hooks/exhaustive-deps
133
  }, [JSON.stringify(initialValues), setValue]);
134

135
  return (
434✔
136
    <FormProvider {...methods}>
137
      <form autoComplete={autocomplete} className={className} id={id} noValidate onSubmit={handleSubmit(onSubmit)}>
138
        {children}
139
        {!!showButtons && (
796✔
140
          <div className="flexbox" style={{ justifyContent: 'flex-end', height: 'min-content', marginTop: 32 }}>
141
            {!!handleCancel && (
411✔
142
              <Button key="cancel" onClick={handleCancel} style={{ marginRight: 10, display: 'inline-block' }}>
143
                Cancel
144
              </Button>
145
            )}
146
            <Button variant="contained" type="submit" disabled={!isValid} color={buttonColor}>
147
              {submitLabel}
148
            </Button>
149
          </div>
150
        )}
151
      </form>
152
    </FormProvider>
153
  );
154
};
155

156
export default Form;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc