mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ACS-4749] add button is enabled for comment contains only spaces (#10577)
* [ACS-4749] Disabled add button for comment when comment has only spaces * [ACS-4749] Unit tests * [ACS-4749] Removed redundant code * [ACS-4749] Fixed sonar issue * [ACS-4749] Resolved issues after rebase * [ACS-4749] Addressed PR comment
This commit is contained in:
parent
e6278109d8
commit
1634716bbe
@ -8,22 +8,22 @@
|
|||||||
matInput
|
matInput
|
||||||
id="comment-input"
|
id="comment-input"
|
||||||
class="adf-text-text-area"
|
class="adf-text-text-area"
|
||||||
[placeholder]='"COMMENTS.ADD" | translate'
|
[placeholder]='("COMMENTS.ADD" | translate) + "*"'
|
||||||
[attr.aria-label]="'COMMENTS.ADD' | translate"
|
[attr.aria-label]="'COMMENTS.ADD' | translate"
|
||||||
[(ngModel)]="message"
|
[formControl]="commentControl"
|
||||||
(keydown.escape)="clearMessage($event)"
|
(keydown.escape)="clearMessage($event)"
|
||||||
>
|
>
|
||||||
</textarea>
|
</textarea>
|
||||||
|
<mat-error *ngIf="commentControl.invalid && commentControl.touched">{{ 'COMMENTS.EMPTY_ERROR' | translate }}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div class="adf-comments-input-actions">
|
<div class="adf-comments-input-actions">
|
||||||
<button
|
<button
|
||||||
mat-button
|
mat-button
|
||||||
class="adf-comments-input-add"
|
|
||||||
data-automation-id="comments-input-add"
|
data-automation-id="comments-input-add"
|
||||||
color="primary"
|
color="primary"
|
||||||
(click)="addComment()"
|
(click)="addComment()"
|
||||||
[disabled]="!message"
|
[disabled]="commentControl.invalid"
|
||||||
>
|
>
|
||||||
{{ 'COMMENTS.ADD' | translate }}
|
{{ 'COMMENTS.ADD' | translate }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -12,10 +12,15 @@ adf-comments {
|
|||||||
|
|
||||||
#{$mat-form-field} {
|
#{$mat-form-field} {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
#{$mat-form-field-subscript-wrapper} {
|
&#{$mat-form-field-invalid} {
|
||||||
display: none;
|
#{$mat-input-element} {
|
||||||
|
&::placeholder,
|
||||||
|
&:focus::placeholder {
|
||||||
|
color: var(--theme-warn-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#{$mat-form-field-wrapper} {
|
#{$mat-form-field-wrapper} {
|
||||||
|
@ -25,6 +25,7 @@ import { CommentsService } from './interfaces/comments-service.interface';
|
|||||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { NoopTranslateModule } from '../testing/noop-translate.module';
|
import { NoopTranslateModule } from '../testing/noop-translate.module';
|
||||||
import { UnitTestingUtils } from '../testing/unit-testing-utils';
|
import { UnitTestingUtils } from '../testing/unit-testing-utils';
|
||||||
|
import { MatError } from '@angular/material/form-field';
|
||||||
|
|
||||||
describe('CommentsComponent', () => {
|
describe('CommentsComponent', () => {
|
||||||
let component: CommentsComponent;
|
let component: CommentsComponent;
|
||||||
@ -156,6 +157,10 @@ describe('CommentsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Add comment', () => {
|
describe('Add comment', () => {
|
||||||
|
const getError = (): string => testingUtils.getByDirective(MatError)?.nativeElement?.textContent;
|
||||||
|
|
||||||
|
const getAddCommentButton = (): HTMLButtonElement => testingUtils.getByDataAutomationId('comments-input-add').nativeElement;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.id = '123';
|
component.id = '123';
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -163,8 +168,8 @@ describe('CommentsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should normalize comment when user input contains spaces sequence', async () => {
|
it('should normalize comment when user input contains spaces sequence', async () => {
|
||||||
component.message = 'test comment';
|
component.commentControl.setValue('test comment');
|
||||||
testingUtils.clickByCSS('.adf-comments-input-add');
|
getAddCommentButton().dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@ -184,8 +189,8 @@ describe('CommentsComponent', () => {
|
|||||||
getCommentSpy.and.returnValue(of([]));
|
getCommentSpy.and.returnValue(of([]));
|
||||||
addCommentSpy.and.returnValue(commentsResponseMock.addComment(commentText));
|
addCommentSpy.and.returnValue(commentsResponseMock.addComment(commentText));
|
||||||
|
|
||||||
component.message = commentText;
|
component.commentControl.setValue(commentText);
|
||||||
testingUtils.clickByCSS('.adf-comments-input-add');
|
getAddCommentButton().dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@ -195,9 +200,10 @@ describe('CommentsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should call service to add a comment when add button is pressed', async () => {
|
it('should call service to add a comment when add button is pressed', async () => {
|
||||||
component.message = 'Test Comment';
|
const comment = 'Test Comment';
|
||||||
addCommentSpy.and.returnValue(commentsResponseMock.addComment(component.message));
|
component.commentControl.setValue(comment);
|
||||||
testingUtils.clickByCSS('.adf-comments-input-add');
|
addCommentSpy.and.returnValue(commentsResponseMock.addComment(comment));
|
||||||
|
getAddCommentButton().dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@ -209,8 +215,8 @@ describe('CommentsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not call service to add a comment when comment is empty', async () => {
|
it('should not call service to add a comment when comment is empty', async () => {
|
||||||
component.message = '';
|
component.commentControl.setValue('');
|
||||||
testingUtils.clickByCSS('.adf-comments-input-add');
|
getAddCommentButton().dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
await fixture.whenStable();
|
await fixture.whenStable();
|
||||||
@ -231,7 +237,7 @@ describe('CommentsComponent', () => {
|
|||||||
it('should emit an error when an error occurs adding the comment', () => {
|
it('should emit an error when an error occurs adding the comment', () => {
|
||||||
const emitSpy = spyOn(component.error, 'emit');
|
const emitSpy = spyOn(component.error, 'emit');
|
||||||
addCommentSpy.and.returnValue(throwError(() => new Error('error')));
|
addCommentSpy.and.returnValue(throwError(() => new Error('error')));
|
||||||
component.message = 'Test comment';
|
component.commentControl.setValue('Test comment');
|
||||||
component.addComment();
|
component.addComment();
|
||||||
expect(emitSpy).toHaveBeenCalled();
|
expect(emitSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@ -255,9 +261,85 @@ describe('CommentsComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should not add comment if message is empty', () => {
|
it('should not add comment if message is empty', () => {
|
||||||
component.message = '';
|
component.commentControl.setValue('');
|
||||||
component.addComment();
|
component.addComment();
|
||||||
expect(addCommentSpy).not.toHaveBeenCalled();
|
expect(addCommentSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not display error message initially', () => {
|
||||||
|
expect(getError()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display error message when comment is empty and was touched', () => {
|
||||||
|
component.commentControl.setValue('');
|
||||||
|
component.commentControl.markAsTouched();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBe('COMMENTS.EMPTY_ERROR');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display error message when comment has only spaces and was touched', () => {
|
||||||
|
component.commentControl.setValue(' ');
|
||||||
|
component.commentControl.markAsTouched();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBe('COMMENTS.EMPTY_ERROR');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display error message when comment is empty but was not touched', () => {
|
||||||
|
component.commentControl.setValue('');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display error message when comment has only spaces but was not touched', () => {
|
||||||
|
component.commentControl.setValue(' ');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display error message when comment is not empty and was touched', () => {
|
||||||
|
component.commentControl.setValue('Some comment');
|
||||||
|
component.commentControl.markAsTouched();
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display error message when comment is not empty and was not touched', () => {
|
||||||
|
component.commentControl.setValue('Some comment');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getError()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable add button initially', () => {
|
||||||
|
expect(getAddCommentButton().disabled).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable add button when comment is empty', () => {
|
||||||
|
component.commentControl.setValue('Some comment');
|
||||||
|
component.commentControl.setValue('');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getAddCommentButton().disabled).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable add button when comment has only spaces', () => {
|
||||||
|
component.commentControl.setValue('Some comment');
|
||||||
|
component.commentControl.setValue(' ');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getAddCommentButton().disabled).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable add button when comment is not empty', () => {
|
||||||
|
component.commentControl.setValue('Some comment');
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(getAddCommentButton().disabled).toBeFalse();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -23,14 +23,23 @@ import { CommonModule } from '@angular/common';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormControl, FormsModule, ReactiveFormsModule, ValidationErrors } from '@angular/forms';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { CommentListComponent } from './comment-list';
|
import { CommentListComponent } from './comment-list';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'adf-comments',
|
selector: 'adf-comments',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, TranslateModule, MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, CommentListComponent],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
FormsModule,
|
||||||
|
MatButtonModule,
|
||||||
|
CommentListComponent,
|
||||||
|
ReactiveFormsModule
|
||||||
|
],
|
||||||
templateUrl: './comments.component.html',
|
templateUrl: './comments.component.html',
|
||||||
styleUrls: ['./comments.component.scss'],
|
styleUrls: ['./comments.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
@ -49,11 +58,16 @@ export class CommentsComponent implements OnChanges {
|
|||||||
error = new EventEmitter<any>();
|
error = new EventEmitter<any>();
|
||||||
|
|
||||||
comments: CommentModel[] = [];
|
comments: CommentModel[] = [];
|
||||||
message: string;
|
|
||||||
beingAdded: boolean = false;
|
beingAdded: boolean = false;
|
||||||
|
|
||||||
private commentsService = inject<CommentsService>(ADF_COMMENTS_SERVICE);
|
private commentsService = inject<CommentsService>(ADF_COMMENTS_SERVICE);
|
||||||
|
|
||||||
|
private readonly _commentControl = new FormControl('', [this.validateEmptyComment]);
|
||||||
|
|
||||||
|
get commentControl(): FormControl<string> {
|
||||||
|
return this._commentControl;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
this.id = null;
|
this.id = null;
|
||||||
|
|
||||||
@ -95,10 +109,10 @@ export class CommentsComponent implements OnChanges {
|
|||||||
|
|
||||||
this.beingAdded = true;
|
this.beingAdded = true;
|
||||||
|
|
||||||
this.commentsService.add(this.id, this.message).subscribe({
|
this.commentsService.add(this.id, this.commentControl.value).subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
this.addToComments(res);
|
this.addToComments(res);
|
||||||
this.resetMessage();
|
this.commentControl.reset();
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
this.error.emit(err);
|
this.error.emit(err);
|
||||||
@ -111,19 +125,15 @@ export class CommentsComponent implements OnChanges {
|
|||||||
|
|
||||||
clearMessage(event: Event): void {
|
clearMessage(event: Event): void {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.resetMessage();
|
this.commentControl.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
private addToComments(comment: CommentModel): void {
|
private addToComments(comment: CommentModel): void {
|
||||||
this.comments.unshift(comment);
|
this.comments.unshift(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetMessage(): void {
|
|
||||||
this.message = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
private canAddComment(): boolean {
|
private canAddComment(): boolean {
|
||||||
return this.hasId() && this.message && this.message.trim() && !this.beingAdded;
|
return this.hasId() && this.commentControl.value?.trim() && !this.beingAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasId(): boolean {
|
private hasId(): boolean {
|
||||||
@ -146,4 +156,8 @@ export class CommentsComponent implements OnChanges {
|
|||||||
private resetComments(): void {
|
private resetComments(): void {
|
||||||
this.comments = [];
|
this.comments = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private validateEmptyComment(commentControl: FormControl<string>): ValidationErrors {
|
||||||
|
return commentControl.value?.trim() ? null : { emptyComment: true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +306,7 @@
|
|||||||
"HEADER": "Comments ({{ count }})",
|
"HEADER": "Comments ({{ count }})",
|
||||||
"CREATED_BY_HEADER": "Created by",
|
"CREATED_BY_HEADER": "Created by",
|
||||||
"MESSAGE_HEADER": "Message",
|
"MESSAGE_HEADER": "Message",
|
||||||
|
"EMPTY_ERROR": "Comment can't be empty",
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
"TITLE": "New comment",
|
"TITLE": "New comment",
|
||||||
"LABELS": {
|
"LABELS": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user