Files
SnapOtter/vitest.config.ts
T
ashim-hq babca4cf97 test: comprehensive test coverage expansion (+965 tests)
Add 42 new test files covering all untested tool routes, image engine
internals, AI sidecar bridge, Zustand stores, and cross-format
compatibility. Expand e2e-docker suite with 7 spec files covering all
48 tools against a real Docker container.

Unit tests:
- Image engine: format detection, MIME mapping, metadata parsing, pipeline
- AI bridge: sidecar lifecycle, all 11 tool functions (mocked)
- Web stores: 14 Zustand stores (collage, settings, features, analytics, etc.)
- API helpers: format decoders, page range, file validation

Integration tests:
- 25 tool routes that had zero dedicated tests
- Cross-format matrix: 17 input formats x 3 tools
- Edge cases: zero-byte files, corrupted headers, path traversal, XSS, SQL injection
- Concurrent request handling and pipeline edge cases

E2E-Docker (Playwright against real container):
- 7 spec files: essential, adjustment, conversion, creative, utility, AI, pipeline
- Custom buildMultipart helper for multi-file tool uploads
- AI tools gracefully skip when sidecar not installed

Fixtures:
- Organized test media: formats/ (18 formats) + content/ (17 content types)
- Reduced from 3.1 GB unorganized samples to 33 MB structured fixtures

Bug fix:
- color-adjustments: gamma exposure used invalid single-param gamma() for
  positive values; fixed to use two-param gamma(gammaIn, gammaOut) form
2026-04-23 17:12:02 +08:00

104 lines
3.9 KiB
TypeScript

import crypto from "node:crypto";
import os from "node:os";
import path from "node:path";
import { defineConfig } from "vitest/config";
// Resolve api-workspace packages that pnpm only exposes under apps/api/node_modules.
const apiNodeModules = path.resolve(__dirname, "apps/api/node_modules");
// Resolve web-workspace packages that pnpm only exposes under apps/web/node_modules.
const webNodeModules = path.resolve(__dirname, "apps/web/node_modules");
// Temp dir for integration test DB + workspace (set BEFORE any app code loads)
const testDir = path.join(os.tmpdir(), `ashim-test-${crypto.randomUUID().slice(0, 8)}`);
export default defineConfig({
test: {
globals: true,
testTimeout: 30_000,
hookTimeout: 30_000,
// Run all test files in a single forked process so integration tests share
// the same SQLite connection and avoid SQLITE_BUSY races on WAL setup.
pool: "forks",
poolOptions: {
forks: {
singleFork: true,
},
},
exclude: [
"tests/e2e/**",
"tests/e2e-docker/**",
"**/node_modules/**",
"**/dist/**",
"**/.{idea,git,cache,output,temp}/**",
".worktrees/**",
".claude/**",
],
// These env vars are injected into process.env BEFORE test files are
// imported, ensuring apps/api/src/config.ts picks them up correctly.
env: {
AUTH_ENABLED: "true",
DEFAULT_USERNAME: "admin",
DEFAULT_PASSWORD: "Adminpass1",
DB_PATH: path.join(testDir, "test.db"),
WORKSPACE_PATH: path.join(testDir, "workspace"),
MAX_UPLOAD_SIZE_MB: "10",
MAX_BATCH_SIZE: "10",
RATE_LIMIT_PER_MIN: "10000",
MAX_USERS: "50",
MAX_MEGAPIXELS: "100",
CONCURRENT_JOBS: "3",
FILE_MAX_AGE_HOURS: "1",
CLEANUP_INTERVAL_MINUTES: "60",
},
coverage: {
provider: "v8",
reporter: ["text", "html", "lcov"],
include: [
"packages/image-engine/src/**",
"apps/api/src/**",
"apps/web/src/stores/**",
"apps/web/src/lib/**",
],
exclude: [
"**/*.d.ts",
"**/node_modules/**",
"**/dist/**",
"apps/api/src/db/migrate.ts",
"apps/api/src/index.ts",
],
},
},
resolve: {
alias: {
"@": path.resolve(__dirname, "apps/web/src"),
"@ashim/image-engine": path.resolve(__dirname, "packages/image-engine/src/index.ts"),
"@ashim/shared": path.resolve(__dirname, "packages/shared/src/index.ts"),
// Map api-only dependencies so integration tests (and transitive imports
// from apps/api/src) can resolve them from the root vitest runner.
fastify: path.join(apiNodeModules, "fastify"),
"@fastify/cors": path.join(apiNodeModules, "@fastify/cors"),
"@fastify/multipart": path.join(apiNodeModules, "@fastify/multipart"),
"@fastify/rate-limit": path.join(apiNodeModules, "@fastify/rate-limit"),
"@fastify/static": path.join(apiNodeModules, "@fastify/static"),
"@fastify/swagger": path.join(apiNodeModules, "@fastify/swagger"),
"@fastify/swagger-ui": path.join(apiNodeModules, "@fastify/swagger-ui"),
"better-sqlite3": path.join(apiNodeModules, "better-sqlite3"),
"drizzle-orm": path.join(apiNodeModules, "drizzle-orm"),
archiver: path.join(apiNodeModules, "archiver"),
"p-queue": path.join(apiNodeModules, "p-queue"),
dotenv: path.join(apiNodeModules, "dotenv"),
potrace: path.join(apiNodeModules, "potrace"),
qrcode: path.join(apiNodeModules, "qrcode"),
jsqr: path.join(apiNodeModules, "jsqr"),
pdfkit: path.join(apiNodeModules, "pdfkit"),
sharp: path.join(apiNodeModules, "sharp"),
// Map web-only dependencies so component tests can resolve them
// from the root vitest runner.
react: path.join(webNodeModules, "react"),
"react-dom": path.join(webNodeModules, "react-dom"),
zustand: path.join(webNodeModules, "zustand"),
},
},
});