@zjex/git-workflow 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +5 -2
- package/ROADMAP.md +275 -0
- package/dist/index.js +349 -88
- package/docs/features/git-wrapped.md +199 -0
- package/package.json +2 -1
- package/scripts/release.sh +61 -1
- package/src/ai-service.ts +8 -2
- package/src/commands/commit.ts +4 -0
- package/src/commands/log.ts +503 -0
- package/src/index.ts +37 -13
- package/src/utils.ts +10 -0
- package/tests/log.test.ts +106 -0
- package/src/commands/help.ts +0 -76
- package/tests/help.test.ts +0 -134
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zjex/git-workflow - Log 命令测试
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
|
|
8
|
+
// Mock execSync
|
|
9
|
+
vi.mock('child_process', () => ({
|
|
10
|
+
execSync: vi.fn()
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
// Mock inquirer prompts
|
|
14
|
+
vi.mock('@inquirer/prompts', () => ({
|
|
15
|
+
select: vi.fn(),
|
|
16
|
+
input: vi.fn(),
|
|
17
|
+
confirm: vi.fn()
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
const mockExecSync = vi.mocked(execSync);
|
|
21
|
+
|
|
22
|
+
describe('Log 命令', () => {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
vi.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('buildLogCommand', () => {
|
|
28
|
+
it('应该构建基本的log命令', async () => {
|
|
29
|
+
// 动态导入以避免模块加载时的副作用
|
|
30
|
+
const { log } = await import('../src/commands/log.js');
|
|
31
|
+
|
|
32
|
+
// Mock execSync 返回值
|
|
33
|
+
mockExecSync.mockReturnValue('mock log output');
|
|
34
|
+
|
|
35
|
+
// 测试基本选项
|
|
36
|
+
const options = { format: 'medium' as const, limit: 10 };
|
|
37
|
+
|
|
38
|
+
// 由于log函数会调用execSync,我们需要模拟它
|
|
39
|
+
await expect(async () => {
|
|
40
|
+
// 这里我们不能直接测试buildLogCommand,因为它不是导出的
|
|
41
|
+
// 但我们可以通过测试log函数来间接测试
|
|
42
|
+
}).not.toThrow();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('应该正确处理作者筛选', () => {
|
|
46
|
+
// 测试作者筛选参数
|
|
47
|
+
expect(mockExecSync).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('应该正确处理时间范围', () => {
|
|
51
|
+
// 测试时间范围参数
|
|
52
|
+
expect(mockExecSync).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('应该正确处理关键词搜索', () => {
|
|
56
|
+
// 测试关键词搜索参数
|
|
57
|
+
expect(mockExecSync).toBeDefined();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('日志格式', () => {
|
|
62
|
+
it('应该支持oneline格式', () => {
|
|
63
|
+
expect(true).toBe(true); // 占位测试
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('应该支持graph格式', () => {
|
|
67
|
+
expect(true).toBe(true); // 占位测试
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('应该支持medium格式', () => {
|
|
71
|
+
expect(true).toBe(true); // 占位测试
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('错误处理', () => {
|
|
76
|
+
it('应该处理Git命令执行失败', async () => {
|
|
77
|
+
mockExecSync.mockImplementation(() => {
|
|
78
|
+
const error = new Error('Command failed') as any;
|
|
79
|
+
error.status = 128;
|
|
80
|
+
throw error;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// 测试错误处理
|
|
84
|
+
expect(mockExecSync).toBeDefined();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('应该处理空的日志输出', () => {
|
|
88
|
+
mockExecSync.mockReturnValue('');
|
|
89
|
+
expect(mockExecSync).toBeDefined();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('快速日志功能', () => {
|
|
94
|
+
it('应该支持快速查看最近提交', async () => {
|
|
95
|
+
mockExecSync.mockReturnValue('abc123 Test commit');
|
|
96
|
+
|
|
97
|
+
const { quickLog } = await import('../src/commands/log.js');
|
|
98
|
+
|
|
99
|
+
await expect(quickLog(5)).resolves.not.toThrow();
|
|
100
|
+
expect(mockExecSync).toHaveBeenCalledWith(
|
|
101
|
+
expect.stringContaining('-5'),
|
|
102
|
+
expect.any(Object)
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
package/src/commands/help.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { TODAY } from "../utils.js";
|
|
2
|
-
|
|
3
|
-
export function showHelp(): string {
|
|
4
|
-
return `
|
|
5
|
-
分支命令:
|
|
6
|
-
gw feature [--base <branch>] 创建 feature 分支
|
|
7
|
-
gw feat [--base <branch>] 同上 (别名)
|
|
8
|
-
gw f [--base <branch>] 同上 (别名)
|
|
9
|
-
|
|
10
|
-
gw hotfix [--base <branch>] 创建 hotfix 分支
|
|
11
|
-
gw fix [--base <branch>] 同上 (别名)
|
|
12
|
-
gw h [--base <branch>] 同上 (别名)
|
|
13
|
-
|
|
14
|
-
gw delete [branch] 删除本地/远程分支
|
|
15
|
-
gw del [branch] 同上 (别名)
|
|
16
|
-
gw d [branch] 同上 (别名)
|
|
17
|
-
|
|
18
|
-
Tag 命令:
|
|
19
|
-
gw tags [prefix] 列出所有 tag,可按前缀过滤
|
|
20
|
-
gw ts [prefix] 同上 (别名)
|
|
21
|
-
|
|
22
|
-
gw tag [prefix] 交互式选择版本类型并创建 tag
|
|
23
|
-
gw t [prefix] 同上 (别名)
|
|
24
|
-
|
|
25
|
-
gw tag:delete 删除 tag
|
|
26
|
-
gw td 同上 (别名)
|
|
27
|
-
|
|
28
|
-
gw tag:update 重命名 tag
|
|
29
|
-
gw tu 同上 (别名)
|
|
30
|
-
|
|
31
|
-
发布命令:
|
|
32
|
-
gw release 交互式选择版本号并更新 package.json
|
|
33
|
-
gw r 同上 (别名)
|
|
34
|
-
|
|
35
|
-
配置命令:
|
|
36
|
-
gw init 初始化配置文件
|
|
37
|
-
• 全局配置: ~/.gwrc.json (所有项目生效)
|
|
38
|
-
• 项目配置: .gwrc.json (仅当前项目)
|
|
39
|
-
运行时可选择配置范围
|
|
40
|
-
|
|
41
|
-
更新命令:
|
|
42
|
-
gw update 检查并更新到最新版本
|
|
43
|
-
gw upt 同上 (别名)
|
|
44
|
-
|
|
45
|
-
清理命令:
|
|
46
|
-
gw clean 清理缓存文件
|
|
47
|
-
|
|
48
|
-
Stash 命令:
|
|
49
|
-
gw stash 交互式管理 stash
|
|
50
|
-
gw s 同上 (别名)
|
|
51
|
-
gw st 同上 (别名)
|
|
52
|
-
|
|
53
|
-
Commit 命令:
|
|
54
|
-
gw commit 交互式提交 (Conventional Commits + Gitmoji)
|
|
55
|
-
gw c 同上 (别名)
|
|
56
|
-
gw cm 同上 (别名)
|
|
57
|
-
|
|
58
|
-
示例:
|
|
59
|
-
gw f 基于 main/master 创建 feature 分支
|
|
60
|
-
gw f --base develop 基于 develop 分支创建 feature 分支
|
|
61
|
-
gw h --base release 基于 release 分支创建 hotfix 分支
|
|
62
|
-
gw d 交互式选择并删除分支
|
|
63
|
-
gw d feature/xxx 直接删除指定分支
|
|
64
|
-
gw ts v 列出所有 v 开头的 tag
|
|
65
|
-
gw t 交互式创建 tag
|
|
66
|
-
gw td 交互式删除 tag
|
|
67
|
-
gw tu 交互式修改 tag
|
|
68
|
-
gw r 交互式发布版本
|
|
69
|
-
gw s 交互式管理 stash
|
|
70
|
-
gw c 交互式提交代码
|
|
71
|
-
|
|
72
|
-
分支命名格式:
|
|
73
|
-
feature/${TODAY}-<Story ID>-<描述>
|
|
74
|
-
hotfix/${TODAY}-<Issue ID>-<描述>
|
|
75
|
-
`;
|
|
76
|
-
}
|
package/tests/help.test.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { showHelp } from "../src/commands/help.js";
|
|
3
|
-
import { TODAY } from "../src/utils.js";
|
|
4
|
-
|
|
5
|
-
describe("Help 模块测试", () => {
|
|
6
|
-
describe("showHelp 函数", () => {
|
|
7
|
-
it("应该返回完整的帮助信息", () => {
|
|
8
|
-
const helpText = showHelp();
|
|
9
|
-
|
|
10
|
-
expect(helpText).toContain("分支命令:");
|
|
11
|
-
expect(helpText).toContain("Tag 命令:");
|
|
12
|
-
expect(helpText).toContain("发布命令:");
|
|
13
|
-
expect(helpText).toContain("配置命令:");
|
|
14
|
-
expect(helpText).toContain("更新命令:");
|
|
15
|
-
expect(helpText).toContain("清理命令:");
|
|
16
|
-
expect(helpText).toContain("Stash 命令:");
|
|
17
|
-
expect(helpText).toContain("Commit 命令:");
|
|
18
|
-
expect(helpText).toContain("示例:");
|
|
19
|
-
expect(helpText).toContain("分支命名格式:");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("应该包含所有主要命令", () => {
|
|
23
|
-
const helpText = showHelp();
|
|
24
|
-
|
|
25
|
-
// 分支命令
|
|
26
|
-
expect(helpText).toContain("gw feature");
|
|
27
|
-
expect(helpText).toContain("gw feat");
|
|
28
|
-
expect(helpText).toContain("gw f");
|
|
29
|
-
expect(helpText).toContain("gw hotfix");
|
|
30
|
-
expect(helpText).toContain("gw fix");
|
|
31
|
-
expect(helpText).toContain("gw h");
|
|
32
|
-
expect(helpText).toContain("gw delete");
|
|
33
|
-
expect(helpText).toContain("gw del");
|
|
34
|
-
expect(helpText).toContain("gw d");
|
|
35
|
-
|
|
36
|
-
// Tag 命令
|
|
37
|
-
expect(helpText).toContain("gw tags");
|
|
38
|
-
expect(helpText).toContain("gw ts");
|
|
39
|
-
expect(helpText).toContain("gw tag");
|
|
40
|
-
expect(helpText).toContain("gw t");
|
|
41
|
-
expect(helpText).toContain("gw tag:delete");
|
|
42
|
-
expect(helpText).toContain("gw td");
|
|
43
|
-
expect(helpText).toContain("gw tag:update");
|
|
44
|
-
expect(helpText).toContain("gw tu");
|
|
45
|
-
|
|
46
|
-
// 其他命令
|
|
47
|
-
expect(helpText).toContain("gw release");
|
|
48
|
-
expect(helpText).toContain("gw r");
|
|
49
|
-
expect(helpText).toContain("gw init");
|
|
50
|
-
expect(helpText).toContain("gw update");
|
|
51
|
-
expect(helpText).toContain("gw upt");
|
|
52
|
-
expect(helpText).toContain("gw clean");
|
|
53
|
-
expect(helpText).toContain("gw stash");
|
|
54
|
-
expect(helpText).toContain("gw s");
|
|
55
|
-
expect(helpText).toContain("gw st");
|
|
56
|
-
expect(helpText).toContain("gw commit");
|
|
57
|
-
expect(helpText).toContain("gw c");
|
|
58
|
-
expect(helpText).toContain("gw cm");
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("应该包含命令描述", () => {
|
|
62
|
-
const helpText = showHelp();
|
|
63
|
-
|
|
64
|
-
expect(helpText).toContain("创建 feature 分支");
|
|
65
|
-
expect(helpText).toContain("创建 hotfix 分支");
|
|
66
|
-
expect(helpText).toContain("删除本地/远程分支");
|
|
67
|
-
expect(helpText).toContain("列出所有 tag");
|
|
68
|
-
expect(helpText).toContain("交互式选择版本类型并创建 tag");
|
|
69
|
-
expect(helpText).toContain("删除 tag");
|
|
70
|
-
expect(helpText).toContain("重命名 tag");
|
|
71
|
-
expect(helpText).toContain("交互式选择版本号并更新 package.json");
|
|
72
|
-
expect(helpText).toContain("初始化配置文件");
|
|
73
|
-
expect(helpText).toContain("检查并更新到最新版本");
|
|
74
|
-
expect(helpText).toContain("清理缓存文件");
|
|
75
|
-
expect(helpText).toContain("交互式管理 stash");
|
|
76
|
-
expect(helpText).toContain("交互式提交");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("应该包含使用示例", () => {
|
|
80
|
-
const helpText = showHelp();
|
|
81
|
-
|
|
82
|
-
expect(helpText).toContain("gw f --base develop");
|
|
83
|
-
expect(helpText).toContain("gw h --base release");
|
|
84
|
-
expect(helpText).toContain("gw d feature/xxx");
|
|
85
|
-
expect(helpText).toContain("gw ts v");
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("应该包含分支命名格式说明", () => {
|
|
89
|
-
const helpText = showHelp();
|
|
90
|
-
|
|
91
|
-
expect(helpText).toContain("feature/20260111-<Story ID>-<描述>");
|
|
92
|
-
expect(helpText).toContain("hotfix/20260111-<Issue ID>-<描述>");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("应该包含配置文件说明", () => {
|
|
96
|
-
const helpText = showHelp();
|
|
97
|
-
|
|
98
|
-
expect(helpText).toContain("全局配置: ~/.gwrc.json");
|
|
99
|
-
expect(helpText).toContain("项目配置: .gwrc.json");
|
|
100
|
-
expect(helpText).toContain("所有项目生效");
|
|
101
|
-
expect(helpText).toContain("仅当前项目");
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("应该包含别名说明", () => {
|
|
105
|
-
const helpText = showHelp();
|
|
106
|
-
|
|
107
|
-
expect(helpText).toContain("同上 (别名)");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("应该包含参数说明", () => {
|
|
111
|
-
const helpText = showHelp();
|
|
112
|
-
|
|
113
|
-
expect(helpText).toContain("[--base <branch>]");
|
|
114
|
-
expect(helpText).toContain("[branch]");
|
|
115
|
-
expect(helpText).toContain("[prefix]");
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("应该是非空字符串", () => {
|
|
119
|
-
const helpText = showHelp();
|
|
120
|
-
|
|
121
|
-
expect(typeof helpText).toBe("string");
|
|
122
|
-
expect(helpText.length).toBeGreaterThan(0);
|
|
123
|
-
expect(helpText.trim().length).toBeGreaterThan(0);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("应该包含实际的日期格式", () => {
|
|
127
|
-
const helpText = showHelp();
|
|
128
|
-
|
|
129
|
-
// 检查是否包含实际的日期格式(YYYYMMDD)
|
|
130
|
-
expect(helpText).toMatch(/feature\/\d{8}-<Story ID>-<描述>/);
|
|
131
|
-
expect(helpText).toMatch(/hotfix\/\d{8}-<Issue ID>-<描述>/);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
});
|