const { test } = require("node:test"); const assert = require("node:assert"); const { buildAttributeDefs } = require("../src/lib/keycloakColumnSync"); test("buildAttributeDefs maps Pleasanter Columns (ColumnName/LabelText) onto Keycloak attribute defs (name/displayName)", () => { const columns = [ { ColumnName: "ClassA", LabelText: "社員ID" }, { ColumnName: "Class001", LabelText: "姓" }, ]; assert.deepStrictEqual(buildAttributeDefs(columns), [ { name: "ClassA", displayName: "社員ID" }, { name: "Class001", displayName: "姓" }, ]); }); test("planProfileAttributeSync detects additions and, on first run (lastSyncedNamesOrNull=null), only removes the legacy fullName/pleasanterLoginId/lineworksUserId attributes", () => { const { planProfileAttributeSync } = require("../src/lib/keycloakColumnSync"); const currentProfile = { attributes: [{ name: "username" }, { name: "email" }, { name: "fullName" }, { name: "pleasanterLoginId" }, { name: "lineworksUserId" }, { name: "someOtherAppAttr" }] }; const attributeDefs = [{ name: "ClassA", displayName: "社員ID" }]; const plan = planProfileAttributeSync(currentProfile, attributeDefs, null); assert.deepStrictEqual(plan.toAdd, [{ name: "ClassA", displayName: "社員ID" }]); assert.deepStrictEqual(plan.toRemove.sort(), ["fullName", "lineworksUserId", "pleasanterLoginId"]); }); test("planProfileAttributeSync on a later run removes only attributes that were synced before but are absent today, keeping unrelated and protected attributes", () => { const { planProfileAttributeSync } = require("../src/lib/keycloakColumnSync"); const currentProfile = { attributes: [{ name: "username" }, { name: "email" }, { name: "ClassA" }, { name: "Class999" }, { name: "someOtherAppAttr" }] }; const attributeDefs = [{ name: "ClassA", displayName: "社員ID" }]; // Class999は今回のColumnsから消えた想定 const lastSyncedNames = ["ClassA", "Class999"]; const plan = planProfileAttributeSync(currentProfile, attributeDefs, lastSyncedNames); assert.deepStrictEqual(plan.toAdd, []); assert.deepStrictEqual(plan.toRemove, ["Class999"]); }); test("planProfileAttributeSync never removes protected attributes (Keycloak standard fields + pleasanterResultId) even if listed in lastSyncedNames", () => { const { planProfileAttributeSync, RESULT_ID_ATTR } = require("../src/lib/keycloakColumnSync"); const currentProfile = { attributes: [{ name: "username" }, { name: "email" }, { name: "firstName" }, { name: "lastName" }, { name: RESULT_ID_ATTR }] }; const plan = planProfileAttributeSync(currentProfile, [], ["username", "email", "firstName", "lastName", RESULT_ID_ATTR]); assert.deepStrictEqual(plan.toRemove, []); }); test("applyProfileAttributePlan adds new attribute defs and removes the ones marked for removal, returning null when there is nothing to change", () => { const { planProfileAttributeSync, applyProfileAttributePlan } = require("../src/lib/keycloakColumnSync"); const currentProfile = { attributes: [{ name: "username" }, { name: "Class999" }] }; const attributeDefs = [{ name: "ClassA", displayName: "社員ID" }]; const plan = planProfileAttributeSync(currentProfile, attributeDefs, ["Class999"]); const newProfile = applyProfileAttributePlan(currentProfile, plan); assert.deepStrictEqual(newProfile.attributes.map((a) => a.name), ["username", "ClassA"]); assert.strictEqual(applyProfileAttributePlan(currentProfile, { toAdd: [], toRemove: [] }), null); }); test("planResultIdDeletions returns ResultIds present last time but absent today; returns [] on first run", () => { const { planResultIdDeletions } = require("../src/lib/keycloakColumnSync"); assert.deepStrictEqual(planResultIdDeletions(["1", "2"], null), []); // 初回実行 assert.deepStrictEqual(planResultIdDeletions(["1"], ["1", "2"]), ["2"]); // 2が消えた assert.deepStrictEqual(planResultIdDeletions(["1", "2"], ["1", "2"]), []); // 変化なし }); test("saveLastSyncedColumnNames/loadLastSyncedColumnNames round-trip via a temp file; missing file returns null", () => { const fs = require("fs"); const os = require("os"); const path = require("path"); const { saveLastSyncedColumnNames, loadLastSyncedColumnNames } = require("../src/lib/keycloakColumnSync"); const tmpFile = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "kc-col-sync-test-")), "last-synced-columns.json"); assert.strictEqual(loadLastSyncedColumnNames(tmpFile), null); saveLastSyncedColumnNames(["ClassA", "Class001"], tmpFile); assert.deepStrictEqual(loadLastSyncedColumnNames(tmpFile), ["ClassA", "Class001"]); }); test("saveLastSyncedResultIds/loadLastSyncedResultIds round-trip via a temp file; missing file returns null", () => { const fs = require("fs"); const os = require("os"); const path = require("path"); const { saveLastSyncedResultIds, loadLastSyncedResultIds } = require("../src/lib/keycloakColumnSync"); const tmpFile = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "kc-resultid-sync-test-")), "last-synced-result-ids.json"); assert.strictEqual(loadLastSyncedResultIds(tmpFile), null); saveLastSyncedResultIds([1350, 831], tmpFile); assert.deepStrictEqual(loadLastSyncedResultIds(tmpFile), [1350, 831]); });