package tests import ( "testing" ) func TestOrgCRUD(t *testing.T) { ensureUsers(t) var orgID string // Test 1: Create Organization t.Run("Create Organization", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "test_org_crud", "name": "Test Org CRUD", "description": "Organization for CRUD tests", }, User1Token) assertStatus(t, resp, 200) var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) orgID = data.ID t.Logf("Created org: %s", orgID) }) if orgID == "" { t.Fatal("Failed to create org, skipping remaining tests") } // Test 2: List Organizations t.Run("List Organizations", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs", nil, User1Token) assertStatus(t, resp, 200) var data struct { Items []OrgResp `json:"items"` Total int64 `json:"total"` } decodeResponse(t, resp, &data) t.Logf("Total orgs: %d", data.Total) if data.Total <= 0 { t.Errorf("Expected at least 1 org, got %d", data.Total) } }) // Test 3: Get Org Details t.Run("Get Org Details", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) var data OrgResp decodeResponse(t, resp, &data) if data.Name != "Test Org CRUD" { t.Errorf("Expected name 'Test Org CRUD', got '%s'", data.Name) } if data.Code != "test_org_crud" { t.Errorf("Expected code 'test_org_crud', got '%s'", data.Code) } }) // Test 4: Update Organization t.Run("Update Organization", func(t *testing.T) { resp := doRequest(t, "PATCH", "/api/orgs/"+orgID, map[string]string{ "name": "Updated Org Name", "description": "Updated description", }, User1Token) assertStatus(t, resp, 200) // Verify update resp = doRequest(t, "GET", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) var data OrgResp decodeResponse(t, resp, &data) if data.Name != "Updated Org Name" { t.Errorf("Expected name 'Updated Org Name', got '%s'", data.Name) } }) // Test 5: Get Org Members t.Run("Get Org Members", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID+"/members", nil, User1Token) assertStatus(t, resp, 200) var data struct { Items []struct { UserID string `json:"user_id"` Role string `json:"role"` } `json:"items"` } decodeResponse(t, resp, &data) t.Logf("Org members count: %d", len(data.Items)) }) // Test 6: Delete Organization (as owner) t.Run("Delete Organization", func(t *testing.T) { resp := doRequest(t, "DELETE", "/api/orgs/"+orgID, nil, User1Token) assertStatus(t, resp, 200) // Verify deletion resp = doRequest(t, "GET", "/api/orgs/"+orgID, nil, User1Token) if resp.Code == 200 { t.Errorf("Expected org to be deleted, but got 200") } else { t.Logf("Org deleted successfully, got code: %d", resp.Code) } }) // Test 7: List after deletion t.Run("List After Delete", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs", nil, User1Token) assertStatus(t, resp, 200) var data struct { Total int64 `json:"total"` } decodeResponse(t, resp, &data) t.Logf("Total orgs after delete: %d", data.Total) }) } // Test Org Tree func TestOrgTree(t *testing.T) { ensureUsers(t) // Create parent org var parentOrgID string t.Run("Create Parent Org", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "parent_org", "name": "Parent Organization", "description": "Parent org for tree test", }, User1Token) assertStatus(t, resp, 200) var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) parentOrgID = data.ID }) if parentOrgID == "" { t.Fatal("Failed to create parent org") } // Get org tree t.Run("Get Org Tree", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/tree", nil, User1Token) assertStatus(t, resp, 200) // Tree endpoint returns array directly var data []OrgResp decodeResponse(t, resp, &data) t.Logf("Org tree items: %d", len(data)) }) } // Test non-member access func TestOrgAccessControl(t *testing.T) { ensureUsers(t) // User1 creates org var orgID string t.Run("User1 Creates Org", func(t *testing.T) { resp := doRequest(t, "POST", "/api/orgs", map[string]string{ "code": "private_org", "name": "Private Organization", "description": "Private org for access test", }, User1Token) assertStatus(t, resp, 200) var data struct { ID string `json:"id"` } decodeResponse(t, resp, &data) orgID = data.ID }) if orgID == "" { t.Fatal("Failed to create org") } // User2 (non-member) tries to access t.Run("Non-member Get Org", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID, nil, User2Token) // Should fail with 403 if resp.Code == 200 { t.Errorf("Expected non-member to be denied, got 200") } else { t.Logf("Non-member correctly denied access, code: %d", resp.Code) } }) t.Run("Non-member Update Org", func(t *testing.T) { resp := doRequest(t, "PATCH", "/api/orgs/"+orgID, map[string]string{ "name": "Hacked", }, User2Token) // Should fail with 403 if resp.Code == 200 { t.Errorf("Expected non-member to be denied, got 200") } else { t.Logf("Non-member correctly denied update, code: %d", resp.Code) } }) t.Run("Non-member Get Members", func(t *testing.T) { resp := doRequest(t, "GET", "/api/orgs/"+orgID+"/members", nil, User2Token) // Should fail with 403 if resp.Code == 200 { t.Errorf("Expected non-member to be denied, got 200") } else { t.Logf("Non-member correctly denied members access, code: %d", resp.Code) } }) }