diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11b8ab9..311159e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,16 +33,8 @@ jobs: - run: npm install - - name: Unit tests - run: npx vitest run --reporter=verbose src/*.test.ts - - - name: Model tests - run: npx vitest run --reporter=verbose src/models/*.test.ts - env: - CI: true - - - name: Integration tests - run: npx vitest run --reporter=verbose src/integration/*.test.ts + - name: Tests + run: npx vitest run --reporter=verbose test/ env: CI: true @@ -71,21 +63,8 @@ jobs: - run: bun install - - name: Unit tests - run: bun test --preload ./src/test-preload.ts src/*.test.ts - env: - DYLD_LIBRARY_PATH: /opt/homebrew/opt/sqlite/lib - LD_LIBRARY_PATH: /usr/lib/x86_64-linux-gnu - - - name: Model tests - run: bun test --preload ./src/test-preload.ts src/models/*.test.ts - env: - CI: true - DYLD_LIBRARY_PATH: /opt/homebrew/opt/sqlite/lib - LD_LIBRARY_PATH: /usr/lib/x86_64-linux-gnu - - - name: Integration tests - run: bun test --preload ./src/test-preload.ts src/integration/*.test.ts + - name: Tests + run: bun test --preload ./src/test-preload.ts test/ env: CI: true DYLD_LIBRARY_PATH: /opt/homebrew/opt/sqlite/lib diff --git a/CLAUDE.md b/CLAUDE.md index 0c80b75..8c5e3b9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,23 +122,15 @@ bun src/qmd.ts # Run from source bun link # Install globally as 'qmd' ``` -## Test Layout +## Tests -- `src/*.test.ts` = unit tests -- `src/models/*.test.ts` = tests that require model/runtime setup -- `src/integration/*.test.ts` = integration tests (CLI subprocesses, daemon/server behavior) - -### Run Order +All tests live in `test/`. Run everything: ```sh -npx vitest run --reporter=verbose src/*.test.ts -npx vitest run --reporter=verbose src/models/*.test.ts -npx vitest run --reporter=verbose src/integration/*.test.ts +npx vitest run --reporter=verbose test/ +bun test --preload ./src/test-preload.ts test/ ``` -Use this order for faster feedback: -`unit -> models -> integration`. - ## Architecture - SQLite FTS5 for full-text search (BM25) diff --git a/package.json b/package.json index 1382b44..b0e066c 100644 --- a/package.json +++ b/package.json @@ -15,19 +15,7 @@ "CHANGELOG.md" ], "scripts": { - "test": "vitest run", - "test:unit": "vitest run --reporter=verbose src/*.test.ts", - "test:models": "vitest run --reporter=verbose src/models/*.test.ts", - "test:integration": "vitest run --reporter=verbose src/integration/*.test.ts", - "test:unit:bun": "bun run vitest run --reporter=verbose --testTimeout=120000 src/*.test.ts", - "test:models:bun": "bun run vitest run --reporter=verbose --testTimeout=120000 src/models/*.test.ts", - "test:integration:bun": "bun run vitest run --reporter=verbose --testTimeout=120000 src/integration/*.test.ts", - "test:unit:node": "npx vitest run --reporter=verbose --testTimeout=120000 src/*.test.ts", - "test:models:node": "npx vitest run --reporter=verbose --testTimeout=120000 src/models/*.test.ts", - "test:integration:node": "npx vitest run --reporter=verbose --testTimeout=120000 src/integration/*.test.ts", - "test:ci:bun": "npm run test:unit:bun && npm run test:models:bun && npm run test:integration:bun", - "test:ci:node": "npm run test:unit:node && npm run test:models:node && npm run test:integration:node", - "test:ci": "npm run test:unit && npm run test:models && npm run test:integration", + "test": "vitest run --reporter=verbose test/", "qmd": "tsx src/qmd.ts", "index": "tsx src/qmd.ts index", "vector": "tsx src/qmd.ts vector", diff --git a/src/integration/cli.test.ts b/test/cli.test.ts similarity index 100% rename from src/integration/cli.test.ts rename to test/cli.test.ts diff --git a/src/eval-bm25.test.ts b/test/eval-bm25.test.ts similarity index 98% rename from src/eval-bm25.test.ts rename to test/eval-bm25.test.ts index b3fb2c2..aaa9fe8 100644 --- a/src/eval-bm25.test.ts +++ b/test/eval-bm25.test.ts @@ -8,7 +8,7 @@ import { describe, test, expect, beforeAll, afterAll } from "vitest"; import { mkdtempSync, rmSync, readFileSync, readdirSync } from "fs"; import { join, dirname } from "path"; import { tmpdir } from "os"; -import type { Database } from "./db.js"; +import type { Database } from "../src/db.js"; import { createHash } from "crypto"; import { fileURLToPath } from "url"; @@ -17,7 +17,7 @@ import { searchFTS, insertDocument, insertContent, -} from "./store"; +} from "../src/store"; // Set INDEX_PATH before importing store to prevent using global index const tempDir = mkdtempSync(join(tmpdir(), "qmd-eval-unit-")); @@ -92,7 +92,7 @@ describe("BM25 Search (FTS)", () => { db = store.db; // Load and index eval documents - const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "../test/eval-docs"); + const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "eval-docs"); const files = readdirSync(evalDocsDir).filter(f => f.endsWith(".md")); for (const file of files) { diff --git a/src/models/eval.test.ts b/test/eval.test.ts similarity index 98% rename from src/models/eval.test.ts rename to test/eval.test.ts index c01defe..d575ff8 100644 --- a/src/models/eval.test.ts +++ b/test/eval.test.ts @@ -14,8 +14,8 @@ import { describe, test, expect, beforeAll, afterAll } from "vitest"; import { mkdtempSync, rmSync, readFileSync, readdirSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; -import { openDatabase } from "../db.js"; -import type { Database } from "../db.js"; +import { openDatabase } from "../src/db.js"; +import type { Database } from "../src/db.js"; import { createHash } from "crypto"; import { fileURLToPath } from "url"; import { dirname } from "path"; @@ -35,8 +35,8 @@ import { reciprocalRankFusion, DEFAULT_EMBED_MODEL, type RankedResult, -} from "../store"; -import { getDefaultLlamaCpp, formatDocForEmbedding, disposeDefaultLlamaCpp } from "../llm"; +} from "../src/store"; +import { getDefaultLlamaCpp, formatDocForEmbedding, disposeDefaultLlamaCpp } from "../src/llm"; // Eval queries with expected documents const evalQueries: { @@ -110,7 +110,7 @@ describe("BM25 Search (FTS)", () => { db = store.db; // Load and index eval documents - const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "../../test/eval-docs"); + const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "eval-docs"); const files = readdirSync(evalDocsDir).filter(f => f.endsWith(".md")); for (const file of files) { @@ -182,7 +182,7 @@ describe.skipIf(!!process.env.CI)("Vector Search", () => { const llm = getDefaultLlamaCpp(); store.ensureVecTable(768); // embeddinggemma uses 768 dimensions - const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "../../test/eval-docs"); + const evalDocsDir = join(dirname(fileURLToPath(import.meta.url)), "eval-docs"); const files = readdirSync(evalDocsDir).filter(f => f.endsWith(".md")); for (const file of files) { diff --git a/src/formatter.test.ts b/test/formatter.test.ts similarity index 98% rename from src/formatter.test.ts rename to test/formatter.test.ts index 1367f2e..9fee06e 100644 --- a/src/formatter.test.ts +++ b/test/formatter.test.ts @@ -27,8 +27,8 @@ import { documentToXml, formatDocument, type MultiGetFile, -} from "./formatter.js"; -import type { SearchResult, DocumentResult } from "./store.js"; +} from "../src/formatter.js"; +import type { SearchResult, DocumentResult } from "../src/store.js"; // ============================================================================= // Test Fixtures diff --git a/src/models/llm.test.ts b/test/llm.test.ts similarity index 99% rename from src/models/llm.test.ts rename to test/llm.test.ts index 8899771..662d11c 100644 --- a/src/models/llm.test.ts +++ b/test/llm.test.ts @@ -17,7 +17,7 @@ import { SessionReleasedError, type RerankDocument, type ILLMSession, -} from "../llm.js"; +} from "../src/llm.js"; // ============================================================================= // Singleton Tests (no model loading required) diff --git a/src/models/mcp.test.ts b/test/mcp.test.ts similarity index 98% rename from src/models/mcp.test.ts rename to test/mcp.test.ts index 5f515e2..ca6b40a 100644 --- a/src/models/mcp.test.ts +++ b/test/mcp.test.ts @@ -6,16 +6,16 @@ */ import { describe, test, expect, beforeAll, afterAll, beforeEach, afterEach } from "vitest"; -import { openDatabase, loadSqliteVec } from "../db.js"; -import type { Database } from "../db.js"; +import { openDatabase, loadSqliteVec } from "../src/db.js"; +import type { Database } from "../src/db.js"; import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; -import { getDefaultLlamaCpp, disposeDefaultLlamaCpp } from "../llm"; +import { getDefaultLlamaCpp, disposeDefaultLlamaCpp } from "../src/llm"; import { mkdtemp, writeFile, readdir, unlink, rmdir } from "node:fs/promises"; import { join } from "node:path"; import { tmpdir } from "node:os"; import YAML from "yaml"; -import type { CollectionConfig } from "../collections"; +import type { CollectionConfig } from "../src/collections"; // ============================================================================= // Test Database Setup @@ -192,8 +192,8 @@ import { DEFAULT_RERANK_MODEL, DEFAULT_MULTI_GET_MAX_BYTES, createStore, -} from "../store"; -import type { RankedResult } from "../store"; +} from "../src/store"; +import type { RankedResult } from "../src/store"; // Note: searchResultsToMcpCsv no longer used in MCP - using structuredContent instead // ============================================================================= @@ -865,8 +865,8 @@ describe("MCP Server", () => { // HTTP Transport Tests // ============================================================================= -import { startMcpHttpServer, type HttpServerHandle } from "../mcp"; -import { enableProductionMode } from "../store"; +import { startMcpHttpServer, type HttpServerHandle } from "../src/mcp"; +import { enableProductionMode } from "../src/store"; describe("MCP HTTP Transport", () => { let handle: HttpServerHandle; diff --git a/src/store-paths.test.ts b/test/store-paths.test.ts similarity index 99% rename from src/store-paths.test.ts rename to test/store-paths.test.ts index ca8726e..52d658b 100644 --- a/src/store-paths.test.ts +++ b/test/store-paths.test.ts @@ -16,7 +16,7 @@ import { normalizePathSeparators, getRelativePathFromPrefix, resolve, -} from "./store.js"; +} from "../src/store.js"; // ============================================================================= // Test Utilities diff --git a/src/store.helpers.unit.test.ts b/test/store.helpers.unit.test.ts similarity index 99% rename from src/store.helpers.unit.test.ts rename to test/store.helpers.unit.test.ts index bd30e9d..3303187 100644 --- a/src/store.helpers.unit.test.ts +++ b/test/store.helpers.unit.test.ts @@ -15,7 +15,7 @@ import { normalizeDocid, isDocid, handelize, -} from "./store"; +} from "../src/store"; // ============================================================================= // Path Utilities diff --git a/src/models/store.test.ts b/test/store.test.ts similarity index 99% rename from src/models/store.test.ts rename to test/store.test.ts index fbd5a56..9c38477 100644 --- a/src/models/store.test.ts +++ b/test/store.test.ts @@ -7,13 +7,13 @@ */ import { describe, test, expect, beforeAll, afterAll, beforeEach, afterEach, vi } from "vitest"; -import { openDatabase, loadSqliteVec } from "../db.js"; -import type { Database } from "../db.js"; +import { openDatabase, loadSqliteVec } from "../src/db.js"; +import type { Database } from "../src/db.js"; import { unlink, mkdtemp, rmdir, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import YAML from "yaml"; -import { disposeDefaultLlamaCpp } from "../llm.js"; +import { disposeDefaultLlamaCpp } from "../src/llm.js"; import { createStore, verifySqliteVecLoaded, @@ -49,8 +49,8 @@ import { type DocumentResult, type SearchResult, type RankedResult, -} from "../store.js"; -import type { CollectionConfig } from "../collections.js"; +} from "../src/store.js"; +import type { CollectionConfig } from "../src/collections.js"; // ============================================================================= // LlamaCpp Setup diff --git a/vitest.config.ts b/vitest.config.ts index 4870abb..fb6d61e 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,5 +3,6 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { testTimeout: 30000, + include: ["test/**/*.test.ts"], }, });