Skip to content

Commit 01b423a

Browse files
committed
Consolidate extension storage under amg-state
1 parent 117aa80 commit 01b423a

10 files changed

Lines changed: 660 additions & 68 deletions

File tree

e2e/pages/web.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import path from "path";
44
declare const chrome: {
55
storage: {
66
local: {
7-
set: (items: Record<string, boolean>) => void | Promise<void>;
7+
get: (keys: string[]) => Promise<Record<string, unknown>>;
8+
set: (items: Record<string, unknown>) => void | Promise<void>;
89
};
910
};
1011
};
@@ -27,7 +28,42 @@ export async function enableDomainInStorage(context: BrowserContext, domain: str
2728
worker = await context.waitForEvent("serviceworker");
2829
}
2930
const setStorage = (d: string) => {
30-
return chrome.storage.local.set({ [d]: true });
31+
const toBooleanRecord = (value: unknown): Record<string, boolean> => {
32+
if (typeof value !== "object" || value === null) return {};
33+
const result: Record<string, boolean> = {};
34+
for (const [key, fieldValue] of Object.entries(value)) {
35+
if (typeof fieldValue === "boolean") {
36+
result[key] = fieldValue;
37+
}
38+
}
39+
return result;
40+
};
41+
const toUnknownRecord = (value: unknown): Record<string, unknown> => {
42+
if (typeof value !== "object" || value === null) return {};
43+
const result: Record<string, unknown> = {};
44+
for (const [key, fieldValue] of Object.entries(value)) {
45+
result[key] = fieldValue;
46+
}
47+
return result;
48+
};
49+
return chrome.storage.local.get(["amg-state"]).then((result) => {
50+
const currentState = result["amg-state"];
51+
const stateRecord = toUnknownRecord(currentState);
52+
const baseState = {
53+
analytics: toUnknownRecord(stateRecord.analytics),
54+
domains: toBooleanRecord(stateRecord.domains),
55+
votes: toBooleanRecord(stateRecord.votes),
56+
};
57+
return chrome.storage.local.set({
58+
"amg-state": {
59+
...baseState,
60+
domains: {
61+
...baseState.domains,
62+
[d]: true,
63+
},
64+
},
65+
});
66+
});
3167
};
3268
await worker.evaluate(setStorage, domain);
3369
}

e2e/tests/popup.spec.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
import pkg from "../../package.json" assert { type: "json" };
22
import { expect, test } from "../fixtures";
33

4+
function toUnknownRecord(value: unknown): Record<string, unknown> {
5+
if (typeof value !== "object" || value === null) return {};
6+
const result: Record<string, unknown> = {};
7+
for (const [key, fieldValue] of Object.entries(value)) {
8+
result[key] = fieldValue;
9+
}
10+
return result;
11+
}
12+
13+
function toBooleanRecord(value: unknown): Record<string, boolean> {
14+
const unknownRecord = toUnknownRecord(value);
15+
const result: Record<string, boolean> = {};
16+
for (const [key, fieldValue] of Object.entries(unknownRecord)) {
17+
if (typeof fieldValue === "boolean") {
18+
result[key] = fieldValue;
19+
}
20+
}
21+
return result;
22+
}
23+
424
test.describe("Popup", () => {
525
test("popup shows correct UI and updates storage when toggled", async ({
626
page,
@@ -31,11 +51,26 @@ test.describe("Popup", () => {
3151
const storageAfter = await page.evaluate(async () => {
3252
return browser.storage.local.get(null);
3353
});
34-
const changedKeys = Object.keys(storageAfter).filter(
35-
(key) => storageAfter[key] !== storageBefore[key],
36-
);
54+
expect(Object.hasOwn(storageBefore, "amg-state")).toBeTruthy();
55+
expect(Object.hasOwn(storageAfter, "amg-state")).toBeTruthy();
56+
57+
const domain = await page.evaluate(async () => {
58+
const [tab] = await browser.tabs.query({
59+
active: true,
60+
currentWindow: true,
61+
});
62+
if (!tab?.url) return "";
63+
return new URL(tab.url).host;
64+
});
65+
66+
const beforeAmgState = toUnknownRecord(storageBefore["amg-state"]);
67+
const afterAmgState = toUnknownRecord(storageAfter["amg-state"]);
68+
const beforeDomains = toBooleanRecord(beforeAmgState.domains);
69+
const afterDomains = toBooleanRecord(afterAmgState.domains);
70+
const beforeDomainValue = beforeDomains[domain];
71+
const afterDomainValue = afterDomains[domain];
3772

38-
expect(changedKeys.length).toBeGreaterThan(0);
39-
expect(changedKeys.some((key) => storageAfter[key] === true)).toBeTruthy();
73+
expect(beforeDomainValue === undefined || beforeDomainValue === false).toBeTruthy();
74+
expect(afterDomainValue).toBeTruthy();
4075
});
4176
});

playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export default defineConfig({
6161
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
6262
// },
6363
],
64-
timeout: process.env.CI ? 30_000 : 5_000,
64+
timeout: process.env.CI ? 30_000 : 10_000,
6565
webServer: {
6666
command: "node e2e/serve-fixtures.mjs 51234",
6767
url: "http://localhost:51234/inspector-playground.html",

src/app.config.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// <srcDir>/app.config.ts
22
import { googleAnalytics4 } from "@wxt-dev/analytics/providers/google-analytics-4";
3+
import {
4+
createAnalyticsEnabledStorageItem,
5+
createAnalyticsUserIdStorageItem,
6+
createAnalyticsUserPropertiesStorageItem,
7+
} from "@/lib/storage/amgState";
38

49
import pkg from "../package.json";
510

@@ -12,15 +17,9 @@ export default defineAppConfig({
1217
measurementId: "G-XWT0HYT2KT",
1318
}),
1419
],
15-
enabled: storage.defineItem("local:analytics-enabled", {
16-
fallback: true,
17-
}),
18-
userId: storage.defineItem<string | undefined>("local:amg-user-id-key", {
19-
fallback: crypto.randomUUID().toString(),
20-
}),
21-
userProperties: storage.defineItem("local:amg-user-properties-key", {
22-
fallback: {},
23-
}),
20+
enabled: createAnalyticsEnabledStorageItem(),
21+
userId: createAnalyticsUserIdStorageItem(),
22+
userProperties: createAnalyticsUserPropertiesStorageItem(),
2423
},
2524
version: pkg.version.toString(),
2625
});

src/entrypoints/background.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
import {
2+
getDomainActive,
3+
migrateLegacyState,
4+
setDomainActive,
5+
setPlatformInfoState,
6+
} from "@/lib/storage/amgState";
7+
18
const IconOff = {
29
16: "icons/icon-off-16.png",
310
32: "icons/icon-off-32.png",
@@ -19,23 +26,23 @@ export default defineBackground(() => {
1926
captureHandler(sender.tab);
2027
} else if (event.type === "EXTENSION_TOGGLE") {
2128
const { domain, isActive } = event.payload;
22-
browser.storage?.local.set({
23-
[domain]: isActive,
24-
});
29+
await setDomainActive(domain, isActive);
2530
setIcon(isActive);
2631
}
2732
});
2833

2934
browser.runtime.onInstalled.addListener(async ({ reason }) => {
3035
console.log(`Extension installed, reason: ${reason}, browser: ${import.meta.env.BROWSER}`);
3136

32-
savePlatformInfo();
37+
await migrateLegacyState();
38+
await savePlatformInfo();
3339
analytics.setEnabled(true);
3440
void updateIconForActiveTab();
3541
});
3642

3743
browser.runtime.onStartup.addListener(async () => {
3844
console.log("Extension started");
45+
await migrateLegacyState();
3946
void updateIconForActiveTab();
4047
});
4148

@@ -62,7 +69,7 @@ export default defineBackground(() => {
6269

6370
async function savePlatformInfo() {
6471
const platformInfo = await browser.runtime.getPlatformInfo();
65-
void browser.storage.local.set({ platformInfo: platformInfo });
72+
await setPlatformInfoState(platformInfo);
6673
}
6774

6875
/**
@@ -95,8 +102,7 @@ async function getCurrentDomain(tabId?: number): Promise<string | null> {
95102
*/
96103
async function isDomainActive(domain: string): Promise<boolean> {
97104
try {
98-
const result = await browser.storage.local.get([domain]);
99-
return Boolean(result[domain]);
105+
return await getDomainActive(domain);
100106
} catch (error) {
101107
console.error("Failed to check domain state:", error);
102108
return true;

src/lib/modules/ExtenstionSettings/App.svelte

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
createMessageHandler,
77
sendMessage,
88
} from "@/lib/core/MessageBus";
9+
import { getDomainActive } from "@/lib/storage/amgState";
910
import { Switch } from "@ark-ui/svelte/switch";
1011
import { browser } from "wxt/browser";
1112
import "./app.css";
@@ -42,11 +43,7 @@
4243
const url = new URL(tab.url);
4344
domain = url.host;
4445
45-
const result = await browser.storage?.local.get([domain]);
46-
const value = result?.[domain];
47-
if (result !== undefined) {
48-
isActive = typeof value === "boolean" ? value : false;
49-
}
46+
isActive = await getDomainActive(domain);
5047
}
5148
5249
if (isActive === undefined) {

0 commit comments

Comments
 (0)