@@ -0,0 +1,89 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGardenCanUsesEffectivePermissions(t *testing.T) {
|
||||
custom := Garden{Role: "garden:custom", Permissions: []string{"plants:create"}}
|
||||
if !custom.Can("plants:create") || custom.Can("garden:update") {
|
||||
t.Fatalf("custom role did not use effective permissions: %+v", custom)
|
||||
}
|
||||
|
||||
deniedOverride := Garden{Role: "owner", Permissions: []string{"garden:read"}}
|
||||
if deniedOverride.Can("garden:update") {
|
||||
t.Fatal("explicit permissions must override the built-in role fallback")
|
||||
}
|
||||
|
||||
legacyOwner := Garden{Role: "owner"}
|
||||
if !legacyOwner.Can("garden:update") {
|
||||
t.Fatal("legacy built-in role response should retain compatibility")
|
||||
}
|
||||
if legacyOwner.Can("unknown:permission") {
|
||||
t.Fatal("legacy role fallback must reject unknown permissions")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGardenClientCRUD(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
name := "Neu"
|
||||
description := "Beschreibung"
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
switch {
|
||||
case r.Method == http.MethodPost && r.URL.Path == "/v1/gardens":
|
||||
var input CreateGardenInput
|
||||
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if input.Name != "Hinterhof" {
|
||||
t.Errorf("create name: got %q, want %q", input.Name, "Hinterhof")
|
||||
}
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
_, _ = w.Write([]byte(`{"garden":{"id":12,"name":"Hinterhof","version":1}}`))
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens":
|
||||
_, _ = w.Write([]byte(`{"gardens":[{"id":12,"name":"Hinterhof","version":1}]}`))
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/v1/gardens/12":
|
||||
_, _ = w.Write([]byte(`{"garden":{"id":12,"name":"Hinterhof","version":1}}`))
|
||||
case r.Method == http.MethodPatch && r.URL.Path == "/v1/gardens/12":
|
||||
var input UpdateGardenInput
|
||||
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if input.Name == nil || *input.Name != name || input.Description == nil || *input.Description != description {
|
||||
t.Errorf("update input: got %+v", input)
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"garden":{"id":12,"name":"Neu","description":"Beschreibung","version":2}}`))
|
||||
case r.Method == http.MethodDelete && r.URL.Path == "/v1/gardens/12":
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
apiClient := newTestClient(t, handler)
|
||||
created, response, err := apiClient.CreateGarden(context.Background(), CreateGardenInput{Name: "Hinterhof"})
|
||||
if err != nil || response.StatusCode != http.StatusCreated || created.ID != 12 {
|
||||
t.Fatalf("CreateGarden(): garden=%+v response=%v err=%v", created, response, err)
|
||||
}
|
||||
gardens, _, err := apiClient.Gardens(context.Background())
|
||||
if err != nil || len(gardens) != 1 || gardens[0].ID != 12 {
|
||||
t.Fatalf("Gardens(): gardens=%+v err=%v", gardens, err)
|
||||
}
|
||||
garden, _, err := apiClient.Garden(context.Background(), 12)
|
||||
if err != nil || garden.Name != "Hinterhof" {
|
||||
t.Fatalf("Garden(): garden=%+v err=%v", garden, err)
|
||||
}
|
||||
updated, _, err := apiClient.UpdateGarden(context.Background(), 12, UpdateGardenInput{Name: &name, Description: &description})
|
||||
if err != nil || updated.Version != 2 || updated.Name != name {
|
||||
t.Fatalf("UpdateGarden(): garden=%+v err=%v", updated, err)
|
||||
}
|
||||
response, err = apiClient.DeleteGarden(context.Background(), 12)
|
||||
if err != nil || response.StatusCode != http.StatusNoContent {
|
||||
t.Fatalf("DeleteGarden(): response=%v err=%v", response, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user