package web import ( "net/http" "net/http/httptest" "net/url" "strings" "testing" "github.com/gin-gonic/gin" "cmautobuy/admin/model" ) func sybPostContext(t *testing.T, values url.Values) (*gin.Context, *httptest.ResponseRecorder) { t.Helper() gin.SetMode(gin.TestMode) recorder := httptest.NewRecorder() context, _ := gin.CreateTestContext(recorder) request := httptest.NewRequest(http.MethodPost, "/syb/sync", strings.NewReader(values.Encode())) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") context.Request = request return context, recorder } func TestSybRedirectLogin_保留指定日期并打开登录弹窗(t *testing.T) { context, recorder := sybPostContext(t, url.Values{ "order_no": {"ORDER-1"}, "date_from": {"2026-08-01"}, "date_to": {"2026-08-09"}, }) (&Handler{}).sybRedirectLogin(context, "") if context.Writer.Status() != http.StatusSeeOther { t.Fatalf("状态码 = %d,期望 %d", context.Writer.Status(), http.StatusSeeOther) } location, err := url.Parse(recorder.Header().Get("Location")) if err != nil { t.Fatalf("解析 Location 失败: %v", err) } query := location.Query() for name, want := range map[string]string{ "login": "1", "order_no": "ORDER-1", "date_from": "2026-08-01", "date_to": "2026-08-09", } { if got := query.Get(name); got != want { t.Errorf("%s = %q,期望 %q;Location=%s", name, got, want, location.String()) } } } func TestSybRedirectRange_保留输入并显示日期错误(t *testing.T) { context, recorder := sybPostContext(t, url.Values{ "date_from": {"2026-08-09"}, "date_to": {"2026-08-01"}, }) (&Handler{}).sybRedirectRange(context, "开始日期不能晚于结束日期") location, err := url.Parse(recorder.Header().Get("Location")) if err != nil { t.Fatalf("解析 Location 失败: %v", err) } query := location.Query() if query.Get("range_error") == "" { t.Fatalf("日期错误后应该显示错误,Location=%s", location.String()) } if query.Get("date_from") != "2026-08-09" || query.Get("date_to") != "2026-08-01" { t.Fatalf("日期错误后应该保留两端输入,Location=%s", location.String()) } } func TestSybRedirectAfterStart_清除本次日期范围(t *testing.T) { context, recorder := sybPostContext(t, url.Values{ "order_no": {"ORDER-1"}, "date_from": {"2026-08-01"}, "date_to": {"2026-08-09"}, }) (&Handler{}).sybRedirectAfterStart(context, "同步已开始") location, err := url.Parse(recorder.Header().Get("Location")) if err != nil { t.Fatal(err) } query := location.Query() if query.Get("order_no") != "ORDER-1" || query.Get("msg") != "同步已开始" { t.Fatalf("跳转应保留搜索和提示: %s", location.String()) } if query.Has("date_from") || query.Has("date_to") { t.Fatalf("启动后不应保留旧日期,否则下一段会误重复: %s", location.String()) } } func TestSybHistoryPagination_保留筛选并重开弹窗(t *testing.T) { view := sybHistoryPagination(2, 3, "ORDER-1", "店铺A", "pdd_missing", "2026-08-01", "2026-08-09") for _, raw := range []string{view.FirstURL, view.PrevURL, view.NextURL, view.LastURL} { location, err := url.Parse(raw) if err != nil { t.Fatal(err) } query := location.Query() if query.Get("history") != "1" || query.Get("order_no") != "ORDER-1" || query.Get("shop") != "店铺A" || query.Get("stage") != "pdd_missing" || query.Get("date_from") != "2026-08-01" || query.Get("date_to") != "2026-08-09" { t.Fatalf("同步记录翻页链接丢失页面状态: %s", raw) } } } func TestSybHistoryURL_刷新时保留当前页和筛选(t *testing.T) { location, err := url.Parse(sybHistoryURL(3, "ORDER-1", "店铺A", "pdd_missing", "2026-08-01", "2026-08-09")) if err != nil { t.Fatal(err) } query := location.Query() for name, want := range map[string]string{ "history": "1", "history_page": "3", "order_no": "ORDER-1", "shop": "店铺A", "stage": "pdd_missing", "date_from": "2026-08-01", "date_to": "2026-08-09", } { if got := query.Get(name); got != want { t.Fatalf("刷新链接 %s=%q,期望 %q;URL=%s", name, got, want, location.String()) } } } func TestSybHistoryPartialURL_只读片段保留当前页和筛选(t *testing.T) { location, err := url.Parse(sybHistoryPartialURL(3, "ORDER-1", "店铺A", "pdd_missing", "2026-08-01", "2026-08-09")) if err != nil { t.Fatal(err) } if location.Path != "/syb/sync-history" { t.Fatalf("局部刷新应使用独立只读路由,实际 %s", location.Path) } query := location.Query() for name, want := range map[string]string{ "history_page": "3", "order_no": "ORDER-1", "shop": "店铺A", "stage": "pdd_missing", "date_from": "2026-08-01", "date_to": "2026-08-09", } { if got := query.Get(name); got != want { t.Fatalf("局部刷新链接 %s=%q,期望 %q;URL=%s", name, got, want, location.String()) } } } func TestSybHistoryPartialPagination_翻页继续使用片段路由(t *testing.T) { view := sybHistoryPartialPagination(2, 3, "ORDER-1", "店铺A", "pdd_missing", "2026-08-01", "2026-08-09") for _, raw := range []string{view.FirstURL, view.PrevURL, view.NextURL, view.LastURL} { location, err := url.Parse(raw) if err != nil { t.Fatal(err) } if location.Path != "/syb/sync-history" { t.Fatalf("弹窗局部翻页不应请求完整 SYB 页面:%s", raw) } } } func TestPurchaseTaskOptionsFromForm_忽略篡改模式并固定Live(t *testing.T) { context, _ := sybPostContext(t, url.Values{ "client_id": {"CLIENT-LIVE"}, "execution_mode": {"dry_run"}, }) options := purchaseTaskOptionsFromForm(context) if options.ExecutionMode != model.TaskExecutionLive { t.Fatalf("篡改 execution_mode 不得创建演练任务,实际 %q", options.ExecutionMode) } if options.ClientID != "CLIENT-LIVE" { t.Fatalf("采购客户端读取错误: %+v", options) } } func TestSybCollectPddBatch_未选择时保留列表筛选(t *testing.T) { context, recorder := sybPostContext(t, url.Values{ "order_no": {"ORDER-1"}, "shop": {"qwg8fkb044"}, "stage": {"pdd_pending"}, "page": {"2"}, }) (&Handler{}).SybCollectPddBatch(context) location, err := url.Parse(recorder.Header().Get("Location")) if err != nil { t.Fatal(err) } query := location.Query() for name, want := range map[string]string{ "order_no": "ORDER-1", "shop": "qwg8fkb044", "stage": "pdd_pending", "page": "2", } { if got := query.Get(name); got != want { t.Errorf("批量采集返回丢失 %s:got=%q want=%q Location=%s", name, got, want, location.String()) } } if !strings.Contains(query.Get("msg"), "没有选择") { t.Fatalf("未选择应返回可读提示:%s", location.String()) } }