This project uses a comprehensive testing approach that combines unit tests, integration tests, and end-to-end tests to ensure reliability across all layers.
"Examples as Test Fixtures" - Examples serve dual purposes:
- Documentation - Show real-world usage patterns
- Test Fixtures - Provide real projects to test against
"Test the User Journey" - End-to-end tests validate complete user workflows in real applications.
This ensures the library works in real scenarios while keeping examples clean and validating user experiences.
Test behavior, not aesthetics. Focus on what users can do and what the component guarantees through its API.
- Public API - props, events, and component contract
- User behavior - clicks, typing, focus, keyboard, ARIA
- State transitions - loading, success, error, disabled states
- Accessibility - focus order, keyboard activation, aria attributes
- Side effects - UI changes that affect user experience
- Pure styling or CSS classes
- Library internals (Radix/shadcn/MUI)
- Implementation details (hooks, setState, private variables)
- Visual variants (use Storybook instead)
- Use Testing Library + user-event for real user simulation
- Query by role, name, label, and text (accessibility first)
- Mock at component boundaries (network, time, context)
- Keep tests fast, deterministic, and parallelizable
- Co-locate tests:
Component.tsxnext toComponent.test.tsx
What: Test individual functions, components, and hooks in isolation with mocked dependencies.
Focus:
- Individual function logic and edge cases
- Component rendering and props
- Error handling and validation
- Type checking
Examples:
create-env.test.ts- TestscreateEnvfunction with mocked environment variablescopy-button.test.tsx- TestsCopyButtoncomponent with mocked clipboard and toastuse-toast.test.ts- TestsuseToasthook in isolation
Key Characteristics:
- Fast execution (< 100ms per test)
- Mocked external dependencies (clipboard, network, etc.)
- Focused on single unit behavior
What: Test how multiple units (components, hooks, functions) work together without mocking their interactions.
Focus:
- Component + Hook interactions
- Function composition and data flow
- Real dependencies between units
- State synchronization across boundaries
Examples:
custom-types.integration.test.ts- TestscreateEnv+scope+ custom types working togethererror.integration.test.ts- Tests error propagation throughcreateEnv+formatErrors+ArkEnvErrorcopy-button.integration.test.tsx- TestsCopyButton+useToast+Toasteras a complete flowheading.integration.test.tsx- TestsHeading+useIsMobileresponding to viewport changestoaster.integration.test.tsx- TestsuseToasthook +Toastercomponent state synchronization
Key Characteristics:
- Slower than unit tests (100ms - 2000ms per test)
- Real interactions between units (not mocked)
- External APIs still mocked (clipboard, network)
- Verifies integration contracts
Naming Convention: Use *.integration.test.ts suffix to distinguish from unit tests.
What: Fixture-based tests using real example projects.
Focus:
- Plugin integration with Vite
- Environment variable loading and injection
- Build-time validation
Key Characteristics:
- Uses real example projects as test fixtures
- Validates complete build process
- Ensures plugin works in real-world scenarios
What: Test complete user workflows in the www application using real browsers.
Focus:
- Complete user journeys in production-like environments
- Real browser behavior across Chromium, Firefox, and WebKit
- Visual rendering and interactions
- Network requests and loading states
Key Characteristics:
- Slowest tests (multiple seconds per test)
- No mocking - tests real application
- Cross-browser compatibility testing
- Catches issues that unit and integration tests might miss
# Run all tests (unit + integration)
pnpm test -- --run
# Run only unit tests (arkenv package)
pnpm test --project arkenv -- --run
# Run only integration tests (across all packages)
pnpm test -- --run "integration"
# Run integration tests for specific package
pnpm test --project arkenv -- --run "integration"
pnpm test --project arkenv.js.org -- --run "integration"
# Run only Vite plugin tests
pnpm test --project vite-plugin -- --run
# Run end-to-end tests
pnpm run test:e2e
# Run e2e tests with UI
pnpm run test:e2e:ui
# Run e2e tests in headed mode
pnpm run test:e2e:headedUnit Tests:
- ✅ Environment variable parsing and validation
- ✅ Type checking and error handling
- ✅ Default value handling
- ✅ Custom type validation (host, port, etc.)
- ✅ Individual function behavior
Integration Tests:
- ✅ Custom types working with
createEnv(custom-types.integration.test.ts) - ✅ Error propagation through validation pipeline (
error.integration.test.ts) - ✅ Array defaults with type validation (
array-defaults.integration.test.ts)
- ✅ Plugin integration with Vite
- ✅ Environment variable loading and injection
- ✅ Real project build testing using the example as a fixture
- ✅ Error handling for missing environment variables
Unit Tests:
- ✅ Individual component rendering and behavior
- ✅ Hook functionality in isolation
- ✅ Utility functions and helpers
Integration Tests:
- ✅ CopyButton + useToast + Toaster workflow (
copy-button.integration.test.tsx) - ✅ Heading + useIsMobile responsive behavior (
heading.integration.test.tsx) - ✅ useToast + Toaster state synchronization (
toaster.integration.test.tsx)
End-to-End Tests:
- ✅ Application loads correctly across all browsers
- ✅ Basic HTML structure validation
- ✅ Console error monitoring and reporting
- ✅ Screenshot capture for visual verification
- ✅ Cross-browser compatibility (Chromium, Firefox, WebKit)
Examples are kept clean and focused on demonstrating usage:
examples/basic- Basic Node.js usageexamples/with-bun- Bun runtime usage
The CI pipeline runs:
- Unit tests for core functionality
- Integration tests for the Vite plugin using real examples
- End-to-end tests for the www application across multiple browsers
- Ensures no regressions in real-world usage scenarios
- Validates complete user journeys in production-like environments