package handler import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "time" "job-cheng-xing/model" "job-cheng-xing/repository" "job-cheng-xing/service" "github.com/gin-gonic/gin" ) func setupRouter() *gin.Engine { gin.SetMode(gin.TestMode) repo := repository.NewMemoryRepo() svc := service.NewOrderService(repo) handler := NewOrderHandler(svc) r := gin.New() r.POST("/orders", handler.CreateOrder) r.PUT("/orders/:id/accept", handler.AcceptOrder) r.PUT("/orders/:id/cancel", handler.CancelOrder) return r } func TestCreateOrder_Handler(t *testing.T) { r := setupRouter() body := map[string]interface{}{ "service_time": time.Now().Add(24 * time.Hour).Format(time.RFC3339), "duration": 120, "address": "北京朝阳区xxx路xxx号", } jsonBody, _ := json.Marshal(body) req, _ := http.NewRequest("POST", "/orders", bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) if w.Code != http.StatusCreated { t.Errorf("expected 201, got %d: %s", w.Code, w.Body.String()) } var order model.Order json.Unmarshal(w.Body.Bytes(), &order) if order.ID == "" { t.Error("expected non-empty ID") } if order.Status != model.StatusPending { t.Errorf("expected pending, got %s", order.Status) } } func TestAcceptOrder_Handler_Success(t *testing.T) { r := setupRouter() body := map[string]interface{}{ "service_time": time.Now().Add(24 * time.Hour).Format(time.RFC3339), "duration": 120, "address": "北京朝阳", } jsonBody, _ := json.Marshal(body) req, _ := http.NewRequest("POST", "/orders", bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) var order model.Order json.Unmarshal(w.Body.Bytes(), &order) acceptBody := map[string]string{"provider_id": "prov_001"} acceptJSON, _ := json.Marshal(acceptBody) req2, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/accept", bytes.NewBuffer(acceptJSON)) req2.Header.Set("Content-Type", "application/json") w2 := httptest.NewRecorder() r.ServeHTTP(w2, req2) if w2.Code != http.StatusOK { t.Errorf("expected 200, got %d: %s", w2.Code, w2.Body.String()) } } func TestAcceptOrder_Handler_DoubleAccept(t *testing.T) { r := setupRouter() body := map[string]interface{}{ "service_time": time.Now().Add(24 * time.Hour).Format(time.RFC3339), "duration": 120, "address": "北京朝阳", } jsonBody, _ := json.Marshal(body) req, _ := http.NewRequest("POST", "/orders", bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) var order model.Order json.Unmarshal(w.Body.Bytes(), &order) acceptBody1 := map[string]string{"provider_id": "prov_001"} acceptJSON1, _ := json.Marshal(acceptBody1) req1, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/accept", bytes.NewBuffer(acceptJSON1)) req1.Header.Set("Content-Type", "application/json") w1 := httptest.NewRecorder() r.ServeHTTP(w1, req1) if w1.Code != http.StatusOK { t.Fatalf("first accept should succeed, got %d", w1.Code) } acceptBody2 := map[string]string{"provider_id": "prov_002"} acceptJSON2, _ := json.Marshal(acceptBody2) req2, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/accept", bytes.NewBuffer(acceptJSON2)) req2.Header.Set("Content-Type", "application/json") w2 := httptest.NewRecorder() r.ServeHTTP(w2, req2) if w2.Code != http.StatusConflict { t.Errorf("expected 409, got %d: %s", w2.Code, w2.Body.String()) } } func TestCancelOrder_Handler_ThenAcceptFails(t *testing.T) { r := setupRouter() body := map[string]interface{}{ "service_time": time.Now().Add(24 * time.Hour).Format(time.RFC3339), "duration": 120, "address": "北京朝阳", } jsonBody, _ := json.Marshal(body) req, _ := http.NewRequest("POST", "/orders", bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) var order model.Order json.Unmarshal(w.Body.Bytes(), &order) req1, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/cancel", bytes.NewBuffer([]byte("{}"))) req1.Header.Set("Content-Type", "application/json") w1 := httptest.NewRecorder() r.ServeHTTP(w1, req1) if w1.Code != http.StatusOK { t.Fatalf("cancel should succeed, got %d", w1.Code) } acceptBody := map[string]string{"provider_id": "prov_001"} acceptJSON, _ := json.Marshal(acceptBody) req2, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/accept", bytes.NewBuffer(acceptJSON)) req2.Header.Set("Content-Type", "application/json") w2 := httptest.NewRecorder() r.ServeHTTP(w2, req2) if w2.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d: %s", w2.Code, w2.Body.String()) } } func TestCancelOrder_Handler_DoubleCancel(t *testing.T) { r := setupRouter() body := map[string]interface{}{ "service_time": time.Now().Add(24 * time.Hour).Format(time.RFC3339), "duration": 120, "address": "北京朝阳", } jsonBody, _ := json.Marshal(body) req, _ := http.NewRequest("POST", "/orders", bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) var order model.Order json.Unmarshal(w.Body.Bytes(), &order) req1, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/cancel", bytes.NewBuffer([]byte("{}"))) req1.Header.Set("Content-Type", "application/json") w1 := httptest.NewRecorder() r.ServeHTTP(w1, req1) req2, _ := http.NewRequest("PUT", "/orders/"+order.ID+"/cancel", bytes.NewBuffer([]byte("{}"))) req2.Header.Set("Content-Type", "application/json") w2 := httptest.NewRecorder() r.ServeHTTP(w2, req2) if w2.Code != http.StatusBadRequest { t.Errorf("expected 400, got %d: %s", w2.Code, w2.Body.String()) } }