added data chunking for storage

This commit is contained in:
Fedor Katurov 2024-10-11 18:58:17 +07:00
parent 6ede9f157e
commit e921803267
8 changed files with 821 additions and 145 deletions

View file

@ -0,0 +1,74 @@
import { it, expect, describe } from "vitest";
import {
splitTextInChunks,
joinTextFromChunks,
makeChunks,
} from "~/utils/chunks";
describe("chunks", () => {
describe("splitTextInChunks", () => {
const getKey = () => "a"; // key of length 1
it("splits text in chunks", () => {
expect(splitTextInChunks("0123456789", 4, getKey)).toEqual([
"012",
"345",
"678",
"9",
]);
expect(splitTextInChunks("", 4, getKey)).toEqual([]);
expect(splitTextInChunks("123", 4, getKey)).toEqual(["123"]);
});
});
describe("joinTextFromChunks", () => {
const getKey = (i: number) => (i === 0 ? `test` : `test_${i}`);
it("collects chunks", () => {
expect(
joinTextFromChunks(getKey, {
test: "abc",
test_1: "def",
test_2: "ghi",
})
).toBe("abcdefghi");
});
it("works with undefined keys", () => {
expect(
joinTextFromChunks(getKey, {
z: "abc",
z_1: "def",
z_2: "ghi",
})
).toBeUndefined();
});
it("works with empty strings keys", () => {
expect(
joinTextFromChunks(getKey, {
test: "",
test_1: "def",
test_2: "ghi",
})
).toBe("defghi");
});
});
describe("makeChunks", () => {
const getKey = (i: number) => `test_${i}`;
const chunkSize = 3;
it("makes chunks", () => {
expect(
makeChunks("abcdefghij", getKey, getKey(0).length + chunkSize)
).toEqual({
test_0: "abc",
test_1: "def",
test_2: "ghi",
test_3: "j",
});
});
});
});

View file

@ -0,0 +1,17 @@
import { Orientation, SerializedDockview } from "dockview";
export const emptyLayout: SerializedDockview = {
panels: {},
grid: {
root: {
type: "leaf",
data: {
views: [],
id: "",
},
},
height: 0,
width: 0,
orientation: Orientation.HORIZONTAL,
},
};

View file

@ -0,0 +1,109 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import {
makePanelChunkKey,
storePanelInSync,
storeLayoutInSync,
layoutKey,
settingsKey,
} from "~/utils/hydrate";
import { FakeStorage } from "../tests";
import { emptyLayout } from "~/utils/__tests__/hydrate.constants";
describe("hydrate", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
describe("storePanelInSync", () => {
it("deletes unused keys", async () => {
const storage = new FakeStorage({
[makePanelChunkKey("key")(0)]: "oldValue",
[makePanelChunkKey("key")(1)]: "anotherOldValue",
[makePanelChunkKey("key")(20)]: "anotherOldValue",
});
vi.stubGlobal("browser", { storage });
await storePanelInSync("key", "value");
expect(storage.sync.get.mock.calls.length).toBe(1);
expect(storage.sync.set.mock.calls).toEqual([
[
{
[makePanelChunkKey("key")(0)]: "value",
},
],
]);
expect(storage.sync.remove.mock.calls).toEqual([
[[makePanelChunkKey("key")(1), makePanelChunkKey("key")(20)]],
]);
});
it("splits text in chunks", async () => {
const storage = new FakeStorage({});
vi.stubGlobal("browser", { storage });
await storePanelInSync(
"key",
"abcdefgh",
makePanelChunkKey("key")(1).length + 3
);
expect(storage.sync.set.mock.calls).toEqual([
[
{
// first item doesn't have _0, so it's longer by 2 symbols
[makePanelChunkKey("key")(0)]: "abcde",
[makePanelChunkKey("key")(1)]: "fgh",
},
],
]);
});
});
describe("storeLayoutInSync", () => {
it("stores layout", async () => {
const storage = new FakeStorage({});
vi.stubGlobal("browser", { storage });
await storeLayoutInSync(emptyLayout);
expect(storage.sync.set.mock.calls).toEqual([
[{ [layoutKey]: emptyLayout }],
]);
});
it("deletes unused panels", async () => {
const goodKey = "good";
const badKey = "bad";
const layout = {
...emptyLayout,
panels: {
[goodKey]: {
id: goodKey,
},
},
};
const storage = new FakeStorage({
[makePanelChunkKey(goodKey)(0)]: "test",
[makePanelChunkKey(goodKey)(1)]: "test",
[makePanelChunkKey(badKey)(0)]: "test",
[makePanelChunkKey(badKey)(1)]: "test",
[layoutKey]: layout,
[settingsKey]: {},
});
vi.stubGlobal("browser", { storage });
await storeLayoutInSync(layout);
expect(storage.sync.remove.mock.calls).toStrictEqual([
[[makePanelChunkKey(badKey)(0), makePanelChunkKey(badKey)(1)]],
]);
});
});
});