frieren / api_test.go
package main
import (
"encoding/json"
"net/http"
"os"
"path/filepath"
"strings"
"testing"
)
func getJSON(t *testing.T, url string, v any) int {
t.Helper()
resp, err := http.Get(url)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if err := json.NewDecoder(resp.Body).Decode(v); err != nil {
t.Fatalf("GET %s: bad json: %v", url, err)
}
return resp.StatusCode
}
func TestJSONAPI(t *testing.T) {
ts, store := newTestServer(t)
if err := store.create("apidemo", "api smoke test"); err != nil {
t.Fatal(err)
}
work := t.TempDir()
mustGit(t, work, "clone", ts.URL+"/apidemo.git", "w")
dir := filepath.Join(work, "w")
os.WriteFile(filepath.Join(dir, "README.md"), []byte("# apidemo\nhello api\n"), 0o644)
os.MkdirAll(filepath.Join(dir, "src"), 0o755)
os.WriteFile(filepath.Join(dir, "src", "main.go"), []byte("package main\n"), 0o644)
mustGit(t, dir, "add", ".")
mustGit(t, dir, "commit", "-m", "seed api test")
mustGit(t, dir, "push", withToken(t, ts.URL+"/apidemo.git"), "master")
var repos []RepoInfo
if code := getJSON(t, ts.URL+"/api/repos", &repos); code != 200 || len(repos) != 1 || repos[0].Name != "apidemo" {
t.Fatalf("repos: code %d, %+v", code, repos)
}
if repos[0].Empty || repos[0].Description != "api smoke test" {
t.Errorf("repo info wrong: %+v", repos[0])
}
var entries []TreeEntry
if code := getJSON(t, ts.URL+"/api/repos/apidemo/tree?path=src", &entries); code != 200 || len(entries) != 1 || entries[0].Name != "main.go" {
t.Fatalf("tree: code %d, %+v", code, entries)
}
var blob blobResponse
if code := getJSON(t, ts.URL+"/api/repos/apidemo/blob?path=src/main.go", &blob); code != 200 || blob.Content != "package main\n" {
t.Fatalf("blob: code %d, %+v", code, blob)
}
var readme readmeResponse
if code := getJSON(t, ts.URL+"/api/repos/apidemo/readme", &readme); code != 200 || !strings.Contains(readme.Content, "hello api") {
t.Fatalf("readme: code %d, %+v", code, readme)
}
var commits []Commit
if code := getJSON(t, ts.URL+"/api/repos/apidemo/commits", &commits); code != 200 || len(commits) != 1 || commits[0].Subject != "seed api test" {
t.Fatalf("commits: code %d, %+v", code, commits)
}
var full commitResponse
if code := getJSON(t, ts.URL+"/api/repos/apidemo/commit/"+commits[0].Hash, &full); code != 200 || !strings.Contains(full.Patch, "package main") {
t.Fatalf("commit: code %d", code)
}
var refs map[string][]Ref
if code := getJSON(t, ts.URL+"/api/repos/apidemo/refs", &refs); code != 200 || len(refs["branches"]) != 1 {
t.Fatalf("refs: code %d, %+v", code, refs)
}
// Errors are JSON with proper codes.
var e map[string]string
if code := getJSON(t, ts.URL+"/api/repos/ghost", &e); code != 404 || e["error"] == "" {
t.Errorf("missing repo: code %d, %+v", code, e)
}
if code := getJSON(t, ts.URL+"/api/repos/apidemo/blob?path=../secret", &e); code != 400 {
t.Errorf("traversal blob: code %d", code)
}
}