forked from baron/baron-sso
Includes Worksmobile SSOT sync comparison updates, UUID import conflict resolution, and Playwright route mock stabilization.
191 lines
6.7 KiB
TypeScript
191 lines
6.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parseUserCSV } from "./csvParser";
|
|
|
|
describe("parseUserCSV", () => {
|
|
it("should parse valid CSV correctly", () => {
|
|
const csv = `email,name,phone,role,tenant,department,emp_id
|
|
user1@test.com,Hong Gil Dong,010-1111-2222,user,baron,HR,E001
|
|
user2@test.com,Kim Cheol Su,,admin,baron,IT,E002`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0]).toEqual({
|
|
email: "user1@test.com",
|
|
name: "Hong Gil Dong",
|
|
phone: "010-1111-2222",
|
|
role: "user",
|
|
tenantSlug: "baron",
|
|
department: "HR",
|
|
metadata: {
|
|
emp_id: "E001",
|
|
},
|
|
});
|
|
expect(result[1].email).toBe("user2@test.com");
|
|
expect(result[1].metadata.emp_id).toBe("E002");
|
|
});
|
|
|
|
it("should return empty array for empty input", () => {
|
|
expect(parseUserCSV("")).toEqual([]);
|
|
});
|
|
|
|
it("should skip rows without email or name", () => {
|
|
const csv = `email,name
|
|
,Only Name
|
|
no-name@test.com,`;
|
|
expect(parseUserCSV(csv)).toHaveLength(0);
|
|
});
|
|
|
|
it("should handle mixed case headers", () => {
|
|
const csv = `EMAIL,Name,Tenant
|
|
test@test.com,Test,baron`;
|
|
const result = parseUserCSV(csv);
|
|
expect(result[0].email).toBe("test@test.com");
|
|
expect(result[0].tenantSlug).toBe("baron");
|
|
});
|
|
|
|
it("should parse NAVERWORKS member CSV sample into Baron bulk user fields", () => {
|
|
const csv = `"LastName","FirstName","ID","Personal email","Sub email","Nickname","User type","Level","Organization","Position","CompanyMainPhone","Mobile/Country code","Mobile/Numbers","Language","Responsibilities","Workplace","SNS","SNS_ID","Birthday (solar, lunar)","Birthday","Entry Date","Employee number","Account activation time"
|
|
"Doe","John","john.doe","john@naver.com","john1@company.com; john2@company.com","John","Permanent Employee","Manager","org.1|org.2|org.3|myteam","Manager","02-0000-0000","+1","9144812222","English","Sales management","New York","Facebook","john","solar","19830415","20230415","AB001","20230415 08:00"`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
email: "john1@company.com",
|
|
loginId: "john.doe",
|
|
name: "John Doe",
|
|
phone: "+19144812222",
|
|
department: "myteam",
|
|
grade: "Manager",
|
|
position: "Manager",
|
|
jobTitle: "Sales management",
|
|
tenantImport: {
|
|
name: "myteam",
|
|
parentTenantName: "org.3",
|
|
},
|
|
metadata: {
|
|
personal_email: "john@naver.com",
|
|
employee_id: "AB001",
|
|
naverworks_user_type: "Permanent Employee",
|
|
naverworks_level: "Manager",
|
|
naverworks_organization_path: "org.1|org.2|org.3|myteam",
|
|
naverworks_workplace: "New York",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("should parse tenant conflict metadata for import resolution", () => {
|
|
const csv = `email,name,tenant_id,tenant_slug,tenant_name,tenant_type,parent_tenant_slug,tenant_memo,email_domain
|
|
test@test.com,Test,local-tenant-id,missing-slug,Missing Tenant,COMPANY,parent-slug,Imported memo,missing.example.com`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result[0]).toMatchObject({
|
|
tenantId: "local-tenant-id",
|
|
tenantSlug: "missing-slug",
|
|
emailDomain: "missing.example.com",
|
|
tenantImport: {
|
|
sourceTenantId: "local-tenant-id",
|
|
slug: "missing-slug",
|
|
name: "Missing Tenant",
|
|
type: "COMPANY",
|
|
parentTenantSlug: "parent-slug",
|
|
memo: "Imported memo",
|
|
emailDomain: "missing.example.com",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("should ignore exported user_id during user CSV import", () => {
|
|
const csv = `user_id,email,name,tenant_id,tenant_slug
|
|
9f8cc1b1-af8d-45d4-946c-924a529c2556,restore@test.com,Restore User,tenant-id,restore-tenant`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
email: "restore@test.com",
|
|
name: "Restore User",
|
|
tenantId: "tenant-id",
|
|
tenantSlug: "restore-tenant",
|
|
});
|
|
expect(result[0]).not.toHaveProperty("id");
|
|
expect(result[0]).not.toHaveProperty("uuid");
|
|
});
|
|
|
|
it("should parse one nullable additional appointment from numbered columns", () => {
|
|
const csv = `email,name,phone,role,tenant_slug,department,grade,position,jobTitle,employee_id,tenant_slug1,department1,grade1,position1,jobTitle1,employee_id1
|
|
dual@test.com,Dual User,010-0000-0000,user,primary-tenant,개발팀,책임,팀장,Backend,EMP001,second-tenant,센터,수석,,Architecture,EMP002
|
|
nullable@test.com,Nullable User,010-1111-1111,user,primary-tenant,개발팀,책임,팀장,Backend,EMP003,,,,,,`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0]).toMatchObject({
|
|
tenantSlug: "primary-tenant",
|
|
department: "개발팀",
|
|
grade: "책임",
|
|
position: "팀장",
|
|
jobTitle: "Backend",
|
|
metadata: {
|
|
employee_id: "EMP001",
|
|
},
|
|
additionalAppointments: [
|
|
{
|
|
tenantSlug: "second-tenant",
|
|
department: "센터",
|
|
grade: "수석",
|
|
jobTitle: "Architecture",
|
|
metadata: {
|
|
employee_id: "EMP002",
|
|
},
|
|
},
|
|
],
|
|
});
|
|
expect(result[1].additionalAppointments).toBeUndefined();
|
|
});
|
|
|
|
it("should preserve sub_email as secondary email metadata without replacing primary email", () => {
|
|
const csv = `email,name,tenant_slug,employee_id,sub_email
|
|
primary@samaneng.com,Primary User,rnd-saman,EMP001,secondary@hanmaceng.co.kr`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
email: "primary@samaneng.com",
|
|
tenantSlug: "rnd-saman",
|
|
metadata: {
|
|
employee_id: "EMP001",
|
|
sub_email: ["secondary@hanmaceng.co.kr"],
|
|
aliasEmails: ["secondary@hanmaceng.co.kr"],
|
|
},
|
|
});
|
|
});
|
|
|
|
it("should mark duplicate bulk alias emails as blocking import errors", () => {
|
|
const csv = `email,name,tenant_slug,sub_email
|
|
user1@samaneng.com,User One,rnd-saman,shared@hanmaceng.co.kr
|
|
user2@samaneng.com,User Two,rnd-saman,shared@hanmaceng.co.kr`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0].importErrors).toContain("duplicateEmail");
|
|
expect(result[1].importErrors).toContain("duplicateEmail");
|
|
});
|
|
|
|
it("should mark a primary email reused as a sub email as a blocking import error", () => {
|
|
const csv = `email,name,tenant_slug,sub_email
|
|
user1@samaneng.com,User One,rnd-saman,user2@samaneng.com
|
|
user2@samaneng.com,User Two,rnd-saman,alias@hanmaceng.co.kr`;
|
|
|
|
const result = parseUserCSV(csv);
|
|
|
|
expect(result).toHaveLength(2);
|
|
expect(result[0].importErrors).toContain("duplicateEmail");
|
|
expect(result[1].importErrors).toContain("duplicateEmail");
|
|
});
|
|
});
|