Skip to content

Commit 41f707d

Browse files
committed
Refactor tests for Bun and Playwright; cache Stripe loader
1 parent 15f96d1 commit 41f707d

File tree

19 files changed

+309
-287
lines changed

19 files changed

+309
-287
lines changed

cli/src/__tests__/e2e/logout-relogin-flow.test.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
} from '../../utils/auth'
2020
import { setProjectRoot } from '../../project-files'
2121

22-
import type * as AuthModule from '../../utils/auth'
23-
import type * as CodebuffApiModule from '../../utils/codebuff-api'
22+
import * as AuthModule from '../../utils/auth'
23+
import * as CodebuffApiModule from '../../utils/codebuff-api'
2424

2525
type User = AuthModule.User
2626

@@ -57,17 +57,14 @@ describe('Logout and Re-login helpers', () => {
5757
})
5858

5959
const mockConfigPaths = () => {
60-
const authModule = require('../../utils/auth') as typeof AuthModule
61-
spyOn(authModule, 'getConfigDir').mockReturnValue(tempConfigDir)
62-
spyOn(authModule, 'getCredentialsPath').mockReturnValue(
60+
spyOn(AuthModule, 'getConfigDir').mockReturnValue(tempConfigDir)
61+
spyOn(AuthModule, 'getCredentialsPath').mockReturnValue(
6362
path.join(tempConfigDir, 'credentials.json'),
6463
)
6564
}
6665

6766
const mockLogoutApi = () => {
68-
const apiModule =
69-
require('../../utils/codebuff-api') as typeof CodebuffApiModule
70-
spyOn(apiModule, 'getApiClient').mockReturnValue({
67+
spyOn(CodebuffApiModule, 'getApiClient').mockReturnValue({
7168
logout: async () => ({ ok: true, status: 200 }),
7269
} as any)
7370
}

cli/src/__tests__/e2e/returning-user-auth.test.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ import {
1414
} from 'bun:test'
1515

1616
import { validateApiKey } from '../../hooks/use-auth-query'
17+
import * as AuthModule from '../../utils/auth'
1718
import { getAuthTokenDetails, saveUserCredentials } from '../../utils/auth'
18-
19-
import type * as AuthModule from '../../utils/auth'
2019
import type { GetUserInfoFromApiKeyFn } from '@codebuff/common/types/contracts/database'
2120
import type { Logger } from '@codebuff/common/types/contracts/logger'
2221

@@ -58,10 +57,8 @@ describe('Returning User Authentication helpers', () => {
5857
})
5958

6059
test('should load auth token from credentials file for returning user', () => {
61-
const authModule = require('../../utils/auth') as typeof AuthModule
62-
63-
spyOn(authModule, 'getConfigDir').mockReturnValue(tempConfigDir)
64-
spyOn(authModule, 'getCredentialsPath').mockReturnValue(
60+
spyOn(AuthModule, 'getConfigDir').mockReturnValue(tempConfigDir)
61+
spyOn(AuthModule, 'getCredentialsPath').mockReturnValue(
6562
path.join(tempConfigDir, 'credentials.json'),
6663
)
6764

@@ -73,10 +70,8 @@ describe('Returning User Authentication helpers', () => {
7370
})
7471

7572
test('should fall back to CODEBUFF_API_KEY when credentials are missing', () => {
76-
const authModule = require('../../utils/auth') as typeof AuthModule
77-
78-
spyOn(authModule, 'getConfigDir').mockReturnValue(tempConfigDir)
79-
spyOn(authModule, 'getCredentialsPath').mockReturnValue(
73+
spyOn(AuthModule, 'getConfigDir').mockReturnValue(tempConfigDir)
74+
spyOn(AuthModule, 'getCredentialsPath').mockReturnValue(
8075
path.join(tempConfigDir, 'credentials.json'),
8176
)
8277

@@ -88,10 +83,8 @@ describe('Returning User Authentication helpers', () => {
8883
})
8984

9085
test('should validate stored credentials without blocking the UI thread', async () => {
91-
const authModule = require('../../utils/auth') as typeof AuthModule
92-
93-
spyOn(authModule, 'getConfigDir').mockReturnValue(tempConfigDir)
94-
spyOn(authModule, 'getCredentialsPath').mockReturnValue(
86+
spyOn(AuthModule, 'getConfigDir').mockReturnValue(tempConfigDir)
87+
spyOn(AuthModule, 'getCredentialsPath').mockReturnValue(
9588
path.join(tempConfigDir, 'credentials.json'),
9689
)
9790

cli/src/__tests__/test-utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ function loadCliEnv(): Record<string, string> {
4343
}
4444

4545
try {
46-
// eslint-disable-next-line @typescript-eslint/no-var-requires
46+
// NOTE: Inline require() is used for lazy loading - the env module depends on
47+
// Infisical secrets which may not be available at module load time in test environments
4748
const { env } = require('../../../packages/internal/src/env') as {
4849
env: Record<string, unknown>
4950
}

cli/src/hooks/__tests__/use-directory-browser.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { describe, test, expect, beforeEach, afterEach } from 'bun:test'
2-
import { mkdirSync, mkdtempSync, rmSync } from 'fs'
2+
import {
3+
existsSync,
4+
mkdirSync,
5+
mkdtempSync,
6+
rmSync,
7+
statSync,
8+
writeFileSync,
9+
} from 'fs'
310
import os from 'os'
411
import path from 'path'
512

@@ -21,7 +28,6 @@ const expandPath = (inputPath: string): string => {
2128

2229
// Extract the path validation logic for testing
2330
const isValidDirectoryPath = (inputPath: string): boolean => {
24-
const { existsSync, statSync } = require('fs')
2531
const expandedPath = expandPath(inputPath.trim())
2632
try {
2733
return existsSync(expandedPath) && statSync(expandedPath).isDirectory()
@@ -141,7 +147,7 @@ describe('useDirectoryBrowser - path validation', () => {
141147

142148
test('returns false for file (not directory)', () => {
143149
const filePath = path.join(tempDir, 'test.txt')
144-
require('fs').writeFileSync(filePath, 'test')
150+
writeFileSync(filePath, 'test')
145151
expect(isValidDirectoryPath(filePath)).toBe(false)
146152
})
147153

cli/src/hooks/__tests__/use-user-details-query.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {
1111
import { createMockApiClient } from '../../__tests__/helpers/mock-api-client'
1212
import { fetchUserDetails } from '../use-user-details-query'
1313

14+
import * as CodebuffApiModule from '../../utils/codebuff-api'
1415
import type { Logger } from '@codebuff/common/types/contracts/logger'
15-
import type * as CodebuffApiModule from '../../utils/codebuff-api'
1616

1717
describe('fetchUserDetails', () => {
1818
const mockLogger: Logger = {
@@ -198,10 +198,11 @@ describe('fetchUserDetails', () => {
198198
)
199199
const apiClient = createMockApiClient({ me: meMock })
200200

201-
const apiModule =
202-
require('../../utils/codebuff-api') as typeof CodebuffApiModule
203-
const setTokenSpy = spyOn(apiModule, 'setApiClientAuthToken')
204-
spyOn(apiModule, 'getApiClient').mockReturnValue(apiClient as any)
201+
const setTokenSpy = spyOn(
202+
CodebuffApiModule,
203+
'setApiClientAuthToken',
204+
)
205+
spyOn(CodebuffApiModule, 'getApiClient').mockReturnValue(apiClient as any)
205206

206207
await expect(
207208
fetchUserDetails({

cli/src/utils/__tests__/image-dimensions.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { mkdirSync, rmSync } from 'fs'
22
import path from 'path'
33

44
import { describe, test, expect, beforeEach, afterEach } from 'bun:test'
5+
import { Jimp } from 'jimp'
56

67
import { setProjectRoot } from '../../project-files'
78
import { calculateDisplaySize } from '../image-display'
@@ -18,8 +19,6 @@ beforeEach(async () => {
1819
setProjectRoot(TEST_DIR)
1920

2021
// Create test images with known dimensions using Jimp
21-
const { Jimp } = await import('jimp')
22-
2322
// Wide image: 200x100 (2:1 aspect ratio)
2423
const wideImage = new Jimp({ width: 200, height: 100, color: 0xff0000ff })
2524
await wideImage.write(
@@ -79,7 +78,6 @@ describe('Image Dimensions', () => {
7978

8079
test('should return compressed dimensions when image is compressed', async () => {
8180
// Create a large image that will be compressed
82-
const { Jimp } = await import('jimp')
8381
const largeImage = new Jimp({
8482
width: 2000,
8583
height: 1000,

cli/src/utils/clipboard.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ export async function copyTextToClipboard(
8484
if (typeof navigator !== 'undefined' && navigator.clipboard) {
8585
await navigator.clipboard.writeText(text)
8686
} else if (typeof process !== 'undefined' && process.platform) {
87+
// NOTE: Inline require() is used because this code path only runs in Node.js
88+
// environments, and we need to check process.platform at runtime first
8789
const { execSync } = require('child_process') as {
8890
execSync: (command: string, options: { input: string }) => void
8991
}

cli/src/utils/local-agent-registry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ interface BundledAgentsModule {
118118
getBundledAgentsAsLocalInfo: () => LocalAgentInfo[]
119119
}
120120

121+
// NOTE: Inline require() with try/catch is used because this file is generated at
122+
// build time by prebuild-agents.ts and may not exist during development
121123
let bundledAgentsModule: BundledAgentsModule | null = null
122124
try {
123125
bundledAgentsModule = require('../agents/bundled-agents.generated')

common/src/testing/fixtures/agent-runtime.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
AgentRuntimeDeps,
1111
AgentRuntimeScopedDeps,
1212
} from '../../types/contracts/agent-runtime'
13+
import type { GetUserInfoFromApiKeyInput, UserColumn } from '../../types/contracts/database'
1314
import type { ClientEnv, CiEnv } from '../../types/contracts/env'
1415
import type { Logger } from '../../types/contracts/logger'
1516

@@ -56,13 +57,22 @@ export const TEST_AGENT_RUNTIME_IMPL = Object.freeze<
5657
ciEnv: testCiEnv,
5758

5859
// Database
59-
getUserInfoFromApiKey: async () => ({
60-
id: 'test-user-id',
61-
email: 'test-email',
62-
discord_id: 'test-discord-id',
63-
referral_code: 'ref-test-code',
64-
banned: false,
65-
}),
60+
getUserInfoFromApiKey: async <T extends UserColumn>({
61+
fields,
62+
}: GetUserInfoFromApiKeyInput<T>) => {
63+
const user = {
64+
id: 'test-user-id',
65+
email: 'test-email',
66+
discord_id: 'test-discord-id',
67+
referral_code: 'ref-test-code',
68+
stripe_customer_id: null,
69+
banned: false,
70+
} as const
71+
72+
return Object.fromEntries(fields.map((field) => [field, user[field]])) as {
73+
[K in T]: (typeof user)[K]
74+
}
75+
},
6676
fetchAgentFromDatabase: async () => null,
6777
startAgentRun: async () => 'test-agent-run-id',
6878
finishAgentRun: async () => {},
@@ -125,4 +135,3 @@ export const TEST_AGENT_RUNTIME_IMPL = Object.freeze<
125135

126136
apiKey: 'test-api-key',
127137
})
128-

common/src/util/model-utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ let explicitlyDefinedModels: Set<string> | null = null
66

77
function getExplicitlyDefinedModels(): Set<string> {
88
if (explicitlyDefinedModels === null) {
9-
// Dynamically import to avoid circular dependency issues
10-
// eslint-disable-next-line @typescript-eslint/no-var-requires
9+
// NOTE: Inline require() avoids circular dependency - old-constants imports this
10+
// module, so a top-level import would create a circular reference
1111
const { models, shouldCacheModels } = require('../old-constants')
1212
explicitlyDefinedModels = new Set([
1313
...(Object.values(models) as string[]),

0 commit comments

Comments
 (0)