forked from baron/baron-sso
조직현황 구조변경. 총괄센터삼안 실 조직 삽입확인
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type { TenantSummary } from "../../../lib/adminApi";
|
||||
import {
|
||||
buildTenantImportParentOptionGroups,
|
||||
buildTenantImportPreview,
|
||||
inferTenantImportRootParentSlug,
|
||||
parseTenantCSV,
|
||||
serializeTenantImportCSV,
|
||||
} from "./tenantCsvImport";
|
||||
@@ -31,9 +33,37 @@ const tenants: TenantSummary[] = [
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
},
|
||||
{
|
||||
id: "tenant-3",
|
||||
type: "COMPANY_GROUP",
|
||||
name: "Hanmac Family",
|
||||
slug: "hanmac-family",
|
||||
description: "",
|
||||
status: "active",
|
||||
domains: [],
|
||||
memberCount: 0,
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
},
|
||||
{
|
||||
id: "tenant-4",
|
||||
type: "ORGANIZATION",
|
||||
name: "기획부",
|
||||
slug: "planning",
|
||||
description: "",
|
||||
status: "active",
|
||||
domains: [],
|
||||
memberCount: 0,
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
},
|
||||
];
|
||||
|
||||
describe("tenantCsvImport", () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("parses tenant CSV rows with the supported import columns", () => {
|
||||
const rows = parseTenantCSV(
|
||||
"tenant_id,name,type,parent_tenant_id,slug,memo,email_domain\n,Hanmac Tech,COMPANY,,hanmac-tech,Memo,hanmac-tech.example.com\n",
|
||||
@@ -87,7 +117,7 @@ describe("tenantCsvImport", () => {
|
||||
});
|
||||
|
||||
expect(csv).toContain(
|
||||
"tenant-1,Hanmac Tech,COMPANY,,hanmac-tech,Memo,hanmac-tech.example.com",
|
||||
"tenant-1,Hanmac Tech,COMPANY,,,hanmac-tech,Memo,hanmac-tech.example.com",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -110,7 +140,7 @@ describe("tenantCsvImport", () => {
|
||||
});
|
||||
|
||||
expect(csv).toContain(
|
||||
"staging-new-tenant-id,Hanmac Technology,COMPANY,,hanmac-imported,Memo,hanmac.example.com",
|
||||
"staging-new-tenant-id,Hanmac Technology,COMPANY,,,hanmac-imported,Memo,hanmac.example.com",
|
||||
);
|
||||
expect(csv).not.toContain("local-tenant-id");
|
||||
});
|
||||
@@ -138,10 +168,10 @@ describe("tenantCsvImport", () => {
|
||||
});
|
||||
|
||||
expect(csv).toContain(
|
||||
"staging-parent-id,Parent Tenant,COMPANY,,parent-staging,,",
|
||||
"staging-parent-id,Parent Tenant,COMPANY,,,parent-staging,,",
|
||||
);
|
||||
expect(csv).toContain(
|
||||
"staging-child-id,Child Tenant,ORGANIZATION,staging-parent-id,child-staging,,",
|
||||
"staging-child-id,Child Tenant,ORGANIZATION,staging-parent-id,,child-staging,,",
|
||||
);
|
||||
expect(csv).not.toContain("local-parent-id");
|
||||
expect(csv).not.toContain("local-child-id");
|
||||
@@ -171,7 +201,157 @@ describe("tenantCsvImport", () => {
|
||||
|
||||
expect(rows[1].parentTenantSlug).toBe("parent-slug");
|
||||
expect(csv).toContain(
|
||||
"staging-child-id,Child Tenant,ORGANIZATION,staging-parent-id,child-slug,,",
|
||||
"staging-child-id,Child Tenant,ORGANIZATION,staging-parent-id,parent-slug,child-slug,,",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps parent_tenant_slug in the serialized CSV as a fallback for hierarchy import", () => {
|
||||
const rows = parseTenantCSV(
|
||||
[
|
||||
"name,type,parent_tenant_slug,slug,memo,email_domain",
|
||||
"Parent Tenant,COMPANY,,parent-slug,,",
|
||||
"Child Tenant,ORGANIZATION,parent-slug,child-slug,,",
|
||||
].join("\n"),
|
||||
);
|
||||
const preview = buildTenantImportPreview(rows, tenants);
|
||||
const csv = serializeTenantImportCSV(preview, {
|
||||
2: {
|
||||
mode: "create",
|
||||
tenantId: "staging-parent-id",
|
||||
slug: "parent-slug",
|
||||
},
|
||||
3: {
|
||||
mode: "create",
|
||||
tenantId: "staging-child-id",
|
||||
slug: "child-slug",
|
||||
},
|
||||
});
|
||||
|
||||
expect(csv.split("\n")[0]).toBe(
|
||||
"tenant_id,name,type,parent_tenant_id,parent_tenant_slug,slug,memo,email_domain",
|
||||
);
|
||||
expect(csv).toContain(
|
||||
"staging-child-id,Child Tenant,ORGANIZATION,staging-parent-id,parent-slug,child-slug,,",
|
||||
);
|
||||
});
|
||||
|
||||
it("parses Naver Works organization CSV columns into tenant import rows", () => {
|
||||
const rows = parseTenantCSV(
|
||||
[
|
||||
'"조직명","멤버 수","조직장","조직 다국어명","설명","메일링 리스트","상위 조직"',
|
||||
'"기술개발센터","1","","","","tdc@samaneng.com",""',
|
||||
'"기획부","1","","","","planning@samaneng.com","기술개발센터(tdc@samaneng.com)"',
|
||||
'"업무팀","0","","","","t_226wn@samaneng.com","기획부(planning@samaneng.com)"',
|
||||
].join("\n"),
|
||||
{ rootParentSlug: "saman" },
|
||||
);
|
||||
|
||||
expect(rows).toMatchObject([
|
||||
{
|
||||
name: "기술개발센터",
|
||||
type: "ORGANIZATION",
|
||||
slug: "tdc",
|
||||
parentTenantSlug: "saman",
|
||||
},
|
||||
{
|
||||
name: "기획부",
|
||||
type: "ORGANIZATION",
|
||||
slug: "planning",
|
||||
parentTenantSlug: "tdc",
|
||||
},
|
||||
{
|
||||
name: "업무팀",
|
||||
type: "ORGANIZATION",
|
||||
slug: "t-226wn",
|
||||
parentTenantSlug: "planning",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("infers root parent slug from an organization CSV file prefix that matches an existing slug", () => {
|
||||
expect(inferTenantImportRootParentSlug("saman_org.csv", tenants)).toBe(
|
||||
"saman",
|
||||
);
|
||||
expect(
|
||||
inferTenantImportRootParentSlug("/tmp/hanmac-family_org.csv", tenants),
|
||||
).toBe("hanmac-family");
|
||||
expect(
|
||||
inferTenantImportRootParentSlug("saman_org_slugged.csv", tenants),
|
||||
).toBe("saman");
|
||||
expect(inferTenantImportRootParentSlug("unknown_org.csv", tenants)).toBe(
|
||||
"",
|
||||
);
|
||||
expect(inferTenantImportRootParentSlug("tenant-import.csv", tenants)).toBe(
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
it("groups existing parent candidates by company group, company, and organization", () => {
|
||||
const groups = buildTenantImportParentOptionGroups(tenants);
|
||||
|
||||
expect(groups.map((group) => group.type)).toEqual([
|
||||
"COMPANY_GROUP",
|
||||
"COMPANY",
|
||||
"ORGANIZATION",
|
||||
]);
|
||||
expect(
|
||||
groups.map((group) => group.tenants.map((tenant) => tenant.id)),
|
||||
).toEqual([["tenant-3"], ["tenant-1", "tenant-2"], ["tenant-4"]]);
|
||||
});
|
||||
|
||||
it("keeps generated ids stable and follows edited parent slugs for child rows", () => {
|
||||
const randomUUID = vi
|
||||
.fn()
|
||||
.mockReturnValueOnce("parent-generated-id")
|
||||
.mockReturnValueOnce("child-generated-id");
|
||||
vi.stubGlobal("crypto", { randomUUID });
|
||||
|
||||
const rows = parseTenantCSV(
|
||||
[
|
||||
"name,type,parent_tenant_slug,slug,memo,email_domain",
|
||||
"기술개발센터,ORGANIZATION,saman,t-536fc,,",
|
||||
"일반구조물 div,ORGANIZATION,t-536fc,t-568cz,,",
|
||||
].join("\n"),
|
||||
);
|
||||
const preview = buildTenantImportPreview(rows, tenants);
|
||||
const csv = serializeTenantImportCSV(preview, {
|
||||
2: { mode: "create", slug: "tech-center" },
|
||||
3: { mode: "create", slug: "structure-div" },
|
||||
});
|
||||
|
||||
expect(csv).toContain(
|
||||
"parent-generated-id,기술개발센터,ORGANIZATION,,saman,tech-center,,",
|
||||
);
|
||||
expect(csv).toContain(
|
||||
"child-generated-id,일반구조물 div,ORGANIZATION,parent-generated-id,tech-center,structure-div,,",
|
||||
);
|
||||
});
|
||||
|
||||
it("serializes explicit parent tenant selections from the import preview", () => {
|
||||
const rows = parseTenantCSV(
|
||||
[
|
||||
"name,type,parent_tenant_slug,slug,memo,email_domain",
|
||||
"기술개발센터,ORGANIZATION,saman,t-536fc,,",
|
||||
"일반구조물 div,ORGANIZATION,t-536fc,t-568cz,,",
|
||||
].join("\n"),
|
||||
);
|
||||
const preview = buildTenantImportPreview(rows, tenants);
|
||||
const csv = serializeTenantImportCSV(preview, {
|
||||
2: {
|
||||
mode: "create",
|
||||
slug: "tech-center",
|
||||
parentTenantId: "tenant-2",
|
||||
parentTenantSlug: "",
|
||||
},
|
||||
3: {
|
||||
mode: "create",
|
||||
slug: "structure-div",
|
||||
parentTenantSlug: "tech-center",
|
||||
},
|
||||
});
|
||||
|
||||
expect(csv).toContain("기술개발센터,ORGANIZATION,tenant-2,,tech-center,,");
|
||||
expect(csv).toContain(",일반구조물 div,ORGANIZATION,");
|
||||
expect(csv).toContain(",tech-center,structure-div,,");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user