diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts index f786c3e04a73e2bc719cacf654aaf0c01d77039d..f3e6c68f3f15f51d766224ea4add00605a4e05be 100644 --- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts +++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts @@ -175,7 +175,7 @@ describe('PostfachFormComponent', () => { function createProblemDetailForAbsenderName(): ProblemDetail { return { ...createProblemDetail(), - 'invalid-params': [{ ...createInvalidParam(), name: 'settingBody.absender.name' }], + invalidParams: [{ ...createInvalidParam(), name: 'settingBody.absender.name' }], }; } diff --git a/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts b/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts index a023a009d1780be33395159d25234da39285f745..cb0f3f5842b32a3ce76321d194097c9a2f64229a 100644 --- a/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts +++ b/alfa-client/libs/design-component/src/lib/form/formcontrol-editor.abstract.component.ts @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Issue } from '@alfa-client/tech-shared'; +import { InvalidParam } from '@alfa-client/tech-shared'; import { Component, OnDestroy, OnInit, Optional, Self } from '@angular/core'; import { ControlValueAccessor, NgControl, UntypedFormControl } from '@angular/forms'; import { isEmpty } from 'lodash-es'; @@ -89,9 +89,11 @@ export abstract class FormControlEditorAbstractComponent } } - get issues(): Issue[] { + get invalidParams(): InvalidParam[] { return this.fieldControl.errors ? - Object.keys(this.fieldControl.errors).map((key) => <Issue>this.fieldControl.errors[key]) + Object.keys(this.fieldControl.errors).map( + (key) => <InvalidParam>this.fieldControl.errors[key], + ) : []; } } diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html index 544b9312b03adba3e0e097e8eba8a20751e5b013..9252326a5bdcc9d9c25ec164981bd0e24915bafa 100644 --- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html +++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.html @@ -10,7 +10,7 @@ > <ods-validation-error error - [issues]="issues" + [invalidParams]="invalidParams" [label]="label" [attr.data-test-id]="(label | convertForDataTest) + '-text-editor-error'" ></ods-validation-error> diff --git a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts index c78a7554800ed6f61eb9d189617811e7f9d0490a..c40849cf31e2279a3727527898213567bab07c4c 100644 --- a/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts +++ b/alfa-client/libs/design-component/src/lib/form/text-editor/text-editor.component.ts @@ -26,6 +26,6 @@ export class TextEditorComponent extends FormControlEditorAbstractComponent { @Input() focus: boolean = false; get variant(): string { - return this.issues.length > 0 ? 'error' : 'default'; + return this.invalidParams.length > 0 ? 'error' : 'default'; } } diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html index 5f3959bd34260ac44c11db6a108f24583986b9b0..c27f425a3f9ca703f85b9961a8c87175a50a0a9f 100644 --- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html +++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.html @@ -10,7 +10,7 @@ > <ods-validation-error error - [issues]="issues" + [invalidParams]="invalidParams" [label]="label" [attr.data-test-id]="(label | convertForDataTest) + '-textarea-editor-error'" ></ods-validation-error> diff --git a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts index f78ee2c938fdb89b91a17060ba862ecadcff04aa..a47b955192b12c4a9ce1379062cd16543e455e2a 100644 --- a/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts +++ b/alfa-client/libs/design-component/src/lib/form/textarea-editor/textarea-editor.component.ts @@ -26,6 +26,6 @@ export class TextareaEditorComponent extends FormControlEditorAbstractComponent @Input() focus: boolean = false; get variant(): string { - return this.issues.length > 0 ? 'error' : 'default'; + return this.invalidParams.length > 0 ? 'error' : 'default'; } } diff --git a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.html b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.html index 703f757c2b17228e8cdfb7d158a7bb7e6a058a93..28ffaaac9b7880787146c5091eceedee3d2a662e 100644 --- a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.html +++ b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.html @@ -1,3 +1,3 @@ -<ng-container *ngFor="let issue of issues" - ><ods-error-message [text]="message(issue)"></ods-error-message +<ng-container *ngFor="let invalidParam of invalidParams" + ><ods-error-message [text]="message(invalidParam)"></ods-error-message ></ng-container> diff --git a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.spec.ts b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.spec.ts index 6abe6133bddfc36ca6ca42e2aa28d049fa96ef4d..9b169d4d08c185e8036dd34f7fe1e56086605fa2 100644 --- a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.spec.ts +++ b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.spec.ts @@ -1,6 +1,7 @@ -import { getMessageForIssue } from '@alfa-client/tech-shared'; +import { getMessageForInvalidParam, InvalidParam } from '@alfa-client/tech-shared'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createIssue } from 'libs/tech-shared/test/error'; +import { ValidationMessageCode } from 'libs/tech-shared/src/lib/validation/tech.validation.messages'; +import { createInvalidParam } from 'libs/tech-shared/test/error'; import { ValidationErrorComponent } from './validation-error.component'; describe('ValidationErrorComponent', () => { @@ -21,32 +22,30 @@ describe('ValidationErrorComponent', () => { expect(component).toBeTruthy(); }); - describe('get message for issue', () => { + describe('get message from invalidParam', () => { const fieldLabel: string = 'Field Label'; + const invalidParam: InvalidParam = { + ...createInvalidParam(), + reason: ValidationMessageCode.VALIDATION_FIELD_SIZE, + messageCode: ValidationMessageCode.VALIDATION_FIELD_SIZE, + }; - it('should return message', () => { - const msg: string = getMessageForIssue(fieldLabel, { - ...createIssue(), - messageCode: 'validation_field_size', - }); + it('should contain ', () => { + const msg: string = getMessageForInvalidParam(fieldLabel, invalidParam); expect(msg).toContain('muss mindestens'); }); it('should set field label', () => { - const msg: string = getMessageForIssue(fieldLabel, { - ...createIssue(), - messageCode: 'validation_field_size', - }); + const msg: string = getMessageForInvalidParam(fieldLabel, invalidParam); expect(msg).toContain(fieldLabel); }); it('should replace min param', () => { - const msg: string = getMessageForIssue(fieldLabel, { - ...createIssue(), - messageCode: 'validation_field_size', - parameters: [{ name: 'min', value: '3' }], + const msg: string = getMessageForInvalidParam(fieldLabel, { + ...invalidParam, + constraintParameters: [{ name: 'min', value: '3' }], }); expect(msg).toContain('3'); diff --git a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.ts b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.ts index d47b675b4984616c8ff76acaa04d3c73ebafad42..4d8a67a6e5f9ee9d39a99c9fe5fd97fe6136fe2c 100644 --- a/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.ts +++ b/alfa-client/libs/design-component/src/lib/form/validation-error/validation-error.component.ts @@ -1,4 +1,4 @@ -import { Issue, getMessageForIssue } from '@alfa-client/tech-shared'; +import { InvalidParam, getMessageForInvalidParam } from '@alfa-client/tech-shared'; import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { ErrorMessageComponent } from '@ods/system'; @@ -11,9 +11,9 @@ import { ErrorMessageComponent } from '@ods/system'; }) export class ValidationErrorComponent { @Input() label: string; - @Input() issues: Issue[]; + @Input() invalidParams: InvalidParam[]; - public message(issue: Issue): string { - return getMessageForIssue(this.label, issue); + public message(invalidParam: InvalidParam): string { + return getMessageForInvalidParam(this.label, invalidParam); } } diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts index ab647437a8483fb73bccc4fa0e4d083ef8c48cde..62a5bb8f8b36733b32c4de0bc7a52150dc39bfc0 100644 --- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts +++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts @@ -30,14 +30,17 @@ import { map } from 'rxjs/operators'; import { hasStateResourceError, StateResource } from '../resource/resource.util'; import { ApiError, HttpError, InvalidParam, Issue, ProblemDetail } from '../tech.model'; import { isNotUndefined } from '../tech.util'; -import { setInvalidParamValidationError, setIssueValidationError } from '../validation/tech.validation.util'; +import { + setInvalidParamValidationError, + setIssueValidationError, +} from '../validation/tech.validation.util'; export abstract class AbstractFormService { form: UntypedFormGroup; pathPrefix: string; source: any; - private readonly PROBLEM_DETAIL_INVALID_PARAMS_KEY: string = 'invalid-params'; + private readonly PROBLEM_DETAIL_INVALID_PARAMS_KEY: string = 'invalidParams'; constructor(public formBuilder: UntypedFormBuilder) { this.form = this.initForm(); diff --git a/alfa-client/libs/tech-shared/src/lib/tech.model.ts b/alfa-client/libs/tech-shared/src/lib/tech.model.ts index c85852676e5184152aa17856cca07bd33b3a3223..adcda221a6e272f1494c104cae61ddee82fdff98 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech.model.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech.model.ts @@ -47,12 +47,20 @@ export interface ProblemDetail { status: HttpStatusCode; detail: string; instance: string; - 'invalid-params': InvalidParam[]; + invalidParams: InvalidParam[]; } export interface InvalidParam { + constraintParameters: ConstraintParameter[]; + messageCode: ValidationMessageCode; name: string; reason: ValidationMessageCode; + value: string; +} + +export interface ConstraintParameter { + name: string; + value: string; } export declare type HttpError = ProblemDetail | ApiError; diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts index 6c71c22768bb5ae231daf6b3522002a9110bda00..741c2f747f7aecd460da684d643aee4f15de94a2 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts @@ -24,6 +24,7 @@ export enum ValidationMessageCode { VALIDATION_FIELD_FILE_SIZE_EXCEEDED = 'validation_field_file_size_exceeded', VALIDATION_FIELD_EMPTY = 'validation_field_empty', + VALIDATION_FIELD_SIZE = 'validation_field_size', VALIDATION_FIELD_FILE_CONTENT_TYPE_INVALID = 'validation_field_file_content_type_invalid', } @@ -31,7 +32,8 @@ export const VALIDATION_MESSAGES: { [code: string]: string } = { [ValidationMessageCode.VALIDATION_FIELD_EMPTY]: 'Bitte {field} ausfüllen', validation_field_max_size: '{field} darf höchstens {max} Zeichen enthalten', validation_field_min_size: '{field} muss aus mindestens {min} Zeichen bestehen', - validation_field_size: '{field} muss mindestens {min} und darf höchstens {max} Zeichen enthalten', + [ValidationMessageCode.VALIDATION_FIELD_SIZE]: + '{field} muss mindestens {min} und darf höchstens {max} Zeichen enthalten', validation_field_date_past: 'Das Datum für {field} muss in der Zukunft liegen', validation_field_invalid: 'Bitte {field} korrekt ausfüllen', [ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED]: diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts index 9e0902270b2423a9510872b1a5f15828549eb8d6..a0a53a088af69909713950670111b2a303151142 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts @@ -28,13 +28,17 @@ import { UntypedFormControl, UntypedFormGroup, } from '@angular/forms'; +import { faker } from '@faker-js/faker'; import { createInvalidParam, createIssue } from '../../../test/error'; import { InvalidParam, Issue } from '../tech.model'; import { getControlForInvalidParam, getControlForIssue, + getFieldPath, + getLastPart, getMessageForInvalidParam, getMessageForIssue, + getPartsAfterPrefix, setInvalidParamValidationError, setIssueValidationError, } from './tech.validation.util'; @@ -55,7 +59,7 @@ describe('ValidationUtils', () => { describe('set issue validation error', () => { describe('get control for issue', () => { it('should return base field control', () => { - const issue: Issue = { ...createIssue(), field: 'baseField1' }; + const issue: Issue = { ...createIssue(), field: 'class.resource.baseField1' }; const control: AbstractControl = getControlForIssue(form, issue); @@ -63,24 +67,24 @@ describe('ValidationUtils', () => { }); it('should return sub group field', () => { - const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; + const issue: Issue = { ...createIssue(), field: 'class.resource.subGroup.subGroupField1' }; - const control: AbstractControl = getControlForIssue(form, issue); + const control: AbstractControl = getControlForIssue(form, issue, 'resource'); expect(control).toBe(subGroupFieldControl); }); it('should ignore path prefix', () => { - const issue: Issue = { ...createIssue(), field: 'pathprefix.resource.baseField1' }; + const issue: Issue = { ...createIssue(), field: 'class.resource.baseField1' }; - const control: AbstractControl = getControlForIssue(form, issue, 'pathprefix.resource'); + const control: AbstractControl = getControlForIssue(form, issue, 'resource'); expect(control).toBe(baseField1Control); }); }); describe('in base field', () => { - const issue: Issue = { ...createIssue(), field: 'baseField1' }; + const issue: Issue = { ...createIssue(), field: 'class.resource.baseField1' }; it('should set error in control', () => { setIssueValidationError(form, issue); @@ -108,10 +112,10 @@ describe('ValidationUtils', () => { }); describe('in subGroup Field', () => { - const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; + const issue: Issue = { ...createIssue(), field: 'class.resource.subGroup.subGroupField1' }; it('should set error in control', () => { - setIssueValidationError(form, issue); + setIssueValidationError(form, issue, 'resource'); expect(subGroupFieldControl.errors).not.toBeNull(); }); @@ -150,13 +154,14 @@ describe('ValidationUtils', () => { }); }); - describe('invalid param', () => { + describe.skip('invalid param', () => { const formPrefixes: string[] = ['', 'some-prefix']; const fieldNames: string[] = ['baseField1', 'baseField2', 'subGroup.subGroupField1']; const prefixNameCombinations: string[][] = formPrefixes.flatMap((prefix) => fieldNames.map((name) => [prefix, name]), ); const unknownName = 'unknown-field'; + const fieldLabel: string = faker.lorem.word(); describe.each(prefixNameCombinations)( 'with prefix "%s" and fieldName "%s"', @@ -173,7 +178,7 @@ describe('ValidationUtils', () => { describe('get message for invalid param', () => { it('should return', () => { - const msg: string = getMessageForInvalidParam(invalidParam, prefix); + const msg: string = getMessageForInvalidParam(fieldLabel, invalidParam); expect(msg).toEqual(`Bitte ${fieldName} ausfüllen`); }); @@ -189,7 +194,7 @@ describe('ValidationUtils', () => { describe('set invalid param validation error', () => { it('should assign invalidParam to form control error without prefix', () => { - const message: string = getMessageForInvalidParam(invalidParam, prefix); + const message: string = getMessageForInvalidParam(fieldLabel, invalidParam); setInvalidParamValidationError(form, invalidParam, prefix); @@ -248,4 +253,50 @@ describe('ValidationUtils', () => { }, ); }); + + describe('getFieldPath', () => { + const resourcePath: string = 'resource'; + const backendClassName: string = 'class'; + + it('should return simple field path', () => { + const fieldPath: string = 'field1'; + const fullPath: string = `${backendClassName}.${resourcePath}.${fieldPath}`; + + const result: string = getFieldPath(fullPath); + + expect(result).toBe(fieldPath); + }); + + it('should return hierarchical field path ', () => { + const fieldPath: string = 'fieldGroup.field1'; + const fullPath: string = `${backendClassName}.${resourcePath}.${fieldPath}`; + + const result: string = getFieldPath(fullPath, resourcePath); + + expect(result).toBe(fieldPath); + }); + }); + + describe('getLastPart', () => { + it('should get last term in string of terms', () => { + const lastPart: string = 'field'; + const allParts: string = 'class.resource.' + lastPart; + + const result: string = getLastPart(allParts); + + expect(result).toBe(lastPart); + }); + }); + + describe('getPartsAfterPrefix', () => { + it('should get all parts after the prefix', () => { + const lastParts: string = 'group.field'; + const prefix: string = 'resource'; + const allParts: string = 'class.' + prefix + '.' + lastParts; + + const result: string = getPartsAfterPrefix(allParts, prefix); + + expect(result).toBe(lastParts); + }); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts index 4a34005de2f231027678dc6ce606a8cc2e3e1bed..fff656c009d7909b68186b406b00777ae92be6c7 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { AbstractControl, UntypedFormGroup } from '@angular/forms'; -import { isNil } from 'lodash-es'; +import { isEmpty, isNil } from 'lodash-es'; import { ApiError, InvalidParam, Issue, IssueParam } from '../tech.model'; -import { isNotNil, replacePlaceholder } from '../tech.util'; +import { replacePlaceholder } from '../tech.util'; import { VALIDATION_MESSAGES, ValidationMessageCode } from './tech.validation.messages'; export function isValidationError(issue: Issue): boolean { @@ -47,7 +47,7 @@ export function getControlForIssue( issue: Issue, pathPrefix?: string, ): AbstractControl { - const fieldPath: string = getFieldPathWithoutPrefix(issue.field, pathPrefix); + const fieldPath: string = getFieldPath(issue.field, pathPrefix); let curControl: AbstractControl = form; fieldPath @@ -86,12 +86,9 @@ export function setInvalidParamValidationError( pathPrefix?: string, ): void { const control: AbstractControl = getControlForInvalidParam(form, invalidParam, pathPrefix); - if (isNotNil(control)) { - control.setErrors({ - [invalidParam.reason]: getMessageForInvalidParam(invalidParam, pathPrefix), - }); - control.markAsTouched(); - } + + control.setErrors({ [invalidParam.reason]: invalidParam }); + control.markAsTouched(); } export function getControlForInvalidParam( @@ -99,17 +96,34 @@ export function getControlForInvalidParam( invalidParam: InvalidParam, pathPrefix?: string, ): AbstractControl { - return form.get(getFieldPathWithoutPrefix(invalidParam.name, pathPrefix)); + return form.get(getFieldPath(invalidParam.name, pathPrefix)); } -export function getMessageForInvalidParam(item: InvalidParam, pathPrefix: string): string { - return replacePlaceholder( - VALIDATION_MESSAGES[item.reason], - 'field', - getFieldPathWithoutPrefix(item.name, pathPrefix), +export function getMessageForInvalidParam(label: string, invalidParam: InvalidParam): string { + let msg: string = VALIDATION_MESSAGES[invalidParam.reason]; + + if (isNil(msg)) { + console.warn('No message for code ' + invalidParam.reason + ' found.'); + return invalidParam.reason; + } + + msg = replacePlaceholder(msg, 'field', label); + invalidParam.constraintParameters.forEach( + (param: IssueParam) => (msg = replacePlaceholder(msg, param.name, param.value)), ); + return msg; +} + +export function getFieldPath(name: string, pathPrefix?: string): string { + return isEmpty(pathPrefix) ? getLastPart(name) : getPartsAfterPrefix(name, pathPrefix); +} + +export function getLastPart(name: string): string { + return name.split('.').pop(); } -function getFieldPathWithoutPrefix(name: string, pathPrefix?: string): string { - return pathPrefix ? name.substring(pathPrefix.length + 1) : name; +export function getPartsAfterPrefix(name: string, pathPrefix: string): string { + pathPrefix = `${pathPrefix}.`; + const indexField = name.lastIndexOf(pathPrefix) + pathPrefix.length; + return name.slice(indexField); } diff --git a/alfa-client/libs/tech-shared/test/error.ts b/alfa-client/libs/tech-shared/test/error.ts index 9803a5a5ad90888ceb7125bc535f5c379548d126..9a37769166dee75159cdfc17509b14e9681c30c3 100644 --- a/alfa-client/libs/tech-shared/test/error.ts +++ b/alfa-client/libs/tech-shared/test/error.ts @@ -23,7 +23,14 @@ */ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { faker } from '@faker-js/faker'; -import { ApiError, InvalidParam, Issue, IssueParam, ProblemDetail } from '../src/lib/tech.model'; +import { + ApiError, + ConstraintParameter, + InvalidParam, + Issue, + IssueParam, + ProblemDetail, +} from '../src/lib/tech.model'; import { ValidationMessageCode } from '../src/lib/validation/tech.validation.messages'; export function createIssueParam(): IssueParam { @@ -63,10 +70,23 @@ export function createProblemDetail( type: faker.random.word(), instance: faker.internet.url(), detail: faker.random.word(), - 'invalid-params': invalidParams, + invalidParams: invalidParams, }; } export function createInvalidParam(): InvalidParam { - return { name: faker.random.word(), reason: ValidationMessageCode.VALIDATION_FIELD_EMPTY }; + return { + name: faker.random.word(), + reason: ValidationMessageCode.VALIDATION_FIELD_EMPTY, + value: faker.random.words(10), + messageCode: ValidationMessageCode.VALIDATION_FIELD_EMPTY, + constraintParameters: [createInvalidParamConstraintParameter()], + }; +} + +export function createInvalidParamConstraintParameter(): ConstraintParameter { + return { + name: faker.random.word(), + value: faker.random.word(), + }; } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html index 6f484f807eca85ab9ccc7bc42c43c12c9bdc850f..8a0fb969d94a66f00007edfff7f6f84f55edd969 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html @@ -54,7 +54,7 @@ <mat-error> <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-autocomplete-error'" - [issues]="issues" + [invalidParams]="invalidParams" [label]="label" > </ozgcloud-validation-error> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html index 589e1679db0ad9e505aa9b98a1c981b366e5abfb..07ec3ad16554c885825d55b1f14139a7e05a246f 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html @@ -43,7 +43,7 @@ <mat-error> <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-date-error'" - [issues]="issues" + [invalidParams]="invalidParams" [label]="label" ></ozgcloud-validation-error> </mat-error> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html index a6f83cf4e2fa94e8a84d5ee0aebbfd9fa1efd8d1..94acabf0cf558593f633a252fb6bdb35f07f5fd0 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html @@ -48,7 +48,7 @@ <mat-error> <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-error'" - [issues]="issues" + [invalidParams]="invalidParams" [label]="label" > </ozgcloud-validation-error> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html index bcf6e536c27a4a13aab0a99e43c2c155920bc241..8a8e01260fd7b5cb4af14320ea4af0d264b9a980 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html @@ -58,7 +58,7 @@ <mat-error> <ozgcloud-validation-error [attr.data-test-id]="(getPlaceholderLabel() | convertForDataTest) + '-text-error'" - [issues]="issues" + [invalidParams]="invalidParams" [label]="getPlaceholderLabel()" ></ozgcloud-validation-error> </mat-error> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html index cf3135707e7a986230e2dc9957326bb1766a6a88..14034ce169db28951cd062e19343976a81ca8d7b 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html @@ -39,8 +39,8 @@ <mat-error> <ozgcloud-validation-error - [issues]="issues" [label]="label" + [invalidParams]="invalidParams" [attr.data-test-id]="(label | convertForDataTest) + '-textarea-error'" > </ozgcloud-validation-error> diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html index 13f1ef45c46566b76aad56247845108a014310e6..2c47c8ccdafa3929335cd41715394e7c2e11357d 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<span *ngFor="let issue of issues">{{ message(issue) }}</span> +<span *ngFor="let invalidParam of invalidParams">{{ message(invalidParam) }}</span> diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts index 299af463232908e4f3edec96f97f7fd912379b0e..1fde64a2f65c14891b42c852e39b71c327d4cef4 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts @@ -21,8 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { InvalidParam, getMessageForInvalidParam } from '@alfa-client/tech-shared'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createIssue } from 'libs/tech-shared/test/error'; +import { ValidationMessageCode } from 'libs/tech-shared/src/lib/validation/tech.validation.messages'; +import { createInvalidParam } from 'libs/tech-shared/test/error'; import { ValidationErrorComponent } from './validation-error.component'; describe('ValidationErrorComponent', () => { @@ -45,9 +47,33 @@ describe('ValidationErrorComponent', () => { expect(component).toBeTruthy(); }); - it('should get message', () => { - var msg = component.message({ ...createIssue(), messageCode: 'validation_field_size' }); + describe('get message from invalidParam', () => { + const fieldLabel: string = 'Field Label'; + const invalidParam: InvalidParam = { + ...createInvalidParam(), + reason: ValidationMessageCode.VALIDATION_FIELD_SIZE, + messageCode: ValidationMessageCode.VALIDATION_FIELD_SIZE, + }; - expect(msg).not.toHaveLength(0); + it('should contain ', () => { + const msg: string = getMessageForInvalidParam(fieldLabel, invalidParam); + + expect(msg).toContain('muss mindestens'); + }); + + it('should set field label', () => { + const msg: string = getMessageForInvalidParam(fieldLabel, invalidParam); + + expect(msg).toContain(fieldLabel); + }); + + it('should replace min param', () => { + const msg: string = getMessageForInvalidParam(fieldLabel, { + ...invalidParam, + constraintParameters: [{ name: 'min', value: '3' }], + }); + + expect(msg).toContain('3'); + }); }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts index 0432ac003dae9960503559194148fb5d79f52c45..1c5e6df544c2a3d480dd40d6915b72ef166c7273 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts @@ -21,8 +21,8 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { InvalidParam, getMessageForInvalidParam } from '@alfa-client/tech-shared'; import { Component, Input } from '@angular/core'; -import { getMessageForIssue, Issue } from '@alfa-client/tech-shared'; @Component({ selector: 'ozgcloud-validation-error', @@ -31,9 +31,9 @@ import { getMessageForIssue, Issue } from '@alfa-client/tech-shared'; }) export class ValidationErrorComponent { @Input() label: string; - @Input() issues: Issue[]; + @Input() invalidParams: InvalidParam[]; - public message(issue: Issue): string { - return getMessageForIssue(this.label, issue); + public message(invalidParam: InvalidParam): string { + return getMessageForInvalidParam(this.label, invalidParam); } }