const { test } = require("node:test"); const assert = require("node:assert"); const fs = require("fs"); const path = require("path"); const os = require("os"); const { saveSiteSnapshot, findSiteDir, ensureSiteDir, sanitize } = require("../src/lib/siteConfigStore"); function makeTempDir() { return fs.mkdtempSync(path.join(os.tmpdir(), "org-master-sync-siteconfig-test-")); } test("sanitize strips path-unsafe characters and falls back to \"untitled\" when empty", () => { assert.strictEqual(sanitize("社員・組織マスタ管理テーブル"), "社員・組織マスタ管理テーブル"); assert.strictEqual(sanitize("a/b\\c:d*e?f\"gi|j"), "a_b_c_d_e_f_g_h_i_j"); assert.strictEqual(sanitize(""), "untitled"); assert.strictEqual(sanitize(undefined), "untitled"); }); test("saveSiteSnapshot creates configs/site-{siteId}_{title}/sitesettings/ with both latest and a timestamped history file", () => { const baseDir = makeTempDir(); const now = new Date("2026-08-08T09:00:00.000Z"); saveSiteSnapshot(1, { Title: "社員・組織マスタ管理テーブル" }, { now, baseDir }); const siteDir = path.join(baseDir, "site-1_社員・組織マスタ管理テーブル"); const settingsDir = path.join(siteDir, "sitesettings"); assert.ok(fs.existsSync(settingsDir)); const latestPath = path.join(settingsDir, "site-1_latest.json"); assert.ok(fs.existsSync(latestPath)); assert.deepStrictEqual(JSON.parse(fs.readFileSync(latestPath, "utf8")), { Title: "社員・組織マスタ管理テーブル" }); const historyFiles = fs.readdirSync(settingsDir).filter((f) => f !== "site-1_latest.json"); assert.strictEqual(historyFiles.length, 1); assert.ok(historyFiles[0].startsWith("site-1_2026-08-08T09-00-00")); }); test("saveSiteSnapshot reuses the existing site-{siteId}_* folder on subsequent calls even if the title changes", () => { const baseDir = makeTempDir(); saveSiteSnapshot(1, { Title: "旧タイトル" }, { now: new Date("2026-08-08T09:00:00.000Z"), baseDir }); saveSiteSnapshot(1, { Title: "新タイトル" }, { now: new Date("2026-08-08T10:00:00.000Z"), baseDir }); const dirs = fs.readdirSync(baseDir); assert.strictEqual(dirs.length, 1); // 新しいタイトルのフォルダを別途作らない assert.strictEqual(dirs[0], "site-1_旧タイトル"); const settingsDir = path.join(baseDir, "site-1_旧タイトル", "sitesettings"); assert.strictEqual(fs.readdirSync(settingsDir).length, 3); // latest.json + history 2件 const latest = JSON.parse(fs.readFileSync(path.join(settingsDir, "site-1_latest.json"), "utf8")); assert.deepStrictEqual(latest, { Title: "新タイトル" }); // latest.jsonの中身は最新で上書き }); test("findSiteDir locates a folder by its site- prefix regardless of the title suffix", () => { const baseDir = makeTempDir(); fs.mkdirSync(path.join(baseDir, "site-42_何かのタイトル"), { recursive: true }); assert.strictEqual(findSiteDir(baseDir, 42), path.join(baseDir, "site-42_何かのタイトル")); assert.strictEqual(findSiteDir(baseDir, 999), null); }); test("ensureSiteDir creates a new site-{siteId}_{title} folder when none exists yet", () => { const baseDir = makeTempDir(); const dir = ensureSiteDir(baseDir, 7, "新規サイト"); assert.strictEqual(dir, path.join(baseDir, "site-7_新規サイト")); assert.ok(fs.existsSync(dir)); });