150 lines
5.0 KiB
JavaScript
150 lines
5.0 KiB
JavaScript
// 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);
|
|||
|
|
});
|
|||
|
|
});
|