fix(replay): recover failed archives and release deleted sessions
This commit is contained in:
@@ -17,6 +17,7 @@ let ObservationSessionApiError;
|
||||
let ObservationSessionContractError;
|
||||
let decodeObservationRecordedMediaManifest;
|
||||
let createObservationReplayCoordinator;
|
||||
let deleteObservationSessionAfterTeardown;
|
||||
let resolveObservationSessionReplay;
|
||||
let waitForObservationReplayPreparation;
|
||||
let storeObservationReplayPreparation;
|
||||
@@ -45,6 +46,7 @@ before(async () => {
|
||||
} = await server.ssrLoadModule("/src/core/observation/sessionArchive.ts"));
|
||||
({
|
||||
createObservationReplayCoordinator,
|
||||
deleteObservationSessionAfterTeardown,
|
||||
resolveObservationSessionReplay,
|
||||
waitForObservationReplayPreparation,
|
||||
storeObservationReplayPreparation,
|
||||
@@ -437,6 +439,56 @@ test("delete API uses one opaque same-origin target and requires an empty 204",
|
||||
);
|
||||
});
|
||||
|
||||
test("session deletion releases the selected presentation before the DELETE request", async () => {
|
||||
const events = [];
|
||||
await deleteObservationSessionAfterTeardown("session-20260716T205632Z", {
|
||||
onDeleteBegin: async (sessionId) => {
|
||||
events.push(`release:${sessionId}`);
|
||||
},
|
||||
deleteSession: async (sessionId) => {
|
||||
events.push(`delete:${sessionId}`);
|
||||
},
|
||||
});
|
||||
assert.deepEqual(events, [
|
||||
"release:session-20260716T205632Z",
|
||||
"delete:session-20260716T205632Z",
|
||||
]);
|
||||
|
||||
let deleteCalled = false;
|
||||
await assert.rejects(
|
||||
deleteObservationSessionAfterTeardown("session-20260716T205632Z", {
|
||||
onDeleteBegin: async () => {
|
||||
throw new Error("viewer teardown failed");
|
||||
},
|
||||
deleteSession: async () => {
|
||||
deleteCalled = true;
|
||||
},
|
||||
}),
|
||||
/viewer teardown failed/,
|
||||
);
|
||||
assert.equal(deleteCalled, false);
|
||||
});
|
||||
|
||||
test("App atomically clears the selected Rerun source before deleting its session", async () => {
|
||||
const appSource = await readFile(new URL("../src/App.tsx", import.meta.url), "utf8");
|
||||
assert.match(
|
||||
appSource,
|
||||
/selectedRecordedSessionIdRef\.current = session\.id[\s\S]*setRecordedReplay\(launch\)/,
|
||||
);
|
||||
assert.match(
|
||||
appSource,
|
||||
/releaseRecordedReplayForDelete[\s\S]*selectedRecordedSessionIdRef\.current !== sessionId[\s\S]*selectedRecordedSessionIdRef\.current = null[\s\S]*setRecordedReplay\(null\)[\s\S]*setSourceUrl\(""\)/,
|
||||
);
|
||||
assert.match(
|
||||
appSource,
|
||||
/onDeleteBegin=\{releaseRecordedReplayForDelete\}/,
|
||||
);
|
||||
assert.match(
|
||||
appSource,
|
||||
/onDeleteBegin:\s*releaseRecordedReplayForDelete/,
|
||||
);
|
||||
});
|
||||
|
||||
test("replay API accepts only a same-origin seekable recording descriptor", async () => {
|
||||
const calls = [];
|
||||
const launch = await replayObservationSession("session-20260716T205632Z", {
|
||||
|
||||
Reference in New Issue
Block a user