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 5e856ed22b
commit e969624297
7 changed files with 307 additions and 137 deletions
-89
View File
@@ -1,89 +0,0 @@
package preview_test
import (
"strings"
"testing"
"github.com/eslider/go-onlyoffice/cmd/office/preview"
)
func TestContactMarkdownCompany(t *testing.T) {
md := preview.ContactMarkdown(map[string]any{
"displayName": "Acme GmbH",
"isCompany": true,
"about": "Widget supplier",
})
if !strings.Contains(md, "Acme GmbH") {
t.Fatalf("title missing: %q", md)
}
if !strings.Contains(md, "Company") {
t.Fatalf("type label missing: %q", md)
}
if !strings.Contains(md, "Widget supplier") {
t.Fatalf("about missing: %q", md)
}
}
func TestOpportunityMarkdown(t *testing.T) {
md := preview.OpportunityMarkdown(map[string]any{
"title": "Big Deal",
"description": "Annual contract",
"bidValue": float64(50000),
"bidCurrency": "EUR",
})
if !strings.Contains(md, "Big Deal") {
t.Fatalf("title missing: %q", md)
}
if !strings.Contains(md, "50000") || !strings.Contains(md, "EUR") {
t.Fatalf("bid missing: %q", md)
}
}
func TestMailMarkdown(t *testing.T) {
md := preview.MailMarkdown(map[string]any{
"subject": "Hello",
"from": "Alice <alice@example.com>",
"body": "<p>Hi there</p>",
})
if !strings.Contains(md, "Hello") {
t.Fatalf("subject missing: %q", md)
}
if !strings.Contains(md, "alice@example.com") {
t.Fatalf("from missing: %q", md)
}
if strings.Contains(md, "<p>") {
t.Fatalf("html not stripped: %q", md)
}
if !strings.Contains(md, "Hi there") {
t.Fatalf("body text missing: %q", md)
}
}
func TestEventMarkdown(t *testing.T) {
md := preview.EventMarkdown(map[string]any{
"title": "Standup",
"start": "2026-06-24T09:00:00",
"end": "2026-06-24T09:15:00",
})
if !strings.Contains(md, "Standup") {
t.Fatalf("title missing: %q", md)
}
if !strings.Contains(md, "2026-06-24") {
t.Fatalf("dates missing: %q", md)
}
}
func TestTaskMarkdown(t *testing.T) {
md := preview.TaskMarkdown(map[string]any{
"title": "Deploy",
"status": "Open",
"deadline": "2026-07-01",
"description": "Roll out v2",
})
if !strings.Contains(md, "Deploy") {
t.Fatalf("title missing: %q", md)
}
if !strings.Contains(md, "Open") {
t.Fatalf("status missing: %q", md)
}
}
@@ -0,0 +1,189 @@
//go:build integration
package preview_test
import (
"context"
"os"
"strings"
"testing"
"github.com/eslider/go-onlyoffice/cmd/internal/bootstrap"
"github.com/eslider/go-onlyoffice/cmd/office/fetch"
"github.com/eslider/go-onlyoffice/cmd/office/model"
"github.com/eslider/go-onlyoffice/cmd/office/preview"
)
func skipWithoutLiveAPI(t *testing.T) {
t.Helper()
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)
}
return &fetch.Loader{Client: client}, context.Background()
}
func TestIntegrationPreviewProjectFromAPI(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectProjects)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("no projects")
}
raw, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatal(err)
}
md := preview.EntityMarkdown(string(model.KindProject), raw)
if md == "" {
t.Fatal("empty markdown")
}
if !strings.Contains(md, items[0].Title) {
t.Fatalf("markdown missing project title %q:\n%s", items[0].Title, md)
}
rendered, err := preview.RenderMarkdown(md, 80)
if err != nil {
t.Fatal(err)
}
if rendered == "" {
t.Fatal("glamour produced empty output")
}
}
func TestIntegrationPreviewContactFromAPI(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectContacts)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("no contacts")
}
raw, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatal(err)
}
md := preview.ContactMarkdown(raw)
if md == "" || !strings.Contains(md, "#") {
t.Fatalf("unexpected contact markdown: %q", md)
}
}
func TestIntegrationPreviewOpportunityFromAPI(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectOpportunities)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("no opportunities")
}
raw, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatal(err)
}
md := preview.OpportunityMarkdown(raw)
if !strings.Contains(md, items[0].Title) {
t.Fatalf("markdown missing deal title:\n%s", md)
}
}
func TestIntegrationPreviewMailFromAPI(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")
}
raw, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatal(err)
}
md := preview.MailMarkdown(raw)
if !strings.Contains(md, items[0].Title) {
t.Fatalf("markdown missing subject %q:\n%s", items[0].Title, md)
}
}
func TestIntegrationPreviewEventFromAPI(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectEvents)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("no events in range")
}
md := preview.EventMarkdown(items[0].Raw)
if !strings.Contains(md, items[0].Title) {
t.Fatalf("markdown missing event title:\n%s", md)
}
}
func TestIntegrationPreviewTaskFromAPI(t *testing.T) {
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectTasks)
if err != nil {
t.Fatal(err)
}
if len(items) == 0 {
t.Skip("no tasks")
}
raw, err := loader.Detail(ctx, items[0])
if err != nil {
t.Fatal(err)
}
md := preview.TaskMarkdown(raw)
if !strings.Contains(md, items[0].Title) {
t.Fatalf("markdown missing task title:\n%s", md)
}
}
func TestIntegrationPreviewCSVFromDownloadedFile(t *testing.T) {
skipWithoutLiveAPI(t)
if os.Getenv("ONLYOFFICE_PROJECT_ID") == "" {
t.Skip("ONLYOFFICE_PROJECT_ID not set")
}
loader, ctx := liveLoader(t)
items, err := loader.List(ctx, model.SubjectProjectFiles)
if err != nil {
t.Fatal(err)
}
var csvItem *model.Item
for i := range items {
if strings.HasSuffix(strings.ToLower(items[i].Title), ".csv") {
csvItem = &items[i]
break
}
}
if csvItem == nil {
t.Skip("no csv file in project documents")
}
var buf strings.Builder
n, err := loader.Client.DownloadFile(ctx, csvItem.ID, &buf)
if err != nil {
t.Fatalf("DownloadFile: %v", err)
}
if n == 0 {
t.Fatal("empty download")
}
md, err := preview.CSVToMarkdownTable([]byte(buf.String()))
if err != nil {
t.Fatalf("CSVToMarkdownTable: %v", err)
}
if !strings.Contains(md, "|") {
t.Fatalf("expected pipe table: %q", md)
}
}