Skip to content

fix(tests): resolve test environment compatibility/brittleness issues for CI builds#24

Open
jamesjmartin wants to merge 2 commits into
LaiZhou:mainfrom
jamesjmartin:fix/brittle-test-env
Open

fix(tests): resolve test environment compatibility/brittleness issues for CI builds#24
jamesjmartin wants to merge 2 commits into
LaiZhou:mainfrom
jamesjmartin:fix/brittle-test-env

Conversation

@jamesjmartin
Copy link
Copy Markdown

Summary

Fix ./gradlew build failures on Windows and in CI by addressing three test environment compatibility issues: missing IntelliJ Application context in unit tests, missing Windows binary extension in PATH search, and a blocking VFS refresh pattern.

Changes

OpenCodeLogicTest — Proper IntelliJ test harness

Replaced the plain JUnit class with java.lang.reflect.Proxy mock of Project with BasePlatformTestCase, which provides a real IntelliJ Application context. Without this, NotificationGroupManager.getInstance() and other platform APIs threw exceptions, disconnecting the SSE listener before diffs could be fetched, causing test timeouts.

Also moved temporary test file creation from java.io.tmpdir to project.basePath, matching where PathUtil.resolveProjectPath resolves relative paths.

RealProcessIntegrationTest — Windows binary detection

On Windows, npm installs opencode.cmd (a batch wrapper), not a bare opencode file. The PATH search now checks platform-appropriate filenames:

  • Windows: opencode.cmd, opencode.bat, opencode.exe, opencode
  • Linux/macOS: opencode (unchanged)

forceVfsRefresh — Async, skip non-existent files

Two changes:

  1. Only refresh files that exist on disk, instead of falling back to the parent directory (which triggered a full synchronous scan of the project base).
  2. Changed refreshIoFiles from synchronous to asynchronous to prevent blocking the background task thread.

SendSelectionToTerminalActionTest — Eliminate race condition

The test had a flaky race on Linux CI: actionPerformed >> schedulePasteAttempt >> scheduled executor (100ms) >> invokeLater (EDT) >> pasteToTerminal >> AppExecutorService.submit (HTTP call) >> FakeOpenCodeServer. Four thread hops meant the HTTP call sometimes didn't complete within the 2-second polling window.

Fix — two parts:

  1. OpenCodeService.kt: Extracted the schedule+invokeLater chain into pasteDispatch, an injectable test hook. schedulePasteAttempt now delegates to pasteDispatch instead of hardcoding the executor/EDT calls.

  2. FakeOpenCodeServer.kt + test: Added CountDownLatch(1) (promptLatch) counted down in the POST handler after receivedPrompts.add(body). The test overrides pasteDispatch = { task -> task() } to run pasteToTerminal synchronously during the action, then blocks on latch.await(5, TimeUnit.SECONDS) — no busy-polling, no thread scheduling lottery.

Verification

$ ./gradlew build
BUILD SUCCESSFUL in 36s
5 tests completed, 0 failed

- Convert OpenCodeLogicTest to extend BasePlatformTestCase for proper
  IntelliJ Application context instead of plain JUnit with Proxy mocks
- Fix Windows binary detection in RealProcessIntegrationTest by searching
  for opencode.cmd/.bat/.exe alongside the bare filename
- Fix forceVfsRefresh to skip non-existent files and use async refresh,
  preventing blocking directory scans on the background thread
- Fix SendSelectionToTerminalActionTest flake: replace thread-hopping
  async paste pipeline with synchronous dispatch and CountDownLatch
…rom Runnable to plain lambda to allign with IntelliJ SDK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant