diff --git a/src/web/app/components/account-requests-table/__snapshots__/account-request-table.component.spec.ts.snap b/src/web/app/components/account-requests-table/__snapshots__/account-request-table.component.spec.ts.snap
new file mode 100644
index 00000000000..51ad25e8f44
--- /dev/null
+++ b/src/web/app/components/account-requests-table/__snapshots__/account-request-table.component.spec.ts.snap
@@ -0,0 +1,758 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AccountRequestTableComponent should display account requests with no reset or expand links button 1`] = `
+
+
+
+
+
+
+
+
+ Name
+ |
+
+ Email
+ |
+
+ Status
+ |
+
+ Institute, Country
+ |
+
+ Created At
+ |
+
+ Comments
+ |
+
+ Options
+ |
+
+
+
+
+
+ name
+ |
+
+ email
+ |
+
+ PENDING
+ |
+
+ institute
+ |
+
+ Tue, 08 Feb 2022, 08:23 AM +00:00
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ name
+ |
+
+ email
+ |
+
+ PENDING
+ |
+
+ institute
+ |
+
+ Tue, 08 Feb 2022, 08:23 AM +00:00
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+`;
+
+exports[`AccountRequestTableComponent should display account requests with reset button and expandable links buttons 1`] = `
+
+
+
+
+
+
+
+
+ Name
+ |
+
+ Email
+ |
+
+ Status
+ |
+
+ Institute, Country
+ |
+
+ Created At
+ |
+
+ Registered At
+ |
+
+ Comments
+ |
+
+ Options
+ |
+
+
+
+
+
+ name
+ |
+
+ email
+ |
+
+ APPROVED
+ |
+
+ institute
+ |
+
+ Tue, 08 Feb 2022, 08:23 AM +00:00
+ |
+
+ Not Registered Yet
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+ name
+ |
+
+ email
+ |
+
+ REGISTERED
+ |
+
+ institute
+ |
+
+ Tue, 08 Feb 2022, 08:23 AM +00:00
+ |
+
+ Not Registered Yet
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+`;
+
+exports[`AccountRequestTableComponent should snap with an expanded account requests table 1`] = `
+
+
+
+
+
+
+
+
+ Name
+ |
+
+ Email
+ |
+
+ Status
+ |
+
+ Institute, Country
+ |
+
+ Created At
+ |
+
+ Comments
+ |
+
+ Options
+ |
+
+
+
+
+
+ name
+ |
+
+ email
+ |
+
+ PENDING
+ |
+
+ institute
+ |
+
+ Tue, 08 Feb 2022, 08:23 AM +00:00
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+`;
diff --git a/src/web/app/components/account-requests-table/account-request-table.component.html b/src/web/app/components/account-requests-table/account-request-table.component.html
index 5095fac7a61..7bf55527f90 100644
--- a/src/web/app/components/account-requests-table/account-request-table.component.html
+++ b/src/web/app/components/account-requests-table/account-request-table.component.html
@@ -66,12 +66,12 @@
-
+
-
+
-
-
+
+
diff --git a/src/web/app/components/account-requests-table/admin-edit-request-modal/admin-edit-request-modal.component.spec.ts b/src/web/app/components/account-requests-table/admin-edit-request-modal/admin-edit-request-modal.component.spec.ts
new file mode 100644
index 00000000000..a2bf17e2fde
--- /dev/null
+++ b/src/web/app/components/account-requests-table/admin-edit-request-modal/admin-edit-request-modal.component.spec.ts
@@ -0,0 +1,60 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { EditRequestModalComponent } from './admin-edit-request-modal.component';
+
+describe('RejectWithReasonModal', () => {
+ let fixture: ComponentFixture;
+ let component: EditRequestModalComponent;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [],
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [NgbActiveModal],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditRequestModalComponent);
+ fixture.detectChanges();
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should show empty fields', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should show populated data', () => {
+ component.accountRequestName = 'John Doe';
+ component.accountRequestEmail = 'johndoe@email.com';
+ component.accountRequestInstitution = 'NUS';
+ component.accountRequestComments = 'Comments';
+ fixture.detectChanges();
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should close modal with data', () => {
+ const spyActiveModal = jest.spyOn(component.activeModal, 'close');
+ component.accountRequestName = 'John Doe';
+ component.accountRequestEmail = 'johndoe@email.com';
+ component.accountRequestInstitution = 'NUS';
+ component.accountRequestComments = 'Comments';
+ fixture.detectChanges();
+ component.edit();
+ expect(spyActiveModal).toHaveBeenCalled();
+ expect(spyActiveModal).toHaveBeenCalledWith({
+ accountRequestName: 'John Doe',
+ accountRequestEmail: 'johndoe@email.com',
+ accountRequestInstitution: 'NUS',
+ accountRequestComment: 'Comments',
+ });
+ });
+});
diff --git a/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/__snapshots__/admin-reject-with-reason-modal.component.spec.ts.snap b/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/__snapshots__/admin-reject-with-reason-modal.component.spec.ts.snap
new file mode 100644
index 00000000000..a9fba7d8d6f
--- /dev/null
+++ b/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/__snapshots__/admin-reject-with-reason-modal.component.spec.ts.snap
@@ -0,0 +1,84 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RejectWithReasonModal should show empty title and body 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/admin-reject-with-reason-modal.component.spec.ts b/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/admin-reject-with-reason-modal.component.spec.ts
new file mode 100644
index 00000000000..66c831077b0
--- /dev/null
+++ b/src/web/app/components/account-requests-table/admin-reject-with-reason-modal/admin-reject-with-reason-modal.component.spec.ts
@@ -0,0 +1,80 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { RejectWithReasonModalComponent } from './admin-reject-with-reason-modal.component';
+import { StatusMessageService } from '../../../../services/status-message.service';
+
+describe('RejectWithReasonModal', () => {
+ let statusMessageService: StatusMessageService;
+ let fixture: ComponentFixture;
+ let component: RejectWithReasonModalComponent;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ declarations: [],
+ imports: [
+ HttpClientTestingModule,
+ ],
+ providers: [NgbActiveModal, StatusMessageService],
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RejectWithReasonModalComponent);
+ statusMessageService = TestBed.inject(StatusMessageService);
+ fixture.detectChanges();
+ component = fixture.componentInstance;
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should show empty title and body', () => {
+ expect(fixture).toMatchSnapshot();
+ });
+
+ it('should show error message when title is empty upon submitting', () => {
+ component.rejectionReasonTitle = '';
+ fixture.detectChanges();
+
+ const spyStatusMessageService = jest.spyOn(statusMessageService, 'showErrorToast')
+ .mockImplementation((args: string) => {
+ expect(args).toEqual('Please provide a title for the rejection email.');
+ });
+
+ const rejectButton: any = fixture.debugElement.query(By.css('#btn-confirm-reject-request'));
+ rejectButton.nativeElement.click();
+
+ expect(spyStatusMessageService).toHaveBeenCalled();
+ });
+
+ it('should show error message when body is empty upon submitting', () => {
+ component.rejectionReasonBody = '';
+ fixture.detectChanges();
+
+ const spyStatusMessageService = jest.spyOn(statusMessageService, 'showErrorToast')
+ .mockImplementation((args: string) => {
+ expect(args).toEqual('Please provide an email body for the rejection email.');
+ });
+
+ const rejectButton: any = fixture.debugElement.query(By.css('#btn-confirm-reject-request'));
+ rejectButton.nativeElement.click();
+ expect(spyStatusMessageService).toHaveBeenCalled();
+ });
+
+ it('should close modal with data', () => {
+ const spyActiveModal = jest.spyOn(component.activeModal, 'close');
+ component.rejectionReasonTitle = 'Rejection Title';
+ component.rejectionReasonBody = 'Rejection Body';
+ fixture.detectChanges();
+ component.reject();
+ expect(spyActiveModal).toHaveBeenCalled();
+ expect(spyActiveModal).toHaveBeenCalledWith({
+ rejectionReasonTitle: 'Rejection Title',
+ rejectionReasonBody: 'Rejection Body',
+ });
+ });
+});
diff --git a/src/web/app/pages-admin/admin-search-page/__snapshots__/admin-search-page.component.spec.ts.snap b/src/web/app/pages-admin/admin-search-page/__snapshots__/admin-search-page.component.spec.ts.snap
index a2bbd6ccf84..58f15f5a35d 100644
--- a/src/web/app/pages-admin/admin-search-page/__snapshots__/admin-search-page.component.spec.ts.snap
+++ b/src/web/app/pages-admin/admin-search-page/__snapshots__/admin-search-page.component.spec.ts.snap
@@ -384,208 +384,6 @@ exports[`AdminSearchPageComponent should snap with a search key 1`] = `
`;
-exports[`AdminSearchPageComponent should snap with an expanded account requests table 1`] = `
-
-
-
-
- Tips: Surround key word to search a whole string or string contains punctuation like "-" "."
-
-
-
-
-
-
- 100 characters left
-
-
-
-
-
-
-
-
-
-
- Name
- |
-
- Email
- |
-
- Status
- |
-
- Institute, Country
- |
-
- Created At
- |
-
- Comments
- |
-
- Options
- |
-
-
-
-
-
- name
- |
-
- email
- |
-
- PENDING
- |
-
- institute
- |
-
- Tue, 08 Feb 2022, 08:23 AM +00:00
- |
-
-
- |
-
-
-
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
-`;
-
exports[`AdminSearchPageComponent should snap with an expanded instructor table 1`] = `
{
let component: AdminSearchPageComponent;
let fixture: ComponentFixture;
@@ -237,26 +222,6 @@ describe('AdminSearchPageComponent', () => {
expect(fixture).toMatchSnapshot();
});
- it('should snap with an expanded account requests table', () => {
- component.accountRequests = [
- {
- id: '132efa02-b208-4195-a262-a8eae25ceb95',
- name: 'name',
- email: 'email',
- instituteAndCountry: 'institute',
- status: AccountRequestStatus.PENDING,
- registrationLink: 'registrationLink',
- createdAtText: 'Tue, 08 Feb 2022, 08:23 AM +00:00',
- registeredAtText: '',
- showLinks: true,
- comments: '',
- },
- ];
-
- fixture.detectChanges();
- expect(fixture).toMatchSnapshot();
- });
-
it('should display error message for invalid input', () => {
jest.spyOn(searchService, 'searchAdmin').mockReturnValue(throwError(() => ({
error: {
@@ -410,52 +375,6 @@ describe('AdminSearchPageComponent', () => {
expect(component.students[1].showLinks).toEqual(false);
});
- it('should display account request results', () => {
- const accountRequestResults: AccountRequestTableRowModel[] = [
- {
- id: '132efa02-b208-4195-a262-a8eae25ceb95',
- name: 'name1',
- email: 'email1',
- instituteAndCountry: 'institute1',
- status: AccountRequestStatus.PENDING,
- registrationLink: 'registrationLink1',
- createdAtText: 'Tue, 08 Feb 2022, 08:23 AM +00:00',
- registeredAtText: '',
- showLinks: false,
- comments: '',
- }, {
- id: '132efa02-b208-4195-a262-a8eae25ceb95',
- name: 'name2',
- email: 'email2',
- instituteAndCountry: 'institute2',
- status: AccountRequestStatus.PENDING,
- registrationLink: 'registrationLink2',
- createdAtText: 'Tue, 08 Feb 2022, 08:23 AM +00:00',
- registeredAtText: 'Wed, 09 Feb 2022, 10:23 AM +00:00',
- showLinks: false,
- comments: '',
- }];
-
- jest.spyOn(searchService, 'searchAdmin').mockReturnValue(of({
- students: [],
- instructors: [],
- accountRequests: accountRequestResults.map((result) => ({
- ...result,
- institute: result.instituteAndCountry,
- })),
- }));
-
- const button: any = fixture.debugElement.nativeElement.querySelector('#search-button');
- button.click();
-
- expect(component.students.length).toEqual(0);
- expect(component.instructors.length).toEqual(0);
- expect(component.accountRequests.length).toEqual(2);
- expect(component.accountRequests).toEqual(accountRequestResults);
- expect(component.accountRequests[0].showLinks).toEqual(false);
- expect(component.accountRequests[1].showLinks).toEqual(false);
- });
-
it('should show instructor links when expand all button clicked', () => {
const instructorResult: InstructorAccountSearchResult = {
name: 'name',
@@ -492,17 +411,6 @@ describe('AdminSearchPageComponent', () => {
expect(component.students[0].showLinks).toEqual(true);
});
- it('should show account request links when expand all button clicked', () => {
- const accountRequestResult: AccountRequestTableRowModel = DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT;
- component.accountRequests = [accountRequestResult];
- component.searchString = 'test'; // To show the account request table
- fixture.detectChanges();
-
- const button: any = fixture.debugElement.nativeElement.querySelector('#show-account-request-links');
- button.click();
- expect(component.accountRequests[0].showLinks).toEqual(true);
- });
-
it('should show success message if successfully reset instructor google id', () => {
const instructorResult: InstructorAccountSearchResult = {
name: 'name',
@@ -909,105 +817,4 @@ describe('AdminSearchPageComponent', () => {
expect(spyStatusMessageService).toHaveBeenCalled();
});
-
- it('should show error message when deleting account request is unsuccessful', () => {
- component.accountRequests = [DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT];
- fixture.detectChanges();
-
- jest.spyOn(ngbModal, 'open').mockImplementation(() => {
- return createMockNgbModalRef({});
- });
-
- jest.spyOn(accountService, 'deleteAccountRequest').mockReturnValue(throwError(() => ({
- error: {
- message: 'This is the error message.',
- },
- })));
-
- const spyStatusMessageService: any = jest.spyOn(statusMessageService, 'showErrorToast')
- .mockImplementation((args: string) => {
- expect(args).toEqual('This is the error message.');
- });
-
- const deleteButton: any = fixture.debugElement.nativeElement.querySelector('#delete-account-request-0');
- deleteButton.click();
-
- expect(spyStatusMessageService).toHaveBeenCalled();
- });
-
- it('should show success message when deleting account request is successful', () => {
- component.accountRequests = [DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT];
- fixture.detectChanges();
-
- jest.spyOn(ngbModal, 'open').mockImplementation(() => {
- return createMockNgbModalRef({});
- });
-
- jest.spyOn(accountService, 'deleteAccountRequest').mockReturnValue(of({
- message: 'Account request successfully deleted.',
- }));
-
- const spyStatusMessageService: any = jest.spyOn(statusMessageService, 'showSuccessToast')
- .mockImplementation((args: string) => {
- expect(args).toEqual('Account request successfully deleted.');
- });
-
- const deleteButton: any = fixture.debugElement.nativeElement.querySelector('#delete-account-request-0');
- deleteButton.click();
-
- expect(spyStatusMessageService).toHaveBeenCalled();
- });
-
- it('should show error message when resetting account request is unsuccessful', () => {
- component.accountRequests = [DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT];
- component.accountRequests[0].registeredAtText = 'Wed, 09 Feb 2022, 10:23 AM +00:00';
- component.searchString = 'test';
- fixture.detectChanges();
-
- jest.spyOn(ngbModal, 'open').mockImplementation(() => {
- return createMockNgbModalRef({});
- });
-
- jest.spyOn(accountService, 'resetAccountRequest').mockReturnValue(throwError(() => ({
- error: {
- message: 'This is the error message.',
- },
- })));
-
- const spyStatusMessageService = jest.spyOn(statusMessageService, 'showErrorToast')
- .mockImplementation((args: string) => {
- expect(args).toEqual('This is the error message.');
- });
-
- const resetButton = fixture.debugElement.nativeElement.querySelector('#reset-account-request-0');
- resetButton.click();
-
- expect(spyStatusMessageService).toHaveBeenCalled();
- });
-
- it('should show success message when resetting account request is successful', () => {
- component.accountRequests = [DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT];
- component.accountRequests[0].registeredAtText = 'Wed, 09 Feb 2022, 10:23 AM +00:00';
- component.searchString = 'test';
- fixture.detectChanges();
-
- jest.spyOn(ngbModal, 'open').mockImplementation(() => {
- return createMockNgbModalRef({});
- });
-
- jest.spyOn(accountService, 'resetAccountRequest').mockReturnValue(of({
- joinLink: 'joinlink',
- }));
-
- const spyStatusMessageService = jest.spyOn(statusMessageService, 'showSuccessToast')
- .mockImplementation((args: string) => {
- expect(args)
- .toEqual(`Reset successful. An email has been sent to ${DEFAULT_ACCOUNT_REQUEST_SEARCH_RESULT.email}.`);
- });
-
- const resetButton = fixture.debugElement.nativeElement.querySelector('#reset-account-request-0');
- resetButton.click();
-
- expect(spyStatusMessageService).toHaveBeenCalled();
- });
});
diff --git a/src/web/services/account.service.ts b/src/web/services/account.service.ts
index 6f2161935ef..35c9c238111 100644
--- a/src/web/services/account.service.ts
+++ b/src/web/services/account.service.ts
@@ -101,7 +101,7 @@ export class AccountService {
* Approves account request by calling API
*/
approveAccountRequest(id: string, name: string, email: string, institute: string)
- : Observable {
+ : Observable {
const paramMap: Record = {
id,
};