From 66547ddd16b5ea9677dc82610024392776c86cd3 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Mon, 27 Jul 2026 01:12:06 +0800 Subject: [PATCH] =?UTF-8?q?test:=20P1=20ConsoleSave=E6=B5=8B=E8=AF=95=20+?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E6=97=A7=E6=B5=8B=E8=AF=95=E7=AD=BE?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/service/config_assets_test.go | 6 +-- internal/service/config_preview_test.go | 10 ++--- internal/web/ui_test.go | 60 ++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/internal/service/config_assets_test.go b/internal/service/config_assets_test.go index 05a2fcc..5bc7dae 100644 --- a/internal/service/config_assets_test.go +++ b/internal/service/config_assets_test.go @@ -405,7 +405,7 @@ func TestListVideoSources(t *testing.T) { repo := storage.NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -439,7 +439,7 @@ func TestDeleteVideoSourceBlocksWhenReferenced(t *testing.T) { repo := storage.NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -474,7 +474,7 @@ func TestSaveVideoSourceAssetAllowsChineseName(t *testing.T) { Config: VideoSourceConfig{ URL: "rtsp://10.0.0.1/live", }, - }) + }, "") if err != nil { t.Fatalf("expected chinese video source name to be accepted, got %v", err) } diff --git a/internal/service/config_preview_test.go b/internal/service/config_preview_test.go index 292c486..4395bad 100644 --- a/internal/service/config_preview_test.go +++ b/internal/service/config_preview_test.go @@ -177,7 +177,7 @@ func TestConfigPreviewServiceRenderProfileEditorWritesResolvedBindings(t *testin defer store.Close() repo := storage.NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -267,7 +267,7 @@ func TestConfigPreviewServiceRenderProfileEditorAllowsUnboundOptionalServiceSlot defer store.Close() repo := storage.NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -351,7 +351,7 @@ func TestConfigPreviewServiceRenderUsesSQLiteProfileAndOverlay(t *testing.T) { t.Fatalf("SaveOverlay: %v", err) } if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -435,7 +435,7 @@ func TestConfigPreviewServiceRenderUsesProfileOverlayWhenRequestOmitsIt(t *testi t.Fatalf("SaveOverlay: %v", err) } if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", @@ -497,7 +497,7 @@ func TestConfigPreviewServiceResolveSceneBindings(t *testing.T) { repo := storage.NewAssetsRepo(store.DB()) if err := repo.SaveVideoSource( - "gate_cam_01", + 0, "gate_cam_01", "rtsp", "东门入口", "东门主入口摄像头", diff --git a/internal/web/ui_test.go b/internal/web/ui_test.go index cb6eb0a..e085511 100644 --- a/internal/web/ui_test.go +++ b/internal/web/ui_test.go @@ -898,7 +898,7 @@ func mustImportAssetsForUI(t *testing.T, preview *service.ConfigPreviewService) func mustSaveVideoSource(t *testing.T, repo *storage.AssetsRepo, name string, body string) { t.Helper() - if err := repo.SaveVideoSource(name, "rtsp", "", name, body); err != nil { + if err := repo.SaveVideoSource(0, name, "rtsp", "", name, body); err != nil { t.Fatalf("SaveVideoSource(%s): %v", name, err) } } @@ -4592,3 +4592,61 @@ func TestUI_SystemDBRestoreRequiresSelectedFile(t *testing.T) { t.Fatalf("expected raw form-file error to stay hidden, got: %s", html) } } + +func newTestUIWithPreview(t *testing.T) (*UI, *storage.Store) { + t.Helper() + dbPath := filepath.Join(t.TempDir(), "console.db") + store, err := storage.OpenSQLite(dbPath) + if err != nil { + t.Fatalf("OpenSQLite: %v", err) + } + t.Cleanup(func() { _ = store.Close() }) + + cfg := &config.Config{Concurrency: 1, OfflineAfterMs: 1000000} + reg := service.NewRegistryService(cfg, nil, storage.NewDevicesRepo(store.DB())) + reg.UpdateDevice(&models.Device{DeviceID: "dev1", DeviceName: "设备1", IP: "10.0.0.1", AgentPort: 9100, Online: true}) + tasks := service.NewTaskService(cfg, nil, reg) + + repo := storage.NewAssetsRepo(store.DB()) + preview := service.NewConfigPreviewService(cfg, repo) + // Seed template + repo.SaveTemplate("std_face_recognition_stream", "test", `{"name":"std_face_recognition_stream","template":{"nodes":[{"id":"in","type":"input_rtsp"}],"edges":[]}}`) + // Seed video source + preview.SaveVideoSourceAsset(service.ConfigVideoSourceAsset{ + Name: "cam1", SourceType: "rtsp", + Config: service.VideoSourceConfig{URL: "rtsp://10.0.0.1/live", Resolution: "1920x1080", FPS: "30"}, + }, "") + + ui, err := NewUI(nil, reg, nil, tasks, nil, preview) + if err != nil { + t.Fatalf("NewUI: %v", err) + } + ui.SetDBPath(dbPath) + autoCfg := service.NewAutoConfigService(preview, tasks, service.NewFeatureRegistry()) + ui.SetAutoConfig(autoCfg) + return ui, store +} + +func TestUI_ConsoleSave_PipelineCreatesTask(t *testing.T) { + ui, _ := newTestUIWithPreview(t) + + form := url.Values{} + form.Set("dirty_device_ids", "dev1") + form.Set("device_dev1_feature", "face") + form.Set("device_dev1_source", "cam1") + + router, _ := ui.Routes() + req := httptest.NewRequest(http.MethodPost, "/console", strings.NewReader(form.Encode())) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + // Should redirect to task page + if rr.Code != http.StatusFound { + t.Fatalf("expected 302, got %d body=%s", rr.Code, rr.Body.String()) + } + loc := rr.Header().Get("Location") + if !strings.Contains(loc, "task=") { + t.Errorf("expected task in redirect, got %s", loc) + } +}