test(office): replace fixture tests with live OnlyOffice API integration

Remove synthetic map-based entity and fetch mapper unit tests; cover all
menu subjects and preview pipelines via integration tests against the real
Workspace API. Handle draft mail without subjects in list mapping.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-24 16:37:46 +01:00
co-authored by Cursor
parent 6d4df4edee
commit 4046f4c46a
7 changed files with 307 additions and 137 deletions
+110 -16
View File
@@ -12,34 +12,128 @@ import (
"github.com/eslider/go-onlyoffice/cmd/office/model"
)
func TestIntegrationListProjects(t *testing.T) {
func skipWithoutLiveAPI(t *testing.T) {
t.Helper()
if os.Getenv("ONLYOFFICE_URL") == "" && os.Getenv("ONLYOFFICE_HOST") == "" {
t.Skip("ONLYOFFICE_URL not set")
}
client, err := bootstrap.NewClient(context.Background())
if err != nil {
t.Fatal(err)
if os.Getenv("ONLYOFFICE_USER") == "" && os.Getenv("ONLYOFFICE_NAME") == "" {
t.Skip("ONLYOFFICE_USER not set")
}
loader := &fetch.Loader{Client: client}
items, err := loader.List(context.Background(), model.SubjectProjects)
if err != nil {
t.Fatal(err)
if os.Getenv("ONLYOFFICE_PASS") == "" && os.Getenv("ONLYOFFICE_PASSWORD") == "" {
t.Skip("ONLYOFFICE_PASS not set")
}
t.Logf("projects: %d", len(items))
}
func TestIntegrationListMailInbox(t *testing.T) {
if os.Getenv("ONLYOFFICE_URL") == "" && os.Getenv("ONLYOFFICE_HOST") == "" {
t.Skip("ONLYOFFICE_URL not set")
}
func liveLoader(t *testing.T) (*fetch.Loader, context.Context) {
t.Helper()
skipWithoutLiveAPI(t)
client, err := bootstrap.NewClient(context.Background())
if err != nil {
t.Fatal(err)
}
loader := &fetch.Loader{Client: client}
items, err := loader.List(context.Background(), model.SubjectMailInbox)
return &fetch.Loader{Client: client}, context.Background()
}
func TestIntegrationListAllSubjects(t *testing.T) {
loader, ctx := liveLoader(t)
cases := []struct {
subject model.Subject
skip string
}{
{model.SubjectProjects, ""},
{model.SubjectTasks, ""},
{model.SubjectCalendars, ""},
{model.SubjectEvents, ""},
{model.SubjectContacts, ""},
{model.SubjectPersons, ""},
{model.SubjectCompanies, ""},
{model.SubjectOpportunities, ""},
{model.SubjectCases, ""},
{model.SubjectCRMTasks, ""},
{model.SubjectMailInbox, ""},
{model.SubjectMailSent, ""},
{model.SubjectMailDrafts, ""},
{model.SubjectMailTrash, ""},
{model.SubjectMailSpam, ""},
{model.SubjectUsers, ""},
{model.SubjectProjectFiles, "ONLYOFFICE_PROJECT_ID not set"},
}
for _, tc := range cases {
t.Run(string(tc.subject), func(t *testing.T) {
if tc.subject == model.SubjectProjectFiles {
if os.Getenv("ONLYOFFICE_PROJECT_ID") == "" {
t.Skip(tc.skip)
}
}
items, err := loader.List(ctx, tc.subject)
if err != nil {
t.Fatalf("List(%s): %v", tc.subject, err)
}
t.Logf("%s: %d items", tc.subject, len(items))
for i, it := range items {
if it.ID == "" {
t.Errorf("item[%d] missing ID: %+v", i, it)
}
if it.Title == "" {
t.Errorf("item[%d] missing Title: id=%s kind=%s", i, it.ID, it.Kind)
}
if it.Kind == "" {
t.Errorf("item[%d] missing Kind: id=%s", i, it.ID)
}
}
})
}
}
func TestIntegrationListProjectsMapsRealFields(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectProjects)
if err != nil {
t.Fatal(err)
}
t.Logf("mail messages: %d", len(items))
if len(items) == 0 {
t.Skip("no projects on instance")
}
it := items[0]
if it.Raw == nil {
t.Fatal("expected Raw payload from API")
}
detail, err := loader.Detail(ctx, it)
if err != nil {
t.Fatalf("Detail: %v", err)
}
if detail == nil {
t.Fatal("nil detail")
}
t.Logf("project id=%s title=%q keys=%d", it.ID, it.Title, len(detail))
}
func TestIntegrationMailInboxDetail(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectMailInbox)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("inbox empty")
}
detail, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatalf("GetMailMessage: %v", err)
}
if detail["subject"] == nil {
t.Fatalf("message missing subject: %+v", detail)
}
}
func TestIntegrationEventsDateRange(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectEvents)
if err != nil {
t.Fatal(err)
}
t.Logf("events in next 7 days: %d", len(items))
}
+3
View File
@@ -36,6 +36,9 @@ func ItemsFromMaps(rows []map[string]any, kind model.Kind, fields FieldMap) []mo
if title == "" {
title = str(row, "name")
}
if title == "" {
title = "(untitled)"
}
raw := row
out[i] = model.Item{
ID: idStr(row, fields.IDKey),
-28
View File
@@ -1,28 +0,0 @@
package fetch_test
import (
"testing"
"github.com/eslider/go-onlyoffice/cmd/office/fetch"
"github.com/eslider/go-onlyoffice/cmd/office/model"
)
func TestItemsFromMaps(t *testing.T) {
rows := []map[string]any{
{"id": float64(1), "title": "Alpha", "status": "Open"},
{"id": float64(2), "title": "Beta", "status": "Closed"},
}
items := fetch.ItemsFromMaps(rows, model.KindTask, fetch.TaskItemFields)
if len(items) != 2 {
t.Fatalf("len=%d", len(items))
}
if items[0].ID != "1" || items[0].Title != "Alpha" {
t.Fatalf("item0=%+v", items[0])
}
if items[0].Kind != model.KindTask {
t.Fatalf("kind=%v", items[0].Kind)
}
if items[1].Subtitle != "Closed" {
t.Fatalf("subtitle=%q", items[1].Subtitle)
}
}