Files
go-nc-exapp/preferences_test.go
T
Konrad NeitzelandCursor 7921694782 Extract AppAPI auth and OCS preferences from CheckDNS.
Publish gonexapp v1 with Credentials, OCSClient, and parameterized
AppAPIPreferences so ExApps share Nextcloud ExApp plumbing per ADR 0013.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 19:14:22 +02:00

127 lines
3.7 KiB
Go

package gonexapp_test
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"gitea.neitzel.de/konrad/go-nc-exapp"
)
func TestOCSCallIncludesFormatJSON(t *testing.T) {
var gotPath string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotPath = r.URL.String()
_ = json.NewEncoder(w).Encode(map[string]string{"ok": "true"})
}))
t.Cleanup(srv.Close)
cred := gonexapp.Credentials{
BaseURL: srv.URL, AppID: "app", AppVersion: "0.1.0", AAVersion: "1.0.0", AppSecret: "s", UserID: "alice",
}
client := gonexapp.OCSClient{Cred: cred, Client: srv.Client()}
raw, err := client.Call(http.MethodGet, "apps/app_api/api/v1/ex-app/preference/get-values", nil)
if err != nil {
t.Fatal(err)
}
if !json.Valid(raw) {
t.Fatalf("not json: %s", raw)
}
if !strings.Contains(gotPath, "format=json") {
t.Fatalf("path missing format=json: %s", gotPath)
}
}
func TestOCSCallRejectsNonJSON(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = io.WriteString(w, "<xml/>")
}))
t.Cleanup(srv.Close)
cred := gonexapp.Credentials{BaseURL: srv.URL, AppID: "app", AppVersion: "0.1.0", AAVersion: "1.0.0", AppSecret: "s", UserID: "alice"}
client := gonexapp.OCSClient{Cred: cred, Client: srv.Client()}
_, err := client.Call(http.MethodGet, "apps/example", nil)
if err == nil || !strings.Contains(err.Error(), "not JSON") {
t.Fatalf("got %v", err)
}
}
func TestOCSCallSurfacesHTTPError(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "nope", http.StatusBadRequest)
}))
t.Cleanup(srv.Close)
cred := gonexapp.Credentials{BaseURL: srv.URL, AppID: "app", AppVersion: "0.1.0", AAVersion: "1.0.0", AppSecret: "s", UserID: "alice"}
client := gonexapp.OCSClient{Cred: cred, Client: srv.Client()}
_, err := client.Call(http.MethodPost, "apps/example", []byte(`{}`))
if err == nil || !strings.Contains(err.Error(), "400") {
t.Fatalf("got %v", err)
}
}
func TestAppAPIPreferencesGetSet(t *testing.T) {
const prefKey = "savedDefault"
prefsVals := map[string]string{}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case strings.Contains(r.URL.Path, "ex-app/preference/get-values"):
_ = json.NewEncoder(w).Encode(map[string]any{
"ocs": map[string]any{
"data": []map[string]string{{
"configkey": prefKey,
"configvalue": prefsVals[prefKey],
}},
},
})
case strings.HasSuffix(r.URL.Path, "ex-app/preference") && r.Method == http.MethodPost:
var body struct {
ConfigKey string `json:"configKey"`
ConfigValue string `json:"configValue"`
}
_ = json.NewDecoder(r.Body).Decode(&body)
prefsVals[body.ConfigKey] = body.ConfigValue
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
default:
http.Error(w, "unhandled "+r.Method+" "+r.URL.Path, http.StatusInternalServerError)
}
}))
t.Cleanup(srv.Close)
cred := gonexapp.Credentials{
BaseURL: srv.URL, AppID: "myexapp", AppVersion: "0.1.0", AAVersion: "1.0.0", AppSecret: "s", UserID: "alice",
}
store := gonexapp.NewAppAPIPreferences(cred, "myexapp", prefKey)
store.Client = srv.Client()
store.OCS.Client = srv.Client()
got, err := store.Get()
if err != nil {
t.Fatal(err)
}
if got != "" {
t.Fatalf("initial value=%q", got)
}
if err := store.Set("Zones"); err != nil {
t.Fatal(err)
}
if prefsVals[prefKey] != "Zones" {
t.Fatalf("prefs not written: %#v", prefsVals)
}
got, err = store.Get()
if err != nil {
t.Fatal(err)
}
if got != "Zones" {
t.Fatalf("got %q", got)
}
}