mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 06:15:51 +00:00
feat: integrate fork work onto upstream main (squashed)
Squash-merge of feat/autofix-pr-test (69 commits) onto upstream/main with -X ours strategy (upstream as authoritative for content conflicts). Key features brought in from fork: - LocalMemoryRecall + VaultHttpFetch tools (end-to-end wired) - /local-memory, /local-vault, /memory-stores, /skill-store interactive panels - /agents-platform, /schedule, /vault command scaffolding - /login: switch / replace / remove of workspace API key - statusline refactor (built-in status row, /statusline as info command) - autofix-pr command + workflow Conflict resolutions (upstream-wins): - 10 .js command stubs kept from upstream (alongside fork's .ts implementations) - src/components/BuiltinStatusLine.tsx accepted upstream's deletion (fork's wire-up references in StatusLine.tsx will be cleaned up next) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
45
tests/mocks/childProcess.ts
Normal file
45
tests/mocks/childProcess.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Shared mock for `node:child_process`.
|
||||
*
|
||||
* Usage:
|
||||
* import { mock } from 'bun:test'
|
||||
* import { childProcessMock, execFileMock, execFileSyncMock } from 'tests/mocks/childProcess'
|
||||
* mock.module('node:child_process', () => childProcessMock)
|
||||
*
|
||||
* Call `execFileMock.mockImplementation(...)` or `execFileSyncMock.mockImplementation(...)`
|
||||
* before each test that needs specific behavior.
|
||||
*/
|
||||
import { mock } from 'bun:test'
|
||||
|
||||
// execFile: node-style callback (cmd, args, opts?, callback)
|
||||
export const execFileMock = mock(
|
||||
(
|
||||
_cmd: string,
|
||||
_args: string[],
|
||||
_optsOrCb?: unknown,
|
||||
_cb?: (err: Error | null, stdout: string, stderr: string) => void,
|
||||
) => {
|
||||
const cb =
|
||||
typeof _optsOrCb === 'function'
|
||||
? (_optsOrCb as (
|
||||
err: Error | null,
|
||||
stdout: string,
|
||||
stderr: string,
|
||||
) => void)
|
||||
: _cb
|
||||
if (cb) cb(null, '', '')
|
||||
return null
|
||||
},
|
||||
)
|
||||
|
||||
// execFileSync: synchronous (returns Buffer)
|
||||
export const execFileSyncMock = mock(
|
||||
(_cmd: string, _args: string[], _opts?: unknown): Buffer => {
|
||||
return Buffer.from('')
|
||||
},
|
||||
)
|
||||
|
||||
export const childProcessMock = {
|
||||
execFile: execFileMock,
|
||||
execFileSync: execFileSyncMock,
|
||||
}
|
||||
91
tests/mocks/state.ts
Normal file
91
tests/mocks/state.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Shared partial mock for src/bootstrap/state.ts
|
||||
*
|
||||
* Covers the most commonly imported exports plus their transitive callers.
|
||||
* Add exports here when new tests need them — never mock exports that don't exist.
|
||||
*
|
||||
* Usage:
|
||||
* import { stateMock } from '../../../tests/mocks/state'
|
||||
* mock.module('src/bootstrap/state.js', stateMock)
|
||||
*/
|
||||
export function stateMock() {
|
||||
const noop = () => {}
|
||||
return {
|
||||
// Session identity
|
||||
getSessionId: () => 'mock-session-id',
|
||||
regenerateSessionId: noop,
|
||||
getParentSessionId: () => undefined,
|
||||
switchSession: noop,
|
||||
onSessionSwitch: () => () => {},
|
||||
|
||||
// CWD / project
|
||||
getOriginalCwd: () => '/mock/cwd',
|
||||
getSessionProjectDir: () => null,
|
||||
getProjectRoot: () => '/mock/project',
|
||||
getCwdState: () => '/mock/cwd',
|
||||
setCwdState: noop,
|
||||
setOriginalCwd: noop,
|
||||
setProjectRoot: noop,
|
||||
|
||||
// Direct-connect
|
||||
getDirectConnectServerUrl: () => undefined,
|
||||
setDirectConnectServerUrl: noop,
|
||||
|
||||
// Duration / cost accumulators
|
||||
addToTotalDurationState: noop,
|
||||
resetTotalDurationStateAndCost_FOR_TESTS_ONLY: noop,
|
||||
addToTotalCostState: noop,
|
||||
getTotalCostUSD: () => 0,
|
||||
getTotalAPIDuration: () => 0,
|
||||
getTotalDuration: () => 0,
|
||||
getTotalAPIDurationWithoutRetries: () => 0,
|
||||
getTotalToolDuration: () => 0,
|
||||
addToToolDuration: noop,
|
||||
|
||||
// Turn stats
|
||||
getTurnHookDurationMs: () => 0,
|
||||
addToTurnHookDuration: noop,
|
||||
resetTurnHookDuration: noop,
|
||||
getTurnHookCount: () => 0,
|
||||
getTurnToolDurationMs: () => 0,
|
||||
resetTurnToolDuration: noop,
|
||||
getTurnToolCount: () => 0,
|
||||
getTurnClassifierDurationMs: () => 0,
|
||||
addToTurnClassifierDuration: noop,
|
||||
resetTurnClassifierDuration: noop,
|
||||
getTurnClassifierCount: () => 0,
|
||||
|
||||
// Stats store
|
||||
getStatsStore: () => ({}),
|
||||
setStatsStore: noop,
|
||||
|
||||
// Interaction time
|
||||
updateLastInteractionTime: noop,
|
||||
flushInteractionTime: noop,
|
||||
|
||||
// Lines changed
|
||||
addToTotalLinesChanged: noop,
|
||||
getTotalLinesAdded: () => 0,
|
||||
getTotalLinesRemoved: () => 0,
|
||||
|
||||
// Token counts
|
||||
getTotalInputTokens: () => 0,
|
||||
getTotalOutputTokens: () => 0,
|
||||
getTotalCacheReadInputTokens: () => 0,
|
||||
getTotalCacheCreationInputTokens: () => 0,
|
||||
getTotalWebSearchRequests: () => 0,
|
||||
getTurnOutputTokens: () => 0,
|
||||
getCurrentTurnTokenBudget: () => null,
|
||||
|
||||
// API request state
|
||||
setLastAPIRequest: noop,
|
||||
getLastAPIRequest: () => null,
|
||||
setLastAPIRequestMessages: noop,
|
||||
getLastAPIRequestMessages: () => [],
|
||||
|
||||
// Various getters (add as needed)
|
||||
getIsNonInteractiveSession: () => false,
|
||||
getSdkAgentProgressSummariesEnabled: () => false,
|
||||
addSlowOperation: noop,
|
||||
}
|
||||
}
|
||||
52
tests/mocks/toolContext.ts
Normal file
52
tests/mocks/toolContext.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Shared minimal ToolUseContext stub for tool unit tests.
|
||||
*
|
||||
* Provides only the fields tools actually access in tests:
|
||||
* - getAppState() returns a context with empty rule arrays for every source
|
||||
* - toolUseId / parentMessageId / assistantMessageId / turnId can be
|
||||
* overridden per test for budget tracking tests
|
||||
*
|
||||
* Usage:
|
||||
* import { mockToolContext } from 'tests/mocks/toolContext'
|
||||
* const ctx = mockToolContext({ toolUseId: 't1' })
|
||||
*
|
||||
* Per memory feedback "Mock dependency not subject" — this exists so each
|
||||
* tool test file does not redefine the same partial stub.
|
||||
*/
|
||||
|
||||
const emptyRules = {
|
||||
user: [],
|
||||
project: [],
|
||||
local: [],
|
||||
session: [],
|
||||
cliArg: [],
|
||||
}
|
||||
|
||||
export interface MockToolContextOptions {
|
||||
toolUseId?: string
|
||||
parentMessageId?: string
|
||||
assistantMessageId?: string
|
||||
turnId?: string
|
||||
/** Override toolPermissionContext fields (e.g. mode, alwaysAllowRules). */
|
||||
permissionOverrides?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export function mockToolContext(opts: MockToolContextOptions = {}): never {
|
||||
return {
|
||||
toolUseId: opts.toolUseId,
|
||||
parentMessageId: opts.parentMessageId,
|
||||
assistantMessageId: opts.assistantMessageId,
|
||||
turnId: opts.turnId,
|
||||
getAppState: () => ({
|
||||
toolPermissionContext: {
|
||||
mode: 'default',
|
||||
additionalWorkingDirectories: new Set(),
|
||||
alwaysAllowRules: { ...emptyRules },
|
||||
alwaysDenyRules: { ...emptyRules },
|
||||
alwaysAskRules: { ...emptyRules },
|
||||
isBypassPermissionsModeAvailable: false,
|
||||
...(opts.permissionOverrides ?? {}),
|
||||
},
|
||||
}),
|
||||
} as never
|
||||
}
|
||||
Reference in New Issue
Block a user