package api
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func newTestPage() ContentResponse {
return ContentResponse{
ID: "12345",
Type: "page",
Title: "Test Page",
Version: Version{
Number: 5,
},
Body: Body{
Storage: StorageBody{
Value: "<h1>Hello</h1><p>World</p>",
Representation: "storage",
},
},
}
}
func TestGetContent(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/rest/api/content/12345", r.URL.Path)
assert.Equal(t, "body.storage,version", r.URL.Query().Get("expand"))
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(page)
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
result, err := client.GetContent("12345")
require.NoError(t, err)
assert.Equal(t, "12345", result.ID)
assert.Equal(t, "Test Page", result.Title)
assert.Equal(t, 5, result.Version.Number)
assert.Equal(t, "<h1>Hello</h1><p>World</p>", result.Body.Storage.Value)
}
func TestFindContent(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/rest/api/content", r.URL.Path)
assert.Equal(t, "TEAM", r.URL.Query().Get("spaceKey"))
assert.Equal(t, "Test Page", r.URL.Query().Get("title"))
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(searchResults{
Results: []ContentResponse{page},
Size: 1,
})
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
result, err := client.FindContent("TEAM", "Test Page")
require.NoError(t, err)
assert.Equal(t, "12345", result.ID)
}
func TestFindContent_NotFound(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(searchResults{Results: nil, Size: 0})
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
_, err := client.FindContent("TEAM", "Nonexistent")
require.Error(t, err)
assert.Contains(t, err.Error(), "not found")
}
func TestUpdateContent(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPut, r.Method)
assert.Equal(t, "/rest/api/content/12345", r.URL.Path)
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
var req updateRequest
err := json.NewDecoder(r.Body).Decode(&req)
require.NoError(t, err)
assert.Equal(t, 6, req.Version.Number, "version should be incremented")
assert.Equal(t, "Test Page", req.Title)
assert.Equal(t, "page", req.Type)
assert.Equal(t, "<h1>Updated</h1>", req.Body.Storage.Value)
assert.Equal(t, "storage", req.Body.Storage.Representation)
assert.Equal(t, "Updated via mdcx", req.Version.Message)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(page)
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
err := client.UpdateContent("12345", &page, "<h1>Updated</h1>", "Updated via mdcx")
require.NoError(t, err)
}
func TestGetContent_Unauthorized(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
}))
defer server.Close()
client := NewClient(server.URL, "bad-token")
_, err := client.GetContent("12345")
require.Error(t, err)
assert.Contains(t, err.Error(), "authentication failed")
}
func TestGetContent_NotFound(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
_, err := client.GetContent("99999")
require.Error(t, err)
assert.Contains(t, err.Error(), "not found")
}
func TestUpdateContent_VersionConflict(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusConflict)
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
err := client.UpdateContent("12345", &page, "<h1>Updated</h1>", "")
require.Error(t, err)
assert.Contains(t, err.Error(), "version conflict")
}
func TestGetPage_ByID(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/rest/api/content/12345", r.URL.Path)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(page)
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
ref := &PageRef{BaseURL: server.URL, PageID: "12345"}
result, err := client.GetPage(ref)
require.NoError(t, err)
assert.Equal(t, "Test Page", result.Title)
}
func TestGetPage_BySpaceAndTitle(t *testing.T) {
page := newTestPage()
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "/rest/api/content", r.URL.Path)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(searchResults{
Results: []ContentResponse{page},
Size: 1,
})
}))
defer server.Close()
client := NewClient(server.URL, "test-token")
ref := &PageRef{BaseURL: server.URL, SpaceKey: "TEAM", Title: "Test Page"}
result, err := client.GetPage(ref)
require.NoError(t, err)
assert.Equal(t, "Test Page", result.Title)
}