Align GoChat with Chatwoot frontend contracts

This commit is contained in:
2026-06-13 22:13:32 +08:00
parent 71abf58636
commit d884fdda0a
162 changed files with 9825 additions and 528 deletions
@@ -222,7 +222,7 @@ func TestCaptainCustomToolHandler_ChatwootToolPayloadsAndScope(t *testing.T) {
}
func TestCaptainDocumentHandler_ChatwootDocumentPayloadsAndSync(t *testing.T) {
router, _, account, otherAccount, assistant := setupCaptainResourceParityTest(t)
router, db, account, otherAccount, assistant := setupCaptainResourceParityTest(t)
basePath := "/api/v1/accounts/" + strconv.FormatUint(uint64(account.ID), 10) + "/captain/documents"
otherBasePath := "/api/v1/accounts/" + strconv.FormatUint(uint64(otherAccount.ID), 10) + "/captain/documents"
@@ -247,6 +247,21 @@ func TestCaptainDocumentHandler_ChatwootDocumentPayloadsAndSync(t *testing.T) {
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &listResp))
assert.Len(t, listResp["payload"], 1)
assert.Equal(t, float64(1), listResp["meta"].(map[string]any)["total_count"])
listedDocument := listResp["payload"].([]any)[0].(map[string]any)
for _, key := range []string{"account_id", "assistant", "content", "content_type", "created_at", "external_link", "display_url", "file_size", "pdf_document", "id", "name", "status", "sync_status", "sync_in_progress", "last_synced_at", "last_sync_attempted_at", "last_sync_error_code", "updated_at"} {
assert.Contains(t, listedDocument, key, "captain document should expose Chatwoot key %s", key)
}
failedDoc := &model.CaptainDocument{AccountID: account.ID, AssistantID: assistant.ID, Name: "Failed Help", ExternalLink: "https://example.com/failed", Status: model.DocumentStatusCompleted, SyncStatus: model.DocumentSyncStatusFailed, LastSyncErrorCode: "timeout"}
require.NoError(t, db.Create(failedDoc).Error)
w = captainResourceJSONRequest(t, router, http.MethodGet, basePath+"/?assistant_id="+strconv.FormatUint(uint64(assistant.ID), 10)+"&filter=failed&source=web&search_key=failed", nil)
assert.Equal(t, http.StatusOK, w.Code)
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &listResp))
assert.Len(t, listResp["payload"], 1)
filteredDocument := listResp["payload"].([]any)[0].(map[string]any)
assert.Equal(t, float64(failedDoc.ID), filteredDocument["id"])
assert.Equal(t, "failed", filteredDocument["sync_status"])
assert.Equal(t, false, filteredDocument["sync_in_progress"])
w = captainResourceJSONRequest(t, router, http.MethodGet, fmt.Sprintf("%s/%d", otherBasePath, documentID), nil)
assert.Equal(t, http.StatusNotFound, w.Code)
@@ -266,7 +281,7 @@ func TestCaptainDocumentHandler_ChatwootDocumentPayloadsAndSync(t *testing.T) {
}
func TestCaptainAssistantResponseHandler_ChatwootResponsePayloadsAndFilters(t *testing.T) {
router, _, account, otherAccount, assistant := setupCaptainResourceParityTest(t)
router, db, account, otherAccount, assistant := setupCaptainResourceParityTest(t)
basePath := "/api/v1/accounts/" + strconv.FormatUint(uint64(account.ID), 10) + "/captain/assistant_responses"
otherBasePath := "/api/v1/accounts/" + strconv.FormatUint(uint64(otherAccount.ID), 10) + "/captain/assistant_responses"
@@ -291,6 +306,24 @@ func TestCaptainAssistantResponseHandler_ChatwootResponsePayloadsAndFilters(t *t
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &listResp))
assert.Len(t, listResp["payload"], 1)
assert.Equal(t, float64(1), listResp["meta"].(map[string]any)["total_count"])
listedResponse := listResp["payload"].([]any)[0].(map[string]any)
for _, key := range []string{"account_id", "answer", "assistant", "created_at", "id", "question", "updated_at", "status", "edited"} {
assert.Contains(t, listedResponse, key, "captain response should expose Chatwoot key %s", key)
}
document := &model.CaptainDocument{AccountID: account.ID, AssistantID: assistant.ID, Name: "FAQ Doc", ExternalLink: "https://example.com/faq", Status: model.DocumentStatusCompleted, SyncStatus: model.DocumentSyncStatusSynced}
require.NoError(t, db.Create(document).Error)
legacyDocumentableType := "CaptainDocument"
documentResponse := &model.CaptainAssistantResponse{AccountID: account.ID, AssistantID: assistant.ID, DocumentableID: &document.ID, DocumentableType: legacyDocumentableType, Question: "Document question", Answer: "Document answer", Status: model.ResponseStatusApproved}
require.NoError(t, db.Create(documentResponse).Error)
w = captainResourceJSONRequest(t, router, http.MethodGet, basePath+"/?document_id="+strconv.FormatUint(uint64(document.ID), 10), nil)
assert.Equal(t, http.StatusOK, w.Code)
require.NoError(t, json.Unmarshal(w.Body.Bytes(), &listResp))
assert.Len(t, listResp["payload"], 1)
documentFilteredResponse := listResp["payload"].([]any)[0].(map[string]any)
assert.Equal(t, float64(documentResponse.ID), documentFilteredResponse["id"])
assert.Equal(t, "Captain::Document", documentFilteredResponse["documentable"].(map[string]any)["type"])
assert.Equal(t, float64(document.ID), documentFilteredResponse["documentable"].(map[string]any)["id"])
w = captainResourceJSONRequest(t, router, http.MethodGet, fmt.Sprintf("%s/%d", otherBasePath, responseID), nil)
assert.Equal(t, http.StatusNotFound, w.Code)