Files
go-onlyoffice/files_integration_test.go
T
eSlider e03fd62200 feat(files): project/task Documents API + oo projects|tasks files
Library (files.go):
- Types: FileEntry, FolderEntry, ProjectFilesResponse.
- GetProjectFiles, GetTaskFiles, GetFile, UploadProjectFile (POST .../upload),
  AttachFilesToTask (POST form files=), UploadTaskFile (upload+attach),
  DetachTaskFile (DELETE ?fileid=), RenameFile, DeleteFiles, DownloadFile.
- Helpers: FileEntryNumericID, FileEntryTitle, SafeLocalFileName, projectIDFromTaskMap.

http.go: putJSON for JSON PUT bodies.

CLI: oo projects files {list,upload,download,rename,delete}, oo tasks files
{list,upload,detach}; projects_files.go + tasks_files.go.

Tests: files_integration_test.go (live), files_test.go + testdata (decode).

Docs: CHANGELOG 0.6.0, README, AGENTS.md, cmd/oo/main.go tree.
Made-with: Cursor
2026-04-24 16:28:39 +01:00

176 lines
4.5 KiB
Go

//go:build integration
package onlyoffice
import (
"bytes"
"context"
"os"
"path/filepath"
"strconv"
"testing"
"time"
)
// TestIntegrationProjectFilesFlow creates a throwaway project, uploads a file
// into its Documents folder, lists, downloads, renames, deletes, then removes
// the project. Destructive — only run against instances you own.
func TestIntegrationProjectFilesFlow(t *testing.T) {
c := liveClient(t)
t.Cleanup(func() { cleanupTestProjects(t, c) })
suffix := time.Now().UTC().Format("20060102-150405")
title := testProjectPrefix + "files-" + suffix
project, err := c.CreateProject(NewProjectRequest{
Title: title,
Description: "go-onlyoffice project files integration",
})
if err != nil {
t.Fatalf("CreateProject: %v", err)
}
if project.ID == nil {
t.Fatal("created project without id")
}
pid := strconv.Itoa(*project.ID)
ctx := context.Background()
tmpDir := t.TempDir()
localPath := filepath.Join(tmpDir, "hello.txt")
content := []byte("integration project file " + suffix + "\n")
if err := os.WriteFile(localPath, content, 0o600); err != nil {
t.Fatal(err)
}
entry, err := c.UploadProjectFile(ctx, pid, localPath)
if err != nil {
t.Fatalf("UploadProjectFile: %v", err)
}
if entry == nil || entry.ID == nil {
t.Fatalf("upload returned no file: %+v", entry)
}
fileID := entry.ID.String()
pf, err := c.GetProjectFiles(ctx, pid)
if err != nil {
t.Fatalf("GetProjectFiles: %v", err)
}
found := false
for _, f := range pf.Files {
if f != nil && f.ID != nil && f.ID.String() == fileID {
found = true
break
}
}
if !found {
t.Logf("uploaded file id=%s not in project files list (may still be ok); folders=%d files=%d",
fileID, len(pf.Folders), len(pf.Files))
}
var buf bytes.Buffer
n, err := c.DownloadFile(ctx, fileID, &buf)
if err != nil {
t.Fatalf("DownloadFile: %v", err)
}
if n != int64(len(content)) || !bytes.Equal(buf.Bytes(), content) {
t.Fatalf("download mismatch: got %d bytes %q want %d bytes", n, buf.String(), len(content))
}
newTitle := "renamed-" + suffix + ".txt"
renamed, err := c.RenameFile(ctx, fileID, newTitle)
if err != nil {
t.Fatalf("RenameFile: %v", err)
}
if renamed == nil || renamed.Title == nil || *renamed.Title != newTitle {
t.Fatalf("rename result: %+v", renamed)
}
nid := int(FileEntryNumericID(entry))
if nid == 0 {
t.Fatal("file id 0 for delete")
}
if err := c.DeleteFiles(ctx, []int{nid}); err != nil {
t.Fatalf("DeleteFiles: %v", err)
}
}
func TestIntegrationTaskFilesFlow(t *testing.T) {
c := liveClient(t)
t.Cleanup(func() { cleanupTestProjects(t, c) })
suffix := time.Now().UTC().Format("20060102-150405")
title := testProjectPrefix + "taskfiles-" + suffix
project, err := c.CreateProject(NewProjectRequest{
Title: title,
Description: "go-onlyoffice task files integration",
})
if err != nil {
t.Fatalf("CreateProject: %v", err)
}
if project.ID == nil {
t.Fatal("created project without id")
}
start := Time(time.Now().AddDate(0, 0, -1))
deadline := Time(time.Now().AddDate(0, 0, 1))
task, err := c.CreateProjectTask(NewProjectTaskRequest{
ProjectId: *project.ID,
Title: "task for file attach " + suffix,
Description: "integration",
StartDate: start,
Deadline: deadline,
Priority: int(TaskPriorityNormal),
})
if err != nil {
t.Fatalf("CreateProjectTask: %v", err)
}
if task.ID == nil {
t.Fatal("task without id")
}
tid := strconv.Itoa(*task.ID)
ctx := context.Background()
tmpDir := t.TempDir()
localPath := filepath.Join(tmpDir, "attach.txt")
content := []byte("task attachment " + suffix + "\n")
if err := os.WriteFile(localPath, content, 0o600); err != nil {
t.Fatal(err)
}
up, err := c.UploadTaskFile(ctx, tid, localPath)
if err != nil {
t.Fatalf("UploadTaskFile: %v", err)
}
if up == nil || up.ID == nil {
t.Fatalf("upload: %+v", up)
}
fileID := up.ID.String()
list, err := c.GetTaskFiles(ctx, tid)
if err != nil {
t.Fatalf("GetTaskFiles: %v", err)
}
found := false
for _, f := range list {
if f != nil && f.ID != nil && f.ID.String() == fileID {
found = true
break
}
}
if !found {
t.Fatalf("uploaded file not in GetTaskFiles: %#v", list)
}
if err := c.DetachTaskFile(ctx, tid, fileID); err != nil {
t.Fatalf("DetachTaskFile: %v", err)
}
list2, err := c.GetTaskFiles(ctx, tid)
if err != nil {
t.Fatalf("GetTaskFiles after detach: %v", err)
}
for _, f := range list2 {
if f != nil && f.ID != nil && f.ID.String() == fileID {
t.Fatalf("file still attached after detach: %v", fileID)
}
}
}