fix: harden favorites storage recovery
This commit is contained in:
@@ -154,7 +154,7 @@ describe("favorites-store", () => {
|
||||
test("recovers from malformed, duplicate, and dangling stored values", async () => {
|
||||
const { repository } = createRepository(
|
||||
createMemoryStorage({
|
||||
version: 42,
|
||||
version: 1,
|
||||
folders: [
|
||||
{
|
||||
id: "folder-1",
|
||||
@@ -214,6 +214,44 @@ describe("favorites-store", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("treats a future stored version as an empty V1 state", async () => {
|
||||
const { repository } = createRepository(
|
||||
createMemoryStorage({
|
||||
version: 2,
|
||||
folders: [
|
||||
{
|
||||
id: "future-folder",
|
||||
name: "未来收藏夹",
|
||||
createdAt: "future",
|
||||
updatedAt: "future"
|
||||
}
|
||||
],
|
||||
creators: [
|
||||
{
|
||||
authorId: "future-author",
|
||||
authorName: "Future",
|
||||
savedAt: "future"
|
||||
}
|
||||
],
|
||||
memberships: [
|
||||
{
|
||||
folderId: "future-folder",
|
||||
authorId: "future-author",
|
||||
addedAt: "future"
|
||||
}
|
||||
],
|
||||
futureOnlyField: "do not retain"
|
||||
})
|
||||
);
|
||||
|
||||
await expect(repository.read()).resolves.toEqual({
|
||||
creators: [],
|
||||
folders: [],
|
||||
memberships: [],
|
||||
version: 1
|
||||
});
|
||||
});
|
||||
|
||||
test("serializes concurrent mutations so neither folder is overwritten", async () => {
|
||||
const { repository } = createRepository();
|
||||
|
||||
@@ -230,18 +268,40 @@ describe("favorites-store", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("propagates rejected storage writes", async () => {
|
||||
test("recovers the mutation queue after one rejected storage write", async () => {
|
||||
let writeAttempts = 0;
|
||||
let storedState: FavoritesStateV1 | undefined;
|
||||
const storage: FavoritesStorage = {
|
||||
async get() {
|
||||
return undefined;
|
||||
return storedState;
|
||||
},
|
||||
async set() {
|
||||
throw new Error("write failed");
|
||||
async set(value) {
|
||||
writeAttempts += 1;
|
||||
if (writeAttempts === 1) {
|
||||
throw new Error("write failed");
|
||||
}
|
||||
storedState = value;
|
||||
}
|
||||
};
|
||||
const { repository } = createRepository(storage);
|
||||
|
||||
await expect(repository.createFolder("合作")).rejects.toThrow("write failed");
|
||||
await expect(repository.createFolder("待联系")).resolves.toMatchObject({
|
||||
name: "待联系"
|
||||
});
|
||||
await expect(repository.read()).resolves.toEqual({
|
||||
creators: [],
|
||||
folders: [
|
||||
{
|
||||
id: "folder-2",
|
||||
name: "待联系",
|
||||
createdAt: "2026-07-17T00:00:00.000Z",
|
||||
updatedAt: "2026-07-17T00:00:00.000Z"
|
||||
}
|
||||
],
|
||||
memberships: [],
|
||||
version: 1
|
||||
});
|
||||
});
|
||||
|
||||
test("uses the exact Chrome storage key and reports unavailable storage", async () => {
|
||||
|
||||
Reference in New Issue
Block a user