| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /**
- * Unit tests for collection config path resolution (PR #190).
- *
- * Tests that getConfigDir() respects XDG_CONFIG_HOME, QMD_CONFIG_DIR,
- * and falls back to ~/.config/qmd.
- */
- import { describe, test, expect, beforeEach, afterEach } from "vitest";
- import { join } from "path";
- import { homedir, tmpdir } from "os";
- import { mkdtempSync, rmSync, readFileSync } from "fs";
- import {
- getConfigPath,
- setConfigIndexName,
- setConfigSource,
- loadConfig,
- saveConfig,
- } from "../src/collections.js";
- import type { CollectionConfig } from "../src/collections.js";
- // Save/restore env vars around each test
- let savedEnv: Record<string, string | undefined>;
- beforeEach(() => {
- savedEnv = {
- QMD_CONFIG_DIR: process.env.QMD_CONFIG_DIR,
- XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
- };
- // Reset index name to default
- setConfigIndexName("index");
- });
- afterEach(() => {
- // Reset index name to default (prevents leaking into other test files under bun test)
- setConfigIndexName("index");
- for (const [key, val] of Object.entries(savedEnv)) {
- if (val === undefined) {
- delete process.env[key];
- } else {
- process.env[key] = val;
- }
- }
- });
- describe("getConfigDir via getConfigPath", () => {
- test("defaults to ~/.config/qmd when no env vars are set", () => {
- delete process.env.QMD_CONFIG_DIR;
- delete process.env.XDG_CONFIG_HOME;
- expect(getConfigPath()).toBe(join(homedir(), ".config", "qmd", "index.yml"));
- });
- test("QMD_CONFIG_DIR takes highest priority", () => {
- process.env.QMD_CONFIG_DIR = "/custom/qmd-config";
- process.env.XDG_CONFIG_HOME = "/xdg/config";
- expect(getConfigPath()).toBe(join("/custom/qmd-config", "index.yml"));
- });
- test("XDG_CONFIG_HOME is used when QMD_CONFIG_DIR is not set", () => {
- delete process.env.QMD_CONFIG_DIR;
- process.env.XDG_CONFIG_HOME = "/xdg/config";
- expect(getConfigPath()).toBe(join("/xdg/config", "qmd", "index.yml"));
- });
- test("XDG_CONFIG_HOME appends qmd subdirectory", () => {
- delete process.env.QMD_CONFIG_DIR;
- process.env.XDG_CONFIG_HOME = "/home/agent/.config";
- expect(getConfigPath()).toBe(join("/home/agent/.config", "qmd", "index.yml"));
- });
- test("QMD_CONFIG_DIR overrides XDG_CONFIG_HOME", () => {
- process.env.QMD_CONFIG_DIR = "/override";
- process.env.XDG_CONFIG_HOME = "/should-not-use";
- expect(getConfigPath()).toBe(join("/override", "index.yml"));
- });
- test("respects custom index name", () => {
- delete process.env.QMD_CONFIG_DIR;
- process.env.XDG_CONFIG_HOME = "/xdg/config";
- setConfigIndexName("myindex");
- expect(getConfigPath()).toBe(join("/xdg/config", "qmd", "myindex.yml"));
- });
- });
- // ============================================================================
- // chunkStrategy schema round-trip (Phase 2 — i-bud0h8vu)
- // ============================================================================
- describe("Collection.chunkStrategy YAML round-trip", () => {
- let tmpDir: string;
- beforeEach(() => {
- tmpDir = mkdtempSync(join(tmpdir(), "qmd-chunkstrategy-"));
- process.env.QMD_CONFIG_DIR = tmpDir;
- setConfigIndexName("index");
- });
- afterEach(() => {
- // Reset config source so we don't leak inline state
- setConfigSource();
- try {
- rmSync(tmpDir, { recursive: true, force: true });
- } catch {
- // best-effort
- }
- });
- test("chunkStrategy field persists through save/load cycle", () => {
- const config: CollectionConfig = {
- collections: {
- "oivo-cli": {
- path: "/srv/cli/src",
- pattern: "**/*.ts",
- chunkStrategy: "function",
- },
- "oivo-docs": {
- path: "/srv/docs",
- pattern: "**/*.md",
- // no chunkStrategy — should remain unset after round-trip
- },
- },
- };
- saveConfig(config);
- const loaded = loadConfig();
- expect(loaded.collections["oivo-cli"]?.chunkStrategy).toBe("function");
- expect(loaded.collections["oivo-docs"]?.chunkStrategy).toBeUndefined();
- });
- test("chunkStrategy 'auto' and 'regex' round-trip", () => {
- const config: CollectionConfig = {
- collections: {
- a: { path: "/a", pattern: "*.ts", chunkStrategy: "auto" },
- b: { path: "/b", pattern: "*.ts", chunkStrategy: "regex" },
- },
- };
- saveConfig(config);
- const loaded = loadConfig();
- expect(loaded.collections.a?.chunkStrategy).toBe("auto");
- expect(loaded.collections.b?.chunkStrategy).toBe("regex");
- });
- test("omitted chunkStrategy does not appear in serialized YAML", () => {
- const config: CollectionConfig = {
- collections: {
- plain: { path: "/p", pattern: "*.md" },
- },
- };
- saveConfig(config);
- const yaml = readFileSync(join(tmpDir, "index.yml"), "utf-8");
- expect(yaml).not.toContain("chunkStrategy");
- });
- });
|