generated from amosproj/amos202Xss0Y-projname
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #168 from amosproj/87-frontend-email-notification-…
…reciever-list 87 frontend email notification reciever list
- Loading branch information
Showing
23 changed files
with
1,255 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
...agement/components/settings/email-receiver-settings/email-receiver-settings.component.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.clr-dg-cell { | ||
text-align: center ; | ||
} | ||
|
||
.error { | ||
color: red; | ||
} |
78 changes: 78 additions & 0 deletions
78
...gement/components/settings/email-receiver-settings/email-receiver-settings.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<h3>Email Alert Recipients</h3> | ||
<div class="clr-row"> | ||
<div class="clr-col-lg-12 clr-col-lg-12"> | ||
<clr-datagrid | ||
*ngIf="emailsSubject$ | async as emails" | ||
[clrDgLoading]="isLoading" | ||
[(clrDgSelected)]="selectedEmails" | ||
> | ||
<clr-dg-action-bar> | ||
<div class="btn-group"> | ||
<button | ||
type="button" | ||
class="btn btn-sm btn-secondary" | ||
(click)="showEmailModal = true" | ||
> | ||
<cds-icon shape="plus"></cds-icon> | ||
New | ||
</button> | ||
<button | ||
type="button" | ||
class="btn btn-sm btn-danger" | ||
(click)="removeEmail(selectedEmails)" | ||
[disabled]="selectedEmails.length === 0" | ||
> | ||
<cds-icon shape="lock"></cds-icon> | ||
Delete | ||
</button> | ||
</div> | ||
</clr-dg-action-bar> | ||
|
||
<clr-dg-column>Email</clr-dg-column> | ||
<clr-dg-placeholder>We couldn't find any emails!</clr-dg-placeholder> | ||
<clr-dg-row | ||
*ngFor="let email of emailsSubject$.getValue()" | ||
[clrDgItem]="email" | ||
> | ||
<clr-dg-cell class="clr-dg-cell">{{ email.mail }}</clr-dg-cell> | ||
</clr-dg-row> | ||
|
||
<clr-dg-footer> </clr-dg-footer> | ||
</clr-datagrid> | ||
</div> | ||
</div> | ||
|
||
<clr-modal [(clrModalOpen)]="showEmailModal"> | ||
<h3 class="modal-title">Add Email Recipient</h3> | ||
<div class="modal-body"> | ||
<form clrForm [formGroup]="emailForm" (ngSubmit)="saveChanges()"> | ||
<clr-spinner *ngIf="isLoading"></clr-spinner> | ||
<clr-input-container> | ||
<label>Email Address</label> | ||
<input clrInput type="email" formControlName="email" /> | ||
<clr-control-error | ||
*ngIf=" | ||
emailForm.get('email')?.touched && emailForm.get('email')?.invalid | ||
" | ||
>Please enter a valid email address</clr-control-error | ||
> | ||
</clr-input-container> | ||
<div class="error" *ngIf="modalError"> | ||
{{ modalError }} | ||
</div> | ||
</form> | ||
</div> | ||
<div class="modal-footer"> | ||
<button type="button" class="btn btn-outline" (click)="resetForm()"> | ||
Cancel | ||
</button> | ||
<button | ||
type="button" | ||
class="btn btn-primary" | ||
(click)="saveChanges()" | ||
[disabled]="!emailForm.valid" | ||
> | ||
Add | ||
</button> | ||
</div> | ||
</clr-modal> |
184 changes: 184 additions & 0 deletions
184
...ent/components/settings/email-receiver-settings/email-receiver-settings.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
import { EmailReceiverSettingsComponent } from './email-receiver-settings.component'; | ||
import { FormBuilder } from '@angular/forms'; | ||
import { EmailReceiverService } from '../../../services/email-receiver/email-receiver.service'; | ||
import { of, throwError } from 'rxjs'; | ||
import { ConfirmDialogService } from '../../../../shared/components/confirm-dialog/service/confirm-dialog.service'; | ||
import { EmailType } from '../../../../shared/types/email'; | ||
|
||
describe('EmailReceiverSettingsComponent', () => { | ||
let component: EmailReceiverSettingsComponent; | ||
let emailService: EmailReceiverService; | ||
let confirmDialogService: ConfirmDialogService; | ||
|
||
const mockEmails: EmailType[] = [ | ||
{ id: '1', mail: '[email protected]' }, | ||
{ id: '2', mail: '[email protected]' }, | ||
]; | ||
|
||
beforeEach(() => { | ||
emailService = { | ||
getAllEmailReceiver: vi.fn().mockReturnValue(of(mockEmails)), | ||
deleteEmail: vi.fn().mockReturnValue(of({})), | ||
updateEmailReceiver: vi.fn(), | ||
} as any; | ||
|
||
confirmDialogService = { | ||
handleConfirmation: vi.fn().mockImplementation((options, onConfirm) => { | ||
onConfirm(); | ||
return Promise.resolve(); | ||
}), | ||
} as any; | ||
|
||
component = new EmailReceiverSettingsComponent( | ||
new FormBuilder(), | ||
emailService, | ||
confirmDialogService | ||
); | ||
|
||
component.ngOnInit(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
describe('loadEmailReceiver', () => { | ||
it('should load emails successfully', () => { | ||
component.loadEmailReceiver(); | ||
|
||
expect(component.isLoading).toBe(false); | ||
expect(emailService.getAllEmailReceiver).toHaveBeenCalled(); | ||
|
||
component['emailsSubject$'].subscribe((emails) => { | ||
expect(emails).toEqual(mockEmails); | ||
}); | ||
}); | ||
|
||
it('should handle error when loading emails', () => { | ||
emailService.getAllEmailReceiver = vi | ||
.fn() | ||
.mockReturnValue(throwError(() => new Error('Failed to load'))); | ||
|
||
component.loadEmailReceiver(); | ||
|
||
expect(component.isLoading).toBe(false); | ||
expect(emailService.getAllEmailReceiver).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
describe('removeEmail', () => { | ||
it('should not proceed if no emails to remove', async () => { | ||
await component.removeEmail([]); | ||
|
||
expect(confirmDialogService.handleConfirmation).not.toHaveBeenCalled(); | ||
expect(emailService.deleteEmail).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should delete emails when confirmed', async () => { | ||
const emailsToRemove = [mockEmails[0]]; | ||
|
||
await component.removeEmail(emailsToRemove); | ||
|
||
expect(confirmDialogService.handleConfirmation).toHaveBeenCalledWith( | ||
expect.objectContaining({ | ||
title: 'Delete Email Recipients', | ||
confirmText: 'Delete', | ||
cancelText: 'Cancel', | ||
}), | ||
expect.any(Function) | ||
); | ||
expect(emailService.deleteEmail).toHaveBeenCalledWith('1'); | ||
}); | ||
|
||
it('should handle cancel confirmation', async () => { | ||
confirmDialogService.handleConfirmation = vi | ||
.fn() | ||
.mockImplementation((options, onConfirm, onCancel) => { | ||
if (onCancel) onCancel(); | ||
return Promise.resolve(); | ||
}); | ||
|
||
await component.removeEmail([mockEmails[0]]); | ||
|
||
expect(emailService.deleteEmail).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should handle error during deletion', async () => { | ||
emailService.deleteEmail = vi | ||
.fn() | ||
.mockReturnValue(throwError(() => new Error('Delete failed'))); | ||
|
||
await component.removeEmail([mockEmails[0]]); | ||
|
||
expect(component.isLoading).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('saveChanges', () => { | ||
it('should not save when form is invalid', () => { | ||
component.emailForm.controls['email'].setValue(''); | ||
|
||
component.saveChanges(); | ||
|
||
expect(emailService.updateEmailReceiver).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should create new email when form is valid', () => { | ||
const newEmail = { mail: '[email protected]' }; | ||
const createdEmail = { id: '3', mail: '[email protected]' }; | ||
|
||
emailService.updateEmailReceiver = vi | ||
.fn() | ||
.mockReturnValue(of(createdEmail)); | ||
component.emailForm.controls['email'].setValue('[email protected]'); | ||
|
||
component.saveChanges(); | ||
|
||
expect(emailService.updateEmailReceiver).toHaveBeenCalledWith(newEmail); | ||
expect(component.showEmailModal).toBe(false); | ||
expect(component.isLoading).toBe(false); | ||
}); | ||
|
||
it('should handle duplicate email error', () => { | ||
emailService.updateEmailReceiver = vi | ||
.fn() | ||
.mockReturnValue(throwError(() => ({ status: 409 }))); | ||
component.emailForm.controls['email'].setValue('[email protected]'); | ||
|
||
component.saveChanges(); | ||
|
||
expect(component.modalError).toBe('This email already exists'); | ||
expect(component.isLoading).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('resetForm', () => { | ||
it('should reset form and modal state', () => { | ||
// Setup form with values | ||
component.emailForm.controls['email'].setValue('[email protected]'); | ||
component.showEmailModal = true; | ||
component.modalError = 'Some error'; | ||
component.isLoading = true; | ||
|
||
// Reset form | ||
component.resetForm(); | ||
|
||
// Verify reset state | ||
expect(component.emailForm.get('email')?.value).toBeNull(); | ||
expect(component.showEmailModal).toBe(false); | ||
expect(component.modalError).toBe(''); | ||
expect(component.isLoading).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('ngOnDestroy', () => { | ||
it('should complete subjects', () => { | ||
const destroySpy = vi.spyOn(component['destroy$'], 'complete'); | ||
|
||
component.ngOnDestroy(); | ||
|
||
expect(destroySpy).toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.