From 54fd097fab9153efb705de7c65c1dc01b2a16799 Mon Sep 17 00:00:00 2001 From: Mykyta Maliarchuk <84377976+nikita-web-ua@users.noreply.github.com> Date: Mon, 7 Jul 2025 10:12:49 +0200 Subject: [PATCH] [ACS-9327] Add prohibited symbols validation for Categories dialog (#10985) * [ACS-9327] Add prohibited symbols validation for Categories dialog * [ACS-9327] add validator for ending dot * [ACS-9327] use endsWith * [ACS-9327] cr fix * [ACS-9327] add appropriate error message --- .../categories-management.component.html | 2 +- .../categories-management.component.spec.ts | 30 +++++++++++++++---- .../categories-management.component.ts | 23 ++++++++++++-- lib/content-services/src/lib/i18n/en.json | 4 ++- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/lib/content-services/src/lib/category/categories-management/categories-management.component.html b/lib/content-services/src/lib/category/categories-management/categories-management.component.html index 9a02fb4fe8..f0c8d0a594 100644 --- a/lib/content-services/src/lib/category/categories-management/categories-management.component.html +++ b/lib/content-services/src/lib/category/categories-management/categories-management.component.html @@ -6,7 +6,7 @@ placeholder="{{'CATEGORIES_MANAGEMENT.CATEGORIES_SEARCH_PLACEHOLDER' | translate }}" adf-auto-focus /> - {{ categoryNameErrorMessageKey | translate }} + {{ categoryNameErrorMessageKey | translate }}
{ expect(component.categoryNameControl.hasValidator(Validators.required)).toBeFalse(); }); - it('should display validation error when searching for empty category', fakeAsync(() => { - typeCategory(' '); - - expect(getFirstError()).toBe('CATEGORIES_MANAGEMENT.ERRORS.EMPTY_CATEGORY'); - })); - it('should clear categories and hide category control when classifiable aspect is removed', () => { const controlVisibilityChangeSpy = spyOn(component.categoryNameControlVisibleChange, 'emit').and.callThrough(); classifiableChangedSubject.next(); @@ -523,6 +517,30 @@ describe('CategoriesManagementComponent', () => { expect(getCreateCategoryLabel().hidden).toBeTrue(); })); + + it('should display validation error when prohibited symbol entered', fakeAsync(() => { + typeCategory('category:name'); + component.categoryNameControl.markAsTouched(); + fixture.detectChanges(); + + expect(getFirstError()).toBe('CATEGORIES_MANAGEMENT.ERRORS.SPECIAL_CHARACTERS'); + })); + + it('should display validation error when dot placed in the end', fakeAsync(() => { + typeCategory('category.'); + component.categoryNameControl.markAsTouched(); + fixture.detectChanges(); + + expect(getFirstError()).toBe('CATEGORIES_MANAGEMENT.ERRORS.ENDS_WITH_DOT'); + })); + + it('should not display validation error when dot used in positions other than the end', fakeAsync(() => { + typeCategory('.category.name'); + component.categoryNameControl.markAsTouched(); + fixture.detectChanges(); + + expect(component.categoryNameControl.valid).toBeTrue(); + })); }); }); }); diff --git a/lib/content-services/src/lib/category/categories-management/categories-management.component.ts b/lib/content-services/src/lib/category/categories-management/categories-management.component.ts index 31e7430255..bd58cb230c 100644 --- a/lib/content-services/src/lib/category/categories-management/categories-management.component.ts +++ b/lib/content-services/src/lib/category/categories-management/categories-management.component.ts @@ -49,6 +49,8 @@ interface CategoryNameControlErrors { duplicatedCategory?: boolean; emptyCategory?: boolean; required?: boolean; + specialCharacters?: boolean; + endsWithDot?: boolean; } @Component({ @@ -73,14 +75,22 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy { ['duplicatedExistingCategory', 'ALREADY_EXISTS'], ['duplicatedCategory', 'DUPLICATED_CATEGORY'], ['emptyCategory', 'EMPTY_CATEGORY'], - ['required', 'REQUIRED'] + ['required', 'REQUIRED'], + ['specialCharacters', 'SPECIAL_CHARACTERS'], + ['endsWithDot', 'ENDS_WITH_DOT'] ]); private existingCategoryLoaded$ = new Subject(); private cancelExistingCategoriesLoading$ = new Subject(); private _categoryNameControl = new FormControl( '', - [this.validateIfNotAlreadyAdded.bind(this), this.validateEmptyCategory, Validators.required], + [ + this.validateIfNotAlreadyAdded.bind(this), + this.validateEmptyCategory, + this.validateSpecialCharacters, + this.validateEndsWithDot, + Validators.required + ], this.validateIfNotAlreadyCreated.bind(this) ); private _existingCategories: Category[]; @@ -358,6 +368,15 @@ export class CategoriesManagementComponent implements OnInit, OnDestroy { return categoryNameControl.value.length && !categoryNameControl.value.trim() ? { emptyCategory: true } : null; } + private validateSpecialCharacters(categoryNameControl: FormControl): CategoryNameControlErrors | null { + const specialSymbolsRegex = /[:"\\|<>/?*]/; + return categoryNameControl.value.length && specialSymbolsRegex.test(categoryNameControl.value) ? { specialCharacters: true } : null; + } + + private validateEndsWithDot(categoryNameControl: FormControl): CategoryNameControlErrors | null { + return categoryNameControl.value.trim().endsWith('.') ? { endsWithDot: true } : null; + } + private setCategoryNameControlErrorMessageKey() { this._categoryNameErrorMessageKey = this.categoryNameControl.invalid ? `CATEGORIES_MANAGEMENT.ERRORS.${this.nameErrorMessagesByErrors.get( diff --git a/lib/content-services/src/lib/i18n/en.json b/lib/content-services/src/lib/i18n/en.json index 292f5178ef..0e3145cf2d 100644 --- a/lib/content-services/src/lib/i18n/en.json +++ b/lib/content-services/src/lib/i18n/en.json @@ -183,7 +183,9 @@ "ALREADY_EXISTS": "Category already exists", "DUPLICATED_CATEGORY": "Category is already added", "CREATE_CATEGORIES": "Error while creating categories", - "EXISTING_CATEGORIES": "Some categories already exist" + "EXISTING_CATEGORIES": "Some categories already exist", + "SPECIAL_CHARACTERS": "Category name cannot contain prohibited characters", + "ENDS_WITH_DOT": "Category name cannot end with a dot" }, "CATEGORIES_SEARCH_PLACEHOLDER": "Search Categories" },