diff --git a/modules/ui/src/app/mocks/profile.mock.ts b/modules/ui/src/app/mocks/profile.mock.ts
index 596f922f8..6f6a36b0e 100644
--- a/modules/ui/src/app/mocks/profile.mock.ts
+++ b/modules/ui/src/app/mocks/profile.mock.ts
@@ -33,6 +33,7 @@ export const PROFILE_FORM: ProfileFormat[] = [
type: FormControlType.EMAIL_MULTIPLE,
validation: {
required: true,
+ max: '30',
},
},
{
diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.html b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.html
index b57d93f04..2cd54d328 100644
--- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.html
+++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.html
@@ -178,6 +178,13 @@
The field is required
+
+ The field must be a maximum of
+ {{ getControl(formControlName).getError('maxlength').requiredLength }}
+ characters.
+
@@ -190,10 +197,12 @@
floatLabel="always"
class="profile-form-field"
[formGroup]="profileForm">
-
+ [formControlName]="formControlName">
{{ description }}The field is required
+
+ The field must be a maximum of
+ {{ getControl(formControlName).getError('maxlength').requiredLength }}
+ characters.
+
@@ -230,6 +246,13 @@
letters, numbers, @ and . (dot).
+
+ The field must be a maximum of
+ {{ getControl(formControlName).getError('maxlength').requiredLength }}
+ characters.
+
diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts
index 3f3f3e5a3..a1e1b9177 100644
--- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts
+++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.spec.ts
@@ -146,6 +146,9 @@ describe('ProfileFormComponent', () => {
} else if (item.type === FormControlType.SELECT_MULTIPLE) {
const select = fields[uiIndex].querySelector('mat-checkbox');
expect(select).toBeTruthy();
+ } else if (item.type === FormControlType.TEXTAREA) {
+ const input = fields[uiIndex]?.querySelector('textarea');
+ expect(input).toBeTruthy();
} else {
const input = fields[uiIndex]?.querySelector('input');
expect(input).toBeTruthy();
@@ -202,99 +205,87 @@ describe('ProfileFormComponent', () => {
}
if (
- (item.type === FormControlType.TEXT ||
- item.type === FormControlType.TEXTAREA) &&
- item.validation?.required
+ item.type === FormControlType.TEXT ||
+ item.type === FormControlType.TEXTAREA ||
+ item.type === FormControlType.EMAIL_MULTIPLE
) {
- describe('text or text-long', () => {
- it('should have "required" error when field is not filled', () => {
- const fields = compiled.querySelectorAll('.profile-form-field');
- const uiIndex = index + 1; // as Profile name is at 0 position, the json items start from 1 i
- const input: HTMLInputElement = fields[uiIndex].querySelector(
- 'input'
- ) as HTMLInputElement;
- ['', ' '].forEach(value => {
- input.value = value;
- input.dispatchEvent(new Event('input'));
- component.getControl(index).markAsTouched();
- fixture.detectChanges();
-
- const error =
- fields[uiIndex].querySelector('mat-error')?.textContent;
-
- expect(error).toContain('The field is required');
- });
- });
-
- it('should have "invalid_format" error when field does not satisfy validation rules', () => {
- [
- 'very long value very long value very long value very long value very long value very long value very long value very long value very long value very long value',
- 'as\\\\\\\\\\""""""""',
- ].forEach(value => {
+ describe('text or text-long or email-multiple', () => {
+ if (item.validation?.required) {
+ it('should have "required" error when field is not filled', () => {
const fields = compiled.querySelectorAll('.profile-form-field');
const uiIndex = index + 1; // as Profile name is at 0 position, the json items start from 1 i
- const input: HTMLInputElement = fields[uiIndex].querySelector(
- 'input'
+ const input = fields[uiIndex].querySelector(
+ '.mat-mdc-input-element'
) as HTMLInputElement;
- input.value = value;
- input.dispatchEvent(new Event('input'));
- component.getControl(index).markAsTouched();
- fixture.detectChanges();
-
- const error = compiled.querySelector('mat-error')?.textContent;
- expect(error).toContain(
- 'Please, check. “ and \\ are not allowed.'
- );
+ ['', ' '].forEach(value => {
+ input.value = value;
+ input.dispatchEvent(new Event('input'));
+ component.getControl(index).markAsTouched();
+ fixture.detectChanges();
+ const errors = fields[uiIndex].querySelectorAll('mat-error');
+ let hasError = false;
+ errors.forEach(error => {
+ if (error.textContent === 'The field is required') {
+ hasError = true;
+ }
+ });
+
+ expect(hasError).toBeTrue();
+ });
});
- });
- });
- }
+ }
- if (
- item.type === FormControlType.EMAIL_MULTIPLE &&
- item.validation?.required
- ) {
- describe('text or text-long', () => {
- it('should have "required" error when field is not filled', () => {
+ it('should have "invalid_format" error when field does not satisfy validation rules', () => {
const fields = compiled.querySelectorAll('.profile-form-field');
const uiIndex = index + 1; // as Profile name is at 0 position, the json items start from 1 i
const input: HTMLInputElement = fields[uiIndex].querySelector(
- 'input'
+ '.mat-mdc-input-element'
) as HTMLInputElement;
- ['', ' '].forEach(value => {
- input.value = value;
- input.dispatchEvent(new Event('input'));
- component.getControl(index).markAsTouched();
- fixture.detectChanges();
-
- const error =
- fields[uiIndex].querySelector('mat-error')?.textContent;
-
- expect(error).toContain('The field is required');
+ input.value = 'as\\\\\\\\\\""""""""';
+ input.dispatchEvent(new Event('input'));
+ component.getControl(index).markAsTouched();
+ fixture.detectChanges();
+ const result =
+ item.type === FormControlType.EMAIL_MULTIPLE
+ ? 'Please, check the email address. Valid e-mail can contain only latin letters, numbers, @ and . (dot).'
+ : 'Please, check. “ and \\ are not allowed.';
+ const errors = fields[uiIndex].querySelectorAll('mat-error');
+ let hasError = false;
+ errors.forEach(error => {
+ if (error.textContent === result) {
+ hasError = true;
+ }
});
+
+ expect(hasError).toBeTrue();
});
- it('should have "invalid_format" error when field does not satisfy validation rules', () => {
- [
- 'very long value very long value very long value very long value very long value very long value very long value very long value very long value very long value',
- 'as\\\\\\\\\\""""""""',
- ].forEach(value => {
+ if (item.validation?.max) {
+ it('should have "maxlength" error when field is exceeding max length', () => {
const fields = compiled.querySelectorAll('.profile-form-field');
const uiIndex = index + 1; // as Profile name is at 0 position, the json items start from 1 i
const input: HTMLInputElement = fields[uiIndex].querySelector(
- 'input'
+ '.mat-mdc-input-element'
) as HTMLInputElement;
- input.value = value;
+ input.value =
+ 'very long value very long value very long value very long value very long value very long value very long value very long value very long value very long value';
input.dispatchEvent(new Event('input'));
component.getControl(index).markAsTouched();
fixture.detectChanges();
- const error = compiled.querySelector('mat-error')?.textContent;
- expect(error).toContain(
- 'Please, check the email address. Valid e-mail can contain only latin letters, numbers, @ and . (dot).'
- );
+ const errors = fields[uiIndex].querySelectorAll('mat-error');
+ let hasError = false;
+ errors.forEach(error => {
+ if (
+ error.textContent ===
+ `The field must be a maximum of ${item.validation?.max} characters.`
+ ) {
+ hasError = true;
+ }
+ });
+ expect(hasError).toBeTrue();
});
- });
+ }
});
}
});
@@ -318,7 +309,7 @@ describe('ProfileFormComponent', () => {
describe('Save button', () => {
it('should be enabled when required fields are present', () => {
component.nameControl.setValue('test');
- component.getControl('0').setValue('test@test.test');
+ component.getControl('0').setValue('a@test.te;b@test.te, c@test.te');
component.getControl('1').setValue('test');
component.getControl('2').setValue('test');
component.getControl('3').setValue({ 0: true, 1: true, 2: true });
diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts
index 1f0ee7656..9270abc4e 100644
--- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts
+++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import { TextFieldModule } from '@angular/cdk/text-field';
import {
ChangeDetectionStrategy,
Component,
@@ -31,6 +32,7 @@ import {
FormGroup,
ReactiveFormsModule,
ValidatorFn,
+ Validators,
} from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { DeviceValidators } from '../../devices/components/device-form/device.validators';
@@ -54,6 +56,7 @@ import { ProfileValidators } from './profile.validators';
MatFormFieldModule,
MatSelectModule,
MatCheckboxModule,
+ TextFieldModule,
],
templateUrl: './profile-form.component.html',
styleUrl: './profile-form.component.scss',
@@ -109,15 +112,14 @@ export class ProfileFormComponent implements OnInit {
if (validation.required) {
validators.push(this.profileValidators.textRequired());
}
+ if (validation.max) {
+ validators.push(Validators.maxLength(Number(validation.max)));
+ }
if (type === FormControlType.EMAIL_MULTIPLE) {
- validators.push(
- this.profileValidators.emailStringFormat(Number(validation.max))
- );
+ validators.push(this.profileValidators.emailStringFormat());
}
if (type === FormControlType.TEXT || type === FormControlType.TEXTAREA) {
- validators.push(
- this.profileValidators.textFormat(Number(validation.max))
- );
+ validators.push(this.profileValidators.textFormat());
}
}
return validators;
diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile.validators.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile.validators.ts
index fe5f60585..720efae97 100644
--- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile.validators.ts
+++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile.validators.ts
@@ -25,7 +25,7 @@ import { Profile } from '../../../model/profile';
@Injectable({ providedIn: 'root' })
export class ProfileValidators {
readonly MULTIPLE_EMAIL_FORMAT_REGEXP = new RegExp(
- '^(([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)(\\s*;\\s*|\\s*$))*$',
+ '^(([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)(\\s*(;|,)\\s*|\\s*$))*$',
'i'
);
@@ -58,19 +58,18 @@ export class ProfileValidators {
return null;
}
- public emailStringFormat(maxLength: number = 128): ValidatorFn {
- return this.stringFormat(this.MULTIPLE_EMAIL_FORMAT_REGEXP, maxLength);
+ public emailStringFormat(): ValidatorFn {
+ return this.stringFormat(this.MULTIPLE_EMAIL_FORMAT_REGEXP);
}
- public textFormat(maxLength: number = 128): ValidatorFn {
- return this.stringFormat(this.STRING_FORMAT_REGEXP, maxLength);
+ public textFormat(): ValidatorFn {
+ return this.stringFormat(this.STRING_FORMAT_REGEXP);
}
- private stringFormat(regExp: RegExp, maxLength: number = 28): ValidatorFn {
+ private stringFormat(regExp: RegExp): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const value = control.value?.trim();
if (value) {
- if (value.length > maxLength) return { invalid_format: true };
const result = regExp.test(value);
return !result ? { invalid_format: true } : null;
}