Skip to content
quarry Artifact [7c520eafd6]
Login

Artifact [7c520eafd6]

Artifact 7c520eafd6bb5df1689491457d6a4de723659aad7aad822938e9842ef29cca4f:


package api

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"

	"craftdesign.group/quarry/internal/ops"
)

// A coded refusal reaches a JSON client as a 400 whose body carries the
// code and fields beside the sentence, so a client can act on it
// without parsing prose.
func TestACodedRefusalCarriesItsCodeAndFieldsInTheBody(t *testing.T) {
	err := fmt.Errorf("accepting: %w", &ops.Refusal{
		Code: RefusalBranchMoved, Message: "moved",
		Fields: map[string]string{"expected": "aaa", "current": "bbb"}})
	w := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/api/v1/r/x/landing/y/accept", nil)
	writeOpError(w, req, "landing.accept", err)
	if w.Code != http.StatusBadRequest {
		t.Fatalf("FAIL: status %d, want 400", w.Code)
	}
	var body map[string]string
	if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
		t.Fatal(err)
	}
	for k, want := range map[string]string{"code": "branch_moved", "expected": "aaa", "current": "bbb"} {
		if body[k] != want {
			t.Errorf("FAIL: body[%q] = %q, want %q (body %v)", k, body[k], want, body)
		}
	}
	if body["error"] == "" {
		t.Errorf("FAIL: body has no error sentence: %v", body)
	}
}

// A plain refusal keeps the one-key body every client already reads.
func TestAnUncodedRefusalKeepsTheOneKeyBody(t *testing.T) {
	w := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	writeOpError(w, req, "x", fmt.Errorf("no: %w", ops.ErrInvalid))
	var body map[string]string
	if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil {
		t.Fatal(err)
	}
	if len(body) != 1 || body["error"] == "" {
		t.Fatalf("FAIL: body %v; want only error", body)
	}
}