From bbd4d5fbafe7d6a102c181d6a1351211051cff2a Mon Sep 17 00:00:00 2001 From: CSantosM <4a.santos@gmail.com> Date: Wed, 21 Jan 2026 09:02:20 +0100 Subject: [PATCH] frontend: Remove unused DestroyRef injection in MeetingContextService --- .../meeting-custom-layout.component.spec.ts | 342 ------------------ .../services/meeting-context.service.ts | 4 +- 2 files changed, 1 insertion(+), 345 deletions(-) delete mode 100644 meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/customization/meeting-custom-layout/meeting-custom-layout.component.spec.ts diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/customization/meeting-custom-layout/meeting-custom-layout.component.spec.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/customization/meeting-custom-layout/meeting-custom-layout.component.spec.ts deleted file mode 100644 index 394f423a..00000000 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/customization/meeting-custom-layout/meeting-custom-layout.component.spec.ts +++ /dev/null @@ -1,342 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { Participant } from 'livekit-client'; -import { - LoggerService, - OpenViduService, - ParticipantModel, - ParticipantService -} from 'openvidu-components-angular'; -import { Subject } from 'rxjs'; -import { MeetLayoutMode } from '../../models/layout.model'; -import { MeetingLayoutService } from '../../services/meeting-layout.service'; -import { MeetingCustomLayoutComponent } from './meeting-custom-layout.component'; - -describe('MeetingLayoutComponent', () => { - let component: MeetingCustomLayoutComponent; - let fixture: ComponentFixture; - let mockLayoutService: jasmine.SpyObj; - let mockParticipantService: jasmine.SpyObj; - let mockOpenViduService: jasmine.SpyObj; - let mockLoggerService: jasmine.SpyObj; - let mockRoom: any; - - // Subjects for testing reactive behavior - let remoteParticipantsSubject: Subject; - let layoutModeSubject: Subject; - - beforeEach(async () => { - // Create subjects for observables - remoteParticipantsSubject = new Subject(); - layoutModeSubject = new Subject(); - - // Mock room with event emitter - mockRoom = { - on: jasmine.createSpy('on'), - off: jasmine.createSpy('off'), - emit: jasmine.createSpy('emit') - }; - - // Create service mocks - mockLayoutService = jasmine.createSpyObj('MeetLayoutService', ['isLastSpeakersLayoutEnabled'], { - layoutMode$: layoutModeSubject.asObservable() - }); - - mockParticipantService = jasmine.createSpyObj('ParticipantService', [], { - remoteParticipants$: remoteParticipantsSubject.asObservable() - }); - - mockOpenViduService = jasmine.createSpyObj('OpenViduService', ['getRoom']); - mockOpenViduService.getRoom.and.returnValue(mockRoom); - - mockLoggerService = jasmine.createSpyObj('LoggerService', ['get']); - mockLoggerService.get.and.returnValue({ - d: jasmine.createSpy('d'), - w: jasmine.createSpy('w'), - e: jasmine.createSpy('e') - }); - - await TestBed.configureTestingModule({ - imports: [MeetingCustomLayoutComponent], - providers: [ - { provide: MeetingLayoutService, useValue: mockLayoutService }, - { provide: ParticipantService, useValue: mockParticipantService }, - { provide: OpenViduService, useValue: mockOpenViduService }, - { provide: LoggerService, useValue: mockLoggerService } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(MeetingCustomLayoutComponent); - component = fixture.componentInstance; - }); - - describe('Initialization', () => { - it('should create', () => { - expect(component).toBeTruthy(); - }); - - it('should set up active speakers listener on creation', () => { - fixture.detectChanges(); - expect(mockRoom.on).toHaveBeenCalledWith('activeSpeakersChanged', jasmine.any(Function)); - }); - - it('should have default maxRemoteSpeakers of 4', () => { - expect(component.maxRemoteSpeakers()).toBe(4); - }); - - it('should accept custom maxRemoteSpeakers input', () => { - fixture.componentRef.setInput('maxRemoteSpeakers', 8); - expect(component.maxRemoteSpeakers()).toBe(8); - }); - }); - - describe('Default Layout Mode', () => { - beforeEach(() => { - fixture.detectChanges(); - layoutModeSubject.next(MeetLayoutMode.MOSAIC); - }); - - it('should show all remote participants in DEFAULT mode', () => { - const mockParticipants = createMockParticipants(6); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - expect(component.filteredRemoteParticipants()).toEqual(mockParticipants); - }); - - it('should update when remote participants change', () => { - const participants1 = createMockParticipants(3); - remoteParticipantsSubject.next(participants1); - fixture.detectChanges(); - - expect(component.filteredRemoteParticipants().length).toBe(3); - - const participants2 = createMockParticipants(5); - remoteParticipantsSubject.next(participants2); - fixture.detectChanges(); - - expect(component.filteredRemoteParticipants().length).toBe(5); - }); - }); - - describe('Last Speakers Layout Mode', () => { - beforeEach(() => { - fixture.detectChanges(); - layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC); - fixture.detectChanges(); - }); - - it('should initialize with first N participants when no active speakers', () => { - fixture.componentRef.setInput('maxRemoteSpeakers', 4); - const mockParticipants = createMockParticipants(10); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const filtered = component.filteredRemoteParticipants(); - expect(filtered.length).toBe(4); - expect(filtered).toEqual(mockParticipants.slice(0, 4)); - }); - - it('should update active speakers when activeSpeakersChanged event fires', () => { - const mockParticipants = createMockParticipants(10); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - // Get the registered callback - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Simulate active speakers event - const activeSpeakers = [ - createMockLiveKitParticipant('participant-5', false), - createMockLiveKitParticipant('participant-7', false), - createMockLiveKitParticipant('participant-3', false) - ]; - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - - const filtered = component.filteredRemoteParticipants(); - expect(filtered.map(p => p.identity)).toContain('participant-5'); - expect(filtered.map(p => p.identity)).toContain('participant-7'); - expect(filtered.map(p => p.identity)).toContain('participant-3'); - }); - - it('should respect maxRemoteSpeakers limit', () => { - fixture.componentRef.setInput('maxRemoteSpeakers', 3); - const mockParticipants = createMockParticipants(10); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Simulate more speakers than max - const activeSpeakers = createMockLiveKitParticipants(6, false); - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - - expect(component.filteredRemoteParticipants().length).toBeLessThanOrEqual(3); - }); - - it('should filter out local participant from active speakers', () => { - const mockParticipants = createMockParticipants(5); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Include local participant in active speakers - const activeSpeakers = [ - createMockLiveKitParticipant('local-participant', true), - createMockLiveKitParticipant('participant-1', false), - createMockLiveKitParticipant('participant-2', false) - ]; - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - - const filtered = component.filteredRemoteParticipants(); - expect(filtered.map(p => p.identity)).not.toContain('local-participant'); - }); - - it('should not update if speaker list is identical', () => { - const mockParticipants = createMockParticipants(5); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - const activeSpeakers = createMockLiveKitParticipants(3, false); - - // First update - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - const firstResult = component.filteredRemoteParticipants(); - - // Same speakers again - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - const secondResult = component.filteredRemoteParticipants(); - - // Should be the same instance (no update) - expect(firstResult).toEqual(secondResult); - }); - - it('should fill with additional participants if active speakers < max', () => { - fixture.componentRef.setInput('maxRemoteSpeakers', 5); - const mockParticipants = createMockParticipants(10); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Only 2 active speakers - const activeSpeakers = createMockLiveKitParticipants(2, false); - activeSpeakersCallback(activeSpeakers); - fixture.detectChanges(); - - // Should fill up to max with additional participants - expect(component.filteredRemoteParticipants().length).toBe(5); - }); - }); - - describe('Participant Cleanup', () => { - it('should remove disconnected participants from active speakers', () => { - fixture.detectChanges(); - layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC); - fixture.detectChanges(); - - const mockParticipants = createMockParticipants(5); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - activeSpeakersCallback(createMockLiveKitParticipants(3, false)); - fixture.detectChanges(); - - // Remove some participants - const remainingParticipants = mockParticipants.slice(2); - remoteParticipantsSubject.next(remainingParticipants); - fixture.detectChanges(); - - // Filtered list should only contain remaining participants - const filtered = component.filteredRemoteParticipants(); - expect(filtered.every(p => remainingParticipants.includes(p))).toBe(true); - }); - }); - - describe('Component Cleanup', () => { - it('should remove event listener on destroy', () => { - fixture.detectChanges(); - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - fixture.destroy(); - - expect(mockRoom.off).toHaveBeenCalledWith('activeSpeakersChanged', activeSpeakersCallback); - }); - }); - - describe('Performance Optimizations', () => { - it('should not process events in DEFAULT mode', () => { - fixture.detectChanges(); - layoutModeSubject.next(MeetLayoutMode.MOSAIC); - fixture.detectChanges(); - - const mockParticipants = createMockParticipants(5); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const initialFiltered = component.filteredRemoteParticipants(); - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Fire event (should be ignored in DEFAULT mode) - activeSpeakersCallback(createMockLiveKitParticipants(3, false)); - fixture.detectChanges(); - - // Should remain unchanged - expect(component.filteredRemoteParticipants()).toEqual(initialFiltered); - }); - - it('should not process empty speaker arrays', () => { - fixture.detectChanges(); - layoutModeSubject.next(MeetLayoutMode.SMART_MOSAIC); - fixture.detectChanges(); - - const mockParticipants = createMockParticipants(5); - remoteParticipantsSubject.next(mockParticipants); - fixture.detectChanges(); - - const initialFiltered = component.filteredRemoteParticipants(); - const activeSpeakersCallback = mockRoom.on.calls.argsFor(0)[1]; - - // Fire event with empty array - activeSpeakersCallback([]); - fixture.detectChanges(); - - // Should remain unchanged - expect(component.filteredRemoteParticipants()).toEqual(initialFiltered); - }); - }); - - // Helper functions - - function createMockParticipants(count: number): ParticipantModel[] { - return Array.from({ length: count }, (_, i) => { - return { - identity: `participant-${i}`, - name: `Participant ${i}`, - isLocal: false, - isSpeaking: false - } as unknown as ParticipantModel; - }); - } - - function createMockLiveKitParticipant(identity: string, isLocal: boolean): Participant { - return { - identity, - isLocal, - metadata: '' - } as Participant; - } - - function createMockLiveKitParticipants(count: number, isLocal: boolean): Participant[] { - return Array.from({ length: count }, (_, i) => - createMockLiveKitParticipant(`participant-${i}`, isLocal) - ); - } -}); diff --git a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts index e6fe225e..0cc8b851 100644 --- a/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts +++ b/meet-ce/frontend/projects/shared-meet-components/src/lib/domains/meeting/services/meeting-context.service.ts @@ -1,5 +1,4 @@ -import { computed, DestroyRef, effect, inject, Injectable, signal } from '@angular/core'; - +import { computed, effect, inject, Injectable, signal } from '@angular/core'; import { MeetRoom } from 'node_modules/@openvidu-meet/typings/dist/room'; import { ParticipantService, Room, ViewportService } from 'openvidu-components-angular'; import { FeatureConfigurationService } from '../../../shared/services/feature-configuration.service'; @@ -19,7 +18,6 @@ export class MeetingContextService { private readonly featureConfigService = inject(FeatureConfigurationService); private readonly viewportService = inject(ViewportService); private readonly sessionStorageService = inject(SessionStorageService); - private readonly destroyRef = inject(DestroyRef); private readonly _meetRoom = signal(undefined); private readonly _lkRoom = signal(undefined);