diff --git a/projects/v3/src/app/components/assessment/assessment.component.ts b/projects/v3/src/app/components/assessment/assessment.component.ts index dcb2249c5..5feebb2c2 100644 --- a/projects/v3/src/app/components/assessment/assessment.component.ts +++ b/projects/v3/src/app/components/assessment/assessment.component.ts @@ -154,8 +154,8 @@ export class AssessmentComponent implements OnInit, OnChanges, OnDestroy { private sharedService: SharedService, private assessmentService: AssessmentService, private activityService: ActivityService, - private cdr: ChangeDetectorRef, private modalController: ModalController, + private cdr: ChangeDetectorRef, ) { this.resubscribe$.pipe( takeUntil(this.unsubscribe$), diff --git a/projects/v3/src/app/pages/home/home.page.html b/projects/v3/src/app/pages/home/home.page.html index 9ee76ea7c..03f531c32 100644 --- a/projects/v3/src/app/pages/home/home.page.html +++ b/projects/v3/src/app/pages/home/home.page.html @@ -44,7 +44,7 @@

-
+
{ let utilsService: jasmine.SpyObj; beforeEach(waitForAsync(() => { - const homeServiceSpy = jasmine.createSpyObj('HomeService', { - 'getExperience': undefined, - 'getMilestones': undefined, - 'getProjectProgress': undefined, - 'getPulseCheckStatuses': of({ data: { pulseCheckStatus: {} } }), - 'getPulseCheckSkills': of({ data: { pulseCheckSkills: [] } }), - }, { - 'experience$': of({ id: 1, name: 'Test Experience', cardUrl: 'test-card-url' }), - 'experienceProgress$': of(0), - 'activityCount$': of(0), - 'milestonesWithProgress$': of([]), - 'milestones$': of([]), - 'projectProgress$': of(0), + const homeServiceSpy = jasmine.createSpyObj('HomeService', [ + 'getExperience', + 'getMilestones', + 'getProjectProgress', + 'getPulseCheckStatuses', + 'getPulseCheckSkills', + ], { + 'experience$': of(), + 'experienceProgress$': of(), + 'activityCount$': of(), + 'milestonesWithProgress$': of(), + 'milestones$': of(), + 'projectProgress$': of(), }); const achievementServiceSpy = jasmine.createSpyObj('AchievementService', [ @@ -55,38 +52,19 @@ describe('HomePage', () => { 'achievements$': of(), }); - const sharedServiceSpy = jasmine.createSpyObj('SharedService', ['refreshJWT'], { - 'team$': of(null), - }); + const sharedServiceSpy = jasmine.createSpyObj('SharedService', ['refreshJWT']); const storageServiceSpy = jasmine.createSpyObj('BrowserStorageService', [ 'get', 'lastVisited', 'getUser', 'getFeature', ]); - // set up default return values for storage service - storageServiceSpy.getUser.and.returnValue({ - role: 'participant', - apikey: 'test-key', - projectId: 1, - teamId: 1, - }); - storageServiceSpy.get.and.callFake((key: string) => { - if (key === 'experience') { - return { id: 1, name: 'Test Experience', cardUrl: 'test-card-url' }; - } - return null; - }); - storageServiceSpy.getFeature.and.returnValue(false); - const fastFeedbackServiceSpy = jasmine.createSpyObj('FastFeedbackService', { - 'pullFastFeedback': of(null), - }); + const fastFeedbackServiceSpy = jasmine.createSpyObj('FastFeedbackService', ['pullFastFeedback']); const utilsServiceSpy = jasmine.createSpyObj('UtilsService', ['setPageTitle', 'isMobile']); TestBed.configureTestingModule({ declarations: [ HomePage ], - imports: [IonicModule.forRoot(), HttpClientTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [IonicModule.forRoot()], providers: [ { provide: ActivatedRoute, @@ -134,27 +112,7 @@ describe('HomePage', () => { 'unlockedTasks$': of([]) }) }, - { - provide: AlertController, - useValue: jasmine.createSpyObj('AlertController', ['create']) - }, - { - provide: PulsecheckService, - useValue: jasmine.createSpyObj('PulsecheckService', ['getPulsecheckStatuses']) - }, - { - provide: NotificationsService, - useValue: jasmine.createSpyObj('NotificationsService', [ - 'alert', - 'popUp', - 'getTodoItems', - ]) - }, - { - provide: ModalController, - useValue: jasmine.createSpyObj('ModalController', ['create', 'dismiss']) - }, - ], + ] }).compileComponents(); fixture = TestBed.createComponent(HomePage); @@ -205,12 +163,7 @@ describe('HomePage', () => { it('should get experience from storage', async () => { await component.updateDashboard(); expect(storageService.get).toHaveBeenCalledWith('experience'); - expect(component.experience).toEqual({ name: 'Test Experience', cardUrl: 'test-url' } as any); - }); - - it('should set project hub visibility from feature toggle', async () => { - await component.updateDashboard(); - expect(storageService.getFeature).toHaveBeenCalledWith('pulseCheckIndicator'); + expect(component.experience).toEqual({ name: 'Test Experience', cardUrl: 'test-url' }); }); it('should set project hub visibility from feature toggle', async () => { @@ -225,6 +178,20 @@ describe('HomePage', () => { expect(component.showProjectHub).toBe(false); }); + it('should treat mentor users as expert users', async () => { + storageService.getUser.and.returnValue({ + role: 'mentor', + apikey: 'test-key', + projectId: 1, + teamId: 1, + }); + + await component.updateDashboard(); + + expect(component.isExpert).toBe(true); + expect(component.isParticipant).toBe(false); + }); + it('should call service methods to fetch data', async () => { await component.updateDashboard(); expect(homeService.getMilestones).toHaveBeenCalled(); @@ -244,7 +211,7 @@ describe('HomePage', () => { component.pulseCheckIndicatorEnabled = true; await component.updateDashboard(); expect(homeService.getPulseCheckStatuses).toHaveBeenCalled(); - expect(component.pulseCheckStatus).toEqual({ red: 1, orange: 2, green: 3 } as any); + expect(component.pulseCheckStatus).toEqual({ red: 1, orange: 2, green: 3 }); }); it('should not get pulse check statuses when pulse check indicator is disabled', async () => { @@ -316,9 +283,7 @@ describe('HomePage', () => { data: { pulseCheckSkills: null } })); await component.updateDashboard(); - // component defaults to [] when pulseCheckSkills is null or empty (see line 243: || []) - // and only updates when newSkills.length > 0, so it stays as initial [] - expect(component.pulseCheckSkills).toEqual([]); + expect(component.pulseCheckSkills).toBeNull(); }); it('should handle empty pulse check skills response', async () => { @@ -333,6 +298,38 @@ describe('HomePage', () => { }); }); + describe('project brief actions', () => { + beforeEach(() => { + component.experience = { + id: 1, + name: 'Test Experience', + leadImage: 'test-image', + cardUrl: 'test-card-url' + } as any; + component.projectBrief = { + id: 1, + title: 'Project Brief' + } as any; + component.showProjectHub = true; + }); + + it('should hide project brief actions for expert users', () => { + component.isExpert = true; + + fixture.detectChanges(); + + expect(fixture.nativeElement.querySelector('.button-group-no-gap')).toBeNull(); + }); + + it('should show project brief actions for non-expert users', () => { + component.isExpert = false; + + fixture.detectChanges(); + + expect(fixture.nativeElement.querySelector('.button-group-no-gap')).not.toBeNull(); + }); + }); + describe('filterActivities', () => { const mockMilestones = [ { diff --git a/projects/v3/src/app/pages/home/home.page.ts b/projects/v3/src/app/pages/home/home.page.ts index 213cabd36..9bca9aa66 100644 --- a/projects/v3/src/app/pages/home/home.page.ts +++ b/projects/v3/src/app/pages/home/home.page.ts @@ -39,6 +39,7 @@ export class HomePage implements OnInit, OnDestroy, AfterViewChecked { isMobile: boolean; isParticipant: boolean; + isExpert: boolean; isExpertWithoutTeam: boolean; pulseCheckIndicatorEnabled: boolean; activityProgresses = {}; @@ -103,10 +104,7 @@ export class HomePage implements OnInit, OnDestroy, AfterViewChecked { } ngOnInit() { - const role = this.storageService.getUser().role; - const teamId = this.storageService.getUser().teamId; - this.isParticipant = role === 'participant'; - this.isExpertWithoutTeam = role === 'mentor' && !teamId; + this.updateUserRoleState(); this.pulseCheckIndicatorEnabled = this.storageService.getFeature('pulseCheckIndicator'); this.isMobile = this.utils.isMobile(); @@ -117,10 +115,8 @@ export class HomePage implements OnInit, OnDestroy, AfterViewChecked { takeUntil(this.unsubscribe$) ) .subscribe(() => { - // re-evaluate expert without team status when team changes - const currentRole = this.storageService.getUser().role; - const currentTeamId = this.storageService.getUser().teamId; - this.isExpertWithoutTeam = currentRole === 'mentor' && !currentTeamId; + // re-evaluate role state when team changes + this.updateUserRoleState(); }); this.homeService.milestones$ @@ -227,10 +223,7 @@ export class HomePage implements OnInit, OnDestroy, AfterViewChecked { await this.sharedService.refreshJWT(); // refresh JWT token [CORE-6083] // re-evaluate user role and team status after JWT refresh updates teamId - const role = this.storageService.getUser().role; - const teamId = this.storageService.getUser().teamId; - this.isParticipant = role === 'participant'; - this.isExpertWithoutTeam = role === 'mentor' && !teamId; + this.updateUserRoleState(); this.experience = this.storageService.get("experience"); this.showProjectHub = this.storageService.getFeature('showProjectHub'); @@ -291,6 +284,16 @@ export class HomePage implements OnInit, OnDestroy, AfterViewChecked { this.router.navigate(["experiences"]); } + private updateUserRoleState(): void { + const user = this.storageService.getUser() || {}; + const role = user.role; + const teamId = user.teamId; + + this.isParticipant = role === 'participant'; + this.isExpert = role === 'mentor'; + this.isExpertWithoutTeam = this.isExpert && !teamId; + } + switchContent(event) { // update points upon switching to badges tab if (event.detail.value === "badges") {