From e8fa7c9c2c9dde8cc41cba40d5aa7de6801cef7b Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 21 Aug 2026 14:17:03 +0800 Subject: [PATCH] H-418: cover widget direct upload file flow (#76) Co-authored-by: Rogee --- .../handler/widget/widget_handler_test.go | 69 ++++++++++++++----- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/backend/internal/handler/widget/widget_handler_test.go b/backend/internal/handler/widget/widget_handler_test.go index d3dda5db..b5bc34a4 100644 --- a/backend/internal/handler/widget/widget_handler_test.go +++ b/backend/internal/handler/widget/widget_handler_test.go @@ -11,6 +11,8 @@ import ( "mime/multipart" "net/http" "net/http/httptest" + "os" + "path/filepath" "strconv" "strings" "testing" @@ -26,6 +28,8 @@ import ( "github.com/gochat/gochat/internal/automation" "github.com/gochat/gochat/internal/campaign" + "github.com/gochat/gochat/internal/config" + apiv1 "github.com/gochat/gochat/internal/handler/api/v1" "github.com/gochat/gochat/internal/model" channelmodel "github.com/gochat/gochat/internal/model/channel" "github.com/gochat/gochat/internal/repository" @@ -963,6 +967,13 @@ func TestWidgetHandler_ChatwootMessageReplyToContentAttributes(t *testing.T) { func TestWidgetHandler_ChatwootMessageDirectUploadAttachment(t *testing.T) { db, router, _ := setupWidgetHandlerTest(t) account, _ := seedWidgetHandlerData(t, db) + tmpDir := t.TempDir() + uploadSvc := service.NewUploadService(repository.NewDirectUploadRepo(db), &config.Config{ + Storage: config.StorageConfig{LocalPath: tmpDir, MaxFileSize: 50 << 20}, + }).WithWidgetAuth(repository.NewInboxRepo(db), repository.NewContactInboxRepo(db)) + uploadHandler := apiv1.NewUploadHandler(uploadSvc) + router.POST("/api/v1/widget/direct_uploads", uploadHandler.DirectUpload) + router.PUT("/api/v1/widget/direct_uploads/:upload_uuid", uploadHandler.CompleteWidgetDirectUpload) wConfig := httptest.NewRecorder() reqConfig, _ := http.NewRequest("POST", "/api/v1/widget/config?website_token=handler_ws_token_123", nil) @@ -973,24 +984,46 @@ func TestWidgetHandler_ChatwootMessageDirectUploadAttachment(t *testing.T) { require.NoError(t, json.Unmarshal(wConfig.Body.Bytes(), &configResp)) authToken := configResp["contact"].(map[string]interface{})["pubsub_token"].(string) - upload := &model.DirectUpload{ - UploadUUID: "signed-widget-upload-1", - AccountID: account.ID, - Status: model.DirectUploadStatusPending, - Source: model.DirectUploadSourceWidget, - OriginalName: "screenshot.png", - FileType: "image", - MimeType: "image/png", - FileSize: 12, - FileURL: "/uploads/widget_direct/signed-widget-upload-1.png", - ThumbURL: "/uploads/widget_direct/signed-widget-upload-1.png", - ExpiresAt: time.Now().Add(time.Hour), - } - require.NoError(t, db.Create(upload).Error) + fileContent := []byte("hello image") + metadataBody, err := json.Marshal(map[string]interface{}{ + "blob": map[string]interface{}{ + "filename": "screenshot.png", + "byte_size": len(fileContent), + "checksum": "checksum-token", + "content_type": "image/png", + "metadata": map[string]interface{}{"identified": true}, + }, + }) + require.NoError(t, err) + + wCreate := httptest.NewRecorder() + reqCreate, _ := http.NewRequest("POST", "/api/v1/widget/direct_uploads?website_token=handler_ws_token_123", bytes.NewReader(metadataBody)) + reqCreate.Header.Set("Content-Type", "application/json") + reqCreate.Header.Set("X-Auth-Token", authToken) + router.ServeHTTP(wCreate, reqCreate) + require.Equal(t, http.StatusOK, wCreate.Code) + + var createResp map[string]interface{} + require.NoError(t, json.Unmarshal(wCreate.Body.Bytes(), &createResp)) + signedID := createResp["signed_id"].(string) + uploadURL := createResp["direct_upload"].(map[string]interface{})["url"].(string) + + wPut := httptest.NewRecorder() + reqPut, _ := http.NewRequest("PUT", uploadURL, bytes.NewReader(fileContent)) + reqPut.Header.Set("Content-Type", "image/png") + router.ServeHTTP(wPut, reqPut) + require.Equal(t, http.StatusOK, wPut.Code) + storedBytes, err := os.ReadFile(filepath.Join(tmpDir, "widget_direct", signedID+".png")) + require.NoError(t, err) + assert.Equal(t, fileContent, storedBytes) + + var upload model.DirectUpload + require.NoError(t, db.Where("upload_uuid = ?", signedID).First(&upload).Error) + require.Equal(t, model.DirectUploadStatusPending, upload.Status) body := &bytes.Buffer{} writer := multipart.NewWriter(body) - require.NoError(t, writer.WriteField("message[attachments][]", upload.UploadUUID)) + require.NoError(t, writer.WriteField("message[attachments][]", signedID)) require.NoError(t, writer.Close()) wMessage := httptest.NewRecorder() @@ -1008,7 +1041,7 @@ func TestWidgetHandler_ChatwootMessageDirectUploadAttachment(t *testing.T) { require.Len(t, attachments, 1) attachmentPayload := attachments[0].(map[string]interface{}) assertWidgetAttachmentFixtureShape(t, attachmentPayload) - assert.Equal(t, "/uploads/widget_direct/signed-widget-upload-1.png", attachmentPayload["data_url"]) + assert.Equal(t, upload.FileURL, attachmentPayload["data_url"]) assert.Equal(t, "image", attachmentPayload["file_type"]) assert.Equal(t, float64(account.ID), attachmentPayload["account_id"]) assert.NotContains(t, attachmentPayload, "created_at") @@ -1016,7 +1049,7 @@ func TestWidgetHandler_ChatwootMessageDirectUploadAttachment(t *testing.T) { var attachment model.Attachment require.NoError(t, db.Where("file_name = ?", "screenshot.png").First(&attachment).Error) assert.Equal(t, upload.FileURL, attachment.FileURL) - require.NoError(t, db.First(upload, upload.ID).Error) + require.NoError(t, db.First(&upload, upload.ID).Error) assert.Equal(t, model.DirectUploadStatusCompleted, upload.Status) wIndex := httptest.NewRecorder() @@ -1035,7 +1068,7 @@ func TestWidgetHandler_ChatwootMessageDirectUploadAttachment(t *testing.T) { require.Len(t, indexedAttachments, 1) indexedAttachment := indexedAttachments[0].(map[string]interface{}) assertWidgetAttachmentFixtureShape(t, indexedAttachment) - assert.Equal(t, "/uploads/widget_direct/signed-widget-upload-1.png", indexedAttachment["data_url"]) + assert.Equal(t, upload.FileURL, indexedAttachment["data_url"]) assert.Equal(t, float64(account.ID), indexedAttachment["account_id"]) assert.NotContains(t, indexedAttachment, "created_at") }