GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。 NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは 別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
90 lines
5.1 KiB
JavaScript
90 lines
5.1 KiB
JavaScript
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]);
|
|
});
|