package lib import ( "encoding/json" "testing" ) func TestOrgDataJSONMarshal(t *testing.T) { tests := []struct { name string orgData OrgData }{ { name: "single domain", orgData: OrgData{ Name: "Kaseya Corp", Domains: []string{"kaseya.com"}, Role: "seller", Website: "https://kaseya.com", Description: "IT management software company", ContactName: "Fred Voccola", ContactEmail: "fred@kaseya.com", }, }, { name: "multi domain", orgData: OrgData{ Name: "Datto Holdings", Domains: []string{"kaseya.com", "datto.com", "unitrends.com"}, Role: "buyer", }, }, { name: "minimal", orgData: OrgData{ Name: "Test Org", Domains: []string{"test.com"}, }, }, { name: "ib role", orgData: OrgData{ Name: "Goldman Sachs", Domains: []string{"gs.com", "goldmansachs.com"}, Role: "ib", }, }, { name: "advisor role", orgData: OrgData{ Name: "Deloitte", Domains: []string{"deloitte.com"}, Role: "advisor", }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { // Marshal data, err := json.Marshal(tc.orgData) if err != nil { t.Fatalf("Marshal failed: %v", err) } // Unmarshal var got OrgData if err := json.Unmarshal(data, &got); err != nil { t.Fatalf("Unmarshal failed: %v", err) } // Verify fields if got.Name != tc.orgData.Name { t.Errorf("Name: got %q, want %q", got.Name, tc.orgData.Name) } if len(got.Domains) != len(tc.orgData.Domains) { t.Errorf("Domains length: got %d, want %d", len(got.Domains), len(tc.orgData.Domains)) } for i, d := range tc.orgData.Domains { if got.Domains[i] != d { t.Errorf("Domains[%d]: got %q, want %q", i, got.Domains[i], d) } } if got.Role != tc.orgData.Role { t.Errorf("Role: got %q, want %q", got.Role, tc.orgData.Role) } if got.Website != tc.orgData.Website { t.Errorf("Website: got %q, want %q", got.Website, tc.orgData.Website) } if got.Description != tc.orgData.Description { t.Errorf("Description: got %q, want %q", got.Description, tc.orgData.Description) } if got.ContactName != tc.orgData.ContactName { t.Errorf("ContactName: got %q, want %q", got.ContactName, tc.orgData.ContactName) } if got.ContactEmail != tc.orgData.ContactEmail { t.Errorf("ContactEmail: got %q, want %q", got.ContactEmail, tc.orgData.ContactEmail) } }) } } func TestOrgDataJSONOmitEmpty(t *testing.T) { // Verify omitempty works for optional fields orgData := OrgData{ Name: "Minimal Org", Domains: []string{"minimal.com"}, } data, err := json.Marshal(orgData) if err != nil { t.Fatalf("Marshal failed: %v", err) } // Parse as map to check field presence var m map[string]interface{} if err := json.Unmarshal(data, &m); err != nil { t.Fatalf("Unmarshal to map failed: %v", err) } // Required fields should be present if _, ok := m["name"]; !ok { t.Error("name should be present") } if _, ok := m["domains"]; !ok { t.Error("domains should be present") } // Optional fields with zero values should be omitted if v, ok := m["website"]; ok && v != "" { t.Error("website should be omitted when empty") } if v, ok := m["description"]; ok && v != "" { t.Error("description should be omitted when empty") } } func TestDealOrgDataJSONMarshal(t *testing.T) { tests := []struct { name string dealOrgData DealOrgData }{ { name: "seller with domain lock", dealOrgData: DealOrgData{ OrgID: "org-123", Role: "seller", DomainLock: true, }, }, { name: "buyer without domain lock", dealOrgData: DealOrgData{ OrgID: "org-456", Role: "buyer", DomainLock: false, }, }, { name: "ib role", dealOrgData: DealOrgData{ OrgID: "org-789", Role: "ib", DomainLock: true, }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { data, err := json.Marshal(tc.dealOrgData) if err != nil { t.Fatalf("Marshal failed: %v", err) } var got DealOrgData if err := json.Unmarshal(data, &got); err != nil { t.Fatalf("Unmarshal failed: %v", err) } if got.OrgID != tc.dealOrgData.OrgID { t.Errorf("OrgID: got %q, want %q", got.OrgID, tc.dealOrgData.OrgID) } if got.Role != tc.dealOrgData.Role { t.Errorf("Role: got %q, want %q", got.Role, tc.dealOrgData.Role) } if got.DomainLock != tc.dealOrgData.DomainLock { t.Errorf("DomainLock: got %v, want %v", got.DomainLock, tc.dealOrgData.DomainLock) } }) } } func TestRequestDataJSONMarshal(t *testing.T) { tests := []struct { name string req RequestData }{ { name: "full request", req: RequestData{ Title: "Provide audited financial statements for the last 3 years", ItemNumber: "1.3", Section: "Financial", Description: "Please provide audited P&L, balance sheet, and cash flow statements for FY2023, FY2024, FY2025.", Priority: "high", Status: "open", AssigneeID: "user-123", AssigneeName: "John Smith", DueDate: "2026-03-15", BuyerComment: "Need by end of week", SellerComment: "Working on it", Tags: []string{"financial", "urgent", "audit"}, LinkedEntryIDs: []string{"entry-1", "entry-2"}, }, }, { name: "minimal request", req: RequestData{ Title: "Basic info request", ItemNumber: "A-1", Section: "General", Priority: "medium", Status: "open", }, }, { name: "answered request", req: RequestData{ Title: "Revenue breakdown by geography", ItemNumber: "2.1", Section: "Sales", Description: "Provide revenue split by region (NA, EMEA, APAC)", Priority: "low", Status: "answered", LinkedEntryIDs: []string{"answer-123"}, }, }, { name: "not applicable", req: RequestData{ Title: "Union contracts", ItemNumber: "5.2", Section: "HR", Description: "Provide all union agreements", Priority: "low", Status: "not_applicable", }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { data, err := json.Marshal(tc.req) if err != nil { t.Fatalf("Marshal failed: %v", err) } var got RequestData if err := json.Unmarshal(data, &got); err != nil { t.Fatalf("Unmarshal failed: %v", err) } if got.Title != tc.req.Title { t.Errorf("Title: got %q, want %q", got.Title, tc.req.Title) } if got.ItemNumber != tc.req.ItemNumber { t.Errorf("ItemNumber: got %q, want %q", got.ItemNumber, tc.req.ItemNumber) } if got.Section != tc.req.Section { t.Errorf("Section: got %q, want %q", got.Section, tc.req.Section) } if got.Priority != tc.req.Priority { t.Errorf("Priority: got %q, want %q", got.Priority, tc.req.Priority) } if got.Status != tc.req.Status { t.Errorf("Status: got %q, want %q", got.Status, tc.req.Status) } if len(got.Tags) != len(tc.req.Tags) { t.Errorf("Tags length: got %d, want %d", len(got.Tags), len(tc.req.Tags)) } if len(got.LinkedEntryIDs) != len(tc.req.LinkedEntryIDs) { t.Errorf("LinkedEntryIDs length: got %d, want %d", len(got.LinkedEntryIDs), len(tc.req.LinkedEntryIDs)) } }) } } func TestWorkstreamDataJSONMarshal(t *testing.T) { tests := []struct { name string ws WorkstreamData }{ { name: "with description", ws: WorkstreamData{ Name: "Financial Due Diligence", Description: "All financial information requests", }, }, { name: "minimal", ws: WorkstreamData{ Name: "Legal", }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { data, err := json.Marshal(tc.ws) if err != nil { t.Fatalf("Marshal failed: %v", err) } var got WorkstreamData if err := json.Unmarshal(data, &got); err != nil { t.Fatalf("Unmarshal failed: %v", err) } if got.Name != tc.ws.Name { t.Errorf("Name: got %q, want %q", got.Name, tc.ws.Name) } if got.Description != tc.ws.Description { t.Errorf("Description: got %q, want %q", got.Description, tc.ws.Description) } }) } } func TestRoleHierarchyContainsSuperAdmin(t *testing.T) { // Verify super_admin is in the hierarchy and has the highest level saLevel, ok := RoleHierarchy[RoleSuperAdmin] if !ok { t.Fatal("super_admin should be in RoleHierarchy") } // super_admin should be higher than all other roles for role, level := range RoleHierarchy { if role != RoleSuperAdmin && level >= saLevel { t.Errorf("super_admin (%d) should be higher than %s (%d)", saLevel, role, level) } } }