mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 20:16:15 -08:00
refactor(epg): gate multi epg queries by runtime capability
This commit is contained in:
1 parent
030c6ef89d
commit
54d29f2239
2 files changed
+105
-3
No files matched your search
@@ -1,4 +1,14 @@
|
||||
import { isSelectedEpgDayToday } from './multi-epg-container.component';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { OverlayRef } from '@angular/cdk/overlay';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import {
|
||||
MultiEpgContainerComponent,
|
||||
isSelectedEpgDayToday,
|
||||
} from './multi-epg-container.component';
|
||||
import { COMPONENT_OVERLAY_REF } from './overlay-ref.token';
|
||||
|
||||
describe('isSelectedEpgDayToday', () => {
|
||||
it('returns true only when the selected EPG day is the actual current day', () => {
|
||||
@@ -9,3 +19,87 @@ describe('isSelectedEpgDayToday', () => {
|
||||
expect(isSelectedEpgDayToday('20260522', now)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MultiEpgContainerComponent runtime gates', () => {
|
||||
let fixture: ComponentFixture<MultiEpgContainerComponent>;
|
||||
let component: MultiEpgContainerComponent;
|
||||
let runtimeCapabilities: { supportsEpg: boolean };
|
||||
const originalElectron = window.electron;
|
||||
|
||||
beforeEach(async () => {
|
||||
runtimeCapabilities = { supportsEpg: false };
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MultiEpgContainerComponent],
|
||||
providers: [
|
||||
{ provide: MatDialog, useValue: { open: jest.fn() } },
|
||||
{
|
||||
provide: COMPONENT_OVERLAY_REF,
|
||||
useValue: { detach: jest.fn() },
|
||||
},
|
||||
{
|
||||
provide: OverlayRef,
|
||||
useValue: { detach: jest.fn() },
|
||||
},
|
||||
{
|
||||
provide: RuntimeCapabilitiesService,
|
||||
useValue: runtimeCapabilities,
|
||||
},
|
||||
{
|
||||
provide: TranslateService,
|
||||
useValue: {
|
||||
currentLang: 'en',
|
||||
defaultLang: 'en',
|
||||
onLangChange: of(null),
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideComponent(MultiEpgContainerComponent, {
|
||||
set: { template: '' },
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MultiEpgContainerComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.electron = originalElectron;
|
||||
fixture.destroy();
|
||||
jest.restoreAllMocks();
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('does not request EPG channel ranges when runtime EPG support is disabled', async () => {
|
||||
const getEpgChannelsByRange = jest.fn().mockResolvedValue([]);
|
||||
window.electron = {
|
||||
...window.electron,
|
||||
getEpgChannelsByRange,
|
||||
} as unknown as typeof window.electron;
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
|
||||
await component.requestPrograms();
|
||||
|
||||
expect(getEpgChannelsByRange).not.toHaveBeenCalled();
|
||||
expect(component.isLoading()).toBe(false);
|
||||
});
|
||||
|
||||
it('does not search EPG programs when runtime EPG support is disabled', () => {
|
||||
jest.useFakeTimers();
|
||||
const searchEpgPrograms = jest.fn().mockResolvedValue([]);
|
||||
window.electron = {
|
||||
...window.electron,
|
||||
searchEpgPrograms,
|
||||
} as unknown as typeof window.electron;
|
||||
|
||||
component.onProgramSearchInput({
|
||||
target: { value: 'news' },
|
||||
} as unknown as Event);
|
||||
jest.advanceTimersByTime(600);
|
||||
|
||||
expect(searchEpgPrograms).not.toHaveBeenCalled();
|
||||
expect(component.isSearchingPrograms()).toBe(false);
|
||||
expect(component.programSearchResults()).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
EpgChannelWithPrograms,
|
||||
EpgProgram,
|
||||
} from '@iptvnator/shared/interfaces';
|
||||
import { RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import { EpgItemDescriptionComponent } from '../epg-list/epg-item-description/epg-item-description.component';
|
||||
import { COMPONENT_OVERLAY_REF } from './overlay-ref.token';
|
||||
|
||||
@@ -181,6 +182,7 @@ export class MultiEpgContainerComponent
|
||||
|
||||
private readonly dialog = inject(MatDialog);
|
||||
private readonly overlayRef = inject<OverlayRef>(COMPONENT_OVERLAY_REF);
|
||||
private readonly runtime = inject(RuntimeCapabilitiesService);
|
||||
|
||||
ngOnInit() {
|
||||
// Update current time line every minute
|
||||
@@ -267,8 +269,8 @@ export class MultiEpgContainerComponent
|
||||
}
|
||||
|
||||
async requestPrograms(): Promise<void> {
|
||||
if (!window.electron) {
|
||||
console.warn('Multi-EPG not available: Electron not detected');
|
||||
if (!this.runtime.supportsEpg) {
|
||||
console.warn('Multi-EPG not available in this runtime');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -460,6 +462,12 @@ export class MultiEpgContainerComponent
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.runtime.supportsEpg) {
|
||||
this.programSearchResults.set([]);
|
||||
this.isSearchingPrograms.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce search by 500ms - show spinner only when search actually starts
|
||||
this.searchDebounceTimer = setTimeout(async () => {
|
||||
this.isSearchingPrograms.set(true);
|
||||
|
||||
Reference in new issue
Block a user