Skip to content

fix(tests): centralize test config dir lifecycle to prevent env var pollution#242

Merged
BYK merged 7 commits intomainfrom
fix/test-env-var-isolation
Feb 13, 2026
Merged

fix(tests): centralize test config dir lifecycle to prevent env var pollution#242
BYK merged 7 commits intomainfrom
fix/test-env-var-isolation

Conversation

@BYK
Copy link
Member

@BYK BYK commented Feb 13, 2026

Summary

Fixes 37 test failures caused by the Ubuntu 24.04 runner image upgrade (20260201.15.120260209.23.1, kernel 6.11 → 6.14) that changed readdir ordering, exposing a latent env var pollution bug.

Root Cause

Bun runs test files sequentially in one thread (load → run all tests → load next file). Several test files unconditionally delete process.env.SENTRY_CONFIG_DIR in their afterEach hooks. When the next file loads, its module-level code captures undefined, causing join(undefined, ...)TypeError.

The runner image upgrade changed the kernel which changed file discovery order, putting "deleting" files before "capturing" files.

Changes

  • test/helpers.ts: Added useTestConfigDir() helper that creates a unique temp directory in beforeEach, points SENTRY_CONFIG_DIR at it, and restores (never deletes) the original value in afterEach. Also handles closeDatabase() and temp dir cleanup.
  • 11 test files migrated to use useTestConfigDir(), eliminating:
    • 3 files that unconditionally deleted SENTRY_CONFIG_DIR (root cause)
    • 3 files with fragile module-level process.env[CONFIG_DIR_ENV_VAR]! captures
    • 2 files with if (original) restore else delete patterns (off-by-one on falsy check)
    • 2 files missing env var restore in afterEach
  • AGENTS.md: Added "Test Environment Isolation" section documenting the pattern and anti-patterns

Net: -87 lines (157 added, 244 removed) — less boilerplate, more safety.

Verification

  • bun run typecheck — passes
  • bun run lint — passes
  • bun run test:unit1545 tests pass, 0 failures

Supercedes #240

…ollution

Bun runs test files sequentially in a single thread. Several test files
unconditionally deleted process.env.SENTRY_CONFIG_DIR in afterEach hooks,
causing the next file's module-level code to read undefined and crash with
TypeError. A runner image upgrade changed file discovery order, exposing
this latent bug.

Introduces useTestConfigDir() helper in test/helpers.ts that creates a
unique temp directory in beforeEach and restores (never deletes) the env
var in afterEach. Migrates all 11 affected test files to use it.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • (formatters) Add Seer fixability score to issue list and detail views by betegon in #234

Bug Fixes 🐛

Telemetry

  • Use SDK session integration instead of manual management by BYK in #232
  • Correct runtime context for Bun binary by BYK in #231

Other

  • (setup) Use correct auth command in install welcome message by betegon in #241
  • (tests) Centralize test config dir lifecycle to prevent env var pollution by BYK in #242

🤖 This preview updates automatically when you update the PR.

BYK added 3 commits February 13, 2026 16:15
The test preload deletes process.env.SENTRY_CLIENT_ID before oauth.ts
loads, causing the module-level constant to capture an empty string.
Tests that later set SENTRY_CLIENT_ID in beforeEach had no effect since
the constant was already captured. This caused refreshAccessToken to
throw ConfigError (not AuthError), which the ky afterResponse hook
caught silently, preventing 401 retry from working.

Replace the module-level constant with a getClientId() function that
reads process.env at call time.
The tests mocked globalThis.fetch for /organizations/ and /projects/
endpoints but not /users/me/regions/. When getUserRegions() got a 404
from the mock, ky threw an HTTPError which listOrganizations caught
and fell back to the non-region path. On certain CI runner images, this
error-fallback code path fails. Adding an explicit regions mock avoids
the error path entirely and makes the tests deterministic.
// (or beforeEach hooks) may read the env var and get undefined.
if (savedConfigDir !== undefined) {
process.env[CONFIG_DIR_ENV_VAR] = savedConfigDir;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config dir not restored when originally unset

Low Severity

useTestConfigDir() only restores process.env[CONFIG_DIR_ENV_VAR] when savedConfigDir !== undefined. If the original value was unset, afterEach leaves SENTRY_CONFIG_DIR pointing to the just-cleaned temp directory, so later tests can inherit a stale, invalid config path.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Tests in resolver.test.ts and errors.test.ts used mock.module() to mock
api-client.js, which persists across test files in Bun's single-threaded
runner. When these files ran before utils.test.ts, the module mock
intercepted listOrganizations/listProjects calls, returning stale mock
data instead of going through the test's globalThis.fetch mock.

Move these files to test/isolated/dsn/ so they run in the separate
test:isolated script, matching the pattern used by resolve-target.test.ts.

Also removes debug logging added in previous commits.
@github-actions
Copy link
Contributor

Codecov Results 📊

✅ Patch coverage is 85.71%. Project has 4061 uncovered lines.
❌ Project coverage is 68.74%. Comparing base (base) to head (head).

Files with missing lines (68)
File Patch % Lines
human.ts 58.29% ⚠️ 395 Missing
resolve-target.ts 20.26% ⚠️ 366 Missing
list.ts 14.39% ⚠️ 345 Missing
api-client.ts 66.23% ⚠️ 231 Missing
list.ts 23.47% ⚠️ 212 Missing
oauth.ts 30.68% ⚠️ 183 Missing
list.ts 21.96% ⚠️ 167 Missing
plan.ts 19.37% ⚠️ 154 Missing
resolver.ts 3.23% ⚠️ 120 Missing
help.ts 19.85% ⚠️ 109 Missing
upgrade.ts 57.71% ⚠️ 107 Missing
view.ts 36.48% ⚠️ 101 Missing
interactive-login.ts 9.17% ⚠️ 99 Missing
errors.ts 5.94% ⚠️ 95 Missing
view.ts 25.81% ⚠️ 92 Missing
view.ts 39.44% ⚠️ 86 Missing
clipboard.ts 4.49% ⚠️ 85 Missing
status.ts 24.07% ⚠️ 82 Missing
migration.ts 47.44% ⚠️ 82 Missing
list.ts 27.18% ⚠️ 75 Missing
browser.ts 4.11% ⚠️ 70 Missing
login.ts 33.33% ⚠️ 64 Missing
span-tree.ts 5.00% ⚠️ 57 Missing
explain.ts 33.33% ⚠️ 56 Missing
api.ts 89.80% ⚠️ 47 Missing
upgrade.ts 66.91% ⚠️ 46 Missing
telemetry.ts 84.72% ⚠️ 46 Missing
seer.ts 75.54% ⚠️ 45 Missing
schema.ts 89.56% ⚠️ 40 Missing
refresh.ts 40.63% ⚠️ 38 Missing
seer.ts 79.87% ⚠️ 30 Missing
preload.ts 53.23% ⚠️ 29 Missing
view.ts 87.27% ⚠️ 28 Missing
utils.ts 88.94% ⚠️ 25 Missing
view.ts 61.54% ⚠️ 25 Missing
detector.ts 90.10% ⚠️ 20 Missing
binary.ts 88.67% ⚠️ 17 Missing
list.ts 91.16% ⚠️ 16 Missing
code-scanner.ts 95.00% ⚠️ 16 Missing
help.ts 57.14% ⚠️ 15 Missing
arg-parsing.ts 90.00% ⚠️ 12 Missing
dsn-cache.ts 94.62% ⚠️ 12 Missing
logout.ts 56.00% ⚠️ 11 Missing
token.ts 52.17% ⚠️ 11 Missing
fix.ts 83.61% ⚠️ 10 Missing
qrcode.ts 33.33% ⚠️ 10 Missing
fs-utils.ts 57.14% ⚠️ 9 Missing
view.ts 94.70% ⚠️ 7 Missing
project-root.ts 97.73% ⚠️ 7 Missing
version-check.ts 91.76% ⚠️ 7 Missing
feedback.ts 84.21% ⚠️ 6 Missing
auth.ts 95.52% ⚠️ 6 Missing
shell.ts 96.23% ⚠️ 6 Missing
app.ts 93.59% ⚠️ 5 Missing
setup.ts 97.84% ⚠️ 4 Missing
list.ts 97.33% ⚠️ 4 Missing
index.ts 95.96% ⚠️ 4 Missing
project-aliases.ts 97.40% ⚠️ 2 Missing
project-root-cache.ts 96.92% ⚠️ 2 Missing
output.ts 89.47% ⚠️ 2 Missing
alias.ts 99.42% ⚠️ 1 Missing
completions.ts 99.37% ⚠️ 1 Missing
env-file.ts 99.19% ⚠️ 1 Missing
parser.ts 98.63% ⚠️ 1 Missing
colors.ts 98.21% ⚠️ 1 Missing
trace.ts 99.16% ⚠️ 1 Missing
helpers.ts 97.62% ⚠️ 1 Missing
helpers.ts 94.74% ⚠️ 1 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
- Coverage    70.11%    68.74%    -1.37%
==========================================
  Files          105       105         —
  Lines        12918     12992       +74
  Branches         0         0         —
==========================================
+ Hits          9057      8931      -126
- Misses        3861      4061      +200
- Partials         0         0         —

Generated by Codecov Action

@BYK BYK merged commit baaa3d3 into main Feb 13, 2026
23 checks passed
@BYK BYK deleted the fix/test-env-var-isolation branch February 13, 2026 17:09
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