test
Some checks failed
test / Run tests (push) Failing after 6s
build / Build (push) Failing after 9s

This commit is contained in:
2025-03-19 18:05:54 +08:00
parent c2219db73e
commit fd2aba4286
31 changed files with 584 additions and 199 deletions

View File

@@ -9,7 +9,7 @@ export interface CacheStorage {
export class ExtCache implements CacheStorage {
get(key: string): Promise<any> {
return new Promise((resolve) => {
chrome.storage.local.get(key, (value) => {
chrome.storage.session.get(key, (value) => {
resolve(value[key]);
});
});
@@ -17,7 +17,7 @@ export class ExtCache implements CacheStorage {
set(key: string, value: any): Promise<void> {
return new Promise((resolve) => {
chrome.storage.local.set(
chrome.storage.session.set(
{
[key]: value,
},
@@ -30,7 +30,7 @@ export class ExtCache implements CacheStorage {
has(key: string): Promise<boolean> {
return new Promise((resolve) => {
chrome.storage.local.get(key, (value) => {
chrome.storage.session.get(key, (value) => {
resolve(value[key] !== undefined);
});
});
@@ -38,7 +38,7 @@ export class ExtCache implements CacheStorage {
del(key: string): Promise<void> {
return new Promise((resolve) => {
chrome.storage.local.remove(key, () => {
chrome.storage.session.remove(key, () => {
resolve();
});
});
@@ -46,7 +46,7 @@ export class ExtCache implements CacheStorage {
list(): Promise<string[]> {
return new Promise((resolve) => {
chrome.storage.local.get(null, (value) => {
chrome.storage.session.get(null, (value) => {
resolve(Object.keys(value));
});
});

View File

@@ -1,62 +0,0 @@
import "fake-indexeddb/auto";
import { DAO, db } from "./dao";
import { LoggerDAO } from "./logger";
import migrate from "../migrate";
migrate();
interface Test {
id: number;
data: string;
}
db.version(17).stores({ test: "++id,data" });
class testDAO extends DAO<Test> {
public tableName = "test";
constructor() {
super();
this.table = db.table(this.tableName);
}
}
describe("dao", () => {
const dao = new testDAO();
it("测试save", async () => {
expect(await dao.save({ id: 0, data: "ok1" })).toEqual(1);
expect(await dao.save({ id: 0, data: "ok" })).toEqual(2);
expect(await dao.save({ id: 2, data: "ok2" })).toEqual(2);
});
it("测试find", async () => {
expect(await dao.findOne({ id: 1 })).toEqual({ id: 1, data: "ok1" });
expect(await dao.findById(2)).toEqual({ id: 2, data: "ok2" });
});
it("测试list", async () => {
expect(await dao.list({ id: 1 })).toEqual([{ id: 1, data: "ok1" }]);
});
it("测试delete", async () => {
expect(await dao.delete({ id: 1 })).toEqual(1);
expect(await dao.findById(1)).toEqual(undefined);
});
});
describe("model", () => {
const logger = new LoggerDAO();
it("save", async () => {
expect(
await logger.save({
id: 0,
level: "info",
message: "ok",
label: {},
createtime: new Date().getTime(),
})
).toEqual(1);
});
});

View File

@@ -1,6 +1,6 @@
import { Group, MessageConnect } from "@Packages/message/server";
export class GMApi {
export default class GMApi {
constructor(private group: Group) {}
xmlHttpRequest(params: GMSend.XHRDetails, con: MessageConnect | null) {

View File

@@ -6,7 +6,7 @@ import { WindowMessage } from "@Packages/message/window_message";
import { ExtensionMessageSend } from "@Packages/message/extension_message";
import { ServiceWorkerClient } from "../service_worker/client";
import { sendMessage } from "@Packages/message/client";
import { GMApi } from "./gm_api";
import GMApi from "./gm_api";
// offscreen环境的管理器
export class OffscreenManager {

View File

@@ -1,10 +1,9 @@
import LoggerCore from "@App/app/logger/core";
import Logger from "@App/app/logger/logger";
import { Script, ScriptDAO } from "@App/app/repo/scripts";
import { Group, MessageConnect, MessageSender } from "@Packages/message/server";
import { Group, MessageConnect, MessageSend, MessageSender } from "@Packages/message/server";
import { ValueService } from "@App/app/service/service_worker/value";
import PermissionVerify from "./permission_verify";
import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
import { connect } from "@Packages/message/client";
import Cache, { incr } from "@App/app/cache";
import { unsafeHeaders } from "@App/runtime/utils";
@@ -35,7 +34,7 @@ export default class GMApi {
constructor(
private group: Group,
private sender: ServiceWorkerMessageSend,
private sender: MessageSend,
private value: ValueService
) {
this.logger = LoggerCore.logger().with({ service: "runtime/gm_api" });

View File

@@ -1,7 +1,6 @@
import { Server } from "@Packages/message/server";
import { MessageQueue } from "@Packages/message/message_queue";
import { ScriptService } from "./script";
import { ExtensionMessage } from "@Packages/message/extension_message";
import { ResourceService } from "./resource";
import { ValueService } from "./value";
import { RuntimeService } from "./runtime";
@@ -11,11 +10,11 @@ export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
// service worker的管理器
export default class ServiceWorkerManager {
private api: Server = new Server(new ExtensionMessage());
private mq: MessageQueue = new MessageQueue(this.api);
private sender: ServiceWorkerMessageSend = new ServiceWorkerMessageSend();
constructor(
private api: Server,
private mq: MessageQueue,
private sender: ServiceWorkerMessageSend
) {}
async initManager() {
this.api.on("preparationOffscreen", async () => {
@@ -32,79 +31,5 @@ export default class ServiceWorkerManager {
script.init();
const runtime = new RuntimeService(this.api.group("runtime"), this.sender, this.mq, value);
runtime.init();
// 测试xhr
// setTimeout(() => {
// chrome.tabs.query(
// {
// url: chrome.runtime.getURL("src/offscreen.html"),
// },
// (result) => {
// console.log(result);
// }
// );
// }, 2000);
// group.on("testGmApi", () => {
// console.log(chrome.runtime.getURL("src/offscreen.html"));
// return new Promise((resolve) => {
// chrome.tabs.query({}, (tabs) => {
// const excludedTabIds: number[] = [];
// tabs.forEach((tab) => {
// if (tab.id) {
// excludedTabIds.push(tab.id);
// }
// });
// chrome.declarativeNetRequest.updateSessionRules(
// {
// removeRuleIds: [100],
// addRules: [
// {
// id: 100,
// priority: 1,
// action: {
// type: chrome.declarativeNetRequest.RuleActionType.MODIFY_HEADERS,
// requestHeaders: [
// {
// header: "cookie",
// operation: chrome.declarativeNetRequest.HeaderOperation.SET,
// value: "test=1234314",
// },
// {
// header: "origin",
// operation: chrome.declarativeNetRequest.HeaderOperation.SET,
// value: "https://learn.scriptcat.org",
// },
// {
// header: "user-agent",
// operation: chrome.declarativeNetRequest.HeaderOperation.SET,
// value: "test",
// },
// ],
// },
// condition: {
// resourceTypes: [chrome.declarativeNetRequest.ResourceType.XMLHTTPREQUEST],
// urlFilter: "^https://scriptcat.org/zh-CN$",
// excludedTabIds: excludedTabIds,
// },
// },
// ],
// },
// () => {
// resolve(1);
// }
// );
// });
// });
// });
// chrome.webRequest.onHeadersReceived.addListener(
// (details) => {
// console.log(details);
// },
// {
// urls: ["<all_urls>"],
// types: ["xmlhttprequest"],
// },
// ["responseHeaders", "extraHeaders"]
// );
}
}

View File

@@ -1,17 +1,16 @@
import { MessageQueue } from "@Packages/message/message_queue";
import { ScriptEnableCallbackValue } from "./client";
import { Group } from "@Packages/message/server";
import { Group, MessageSend } from "@Packages/message/server";
import { Script, SCRIPT_STATUS_ENABLE, SCRIPT_TYPE_NORMAL, ScriptAndCode, ScriptDAO } from "@App/app/repo/scripts";
import { ValueService } from "./value";
import GMApi from "./gm_api";
import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
export class RuntimeService {
scriptDAO: ScriptDAO = new ScriptDAO();
constructor(
private group: Group,
private sender: ServiceWorkerMessageSend,
private sender: MessageSend,
private mq: MessageQueue,
private value: ValueService
) {}

View File

@@ -1,37 +1,27 @@
import { formatTime, nextTime, ltever, checkSilenceUpdate } from "./utils";
import { describe, test, expect, it } from "vitest";
import { nextTime, ltever, checkSilenceUpdate } from "./utils";
import dayjs from "dayjs";
describe("nextTime", () => {
test("每分钟表达式", () => {
expect(nextTime("* * * * *")).toEqual(
dayjs(new Date()).add(1, "minute").format("YYYY-MM-DD HH:mm:00")
);
expect(nextTime("* * * * *")).toEqual(dayjs(new Date()).add(1, "minute").format("YYYY-MM-DD HH:mm:00"));
});
test("每分钟一次表达式", () => {
expect(nextTime("once * * * *")).toEqual(
dayjs(new Date())
.add(1, "minute")
.format("YYYY-MM-DD HH:mm 每分钟运行一次")
dayjs(new Date()).add(1, "minute").format("YYYY-MM-DD HH:mm 每分钟运行一次")
);
});
test("每小时一次表达式", () => {
expect(nextTime("* once * * *")).toEqual(
dayjs(new Date()).add(1, "hour").format("YYYY-MM-DD HH 每小时运行一次")
);
expect(nextTime("* once * * *")).toEqual(dayjs(new Date()).add(1, "hour").format("YYYY-MM-DD HH 每小时运行一次"));
});
test("每天一次表达式", () => {
expect(nextTime("* * once * *")).toEqual(
dayjs(new Date()).add(1, "day").format("YYYY-MM-DD 每天运行一次")
);
expect(nextTime("* * once * *")).toEqual(dayjs(new Date()).add(1, "day").format("YYYY-MM-DD 每天运行一次"));
});
test("每月一次表达式", () => {
expect(nextTime("* * * once *")).toEqual(
dayjs(new Date()).add(1, "month").format("YYYY-MM 每月运行一次")
);
expect(nextTime("* * * once *")).toEqual(dayjs(new Date()).add(1, "month").format("YYYY-MM 每月运行一次"));
});
test("每星期一次表达式", () => {
expect(nextTime("* * * * once")).toEqual(
dayjs(new Date()).add(1, "week").format("YYYY-MM-DD 每星期运行一次")
);
expect(nextTime("* * * * once")).toEqual(dayjs(new Date()).add(1, "week").format("YYYY-MM-DD 每星期运行一次"));
});
});

View File

@@ -1,3 +1,4 @@
import { Metadata } from "@App/app/repo/scripts";
import { CronTime } from "cron";
import dayjs from "dayjs";
import semver from "semver";
@@ -186,3 +187,27 @@ export function openInCurrentTab(url: string) {
export function isDebug() {
return process.env.NODE_ENV === "development";
}
// 检查订阅规则是否改变,是否能够静默更新
export function checkSilenceUpdate(oldMeta: Metadata, newMeta: Metadata): boolean {
// 判断connect是否改变
const oldConnect: { [key: string]: boolean } = {};
const newConnect: { [key: string]: boolean } = {};
oldMeta.connect &&
oldMeta.connect.forEach((val) => {
oldConnect[val] = true;
});
newMeta.connect &&
newMeta.connect.forEach((val) => {
newConnect[val] = true;
});
// 老的里面没有新的就需要用户确认了
const keys = Object.keys(newConnect);
for (let i = 0; i < keys.length; i += 1) {
const key = keys[i];
if (!oldConnect[key]) {
return false;
}
}
return true;
}

View File

@@ -1,8 +1,8 @@
import initTestEnv from "@App/pkg/utils/test_utils";
import { ScriptRunResouce } from "@App/app/repo/scripts";
import ExecScript from "./exec_script";
import { compileScript, compileScriptCode } from "./utils";
import { ExtVersion } from "@App/app/const";
import initTestEnv from "@Tests/utils";
initTestEnv();

View File

@@ -1,16 +1,16 @@
import { fakeBrowser } from "@webext-core/fake-browser";
import { it } from "node:test";
import initTestEnv from "@Tests/utils";
import { beforeEach, describe, expect } from "vitest";
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import { initTestEnv } from "@Tests/utils";
initTestEnv();
// serviceWorker环境
beforeAll(() => {});
describe("GM xhr", () => {
beforeEach(() => {
// See https://webext-core.aklinker1.io/fake-browser/reseting-state
fakeBrowser.reset();
});
it("1", async () => {
expect(1).toBe(2);
it("123123", async () => {
expect(1).toBe(1);
});
});

View File

@@ -3,6 +3,10 @@ import migrate from "./app/migrate";
import LoggerCore from "./app/logger/core";
import DBWriter from "./app/logger/db_writer";
import { LoggerDAO } from "./app/repo/logger";
import { ExtensionMessage } from "@Packages/message/extension_message";
import { Server } from "@Packages/message/server";
import { MessageQueue } from "@Packages/message/message_queue";
import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
const OFFSCREEN_DOCUMENT_PATH = "src/offscreen.html";
@@ -51,7 +55,8 @@ async function main() {
});
loggerCore.logger().debug("service worker start");
// 初始化管理器
const manager = new ServiceWorkerManager();
const server = new Server(new ExtensionMessage());
const manager = new ServiceWorkerManager(server, new MessageQueue(server), new ServiceWorkerMessageSend());
manager.initManager();
// 初始化沙盒环境
await setupOffscreenDocument();