package osi import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "time" ) func TestLastHealthCheckDecodesSummaryAndHitsPath(t *testing.T) { var seenPath string server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seenPath = r.URL.Path w.Header().Set("Content-Type", "application/json") // data 为单个对象(非数组);字段名取自实测结构,值均为脱敏假数据 _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":{"checkId":"CHK-TEST-001","healthCheck":"CHK-TEST-001","idcard":"TEST-ID","personName":"测试","checkDate":"2026-01-01"}}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{BaseURL: server.URL, UserName: "u", Ask: "k", Transport: transport}) summary, result, err := client.LastHealthCheck(context.Background(), FindHealthCheckQuery{IDCard: "TEST-ID"}) if err != nil { t.Fatalf("LastHealthCheck: %v", err) } if seenPath != "/osi/api/auto/jktjlscx/query" { t.Fatalf("path = %q", seenPath) } if summary.CheckID != "CHK-TEST-001" || summary.HealthCheck != "CHK-TEST-001" { t.Fatalf("summary keys = %#v", summary) } // 体检身份证是小写 idcard,确认 tag 正确映射 if summary.IDCard != "TEST-ID" { t.Fatalf("summary.IDCard = %q (体检 idcard tag 映射错误)", summary.IDCard) } if !result.Success || len(result.Raw) == 0 { t.Fatalf("result should be success with raw retained: %#v", result) } } func TestQueryHealthChecksDecodesArrayAndHitsPath(t *testing.T) { var seenPath string server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seenPath = r.URL.Path w.Header().Set("Content-Type", "application/json") // data 为数组=某人全部体检;idCard 驼峰;历史记录 checkId 为 null(脱敏假数据) _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":[` + `{"checkId":"CHK-1","checkDate":"2025-06-23","idCard":"TEST-ID","personName":"测试"},` + `{"checkId":null,"checkDate":"2013-06-07","idCard":"TEST-ID","personName":"测试"}]}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{BaseURL: server.URL, UserName: "u", Ask: "k", Transport: transport}) records, result, err := client.QueryHealthChecks(context.Background(), FindHealthCheckQuery{IDCard: "TEST-ID"}) if err != nil { t.Fatalf("QueryHealthChecks: %v", err) } if seenPath != "/osi/api/auto/jktj/query" { t.Fatalf("path = %q", seenPath) } if !result.Success || len(records) != 2 { t.Fatalf("records = %d result = %#v", len(records), result) } // 驼峰 idCard 应解出;历史记录 null checkId 解为空串且不报错 if records[0].CheckID != "CHK-1" || records[0].IDCard != "TEST-ID" { t.Fatalf("row0 = %#v", records[0]) } if records[1].CheckID != "" || records[1].CheckDate != "2013-06-07" { t.Fatalf("row1 (null checkId) = %#v", records[1]) } } func TestListHealthCheckPeopleDecodesRosterAndHitsPath(t *testing.T) { var seenPath string var seenBody map[string]any server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { seenPath = r.URL.Path _ = json.NewDecoder(r.Body).Decode(&seenBody) w.Header().Set("Content-Type", "application/json") // data 为人员名单数组;字段名取自实测,值均为脱敏假数据 _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":[` + `{"idCard":"TEST-1","personName":"甲","phrId":"PHR-1","checkType":"0","rqbj":"PU"},` + `{"idCard":"TEST-2","personName":"乙","phrId":"PHR-2","checkType":"1","rqbj":"LAO"}]}`)) })) defer server.Close() transport, err := NewTransport(TransportConfig{Timeout: time.Second}) if err != nil { t.Fatalf("NewTransport: %v", err) } client := NewClient(ClientConfig{BaseURL: server.URL, UserName: "u", Ask: "k", Transport: transport}) people, result, err := client.ListHealthCheckPeople(context.Background(), ListHealthCheckQuery{CheckYear: "2025", IDCard: "TEST-1", CheckType: "2"}) if err != nil { t.Fatalf("ListHealthCheckPeople: %v", err) } if seenPath != "/osi/api/auto/jktjlist/query" { t.Fatalf("path = %q", seenPath) } if !result.Success || len(people) != 2 { t.Fatalf("people = %d result = %#v", len(people), result) } if people[0].CheckType != "0" || people[0].PhrID != "PHR-1" { t.Fatalf("row0 = %#v", people[0]) } // checkYear/page/rows 应落在 uploadinfo.baseInfo base := seenBody["uploadinfo"].(map[string]any)["baseInfo"].(map[string]any) if base["checkYear"] != "2025" || base["page"] != "1" || base["rows"] != "10" { t.Fatalf("baseInfo = %#v", base) } } func TestListHealthCheckQueryRequiresCheckYear(t *testing.T) { if _, err := (ListHealthCheckQuery{IDCard: "x"}).baseInfo(); err == nil { t.Fatal("missing checkYear should error") } base, err := (ListHealthCheckQuery{CheckYear: "2025"}).baseInfo() if err != nil || base["page"] != "1" || base["rows"] != "10" { t.Fatalf("default page/rows wrong: %v err=%v", base, err) } } func TestFindHealthCheckQueryRequiresExactlyOneKey(t *testing.T) { if _, err := (FindHealthCheckQuery{}).baseInfo(); err == nil { t.Fatal("empty query should error") } if _, err := (FindHealthCheckQuery{IDCard: "a", PHRID: "b"}).baseInfo(); err == nil { t.Fatal("two keys should error") } bi, err := (FindHealthCheckQuery{IDCard: "a"}).baseInfo() if err != nil || bi["idCard"] != "a" { t.Fatalf("baseInfo = %v err = %v", bi, err) } }