refactor(epg): gate progress bridge by runtime capability

This commit is contained in:
4gray committed 2026-05-22 13:33:31 +03:00
1 parent 096a8bb803
commit f974297634
2 files changed
+92 -2

No files matched your search

@@ -0,0 +1,85 @@
import { TestBed } from '@angular/core/testing';
import { RuntimeCapabilitiesService } from '@iptvnator/services';
import {
EpgImportProgress,
EpgProgressService,
} from './epg-progress.service';
describe('EpgProgressService', () => {
let runtimeCapabilities: { supportsEpg: boolean };
const originalElectron = window.electron;
beforeEach(() => {
runtimeCapabilities = { supportsEpg: false };
});
afterEach(() => {
window.electron = originalElectron;
TestBed.resetTestingModule();
jest.restoreAllMocks();
});
function configureService(): EpgProgressService {
TestBed.configureTestingModule({
providers: [
EpgProgressService,
{
provide: RuntimeCapabilitiesService,
useValue: runtimeCapabilities,
},
],
});
return TestBed.inject(EpgProgressService);
}
it('does not subscribe to Electron progress events when runtime EPG support is disabled', () => {
const onEpgProgress = jest.fn();
window.electron = {
...window.electron,
onEpgProgress,
} as unknown as typeof window.electron;
configureService();
expect(onEpgProgress).not.toHaveBeenCalled();
});
it('does not force retry when runtime EPG support is disabled', () => {
const forceFetchEpg = jest.fn();
window.electron = {
...window.electron,
forceFetchEpg,
} as unknown as typeof window.electron;
const service = configureService();
service.retry('https://example.com/epg.xml');
expect(forceFetchEpg).not.toHaveBeenCalled();
});
it('updates imports from Electron progress events when runtime EPG support is enabled', () => {
let listener: ((progress: EpgImportProgress) => void) | undefined;
window.electron = {
...window.electron,
onEpgProgress: jest.fn((callback) => {
listener = callback;
}),
} as unknown as typeof window.electron;
runtimeCapabilities.supportsEpg = true;
const service = configureService();
listener?.({
url: 'https://example.com/epg.xml',
status: 'loading',
});
expect(window.electron?.onEpgProgress).toHaveBeenCalledTimes(1);
expect(service.imports()).toEqual([
{
url: 'https://example.com/epg.xml',
status: 'loading',
},
]);
});
});
@@ -1,4 +1,5 @@
import { Injectable, computed, signal } from '@angular/core';
import { Injectable, computed, inject, signal } from '@angular/core';
import { RuntimeCapabilitiesService } from '@iptvnator/services';
export interface EpgImportProgress {
url: string;
@@ -10,6 +11,7 @@ export interface EpgImportProgress {
@Injectable({ providedIn: 'root' })
export class EpgProgressService {
private readonly runtime = inject(RuntimeCapabilitiesService);
private readonly importsMap = signal<Map<string, EpgImportProgress>>(
new Map()
);
@@ -48,6 +50,9 @@ export class EpgProgressService {
// Clear the errored row so the backend's subsequent 'queued' event
// reappears cleanly rather than updating an existing error row.
this.removeImport(url);
if (!this.runtime.supportsEpg) {
return;
}
void window.electron?.forceFetchEpg?.(url);
}
@@ -57,7 +62,7 @@ export class EpgProgressService {
}
this.initialized = true;
if (window.electron?.onEpgProgress) {
if (this.runtime.supportsEpg && window.electron?.onEpgProgress) {
window.electron.onEpgProgress((data) => {
this.updateProgress(data);
});