package server import ( "net/http" "net/http/httptest" "net/url" "regexp" "strings" "testing" ) var csrfRe = regexp.MustCompile(`name="csrf" value="([^"]+)"`) func login(t *testing.T, srv *Server, user, pass string) *httptest.ResponseRecorder { t.Helper() r := httptest.NewRequest(http.MethodPost, "/login", strings.NewReader(url.Values{"username": {user}, "password": {pass}}.Encode())) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, r) if w.Code != http.StatusFound && w.Code != http.StatusOK { t.Fatalf("登录 %s 返回 %d", user, w.Code) } return w } func csrfOf(t *testing.T, srv *Server, path, cookie string) string { t.Helper() r := httptest.NewRequest(http.MethodGet, path, nil) r.AddCookie(&http.Cookie{Name: SessionCookieName, Value: cookie}) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, r) m := csrfRe.FindStringSubmatch(w.Body.String()) if m == nil { t.Fatalf("页面 %s 里找不到 csrf", path) } return m[1] } func sessionCookie(t *testing.T, w *httptest.ResponseRecorder) string { t.Helper() for _, c := range w.Result().Cookies() { if c.Name == SessionCookieName { return c.Value } } t.Fatal("登录响应里没有会话 Cookie") return "" } // TestRepoSettingsRenameIsAtomic 回归:改名成功后,同一请求里的后续校验 // 曾因继续使用已失效的旧目录而返回 400,把成功的改名报成失败。 func TestRepoSettingsRenameIsAtomic(t *testing.T) { srv, st, _, _ := newTestServer(t) dir := makeRepo(t, srv, st, "before", nil) commitFiles(t, dir, "init", map[string]string{"a.txt": "x"}) sess := sessionCookie(t, login(t, srv, "alice", testPass)) csrf := csrfOf(t, srv, "/before/settings", sess) form := url.Values{ "csrf": {csrf}, "new_name": {"after"}, "description": {"改过的描述"}, "default_branch": {"main"}, "ai_enabled": {"on"}, } r := httptest.NewRequest(http.MethodPost, "/before/settings", strings.NewReader(form.Encode())) r.Header.Set("Content-Type", "application/x-www-form-urlencoded") r.AddCookie(&http.Cookie{Name: SessionCookieName, Value: sess}) w := httptest.NewRecorder() srv.Handler().ServeHTTP(w, r) if w.Code >= 400 { t.Errorf("改名 + 保存设置返回 %d,应为 3xx(改名已生效,不该报错)", w.Code) } got, err := st.RepoByName("after") if err != nil { t.Fatalf("改名未生效: %v", err) } if got.Description != "改过的描述" { t.Errorf("同一次提交里的描述没有保存: %q", got.Description) } if got.DefaultBranch != "main" { t.Errorf("默认分支未保存: %q", got.DefaultBranch) } }