fix(ci): simplify test runner to plain bun test by fixing mock.module() leakage

- Add afterAll(() => { mock.restore() }) to 52 test files missing cleanup
- Rewrite create-tool-guard-hooks.test.ts to use spyOn instead of barrel mock
- Fix skill-mcp-manager OAuth tests with missing mockTokens/mockLogin definitions
- Fix start-work hook: show worktree active block on resume with existing worktree_path
- Extract createWorktreeActiveBlock to worktree-block.ts to avoid circular import
- Replace 80-line isolated test runner CI config with single `bun test` command
This commit is contained in:
YeonGyu-Kim
2026-04-03 23:06:35 +09:00
parent 06180e09f8
commit 53eeac3f31
55 changed files with 219 additions and 190 deletions
@@ -1,5 +1,5 @@
declare const require: (name: string) => any
const { describe, test, expect, beforeEach, afterEach, spyOn, mock } = require("bun:test")
const { describe, test, expect, beforeEach, afterEach, afterAll, spyOn, mock } = require("bun:test")
mock.module("../../shared/connected-providers-cache", () => ({
readConnectedProvidersCache: () => null,
@@ -10,6 +10,8 @@ mock.module("../../shared/connected-providers-cache", () => ({
updateConnectedProvidersCache: () => {},
}))
afterAll(() => { mock.restore() })
import { getSessionPromptParams, clearSessionPromptParams } from "../../shared/session-prompt-params-state"
import { tmpdir } from "node:os"
import type { PluginInput } from "@opencode-ai/plugin"
@@ -1,9 +1,11 @@
import { describe, test, expect, mock } from "bun:test"
import { describe, test, expect, mock, afterAll } from "bun:test"
import { isActiveSessionStatus, isTerminalSessionStatus } from "./session-status-classifier"
const mockLog = mock()
mock.module("../../shared", () => ({ log: mockLog }))
afterAll(() => { mock.restore() })
describe("isActiveSessionStatus", () => {
describe("#given a known active session status", () => {
test('#when type is "busy" #then returns true', () => {
@@ -1,4 +1,4 @@
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test"
import { afterEach, beforeEach, describe, expect, it, mock, afterAll } from "bun:test"
import type { ClaudeCodeMcpServer } from "../claude-code-mcp-loader/types"
import type { SkillMcpClientInfo, SkillMcpManagerState } from "./types"
@@ -47,6 +47,8 @@ mock.module("@modelcontextprotocol/sdk/client/stdio.js", () => ({
StdioClientTransport: MockStdioClientTransport,
}))
afterAll(() => { mock.restore() })
const { disconnectAll, disconnectSession } = await import("./cleanup")
const { getOrCreateClient } = await import("./connection")
+8 -22
View File
@@ -1,4 +1,4 @@
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test"
import { describe, it, expect, beforeEach, afterEach, afterAll, mock, spyOn } from "bun:test"
import { SkillMcpManager } from "./manager"
import type { SkillMcpClientInfo, SkillMcpServerContext } from "./types"
import type { ClaudeCodeMcpServer } from "../claude-code-mcp-loader/types"
@@ -22,33 +22,19 @@ mock.module("@modelcontextprotocol/sdk/client/streamableHttp.js", () => ({
},
}))
const mockTokens = mock(() => null as { accessToken: string; refreshToken?: string; expiresAt?: number } | null)
const mockLogin = mock(() => Promise.resolve({ accessToken: "new-token" }))
// Mock OAuth provider for OAuth integration tests
const mockTokens = mock(() => null as { accessToken: string } | null)
const mockLogin = mock(() => Promise.resolve({ accessToken: "test-token" }) as Promise<{ accessToken: string } | null>)
mock.module("../mcp-oauth/provider", () => ({
McpOAuthProvider: class MockMcpOAuthProvider {
constructor(public options: { serverUrl: string; clientId?: string; scopes?: string[] }) {}
tokens() {
return mockTokens()
}
async login() {
return mockLogin()
}
tokens = mockTokens
login = mockLogin
constructor(_opts: unknown) {}
},
}))
afterAll(() => { mock.restore() })
describe("SkillMcpManager", () => {
let manager: SkillMcpManager
+3 -1
View File
@@ -1,4 +1,4 @@
import { describe, test, expect, mock, beforeEach, spyOn } from 'bun:test'
import { describe, test, expect, mock, beforeEach, spyOn, afterAll } from 'bun:test'
import type { TmuxConfig } from '../../config/schema'
import type { WindowState, PaneAction } from './types'
import type { ActionResult, ExecuteContext } from './action-executor'
@@ -77,6 +77,8 @@ mock.module('./pane-state-querier', () => ({
: null,
}))
afterAll(() => { mock.restore() })
mock.module('./action-executor', () => ({
executeActions: mockExecuteActions,
executeAction: mockExecuteAction,
@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, mock, test } from "bun:test"
import { beforeEach, describe, expect, mock, test, afterAll } from "bun:test"
import type { TmuxConfig } from "../../config/schema"
import type { ActionResult, ExecuteContext, ExecuteActionsResult } from "./action-executor"
import type { TmuxUtilDeps } from "./manager"
@@ -46,6 +46,8 @@ mock.module("../../shared/tmux", () => ({
SESSION_MISSING_GRACE_MS: 1_000,
}))
afterAll(() => { mock.restore() })
const mockTmuxDeps: TmuxUtilDeps = {
isInsideTmux: mockIsInsideTmux,
getCurrentPaneId: mockGetCurrentPaneId,