package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "testing" "gcy_hpc_server/internal/testutil/testenv" ) // folderData mirrors the FolderResponse DTO returned by the API. type folderData struct { ID int64 `json:"id"` Name string `json:"name"` ParentID *int64 `json:"parent_id,omitempty"` Path string `json:"path"` FileCount int64 `json:"file_count"` SubFolderCount int64 `json:"subfolder_count"` } // folderMessageData mirrors the delete endpoint response data structure. type folderMessageData struct { Message string `json:"message"` } // folderDoRequest marshals body and calls env.DoRequest. func folderDoRequest(env *testenv.TestEnv, method, path string, body interface{}) *http.Response { var r io.Reader if body != nil { b, err := json.Marshal(body) if err != nil { panic(fmt.Sprintf("folderDoRequest marshal: %v", err)) } r = bytes.NewReader(b) } return env.DoRequest(method, path, r) } // folderDecodeAll decodes the response and returns status, success, and raw data. func folderDecodeAll(env *testenv.TestEnv, resp *http.Response) (statusCode int, success bool, data json.RawMessage, err error) { statusCode = resp.StatusCode success, data, err = env.DecodeResponse(resp) return } // folderSeed creates a folder via HTTP and returns its ID. func folderSeed(env *testenv.TestEnv, name string) int64 { body := map[string]interface{}{"name": name} resp := folderDoRequest(env, http.MethodPost, "/api/v1/files/folders", body) status, success, data, err := folderDecodeAll(env, resp) if err != nil { panic(fmt.Sprintf("folderSeed decode: %v", err)) } if status != http.StatusCreated { panic(fmt.Sprintf("folderSeed: expected 201, got %d", status)) } if !success { panic("folderSeed: expected success=true") } var f folderData if err := json.Unmarshal(data, &f); err != nil { panic(fmt.Sprintf("folderSeed unmarshal: %v", err)) } return f.ID } // TestIntegration_Folder_Create verifies POST /api/v1/files/folders creates a folder. func TestIntegration_Folder_Create(t *testing.T) { env := testenv.NewTestEnv(t) body := map[string]interface{}{"name": "test-folder-create"} resp := folderDoRequest(env, http.MethodPost, "/api/v1/files/folders", body) status, success, data, err := folderDecodeAll(env, resp) if err != nil { t.Fatalf("decode response: %v", err) } if status != http.StatusCreated { t.Fatalf("expected status 201, got %d", status) } if !success { t.Fatal("expected success=true") } var created folderData if err := json.Unmarshal(data, &created); err != nil { t.Fatalf("unmarshal created data: %v", err) } if created.ID <= 0 { t.Fatalf("expected positive id, got %d", created.ID) } if created.Name != "test-folder-create" { t.Fatalf("expected name=test-folder-create, got %s", created.Name) } } // TestIntegration_Folder_List verifies GET /api/v1/files/folders returns a list. func TestIntegration_Folder_List(t *testing.T) { env := testenv.NewTestEnv(t) // Seed two folders. folderSeed(env, "list-folder-1") folderSeed(env, "list-folder-2") resp := env.DoRequest(http.MethodGet, "/api/v1/files/folders", nil) status, success, data, err := folderDecodeAll(env, resp) if err != nil { t.Fatalf("decode response: %v", err) } if status != http.StatusOK { t.Fatalf("expected status 200, got %d", status) } if !success { t.Fatal("expected success=true") } var folders []folderData if err := json.Unmarshal(data, &folders); err != nil { t.Fatalf("unmarshal list data: %v", err) } if len(folders) < 2 { t.Fatalf("expected at least 2 folders, got %d", len(folders)) } } // TestIntegration_Folder_Get verifies GET /api/v1/files/folders/:id returns folder details. func TestIntegration_Folder_Get(t *testing.T) { env := testenv.NewTestEnv(t) id := folderSeed(env, "test-folder-get") path := fmt.Sprintf("/api/v1/files/folders/%d", id) resp := env.DoRequest(http.MethodGet, path, nil) status, success, data, err := folderDecodeAll(env, resp) if err != nil { t.Fatalf("decode response: %v", err) } if status != http.StatusOK { t.Fatalf("expected status 200, got %d", status) } if !success { t.Fatal("expected success=true") } var f folderData if err := json.Unmarshal(data, &f); err != nil { t.Fatalf("unmarshal folder data: %v", err) } if f.ID != id { t.Fatalf("expected id=%d, got %d", id, f.ID) } if f.Name != "test-folder-get" { t.Fatalf("expected name=test-folder-get, got %s", f.Name) } } // TestIntegration_Folder_Delete verifies DELETE /api/v1/files/folders/:id removes a folder. func TestIntegration_Folder_Delete(t *testing.T) { env := testenv.NewTestEnv(t) id := folderSeed(env, "test-folder-delete") path := fmt.Sprintf("/api/v1/files/folders/%d", id) resp := env.DoRequest(http.MethodDelete, path, nil) status, success, data, err := folderDecodeAll(env, resp) if err != nil { t.Fatalf("decode response: %v", err) } if status != http.StatusOK { t.Fatalf("expected status 200, got %d", status) } if !success { t.Fatal("expected success=true") } var msg folderMessageData if err := json.Unmarshal(data, &msg); err != nil { t.Fatalf("unmarshal message data: %v", err) } if msg.Message != "folder deleted" { t.Fatalf("expected message 'folder deleted', got %q", msg.Message) } // Verify it's gone via GET → 404. getResp := env.DoRequest(http.MethodGet, path, nil) getStatus, getSuccess, _, _ := folderDecodeAll(env, getResp) if getStatus != http.StatusNotFound { t.Fatalf("expected status 404 after delete, got %d", getStatus) } if getSuccess { t.Fatal("expected success=false after delete") } }