From fe9049a36b702d8c2c1d5be2983cd614f23e15d6 Mon Sep 17 00:00:00 2001 From: George Nash Date: Mon, 29 Apr 2024 14:47:36 +0100 Subject: [PATCH] added contact update test --- .../contact/contact-update.component.spec.ts | 150 +++++++++++++++++- .../home/contact/contact-update.component.ts | 47 +++--- 2 files changed, 172 insertions(+), 25 deletions(-) diff --git a/ui/src/app/home/contact/contact-update.component.spec.ts b/ui/src/app/home/contact/contact-update.component.spec.ts index 9958487c6..d0036f7f4 100644 --- a/ui/src/app/home/contact/contact-update.component.spec.ts +++ b/ui/src/app/home/contact/contact-update.component.spec.ts @@ -1,23 +1,167 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' -import { ContactUpdateComponent } from '../home/contact/contact-update.component' -import { AppModule } from '../app.module' +import { ContactUpdateComponent } from './contact-update.component' +import { AppModule } from '../../app.module' +import { MemberService } from 'src/app/member/service/member.service' +import { AccountService } from 'src/app/account' +import { HttpClientTestingModule } from '@angular/common/http/testing' +import { ActivatedRoute, Router } from '@angular/router' +import { RouterTestingModule } from '@angular/router/testing' +import { of } from 'rxjs' +import { SFMemberData } from 'src/app/member/model/salesforce-member-data.model' +import { AlertService } from 'src/app/shared/service/alert.service' +import { AlertType } from 'src/app/app.constants' describe('ContactUpdateComponent', () => { let component: ContactUpdateComponent let fixture: ComponentFixture + let memberServiceSpy: jasmine.SpyObj + let accountServiceSpy: jasmine.SpyObj + let alertServiceSpy: jasmine.SpyObj + let activatedRoute: jasmine.SpyObj + let router: jasmine.SpyObj beforeEach(() => { + memberServiceSpy = jasmine.createSpyObj('MemberService', ['find', 'getMemberData', 'updateContact']) + accountServiceSpy = jasmine.createSpyObj('AccountService', ['getAccountData']) + alertServiceSpy = jasmine.createSpyObj('AlertService', ['broadcast']) + TestBed.configureTestingModule({ - imports: [AppModule], + imports: [HttpClientTestingModule, RouterTestingModule], declarations: [ContactUpdateComponent], + providers: [ + { provide: MemberService, useValue: memberServiceSpy }, + { provide: AccountService, useValue: accountServiceSpy }, + { provide: AlertService, useValue: alertServiceSpy }, + ], }) + accountServiceSpy = TestBed.inject(AccountService) as jasmine.SpyObj + memberServiceSpy = TestBed.inject(MemberService) as jasmine.SpyObj + alertServiceSpy = TestBed.inject(AlertService) as jasmine.SpyObj + router = TestBed.inject(Router) as jasmine.SpyObj + activatedRoute = TestBed.inject(ActivatedRoute) as jasmine.SpyObj + fixture = TestBed.createComponent(ContactUpdateComponent) component = fixture.componentInstance fixture.detectChanges() + + spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)) }) it('should create', () => { expect(component).toBeTruthy() }) + + it('should call getAccountData and getMemberData to get contact data on init', () => { + accountServiceSpy.getAccountData.and.returnValue( + of({ + activated: true, + authorities: ['test', 'test'], + email: 'email@email.com', + firstName: 'name', + langKey: 'en', + lastName: 'surname', + imageUrl: 'url', + salesforceId: 'sfid', + loggedAs: false, + loginAs: 'sfid', + mainContact: false, + mfaEnabled: true, + }) + ) + + memberServiceSpy.getMemberData.and.returnValue( + of({ + id: 'some-id', + contacts: [ + { + memberId: 'some-id', + votingContant: false, + memberOrgRole: ['role'], + name: 'contact 1', + contactEmail: 'contact1@orcid.org', + title: 'title', + phone: '0123456789', + }, + ], + }) + ) + + component.contactId = 'contact1@orcid.org' + + component.ngOnInit() + + expect(accountServiceSpy.getAccountData).toHaveBeenCalled() + expect(memberServiceSpy.getMemberData).toHaveBeenCalled() + expect(component.contact).toBeTruthy() + }) + + it('should call memberService.updateContact when saving', () => { + component.memberData = { name: 'member' } + component.contact = { + memberId: 'some-id', + votingContant: false, + memberOrgRole: ['role'], + name: 'contact 1', + contactEmail: 'contact1@orcid.org', + title: 'title', + phone: '0123456789', + } + + memberServiceSpy.updateContact.and.returnValue(of(true)) + + // set form to valid + for (const control in component.editForm.controls) { + component.editForm.controls[control].clearAsyncValidators() + component.editForm.controls[control].clearValidators() + component.editForm.controls[control].updateValueAndValidity({ onlySelf: true }) + } + component.editForm.updateValueAndValidity() + + component.contactId = 'contact1@orcid.org' + + component.save() + + expect(memberServiceSpy.updateContact).toHaveBeenCalled() + }) + + it('should not call memberService.updateContact when saving if form is invalid', () => { + // form is invalid as we haven't set its values + component.save() + expect(memberServiceSpy.updateContact).toHaveBeenCalledTimes(0) + }) + + it('should call memberService.updateContact when deleting', () => { + component.memberData = { name: 'member' } + component.contact = { + memberId: 'some-id', + votingContant: false, + memberOrgRole: ['role'], + name: 'contact 1', + contactEmail: 'contact1@orcid.org', + title: 'title', + phone: '0123456789', + } + + memberServiceSpy.updateContact.and.returnValue(of(true)) + + // set form to valid + for (const control in component.editForm.controls) { + component.editForm.controls[control].clearAsyncValidators() + component.editForm.controls[control].clearValidators() + component.editForm.controls[control].updateValueAndValidity({ onlySelf: true }) + } + component.editForm.updateValueAndValidity() + + component.contactId = 'contact1@orcid.org' + + component.delete() + + expect(memberServiceSpy.updateContact).toHaveBeenCalled() + }) + + it('alert service and router should be called on save success', () => { + component.onSaveSuccess() + expect(alertServiceSpy.broadcast).toHaveBeenCalledWith(AlertType.CONTACT_UPDATED) + }) }) diff --git a/ui/src/app/home/contact/contact-update.component.ts b/ui/src/app/home/contact/contact-update.component.ts index fea333f24..d1409913d 100644 --- a/ui/src/app/home/contact/contact-update.component.ts +++ b/ui/src/app/home/contact/contact-update.component.ts @@ -37,7 +37,6 @@ export class ContactUpdateComponent implements OnInit, OnDestroy { isSaving = false invalidForm = false routeData: any - editForm: FormGroup | undefined contactId: string | undefined managedMember: string | undefined destroy$ = new Subject() @@ -51,6 +50,28 @@ export class ContactUpdateComponent implements OnInit, OnDestroy { new SFMemberContactRole(6, false, 'Product contact'), ] + validateContactRoles: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { + const rolesArray = control as FormArray + const selectedRoles = rolesArray.controls.filter((control) => control.value.selected) + if (selectedRoles.length < 1) { + return { oneRoleSelected: true } + } + return null + } + + editForm: FormGroup = this.fb.group({ + name: [null, [Validators.required, Validators.maxLength(80)]], + phone: [null, [Validators.maxLength(40)]], + email: [null, [Validators.required, Validators.pattern(EMAIL_REGEXP), Validators.maxLength(80)]], + title: [null, [Validators.maxLength(128)]], + roles: this.fb.array( + this.rolesData.map((val: SFMemberContactRole) => + this.fb.group({ id: val.id, selected: val.selected, name: val.name }) + ), + [this.validateContactRoles] + ), + }) + constructor( private memberService: MemberService, private accountService: AccountService, @@ -70,18 +91,7 @@ export class ContactUpdateComponent implements OnInit, OnDestroy { this.memberService.setManagedMember(params['id']) } }) - this.editForm = this.fb.group({ - name: [null, [Validators.required, Validators.maxLength(80)]], - phone: [null, [Validators.maxLength(40)]], - email: [null, [Validators.required, Validators.pattern(EMAIL_REGEXP), Validators.maxLength(80)]], - title: [null, [Validators.maxLength(128)]], - roles: this.fb.array( - this.rolesData.map((val: SFMemberContactRole) => - this.fb.group({ id: val.id, selected: val.selected, name: val.name }) - ), - [this.validateContactRoles] - ), - }) + combineLatest([this.activatedRoute.params, this.accountService.getAccountData()]) .pipe( switchMap(([params, account]) => { @@ -122,15 +132,6 @@ export class ContactUpdateComponent implements OnInit, OnDestroy { }) } - validateContactRoles: ValidatorFn = (control: AbstractControl): ValidationErrors | null => { - const rolesArray = control as FormArray - const selectedRoles = rolesArray.controls.filter((control) => control.value.selected) - if (selectedRoles.length < 1) { - return { oneRoleSelected: true } - } - return null - } - updateForm(contact: ISFMemberContact) { this.editForm!.patchValue({ name: contact.name, @@ -173,6 +174,8 @@ export class ContactUpdateComponent implements OnInit, OnDestroy { }) this.editForm!.markAllAsTouched() } else { + console.log('form valid') + this.invalidForm = false this.isSaving = true const contact = this.createContactFromForm()