Files
Mango f2abe34dac 新建命令时按执行方式填上默认图标
MCP 建出来的命令 features.icon 是空的,命令卡片上就是个空位。现在 icon 留空时
按 program 填对应语言的默认图标(shell -> logo/shell.png、python ->
logo/python.png,编排用内置图标),显式传了 icon 就用传入的。
2026-10-13 01:38:05 +08:00

123 lines
4.7 KiB
JavaScript

/**
* commandStore 的自检脚本(不依赖 uTools,用假 db 跑一遍增删改查)
* 运行:node test/commandStore.test.js
*/
const assert = require("assert");
const db = new Map();
const features = new Map();
global.window = {
lodashM: { cloneDeep: (x) => JSON.parse(JSON.stringify(x)) },
dispatchEvent: () => true,
utools: {
db: {
get: (id) => (db.has(id) ? { _id: id, _rev: "1-x", data: db.get(id) } : undefined),
put: (doc) => (db.set(doc._id, doc.data), { ok: true }),
remove: (id) => (db.delete(id), { ok: true }),
allDocs: (prefix) =>
[...db.entries()]
.filter(([id]) => id.startsWith(prefix))
.map(([id, data]) => ({ _id: id, data })),
},
getFeatures: () => [...features.values()],
setFeature: (feature) => (features.set(feature.code, feature), true),
removeFeature: (code) => features.delete(code),
},
};
global.localStorage = { length: 0, key: () => null, removeItem: () => {} };
const store = require("../plugin/lib/commandStore.js");
const draft = {
program: "quickcommand",
cmd: "console.log(1)",
features: { explain: "测试命令", cmds: ["测试命令"] },
output: "text",
tags: ["测试"],
};
// 建
const created = store.create(draft);
assert.deepStrictEqual(created.errors, undefined);
const command = created.command;
const code = command.features.code;
assert.match(code, /^key_[0-9a-f]{8}$/);
assert.strictEqual(command.features.cmds[0], "测试命令");
assert.strictEqual(command.features.mainHide, false);
// 不带图标时用该执行方式的默认图标
assert.strictEqual(command.features.icon, "logo/quickcommand.png");
const pyCommand = store.create({
program: "python",
cmd: "print(1)",
features: { explain: "py", cmds: ["py"] },
}).command;
assert.strictEqual(pyCommand.features.icon, "logo/python.png");
const customCommand = store.create({
program: "custom",
cmd: "x",
features: { explain: "自定义", cmds: ["自定义"], icon: "data:image/png;base64,xxx" },
}).command;
assert.strictEqual(customCommand.features.icon, "data:image/png;base64,xxx");
store.remove(pyCommand.features.code);
store.remove(customCommand.features.code);
assert.ok(db.has("qc_" + code));
assert.ok(features.has(code));
// 参数不合法时不落库
const before = db.size;
assert.ok(store.create({ ...draft, program: "python3" }).errors.length);
assert.ok(store.create({ ...draft, features: { explain: "", cmds: [] } }).errors.length);
assert.strictEqual(db.size, before);
// 查
assert.strictEqual(store.list({}).total, 1);
assert.strictEqual(store.list({ tag: "测试" }).total, 1);
assert.strictEqual(store.list({ tag: "不存在" }).total, 0);
assert.strictEqual(store.list({ keyword: "测试" }).total, 1);
assert.strictEqual(store.list({ enabled: true }).total, 1);
assert.strictEqual(store.list({ enabled: false }).total, 0);
assert.deepStrictEqual(store.listTags(), [{ tag: "测试", count: 1 }]);
assert.strictEqual(store.get(code).cmd, "console.log(1)");
// 改
const updated = store.update(code, {
...command,
cmd: "console.log(2)",
features: { ...command.features, explain: "改名了" },
});
assert.strictEqual(updated.command.features.code, code);
assert.strictEqual(updated.command.features.explain, "改名了");
assert.strictEqual(db.get("qc_" + code).cmd, "console.log(2)");
// 字符串形式的触发方式是关键词,不派生 label;对象形式的匹配规则 label 跟随 explain
assert.strictEqual(db.get("qc_" + code).features.cmds[0], "测试命令");
const withRule = store.create({
...draft,
features: { explain: "正则命令", cmds: [{ type: "regex", match: "/^\\d+$/i" }] },
}).command;
assert.strictEqual(withRule.features.cmds[0].label, "正则命令");
assert.ok(store.update(code, { ...command, tags: "不是数组" }).errors.length);
assert.ok(store.update(code, { ...command, features: { ...command.features, icon: "x".repeat(40000) } }).errors.length);
// 启用/禁用
assert.deepStrictEqual(store.setEnabled([code], false), [{ code, enabled: false }]);
assert.ok(!features.has(code));
assert.strictEqual(store.list({ enabled: false }).total, 1);
store.setEnabled([code], true);
assert.ok(features.has(code));
// 内置命令一律只读
assert.throws(() => store.get("default_textReplacer"), /内置/);
assert.throws(() => store.remove("default_textReplacer"), /内置/);
assert.throws(() => store.update("default_textReplacer", draft), /内置/);
assert.notDeepStrictEqual(store.create({ ...draft, features: { ...draft.features, code: "default_x" } }).command.features.code, "default_x");
// 删
const removed = store.remove(code);
assert.strictEqual(removed.features.code, code);
assert.ok(!db.has("qc_" + code));
assert.ok(!features.has(code));
assert.throws(() => store.get(code), /没有找到/);
console.log("commandStore 自检通过");