test: 固化Bilibili卡片插件架构门禁
This commit is contained in:
parent
98e26616bb
commit
414136a7bd
@ -249,12 +249,81 @@ INSERT INTO qqbot_plugin (
|
||||
'Repeater',
|
||||
'Built-in repeater event plugin metadata.',
|
||||
'installed'
|
||||
),
|
||||
(
|
||||
1000000000000000105,
|
||||
'bilibili-card',
|
||||
'Bilibili Card',
|
||||
'Built-in Bilibili card event plugin metadata.',
|
||||
'installed'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
plugin_name = VALUES(plugin_name),
|
||||
description = VALUES(description),
|
||||
status = VALUES(status);
|
||||
|
||||
INSERT INTO qqbot_plugin_version (
|
||||
id,
|
||||
plugin_id,
|
||||
version,
|
||||
package_hash,
|
||||
manifest_json
|
||||
) VALUES (
|
||||
1000000000000001105,
|
||||
1000000000000000105,
|
||||
'1.0.0',
|
||||
'builtin-bilibili-card-1.0.0',
|
||||
JSON_OBJECT(
|
||||
'key', 'bilibili-card',
|
||||
'name', 'Bilibili Card',
|
||||
'version', '1.0.0',
|
||||
'entry', 'src/index.ts',
|
||||
'events', JSON_ARRAY(JSON_OBJECT(
|
||||
'key', 'bilibili-card.message',
|
||||
'eventName', 'message',
|
||||
'handlerName', 'handleMessage',
|
||||
'name', 'Bilibili 卡片解析'
|
||||
))
|
||||
)
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
package_hash = VALUES(package_hash),
|
||||
manifest_json = VALUES(manifest_json);
|
||||
|
||||
INSERT INTO qqbot_plugin_installation (
|
||||
id,
|
||||
plugin_id,
|
||||
version_id,
|
||||
status,
|
||||
runtime_status,
|
||||
installed_path
|
||||
) VALUES (
|
||||
1000000000000001205,
|
||||
1000000000000000105,
|
||||
1000000000000001105,
|
||||
'installed',
|
||||
'idle',
|
||||
'src/modules/qqbot/plugins/bilibili-card'
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
status = VALUES(status),
|
||||
runtime_status = VALUES(runtime_status),
|
||||
installed_path = VALUES(installed_path);
|
||||
|
||||
INSERT INTO qqbot_plugin_event_handler (
|
||||
id,
|
||||
plugin_id,
|
||||
event_key,
|
||||
handler_name,
|
||||
enabled
|
||||
) VALUES (
|
||||
1000000000000001305,
|
||||
1000000000000000105,
|
||||
'bilibili-card.message',
|
||||
'handleMessage',
|
||||
1
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
handler_name = VALUES(handler_name),
|
||||
enabled = VALUES(enabled);
|
||||
|
||||
INSERT INTO qqbot_command (
|
||||
id,
|
||||
operation_key,
|
||||
|
||||
@ -36,6 +36,17 @@ FROM qqbot_plugin
|
||||
WHERE plugin_key = 'bangdream'
|
||||
AND status = 'installed';
|
||||
|
||||
SELECT 'seed_qqbot_plugin_bilibili_card' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM qqbot_plugin
|
||||
WHERE plugin_key = 'bilibili-card'
|
||||
AND status = 'installed';
|
||||
|
||||
SELECT 'seed_qqbot_plugin_event_bilibili_card' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM qqbot_plugin_event_handler
|
||||
WHERE event_key = 'bilibili-card.message'
|
||||
AND handler_name = 'handleMessage'
|
||||
AND enabled = 1;
|
||||
|
||||
SELECT 'seed_qqbot_command_bangdream_song' AS check_name, COUNT(*) AS matched_rows
|
||||
FROM qqbot_command
|
||||
WHERE command_key = 'bangdream_song'
|
||||
|
||||
@ -142,6 +142,7 @@ describe('QQBot current operation matrix', () => {
|
||||
it('freezes built-in plugin manifests and exposed capabilities', () => {
|
||||
const manifests = {
|
||||
bangdream: readManifest('bangdream'),
|
||||
bilibiliCard: readManifest('bilibili-card'),
|
||||
ff14: readManifest('ff14-market'),
|
||||
fflogs: readManifest('fflogs'),
|
||||
repeater: readManifest('repeater'),
|
||||
@ -157,6 +158,23 @@ describe('QQBot current operation matrix', () => {
|
||||
})),
|
||||
).toEqual(bangdreamOperations);
|
||||
|
||||
expect(
|
||||
manifests.bilibiliCard.events.map((event) => ({
|
||||
eventName: event.eventName,
|
||||
handlerName: event.handlerName,
|
||||
key: event.key,
|
||||
name: event.name,
|
||||
})),
|
||||
).toEqual([
|
||||
{
|
||||
eventName: 'message',
|
||||
handlerName: 'handleMessage',
|
||||
key: 'bilibili-card.message',
|
||||
name: 'Bilibili 卡片解析',
|
||||
},
|
||||
]);
|
||||
expect(manifests.bilibiliCard.operations).toEqual([]);
|
||||
|
||||
expect(
|
||||
manifests.ff14.operations.map((operation) => ({
|
||||
aliases: operation.aliases,
|
||||
@ -215,6 +233,10 @@ describe('QQBot current operation matrix', () => {
|
||||
|
||||
it('freezes current online command seed linkage for command plugins', () => {
|
||||
const seedSql = readFileSync(join(repoRoot, 'sql/qqbot-init.sql'), 'utf8');
|
||||
const refactorSeedSql = readFileSync(
|
||||
join(repoRoot, 'sql/refactor-v3/01-seed-core.sql'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
for (const operation of bangdreamOperations) {
|
||||
expect(seedSql).toContain(`'${operation.key}'`);
|
||||
@ -224,5 +246,7 @@ describe('QQBot current operation matrix', () => {
|
||||
expect(seedSql).toContain(`'ff14-market', 'ff14.market.price'`);
|
||||
expect(seedSql).toContain(`'fflogs', 'fflogs.character.summary'`);
|
||||
expect(seedSql).toContain(`'bangdream', 'bangdream.event.stage', 'plain'`);
|
||||
expect(refactorSeedSql).toContain(`'bilibili-card'`);
|
||||
expect(refactorSeedSql).toContain(`'bilibili-card.message'`);
|
||||
});
|
||||
});
|
||||
|
||||
@ -97,6 +97,7 @@ describe('QQBot plugin package boundary', () => {
|
||||
|
||||
expect(pluginDirs).toEqual([
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
@ -104,23 +105,27 @@ describe('QQBot plugin package boundary', () => {
|
||||
});
|
||||
|
||||
it('uses the same package shape for every built-in plugin', () => {
|
||||
const missing = ['bangdream', 'ff14-market', 'fflogs', 'repeater'].flatMap(
|
||||
(pluginKey) => {
|
||||
const manifest = JSON.parse(
|
||||
readFileSync(join(pluginRoot, pluginKey, 'plugin.json'), 'utf8'),
|
||||
) as { events?: unknown[]; operations?: unknown[] };
|
||||
const requiredPaths = [
|
||||
...requiredPluginPaths,
|
||||
...((manifest.operations || []).length
|
||||
? requiredCommandPluginPaths
|
||||
: []),
|
||||
...((manifest.events || []).length ? requiredEventPluginPaths : []),
|
||||
];
|
||||
return requiredPaths
|
||||
.map((pathName) => `${pluginKey}/${pathName}`)
|
||||
.filter((pathName) => !existsSync(join(pluginRoot, pathName)));
|
||||
},
|
||||
);
|
||||
const missing = [
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
].flatMap((pluginKey) => {
|
||||
const manifest = JSON.parse(
|
||||
readFileSync(join(pluginRoot, pluginKey, 'plugin.json'), 'utf8'),
|
||||
) as { events?: unknown[]; operations?: unknown[] };
|
||||
const requiredPaths = [
|
||||
...requiredPluginPaths,
|
||||
...((manifest.operations || []).length
|
||||
? requiredCommandPluginPaths
|
||||
: []),
|
||||
...((manifest.events || []).length ? requiredEventPluginPaths : []),
|
||||
];
|
||||
return requiredPaths
|
||||
.map((pathName) => `${pluginKey}/${pathName}`)
|
||||
.filter((pathName) => !existsSync(join(pluginRoot, pathName)));
|
||||
});
|
||||
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
@ -128,6 +133,7 @@ describe('QQBot plugin package boundary', () => {
|
||||
it('does not keep third-phase package directories as empty shells', () => {
|
||||
const emptyRequiredDirs = [
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
@ -242,6 +248,7 @@ describe('QQBot plugin package boundary', () => {
|
||||
it('keeps plugin package entrypoints limited to createPlugin', () => {
|
||||
const extraExports = [
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
@ -319,7 +326,7 @@ describe('plugin platform package decoupling', () => {
|
||||
.join('|'),
|
||||
);
|
||||
const forbiddenBranchPattern =
|
||||
/pluginKey\s*(?:={2,3})\s*['"`](bangdream|ff14-market|fflogs|repeater)['"`]|case\s+['"`](bangdream|ff14-market|fflogs|repeater)['"`]/;
|
||||
/pluginKey\s*(?:={2,3})\s*['"`](bangdream|bilibili-card|ff14-market|fflogs|repeater)['"`]|case\s+['"`](bangdream|bilibili-card|ff14-market|fflogs|repeater)['"`]/;
|
||||
|
||||
/**
|
||||
* Escapes a literal token before it is placed into the architecture gate regexp.
|
||||
|
||||
@ -41,7 +41,13 @@ describe('QQBot existing plugin platform migration', () => {
|
||||
readdirSync(pluginRoot)
|
||||
.filter((name) => statSync(join(pluginRoot, name)).isDirectory())
|
||||
.sort(),
|
||||
).toEqual(['bangdream', 'ff14-market', 'fflogs', 'repeater']);
|
||||
).toEqual([
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
]);
|
||||
|
||||
const legacySources = collectFiles(legacyPluginRoot).filter((filePath) =>
|
||||
filePath.endsWith('.ts'),
|
||||
@ -50,21 +56,26 @@ describe('QQBot existing plugin platform migration', () => {
|
||||
});
|
||||
|
||||
it('declares parseable platform manifests for every existing plugin', () => {
|
||||
const manifests = ['bangdream', 'ff14-market', 'fflogs', 'repeater'].map(
|
||||
(pluginName) => {
|
||||
const root = join(pluginRoot, pluginName);
|
||||
const manifest = parseQqbotPluginManifest(
|
||||
readJson(join(root, 'plugin.json')),
|
||||
{
|
||||
pluginRoot: root,
|
||||
},
|
||||
);
|
||||
return manifest;
|
||||
},
|
||||
);
|
||||
const manifests = [
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
].map((pluginName) => {
|
||||
const root = join(pluginRoot, pluginName);
|
||||
const manifest = parseQqbotPluginManifest(
|
||||
readJson(join(root, 'plugin.json')),
|
||||
{
|
||||
pluginRoot: root,
|
||||
},
|
||||
);
|
||||
return manifest;
|
||||
});
|
||||
|
||||
expect(manifests.map((manifest) => manifest.pluginKey).sort()).toEqual([
|
||||
'bangdream',
|
||||
'bilibili-card',
|
||||
'ff14-market',
|
||||
'fflogs',
|
||||
'repeater',
|
||||
@ -79,6 +90,16 @@ describe('QQBot existing plugin platform migration', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('seeds Bilibili card plugin event metadata in refactor v3 SQL', () => {
|
||||
const refactorSeedSql = readFileSync(
|
||||
join(repoRoot, 'sql/refactor-v3/01-seed-core.sql'),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
expect(refactorSeedSql).toContain(`'bilibili-card'`);
|
||||
expect(refactorSeedSql).toContain(`'bilibili-card.message'`);
|
||||
});
|
||||
|
||||
it('keeps BangDream manifest operations as the single metadata source', () => {
|
||||
const manifest = parseQqbotPluginManifest(
|
||||
readJson(join(pluginRoot, 'bangdream/plugin.json')),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user