// tests/permissions.test.js // 测试 permissions.js:可选主机权限的授权状态判断与申请逻辑 // 运行:node --test tests/permissions.test.js const { describe, it, beforeEach } = require("node:test"); const assert = require("node:assert/strict"); const { toMatchPatterns } = require("../dist/utils.js"); /** 构造一个假的 chrome.permissions,granted 集合可观察 */ function createFakePermissions(granted = []) { const state = { granted: new Set(granted), requestCalls: [], containsCalls: 0, throwOnContains: false, }; return { state, api: { contains: async ({ origins }) => { state.containsCalls++; if (state.throwOnContains) throw new Error("boom"); return origins.every((o) => state.granted.has(o)); }, request: async ({ origins }) => { state.requestCalls.push(origins); origins.forEach((o) => state.granted.add(o)); return true; }, }, }; } function loadPerms(permissionsApi) { global.toMatchPatterns = toMatchPatterns; // permissions.js 会延迟读取该全局函数 global.chrome = permissionsApi === null ? {} : { permissions: permissionsApi }; delete require.cache[require.resolve("../dist/permissions.js")]; return require("../dist/permissions.js"); } describe("permissions - patternsForDomain", () => { beforeEach(() => { global.toMatchPatterns = toMatchPatterns; }); it("返回 http / https 两条模式", () => { const P = loadPerms(createFakePermissions().api); assert.deepEqual(P.patternsForDomain("example.com"), ["http://example.com/*", "https://example.com/*"]); }); it("通配符域名同样可转成可申请的 origin", () => { const P = loadPerms(createFakePermissions().api); assert.deepEqual(P.patternsForDomain("*.example.com"), [ "http://*.example.com/*", "https://*.example.com/*", ]); }); it("无法表达的规则返回空数组", () => { const P = loadPerms(createFakePermissions().api); assert.deepEqual(P.patternsForDomain("*"), []); assert.deepEqual(P.patternsForDomain(""), []); }); }); describe("permissions - partitionPatterns", () => { it("按已授权拆分成 granted / missing", async () => { const fake = createFakePermissions(["https://a.com/*"]); const P = loadPerms(fake.api); const result = await P.partitionPatterns(["https://a.com/*", "http://b.com/*", "https://b.com/*"]); assert.deepEqual(result.granted, ["https://a.com/*"]); assert.deepEqual(result.missing, ["http://b.com/*", "https://b.com/*"]); }); it("contains 抛错时按未授权处理", async () => { const fake = createFakePermissions(["https://a.com/*"]); fake.state.throwOnContains = true; const P = loadPerms(fake.api); const result = await P.partitionPatterns(["https://a.com/*"]); assert.deepEqual(result.granted, []); assert.deepEqual(result.missing, ["https://a.com/*"]); }); }); describe("permissions - partitionDomains", () => { it("任一 scheme 已授权即算该域名已授权", async () => { const fake = createFakePermissions(["https://a.com/*"]); const P = loadPerms(fake.api); const result = await P.partitionDomains(["a.com", "b.com"]); assert.deepEqual(result.granted, ["a.com"]); assert.deepEqual(result.missing, ["b.com"]); }); it("完全未授权的域名进入 missing", async () => { const P = loadPerms(createFakePermissions().api); const result = await P.partitionDomains(["a.com"]); assert.deepEqual(result.missing, ["a.com"]); }); it("无法转成模式的域名视为未授权", async () => { const P = loadPerms(createFakePermissions().api); const result = await P.partitionDomains(["*"]); assert.deepEqual(result.missing, ["*"]); }); }); describe("permissions - requestForDomain", () => { it("已授权时直接返回 true 且不重复申请", async () => { const fake = createFakePermissions(["http://a.com/*", "https://a.com/*"]); const P = loadPerms(fake.api); assert.equal(await P.requestForDomain("a.com"), true); assert.equal(fake.state.requestCalls.length, 0, "已授权不应再次弹框"); }); it("未授权时申请全部模式", async () => { const fake = createFakePermissions(); const P = loadPerms(fake.api); assert.equal(await P.requestForDomain("a.com"), true); assert.deepEqual(fake.state.requestCalls, [["http://a.com/*", "https://a.com/*"]]); }); it("无法转换的域名不会发起申请", async () => { const fake = createFakePermissions(); const P = loadPerms(fake.api); assert.equal(await P.requestForDomain("*"), false); assert.equal(fake.state.requestCalls.length, 0); }); it("环境没有 chrome.permissions 时返回 false", async () => { const P = loadPerms(null); assert.equal(await P.requestForDomain("a.com"), false); }); it("申请被拒绝时返回 false(不抛错)", async () => { const fake = createFakePermissions(); fake.api.request = async () => false; const P = loadPerms(fake.api); assert.equal(await P.requestForDomain("a.com"), false); }); });