Files
QSfera/Server/services/collaboration/pkg/connector/httpadapter_test.go
T
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

669 lines
22 KiB
Go

package connector_test
import (
"context"
"encoding/json"
"errors"
"io"
"net/http/httptest"
"strings"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/go-chi/chi/v5"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/qsfera/server/services/collaboration/mocks"
"github.com/qsfera/server/services/collaboration/pkg/connector"
"github.com/qsfera/server/services/collaboration/pkg/connector/fileinfo"
"github.com/stretchr/testify/mock"
)
var _ = Describe("HttpAdapter", func() {
var (
fc *mocks.FileConnectorService
cc *mocks.ContentConnectorService
con *mocks.ConnectorService
locks *mocks.LockParser
httpAdapter *connector.HttpAdapter
)
BeforeEach(func() {
fc = &mocks.FileConnectorService{}
cc = &mocks.ContentConnectorService{}
con = &mocks.ConnectorService{}
con.On("GetContentConnector").Return(cc)
con.On("GetFileConnector").Return(fc)
locks = &mocks.LockParser{}
locks.EXPECT().ParseLock(mock.Anything).RunAndReturn(func(id string) string {
return id
})
httpAdapter = connector.NewHttpAdapterWithConnector(con, locks)
})
Describe("GetLock", func() {
It("General error", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "POST_LOCK")
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.GetLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("File not found", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "POST_LOCK")
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponse(404), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(404))
})
It("LockId", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "POST_LOCK")
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponseWithLock(200, "zzz111"), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
})
It("Empty LockId", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "POST_LOCK")
w := httptest.NewRecorder()
fc.On("GetLock", mock.Anything).Times(1).Return(connector.NewResponseWithLock(200, ""), nil)
httpAdapter.GetLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal(""))
})
})
Describe("Lock", func() {
Describe("Just lock", func() {
It("General error", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("No LockId provided", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "", "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(400))
})
It("Conflict", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "").Times(1).Return(
connector.NewResponseWithVersionAndLock(
200,
&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(567)},
"abc123",
), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("abc123"))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v1234567"))
})
})
Describe("Unlock and relock", func() {
It("General error", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiOldLock, "qwerty")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("No LockId provided", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "")
req.Header.Set(connector.HeaderWopiOldLock, "")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "", "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(400))
})
It("Conflict", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiOldLock, "qwerty")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiOldLock, "qwerty")
w := httptest.NewRecorder()
fc.On("Lock", mock.Anything, "abc123", "qwerty").Times(1).Return(
connector.NewResponseWithVersionAndLock(
200,
&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(567)},
"abc123",
), nil)
httpAdapter.Lock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("abc123"))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v1234567"))
})
})
})
Describe("RefreshLock", func() {
It("General error", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "REFRESH_LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.RefreshLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("No LockId provided", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "REFRESH_LOCK")
req.Header.Set(connector.HeaderWopiLock, "")
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(400))
})
It("Conflict", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "REFRESH_LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "REFRESH_LOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("RefreshLock", mock.Anything, "abc123").Times(1).Return(
connector.NewResponseWithVersionAndLock(
200,
&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(5678)},
"abc123",
), nil)
httpAdapter.RefreshLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("abc123"))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v12345678"))
})
})
Describe("Unlock", func() {
It("General error", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "UNLOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.UnLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("No LockId provided", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "UNLOCK")
req.Header.Set(connector.HeaderWopiLock, "")
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "").Times(1).Return(connector.NewResponse(400), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(400))
})
It("Conflict", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "UNLOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
req := httptest.NewRequest("POST", "/wopi/files/abcdef", nil)
req.Header.Set("X-WOPI-Override", "UNLOCK")
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
fc.On("UnLock", mock.Anything, "abc123").Times(1).Return(
connector.NewResponseWithVersion(&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(567)}), nil)
httpAdapter.UnLock(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v1234567"))
})
})
Describe("CheckFileInfo", func() {
It("General error", func() {
req := httptest.NewRequest("GET", "/wopi/files/abcdef", nil)
w := httptest.NewRecorder()
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("Not found", func() {
// 404 isn't thrown at the moment. Test is here to prove it's possible to
// throw any error code
req := httptest.NewRequest("GET", "/wopi/files/abcdef", nil)
w := httptest.NewRecorder()
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(connector.NewResponse(404), nil)
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(404))
})
It("Success", func() {
req := httptest.NewRequest("GET", "/wopi/files/abcdef", nil)
w := httptest.NewRecorder()
// might need more info, but should be enough for the test
finfo := &fileinfo.Microsoft{
Size: 123456789,
BreadcrumbDocName: "testy.docx",
}
fc.On("CheckFileInfo", mock.Anything).Times(1).Return(connector.NewResponseSuccessBody(finfo), nil)
httpAdapter.CheckFileInfo(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
jsonInfo, _ := io.ReadAll(resp.Body)
var responseInfo *fileinfo.Microsoft
json.Unmarshal(jsonInfo, &responseInfo)
Expect(responseInfo).To(Equal(finfo))
})
})
Describe("GetFile", func() {
It("General error", func() {
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", nil)
w := httptest.NewRecorder()
cc.On("GetFile", mock.Anything, mock.Anything).Times(1).Return(errors.New("Something happened"))
httpAdapter.GetFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
})
It("Not found", func() {
// 404 isn't thrown at the moment. Test is here to prove it's possible to
// throw any error code
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", nil)
w := httptest.NewRecorder()
cc.On("GetFile", mock.Anything, mock.Anything).Times(1).Return(connector.NewConnectorError(404, "Not found"))
httpAdapter.GetFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(404))
})
It("Success", func() {
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", nil)
w := httptest.NewRecorder()
expectedContent := []byte("This is a fake content for a test file")
cc.On("GetFile", mock.Anything, mock.Anything).Times(1).Run(func(args mock.Arguments) {
w := args.Get(1).(io.Writer)
w.Write(expectedContent)
}).Return(nil)
httpAdapter.GetFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
content, _ := io.ReadAll(resp.Body)
Expect(content).To(Equal(expectedContent))
})
})
Describe("PutFile", func() {
It("General error", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(nil, errors.New("Something happened"))
httpAdapter.PutFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
content, _ := io.ReadAll(resp.Body)
Expect(content).To(Equal([]byte("")))
})
It("Connector error", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(nil, connector.NewConnectorError(500, "Something happened"))
httpAdapter.PutFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
content, _ := io.ReadAll(resp.Body)
Expect(content).To(Equal([]byte("")))
})
It("Conflict", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(
connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.PutFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
w := httptest.NewRecorder()
cc.On("PutFile", mock.Anything, mock.Anything, int64(len(contentBody)), "abc123").Times(1).Return(
connector.NewResponseWithVersionAndLock(
200,
&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(567)},
"abc123",
), nil)
httpAdapter.PutFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("abc123"))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v1234567"))
})
})
Describe("GetAvatar", func() {
It("Missing userID returns 400", func() {
// No chi route context means chi.URLParam returns ""
req := httptest.NewRequest("GET", "/wopi/avatars/", nil)
w := httptest.NewRecorder()
httpAdapter.GetAvatar(w, req)
Expect(w.Result().StatusCode).To(Equal(400))
})
It("ConnectorError propagates the status code", func() {
req := httptest.NewRequest("GET", "/wopi/avatars/user-123", nil)
rctx := chi.NewRouteContext()
rctx.URLParams.Add("userID", "user-123")
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
w := httptest.NewRecorder()
fc.On("GetAvatar", mock.Anything, "user-123").Times(1).
Return(nil, connector.NewConnectorError(502, "Bad Gateway"))
httpAdapter.GetAvatar(w, req)
Expect(w.Result().StatusCode).To(Equal(502))
})
It("General error returns 500", func() {
req := httptest.NewRequest("GET", "/wopi/avatars/user-123", nil)
rctx := chi.NewRouteContext()
rctx.URLParams.Add("userID", "user-123")
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
w := httptest.NewRecorder()
fc.On("GetAvatar", mock.Anything, "user-123").Times(1).
Return(nil, errors.New("unexpected failure"))
httpAdapter.GetAvatar(w, req)
Expect(w.Result().StatusCode).To(Equal(500))
})
It("Success writes Content-Type, Cache-Control and body", func() {
req := httptest.NewRequest("GET", "/wopi/avatars/user-123", nil)
rctx := chi.NewRouteContext()
rctx.URLParams.Add("userID", "user-123")
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
w := httptest.NewRecorder()
avatarData := []byte{0xFF, 0xD8, 0xFF, 0xE0} // fake JPEG bytes
fc.On("GetAvatar", mock.Anything, "user-123").Times(1).Return(
&connector.ConnectorResponse{
Status: 200,
Headers: map[string]string{
"Content-Type": "image/jpeg",
"Cache-Control": "public, max-age=300",
},
Body: avatarData,
}, nil)
httpAdapter.GetAvatar(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get("Content-Type")).To(Equal("image/jpeg"))
Expect(resp.Header.Get("Cache-Control")).To(Equal("public, max-age=300"))
body, _ := io.ReadAll(resp.Body)
Expect(body).To(Equal(avatarData))
})
})
Describe("PutRelativeFile", func() {
It("Connector error", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiRT, "relativetarget.docx")
w := httptest.NewRecorder()
fc.On("PutRelativeFileRelative", mock.Anything, mock.Anything, mock.Anything, int64(len(contentBody)), "relativetarget.docx").Times(1).Return(nil, connector.NewConnectorError(500, "Something happened"))
httpAdapter.PutRelativeFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(500))
content, _ := io.ReadAll(resp.Body)
Expect(content).To(Equal([]byte("")))
})
It("Conflict", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiRT, "relativetarget.docx")
w := httptest.NewRecorder()
fc.On("PutRelativeFileRelative", mock.Anything, mock.Anything, mock.Anything, int64(len(contentBody)), "relativetarget.docx").Times(1).Return(
connector.NewResponseLockConflict("zzz111", "Lock Conflict"), nil)
httpAdapter.PutRelativeFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(409))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("zzz111"))
Expect(resp.Header.Get(connector.HeaderWopiLockFailureReason)).To(Equal("Lock Conflict"))
})
It("Success", func() {
contentBody := "this is the new fake content"
req := httptest.NewRequest("GET", "/wopi/files/abcdef/contents", strings.NewReader(contentBody))
req.Header.Set(connector.HeaderWopiLock, "abc123")
req.Header.Set(connector.HeaderWopiRT, "relativetarget.docx")
w := httptest.NewRecorder()
fc.On("PutRelativeFileRelative", mock.Anything, mock.Anything, mock.Anything, int64(len(contentBody)), "relativetarget.docx").Times(1).Return(
connector.NewResponseWithVersionAndLock(
200,
&typesv1beta1.Timestamp{Seconds: uint64(1234), Nanos: uint32(567)},
"abc123",
), nil)
httpAdapter.PutRelativeFile(w, req)
resp := w.Result()
Expect(resp.StatusCode).To(Equal(200))
Expect(resp.Header.Get(connector.HeaderWopiLock)).To(Equal("abc123"))
Expect(resp.Header.Get(connector.HeaderWopiVersion)).To(Equal("v1234567"))
})
})
})