import { describe, expect, it } from "vitest"; import { buildAuthenticatedOrgChartTenantPickerUrl, buildAuthenticatedOrgChartUrl, buildAuthenticatedOrgChartUserMultiPickerUrl, buildOrgChartTenantPickerUrl, classifyTenantByMembershipRoot, filterNonHanmacFamilyTenants, getTenantGradeOptions, isHanmacFamilyUser, parseOrgChartTenantSelection, parseOrgChartUserSelections, USER_MEMBERSHIP_TENANT_TABS, } from "./orgChartPicker"; describe("orgChartPicker", () => { it("builds the tenant picker embed URL from ORGFRONT_URL", () => { expect(buildOrgChartTenantPickerUrl("https://orgchart.example.com/")).toBe( "https://orgchart.example.com/embed/picker?mode=single&select=tenant&width=400&height=600", ); }); it("adds internal visibility to tenant picker URLs only when requested", () => { expect( buildOrgChartTenantPickerUrl("https://orgchart.example.com/", { includeInternal: true, }), ).toBe( "https://orgchart.example.com/embed/picker?mode=single&select=tenant&width=400&height=600&includeInternal=true", ); }); it("adds tenantId to the tenant picker URL when Hanmac family scope is known", () => { expect( buildOrgChartTenantPickerUrl("https://orgchart.example.com/", { tenantId: "hanmac-family-id", }), ).toBe( "https://orgchart.example.com/embed/picker?mode=single&select=tenant&width=400&height=600&tenantId=hanmac-family-id", ); }); it("wraps the picker URL with the org-chart auto login entry", () => { expect( buildAuthenticatedOrgChartTenantPickerUrl( "https://orgchart.example.com", { tenantId: "hanmac-family-id", }, ), ).toBe( "https://orgchart.example.com/login?auto=1&returnTo=%2Fembed%2Fpicker%3Fmode%3Dsingle%26select%3Dtenant%26width%3D400%26height%3D600%26tenantId%3Dhanmac-family-id%26includeInternal%3Dtrue", ); }); it("falls back to the orgfront development origin for authenticated picker URLs", () => { expect( buildAuthenticatedOrgChartTenantPickerUrl(undefined, { tenantId: "hanmac-family-id", }), ).toBe( "http://localhost:5175/login?auto=1&returnTo=%2Fembed%2Fpicker%3Fmode%3Dsingle%26select%3Dtenant%26width%3D400%26height%3D600%26tenantId%3Dhanmac-family-id%26includeInternal%3Dtrue", ); }); it("builds an authenticated multi picker URL for tenant member selection", () => { expect( buildAuthenticatedOrgChartUserMultiPickerUrl( "https://orgchart.example.com", ), ).toBe( "https://orgchart.example.com/login?auto=1&returnTo=%2Fembed%2Fpicker%3Fmode%3Dmultiple%26select%3Duser%26width%3D720%26height%3D640%26includeInternal%3Dtrue%26includeDescendants%3Dtrue%26showDescendantToggle%3Dtrue%26rootTenantId%3Dall", ); }); it("builds a scoped authenticated multi picker URL for recursive tenant user selection", () => { expect( buildAuthenticatedOrgChartUserMultiPickerUrl( "https://orgchart.example.com", { tenantId: "tenant-a" }, ), ).toBe( "https://orgchart.example.com/login?auto=1&returnTo=%2Fembed%2Fpicker%3Fmode%3Dmultiple%26select%3Duser%26width%3D720%26height%3D640%26includeInternal%3Dtrue%26includeDescendants%3Dtrue%26showDescendantToggle%3Dtrue%26tenantId%3Dtenant-a", ); }); it("builds the admin chart navigation URL without internal visibility by default", () => { expect(buildAuthenticatedOrgChartUrl("https://orgchart.example.com/")).toBe( "https://orgchart.example.com/login?auto=1&returnTo=%2Fchart", ); }); it("can build chart navigation URL with internal visibility when explicitly requested", () => { expect( buildAuthenticatedOrgChartUrl("https://orgchart.example.com/", { includeInternal: true, }), ).toBe( "https://orgchart.example.com/login?auto=1&returnTo=%2Fchart%3FincludeInternal%3Dtrue", ); }); it("parses the first tenant id and name from orgfront confirm messages", () => { expect( parseOrgChartTenantSelection({ type: "orgfront:picker:confirm", payload: { mode: "single", selections: [ { type: "tenant", id: "03dbe16b-e47b-4f72-927b-782807d67a35", name: "기술기획", }, ], }, }), ).toEqual({ id: "03dbe16b-e47b-4f72-927b-782807d67a35", name: "기술기획", }); }); it("ignores non-tenant or malformed picker messages", () => { expect( parseOrgChartTenantSelection({ type: "orgfront:picker:confirm", payload: { mode: "single", selections: [{ type: "user", id: "u-1", name: "User" }], }, }), ).toBeNull(); expect(parseOrgChartTenantSelection({ type: "other" })).toBeNull(); }); it("parses user selections from orgfront multi picker messages", () => { expect( parseOrgChartUserSelections({ type: "orgfront:picker:confirm", payload: { mode: "multiple", selections: [ { type: "tenant", id: "tenant-1", name: "기술기획" }, { type: "user", id: "user-1", name: "홍길동", email: "hong@example.com", rootTenantName: "한맥가족", leafTenantName: "기술기획", }, { type: "user", id: "user-2", name: "김영희", tenantName: "디자인팀", }, { type: "user", id: "", name: "잘못된 사용자" }, ], }, }), ).toEqual([ { id: "user-1", name: "홍길동", email: "hong@example.com", rootTenantName: "한맥가족", leafTenantName: "기술기획", }, { id: "user-2", name: "김영희", email: "", rootTenantName: undefined, leafTenantName: "디자인팀", }, ]); }); it("filters Hanmac family subtree and system tenants from non-family tenant choices", () => { const visibleTenants = filterNonHanmacFamilyTenants( [ { id: "system-id", slug: "system", name: "System", type: "SYSTEM", parentId: undefined, }, { id: "external-id", slug: "external", name: "External", type: "COMPANY", parentId: undefined, }, { id: "internal-id", slug: "internal", name: "Internal", type: "COMPANY", parentId: undefined, config: { visibility: "internal" }, }, { id: "private-id", slug: "private", name: "Private", type: "COMPANY", parentId: undefined, visibility: "private", }, { id: "hanmac-family-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "hanmac-company-id", slug: "hanmac-company", name: "한맥기술", type: "COMPANY", parentId: "hanmac-family-id", }, { id: "hanmac-team-id", slug: "hanmac-team", name: "한맥팀", type: "USER_GROUP", parentId: "hanmac-company-id", }, ], "hanmac-family-id", ); expect(visibleTenants.map((tenant) => tenant.slug)).toEqual(["external"]); }); it("detects existing users as Hanmac family from tenant subtree without metadata flag", () => { const tenants = [ { id: "external-id", slug: "external", name: "External", type: "COMPANY", parentId: undefined, }, { id: "hanmac-family-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "hanmac-company-id", slug: "hanmac-company", name: "한맥기술", type: "COMPANY", parentId: "hanmac-family-id", }, { id: "hanmac-team-id", slug: "hanmac-team", name: "기술기획", type: "USER_GROUP", parentId: "hanmac-company-id", }, ]; expect( isHanmacFamilyUser( { companyCode: "external", tenant: tenants[0], joinedTenants: [tenants[3]], metadata: {}, }, tenants, "hanmac-family-id", ), ).toBe(true); }); it("does not treat legacy hanmacFamily metadata as Hanmac family without tenant evidence", () => { const tenants = [ { id: "hanmac-family-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "external-id", slug: "external", name: "External", type: "COMPANY", parentId: undefined, }, ]; expect( isHanmacFamilyUser( { companyCode: "external", tenant: tenants[1], metadata: { hanmacFamily: true }, }, tenants, "hanmac-family-id", ), ).toBe(false); }); it("does not treat userType metadata as Hanmac family without tenant evidence", () => { const tenants = [ { id: "hanmac-family-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "external-id", slug: "external", name: "External", type: "COMPANY", parentId: undefined, }, ]; expect( isHanmacFamilyUser( { companyCode: "external", tenant: tenants[1], metadata: { userType: "hanmac" }, }, tenants, "hanmac-family-id", ), ).toBe(false); }); it("returns GPDTDC rank options for GPDTDC subtree and general Hanmac ranks otherwise", () => { const tenants = [ { id: "hanmac-family-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "gpdtdc-id", slug: "gpdtdc", name: "총괄기획&기술개발센터", type: "COMPANY", parentId: "hanmac-family-id", }, { id: "gpdtdc-team-id", slug: "gpdtdc-team", name: "연구팀", type: "USER_GROUP", parentId: "gpdtdc-id", }, { id: "hanmac-id", slug: "hanmac", name: "한맥기술", type: "COMPANY", parentId: "hanmac-family-id", }, ]; expect( getTenantGradeOptions({ tenantId: "gpdtdc-team-id" }, tenants), ).toEqual(["연구원", "선임", "책임", "수석", "부사장", "사장"]); expect(getTenantGradeOptions({ tenantSlug: "hanmac" }, tenants)).toEqual([ "사원", "대리", "과장", "차장", "부장", "이사", "상무이사", "전무이사", "부사장", "사장", "회장", ]); }); it("classifies tenants by the configured top-level tenant root UUIDs", () => { const tenants = [ { id: "hanmac-root-id", slug: "hanmac-family", name: "한맥가족", type: "COMPANY_GROUP", parentId: undefined, }, { id: "commercial-root-id", slug: "commercial", name: "Commercial", type: "COMPANY_GROUP", parentId: undefined, }, { id: "commercial-child-id", slug: "external-company", name: "외부기업", type: "COMPANY", parentId: "commercial-root-id", }, ]; expect(USER_MEMBERSHIP_TENANT_TABS.map((tab) => tab.id)).toEqual([ "hanmac-family", "commercial", "public-org", "edu", "personal", ]); expect(classifyTenantByMembershipRoot(tenants[2], tenants)?.id).toBe( "commercial", ); }); });