package main import ( "encoding/json" "io" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" ) const cliEntry = `--- id: hall-worker-cli type: worker-entry display_name: CLI status: draft --- # A title ## What I would want remembered Remember this line. ` func TestCLIDraftApprovePublish(t *testing.T) { dir := t.TempDir() entry := filepath.Join(dir, "entry.md") if err := os.WriteFile(entry, []byte(cliEntry), 0o644); err != nil { t.Fatal(err) } queue := filepath.Join(dir, "queue") if err := run([]string{"draft", "--entry", entry, "--queue", queue, "--base-url", "https://example.test"}); err != nil { t.Fatal(err) } id := onlyPostID(t, queue) raw, err := os.ReadFile(filepath.Join(queue, id+".json")) if err != nil { t.Fatal(err) } if strings.Contains(string(raw), "reviewed_by") || strings.Contains(string(raw), "subject_consent") { t.Fatalf("draft file has review fields: %s", raw) } err = run([]string{"approve", "--queue", queue, "--post", id, "--reviewer", "Ada"}) if err == nil { t.Fatal("approve without --consent succeeded") } var body map[string]any srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if err := json.NewDecoder(r.Body).Decode(&body); err != nil { t.Errorf("decode: %v", err) } w.WriteHeader(http.StatusCreated) _, _ = io.WriteString(w, `{"state":"published"}`) })) defer srv.Close() if _, err := os.Stat(filepath.Join(queue, id+".json")); err != nil { t.Fatal(err) } if err := run([]string{"publish", "--queue", queue, "--post", id, "--adapter", srv.URL}); err == nil { t.Fatal("publish before approval succeeded") } if body != nil { t.Fatalf("publish before approval sent a body: %#v", body) } if err := run([]string{"approve", "--queue", queue, "--post", id, "--reviewer", "Ada", "--consent", "explicit"}); err != nil { t.Fatal(err) } if err := run([]string{"publish", "--queue", queue, "--post", id, "--adapter", srv.URL}); err != nil { t.Fatal(err) } if body["post_id"] != id || body["reviewed_by"] != "Ada" || body["subject_consent"] != "explicit" || body["variant"] != "quoted-remembrance-v1" { t.Fatalf("POST body = %#v", body) } if body["source_entry_url"] != "https://example.test/hall-of-helix/hall-worker-cli" { t.Fatalf("source url = %#v", body["source_entry_url"]) } if !strings.Contains(body["body"].(string), "Remember this line.") { t.Fatalf("body = %#v", body["body"]) } } func onlyPostID(t *testing.T, dir string) string { t.Helper() ents, err := os.ReadDir(dir) if err != nil { t.Fatal(err) } var id string for _, e := range ents { if !strings.HasSuffix(e.Name(), ".json") { continue } raw, err := os.ReadFile(filepath.Join(dir, e.Name())) if err != nil { t.Fatal(err) } var d struct { PostID string `json:"post_id"` } if err := json.Unmarshal(raw, &d); err != nil { t.Fatal(err) } if id != "" { t.Fatal("queue has more than one draft") } id = d.PostID } if id == "" { t.Fatal("queue is empty") } return id }