kt-template-online-api/test/modules/qqbot/plugins/bangdream-rewrite/bangdream-operation-parity.spec.ts

164 lines
4.9 KiB
TypeScript

import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
const repoRoot = join(__dirname, '../../../../..');
const newBangDreamRoot = join(
repoRoot,
'src/modules/qqbot/plugins/bangdream',
);
const baselineTest = join(
repoRoot,
'test/modules/qqbot/architecture/qqbot-current-operation-matrix.spec.ts',
);
const expectedOperationKeys = [
'bangdream.song.search',
'bangdream.song.chart',
'bangdream.song.random',
'bangdream.song.meta',
'bangdream.card.search',
'bangdream.card.illustration',
'bangdream.character.search',
'bangdream.event.search',
'bangdream.event.stage',
'bangdream.player.search',
'bangdream.gacha.search',
'bangdream.gacha.simulate',
'bangdream.cutoff.detail',
'bangdream.cutoff.all',
'bangdream.cutoff.recent',
];
describe('BangDream rewritten plugin parity', () => {
it('uses the new platform package structure', () => {
const requiredPaths = [
'plugin.json',
'src/index.ts',
'src/application/bangdream-command-context.ts',
'src/application/hook/hook-registry.ts',
'src/operations/song-search',
'src/operations/song-chart',
'src/operations/song-random',
'src/operations/song-meta',
'src/operations/card-search',
'src/operations/card-illustration',
'src/operations/character-search',
'src/operations/event-search',
'src/operations/event-stage',
'src/operations/player-search',
'src/operations/gacha-search',
'src/operations/gacha-simulate',
'src/operations/cutoff-detail',
'src/operations/cutoff-all',
'src/operations/cutoff-recent',
'src/domain/song',
'src/domain/card',
'src/domain/character',
'src/domain/event',
'src/domain/gacha',
'src/domain/player',
'src/domain/cutoff',
'src/domain/catalog',
'src/domain/common/qqbot-bangdream.types.ts',
'src/infrastructure/integration',
'src/infrastructure/storage',
'src/config',
'src/config/dictionary',
'src/assets',
];
const missing = requiredPaths.filter(
(relativePath) => !existsSync(join(newBangDreamRoot, relativePath)),
);
expect(missing).toEqual([]);
});
it('preserves the 15 approved operation keys in the new manifest', () => {
const manifestPath = join(newBangDreamRoot, 'plugin.json');
expect(existsSync(manifestPath)).toBe(true);
if (!existsSync(manifestPath)) return;
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as {
operations?: Array<{ key?: string }>;
pluginKey?: string;
};
expect(manifest.pluginKey).toBe('bangdream');
expect(manifest.operations?.map((operation) => operation.key)).toEqual(
expectedOperationKeys,
);
});
it('keeps event stage split output as a hard parity gate', () => {
const baseline = readFileSync(baselineTest, 'utf8');
const operationSourcePath = join(
newBangDreamRoot,
'src/operations/event-stage',
);
expect(baseline).toContain('bangdream.event.stage');
expect(existsSync(operationSourcePath)).toBe(true);
if (!existsSync(operationSourcePath)) return;
const eventStageSource = readFileSync(
join(operationSourcePath, 'index.ts'),
'utf8',
);
expect(eventStageSource).toContain('expectedImageCount');
expect(eventStageSource).toContain('5');
});
it('makes operation modules executable instead of handler-name placeholders', () => {
const operationRoot = join(newBangDreamRoot, 'src/operations');
const operationDirs = expectedOperationKeys.map((operationKey) =>
operationKey.replace('bangdream.', '').replace(/\./g, '-'),
);
for (const operationDir of operationDirs) {
const source = readFileSync(
join(operationRoot, operationDir, 'index.ts'),
'utf8',
);
expect(source).toContain('execute: async');
expect(source).toContain('context.');
expect(source).not.toMatch(/key: 'bangdream\./);
}
});
it('uses real business directories and removes old wrapper layers', () => {
const domainDirs = [
'song',
'card',
'character',
'event',
'gacha',
'player',
'cutoff',
'catalog',
];
for (const domainDir of domainDirs) {
expect(existsSync(join(newBangDreamRoot, 'src/domain', domainDir))).toBe(
true,
);
expect(
existsSync(join(newBangDreamRoot, 'src/domain', domainDir, 'index.ts')),
).toBe(false);
}
for (const removedPath of [
'src/application/bangdream-renderer.facade.ts',
'src/application/bangdream-application.service.ts',
'src/application/bangdream-context.ts',
'src/application/bangdream-operation-runtime.ts',
'src/application/operation-pipeline.ts',
'src/operations/operation-executor.ts',
'src/domain/common/bangdream-constants.ts',
'src/qqbot-bangdream.types.ts',
]) {
expect(existsSync(join(newBangDreamRoot, removedPath))).toBe(false);
}
});
});