Skip to content

Commit ad1d909

Browse files
committed
fix tests
1 parent 1b56990 commit ad1d909

7 files changed

Lines changed: 52 additions & 57 deletions

File tree

apps/sim/app/api/knowledge/[id]/documents/route.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ vi.mock('@/lib/knowledge/documents/service', () => ({
4343
KnowledgeBaseFileOwnershipError: class KnowledgeBaseFileOwnershipError extends Error {},
4444
}))
4545

46+
vi.mock('@/lib/billing/calculations/usage-monitor', () => ({
47+
checkActorUsageLimits: vi.fn().mockResolvedValue({ isExceeded: false }),
48+
}))
49+
4650
vi.mock('@sim/audit', () => auditMock)
4751

4852
import {

apps/sim/app/api/knowledge/[id]/documents/upsert/route.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ vi.mock('@/lib/auth/hybrid', () => hybridAuthMock)
2727
vi.mock('@/app/api/knowledge/utils', () => knowledgeApiUtilsMock)
2828
vi.mock('@sim/audit', () => auditMock)
2929

30+
vi.mock('@/lib/billing/calculations/usage-monitor', () => ({
31+
checkActorUsageLimits: vi.fn().mockResolvedValue({ isExceeded: false }),
32+
}))
33+
3034
vi.mock('@/lib/knowledge/documents/service', () => ({
3135
createDocumentRecords: vi.fn(),
3236
deleteDocument: vi.fn(),

apps/sim/app/api/v1/knowledge/search/route.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ vi.mock('@/app/api/knowledge/search/utils', () => ({
4242

4343
vi.mock('@/app/api/knowledge/utils', () => knowledgeApiUtilsMock)
4444

45+
vi.mock('@/lib/billing/calculations/usage-monitor', () => ({
46+
checkActorUsageLimits: vi.fn().mockResolvedValue({ isExceeded: false }),
47+
}))
48+
4549
vi.mock('@/app/api/v1/middleware', () => ({
4650
authenticateRequest: mockAuthenticateRequest,
4751
validateWorkspaceAccess: mockValidateWorkspaceAccess,

apps/sim/lib/copilot/request/lifecycle/headless.test.ts

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { propagation, trace } from '@opentelemetry/api'
66
import { W3CTraceContextPropagator } from '@opentelemetry/core'
77
import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base'
88
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
9-
import { RequestTraceV1Outcome } from '@/lib/copilot/generated/request-trace-v1'
109
import type { OrchestratorResult } from '@/lib/copilot/request/types'
1110

1211
const { runCopilotLifecycle } = vi.hoisted(() => ({
@@ -34,22 +33,13 @@ describe('runHeadlessCopilotLifecycle', () => {
3433
beforeEach(() => {
3534
trace.setGlobalTracerProvider(new BasicTracerProvider())
3635
propagation.setGlobalPropagator(new W3CTraceContextPropagator())
37-
vi.stubGlobal(
38-
'fetch',
39-
vi.fn().mockResolvedValue(
40-
new Response(null, {
41-
status: 200,
42-
})
43-
)
44-
)
4536
})
4637

4738
afterEach(() => {
4839
vi.clearAllMocks()
49-
vi.unstubAllGlobals()
5040
})
5141

52-
it('reports a successful headless trace', async () => {
42+
it('runs the lifecycle and returns its result', async () => {
5343
runCopilotLifecycle.mockResolvedValueOnce(
5444
createLifecycleResult({
5545
usage: { prompt: 10, completion: 5 },
@@ -77,32 +67,13 @@ describe('runHeadlessCopilotLifecycle', () => {
7767
expect.objectContaining({
7868
simRequestId: 'req-1',
7969
trace: expect.any(Object),
70+
otelContext: expect.any(Object),
8071
chatId: 'chat-1',
8172
})
8273
)
83-
84-
expect(fetch).toHaveBeenCalledTimes(1)
85-
const [url, init] = vi.mocked(fetch).mock.calls[0] as [string, RequestInit]
86-
expect(url).toContain('/api/traces')
87-
const body = JSON.parse(String(init.body))
88-
expect(body).toEqual(
89-
expect.objectContaining({
90-
simRequestId: 'req-1',
91-
outcome: RequestTraceV1Outcome.success,
92-
chatId: 'chat-1',
93-
usage: expect.objectContaining({
94-
inputTokens: 10,
95-
outputTokens: 5,
96-
}),
97-
cost: {
98-
rawTotalCost: 3,
99-
billedTotalCost: 3,
100-
},
101-
})
102-
)
10374
})
10475

105-
it('reports an error trace when the lifecycle result is unsuccessful', async () => {
76+
it('returns an unsuccessful result from the lifecycle', async () => {
10677
runCopilotLifecycle.mockResolvedValueOnce(
10778
createLifecycleResult({
10879
success: false,
@@ -125,9 +96,6 @@ describe('runHeadlessCopilotLifecycle', () => {
12596
)
12697

12798
expect(result.success).toBe(false)
128-
const [, init] = vi.mocked(fetch).mock.calls[0] as [string, RequestInit]
129-
const body = JSON.parse(String(init.body))
130-
expect(body.outcome).toBe(RequestTraceV1Outcome.error)
13199
})
132100

133101
it('prefers an explicit simRequestId over the payload messageId', async () => {
@@ -154,13 +122,9 @@ describe('runHeadlessCopilotLifecycle', () => {
154122
simRequestId: 'workflow-request-id',
155123
})
156124
)
157-
158-
const [, init] = vi.mocked(fetch).mock.calls[0] as [string, RequestInit]
159-
const body = JSON.parse(String(init.body))
160-
expect(body.simRequestId).toBe('workflow-request-id')
161125
})
162126

163-
it('passes an OTel context to the lifecycle and trace report', async () => {
127+
it('threads a valid OTel context into the lifecycle', async () => {
164128
let lifecycleTraceparent = ''
165129
runCopilotLifecycle.mockImplementationOnce(async (_payload, options) => {
166130
const { traceHeaders } = await import('@/lib/copilot/request/go/propagation')
@@ -183,18 +147,9 @@ describe('runHeadlessCopilotLifecycle', () => {
183147
)
184148

185149
expect(lifecycleTraceparent).toMatch(/^00-[0-9a-f]{32}-[0-9a-f]{16}-0[0-9a-f]$/)
186-
const [, init] = vi.mocked(fetch).mock.calls[0] as [string, RequestInit]
187-
const headers = init.headers as Record<string, string>
188-
// The outbound trace report now runs inside its own OTel child span, so
189-
// traceparent has the same trace-id as the lifecycle but a different
190-
// span-id. Both must stay on the same trace.
191-
const lifecycleTraceId = lifecycleTraceparent.split('-')[1]
192-
expect(headers.traceparent).toMatch(/^00-[0-9a-f]{32}-[0-9a-f]{16}-0[0-9a-f]$/)
193-
expect(headers.traceparent.split('-')[1]).toBe(lifecycleTraceId)
194-
expect(headers.traceparent.split('-')[2]).not.toBe(lifecycleTraceparent.split('-')[2])
195150
})
196151

197-
it('reports an error trace when the lifecycle throws', async () => {
152+
it('rethrows when the lifecycle throws', async () => {
198153
runCopilotLifecycle.mockRejectedValueOnce(new Error('kaboom'))
199154

200155
await expect(
@@ -212,9 +167,5 @@ describe('runHeadlessCopilotLifecycle', () => {
212167
}
213168
)
214169
).rejects.toThrow('kaboom')
215-
216-
const [, init] = vi.mocked(fetch).mock.calls[0] as [string, RequestInit]
217-
const body = JSON.parse(String(init.body))
218-
expect(body.outcome).toBe(RequestTraceV1Outcome.error)
219170
})
220171
})

apps/sim/lib/copilot/tools/handlers/workflow/mutations.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
* @vitest-environment node
33
*/
4+
import { createEnvMock } from '@sim/testing'
45
import { beforeEach, describe, expect, it, vi } from 'vitest'
56

67
const {
@@ -34,9 +35,7 @@ vi.mock('@/lib/api-key/orchestration', () => ({
3435
performCreateWorkspaceApiKey: vi.fn(),
3536
}))
3637

37-
vi.mock('@/lib/core/config/env', () => ({
38-
env: { INTERNAL_API_SECRET: 'secret' },
39-
}))
38+
vi.mock('@/lib/core/config/env', () => createEnvMock({ INTERNAL_API_SECRET: 'secret' }))
4039

4140
vi.mock('@/lib/core/utils/request', () => ({
4241
generateRequestId: () => 'request-1',

apps/sim/lib/mcp/service.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,38 @@ const {
1313
mockValidateDomain,
1414
mockValidateSsrf,
1515
mockIsDomainAllowed,
16+
mockCacheAdapter,
1617
} = vi.hoisted(() => {
1718
const mockListTools = vi.fn()
1819
const mockConnect = vi.fn()
1920
const mockDisconnect = vi.fn()
21+
// In-memory cache adapter so the service never touches the real Redis the
22+
// local .env points at (unreachable in CI/sandbox → hangs). Honors TTL via
23+
// an expiry timestamp so negative-cache assertions behave like production.
24+
const cacheStore = new Map<string, { tools: unknown[]; expiry: number }>()
25+
const mockCacheAdapter = {
26+
get: async (key: string) => {
27+
const entry = cacheStore.get(key)
28+
if (!entry) return null
29+
if (entry.expiry <= Date.now()) {
30+
cacheStore.delete(key)
31+
return null
32+
}
33+
return entry
34+
},
35+
set: async (key: string, tools: unknown[], ttlMs: number) => {
36+
cacheStore.set(key, { tools, expiry: Date.now() + ttlMs })
37+
},
38+
delete: async (key: string) => {
39+
cacheStore.delete(key)
40+
},
41+
clear: async () => {
42+
cacheStore.clear()
43+
},
44+
dispose: () => {},
45+
}
2046
return {
47+
mockCacheAdapter,
2148
MockMcpClient: vi.fn().mockImplementation(
2249
class {
2350
constructor() {
@@ -91,6 +118,11 @@ vi.mock('@/lib/mcp/resolve-config', () => ({
91118
resolveMcpConfigEnvVars: (...args: unknown[]) => mockResolveEnvVars(...args),
92119
}))
93120

121+
vi.mock('@/lib/mcp/storage', () => ({
122+
createMcpCacheAdapter: () => mockCacheAdapter,
123+
getMcpCacheType: () => 'memory',
124+
}))
125+
94126
import { mcpService } from '@/lib/mcp/service'
95127
import { McpOauthAuthorizationRequiredError } from '@/lib/mcp/types'
96128

packages/testing/src/mocks/audit.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ export const auditMock = {
112112
ORG_MEMBER_ADDED: 'org_member.added',
113113
ORG_MEMBER_REMOVED: 'org_member.removed',
114114
ORG_MEMBER_ROLE_CHANGED: 'org_member.role_changed',
115+
ORG_MEMBER_USAGE_LIMIT_CHANGED: 'org_member.usage_limit_changed',
115116
ORG_INVITATION_CREATED: 'org_invitation.created',
116117
ORG_INVITATION_UPDATED: 'org_invitation.updated',
117118
ORG_INVITATION_ACCEPTED: 'org_invitation.accepted',

0 commit comments

Comments
 (0)