Release / GoReleaser (push) Skipped
Tests / Secret scan (gitleaks) (push) Skipped
Tests / Test (Go 1.25) (push) Skipped
Tests / Test (Go stable) (push) Skipped
Tests / Secret scan (gitleaks) (pull_request) Successful in 4s
Tests / Test (Go stable) (pull_request) Successful in 1m19s
Tests / Test (Go 1.25) (pull_request) Successful in 1m24s
Keep the public tree project-generic. Business/one-off tools, deployment and business docs move to the private oo-workspace repo. Moved to oo-workspace: - cmd/ooscan, cmd/pdfamount, cmd/kontoblatt, cmd/kontolink - internal/xlspipe (cutover-portugal workbook) -> oow workbook build (drops the --template/--title flags from oo docs put-xlsx) - deploy/docker-compose.rclone-webdav.yml + docs/rclone-webdav.md - docs/crm-associations.md Removed GitHub-era leftovers: - .github/workflows/release-please.yml, release-please-config.json, .release-please-manifest.json (tags are created on Gitea per SemVer) Naming: the FileStore subsystem is now filestore_*.go (was file_*.go) to match files_*.go (project Documents). Docs/AGENTS/README updated.
132 lines
3.9 KiB
Go
132 lines
3.9 KiB
Go
//go:build integration
|
|
|
|
package onlyoffice
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestIntegrationFacadeCRUD drives the whole operation set through the composed
|
|
// facade c.Files(): folder create, upload, stat, list, rename, move, copy,
|
|
// delete. Writes must go to REST (the default writeOrder), reads follow
|
|
// readOrder (REST when no SQL backend is registered) and every returned Entry
|
|
// must report its provider. Destructive — throwaway project, cleaned up.
|
|
func TestIntegrationFacadeCRUD(t *testing.T) {
|
|
c := liveClient(t)
|
|
t.Cleanup(func() { cleanupTestProjects(t, c) })
|
|
ctx := context.Background()
|
|
|
|
suffix := time.Now().UTC().Format("20060102-150405")
|
|
project, err := c.CreateProject(NewProjectRequest{
|
|
Title: testProjectPrefix + "facade-" + suffix,
|
|
Description: "go-onlyoffice facade CRUD integration",
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("CreateProject: %v", err)
|
|
}
|
|
if project.ID == nil {
|
|
t.Fatal("created project without id")
|
|
}
|
|
root, err := c.projectFolderID(ctx, strconv.Itoa(*project.ID))
|
|
if err != nil {
|
|
t.Fatalf("projectFolderID: %v", err)
|
|
}
|
|
|
|
f := c.Files()
|
|
if got := f.Write().Name(); got != ProviderREST {
|
|
t.Fatalf("Write().Name() = %q, want %q", got, ProviderREST)
|
|
}
|
|
if got := f.Read().Name(); got != ProviderREST {
|
|
t.Fatalf("Read().Name() = %q, want %q (no SQL backend registered)", got, ProviderREST)
|
|
}
|
|
|
|
src, err := f.CreateFolder(ctx, root, "facade-src-"+suffix)
|
|
if err != nil {
|
|
t.Fatalf("CreateFolder src: %v", err)
|
|
}
|
|
if src.Kind != Folder || src.ID == "" {
|
|
t.Fatalf("created src folder: %+v", src)
|
|
}
|
|
if src.Provider != ProviderREST {
|
|
t.Fatalf("CreateFolder provider = %q, want %q", src.Provider, ProviderREST)
|
|
}
|
|
dst, err := f.CreateFolder(ctx, root, "facade-dst-"+suffix)
|
|
if err != nil {
|
|
t.Fatalf("CreateFolder dst: %v", err)
|
|
}
|
|
if dst.Provider != ProviderREST {
|
|
t.Fatalf("CreateFolder dst provider = %q, want %q", dst.Provider, ProviderREST)
|
|
}
|
|
t.Cleanup(func() {
|
|
if err := c.DeleteDavItems(ctx, []string{src.ID, dst.ID}, nil); err != nil {
|
|
t.Logf("cleanup folders: %v", err)
|
|
}
|
|
})
|
|
|
|
content := []byte("facade crud " + suffix + "\n")
|
|
up, err := f.Upload(ctx, src.ID, "facade-doc-"+suffix+".txt", bytes.NewReader(content))
|
|
if err != nil {
|
|
t.Fatalf("Upload: %v", err)
|
|
}
|
|
if up.Kind != File || up.ID == "" {
|
|
t.Fatalf("uploaded entry: %+v", up)
|
|
}
|
|
if up.Provider != ProviderREST {
|
|
t.Fatalf("Upload provider = %q, want %q (write order REST first)", up.Provider, ProviderREST)
|
|
}
|
|
if !waitEntry(ctx, f, src.ID, up.ID, 15*time.Second) {
|
|
t.Fatalf("uploaded %s not listed in src", up.ID)
|
|
}
|
|
|
|
st, err := f.Stat(ctx, up.ID)
|
|
if err != nil {
|
|
t.Fatalf("Stat: %v", err)
|
|
}
|
|
if st.ID != up.ID || st.Kind != File {
|
|
t.Fatalf("Stat = %+v", st)
|
|
}
|
|
if st.Provider != ProviderREST {
|
|
t.Fatalf("Stat provider = %q, want %q (read order REST)", st.Provider, ProviderREST)
|
|
}
|
|
|
|
list, err := f.List(ctx, src.ID)
|
|
if err != nil {
|
|
t.Fatalf("List: %v", err)
|
|
}
|
|
if e := entryByID(list, up.ID); e == nil {
|
|
t.Fatalf("uploaded %s not in List(src)", up.ID)
|
|
} else if e.Provider != ProviderREST {
|
|
t.Fatalf("List provider = %q, want %q", e.Provider, ProviderREST)
|
|
}
|
|
|
|
renamed := "facade-renamed-" + suffix + ".txt"
|
|
renameEventually(t, ctx, f, up.ID, renamed)
|
|
|
|
moveEventually(t, ctx, f, up.ID, dst.ID)
|
|
if !waitEntry(ctx, f, dst.ID, up.ID, 20*time.Second) {
|
|
t.Fatalf("moved file %s not in dst", up.ID)
|
|
}
|
|
|
|
copied := copyEventually(t, ctx, f, up.ID, src.ID, 20*time.Second)
|
|
if copied == nil {
|
|
t.Fatalf("no copy found in src after Copy")
|
|
}
|
|
if copied.Provider != ProviderREST {
|
|
t.Fatalf("Copy provider = %q, want %q", copied.Provider, ProviderREST)
|
|
}
|
|
|
|
if err := f.Delete(ctx, []string{up.ID, copied.ID}); err != nil {
|
|
t.Fatalf("Delete: %v", err)
|
|
}
|
|
if !waitNoEntry(ctx, f, dst.ID, up.ID, 20*time.Second) {
|
|
t.Fatalf("file %s still present in dst after delete", up.ID)
|
|
}
|
|
if !waitNoEntry(ctx, f, src.ID, copied.ID, 20*time.Second) {
|
|
t.Fatalf("copy %s still present in src after delete", copied.ID)
|
|
}
|
|
}
|