mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-13 20:56:19 -08:00
refactor(stalker): gate portal sqlite sync by runtime capability
This commit is contained in:
1 parent
790dbb7062
commit
465b1b5559
2 files changed
+142
-7
No files matched your search
+131
@@ -0,0 +1,131 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { signalStore } from '@ngrx/signals';
|
||||
import { DataService, RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import { PlaylistMeta, STALKER_REQUEST } from '@iptvnator/shared/interfaces';
|
||||
import { StalkerSessionService } from '../../stalker-session.service';
|
||||
import { withStalkerPortal } from './with-stalker-portal.feature';
|
||||
|
||||
jest.mock('@iptvnator/portal/shared/util', () => ({
|
||||
createLogger: () => ({
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
info: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
const TestPortalStore = signalStore(withStalkerPortal());
|
||||
|
||||
const PLAYLIST = {
|
||||
_id: 'stalker-1',
|
||||
title: 'Demo Stalker',
|
||||
count: 0,
|
||||
autoRefresh: false,
|
||||
importDate: '2026-05-22T00:00:00.000Z',
|
||||
portalUrl: 'http://demo.example/stalker_portal/server/load.php',
|
||||
macAddress: '00:1A:79:00:00:01',
|
||||
isFullStalkerPortal: false,
|
||||
} as PlaylistMeta;
|
||||
|
||||
describe('withStalkerPortal', () => {
|
||||
let store: InstanceType<typeof TestPortalStore>;
|
||||
let dbCreatePlaylist: jest.Mock;
|
||||
let dbGetPlaylist: jest.Mock;
|
||||
let runtime: {
|
||||
hasElectronMethod: jest.Mock<boolean, [string]>;
|
||||
};
|
||||
let stalkerSession: {
|
||||
ensureToken: jest.Mock;
|
||||
setActiveWatchdogPlaylist: jest.Mock;
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
dbCreatePlaylist = jest.fn().mockResolvedValue(undefined);
|
||||
dbGetPlaylist = jest.fn().mockResolvedValue(null);
|
||||
Object.defineProperty(window, 'electron', {
|
||||
value: {
|
||||
dbCreatePlaylist,
|
||||
dbGetPlaylist,
|
||||
} as Window['electron'],
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
runtime = {
|
||||
hasElectronMethod: jest.fn(() => true),
|
||||
};
|
||||
stalkerSession = {
|
||||
ensureToken: jest.fn(),
|
||||
setActiveWatchdogPlaylist: jest.fn(),
|
||||
};
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
TestPortalStore,
|
||||
{
|
||||
provide: DataService,
|
||||
useValue: {
|
||||
sendIpcEvent: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: RuntimeCapabilitiesService,
|
||||
useValue: runtime,
|
||||
},
|
||||
{
|
||||
provide: StalkerSessionService,
|
||||
useValue: stalkerSession,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
store = TestBed.inject(TestPortalStore);
|
||||
});
|
||||
|
||||
it('creates the SQLite playlist row when the runtime exposes the required bridge methods', async () => {
|
||||
await store.setCurrentPlaylist(PLAYLIST);
|
||||
|
||||
expect(dbGetPlaylist).toHaveBeenCalledWith('stalker-1');
|
||||
expect(dbCreatePlaylist).toHaveBeenCalledWith({
|
||||
id: 'stalker-1',
|
||||
name: 'Demo Stalker',
|
||||
macAddress: '00:1A:79:00:00:01',
|
||||
url: 'http://demo.example/stalker_portal/server/load.php',
|
||||
type: 'stalker',
|
||||
});
|
||||
expect(stalkerSession.setActiveWatchdogPlaylist).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
macAddress: '00:1A:79:00:00:01',
|
||||
portalUrl: 'http://demo.example/stalker_portal/server/load.php',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('does not touch SQLite when the Electron bridge is partial', async () => {
|
||||
runtime.hasElectronMethod.mockImplementation(
|
||||
(methodName) => methodName === 'dbGetPlaylist'
|
||||
);
|
||||
|
||||
await store.setCurrentPlaylist(PLAYLIST);
|
||||
|
||||
expect(dbGetPlaylist).not.toHaveBeenCalled();
|
||||
expect(dbCreatePlaylist).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sends Stalker requests through DataService without requiring the SQLite bridge', async () => {
|
||||
const dataService = TestBed.inject(DataService) as unknown as {
|
||||
sendIpcEvent: jest.Mock;
|
||||
};
|
||||
dataService.sendIpcEvent.mockResolvedValue({ js: { data: [] } });
|
||||
|
||||
await store.makeStalkerRequest(PLAYLIST, { action: 'get_profile' });
|
||||
|
||||
expect(dataService.sendIpcEvent).toHaveBeenCalledWith(
|
||||
STALKER_REQUEST,
|
||||
expect.objectContaining({
|
||||
macAddress: '00:1A:79:00:00:01',
|
||||
params: { action: 'get_profile' },
|
||||
url: 'http://demo.example/stalker_portal/server/load.php',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
+11
-7
@@ -8,20 +8,20 @@ import {
|
||||
} from '@ngrx/signals';
|
||||
import { PlaylistMeta, STALKER_REQUEST } from '@iptvnator/shared/interfaces';
|
||||
import { createLogger } from '@iptvnator/portal/shared/util';
|
||||
import { DataService } from '@iptvnator/services';
|
||||
import { DataService, RuntimeCapabilitiesService } from '@iptvnator/services';
|
||||
import { StalkerSessionService } from '../../stalker-session.service';
|
||||
import { toStalkerSessionPlaylist } from '../utils';
|
||||
|
||||
type StalkerPortalWindow = Window & {
|
||||
electron?: {
|
||||
dbCreatePlaylist: (playlist: {
|
||||
dbCreatePlaylist?: (playlist: {
|
||||
id: string;
|
||||
name: string;
|
||||
macAddress: string;
|
||||
url: string;
|
||||
type: 'stalker';
|
||||
}) => Promise<unknown>;
|
||||
dbGetPlaylist: (playlistId: string) => Promise<unknown>;
|
||||
dbGetPlaylist?: (playlistId: string) => Promise<unknown>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -81,8 +81,8 @@ export function withStalkerPortal() {
|
||||
withMethods(
|
||||
(
|
||||
store,
|
||||
dataService = inject(DataService),
|
||||
stalkerSession = inject(StalkerSessionService)
|
||||
stalkerSession = inject(StalkerSessionService),
|
||||
runtime = inject(RuntimeCapabilitiesService)
|
||||
) => ({
|
||||
async setCurrentPlaylist(playlist: PlaylistMeta | undefined) {
|
||||
stalkerSession.setActiveWatchdogPlaylist(
|
||||
@@ -96,7 +96,8 @@ export function withStalkerPortal() {
|
||||
// Only sync if this is actually a Stalker playlist (has macAddress and portalUrl)
|
||||
if (
|
||||
playlist &&
|
||||
dataService.isElectron &&
|
||||
runtime.hasElectronMethod('dbGetPlaylist') &&
|
||||
runtime.hasElectronMethod('dbCreatePlaylist') &&
|
||||
playlist._id &&
|
||||
playlist.macAddress &&
|
||||
playlist.portalUrl
|
||||
@@ -104,7 +105,10 @@ export function withStalkerPortal() {
|
||||
try {
|
||||
const electronApi = (window as StalkerPortalWindow)
|
||||
.electron;
|
||||
if (!electronApi) {
|
||||
if (
|
||||
!electronApi?.dbGetPlaylist ||
|
||||
!electronApi.dbCreatePlaylist
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user