@opentask/taskin-task-manager 1.0.8 → 2.0.0
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/.prettierignore +1 -0
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-format.log +13 -26
- package/.turbo/turbo-install.log +6 -0
- package/.turbo/turbo-lint$colon$fix.log +12 -0
- package/.turbo/turbo-lint.log +13 -0
- package/.turbo/turbo-test.log +7 -7
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +51 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/provider-stats.test.js +14 -14
- package/dist/task-manager.d.ts +8 -14
- package/dist/task-manager.js +43 -31
- package/dist/task-manager.js.map +1 -1
- package/dist/task-manager.mock.js +17 -16
- package/dist/task-manager.mock.js.map +1 -1
- package/dist/task-manager.test.js +114 -93
- package/dist/task-manager.test.js.map +1 -1
- package/dist/task-manager.types.d.ts +113 -100
- package/dist/task-manager.types.js +1 -1
- package/package.json +3 -2
- package/src/index.ts +1 -0
- package/src/task-manager.mock.ts +1 -0
- package/src/task-manager.test.ts +50 -0
- package/src/task-manager.ts +19 -0
- package/src/task-manager.types.ts +15 -0
- package/tsconfig.tsbuildinfo +1 -1
package/.prettierignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dist/
|
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-format.log
CHANGED
|
@@ -1,31 +1,18 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @opentask/taskin-task-manager@
|
|
3
|
+
> @opentask/taskin-task-manager@2.0.0 format /Users/sidarta/repositorios/taskin/packages/task-manager
|
|
4
4
|
> prettier --write .
|
|
5
5
|
|
|
6
|
-
.turbo/turbo-build.log[2K[1G.turbo/turbo-format.log[2K[1G.turbo/turbo-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
dist/task-manager.test.js.map[2K[1Gdist/task-manager.types.d.ts[2K[1G[90mdist/task-manager.types.d.ts[39m 19ms (unchanged)
|
|
19
|
-
dist/task-manager.types.js[2K[1G[90mdist/task-manager.types.js[39m 2ms (unchanged)
|
|
20
|
-
dist/task-manager.types.js.map[2K[1Geslint.config.js[2K[1G[90meslint.config.js[39m 9ms (unchanged)
|
|
21
|
-
package.json[2K[1G[90mpackage.json[39m 7ms (unchanged)
|
|
22
|
-
README.md[2K[1G[90mREADME.md[39m 26ms (unchanged)
|
|
23
|
-
src/index.ts[2K[1G[90msrc/index.ts[39m 4ms (unchanged)
|
|
24
|
-
src/metrics.types.ts[2K[1G[90msrc/metrics.types.ts[39m 14ms (unchanged)
|
|
25
|
-
src/provider-stats.test.ts[2K[1G[90msrc/provider-stats.test.ts[39m 8ms (unchanged)
|
|
26
|
-
src/task-manager.mock.ts[2K[1G[90msrc/task-manager.mock.ts[39m 13ms (unchanged)
|
|
27
|
-
src/task-manager.test.ts[2K[1G[90msrc/task-manager.test.ts[39m 48ms (unchanged)
|
|
28
|
-
src/task-manager.ts[2K[1G[90msrc/task-manager.ts[39m 27ms (unchanged)
|
|
29
|
-
src/task-manager.types.ts[2K[1G[90msrc/task-manager.types.ts[39m 9ms (unchanged)
|
|
30
|
-
tsconfig.json[2K[1G[90mtsconfig.json[39m 2ms (unchanged)
|
|
6
|
+
.prettierignore[2K[1G.turbo/turbo-build.log[2K[1G.turbo/turbo-format.log[2K[1G.turbo/turbo-install.log[2K[1G.turbo/turbo-lint.log[2K[1G.turbo/turbo-lint$colon$fix.log[2K[1G.turbo/turbo-test.log[2K[1G.turbo/turbo-typecheck.log[2K[1GCHANGELOG.md[2K[1G[90mCHANGELOG.md[39m 81ms (unchanged)
|
|
7
|
+
eslint.config.js[2K[1G[90meslint.config.js[39m 290ms (unchanged)
|
|
8
|
+
package.json[2K[1G[90mpackage.json[39m 6ms (unchanged)
|
|
9
|
+
README.md[2K[1G[90mREADME.md[39m 133ms (unchanged)
|
|
10
|
+
src/index.ts[2K[1G[90msrc/index.ts[39m 27ms (unchanged)
|
|
11
|
+
src/metrics.types.ts[2K[1G[90msrc/metrics.types.ts[39m 13ms (unchanged)
|
|
12
|
+
src/provider-stats.test.ts[2K[1G[90msrc/provider-stats.test.ts[39m 129ms (unchanged)
|
|
13
|
+
src/task-manager.mock.ts[2K[1G[90msrc/task-manager.mock.ts[39m 15ms (unchanged)
|
|
14
|
+
src/task-manager.test.ts[2K[1G[90msrc/task-manager.test.ts[39m 102ms (unchanged)
|
|
15
|
+
src/task-manager.ts[2K[1G[90msrc/task-manager.ts[39m 13ms (unchanged)
|
|
16
|
+
src/task-manager.types.ts[2K[1G[90msrc/task-manager.types.ts[39m 28ms (unchanged)
|
|
17
|
+
tsconfig.json[2K[1G[90mtsconfig.json[39m 4ms (unchanged)
|
|
31
18
|
tsconfig.tsbuildinfo[2K[1Gvitest.config.ts[2K[1G[90mvitest.config.ts[39m 4ms (unchanged)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
> @opentask/taskin-task-manager@1.0.8 lint:fix /Users/sidarta/repositorios/taskin/packages/task-manager
|
|
3
|
+
> eslint . --fix
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/Users/sidarta/repositorios/taskin/packages/task-manager/src/provider-stats.test.ts
|
|
7
|
+
7:65 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
|
|
8
|
+
8:65 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
|
|
9
|
+
9:65 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
|
|
10
|
+
|
|
11
|
+
✖ 3 problems (0 errors, 3 warnings)
|
|
12
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
> @opentask/taskin-task-manager@2.0.0 lint /Users/sidarta/repositorios/taskin/packages/task-manager
|
|
4
|
+
> eslint .
|
|
5
|
+
|
|
6
|
+
[0m
|
|
7
|
+
[4m/Users/sidarta/repositorios/taskin/packages/task-manager/src/provider-stats.test.ts[24m
|
|
8
|
+
[2m7:65[22m [33mwarning[39m Unexpected any. Specify a different type [2m@typescript-eslint/no-explicit-any[22m
|
|
9
|
+
[2m8:65[22m [33mwarning[39m Unexpected any. Specify a different type [2m@typescript-eslint/no-explicit-any[22m
|
|
10
|
+
[2m9:65[22m [33mwarning[39m Unexpected any. Specify a different type [2m@typescript-eslint/no-explicit-any[22m
|
|
11
|
+
|
|
12
|
+
[33m[1m✖ 3 problems (0 errors, 3 warnings)[22m[39m
|
|
13
|
+
[0m
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
|
|
2
|
-
> @opentask/taskin-task-manager@
|
|
2
|
+
> @opentask/taskin-task-manager@2.0.0 test /Users/sidarta/repositorios/taskin/packages/task-manager
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[1m[46m RUN [49m[22m [36mv4.0.
|
|
6
|
+
[1m[46m RUN [49m[22m [36mv4.0.18 [39m[90m/Users/sidarta/repositorios/taskin/packages/task-manager[39m
|
|
7
7
|
|
|
8
|
-
[32m✓[39m src/provider-stats.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
9
|
-
[32m✓[39m src/task-manager.test.ts [2m([22m[
|
|
8
|
+
[32m✓[39m src/provider-stats.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 3[2mms[22m[39m
|
|
9
|
+
[32m✓[39m src/task-manager.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
10
10
|
|
|
11
11
|
[2m Test Files [22m [1m[32m2 passed[39m[22m[90m (2)[39m
|
|
12
|
-
[2m Tests [22m [1m[
|
|
13
|
-
[2m Start at [22m
|
|
14
|
-
[2m Duration [22m
|
|
12
|
+
[2m Tests [22m [1m[32m15 passed[39m[22m[90m (15)[39m
|
|
13
|
+
[2m Start at [22m 13:46:24
|
|
14
|
+
[2m Duration [22m 429ms[2m (transform 362ms, setup 0ms, import 414ms, tests 11ms, environment 0ms)[22m
|
|
15
15
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# @opentask/taskin-task-manager
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- feat(cli): implement review command with unified hook system
|
|
8
|
+
|
|
9
|
+
Add new `taskin review` command to prepare tasks for code review with automated quality checks.
|
|
10
|
+
|
|
11
|
+
**New Features:**
|
|
12
|
+
- Add `review` command to transition tasks from in-progress to in-review status
|
|
13
|
+
- Implement unified hook system supporting pre/during/post phases for all commands
|
|
14
|
+
- Add config-manager for .taskin.json hook configuration
|
|
15
|
+
- Add reviewTask() method to TaskManager
|
|
16
|
+
- Add comprehensive TypeScript schemas and types for hooks and configuration
|
|
17
|
+
|
|
18
|
+
**UX Improvements:**
|
|
19
|
+
- Standardize --open flag semantics across list and dashboard commands
|
|
20
|
+
- Add --browser/-b flag for launching browser in dashboard
|
|
21
|
+
- Remove redundant --filter-open and --filter-closed flags
|
|
22
|
+
|
|
23
|
+
**Build Fixes:**
|
|
24
|
+
- Add composite:true to CLI tsconfig for project references
|
|
25
|
+
- Add @modelcontextprotocol/sdk as direct dependency
|
|
26
|
+
- Fix VS Code TypeScript Language Server cache issues
|
|
27
|
+
|
|
28
|
+
**BREAKING CHANGE:**
|
|
29
|
+
|
|
30
|
+
The `--open` flag in `taskin dashboard` now filters open tasks (consistent with list command) instead of opening a browser. Use the new `--browser` or `-b` flag to open the browser automatically.
|
|
31
|
+
|
|
32
|
+
**New Files:**
|
|
33
|
+
- packages/cli/src/commands/review.ts (321 lines)
|
|
34
|
+
- packages/cli/src/lib/hook-runner.ts (119 lines)
|
|
35
|
+
- packages/cli/src/lib/hook-runner.test.ts (242 lines)
|
|
36
|
+
- packages/cli/src/lib/config-manager.ts (46 lines)
|
|
37
|
+
- packages/types-ts/src/taskin.schemas.ts (+137 lines)
|
|
38
|
+
- packages/types-ts/src/taskin.types.ts (+108 lines)
|
|
39
|
+
|
|
40
|
+
Closes #014
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- Updated dependencies
|
|
45
|
+
- @opentask/taskin-types@1.1.0
|
|
46
|
+
|
|
47
|
+
## 1.0.9
|
|
48
|
+
|
|
49
|
+
### Patch Changes
|
|
50
|
+
|
|
51
|
+
- Updated dependencies
|
|
52
|
+
- @opentask/taskin-types@1.0.6
|
|
53
|
+
|
|
3
54
|
## 1.0.8
|
|
4
55
|
|
|
5
56
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
describe('IMetricsManager contract', () => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
it('accepts an object implementing IMetricsManager', async () => {
|
|
4
|
+
const metrics = {
|
|
5
|
+
getUserMetrics: async (userId) => ({ userId }),
|
|
6
|
+
getTeamMetrics: async (teamId) => ({ teamId }),
|
|
7
|
+
getTaskMetrics: async (taskId) => ({ taskId }),
|
|
8
|
+
};
|
|
9
|
+
expect(typeof metrics.getUserMetrics).toBe('function');
|
|
10
|
+
expect(typeof metrics.getTeamMetrics).toBe('function');
|
|
11
|
+
expect(typeof metrics.getTaskMetrics).toBe('function');
|
|
12
|
+
await expect(metrics.getUserMetrics('u1')).resolves.toBeDefined();
|
|
13
|
+
await expect(metrics.getTeamMetrics('t1')).resolves.toBeDefined();
|
|
14
|
+
await expect(metrics.getTaskMetrics('task1')).resolves.toBeDefined();
|
|
15
|
+
});
|
|
16
16
|
});
|
|
17
|
-
//# sourceMappingURL=provider-stats.test.js.map
|
|
17
|
+
//# sourceMappingURL=provider-stats.test.js.map
|
package/dist/task-manager.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
CreateTaskOptions,
|
|
3
|
-
CreateTaskResult,
|
|
4
|
-
ITaskManager,
|
|
5
|
-
ITaskProvider,
|
|
6
|
-
LintResult,
|
|
7
|
-
TaskFile,
|
|
8
|
-
} from './task-manager.types';
|
|
1
|
+
import type { CreateTaskOptions, CreateTaskResult, ITaskManager, ITaskProvider, LintResult, TaskFile } from './task-manager.types';
|
|
9
2
|
export declare class TaskManager implements ITaskManager {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
private taskProvider;
|
|
4
|
+
constructor(taskProvider: ITaskProvider);
|
|
5
|
+
startTask(taskId: string): Promise<TaskFile>;
|
|
6
|
+
finishTask(taskId: string): Promise<TaskFile>;
|
|
7
|
+
reviewTask(taskId: string): Promise<TaskFile>;
|
|
8
|
+
createTask(options: CreateTaskOptions): Promise<CreateTaskResult>;
|
|
9
|
+
lint(fix?: boolean): Promise<LintResult>;
|
|
16
10
|
}
|
package/dist/task-manager.js
CHANGED
|
@@ -1,37 +1,49 @@
|
|
|
1
1
|
export class TaskManager {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
async startTask(taskId) {
|
|
7
|
-
const task = await this.taskProvider.findTask(taskId);
|
|
8
|
-
if (!task) {
|
|
9
|
-
throw new Error(`Task with ID '${taskId}' not found.`);
|
|
2
|
+
taskProvider;
|
|
3
|
+
constructor(taskProvider) {
|
|
4
|
+
this.taskProvider = taskProvider;
|
|
10
5
|
}
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
async startTask(taskId) {
|
|
7
|
+
const task = await this.taskProvider.findTask(taskId);
|
|
8
|
+
if (!task) {
|
|
9
|
+
throw new Error(`Task with ID '${taskId}' not found.`);
|
|
10
|
+
}
|
|
11
|
+
if (task.status === 'in-progress') {
|
|
12
|
+
throw new Error(`Task '${taskId}' is already in progress.`);
|
|
13
|
+
}
|
|
14
|
+
if (task.status === 'done') {
|
|
15
|
+
throw new Error(`Task '${taskId}' is already done.`);
|
|
16
|
+
}
|
|
17
|
+
const updatedTask = { ...task, status: 'in-progress' };
|
|
18
|
+
await this.taskProvider.updateTask(updatedTask);
|
|
19
|
+
return updatedTask;
|
|
13
20
|
}
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
async finishTask(taskId) {
|
|
22
|
+
const task = await this.taskProvider.findTask(taskId);
|
|
23
|
+
if (!task) {
|
|
24
|
+
throw new Error(`Task with ID '${taskId}' not found.`);
|
|
25
|
+
}
|
|
26
|
+
const updatedTask = { ...task, status: 'done' };
|
|
27
|
+
await this.taskProvider.updateTask(updatedTask);
|
|
28
|
+
return updatedTask;
|
|
16
29
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
async reviewTask(taskId) {
|
|
31
|
+
const task = await this.taskProvider.findTask(taskId);
|
|
32
|
+
if (!task) {
|
|
33
|
+
throw new Error(`Task with ID '${taskId}' not found.`);
|
|
34
|
+
}
|
|
35
|
+
if (task.status !== 'in-progress') {
|
|
36
|
+
throw new Error(`Task '${taskId}' must be in 'in-progress' status to be reviewed. Current status: ${task.status}`);
|
|
37
|
+
}
|
|
38
|
+
const updatedTask = { ...task, status: 'in-review' };
|
|
39
|
+
await this.taskProvider.updateTask(updatedTask);
|
|
40
|
+
return updatedTask;
|
|
41
|
+
}
|
|
42
|
+
async createTask(options) {
|
|
43
|
+
return this.taskProvider.createTask(options);
|
|
44
|
+
}
|
|
45
|
+
async lint(fix) {
|
|
46
|
+
return this.taskProvider.lint(fix);
|
|
25
47
|
}
|
|
26
|
-
const updatedTask = { ...task, status: 'done' };
|
|
27
|
-
await this.taskProvider.updateTask(updatedTask);
|
|
28
|
-
return updatedTask;
|
|
29
|
-
}
|
|
30
|
-
async createTask(options) {
|
|
31
|
-
return this.taskProvider.createTask(options);
|
|
32
|
-
}
|
|
33
|
-
async lint(fix) {
|
|
34
|
-
return this.taskProvider.lint(fix);
|
|
35
|
-
}
|
|
36
48
|
}
|
|
37
|
-
//# sourceMappingURL=task-manager.js.map
|
|
49
|
+
//# sourceMappingURL=task-manager.js.map
|
package/dist/task-manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-manager.js","sourceRoot":"","sources":["../src/task-manager.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,WAAW;IACF;IAApB,YAAoB,YAA2B;QAA3B,iBAAY,GAAZ,YAAY,CAAe;IAAG,CAAC;IAEnD,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,2BAA2B,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,oBAAoB,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QACjE,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAA0B;QACzC,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAa;QACtB,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"task-manager.js","sourceRoot":"","sources":["../src/task-manager.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,WAAW;IACF;IAApB,YAAoB,YAA2B;QAA3B,iBAAY,GAAZ,YAAY,CAAe;IAAG,CAAC;IAEnD,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,2BAA2B,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,oBAAoB,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;QACjE,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC1D,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,cAAc,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,SAAS,MAAM,qEAAqE,IAAI,CAAC,MAAM,EAAE,CAClG,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GAAa,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAC/D,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAA0B;QACzC,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAa;QACtB,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
2
|
export const createMockTask = (overrides) => ({
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
content: '# Task 001 - Implement feature',
|
|
4
|
+
createdAt: new Date().toISOString(),
|
|
5
|
+
description: 'A test feature',
|
|
6
|
+
filePath: '/tasks/task-001.md',
|
|
7
|
+
id: 'task-001',
|
|
8
|
+
status: 'pending',
|
|
9
|
+
title: 'Implement feature',
|
|
10
|
+
type: 'feat',
|
|
11
|
+
userId: 'user-123',
|
|
12
|
+
...overrides,
|
|
13
13
|
});
|
|
14
14
|
export const createMockTaskProvider = () => ({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
findTask: vi.fn(),
|
|
16
|
+
getAllTasks: vi.fn(),
|
|
17
|
+
updateTask: vi.fn(),
|
|
18
|
+
createTask: vi.fn(),
|
|
19
|
+
lint: vi.fn(),
|
|
20
|
+
initialize: vi.fn(),
|
|
20
21
|
});
|
|
21
|
-
//# sourceMappingURL=task-manager.mock.js.map
|
|
22
|
+
//# sourceMappingURL=task-manager.mock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-manager.mock.js","sourceRoot":"","sources":["../src/task-manager.mock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG5B,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAA6B,EAAY,EAAE,CAAC,CAAC;IAC1E,OAAO,EAAE,gCAAgC;IACzC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IACnC,WAAW,EAAE,gBAAgB;IAC7B,QAAQ,EAAE,oBAAoB;IAC9B,EAAE,EAAE,UAAqC;IACzC,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,mBAAmB;IAC1B,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,UAAU;IAClB,GAAG,SAAS;CACb,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAkB,EAAE,CAAC,CAAC;IAC1D,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;IACjB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;IACpB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"task-manager.mock.js","sourceRoot":"","sources":["../src/task-manager.mock.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG5B,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAA6B,EAAY,EAAE,CAAC,CAAC;IAC1E,OAAO,EAAE,gCAAgC;IACzC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;IACnC,WAAW,EAAE,gBAAgB;IAC7B,QAAQ,EAAE,oBAAoB;IAC9B,EAAE,EAAE,UAAqC;IACzC,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,mBAAmB;IAC1B,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,UAAU;IAClB,GAAG,SAAS;CACb,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAkB,EAAE,CAAC,CAAC;IAC1D,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;IACjB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;IACpB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;IACnB,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;IACb,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;CACpB,CAAC,CAAC"}
|
|
@@ -2,103 +2,124 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
2
2
|
import { TaskManager } from './task-manager';
|
|
3
3
|
import { createMockTask, createMockTaskProvider } from './task-manager.mock';
|
|
4
4
|
describe('TaskManager', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
});
|
|
14
|
-
describe('startTask', () => {
|
|
15
|
-
it('should start a pending task', async () => {
|
|
16
|
-
mockTaskProvider.findTask.mockResolvedValue(mockTask);
|
|
17
|
-
const updatedTask = await taskManager.startTask('task-001');
|
|
18
|
-
expect(mockTaskProvider.findTask).toHaveBeenCalledWith('task-001');
|
|
19
|
-
expect(mockTaskProvider.updateTask).toHaveBeenCalledWith(
|
|
20
|
-
expect.objectContaining({ status: 'in-progress' }),
|
|
21
|
-
);
|
|
22
|
-
expect(updatedTask.status).toBe('in-progress');
|
|
5
|
+
let taskManager;
|
|
6
|
+
let mockTaskProvider;
|
|
7
|
+
let mockTask;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
vi.clearAllMocks();
|
|
10
|
+
mockTaskProvider = createMockTaskProvider();
|
|
11
|
+
mockTask = createMockTask();
|
|
12
|
+
taskManager = new TaskManager(mockTaskProvider);
|
|
23
13
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
describe('startTask', () => {
|
|
15
|
+
it('should start a pending task', async () => {
|
|
16
|
+
mockTaskProvider.findTask.mockResolvedValue(mockTask);
|
|
17
|
+
const updatedTask = await taskManager.startTask('task-001');
|
|
18
|
+
expect(mockTaskProvider.findTask).toHaveBeenCalledWith('task-001');
|
|
19
|
+
expect(mockTaskProvider.updateTask).toHaveBeenCalledWith(expect.objectContaining({ status: 'in-progress' }));
|
|
20
|
+
expect(updatedTask.status).toBe('in-progress');
|
|
21
|
+
});
|
|
22
|
+
it('should throw an error if task is not found', async () => {
|
|
23
|
+
mockTaskProvider.findTask.mockResolvedValue(undefined);
|
|
24
|
+
await expect(taskManager.startTask('not-found')).rejects.toThrow("Task with ID 'not-found' not found.");
|
|
25
|
+
});
|
|
26
|
+
it('should throw an error if task is already in progress', async () => {
|
|
27
|
+
const inProgressTask = { ...mockTask, status: 'in-progress' };
|
|
28
|
+
mockTaskProvider.findTask.mockResolvedValue(inProgressTask);
|
|
29
|
+
await expect(taskManager.startTask('task-001')).rejects.toThrow("Task 'task-001' is already in progress.");
|
|
30
|
+
});
|
|
29
31
|
});
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
describe('finishTask', () => {
|
|
33
|
+
it('should finish an in-progress task', async () => {
|
|
34
|
+
const inProgressTask = { ...mockTask, status: 'in-progress' };
|
|
35
|
+
mockTaskProvider.findTask.mockResolvedValue(inProgressTask);
|
|
36
|
+
const updatedTask = await taskManager.finishTask('task-001');
|
|
37
|
+
expect(mockTaskProvider.updateTask).toHaveBeenCalledWith(expect.objectContaining({ status: 'done' }));
|
|
38
|
+
expect(updatedTask.status).toBe('done');
|
|
39
|
+
});
|
|
36
40
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
describe('reviewTask', () => {
|
|
42
|
+
it('should change status to in-review for an in-progress task', async () => {
|
|
43
|
+
const inProgressTask = { ...mockTask, status: 'in-progress' };
|
|
44
|
+
mockTaskProvider.findTask.mockResolvedValue(inProgressTask);
|
|
45
|
+
const updatedTask = await taskManager.reviewTask('task-001');
|
|
46
|
+
expect(mockTaskProvider.findTask).toHaveBeenCalledWith('task-001');
|
|
47
|
+
expect(mockTaskProvider.updateTask).toHaveBeenCalledWith(expect.objectContaining({ status: 'in-review' }));
|
|
48
|
+
expect(updatedTask.status).toBe('in-review');
|
|
49
|
+
});
|
|
50
|
+
it('should throw an error if task is not found', async () => {
|
|
51
|
+
mockTaskProvider.findTask.mockResolvedValue(undefined);
|
|
52
|
+
await expect(taskManager.reviewTask('not-found')).rejects.toThrow("Task with ID 'not-found' not found.");
|
|
53
|
+
});
|
|
54
|
+
it('should throw an error if task is not in-progress', async () => {
|
|
55
|
+
const pendingTask = { ...mockTask, status: 'pending' };
|
|
56
|
+
mockTaskProvider.findTask.mockResolvedValue(pendingTask);
|
|
57
|
+
await expect(taskManager.reviewTask('task-001')).rejects.toThrow("Task 'task-001' must be in 'in-progress' status to be reviewed");
|
|
58
|
+
});
|
|
59
|
+
it('should throw an error if task is already done', async () => {
|
|
60
|
+
const doneTask = { ...mockTask, status: 'done' };
|
|
61
|
+
mockTaskProvider.findTask.mockResolvedValue(doneTask);
|
|
62
|
+
await expect(taskManager.reviewTask('task-001')).rejects.toThrow("Task 'task-001' must be in 'in-progress' status to be reviewed");
|
|
63
|
+
});
|
|
64
|
+
it('should throw an error if task is already in-review', async () => {
|
|
65
|
+
const reviewTask = { ...mockTask, status: 'in-review' };
|
|
66
|
+
mockTaskProvider.findTask.mockResolvedValue(reviewTask);
|
|
67
|
+
await expect(taskManager.reviewTask('task-001')).rejects.toThrow("Task 'task-001' must be in 'in-progress' status to be reviewed");
|
|
68
|
+
});
|
|
47
69
|
});
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
describe('createTask', () => {
|
|
71
|
+
it('should delegate task creation to provider', async () => {
|
|
72
|
+
const createOptions = { title: 'New Task', type: 'feat' };
|
|
73
|
+
const createResult = {
|
|
74
|
+
task: mockTask,
|
|
75
|
+
taskId: '001',
|
|
76
|
+
filePath: '/tasks/task-001.md',
|
|
77
|
+
};
|
|
78
|
+
mockTaskProvider.createTask.mockResolvedValue(createResult);
|
|
79
|
+
const result = await taskManager.createTask(createOptions);
|
|
80
|
+
expect(mockTaskProvider.createTask).toHaveBeenCalledWith(createOptions);
|
|
81
|
+
expect(result).toEqual(createResult);
|
|
82
|
+
});
|
|
83
|
+
it('should pass through description and assignee to provider', async () => {
|
|
84
|
+
const createOptions = {
|
|
85
|
+
title: 'New Task',
|
|
86
|
+
type: 'fix',
|
|
87
|
+
description: 'Fix something',
|
|
88
|
+
assignee: 'john-doe',
|
|
89
|
+
};
|
|
90
|
+
const createResult = {
|
|
91
|
+
task: mockTask,
|
|
92
|
+
taskId: '002',
|
|
93
|
+
filePath: '/tasks/task-002.md',
|
|
94
|
+
};
|
|
95
|
+
mockTaskProvider.createTask.mockResolvedValue(createResult);
|
|
96
|
+
const result = await taskManager.createTask(createOptions);
|
|
97
|
+
expect(mockTaskProvider.createTask).toHaveBeenCalledWith(createOptions);
|
|
98
|
+
expect(result.taskId).toBe('002');
|
|
99
|
+
});
|
|
61
100
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
describe('lint', () => {
|
|
102
|
+
it('should delegate lint without fix to provider', async () => {
|
|
103
|
+
const lintResult = { errors: 0, warnings: 2, details: [] };
|
|
104
|
+
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
105
|
+
const result = await taskManager.lint();
|
|
106
|
+
expect(mockTaskProvider.lint).toHaveBeenCalledWith(undefined);
|
|
107
|
+
expect(result).toEqual(lintResult);
|
|
108
|
+
});
|
|
109
|
+
it('should delegate lint with fix=true to provider', async () => {
|
|
110
|
+
const lintResult = { errors: 0, warnings: 0, details: [] };
|
|
111
|
+
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
112
|
+
const result = await taskManager.lint(true);
|
|
113
|
+
expect(mockTaskProvider.lint).toHaveBeenCalledWith(true);
|
|
114
|
+
expect(result).toEqual(lintResult);
|
|
115
|
+
});
|
|
116
|
+
it('should delegate lint with fix=false to provider', async () => {
|
|
117
|
+
const lintResult = { errors: 1, warnings: 2, details: [] };
|
|
118
|
+
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
119
|
+
const result = await taskManager.lint(false);
|
|
120
|
+
expect(mockTaskProvider.lint).toHaveBeenCalledWith(false);
|
|
121
|
+
expect(result).toEqual(lintResult);
|
|
122
|
+
});
|
|
78
123
|
});
|
|
79
|
-
});
|
|
80
|
-
describe('lint', () => {
|
|
81
|
-
it('should delegate lint without fix to provider', async () => {
|
|
82
|
-
const lintResult = { errors: 0, warnings: 2, details: [] };
|
|
83
|
-
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
84
|
-
const result = await taskManager.lint();
|
|
85
|
-
expect(mockTaskProvider.lint).toHaveBeenCalledWith(undefined);
|
|
86
|
-
expect(result).toEqual(lintResult);
|
|
87
|
-
});
|
|
88
|
-
it('should delegate lint with fix=true to provider', async () => {
|
|
89
|
-
const lintResult = { errors: 0, warnings: 0, details: [] };
|
|
90
|
-
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
91
|
-
const result = await taskManager.lint(true);
|
|
92
|
-
expect(mockTaskProvider.lint).toHaveBeenCalledWith(true);
|
|
93
|
-
expect(result).toEqual(lintResult);
|
|
94
|
-
});
|
|
95
|
-
it('should delegate lint with fix=false to provider', async () => {
|
|
96
|
-
const lintResult = { errors: 1, warnings: 2, details: [] };
|
|
97
|
-
mockTaskProvider.lint.mockResolvedValue(lintResult);
|
|
98
|
-
const result = await taskManager.lint(false);
|
|
99
|
-
expect(mockTaskProvider.lint).toHaveBeenCalledWith(false);
|
|
100
|
-
expect(result).toEqual(lintResult);
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
124
|
});
|
|
104
|
-
//# sourceMappingURL=task-manager.test.js.map
|
|
125
|
+
//# sourceMappingURL=task-manager.test.js.map
|