54d0fb75ea
新增 GDExtension 自动引导、GDScript 执行和实例隔离缓存 接入 AGC 插件开关、Runner、Agent 工具与权限审计 完善执行回执确认、不确定状态阻断及卸载恢复 补齐 Windows 分发资源、定向测试与实机验收文档
118 lines
4.4 KiB
TypeScript
118 lines
4.4 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { dirname, resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
import { describe, expect, test } from 'vitest';
|
|
|
|
import {
|
|
RUSTFMT_EXCLUDED_WORKSPACES,
|
|
RUSTFMT_WORKSPACES,
|
|
selectRustfmtWorkspaces,
|
|
} from './lint-staged-rustfmt-workspaces.mjs';
|
|
|
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
|
function selectedManifests(stagedFiles: string[], root = repoRoot) {
|
|
return selectRustfmtWorkspaces({
|
|
stagedFiles,
|
|
repoRoot: root,
|
|
}).workspaces.map((workspace) => workspace.manifestPath);
|
|
}
|
|
|
|
describe('lint-staged Rust 格式检查的 workspace 选择', () => {
|
|
test('只暂存 server-rs 时不再连带检查 src-tauri', () => {
|
|
// 回归判据:`cargo fmt --all` 会连未暂存的在改文件一起查,全量跑两个 workspace
|
|
// 会让「只暂存了 server-rs 干净文件」的提交被别人的 src-tauri 改动挡下来。
|
|
expect(
|
|
selectedManifests([
|
|
'server-rs/crates/api-server/src/editor_project.rs',
|
|
'server-rs/crates/shared-contracts/src/game_creation_app.rs',
|
|
]),
|
|
).toEqual(['server-rs/Cargo.toml']);
|
|
});
|
|
|
|
test('只暂存 src-tauri 时不再连带检查 server-rs', () => {
|
|
expect(
|
|
selectedManifests(['apps/ai-game-creator-shell/src-tauri/src/assets.rs']),
|
|
).toEqual(['apps/ai-game-creator-shell/src-tauri/Cargo.toml']);
|
|
});
|
|
|
|
test('多个 workspace 都有暂存文件时分别检查', () => {
|
|
expect(
|
|
selectedManifests([
|
|
'server-rs/crates/api-server/src/editor_project.rs',
|
|
'apps/ai-game-creator-shell/src-tauri/src/assets.rs',
|
|
'plugins/agc-unity-editor/native/unity-editor-bridge/src/lib.rs',
|
|
'plugins/agc-godot-editor/native/godot-editor-bridge/src/lib.rs',
|
|
]),
|
|
).toEqual([
|
|
'server-rs/Cargo.toml',
|
|
'apps/ai-game-creator-shell/src-tauri/Cargo.toml',
|
|
'plugins/agc-unity-editor/native/unity-editor-bridge/Cargo.toml',
|
|
'plugins/agc-godot-editor/native/godot-editor-bridge/Cargo.toml',
|
|
]);
|
|
});
|
|
|
|
test('手工执行(没有暂存列表)时保持全量检查语义', () => {
|
|
const selection = selectRustfmtWorkspaces({ stagedFiles: [], repoRoot });
|
|
expect(selection.usedStagedList).toBe(false);
|
|
expect(selection.workspaces).toEqual(RUSTFMT_WORKSPACES);
|
|
});
|
|
|
|
test('排除的 workspace 与未登记路径都会被显式报出,不静默通过', () => {
|
|
const selection = selectRustfmtWorkspaces({
|
|
stagedFiles: [
|
|
'apps/desktop-shell/src-tauri/src/host_bridge/mod.rs',
|
|
'somewhere-new/src/lib.rs',
|
|
],
|
|
repoRoot,
|
|
});
|
|
// desktop-shell 当前整体未过 `cargo fmt --check`,所以它不参与检查……
|
|
expect(selection.workspaces).toEqual([]);
|
|
// ……但必须被点名,否则「glob 命中了、谁都没查」就是静默通过。
|
|
expect(selection.excluded).toEqual([
|
|
'apps/desktop-shell/src-tauri/src/host_bridge/mod.rs',
|
|
]);
|
|
expect(selection.unmanaged).toEqual(['somewhere-new/src/lib.rs']);
|
|
});
|
|
|
|
test('Windows 反斜杠与绝对路径都归一化成仓库相对路径', () => {
|
|
const root = 'C:\\repo\\genarrative';
|
|
expect(
|
|
selectedManifests(
|
|
[
|
|
'server-rs\\crates\\api-server\\src\\editor_project.rs',
|
|
`${root}\\apps\\ai-game-creator-shell\\src-tauri\\src\\assets.rs`,
|
|
],
|
|
root,
|
|
),
|
|
).toEqual([
|
|
'server-rs/Cargo.toml',
|
|
'apps/ai-game-creator-shell/src-tauri/Cargo.toml',
|
|
]);
|
|
});
|
|
|
|
test('检查清单与 package.json 的 check:rustfmt 保持同一份 workspace 表', () => {
|
|
// 两处各写一份 workspace 列表就会漂移:hook 查的与 `npm run check:rustfmt` 查的必须同集。
|
|
const packageJson = JSON.parse(
|
|
readFileSync(resolve(repoRoot, 'package.json'), 'utf8'),
|
|
) as { scripts: Record<string, string> };
|
|
const manifests = Array.from(
|
|
packageJson.scripts['check:rustfmt']!.matchAll(
|
|
/--manifest-path\s+(\S+)\s+--\s+--check/gu,
|
|
),
|
|
).map((match) => match[1]!);
|
|
expect(manifests).toEqual(
|
|
RUSTFMT_WORKSPACES.map((workspace) => workspace.manifestPath),
|
|
);
|
|
// 排除项必须是「检查清单之外」的,否则这段注释与实际行为不符。
|
|
for (const excluded of RUSTFMT_EXCLUDED_WORKSPACES) {
|
|
expect(
|
|
RUSTFMT_WORKSPACES.some((workspace) =>
|
|
workspace.prefix.startsWith(excluded.prefix),
|
|
),
|
|
).toBe(false);
|
|
}
|
|
});
|
|
});
|