diff --git a/server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts b/server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts index 5c1fcca442..623d132a14 100644 --- a/server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts +++ b/server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts @@ -5,6 +5,7 @@ import { getTableName, type SQL } from "drizzle-orm"; import { PgDialect } from "drizzle-orm/pg-core"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { HttpError } from "../errors.js"; +import { hoistModuleGraph } from "./helpers/hoist-module-graph.js"; const issueId = "11111111-1111-4111-8111-111111111111"; const companyId = "22222222-2222-4222-8222-222222222222"; @@ -380,31 +381,6 @@ function createRunContextDb( return dbStub; } -async function createApp( - actor: Record, - db?: unknown, - options: { chatRunRetries?: typeof mockChatRunRetries } = {}, -) { - const routeDb = db ?? createRunContextDb( - {}, - typeof actor.agentId === "string" ? actor.agentId : ownerAgentId, - typeof actor.runId === "string" ? actor.runId : ownerRunId, - ); - const [{ errorHandler }, { issueRoutes }] = await Promise.all([ - vi.importActual("../middleware/index.js"), - vi.importActual("../routes/issues.js"), - ]); - const app = express(); - app.use(express.json()); - app.use((req, _res, next) => { - (req as any).actor = actor; - next(); - }); - app.use("/api", issueRoutes(routeDb as any, mockStorageService as any, options)); - app.use(errorHandler); - return app; -} - function peerActor(overrides: Record = {}) { return { type: "agent", @@ -437,23 +413,43 @@ function boardActor() { } describe("agent issue mutation checkout ownership", () => { + const routeModules = hoistModuleGraph(registerRouteMocks, async () => { + const [{ errorHandler }, { issueRoutes, __clearIssueListResponseCacheForTests }] = await Promise.all([ + vi.importActual("../middleware/index.js"), + vi.importActual("../routes/issues.js"), + ]); + return { errorHandler, issueRoutes, __clearIssueListResponseCacheForTests }; + }); + + function createApp( + actor: Record, + db?: unknown, + options: { chatRunRetries?: typeof mockChatRunRetries } = {}, + ) { + const routeDb = db ?? createRunContextDb( + {}, + typeof actor.agentId === "string" ? actor.agentId : ownerAgentId, + typeof actor.runId === "string" ? actor.runId : ownerRunId, + ); + const { errorHandler, issueRoutes } = routeModules.value; + const app = express(); + app.use(express.json()); + app.use((req, _res, next) => { + (req as any).actor = actor; + next(); + }); + app.use("/api", issueRoutes(routeDb as any, mockStorageService as any, options)); + app.use(errorHandler); + return app; + } + beforeEach(() => { - vi.resetModules(); - vi.doUnmock("@paperclipai/shared/telemetry"); - vi.doUnmock("../telemetry.js"); - vi.doUnmock("../services/access.js"); - vi.doUnmock("../services/activity-log.js"); - vi.doUnmock("../services/cross-issue-influence-limit.js"); - vi.doUnmock("../services/agents.js"); - vi.doUnmock("../services/documents.js"); - vi.doUnmock("../services/external-objects.js"); - vi.doUnmock("../services/index.js"); - vi.doUnmock("../services/issues.js"); - vi.doUnmock("../services/work-products.js"); - vi.doUnmock("../routes/issues.js"); - vi.doUnmock("../routes/authz.js"); - vi.doUnmock("../middleware/index.js"); - registerRouteMocks(); + // This block loads the route module graph one time (see + // hoistModuleGraph above). As a result, the issue-list route keeps its + // response cache in memory between tests. Clear the cache before each + // test. This stops one test from reusing a cached response left behind + // by an earlier test. + routeModules.value.__clearIssueListResponseCacheForTests(); vi.clearAllMocks(); mockChatRunRetries.prepareFailedChatRunRetry.mockReset(); mockChatRunRetries.processFailedChatRunRetry.mockReset();