feat(tools): new-game 一键新建子游戏工程

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 12:15:01 +08:00
co-authored by Claude Opus 4.8
parent 8bb3b80544
commit 28362314d2
2 changed files with 90 additions and 0 deletions
@@ -0,0 +1,50 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { join } from 'node:path';
import { existsSync, readFileSync } from 'node:fs';
import { makeTempMonorepo, makeSeed, cleanup } from './helpers.mjs';
import { newGame } from '../new-game.mjs';
import { isLink } from '../lib/junction.mjs';
test('newGame 生成工程:改身份 + 挂 framework junction + 铺 game 骨架', () => {
const mono = makeTempMonorepo();
try {
const seed = makeSeed(mono.root);
const result = newGame('doudizhu', { seedDir: seed, gamesDir: mono.games, frameworkSrc: mono.framework });
const dest = join(mono.games, 'doudizhu');
assert.equal(result.projectDir, dest);
const pkg = JSON.parse(readFileSync(join(dest, 'package.json'), 'utf8'));
assert.equal(pkg.name, 'doudizhu');
assert.notEqual(pkg.uuid, 'seed-uuid');
const link = join(dest, 'assets', 'framework');
assert.ok(isLink(link));
assert.equal(readFileSync(join(link, 'README.md'), 'utf8'), '# framework src\n');
assert.ok(existsSync(join(dest, 'assets', 'game', 'GameModule.ts')));
} finally {
cleanup(mono.root);
}
});
test('newGame 拒绝重名工程', () => {
const mono = makeTempMonorepo();
try {
const seed = makeSeed(mono.root);
const opts = { seedDir: seed, gamesDir: mono.games, frameworkSrc: mono.framework };
newGame('doudizhu', opts);
assert.throws(() => newGame('doudizhu', opts), /已存在/);
} finally {
cleanup(mono.root);
}
});
test('newGame 校验名称非空且合法', () => {
const mono = makeTempMonorepo();
try {
const seed = makeSeed(mono.root);
const opts = { seedDir: seed, gamesDir: mono.games, frameworkSrc: mono.framework };
assert.throws(() => newGame('', opts), /名称/);
assert.throws(() => newGame('Bad Name!', opts), /名称/);
} finally {
cleanup(mono.root);
}
});