| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- package testutil
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "testing"
- "time"
- "wails-app/internal/dao"
- "wails-app/internal/global"
- "wails-app/internal/model/common/response"
- "wails-app/internal/utils"
- )
- // ===================== 端到端测试用例 =====================
- func TestLoginFlow(t *testing.T) {
- env := InitTestEnv(t)
- if env.Token == "" {
- t.Fatalf("Token is empty")
- }
- j := &utils.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)}
- claims, err := j.ParseToken(env.Token)
- if err != nil {
- t.Fatalf("Token parse failed: %v", err)
- }
- if claims.Username != "admin" || claims.AuthorityId != 888 {
- t.Fatalf("Token claims mismatch: username=%s, authorityId=%d", claims.Username, claims.AuthorityId)
- }
- fmt.Printf("PASS: Login flow verified, Token: %s...\n", env.Token[:min(20, len(env.Token))])
- }
- func TestSystemManagement(t *testing.T) {
- env := InitTestEnv(t)
- resp, body := env.DoPost("/user/getUserList", map[string]interface{}{
- "page": 1,
- "pageSize": 10,
- })
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- var result response.Response
- json.Unmarshal(body, &result)
- dataMap, ok := result.Data.(map[string]interface{})
- if !ok {
- t.Fatalf("data is not map type: %T", result.Data)
- }
- listRaw, exists := dataMap["list"]
- if !exists {
- t.Fatalf("data.list missing, keys: %v", mapKeys(dataMap))
- }
- list, ok := listRaw.([]interface{})
- if !ok {
- t.Fatalf("data.list is not array: %T", listRaw)
- }
- if len(list) == 0 {
- t.Fatalf("user list is empty")
- }
- fmt.Printf("PASS: User list query successful, total %d records\n", len(list))
- }
- func TestParkingInfrastructure(t *testing.T) {
- env := InitTestEnv(t)
- lotResp, lotBody := env.DoPost("/parking/lot/create", map[string]interface{}{
- "lot_code": "TEST002",
- "lot_name": "Test Parking Lot B Zone",
- "capacity": 200,
- "description": "Automated test parking lot B zone",
- })
- AssertResponse(t, lotResp, lotBody, http.StatusOK, response.SUCCESS)
- resp, body := env.DoGet("/parking/lot/list", map[string]string{
- "page": "1",
- "page_size": "10",
- })
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- list := ParsePageList(body)
- if len(list) < 2 {
- t.Fatalf("Parking lot list should contain at least 2 items, actual %d", len(list))
- }
- fmt.Printf("PASS: Parking lot create and query successful, total %d lots\n", len(list))
- }
- func TestVehicleCRUD(t *testing.T) {
- env := InitTestEnv(t)
- createVehicle(t, env, "JingA12345", "RFID001", 1)
- resp, body := env.DoGet("/vehicle/get-by-plate", map[string]string{
- "plate_number": "JingA12345",
- })
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- dataMap := ParseDataMap(body)
- if dataMap["plate_number"] != "JingA12345" {
- t.Fatalf("Vehicle info mismatch")
- }
- fmt.Println("PASS: Vehicle create and query successful")
- }
- func TestFeeConfig(t *testing.T) {
- env := InitTestEnv(t)
- resp, body := env.DoGet("/vehicle/fee-config/list", map[string]string{
- "page": "1",
- "page_size": "10",
- })
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- list := ParsePageList(body)
- if len(list) == 0 {
- t.Fatalf("Fee config list is empty")
- }
- fmt.Printf("PASS: Fee config query successful, total %d records\n", len(list))
- }
- func TestVehicleEntryAndExit(t *testing.T) {
- env := InitTestEnv(t)
- createVehicle(t, env, "JingB67890", "RFID002", 1)
- entryResp, entryBody := env.DoPost("/vehicle/entry", map[string]interface{}{
- "plate_number": "JingB67890",
- "rfid_tag": "RFID002",
- "parking_lot_id": 1,
- "parking_space_id": 10,
- "entry_image": "test_entry.jpg",
- })
- AssertResponse(t, entryResp, entryBody, http.StatusOK, response.SUCCESS)
- fmt.Println("PASS: Vehicle entry successful")
- // Set entry time to 2 hours ago to skip real waiting
- entryTime := time.Now().Add(-2 * time.Hour)
- global.GVA_DB.Model(&dao.VehicleRecord{}).Where("plate_number = ?", "JingB67890").Update("entry_time", entryTime)
- exitPreviewResp, exitPreviewBody := env.DoPost("/vehicle/exit/preview", map[string]interface{}{
- "plate_number": "JingB67890",
- "rfid_tag": "RFID002",
- })
- AssertResponse(t, exitPreviewResp, exitPreviewBody, http.StatusOK, response.SUCCESS)
- exitConfirmResp, exitConfirmBody := env.DoPost("/vehicle/exit/confirm", map[string]interface{}{
- "plate_number": "JingB67890",
- "rfid_tag": "RFID002",
- "payment_method": "cash",
- "paid_amount": 10.0,
- })
- AssertResponse(t, exitConfirmResp, exitConfirmBody, http.StatusOK, response.SUCCESS)
- fmt.Println("PASS: Vehicle exit and payment successful")
- paymentResp, paymentBody := env.DoGet("/payment/list", map[string]string{
- "page": "1",
- "page_size": "10",
- "plate_number": "JingB67890",
- })
- AssertResponse(t, paymentResp, paymentBody, http.StatusOK, response.SUCCESS)
- list := ParsePageList(paymentBody)
- if len(list) == 0 {
- t.Fatalf("Payment record query returned empty")
- }
- fmt.Printf("PASS: Payment record query successful, total %d records\n", len(list))
- }
- func TestBlackWhiteList(t *testing.T) {
- env := InitTestEnv(t)
- createVehicle(t, env, "JingC11111", "RFID_WHITE", 1)
- var vehicle dao.Vehicle
- env.DB.Where("plate_number = ?", "JingC11111").First(&vehicle)
- shortlistResp, shortlistBody := env.DoPost("/shortlist/createShortlist", dao.Shortlist{
- ListType: "白名单",
- VehicleId: int(vehicle.ID),
- ExpirationTime: nil,
- })
- AssertResponse(t, shortlistResp, shortlistBody, http.StatusOK, response.SUCCESS)
- resp, body := env.DoGet("/shortlist/queryAllShortlists", nil)
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- fmt.Println("PASS: Black/white list operation successful")
- }
- // TestBlackWhiteListEntryExitBehavior 测试黑白名单对进出场的影响
- // 注意:当前后端 VehicleEntry 尚未集成 CheckVehicleShortlist,
- // 此测试记录当前行为,待业务逻辑接入后断言应反转。
- func TestBlackWhiteListEntryExitBehavior(t *testing.T) {
- env := InitTestEnv(t)
- // --- 场景1:黑名单车辆尝试进场 ---
- createVehicle(t, env, "JingB99999", "RFID_BLACK", 1)
- var blackVehicle dao.Vehicle
- env.DB.Where("plate_number = ?", "JingB99999").First(&blackVehicle)
- _, _ = env.DoPost("/shortlist/createShortlist", dao.Shortlist{
- ListType: "黑名单",
- VehicleId: int(blackVehicle.ID),
- ExpirationTime: nil,
- })
- entryResp, entryBody := env.DoPost("/vehicle/entry", map[string]interface{}{
- "plate_number": "JingB99999",
- "rfid_tag": "RFID_BLACK",
- "parking_lot_id": 1,
- "parking_space_id": 99,
- "entry_image": "test_black_entry.jpg",
- })
- // 黑名单车辆应该被拦截,进场请求应返回失败
- if entryResp.StatusCode == http.StatusOK {
- var result struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- }
- json.Unmarshal(entryBody, &result)
- if result.Code == response.SUCCESS {
- t.Fatalf("BUG: Blacklisted vehicle entry was NOT blocked! Response: code=%d msg=%s", result.Code, result.Msg)
- }
- }
- AssertResponse(t, entryResp, entryBody, http.StatusOK, response.ERROR)
- // --- 场景2:白名单车辆进场 ---
- createVehicle(t, env, "JingW00001", "RFID_WHITELIST", 1)
- var whiteVehicle dao.Vehicle
- env.DB.Where("plate_number = ?", "JingW00001").First(&whiteVehicle)
- _, _ = env.DoPost("/shortlist/createShortlist", dao.Shortlist{
- ListType: "白名单",
- VehicleId: int(whiteVehicle.ID),
- ExpirationTime: nil,
- })
- entryResp2, entryBody2 := env.DoPost("/vehicle/entry", map[string]interface{}{
- "plate_number": "JingW00001",
- "rfid_tag": "RFID_WHITELIST",
- "parking_lot_id": 1,
- "parking_space_id": 88,
- "entry_image": "test_white_entry.jpg",
- })
- AssertResponse(t, entryResp2, entryBody2, http.StatusOK, response.SUCCESS)
- fmt.Println("PASS: Whitelisted vehicle entry successful")
- // --- 场景3:查询黑白名单列表确认两条记录存在 ---
- resp3, body3 := env.DoGet("/shortlist/queryAllShortlists", nil)
- AssertResponse(t, resp3, body3, http.StatusOK, response.SUCCESS)
- // queryAllShortlists 返回 data=[] 数组格式,不是分页结构
- var result3 response.Response
- json.Unmarshal(body3, &result3)
- listRaw, ok := result3.Data.([]interface{})
- if !ok {
- t.Fatalf("shortlist data is not array: %T", result3.Data)
- }
- if len(listRaw) < 2 {
- t.Fatalf("Expected at least 2 shortlist records, got %d", len(listRaw))
- }
- fmt.Printf("PASS: Shortlist query returned %d records\n", len(listRaw))
- // --- 场景4:白名单车辆出场,验证费用计算(VIP/白名单免单逻辑)---
- exitPreviewResp, exitPreviewBody := env.DoPost("/vehicle/exit/preview", map[string]interface{}{
- "plate_number": "JingW00001",
- "rfid_tag": "RFID_WHITELIST",
- })
- AssertResponse(t, exitPreviewResp, exitPreviewBody, http.StatusOK, response.SUCCESS)
- // 修改入场时间为 1 小时前
- entryTime := time.Now().Add(-1 * time.Hour)
- global.GVA_DB.Model(&dao.VehicleRecord{}).Where("plate_number = ?", "JingW00001").Update("entry_time", entryTime)
- exitConfirmResp, exitConfirmBody := env.DoPost("/vehicle/exit/confirm", map[string]interface{}{
- "plate_number": "JingW00001",
- "rfid_tag": "RFID_WHITELIST",
- "payment_method": "cash",
- "paid_amount": 0.0,
- })
- AssertResponse(t, exitConfirmResp, exitConfirmBody, http.StatusOK, response.SUCCESS)
- fmt.Println("PASS: Whitelisted vehicle exit and payment successful")
- }
- func TestOwnerManagement(t *testing.T) {
- env := InitTestEnv(t)
- ownerResp, ownerBody := env.DoPost("/owner/create", map[string]interface{}{
- "owner_name": "Zhang San",
- "owner_surname": "Zhang",
- "owner_phone": "13800138000",
- "is_vip": true,
- "vip_expire_time": time.Now().Add(365 * 24 * time.Hour).Format(time.RFC3339),
- })
- AssertResponse(t, ownerResp, ownerBody, http.StatusOK, response.SUCCESS)
- resp, body := env.DoGet("/owner/list", map[string]string{
- "page": "1",
- "page_size": "10",
- })
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- list := ParsePageList(body)
- if len(list) == 0 {
- t.Fatalf("Owner list is empty after creation")
- }
- fmt.Printf("PASS: Owner management successful, total %d owners\n", len(list))
- }
- func TestDashboardMonitoring(t *testing.T) {
- env := InitTestEnv(t)
- resp, body := env.DoGetRaw("/dashboard/monitor", nil)
- AssertResponse(t, resp, body, http.StatusOK, response.SUCCESS)
- dataMap := ParseDataMap(body)
- if dataMap == nil {
- t.Fatalf("Dashboard data is empty")
- }
- fmt.Println("PASS: Dashboard monitoring data query successful")
- }
- // ===================== Helper functions =====================
- func createVehicle(t *testing.T, env *TestEnv, plateNumber, rfidTag string, vehicleTypeID uint) {
- t.Helper()
- _, body := env.DoPost("/vehicle/create", map[string]interface{}{
- "plate_number": plateNumber,
- "vehicle_type_id": vehicleTypeID,
- "vehicle_brand": "TestBrand",
- "vehicle_color": "TestColor",
- "rfid_tag": rfidTag,
- })
- var result struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- }
- json.Unmarshal(body, &result)
- if result.Code != response.SUCCESS {
- t.Fatalf("Failed to create vehicle: %s", result.Msg)
- }
- }
|