From e66d3fd824d1e79bf575f6de2ec81d62c9c6f8cc Mon Sep 17 00:00:00 2001 From: sunlei Date: Mon, 15 Jun 2026 10:02:43 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E6=94=B6=E6=95=9B=E7=BB=93=E6=9E=84=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../architecture-convergence.spec.ts | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 test/refactor-v3/architecture-convergence.spec.ts diff --git a/test/refactor-v3/architecture-convergence.spec.ts b/test/refactor-v3/architecture-convergence.spec.ts new file mode 100644 index 0000000..bba8e7b --- /dev/null +++ b/test/refactor-v3/architecture-convergence.spec.ts @@ -0,0 +1,74 @@ +import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; +import { join, relative } from 'node:path'; + +const repoRoot = join(__dirname, '..', '..'); +const srcRoot = join(repoRoot, 'src'); + +const legacyRoots = ['admin', 'blog', 'minio', 'wordpress', 'qqbot']; +const moduleRoots = ['admin', 'asset', 'blog', 'wordpress', 'qqbot']; +const qqbotRoots = ['core', 'napcat', 'plugin-platform', 'plugins']; + +function listFiles(dir: string): string[] { + if (!existsSync(dir)) return []; + return readdirSync(dir).flatMap((entry) => { + const absolute = join(dir, entry); + const stat = statSync(absolute); + if (stat.isDirectory()) return listFiles(absolute); + return [absolute]; + }); +} + +function readTextFiles(dir: string): Array<{ file: string; text: string }> { + return listFiles(dir) + .filter((file) => /\.(ts|tsx|vue|js|mjs|cjs)$/.test(file)) + .map((file) => ({ + file: relative(repoRoot, file).replace(/\\/g, '/'), + text: readFileSync(file, 'utf8'), + })); +} + +describe('architecture convergence', () => { + it('does not keep API legacy source roots', () => { + const existing = legacyRoots.filter((root) => + existsSync(join(srcRoot, root)), + ); + + expect(existing).toEqual([]); + }); + + it('keeps all business modules under src/modules', () => { + const missing = moduleRoots.filter( + (root) => !existsSync(join(srcRoot, 'modules', root)), + ); + + expect(missing).toEqual([]); + }); + + it('keeps QQBot subdomains under src/modules/qqbot', () => { + const missing = qqbotRoots.filter( + (root) => !existsSync(join(srcRoot, 'modules', 'qqbot', root)), + ); + + expect(missing).toEqual([]); + }); + + it('does not import old roots from src/modules', () => { + const forbidden = /@\/(?:admin|blog|minio|wordpress|qqbot)\//; + const offenders = readTextFiles(join(srcRoot, 'modules')) + .filter(({ text }) => forbidden.test(text)) + .map(({ file }) => file); + + expect(offenders).toEqual([]); + }); + + it('does not import old roots from app module', () => { + const appModule = readFileSync(join(srcRoot, 'app.module.ts'), 'utf8'); + + expect(appModule).not.toMatch( + /from ['"]\.\/(?:admin|blog|minio|wordpress|qqbot)/, + ); + expect(appModule).not.toMatch( + /from ['"]@\/(?:admin|blog|minio|wordpress|qqbot)\//, + ); + }); +});