gitforest 0.1.0 → 1.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/LICENSE +21 -0
- package/package.json +24 -4
- package/src/github/auth.ts +3 -3
- package/src/utils/debug.ts +4 -4
- package/.bunignore +0 -7
- package/.github/workflows/ci.yml +0 -73
- package/CLAUDE.md +0 -111
- package/CONTRIBUTING.md +0 -145
- package/bun.lock +0 -267
- package/bunfig.toml +0 -15
- package/cli +0 -0
- package/docs/ai/IMPROVEMENT_PLAN.md +0 -341
- package/docs/ai/VERIFICATION_REPORT.md +0 -87
- package/docs/ai/architecture.md +0 -169
- package/docs/ai/checks/check-2025-12-02-tests.md +0 -40
- package/docs/ai/checks/check-2025-12-02.md +0 -55
- package/docs/ai/checks/test-verification-report.md +0 -85
- package/docs/ai/implementation-guide.md +0 -776
- package/docs/ai/research/gitty-codebase-analysis.md +0 -221
- package/docs/ai/tickets/GENERAL-sitrep.md +0 -30
- package/docs/ai/tickets/TASK-database-tests-sitrep.md +0 -25
- package/docs/ai/tickets/TASK-deprecated-functions-sitrep.md +0 -28
- package/docs/ai/tickets/TASK-detail-modal-sitrep.md +0 -28
- package/docs/ai/tickets/TASK-filter-overlay-sitrep.md +0 -24
- package/docs/ai/tickets/TASK-github-service-sitrep.md +0 -32
- package/docs/ai/tickets/TASK-github-token-sitrep.md +0 -51
- package/docs/ai/tickets/TASK-hascommits-sitrep.md +0 -35
- package/docs/ai/tickets/TASK-keybindings-sitrep.md +0 -26
- package/docs/ai/tickets/TASK-layout-sitrep.md +0 -25
- package/docs/ai/tickets/TASK-markdown-sitrep.md +0 -28
- package/docs/ai/tickets/TASK-project-item-sitrep.md +0 -79
- package/docs/ai/tickets/TASK-sitrep.md +0 -28
- package/docs/ai/tickets/TASK-state-sitrep.md +0 -26
- package/docs/ai/tickets/TASK-types-sitrep.md +0 -25
- package/docs/ai/tickets/TASK-unified-item-fix-sitrep.md +0 -26
- package/docs/ai/tickets/TKT-001-sitrep.md +0 -24
- package/docs/ai/tickets/TKT-002-sitrep.md +0 -25
- package/docs/ai/tickets/TKT-003-git-service-refactoring-complete.md +0 -46
- package/docs/ai/tickets/TKT-003-git-service-refactoring-plan.md +0 -135
- package/docs/ai/tickets/TKT-003-sitrep.md +0 -26
- package/docs/ai/tickets/TKT-004-sitrep.md +0 -27
- package/docs/ai/tickets/TKT-005-sitrep.md +0 -25
- package/docs/ai/tickets/TKT-006-sitrep.md +0 -26
- package/docs/ai/tickets/TKT-007-sitrep.md +0 -30
- package/docs/ai/tickets/TKT-008-sitrep.md +0 -32
- package/docs/ai/tickets/TKT-009-sitrep.md +0 -27
- package/docs/ai/tickets/TKT-010-sitrep.md +0 -27
- package/docs/ai/tickets/TKT-011-sitrep.md +0 -26
- package/docs/ai/tickets/TKT-012-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-actions-sitrep.md +0 -28
- package/docs/ai/tickets/sitreps/TASK-actions-test-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-app-integration-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-background-fetch-sitrep.md +0 -24
- package/docs/ai/tickets/sitreps/TASK-background-fetch-test-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-batch-tests-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-bun-test-sitrep.md +0 -26
- package/docs/ai/tickets/sitreps/TASK-cache-tests-sitrep.md +0 -30
- package/docs/ai/tickets/sitreps/TASK-cli-tests-sitrep.md +0 -28
- package/docs/ai/tickets/sitreps/TASK-clone-error-handling-sitrep.md +0 -26
- package/docs/ai/tickets/sitreps/TASK-commands-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-component-tests-1-sitrep.md +0 -30
- package/docs/ai/tickets/sitreps/TASK-configloader-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-confirm-dialog-test-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-coverage-sitrep.md +0 -95
- package/docs/ai/tickets/sitreps/TASK-database-tests-summary.md +0 -61
- package/docs/ai/tickets/sitreps/TASK-error-boundary-sitrep.md +0 -30
- package/docs/ai/tickets/sitreps/TASK-error-tests-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-errors-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-extract-reducer-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-filter-overlay-test-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-final-verification-sitrep.md +0 -28
- package/docs/ai/tickets/sitreps/TASK-fix-all-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-fix-hooks-sitrep.md +0 -26
- package/docs/ai/tickets/sitreps/TASK-fix-remaining-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-fix-test-failures-sitrep.md +0 -26
- package/docs/ai/tickets/sitreps/TASK-fix-tests-sitrep.md +0 -24
- package/docs/ai/tickets/sitreps/TASK-formatters-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-git-timeouts-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-github-cache-test-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-githubcli-tests-sitrep.md +0 -24
- package/docs/ai/tickets/sitreps/TASK-gitstatus-tests-sitrep.md +0 -24
- package/docs/ai/tickets/sitreps/TASK-hooks-isolation-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-keybindings-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-layout-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-mock-factories-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-modal-tests-sitrep.md +0 -32
- package/docs/ai/tickets/sitreps/TASK-processbatch-fix-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-projectlist-tests-sitrep.md +0 -30
- package/docs/ai/tickets/sitreps/TASK-projectutils-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-scanner-tests-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-select-all-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-shell-error-handling-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-store-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-test-fixes-sitrep.md +0 -26
- package/docs/ai/tickets/sitreps/TASK-test-summary-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-test-verification-sitrep.md +0 -27
- package/docs/ai/tickets/sitreps/TASK-testsuite-sitrep.md +0 -75
- package/docs/ai/tickets/sitreps/TASK-unified-reducer-tests-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-unified-repos-test-sitrep.md +0 -29
- package/docs/ai/tickets/sitreps/TASK-unified-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-useprojects-tests-sitrep.md +0 -25
- package/docs/ai/tickets/sitreps/TASK-utility-tests-sitrep.md +0 -32
- package/docs/ai/tickets/sitreps/TKT-003-git-service-refactoring-sitrep.md +0 -64
- package/docs/ai/tkt-001-fix-database-error.md +0 -217
- package/docs/ai/ui-enhancement-plan.md +0 -562
- package/test/integration/app.isolated.tsx +0 -240
- package/test/integration/cli-commands.test.ts +0 -287
- package/test/integration/cli-validation.test.ts +0 -264
- package/test/integration/git-operations.test.ts +0 -218
- package/test/integration/scanner.test.ts +0 -228
- package/test/preload.ts +0 -18
- package/test/unit/cli/commands.test.ts +0 -13
- package/test/unit/cli/formatters.test.ts +0 -1116
- package/test/unit/cli/github-commands.test.ts +0 -12
- package/test/unit/components/CloneDialog.test.tsx +0 -240
- package/test/unit/components/ColumnHeader.test.tsx +0 -128
- package/test/unit/components/CommandPalette.test.tsx +0 -355
- package/test/unit/components/ConfirmDialog.test.tsx +0 -111
- package/test/unit/components/ErrorBoundary.test.tsx +0 -139
- package/test/unit/components/FilterBar.test.tsx +0 -43
- package/test/unit/components/FilterOptionsOverlay.test.tsx +0 -197
- package/test/unit/components/HelpOverlay.test.tsx +0 -90
- package/test/unit/components/Layout.test.tsx +0 -328
- package/test/unit/components/MarkdownRenderer.test.tsx +0 -45
- package/test/unit/components/ProgressBar.test.tsx +0 -138
- package/test/unit/components/ProjectItem.test.tsx +0 -182
- package/test/unit/components/ProjectList.test.tsx +0 -311
- package/test/unit/components/RepoDetailModal.test.tsx +0 -445
- package/test/unit/components/StatusBar.test.tsx +0 -112
- package/test/unit/components/UnifiedProjectItem.test.tsx +0 -618
- package/test/unit/components/ViewModeIndicator.test.tsx +0 -137
- package/test/unit/components/test-utils.tsx +0 -63
- package/test/unit/config/loader.test.ts +0 -692
- package/test/unit/db/database.test.ts +0 -978
- package/test/unit/db/index.test.ts +0 -314
- package/test/unit/fixtures/setup.ts +0 -186
- package/test/unit/git/commands-untested.test.ts +0 -205
- package/test/unit/git/commands.test.ts +0 -269
- package/test/unit/git/operations.test.ts +0 -322
- package/test/unit/git/status.test.ts +0 -219
- package/test/unit/github/auth.test.ts +0 -317
- package/test/unit/github/cache.test.ts +0 -1028
- package/test/unit/github/cli.test.ts +0 -135
- package/test/unit/github/unified.test.ts +0 -1201
- package/test/unit/graceful-shutdown.test.ts +0 -83
- package/test/unit/hooks/useBackgroundFetch.test.tsx +0 -239
- package/test/unit/hooks/useConfirmDialogActions.test.tsx +0 -81
- package/test/unit/hooks/useKeyBindings.isolated.ts +0 -715
- package/test/unit/hooks/useProjects.test.tsx +0 -186
- package/test/unit/hooks/useUnifiedRepos-simple.test.tsx +0 -115
- package/test/unit/hooks/useUnifiedRepos.test.tsx +0 -177
- package/test/unit/mocks/config.ts +0 -109
- package/test/unit/mocks/git-service.ts +0 -274
- package/test/unit/mocks/github-service.ts +0 -250
- package/test/unit/mocks/index.ts +0 -72
- package/test/unit/mocks/project.ts +0 -148
- package/test/unit/mocks/state-mocks.ts +0 -187
- package/test/unit/mocks/unified.ts +0 -169
- package/test/unit/operations/batch.test.ts +0 -216
- package/test/unit/operations/commands.test.ts +0 -550
- package/test/unit/scanner/errors.test.ts +0 -297
- package/test/unit/scanner/index.test.ts +0 -1011
- package/test/unit/scanner/markers.test.ts +0 -150
- package/test/unit/scanner/submodules.test.ts +0 -99
- package/test/unit/services/git-errors.test.ts +0 -190
- package/test/unit/services/git.test.ts +0 -442
- package/test/unit/services/github-errors.test.ts +0 -293
- package/test/unit/services/github.test.ts +0 -200
- package/test/unit/state/actions.test.ts +0 -217
- package/test/unit/state/reducer.test.ts +0 -745
- package/test/unit/state/store.test.tsx +0 -711
- package/test/unit/types/commands.test.ts +0 -220
- package/test/unit/types/schema.test.ts +0 -179
- package/test/unit/utils/array.test.ts +0 -73
- package/test/unit/utils/debug.test.ts +0 -23
- package/test/unit/utils/errors.test.ts +0 -295
- package/test/unit/utils/markdown.test.ts +0 -163
- package/test/unit/utils/project-utils.test.ts +0 -756
- package/test/unit/utils/rate-limiter.test.ts +0 -256
- package/test/unit/utils/retry.test.ts +0 -165
- package/test/unit/utils/strip-ansi.ts +0 -13
- package/test/unit/utils/timeout.test.ts +0 -93
- package/tsconfig.json +0 -29
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock factory for Project objects
|
|
3
|
-
* Provides configurable mock projects for testing
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Project } from "../../../src/types/index";
|
|
7
|
-
import { defaultMockStatus, createDirtyStatus, createAheadStatus } from "./git-service";
|
|
8
|
-
|
|
9
|
-
let projectIdCounter = 0;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Create a mock project for testing
|
|
13
|
-
*/
|
|
14
|
-
export function createMockProject(overrides?: Partial<Project>): Project {
|
|
15
|
-
projectIdCounter++;
|
|
16
|
-
const id = overrides?.id ?? `mock-project-${projectIdCounter}`;
|
|
17
|
-
const name = overrides?.name ?? `project-${projectIdCounter}`;
|
|
18
|
-
const type = overrides?.type ?? "git";
|
|
19
|
-
|
|
20
|
-
const baseProject: Project = {
|
|
21
|
-
id,
|
|
22
|
-
name,
|
|
23
|
-
path: overrides?.path ?? `/test/projects/${name}`,
|
|
24
|
-
type,
|
|
25
|
-
projectMarker: type === "non-git" ? (overrides?.projectMarker ?? "package.json") : null,
|
|
26
|
-
status: type !== "non-git" ? (overrides?.status ?? { ...defaultMockStatus }) : null,
|
|
27
|
-
submodule: null,
|
|
28
|
-
lastScanned: overrides?.lastScanned ?? new Date(),
|
|
29
|
-
lastModified: overrides?.lastModified ?? (type === "non-git" ? new Date() : null),
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
return { ...baseProject, ...overrides };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Create a clean git project (no changes)
|
|
37
|
-
*/
|
|
38
|
-
export function createCleanProject(name?: string): Project {
|
|
39
|
-
return createMockProject({
|
|
40
|
-
name: name ?? `clean-project-${++projectIdCounter}`,
|
|
41
|
-
type: "git",
|
|
42
|
-
status: { ...defaultMockStatus },
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Create a dirty git project (uncommitted changes)
|
|
48
|
-
*/
|
|
49
|
-
export function createDirtyProject(name?: string): Project {
|
|
50
|
-
return createMockProject({
|
|
51
|
-
name: name ?? `dirty-project-${++projectIdCounter}`,
|
|
52
|
-
type: "git",
|
|
53
|
-
status: createDirtyStatus(),
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Create a project with unpushed commits
|
|
59
|
-
*/
|
|
60
|
-
export function createAheadProject(name?: string, commits = 3): Project {
|
|
61
|
-
return createMockProject({
|
|
62
|
-
name: name ?? `ahead-project-${++projectIdCounter}`,
|
|
63
|
-
type: "git",
|
|
64
|
-
status: createAheadStatus(commits),
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Create a non-git project
|
|
70
|
-
*/
|
|
71
|
-
export function createNonGitProject(name?: string, marker = "package.json"): Project {
|
|
72
|
-
return createMockProject({
|
|
73
|
-
name: name ?? `non-git-project-${++projectIdCounter}`,
|
|
74
|
-
type: "non-git",
|
|
75
|
-
projectMarker: marker,
|
|
76
|
-
status: null,
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Create a submodule project
|
|
82
|
-
*/
|
|
83
|
-
export function createSubmoduleProject(
|
|
84
|
-
name?: string,
|
|
85
|
-
parentPath = "/test/parent"
|
|
86
|
-
): Project {
|
|
87
|
-
const submoduleName = name ?? `submodule-${++projectIdCounter}`;
|
|
88
|
-
return createMockProject({
|
|
89
|
-
name: submoduleName,
|
|
90
|
-
type: "git-submodule",
|
|
91
|
-
submodule: {
|
|
92
|
-
parentPath,
|
|
93
|
-
relativePath: submoduleName,
|
|
94
|
-
configuredCommit: "abc123def456",
|
|
95
|
-
currentCommit: "abc123def456",
|
|
96
|
-
isInitialized: true,
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Create a batch of diverse projects for testing
|
|
103
|
-
*/
|
|
104
|
-
export function createMockProjectBatch(): {
|
|
105
|
-
clean: Project[];
|
|
106
|
-
dirty: Project[];
|
|
107
|
-
ahead: Project[];
|
|
108
|
-
behind: Project[];
|
|
109
|
-
nonGit: Project[];
|
|
110
|
-
} {
|
|
111
|
-
return {
|
|
112
|
-
clean: [
|
|
113
|
-
createCleanProject("clean-1"),
|
|
114
|
-
createCleanProject("clean-2"),
|
|
115
|
-
],
|
|
116
|
-
dirty: [
|
|
117
|
-
createDirtyProject("dirty-1"),
|
|
118
|
-
createDirtyProject("dirty-2"),
|
|
119
|
-
],
|
|
120
|
-
ahead: [
|
|
121
|
-
createAheadProject("ahead-1", 2),
|
|
122
|
-
createAheadProject("ahead-2", 5),
|
|
123
|
-
],
|
|
124
|
-
behind: [
|
|
125
|
-
createMockProject({
|
|
126
|
-
name: "behind-1",
|
|
127
|
-
type: "git",
|
|
128
|
-
status: {
|
|
129
|
-
...defaultMockStatus,
|
|
130
|
-
unpulledCommits: 3,
|
|
131
|
-
isBehind: true,
|
|
132
|
-
isOutOfSync: true,
|
|
133
|
-
},
|
|
134
|
-
}),
|
|
135
|
-
],
|
|
136
|
-
nonGit: [
|
|
137
|
-
createNonGitProject("npm-project", "package.json"),
|
|
138
|
-
createNonGitProject("rust-project", "Cargo.toml"),
|
|
139
|
-
],
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Reset the project ID counter (useful between tests)
|
|
145
|
-
*/
|
|
146
|
-
export function resetProjectIdCounter(): void {
|
|
147
|
-
projectIdCounter = 0;
|
|
148
|
-
}
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Complete mock exports for state modules
|
|
3
|
-
*
|
|
4
|
-
* These exports include ALL functions from their respective modules
|
|
5
|
-
* to prevent incomplete module mocking from breaking other tests.
|
|
6
|
-
*
|
|
7
|
-
* When using mock.module(), use these complete exports to avoid
|
|
8
|
-
* "Export not found" errors when tests run together.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { mock } from "bun:test";
|
|
12
|
-
import type { Project, GitHubRepoInfo, UnifiedRepo } from "../../../src/types/index";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Complete mock for src/state/actions.ts
|
|
16
|
-
* Includes all 34 action creators
|
|
17
|
-
*/
|
|
18
|
-
export function createActionsMock() {
|
|
19
|
-
return {
|
|
20
|
-
// Project actions
|
|
21
|
-
setProjects: (payload: Project[]) => ({ type: "SET_PROJECTS", payload }),
|
|
22
|
-
setLoading: (payload: boolean) => ({ type: "SET_LOADING", payload }),
|
|
23
|
-
setError: (payload: string | null) => ({ type: "SET_ERROR", payload }),
|
|
24
|
-
setMessage: (payload: string | null) => ({ type: "SET_MESSAGE", payload }),
|
|
25
|
-
updateProject: (id: string, updates: Partial<Project>) => ({ type: "UPDATE_PROJECT", payload: { id, updates } }),
|
|
26
|
-
|
|
27
|
-
// Cursor and selection actions
|
|
28
|
-
moveCursor: (index: number) => ({ type: "MOVE_CURSOR", payload: index }),
|
|
29
|
-
toggleSelection: (index: number) => ({ type: "TOGGLE_SELECTION", payload: index }),
|
|
30
|
-
selectAll: () => ({ type: "SELECT_ALL" }),
|
|
31
|
-
deselectAll: () => ({ type: "DESELECT_ALL" }),
|
|
32
|
-
setScrollOffset: (offset: number) => ({ type: "SET_SCROLL_OFFSET", payload: offset }),
|
|
33
|
-
|
|
34
|
-
// Filter and sort actions
|
|
35
|
-
setFilter: (text: string) => ({ type: "SET_FILTER", payload: text }),
|
|
36
|
-
setSort: (by: string, direction: string) => ({ type: "SET_SORT", payload: { by, direction } }),
|
|
37
|
-
cycleSort: () => ({ type: "CYCLE_SORT" }),
|
|
38
|
-
setQuickFilter: (filter: string) => ({ type: "SET_QUICK_FILTER", payload: filter }),
|
|
39
|
-
setLanguageFilter: (language: string | null) => ({ type: "SET_LANGUAGE_FILTER", payload: language }),
|
|
40
|
-
|
|
41
|
-
// Mode actions
|
|
42
|
-
setMode: (mode: string) => ({ type: "SET_MODE", payload: mode }),
|
|
43
|
-
setViewMode: (mode: string) => ({ type: "SET_VIEW_MODE", payload: mode }),
|
|
44
|
-
|
|
45
|
-
// Action progress
|
|
46
|
-
startAction: (action: string) => ({ type: "START_ACTION", payload: action }),
|
|
47
|
-
endAction: () => ({ type: "END_ACTION" }),
|
|
48
|
-
updateProgress: (current: number, total: number) => ({ type: "UPDATE_PROGRESS", payload: { current, total } }),
|
|
49
|
-
|
|
50
|
-
// GitHub actions
|
|
51
|
-
setGitHubRepos: (repos: GitHubRepoInfo[]) => ({ type: "SET_GITHUB_REPOS", payload: repos }),
|
|
52
|
-
setUnifiedRepos: (repos: UnifiedRepo[]) => ({ type: "SET_UNIFIED_REPOS", payload: repos }),
|
|
53
|
-
setGitHubLoading: (loading: boolean) => ({ type: "SET_GITHUB_LOADING", payload: loading }),
|
|
54
|
-
setGitHubError: (error: string | null) => ({ type: "SET_GITHUB_ERROR", payload: error }),
|
|
55
|
-
setRefreshing: (refreshing: boolean) => ({ type: "SET_REFRESHING", payload: refreshing }),
|
|
56
|
-
|
|
57
|
-
// Clone dialog actions
|
|
58
|
-
showCloneDialog: (repos: UnifiedRepo[], directories: any[], selectedDirIndex: number, useSSH: boolean) =>
|
|
59
|
-
({ type: "SHOW_CLONE_DIALOG", payload: { repos, directories, selectedDirIndex, useSSH } }),
|
|
60
|
-
hideCloneDialog: () => ({ type: "HIDE_CLONE_DIALOG" }),
|
|
61
|
-
updateCloneDialog: (updates: any) => ({ type: "UPDATE_CLONE_DIALOG", payload: updates }),
|
|
62
|
-
cloneRepoStart: (repoId: string) => ({ type: "CLONE_REPO_START", payload: repoId }),
|
|
63
|
-
cloneRepoComplete: (id: string, localPath: string) => ({ type: "CLONE_REPO_COMPLETE", payload: { id, localPath } }),
|
|
64
|
-
cloneRepoFailed: (id: string, error: string) => ({ type: "CLONE_REPO_FAILED", payload: { id, error } }),
|
|
65
|
-
|
|
66
|
-
// Detail modal actions
|
|
67
|
-
showDetailModal: (modal: any) => ({ type: "SHOW_DETAIL_MODAL", payload: modal }),
|
|
68
|
-
hideDetailModal: () => ({ type: "HIDE_DETAIL_MODAL" }),
|
|
69
|
-
updateDetailModal: (updates: any) => ({ type: "UPDATE_DETAIL_MODAL", payload: updates }),
|
|
70
|
-
|
|
71
|
-
// Confirm dialog actions
|
|
72
|
-
showConfirmDialog: (dialog: any) => ({ type: "SHOW_CONFIRM_DIALOG", payload: dialog }),
|
|
73
|
-
hideConfirmDialog: () => ({ type: "HIDE_CONFIRM_DIALOG" }),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Complete mock for src/state/store.tsx
|
|
79
|
-
* Includes all exported hooks and components
|
|
80
|
-
*/
|
|
81
|
-
export function createStoreMock(stateGetter?: () => any, dispatch?: (action: any) => void) {
|
|
82
|
-
const defaultState = {
|
|
83
|
-
projects: [],
|
|
84
|
-
isLoading: false,
|
|
85
|
-
error: null,
|
|
86
|
-
message: null,
|
|
87
|
-
cursorIndex: 0,
|
|
88
|
-
selectedIndices: new Set(),
|
|
89
|
-
scrollOffset: 0,
|
|
90
|
-
filterText: "",
|
|
91
|
-
quickFilter: "all",
|
|
92
|
-
sortBy: "status",
|
|
93
|
-
sortDirection: "desc",
|
|
94
|
-
mode: "normal",
|
|
95
|
-
actionInProgress: null,
|
|
96
|
-
actionProgress: null,
|
|
97
|
-
confirmDialog: null,
|
|
98
|
-
viewMode: "combined",
|
|
99
|
-
detailModal: null,
|
|
100
|
-
cloneDialog: null,
|
|
101
|
-
refreshing: false,
|
|
102
|
-
unifiedRepos: [],
|
|
103
|
-
githubRepos: [],
|
|
104
|
-
isLoadingGitHub: false,
|
|
105
|
-
githubError: null,
|
|
106
|
-
isRefreshing: false,
|
|
107
|
-
languageFilter: null,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
useStore: () => ({
|
|
112
|
-
state: stateGetter ? stateGetter() : defaultState,
|
|
113
|
-
dispatch: dispatch || mock(() => {}),
|
|
114
|
-
}),
|
|
115
|
-
useFilteredProjects: () => [],
|
|
116
|
-
useSelectedProjects: () => [],
|
|
117
|
-
useFilteredUnifiedRepos: () => [],
|
|
118
|
-
useSelectedUnifiedRepos: () => [],
|
|
119
|
-
StoreProvider: ({ children }: { children: any }) => children,
|
|
120
|
-
StoreContext: { Provider: ({ children }: any) => children },
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Complete mock for src/scanner/index.ts
|
|
126
|
-
* Includes all exported functions
|
|
127
|
-
*/
|
|
128
|
-
export function createScannerMock() {
|
|
129
|
-
return {
|
|
130
|
-
scanAllDirectories: mock(() => Promise.resolve([])),
|
|
131
|
-
scanWithCache: mock(() => Promise.resolve([])),
|
|
132
|
-
sortProjects: (projects: any[]) => projects,
|
|
133
|
-
filterProjects: (projects: any[]) => projects,
|
|
134
|
-
getCacheStats: mock(() => Promise.resolve({ projectCount: 0, oldestScan: null, newestScan: null })),
|
|
135
|
-
clearCache: mock(() => Promise.resolve()),
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Complete mock for src/operations/batch.ts
|
|
141
|
-
* Includes all exported functions
|
|
142
|
-
*/
|
|
143
|
-
export function createBatchMock() {
|
|
144
|
-
const emptyResult = { total: 0, successful: 0, failed: 0, results: [], duration: 0 };
|
|
145
|
-
return {
|
|
146
|
-
batchPull: mock(() => Promise.resolve(emptyResult)),
|
|
147
|
-
batchPush: mock(() => Promise.resolve(emptyResult)),
|
|
148
|
-
batchFetch: mock(() => Promise.resolve(emptyResult)),
|
|
149
|
-
batchRefreshStatus: mock(() => Promise.resolve(emptyResult)),
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Complete mock for src/git/operations.ts
|
|
155
|
-
* Includes all exported functions
|
|
156
|
-
*/
|
|
157
|
-
export function createGitOperationsMock() {
|
|
158
|
-
return {
|
|
159
|
-
initGitInProject: mock(() => Promise.resolve({ success: true })),
|
|
160
|
-
getGitRemote: mock(() => Promise.resolve(null)),
|
|
161
|
-
setGitRemote: mock(() => Promise.resolve({ success: true })),
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Complete mock for src/github/cache.ts
|
|
167
|
-
* Includes all exported functions
|
|
168
|
-
*/
|
|
169
|
-
export function createGitHubCacheMock() {
|
|
170
|
-
return {
|
|
171
|
-
fetchGitHubReposWithCache: mock(() => Promise.resolve({ repos: [], error: null })),
|
|
172
|
-
loadGitHubReposFromCache: mock(() => Promise.resolve([])),
|
|
173
|
-
clearGitHubCache: mock(() => Promise.resolve()),
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Complete mock for src/github/unified.ts
|
|
179
|
-
* Includes all exported functions
|
|
180
|
-
*/
|
|
181
|
-
export function createGitHubUnifiedMock() {
|
|
182
|
-
return {
|
|
183
|
-
cloneGitHubRepo: mock(() => Promise.resolve({ success: true, path: "/test/path" })),
|
|
184
|
-
createUnifiedView: mock(() => []),
|
|
185
|
-
fetchUnifiedRepos: mock(() => Promise.resolve([])),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock factory for UnifiedRepo and related types
|
|
3
|
-
* Provides configurable mocks for unified repository view
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
UnifiedRepo,
|
|
8
|
-
GitHubRepoInfo,
|
|
9
|
-
UnifiedAppState,
|
|
10
|
-
Project
|
|
11
|
-
} from "../../../src/types/index";
|
|
12
|
-
import { createMockProject } from "./project";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Create a mock GitHub repository info
|
|
16
|
-
*/
|
|
17
|
-
export function createMockGitHubRepoInfo(overrides?: Partial<GitHubRepoInfo>): GitHubRepoInfo {
|
|
18
|
-
const name = overrides?.name ?? "test-repo";
|
|
19
|
-
const owner = overrides?.owner ?? "testuser";
|
|
20
|
-
const fullName = overrides?.fullName ?? `${owner}/${name}`;
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
name,
|
|
24
|
-
fullName,
|
|
25
|
-
owner,
|
|
26
|
-
description: overrides?.description ?? `A test repository: ${name}`,
|
|
27
|
-
htmlUrl: overrides?.htmlUrl ?? `https://github.com/${owner}/${name}`,
|
|
28
|
-
sshUrl: overrides?.sshUrl ?? `git@github.com:${owner}/${name}.git`,
|
|
29
|
-
cloneUrl: overrides?.cloneUrl ?? `https://github.com/${owner}/${name}.git`,
|
|
30
|
-
isPrivate: overrides?.isPrivate ?? false,
|
|
31
|
-
isArchived: overrides?.isArchived ?? false,
|
|
32
|
-
isFork: overrides?.isFork ?? false,
|
|
33
|
-
pushedAt: overrides?.pushedAt ?? new Date(),
|
|
34
|
-
updatedAt: overrides?.updatedAt ?? new Date(),
|
|
35
|
-
defaultBranch: overrides?.defaultBranch ?? "main",
|
|
36
|
-
language: overrides?.language ?? "TypeScript",
|
|
37
|
-
size: overrides?.size ?? 1024,
|
|
38
|
-
stargazersCount: overrides?.stargazersCount ?? 10,
|
|
39
|
-
forksCount: overrides?.forksCount ?? 5,
|
|
40
|
-
openIssuesCount: overrides?.openIssuesCount ?? 2,
|
|
41
|
-
watchersCount: overrides?.watchersCount ?? 15,
|
|
42
|
-
topics: overrides?.topics ?? ["typescript", "test"],
|
|
43
|
-
license: overrides?.license ?? "MIT",
|
|
44
|
-
hasIssues: overrides?.hasIssues ?? true,
|
|
45
|
-
hasWiki: overrides?.hasWiki ?? true,
|
|
46
|
-
hasDiscussions: overrides?.hasDiscussions ?? false,
|
|
47
|
-
...overrides,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Create a mock unified repository
|
|
53
|
-
*/
|
|
54
|
-
export function createMockUnifiedRepo(overrides?: Partial<UnifiedRepo>): UnifiedRepo {
|
|
55
|
-
const name = overrides?.name ?? "test-repo";
|
|
56
|
-
const id = overrides?.id ?? `unified-${name}`;
|
|
57
|
-
const source = overrides?.source ?? "local";
|
|
58
|
-
|
|
59
|
-
// Create local project if not explicitly null and source allows it
|
|
60
|
-
let local: Project | null = null;
|
|
61
|
-
if (overrides?.local !== null && (source === "local" || source === "both")) {
|
|
62
|
-
local = overrides?.local ?? createMockProject({
|
|
63
|
-
name,
|
|
64
|
-
path: `/test/projects/${name}`
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Create GitHub info if not explicitly null and source allows it
|
|
69
|
-
let github: GitHubRepoInfo | null = null;
|
|
70
|
-
if (overrides?.github !== null && (source === "github" || source === "both")) {
|
|
71
|
-
github = overrides?.github ?? createMockGitHubRepoInfo({ name });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
id,
|
|
76
|
-
name,
|
|
77
|
-
source,
|
|
78
|
-
local,
|
|
79
|
-
github,
|
|
80
|
-
isCloned: overrides?.isCloned ?? (local !== null),
|
|
81
|
-
isOnGitHub: overrides?.isOnGitHub ?? (github !== null),
|
|
82
|
-
localPath: overrides?.localPath ?? (local ? local.path : null),
|
|
83
|
-
...overrides,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Create a mock unified app state
|
|
89
|
-
*/
|
|
90
|
-
export function createMockUnifiedAppState(overrides?: Partial<UnifiedAppState>): UnifiedAppState {
|
|
91
|
-
const viewMode = overrides?.viewMode ?? "combined";
|
|
92
|
-
const projects = overrides?.projects ?? [];
|
|
93
|
-
const githubRepos = overrides?.githubRepos ?? [];
|
|
94
|
-
const unifiedRepos = overrides?.unifiedRepos ?? [];
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
// AppState properties
|
|
98
|
-
projects,
|
|
99
|
-
isLoading: overrides?.isLoading ?? false,
|
|
100
|
-
error: overrides?.error ?? null,
|
|
101
|
-
message: overrides?.message ?? null,
|
|
102
|
-
cursorIndex: overrides?.cursorIndex ?? 0,
|
|
103
|
-
selectedIndices: overrides?.selectedIndices ?? new Set(),
|
|
104
|
-
scrollOffset: overrides?.scrollOffset ?? 0,
|
|
105
|
-
filterText: overrides?.filterText ?? "",
|
|
106
|
-
quickFilter: overrides?.quickFilter ?? "all",
|
|
107
|
-
sortBy: overrides?.sortBy ?? "status",
|
|
108
|
-
sortDirection: overrides?.sortDirection ?? "desc",
|
|
109
|
-
mode: overrides?.mode ?? "normal",
|
|
110
|
-
actionInProgress: overrides?.actionInProgress ?? null,
|
|
111
|
-
actionProgress: overrides?.actionProgress ?? null,
|
|
112
|
-
confirmDialog: overrides?.confirmDialog ?? null,
|
|
113
|
-
|
|
114
|
-
// UnifiedAppState properties
|
|
115
|
-
viewMode,
|
|
116
|
-
githubRepos,
|
|
117
|
-
unifiedRepos,
|
|
118
|
-
isLoadingGitHub: overrides?.isLoadingGitHub ?? false,
|
|
119
|
-
githubError: overrides?.githubError ?? null,
|
|
120
|
-
isRefreshing: overrides?.isRefreshing ?? false,
|
|
121
|
-
cloneDialog: overrides?.cloneDialog ?? null,
|
|
122
|
-
detailModal: overrides?.detailModal ?? null,
|
|
123
|
-
languageFilter: overrides?.languageFilter ?? null,
|
|
124
|
-
|
|
125
|
-
...overrides,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Helper to create a local-only unified repo
|
|
131
|
-
*/
|
|
132
|
-
export function createLocalOnlyUnifiedRepo(name?: string, overrides?: Partial<UnifiedRepo>): UnifiedRepo {
|
|
133
|
-
return createMockUnifiedRepo({
|
|
134
|
-
name: name ?? "local-only-repo",
|
|
135
|
-
source: "local",
|
|
136
|
-
github: null,
|
|
137
|
-
isOnGitHub: false,
|
|
138
|
-
...overrides,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Helper to create a GitHub-only unified repo
|
|
144
|
-
*/
|
|
145
|
-
export function createGitHubOnlyUnifiedRepo(name?: string, overrides?: Partial<UnifiedRepo>): UnifiedRepo {
|
|
146
|
-
return createMockUnifiedRepo({
|
|
147
|
-
name: name ?? "github-only-repo",
|
|
148
|
-
source: "github",
|
|
149
|
-
local: null,
|
|
150
|
-
isCloned: false,
|
|
151
|
-
localPath: null,
|
|
152
|
-
...overrides,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Helper to create a fully synced unified repo (exists both locally and on GitHub)
|
|
158
|
-
*/
|
|
159
|
-
export function createSyncedUnifiedRepo(name?: string, overrides?: Partial<UnifiedRepo>): UnifiedRepo {
|
|
160
|
-
const repoName = name ?? "synced-repo";
|
|
161
|
-
return createMockUnifiedRepo({
|
|
162
|
-
name: repoName,
|
|
163
|
-
source: "both",
|
|
164
|
-
isCloned: true,
|
|
165
|
-
isOnGitHub: true,
|
|
166
|
-
localPath: `/test/projects/${repoName}`,
|
|
167
|
-
...overrides,
|
|
168
|
-
});
|
|
169
|
-
}
|