Skip to content

Conversation

@danciudev
Copy link
Contributor

@danciudev danciudev commented Dec 25, 2025

Hello, I added the functionality to support custom directories with the “envDir” for the vite plugin

Summary by CodeRabbit

  • New Features

    • Vite plugin now respects Vite's envDir and loads env files from prioritized locations, exposing VITE_ variables.
  • Tests

    • Improved tests and mocking to validate env loading order, mode/envDir/prefix arguments, and full propagation; added integration tests for custom envDir scenarios.
  • Fixtures

    • Added and updated .env fixtures to cover custom envDir, precedence, and extra-variable cases.
  • Chores

    • Release metadata updated for a patch bump.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Dec 25, 2025

🦋 Changeset detected

Latest commit: 9bf741b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@arkenv/vite-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Dec 25, 2025

@Andrei-Danciu-Redslim is attempting to deploy a commit to the yamcodes Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added @arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv tests This issue or PR is about adding, removing or changing tests. labels Dec 25, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 25, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

Compute envDir as config.envDir ?? config.root ?? process.cwd() and pass it to Vite's loadEnv; tests and fixtures updated to validate custom envDir loading, multi-file env precedence, and propagation of loaded vars into createEnv calls.

Changes

Cohort / File(s) Summary
Core implementation
packages/vite-plugin/src/index.ts
Compute envDir = config.envDir ?? config.root ?? process.cwd() and call vite.loadEnv(mode, envDir, "") instead of using process.cwd().
Unit & integration tests
packages/vite-plugin/src/index.test.ts
Replace mocks with spies that wrap real implementations (arkenv and vite.loadEnv), adjust fixture iteration, add/extend per-test mock resets, and add assertions verifying loadEnv and createEnv interactions (including custom envDir scenarios).
New with-env-dir fixture
packages/vite-plugin/src/__fixtures__/with-env-dir/*, packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
Add typed Env schema, fixture config reading import.meta.env, Vite client types ref, and custom env files (VITE_CUSTOM_VAR, VITE_FROM_ENV_DIR, EXTRA_VAR).
Basic fixture updates
packages/vite-plugin/src/__fixtures__/basic/.env.test, packages/vite-plugin/src/__fixtures__/basic/env.test
Update fixture env entries to reflect multi-file env loading and precedence ordering.
Changeset / release note
.changeset/red-peaches-pay.md
Add changeset documenting that the plugin now respects Vite's envDir option.

Sequence Diagram(s)

sequenceDiagram
  %%{init: {"themeVariables":{"actorBorder":"#2b6cb0","actorBackground":"#ebf8ff","noteBackground":"#f0fff4"}}}%%
  participant Vite as Vite (runner)
  participant Plugin as `@arkenv/vite-plugin`
  participant ViteLoadEnv as vite.loadEnv
  participant arkenv as arkenv.createEnv
  participant App as App (import.meta.env)

  Vite->>Plugin: pluginHook(config, mode)
  Plugin->>ViteLoadEnv: loadEnv(mode, envDir, "")
  Note right of ViteLoadEnv: Read .env files from envDir in precedence\n(.env, .env.local, .env.{mode} — later override earlier)
  ViteLoadEnv-->>Plugin: envMap
  Plugin->>arkenv: createEnv(envMap, { mode, root: config.root })
  arkenv-->>Plugin: runtimeEnv (validated)
  Plugin->>Vite: expose runtimeEnv via define/import.meta.env
  Vite->>App: application reads import.meta.env values
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 I hopped through envDir paths with care,
Load files from places I found there,
loadEnv called with mode and dir,
createEnv shaped the vars for your app to infer,
A tidy rabbit, bouncing code with flair.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding support for custom environment directories via Vite's envDir config in the vite-plugin.

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between acb2210 and 9bf741b.

📒 Files selected for processing (1)
  • packages/vite-plugin/src/index.test.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5747c12 and b5f7d10.

📒 Files selected for processing (2)
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/index.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/index.ts
  • packages/vite-plugin/src/index.test.ts
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • packages/vite-plugin/src/index.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • packages/vite-plugin/src/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/index.ts
  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/index.ts
  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/index.ts
  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun:test` for unit and integration testing with `test` and `expect` from the built-in test module

Applied to files:

  • packages/vite-plugin/src/index.test.ts
🔇 Additional comments (2)
packages/vite-plugin/src/index.ts (2)

61-63: LGTM! Clean implementation of envDir support.

The envDir derivation correctly follows Vite's config pattern with proper fallback to process.cwd().


68-68: LGTM! Correct usage of envDir parameter.

The loadEnv call now properly uses the derived envDir variable.

Copy link
Owner

@yamcodes yamcodes left a comment

Choose a reason for hiding this comment

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

Thanks so much for the contribution, @danciudev!
It's a welcome improvement - and I'd definitely like to get it in!

That said, I think the tests can be stronger. As written, they pass both before and after the change in this PR. Ideally, the tests should fail without the change and pass with it, so they actually protect the behavior introduced here and avoid false positives.

I also agree that the unit tests are relatively low-value compared to a real-world plugin test. If you’re up for it, a fixture-based test that initializes the plugin with a custom envDir and verifies the full parsing and validation flow would be awesome and much closer to how the plugin is used in practice.

Let me know if you want any pointers or examples - happy to help!

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 25, 2025

Open in StackBlitz

npm i https://pkg.pr.new/arkenv@614
npm i https://pkg.pr.new/@arkenv/bun-plugin@614
npm i https://pkg.pr.new/@arkenv/vite-plugin@614

commit: acb2210

@danciudev
Copy link
Contributor Author

Sorry for generating them automatically and not checking them in detail. I've added some new ones, check them out and let me know what you think =)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
packages/vite-plugin/src/index.test.ts (2)

531-566: Test doesn't verify custom envDir is actually used.

This test was flagged in a previous review. The assertion only verifies createEnv was called, not that loadEnv received the custom envDir. Without mocking loadEnv, this test passes regardless of whether the envDir feature works.


568-601: Test doesn't verify default envDir behavior.

Same issue as above - this test was flagged in a previous review. It doesn't verify that loadEnv is called with process.cwd() when envDir is not configured.

🧹 Nitpick comments (1)
packages/vite-plugin/src/index.test.ts (1)

687-700: Test appears redundant with "should load environment variables from custom envDir".

This test has identical setup and assertions as the test on lines 641-654. Both tests:

  1. Mock createEnv with expectedEnvVars
  2. Stub env vars with stubEnvVars(expectedEnvVars)
  3. Build with createBuildConfig(customEnvDir, config.Env)
  4. Assert createEnv was called with expectedEnvVars

To meaningfully test "envDir over root" precedence, the test would need to have different values in root vs. envDir and verify the envDir values take priority.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02c8b0d and 59e5fa2.

📒 Files selected for processing (5)
  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/env.test
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/vite-env.d.ts
  • packages/vite-plugin/src/index.test.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/vite-plugin/src/fixtures/with-env-dir/custom-dir/env.test
  • packages/vite-plugin/src/fixtures/with-env-dir/vite-env.d.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
**/index.ts

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Use barrel exports (index.ts) for package entry points

Files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Keep environment variable schemas readable and TypeScript-like using ArkType syntax

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Use ArkEnvError for environment variable errors instead of generic Error types

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{ts,tsx} : For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'development' | 'production' | 'test'")

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Use ArkType's `type()` function to define schemas in environment variable definitions

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Convert ArkType validation errors to `ArkEnvError` for user-friendly error messages that include variable name and expected type

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: Applies to packages/arkenv/**/*.ts : Leverage ArkType's built-in types (e.g., `string.host`, `number.port`) where possible in environment schemas

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-11-24T16:03:45.295Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/arktype.mdc:0-0
Timestamp: 2025-11-24T16:03:45.295Z
Learning: ArkType validates environment variables at runtime and TypeScript types are inferred from the schema definition

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock at component boundaries (network, time, context)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.082Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.082Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Create integration tests with `.integration.test.ts` or `.integration.test.tsx` suffix, testing how multiple units work together without mocking their interactions (except external APIs)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Keep tests fast, deterministic, and parallelizable

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts
🧬 Code graph analysis (2)
packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts (4)
packages/arkenv/src/type.ts (1)
  • type (3-3)
examples/with-vite-react/src/vite-env.d.ts (1)
  • ImportMetaEnv (21-21)
apps/playgrounds/vite-legacy/vite.config.ts (1)
  • env (19-37)
apps/playgrounds/vite/vite.config.ts (1)
  • env (19-37)
packages/vite-plugin/src/index.test.ts (2)
packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts (1)
  • config (2-5)
packages/vite-plugin/src/index.ts (1)
  • config (54-88)
🔇 Additional comments (6)
packages/vite-plugin/src/__fixtures__/with-env-dir/config.ts (1)

1-6: LGTM!

Clean fixture definition following established patterns. The schema correctly uses ArkType's type() helper with string type definitions for the two environment variables. Based on learnings, this properly follows the fixture-based testing pattern for Vite plugin tests.

packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts (1)

1-5: LGTM!

Straightforward fixture that demonstrates accessing environment variables from a custom envDir. The empty string fallbacks handle the case when variables aren't loaded.

packages/vite-plugin/src/index.test.ts (4)

656-673: LGTM!

Valid error handling test that verifies validation errors propagate correctly when envDir points to a non-existent directory.


675-685: LGTM!

Good failure case test with a specific error message assertion, verifying the expected behavior when required environment variables are missing.


702-718: LGTM!

Good test verifying that all environment variables (including those not in the schema) are passed to createEnv. This ensures the plugin doesn't prematurely filter environment variables.


721-728: LGTM!

Clean helper function that reduces test boilerplate. Follows the DRY principle.

@yamcodes
Copy link
Owner

Looks like CI tests fail for an unrelated reason to this PR. Fixing that and taking another look.

@yamcodes
Copy link
Owner

@danciudev

I tested this locally by removing the envDir change - the tests are still passing.
image
That means we still don’t have regression coverage for this change.

Could you adjust one of the tests so it fails without the change and passes with it?
For example, by asserting the envDir passed to loadEnv, or better yet, making the fixture test depend on real .env loading without mocking createEnv.

Once that’s in place, I’m happy to merge.

@yamcodes yamcodes force-pushed the feat/support-custom-env-directory branch from 59e5fa2 to 8db9e70 Compare December 26, 2025 21:52
@yamcodes
Copy link
Owner

@danciudev
Thanks again for the work here, the feature looks solid, I’m going to take this over from here to tighten the tests so we get proper regression coverage, add a Changeset, and then merge.
Really appreciate the contribution 🙌

@danciudev
Copy link
Contributor Author

Hey! Thanks a lot for the kind words 🙌
I’m actually on holiday right now. I was planning to pick this up when I’m back, but please go ahead 😁
It’s a great project, and I’ll try to contribute to other improvements after Christmas.
Thanks again!

@github-actions github-actions bot added the docs Improvements or additions to documentation label Dec 30, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8db9e70 and d195cb8.

📒 Files selected for processing (4)
  • .changeset/red-peaches-pay.md
  • packages/vite-plugin/src/__fixtures__/basic/env.test
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/index.ts
💤 Files with no reviewable changes (1)
  • packages/vite-plugin/src/fixtures/basic/env.test
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/vite-plugin/src/index.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
🧠 Learnings (25)
📓 Common learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
📚 Learning: 2025-12-26T19:27:06.951Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:06.951Z
Learning: In packages/vite-plugin/src/index.test.ts, tests that rely on env.test fixtures are read by the readTestConfig helper and injected via vi.stubEnv into process.env, not loaded by Vite's loadEnv during tests. Treat env.test files as fixtures used for environment setup, and ensure test code does not rely on Vite's loadEnv to read them. If adding new tests that use a similar fixture strategy, follow the same pattern: read fixtures through readTestConfig and stub into process.env, rather than permitting Vite to load them automatically.

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock at component boundaries (network, time, context)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Create integration tests with `.integration.test.ts` or `.integration.test.tsx` suffix, testing how multiple units work together without mocking their interactions (except external APIs)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-26T19:27:11.710Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.

Applied to files:

  • .changeset/red-peaches-pay.md
🪛 GitHub Check: test (latest)
packages/vite-plugin/src/index.test.ts

[failure] 725-725: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should pass all loaded env vars to createEnv, not just schema keys
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "EXTRA_VAR": "extra-value",
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME"
    

[failure] 708-708: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should prioritize envDir over root when both are specified
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME": "/usr/share/gradle-9.2.1",
    

[failure] 663-663: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should load environment variables from custom envDir
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_25f3a22e-138a-47cc-8690-df9b1a6a99cd",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME": "/usr/share/gradle-9.2.1",
    
🪛 GitHub Check: test (lts/*)
packages/vite-plugin/src/index.test.ts

[failure] 725-725: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should pass all loaded env vars to createEnv, not just schema keys
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "EXTRA_VAR": "extra-value",
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME"
    

[failure] 708-708: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should prioritize envDir over root when both are specified
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME": "/usr/share/gradle-9.2.1",
    

[failure] 663-663: [@arkenv/vite-plugin] src/index.test.ts > Custom envDir Configuration (with-env-dir fixture) > should load environment variables from custom envDir
AssertionError: expected "vi.fn()" to be called with arguments: [ {}, { env: ObjectContaining{…} } ]

Received:

1st vi.fn() call:

[
{},
{

  • "env": ObjectContaining {
    
  •   "VITE_CUSTOM_VAR": "custom-value",
    
  •   "VITE_FROM_ENV_DIR": "loaded-from-env-dir",
    
  • "env": {
    
  •   "ACCEPT_EULA": "Y",
    
  •   "ACTIONS_RUNNER_ACTION_ARCHIVE_CACHE": "/opt/actionarchivecache",
    
  •   "AGENT_TOOLSDIRECTORY": "/opt/hostedtoolcache",
    
  •   "ANDROID_HOME": "/usr/local/lib/android/sdk",
    
  •   "ANDROID_NDK": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_HOME": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_NDK_LATEST_HOME": "/usr/local/lib/android/sdk/ndk/29.0.14206865",
    
  •   "ANDROID_NDK_ROOT": "/usr/local/lib/android/sdk/ndk/27.3.13750724",
    
  •   "ANDROID_SDK_ROOT": "/usr/local/lib/android/sdk",
    
  •   "ANT_HOME": "/usr/share/ant",
    
  •   "AZURE_EXTENSION_DIR": "/opt/az/azcliextensions",
    
  •   "BASE_URL": "/",
    
  •   "BOOTSTRAP_HASKELL_NONINTERACTIVE": "1",
    
  •   "CHROMEWEBDRIVER": "/usr/local/share/chromedriver-linux64",
    
  •   "CHROME_BIN": "/usr/bin/google-chrome",
    
  •   "CI": "true",
    
  •   "CONDA": "/usr/share/miniconda",
    
  •   "DEBIAN_FRONTEND": "noninteractive",
    
  •   "DEV": "1",
    
  •   "DOTNET_MULTILEVEL_LOOKUP": "0",
    
  •   "DOTNET_NOLOGO": "1",
    
  •   "DOTNET_SKIP_FIRST_TIME_EXPERIENCE": "1",
    
  •   "EDGEWEBDRIVER": "/usr/local/share/edge_driver",
    
  •   "ENABLE_RUNNER_TRACING": "true",
    
  •   "FORCE_TTY": "",
    
  •   "GECKOWEBDRIVER": "/usr/local/share/gecko_driver",
    
  •   "GHCUP_INSTALL_BASE_PREFIX": "/usr/local",
    
  •   "GITHUB_ACTION": "__run_3",
    
  •   "GITHUB_ACTIONS": "true",
    
  •   "GITHUB_ACTION_REF": "",
    
  •   "GITHUB_ACTION_REPOSITORY": "",
    
  •   "GITHUB_ACTOR": "yamcodes",
    
  •   "GITHUB_ACTOR_ID": "2014360",
    
  •   "GITHUB_API_URL": "https://api.github.com",
    
  •   "GITHUB_BASE_REF": "main",
    
  •   "GITHUB_ENV": "/home/runner/work/_temp/_runner_file_commands/set_env_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_EVENT_NAME": "pull_request",
    
  •   "GITHUB_EVENT_PATH": "/home/runner/work/_temp/_github_workflow/event.json",
    
  •   "GITHUB_GRAPHQL_URL": "https://api.github.com/graphql",
    
  •   "GITHUB_HEAD_REF": "feat/support-custom-env-directory",
    
  •   "GITHUB_JOB": "test",
    
  •   "GITHUB_OUTPUT": "/home/runner/work/_temp/_runner_file_commands/set_output_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_PATH": "/home/runner/work/_temp/_runner_file_commands/add_path_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_REF": "refs/pull/614/merge",
    
  •   "GITHUB_REF_NAME": "614/merge",
    
  •   "GITHUB_REF_PROTECTED": "false",
    
  •   "GITHUB_REF_TYPE": "branch",
    
  •   "GITHUB_REPOSITORY": "yamcodes/arkenv",
    
  •   "GITHUB_REPOSITORY_ID": "922104035",
    
  •   "GITHUB_REPOSITORY_OWNER": "yamcodes",
    
  •   "GITHUB_REPOSITORY_OWNER_ID": "2014360",
    
  •   "GITHUB_RETENTION_DAYS": "90",
    
  •   "GITHUB_RUN_ATTEMPT": "2",
    
  •   "GITHUB_RUN_ID": "20606138902",
    
  •   "GITHUB_RUN_NUMBER": "1007",
    
  •   "GITHUB_SERVER_URL": "https://github.com",
    
  •   "GITHUB_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_STATE": "/home/runner/work/_temp/_runner_file_commands/save_state_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_STEP_SUMMARY": "/home/runner/work/_temp/_runner_file_commands/step_summary_02d8aeda-f0fa-403e-a724-e07ab5a1ca9b",
    
  •   "GITHUB_TRIGGERING_ACTOR": "yamcodes",
    
  •   "GITHUB_WORKFLOW": "test",
    
  •   "GITHUB_WORKFLOW_REF": "yamcodes/arkenv/.github/workflows/test.yml@refs/pull/614/merge",
    
  •   "GITHUB_WORKFLOW_SHA": "31d605fdde6fb8b6ae4532a123fd5ae9f6fe3e80",
    
  •   "GITHUB_WORKSPACE": "/home/runner/work/arkenv/arkenv",
    
  •   "GOROOT_1_22_X64": "/opt/hostedtoolcache/go/1.22.12/x64",
    
  •   "GOROOT_1_23_X64": "/opt/hostedtoolcache/go/1.23.12/x64",
    
  •   "GOROOT_1_24_X64": "/opt/hostedtoolcache/go/1.24.11/x64",
    
  •   "GOROOT_1_25_X64": "/opt/hostedtoolcache/go/1.25.5/x64",
    
  •   "GRADLE_HOME": "/usr/share/gradle-9.2.1",
    
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-build (latest)
  • GitHub Check: test-build (lts/*)
  • GitHub Check: test-typesafety
🔇 Additional comments (6)
.changeset/red-peaches-pay.md (1)

1-7: LGTM! Clear changeset documentation.

The changeset appropriately documents this patch-level feature addition with a clear description and helpful reference to Vite's documentation.

packages/vite-plugin/src/index.test.ts (5)

13-20: Good: Mock setup addresses previous false-positive concerns.

The mock correctly wraps loadEnv to capture calls while preserving its behavior, enabling verification that the plugin passes the correct envDir argument. This addresses the false-positive issue identified in previous reviews where tests passed regardless of the PR changes.


27-29: LGTM: Proper mock management.

Mock references are correctly retrieved and consistently cleaned up in test hooks across all test suites.

Also applies to: 40-40, 47-47, 87-87, 93-93


537-574: LGTM: Unit test properly guards envDir behavior.

This test correctly verifies that loadEnv is called with the custom envDir parameter, addressing the false-positive issue from previous reviews. The test will now fail if the PR's envDir handling is removed.


576-612: LGTM: Default envDir behavior properly tested.

This test correctly verifies that the plugin defaults to process.cwd() when envDir is not configured, providing good coverage for the fallback behavior.


742-756: The concern raised in this review is based on outdated learnings that do not match the actual codebase implementation.

Investigation findings:

  • The readTestConfig helper intentionally reads from optional .env files (if present) and returns them as envVars
  • These envVars are used in test mocks: mockCreateEnv.mockReturnValue(config.envVars || {})
  • The test does not use vi.stubEnv or stub process.env; instead, it mocks the createEnv function directly
  • Neither env.test nor .env files currently exist in the fixtures, which is fine—the code handles missing files gracefully with exception catching

The retrieved learnings about env.test files and vi.stubEnv do not reflect the actual testing pattern implemented here. The current approach of optionally reading .env files and passing them to mocked createEnv is a valid design choice and consistent with the fixture structure.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/vite-plugin/src/index.test.ts (1)

743-758: Update readTestConfig to look for mode-specific .env files.

The function now reads from .env (line 746), but the fixture files are named .env.test to match Vite's convention for test mode. This mismatch causes fixture variables not to be loaded.

🔎 Proposed fix

Update the function to try multiple file names in order of precedence:

-// Read environment variables from .env file if it exists
+// Read environment variables from .env files (try mode-specific first)
 let envVars: Record<string, string> = {};
+const envFiles = [".env.test", ".env.local", ".env"];
+
+for (const envFile of envFiles) {
   try {
-    const envContent = readFileSync(join(fixtureDir, ".env"), "utf-8");
+    const envContent = readFileSync(join(fixtureDir, envFile), "utf-8");
     envVars = Object.fromEntries(
       envContent
         .split("\n")
         .filter((line) => line.trim() && !line.startsWith("#"))
         .map((line) => {
           const [key, ...valueParts] = line.split("=");
           return [key.trim(), valueParts.join("=").trim()];
         }),
     );
+    break; // Stop after first successful read
   } catch {
-    // .env file doesn't exist, that's fine
+    // Try next file
   }
+}

This aligns with Vite's loadEnv behavior and allows fixtures to use mode-specific naming.

Based on learnings, the test suite previously used env.test files (without leading dot) that were manually read. The switch to .env files should match what Vite's loadEnv expects.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d195cb8 and 9ae1b8e.

📒 Files selected for processing (3)
  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
  • packages/vite-plugin/src/index.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
🧠 Learnings (27)
📓 Common learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
📚 Learning: 2025-12-26T19:27:11.710Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.

Applied to files:

  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/__fixtures__/basic/.env.test
  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-26T19:27:06.951Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:06.951Z
Learning: In packages/vite-plugin/src/index.test.ts, tests that rely on env.test fixtures are read by the readTestConfig helper and injected via vi.stubEnv into process.env, not loaded by Vite's loadEnv during tests. Treat env.test files as fixtures used for environment setup, and ensure test code does not rely on Vite's loadEnv to read them. If adding new tests that use a similar fixture strategy, follow the same pattern: read fixtures through readTestConfig and stub into process.env, rather than permitting Vite to load them automatically.

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock at component boundaries (network, time, context)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
  • packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Create integration tests with `.integration.test.ts` or `.integration.test.tsx` suffix, testing how multiple units work together without mocking their interactions (except external APIs)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Keep tests fast, deterministic, and parallelizable

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:11.901Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/monorepo.mdc:0-0
Timestamp: 2025-11-24T16:04:11.901Z
Learning: Applies to examples/*/package.json : Examples in examples/ directory are not published, may have their own lock files, and are used as test fixtures

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use the dotenv package

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')

Applied to files:

  • packages/vite-plugin/src/index.test.ts
🧬 Code graph analysis (1)
packages/vite-plugin/src/index.test.ts (2)
packages/vite-plugin/src/index.ts (1)
  • config (54-88)
packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts (1)
  • config (2-5)
🪛 dotenv-linter (4.0.0)
packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test

[warning] 3-3: [UnorderedKey] The EXTRA_VAR key should go before the VITE_CUSTOM_VAR key

(UnorderedKey)

🔇 Additional comments (4)
packages/vite-plugin/src/index.test.ts (2)

13-20: LGTM! Proper mocking setup for unit tests.

The loadEnv mock setup correctly preserves the actual implementation while allowing call assertions, which is appropriate for the unit tests at lines 537-612.

However, note that this mock should be disabled for the integration tests at lines 615-730 to enable actual file loading from fixtures (see separate comment on those tests).


537-612: Unit tests correctly verify envDir is passed to loadEnv.

These tests now properly assert that loadEnv is called with the correct envDir parameter (custom or default), addressing the false positive issue identified in previous reviews.

The assertions at lines 565 and 603 ensure the tests would fail if the PR's envDir logic were removed, providing proper regression coverage for the unit test layer.

packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test (1)

1-3: Rename fixture to .env.test files that Vite's loadEnv will recognize.

This file is named .env.test, but there's a critical mismatch in how it's being used:

  1. The readTestConfig helper (line 746 in index.test.ts) looks for .env files
  2. Vite's loadEnv in test mode looks for .env, .env.test, .env.local, and .env.test.local
  3. The integration tests are failing (see pipeline failures) because the full process.env is being passed instead of these fixture variables
🔎 Proposed fix

Since these tests run in test mode and use Vite's loadEnv, the fixture file naming is actually correct (.env.test). However, the integration tests are currently mocking loadEnv, which prevents it from reading this file.

Option 1 (Recommended): Keep this filename and unmock loadEnv in the integration tests at lines 615-730 so Vite actually reads this fixture file.

Option 2: Rename to .env and update readTestConfig to look for .env.test as a fallback:

mv packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env.test \
   packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/.env

This issue is causing the test failures visible in the pipeline checks, where expect.objectContaining assertions fail because the env contains all of process.env instead of just the fixture variables.

⛔ Skipped due to learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Use *.integration.test.ts suffix to distinguish integration tests from unit tests
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies
packages/vite-plugin/src/__fixtures__/basic/.env.test (1)

1-2: Rename fixture to .env to match readTestConfig expectations.

The fixture file is named .env.test, but the readTestConfig helper function (line 746 in index.test.ts) now reads from .env files. This mismatch means the fixture variables won't be loaded during tests.

🔎 Proposed fix

Rename this file from .env.test to .env:

mv packages/vite-plugin/src/__fixtures__/basic/.env.test packages/vite-plugin/src/__fixtures__/basic/.env

Alternatively, if test-mode-specific fixtures are intended, update readTestConfig to read from .env.test files, or ensure Vite's loadEnv can find these files during test mode.

Based on learnings, the previous convention used env.test files (without leading dot) that were manually read and stubbed. The new approach attempts to use .env files that Vite's loadEnv can read naturally, but the fixture naming doesn't match the implementation.

⛔ Skipped due to learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun test` instead of `jest` or `vitest` for running tests
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

…est` and `.env.local` for environment variable loading.
…tation and remove explicit `createEnv` return value mocks.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/vite-plugin/src/index.test.ts (1)

545-582: Redundant local variable shadows module-level mock.

Line 546 re-declares mockLoadEnv when the module-level declaration at line 33 is already in scope. This works but adds unnecessary code.

🔎 Proposed fix
 	it("should use custom envDir when provided in config", async () => {
-		const mockLoadEnv = vi.mocked(vite.loadEnv);
 		mockCreateEnv.mockReturnValue({ VITE_TEST: "test" });
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ae1b8e and 0b3987f.

📒 Files selected for processing (1)
  • packages/vite-plugin/src/index.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
🧠 Learnings (26)
📓 Common learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
📚 Learning: 2025-12-26T19:27:06.951Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:06.951Z
Learning: In packages/vite-plugin/src/index.test.ts, tests that rely on env.test fixtures are read by the readTestConfig helper and injected via vi.stubEnv into process.env, not loaded by Vite's loadEnv during tests. Treat env.test files as fixtures used for environment setup, and ensure test code does not rely on Vite's loadEnv to read them. If adding new tests that use a similar fixture strategy, follow the same pattern: read fixtures through readTestConfig and stub into process.env, rather than permitting Vite to load them automatically.

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock at component boundaries (network, time, context)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Create integration tests with `.integration.test.ts` or `.integration.test.tsx` suffix, testing how multiple units work together without mocking their interactions (except external APIs)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Keep tests fast, deterministic, and parallelizable

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun:test` for unit and integration testing with `test` and `expect` from the built-in test module

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use ArkEnvError for environment variable errors instead of generic Error types

Applied to files:

  • packages/vite-plugin/src/index.test.ts
🧬 Code graph analysis (1)
packages/vite-plugin/src/index.test.ts (3)
packages/vite-plugin/src/index.ts (1)
  • config (54-88)
packages/vite-plugin/src/__fixtures__/with-env-dir/index.ts (1)
  • config (2-5)
packages/vite-plugin/src/__fixtures__/basic/index.ts (1)
  • config (2-5)
🔇 Additional comments (6)
packages/vite-plugin/src/index.test.ts (6)

7-24: Well-structured mock setup that enables both unit and integration testing.

The use of vi.fn(actual.createEnv) and vi.fn(actual.loadEnv) creates spies that delegate to the real implementations by default. This addresses the previous review concerns about over-mocking - unit tests can override with mockReturnValue when needed, while integration tests use the real behavior.


35-39: Good separation of specialized fixtures.

Excluding with-env-dir from the generic fixture loop and handling it in dedicated integration tests (lines 623-723) improves test clarity and allows for custom assertions specific to envDir behavior.


584-620: Good regression test for default envDir behavior.

This test now properly verifies that loadEnv is called with process.cwd() when envDir is not configured, addressing the previous review feedback about needing to guard this behavior.


663-673: Good integration test for custom envDir loading.

This test validates that environment variables are loaded from the custom envDir and passed correctly to createEnv. The assertion with expect.objectContaining(expectedEnvVars) properly verifies the loaded values.


709-722: Good test for verifying all env vars are propagated.

This test validates that the plugin passes all loaded environment variables to createEnv, not just the ones defined in the schema. This ensures the plugin doesn't filter out variables prematurely.


736-756: Improved env file reading with proper fallback strategy.

The updated readTestConfig now attempts to read from .env.test, .env.local, and .env in order, which better aligns with Vite's mode-specific env file loading behavior. The value parsing correctly handles = signs in values via valueParts.join("=").

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/vite-plugin/src/index.test.ts (1)

735-755: readTestConfig reads only one .env file instead of merging like Vite's loadEnv.

readTestConfig loads the first existing file from [".env.test", ".env.local", ".env"] and breaks (line 751), whereas Vite's loadEnv merges multiple files with later ones overriding earlier ones (.env.env.local.env.test.env.test.local).

For single-file fixtures this works, but if testing precedence behavior (e.g., line 696 "should prioritize envDir over root") with multiple env files, readTestConfig won't produce the same merged result as loadEnv. Consider updating to merge all existing files in order, or document this limitation.

🔎 Proposed refactor to merge env files like Vite
-  // Read environment variables from .env files (try mode-specific first)
+  // Read and merge environment variables from .env files (matching Vite's loadEnv behavior)
   let envVars: Record<string, string> = {};
   const envFiles = [".env.test", ".env.local", ".env"];

   for (const envFile of envFiles) {
     try {
       const envContent = readFileSync(join(fixtureDir, envFile), "utf-8");
-      envVars = Object.fromEntries(
+      const fileVars = Object.fromEntries(
         envContent
           .split("\n")
           .filter((line) => line.trim() && !line.startsWith("#"))
           .map((line) => {
             const [key, ...valueParts] = line.split("=");
             return [key.trim(), valueParts.join("=").trim()];
           }),
       );
-      break; // Stop after first successful read
+      // Merge with precedence: later files override earlier ones
+      envVars = { ...envVars, ...fileVars };
     } catch {
       // Try next file
     }
   }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b3987f and acb2210.

📒 Files selected for processing (2)
  • packages/vite-plugin/src/__fixtures__/with-env-dir/empty-dir/.gitkeep
  • packages/vite-plugin/src/index.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

**/*.{ts,tsx}: Prefer type over interface for type definitions in TypeScript
Use TypeScript 5.1+ features when appropriate
Leverage const type parameters for better inference in TypeScript
Use JSDoc comments for public APIs
Use tabs for indentation (configured in Biome)
Use double quotes for strings (configured in Biome)
Organize imports automatically (Biome handles this)
Avoid explicit types when TypeScript can infer them (noInferrableTypes error)
Use as const where appropriate for immutable values (useAsConstAssertion error)
Don't reassign function parameters (noParameterAssign error)
Place default parameters last in function signatures (useDefaultParameterLast error)
Always initialize enum values (useEnumInitializers error)
Declare one variable per statement (useSingleVarDeclarator error)
Avoid unnecessary template literals (noUnusedTemplateLiteral error)
Prefer Number.parseInt over global parseInt (useNumberNamespace error)
Use kebab-case for TypeScript filenames (e.g., create-env.ts)
Use camelCase for function names (e.g., createEnv)
Use PascalCase for type names (e.g., ArkEnvError)
Use UPPER_SNAKE_CASE for environment variables and constants
Include examples in JSDoc comments when helpful for public APIs
Document complex type logic with JSDoc comments
Use ArkEnvError for environment variable validation errors
Provide clear, actionable error messages that include the variable name and expected type

**/*.{ts,tsx}: Use createEnv(schema) function (or default import as arkenv) to create validated environment objects in TypeScript
Use built-in validators (host, port, url, email) from ArkEnv when available instead of custom ArkType schemas
Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')
Use ArkEnvError for environment variable errors instead of generic Error types
For environment schema definition, use ArkType string literal syntax for enumerated values (e.g., "'deve...

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/coding-guidelines.mdc)

Co-locate tests with components: Component.tsx next to Component.test.tsx

**/*.test.{ts,tsx}: Use Vitest for unit and integration tests
Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests
Unit tests should focus on individual function logic and edge cases, component rendering and props, error handling and validation, and type checking
Unit tests should execute in less than 100ms per test
Mock external dependencies (clipboard, network, etc.) in unit tests
Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
Test component behavior, not aesthetics, and focus on what users can do and what the component guarantees through its API
Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests
Do not test pure styling or CSS classes, library internals (Radix/shadcn), implementation details (hooks, setState, private variables), or visual variants in component tests
Use Testing Library with user-event for real user simulation in component tests
Query by role, name, label, and text (accessibility first) in component tests
Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible
Keep tests fast, deterministic, and parallelizable
Mock at component boundaries (network, time, context)

Create unit tests with .test.ts or .test.tsx suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Files:

  • packages/vite-plugin/src/index.test.ts
packages/vite-plugin/src/**/*.test.ts

📄 CodeRabbit inference engine (.cursor/rules/test-patterns.mdc)

packages/vite-plugin/src/**/*.test.ts: Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Use fixture-based testing pattern for Vite plugin tests by placing fixtures in fixtures directory

Files:

  • packages/vite-plugin/src/index.test.ts
**/*.{test,integration.test}.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,integration.test}.{ts,tsx}: Use Vitest's describe/it structure for all test files
Test both success and failure cases in unit and integration tests
Mock process.env in unit tests to test different environment variable scenarios

Files:

  • packages/vite-plugin/src/index.test.ts
🧠 Learnings (27)
📓 Common learnings
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:11.710Z
Learning: In packages/vite-plugin/src/**/*.test.ts: The test suite uses `env.test` files (without leading dot) as test fixtures that are manually read by the `readTestConfig` helper function and stubbed into process.env with `vi.stubEnv`, not as files to be read by Vite's loadEnv during tests.
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)
📚 Learning: 2025-12-26T19:27:06.951Z
Learnt from: danciudev
Repo: yamcodes/arkenv PR: 614
File: packages/vite-plugin/src/index.test.ts:641-654
Timestamp: 2025-12-26T19:27:06.951Z
Learning: In packages/vite-plugin/src/index.test.ts, tests that rely on env.test fixtures are read by the readTestConfig helper and injected via vi.stubEnv into process.env, not loaded by Vite's loadEnv during tests. Treat env.test files as fixtures used for environment setup, and ensure test code does not rely on Vite's loadEnv to read them. If adding new tests that use a similar fixture strategy, follow the same pattern: read fixtures through readTestConfig and stub into process.env, rather than permitting Vite to load them automatically.

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Use fixture-based testing pattern for Vite plugin tests by placing fixtures in __fixtures__ directory

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Mock `process.env` in unit tests to test different environment variable scenarios

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to packages/vite-plugin/src/**/*.test.ts : Test the Vite plugin using the with-vite-react example as a fixture and validate that the plugin works with real Vite projects

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test individual functions, components, and hooks in isolation with mocked dependencies in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Test how multiple units (components, hooks, functions) work together without mocking their interactions in integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock at component boundaries (network, time, context)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Test component public API (props, events, and component contract), user behavior (clicks, typing, focus, keyboard, ARIA), state transitions, accessibility, and side effects in component tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.test.{ts,tsx} : Create unit tests with `.test.ts` or `.test.tsx` suffix located alongside source files, testing individual functions and components in isolation with mocked dependencies

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies (clipboard, network, etc.) in unit tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Co-locate unit test files with source files using naming convention: source file → test file (e.g., create-env.ts → create-env.test.ts)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use Vitest for unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use `createEnv(schema)` function (or default import as `arkenv`) to create validated environment objects in TypeScript

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Integration tests should focus on component and hook interactions, function composition and data flow, real dependencies between units, and state synchronization across boundaries

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Test both success and failure cases in unit and integration tests

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.integration.test.{ts,tsx} : Create integration tests with `.integration.test.ts` or `.integration.test.tsx` suffix, testing how multiple units work together without mocking their interactions (except external APIs)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Keep tests fast, deterministic, and parallelizable

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use descriptive environment variable names that indicate purpose and format (e.g., DATABASE_URL, NODE_ENV, FEATURE_FLAG)

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{test,integration.test}.{ts,tsx} : Use Vitest's `describe`/`it` structure for all test files

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-12T13:20:01.954Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/test-patterns.mdc:0-0
Timestamp: 2025-12-12T13:20:01.954Z
Learning: Applies to **/*.test.{ts,tsx} : Use beforeEach/afterEach for cleanup, not beforeAll/afterAll when possible

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:47.583Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun-react/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:47.583Z
Learning: Applies to apps/playgrounds/bun-react/**/*.test.{ts,tsx,js,jsx} : Use `bun:test` for unit and integration testing with `test` and `expect` from the built-in test module

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Provide default values for optional environment variables using ArkType syntax (e.g., 'boolean = false')

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use UPPER_SNAKE_CASE for environment variables and constants

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:58.629Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: apps/playgrounds/bun/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc:0-0
Timestamp: 2025-11-24T16:04:58.629Z
Learning: Applies to apps/playgrounds/bun/**/*.{ts,tsx,js,jsx} : Bun automatically loads .env files, so don't use `dotenv` library

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-11-24T16:04:00.957Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .cursor/rules/coding-guidelines.mdc:0-0
Timestamp: 2025-11-24T16:04:00.957Z
Learning: Applies to **/*.{ts,tsx} : Use `ArkEnvError` for environment variable validation errors

Applied to files:

  • packages/vite-plugin/src/index.test.ts
📚 Learning: 2025-12-23T07:09:57.130Z
Learnt from: CR
Repo: yamcodes/arkenv PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T07:09:57.130Z
Learning: Applies to **/*.{ts,tsx} : Use ArkEnvError for environment variable errors instead of generic Error types

Applied to files:

  • packages/vite-plugin/src/index.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test-e2e (a11y)
  • GitHub Check: test-e2e (e2e)
  • GitHub Check: test-typesafety
  • GitHub Check: test-build (latest)
  • GitHub Check: test-build (lts/*)
🔇 Additional comments (4)
packages/vite-plugin/src/index.test.ts (4)

7-24: Spy-wrapped mock pattern enables effective integration testing.

The updated mock setup preserves real implementations while enabling call verification. Using importActual + vi.fn() wrappers allows tests to validate arguments passed to loadEnv and createEnv while exercising actual behavior, addressing previous concerns about over-mocking.


545-619: Unit tests provide proper regression coverage for envDir feature.

These tests directly verify that loadEnv receives the correct envDir argument (custom path or process.cwd() default). The assertions on lines 572 and 610 would fail if the envDir feature were removed, addressing the regression coverage gap noted in the PR objectives.


658-659: Correct use of mockClear for cleanup.

Using mockClear() instead of mockReset() preserves the spy-to-real-implementation binding established by vi.fn(actual.createEnv) and vi.fn(actual.loadEnv), while clearing call history between tests. This addresses the previous review concern about mockReset() breaking the spy wrapper.


662-694: Verify fixture directory structure and .env file naming.

The integration tests expect:

  1. packages/vite-plugin/src/__fixtures__/with-env-dir/custom-dir/ containing .env.test with environment variables
  2. packages/vite-plugin/src/__fixtures__/with-env-dir/empty-dir/ (empty directory)

All fixtures are correctly in place. The custom-dir/.env.test file contains the expected variables (VITE_CUSTOM_VAR, VITE_FROM_ENV_DIR, EXTRA_VAR), and readTestConfig properly reads them by checking .env.test first (then .env.local, then .env), matching Vite's test mode behavior. The empty-dir is empty as required for testing the failure case.

@yamcodes yamcodes merged commit b5f2781 into yamcodes:main Dec 30, 2025
3 of 4 checks passed
@arkenv-bot arkenv-bot bot mentioned this pull request Dec 30, 2025
@yamcodes
Copy link
Owner

Hey! Thanks a lot for the kind words 🙌 I’m actually on holiday right now. I was planning to pick this up when I’m back, but please go ahead 😁 It’s a great project, and I’ll try to contribute to other improvements after Christmas. Thanks again!

@danciudev thank you, and, of course! Merry christmas and a happy new year!

Excited to see more from you 😁

@all-contributors add @danciudev for code

@allcontributors
Copy link
Contributor

@yamcodes

I've put up a pull request to add @danciudev! 🎉

yamcodes pushed a commit that referenced this pull request Dec 30, 2025
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @arkenv/[email protected]

### Patch Changes

- #### Support Vite's `envDir` for custom env directories
_[`#614`](#614)
[`b5f2781`](b5f2781)
[@danciudev](https://github.com/danciudev)_

The plugin now internally passes along [Vite's `envDir` config
option](https://vite.dev/config/shared-options.html#envdir), allowing
users to specify a custom directory for environment files.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
yamcodes pushed a commit that referenced this pull request Dec 30, 2025
Adds @danciudev as a contributor for code.

This was requested by yamcodes [in this
comment](#614 (comment))

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

@arkenv/vite-plugin Issues or Pull Requests involving the Vite plugin for ArkEnv docs Improvements or additions to documentation tests This issue or PR is about adding, removing or changing tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants