Skip to content

Testing

ElyOS uses three testing layers to ensure code quality.

ToolTypeRun commandDocumentation
VitestUnit testsbun testVitest →
fast-checkProperty-based testsbun test:pbtProperty-based →
PlaywrightE2E testsbunx playwright testE2E →

Important: Tests must be run from the apps/web directory.

Purpose: Testing individual functions, classes, and components in isolation.

Examples:

  • Utility functions (formatting, validation, calculations)
  • Store state management
  • Server action logic
  • Database repository functions

Advantages:

  • Fast execution
  • Simple debugging
  • Precise error reporting

Details →


Purpose: Checking invariants with random inputs.

Examples:

  • Mathematical properties (commutative, associative)
  • Data structure invariants
  • Validation logic
  • Pagination calculations

Advantages:

  • Automatic testing of many edge cases
  • Discovering hidden bugs
  • Documenting specifications

Details →


Purpose: Testing complete user flows in a browser.

Examples:

  • Login flow
  • Opening and using applications
  • Form filling and saving
  • Navigation and routing

Advantages:

  • Testing real user experience
  • Browser compatibility
  • Detecting visual regressions

Details →


/\
/ \ E2E (Playwright)
/ \ - Few, slow, brittle
/------\
/ \ Property-based (fast-check)
/ \ - Medium quantity, invariants
/------------\
/ \ Unit (Vitest)
\______________/ - Many, fast, stable
Terminál
# Unit tests
cd apps/web && bun test
# Property-based tests
cd apps/web && bun test:pbt
# E2E tests
cd apps/web && bunx playwright test
# Watch mode (during development)
cd apps/web && bunx vitest

Detailed commands: Scripts reference →

  • Filename: [filename].test.ts or [filename].spec.ts
  • Location: Next to the tested file
  • Describe block: Name of the tested unit
  • It block: Description of specific behavior
  • Pattern: Arrange-Act-Assert
  • Coverage: At least one test for every public function
  • Edge cases: Test empty input, null, boundary values

Generating random but realistic test data:

import { faker } from '@faker-js/faker';
const testUser = {
name: faker.person.fullName(),
email: faker.internet.email(),
password: faker.internet.password({ length: 12 })
};