fix(xtream): retain favorites through storage and metadata updates

This commit is contained in:
4gray committed 2026-10-14 01:12:34 +02:00
1 parent 844aaa5329
commit fcbf57db3e
7 files changed
+284 -48

No files matched your search

@@ -9,6 +9,7 @@ import {
openSources,
openWorkspaceSection,
resetMockServers,
restartElectronApp,
sourceRowByTitle,
test,
waitForXtreamWorkspaceReady,
@@ -148,3 +149,111 @@ test('@critical @persistence @xtream @electron rejects a reused favorite identit
if (app) await closeElectronApp(app);
}
});
test('@persistence @xtream @electron retains a late-confirmed snapshot through catalog loss and unavailable legacy storage', async ({
dataDir,
request,
}) => {
await resetMockServers(request, ['xtream']);
const credentials = { username: 'minimal', password: 'minimal' };
const fixture = await fetchXtreamVodFixture(request, credentials);
const item = fixture.items[0];
const title = getXtreamTitle(item);
const oldTitle = 'Snapshot before identity confirmation';
let app: LaunchedElectronApp | undefined;
try {
app = await launchElectronApp(dataDir);
await addXtreamPortal(app.mainWindow, {
...credentials,
name: 'Late confirmed favorite',
});
await waitForXtreamWorkspaceReady(app.mainWindow);
const playlistId = /\/xtreams\/([^/]+)/.exec(
new URL(app.mainWindow.url()).pathname
)?.[1];
if (!playlistId) throw new Error('Expected a playlist route');
await app.mainWindow
.getByRole('link', { name: 'Movies', exact: true })
.click();
await clickCategoryByNameExact(app.mainWindow, fixture.categoryName);
const returned = await app.mainWindow.evaluate(
async ({ playlistId, xtreamId, oldTitle }) => {
const row = await window.electron.dbGetContentByXtreamId(
xtreamId,
playlistId,
'movie'
);
if (!row) throw new Error('Expected imported content');
const identity = { tmdbId: 99999999, releaseYear: 2000 };
const restored = await window.electron.dbRestoreXtreamFavorites(
playlistId,
[
{
xtreamId,
contentType: 'movie',
snapshot: {
title: oldTitle,
posterUrl: 'https://art.invalid/old.jpg',
...identity,
},
},
]
);
if (!restored.success)
throw new Error('Could not seed favorite');
await window.electron.dbSetAppState(
`xtream-import-status:${playlistId}:movie`,
'completed'
);
const [unconfirmed] =
await window.electron.dbGetFavoritesForBackup(playlistId);
if (unconfirmed.title !== oldTitle)
throw new Error('Unconfirmed snapshot overwritten');
const enriched =
await window.electron.dbSetContentMetadataIfMissing(
row.id,
identity
);
if (!enriched.success)
throw new Error('Could not confirm identity');
// No second import completion is allowed to repair the snapshot.
await window.electron.dbDeleteXtreamContent(playlistId);
return {
poster: row.poster_url,
backdrop: row.backdrop_url ?? null,
};
},
{ playlistId, xtreamId: Number(item.stream_id), oldTitle }
);
const [saved] = await readSavedFavorites(app.mainWindow, playlistId);
expect(saved).toMatchObject({
id: null,
title,
poster_url: returned.poster,
backdrop_url: returned.backdrop,
});
await app.mainWindow.evaluate((playlistId) => {
const key = `xtream-restore-${playlistId}`;
localStorage.setItem(key, JSON.stringify({ favorites: [] }));
const getItem = Storage.prototype.getItem;
Storage.prototype.getItem = function (requestedKey) {
if (requestedKey === key)
throw new Error('Storage unavailable');
return getItem.call(this, requestedKey);
};
}, playlistId);
await openWorkspaceSection(app.mainWindow, 'Global favorites');
await expect(contentCardByTitle(app.mainWindow, title)).toBeVisible();
await expect(contentCardByTitle(app.mainWindow, oldTitle)).toHaveCount(
0
);
app = await restartElectronApp(app, dataDir);
await openWorkspaceSection(app.mainWindow, 'Global favorites');
await expect(contentCardByTitle(app.mainWindow, title)).toBeVisible();
expect(await readSavedFavorites(app.mainWindow, playlistId)).toEqual([
saved,
]);
} finally {
if (app) await closeElectronApp(app);
}
});