package clientcmd import ( "bytes" "context" "net/http" "strings" "testing" "inbox/internal/client" ) type stubClient struct { response client.Response err error method string path string headers http.Header body []byte } func (s *stubClient) Do(_ context.Context, method, path string, headers http.Header, body []byte) (client.Response, error) { s.method = method s.path = path s.headers = headers.Clone() s.body = append([]byte(nil), body...) return s.response, s.err } func TestRunAPIWritesResponseBody(t *testing.T) { var stdout bytes.Buffer stub := &stubClient{ response: client.Response{ StatusCode: http.StatusOK, Body: []byte("{\"ok\":true}\n"), }, } err := RunAPI([]string{"POST", "/api/v2/topics", "--data", `{"title":"Alpha"}`}, APIDeps{ Stdout: &stdout, NewClient: func(string, *http.Client) APIClient { return stub }, }) if err != nil { t.Fatalf("RunAPI() error = %v", err) } if stub.method != http.MethodPost || stub.path != "/api/v2/topics" { t.Fatalf("unexpected request: method=%s path=%s", stub.method, stub.path) } if got := strings.TrimSpace(stdout.String()); got != `{"ok":true}` { t.Fatalf("stdout = %q", got) } if got := string(stub.body); got != `{"title":"Alpha"}` { t.Fatalf("body = %q", got) } if got := stub.headers.Get("Content-Type"); got != "application/json" { t.Fatalf("content type = %q", got) } } func TestRunAPIReadsBodyFromStdin(t *testing.T) { var stdout bytes.Buffer stub := &stubClient{ response: client.Response{ StatusCode: http.StatusCreated, Body: []byte("{}"), }, } err := RunAPI([]string{"PATCH", "/api/v2/requirements/req_1", "--file", "-"}, APIDeps{ Stdout: &stdout, Stdin: strings.NewReader(`{"status":"completed"}`), NewClient: func(string, *http.Client) APIClient { return stub }, }) if err != nil { t.Fatalf("RunAPI() error = %v", err) } if got := string(stub.body); got != `{"status":"completed"}` { t.Fatalf("stdin body = %q", got) } } func TestRunAPIReturnsStatusError(t *testing.T) { stub := &stubClient{ response: client.Response{ StatusCode: http.StatusBadRequest, Body: []byte(`{"error":"bad request"}`), }, } err := RunAPI([]string{"GET", "/api/v2/topics"}, APIDeps{ NewClient: func(string, *http.Client) APIClient { return stub }, }) if err == nil || !strings.Contains(err.Error(), `status 400`) { t.Fatalf("RunAPI() error = %v", err) } } func TestRunAPIRejectsMissingArguments(t *testing.T) { err := RunAPI([]string{"GET"}, APIDeps{}) if err == nil || !strings.Contains(err.Error(), "usage: inbox api") { t.Fatalf("RunAPI() error = %v", err) } }