mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 05:36:17 -08:00
fix(portals): preserve Xtream restore retry state
This commit is contained in:
1 parent
b0598f8f70
commit
83fb06e79a
24 files changed
+913
-115
No files matched your search
@@ -4,6 +4,7 @@ import {
|
||||
selectAllPlaylistsMeta,
|
||||
selectIsEpgAvailable,
|
||||
} from '@iptvnator/m3u-state';
|
||||
import { XtreamStore } from '@iptvnator/portal/xtream/data-access';
|
||||
import { PlaylistBackupService } from '@iptvnator/services';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@@ -36,6 +37,9 @@ describe('SettingsBackupFacade', () => {
|
||||
.mockResolvedValue(BACKUP_EXPORT_RESULT),
|
||||
importBackup: jest.fn(),
|
||||
}),
|
||||
MockProvider(XtreamStore, {
|
||||
reconcilePendingRestoreBlock: jest.fn(),
|
||||
}),
|
||||
provideMockStore({
|
||||
selectors: [
|
||||
{ selector: selectAllPlaylistsMeta, value: [] },
|
||||
@@ -154,4 +158,46 @@ describe('SettingsBackupFacade', () => {
|
||||
expect.objectContaining({ panelClass: ['settings-snackbar'] })
|
||||
);
|
||||
});
|
||||
|
||||
it('reconciles a pending Xtream restore before completing an import', async () => {
|
||||
configure();
|
||||
const input = document.createElement('input');
|
||||
const file = {
|
||||
text: jest.fn().mockResolvedValue('{}'),
|
||||
} as unknown as File;
|
||||
Object.defineProperty(input, 'files', { value: [file] });
|
||||
const addEventListener = jest.spyOn(input, 'addEventListener');
|
||||
const createElement = jest
|
||||
.spyOn(document, 'createElement')
|
||||
.mockReturnValue(input);
|
||||
jest.spyOn(input, 'click').mockImplementation();
|
||||
const summary = {
|
||||
imported: 0,
|
||||
merged: 0,
|
||||
skipped: 0,
|
||||
failed: 1,
|
||||
errors: ['pending restore state could not be consumed'],
|
||||
};
|
||||
(playlistBackupService.importBackup as jest.Mock).mockResolvedValue(
|
||||
summary
|
||||
);
|
||||
const onImported = jest.fn();
|
||||
const xtreamStore = TestBed.inject(XtreamStore);
|
||||
|
||||
facade.importData(onImported);
|
||||
const changeListener = addEventListener.mock.calls.find(
|
||||
([type]) => type === 'change'
|
||||
)?.[1] as (event: Event) => Promise<void>;
|
||||
await changeListener({ target: input } as unknown as Event);
|
||||
|
||||
expect(xtreamStore.reconcilePendingRestoreBlock).toHaveBeenCalledTimes(
|
||||
1
|
||||
);
|
||||
expect(onImported).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
(xtreamStore.reconcilePendingRestoreBlock as jest.Mock).mock
|
||||
.invocationCallOrder[0]
|
||||
).toBeLessThan(onImported.mock.invocationCallOrder[0]);
|
||||
createElement.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,8 @@
|
||||
import { inject, Injectable, signal } from '@angular/core';
|
||||
import { inject, Injectable, Injector, signal } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { PlaylistActions } from '@iptvnator/m3u-state';
|
||||
import { XtreamStore } from '@iptvnator/portal/xtream/data-access';
|
||||
import {
|
||||
PlaylistBackupImportSummary,
|
||||
PlaylistBackupService,
|
||||
@@ -16,6 +17,7 @@ export class SettingsBackupFacade {
|
||||
private readonly settingsSnackbar = inject(SettingsSnackbarService);
|
||||
private readonly store = inject(Store);
|
||||
private readonly translate = inject(TranslateService);
|
||||
private readonly injector = inject(Injector);
|
||||
|
||||
readonly isExportingData = signal(false);
|
||||
|
||||
@@ -79,6 +81,9 @@ export class SettingsBackupFacade {
|
||||
const summary = await this.playlistBackupService.importBackup(
|
||||
await file.text()
|
||||
);
|
||||
this.injector
|
||||
.get(XtreamStore, null)
|
||||
?.reconcilePendingRestoreBlock();
|
||||
|
||||
if (summary.imported > 0 || summary.merged > 0) {
|
||||
this.store.dispatch(PlaylistActions.removeAllPlaylists());
|
||||
|
||||
Reference in new issue
Block a user