test(crm): cover chatwoot frontend crm smoke
This commit is contained in:
@@ -0,0 +1,391 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
"github.com/gochat/gochat/internal/model"
|
||||
"github.com/gochat/gochat/internal/repository"
|
||||
"github.com/gochat/gochat/internal/service"
|
||||
)
|
||||
|
||||
func TestChatwootFrontendCRMSmoke(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
|
||||
db, err := gorm.Open(sqlite.Open("file:crm_frontend_smoke?mode=memory&cache=shared"), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Silent),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
sqlDB, dbErr := db.DB()
|
||||
if dbErr == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
})
|
||||
|
||||
require.NoError(t, db.AutoMigrate(
|
||||
&model.Account{},
|
||||
&model.User{},
|
||||
&model.AccountUser{},
|
||||
&model.Tag{},
|
||||
&model.Contact{},
|
||||
&model.ContactLabel{},
|
||||
&model.ContactInbox{},
|
||||
&model.Inbox{},
|
||||
&model.Company{},
|
||||
&model.CompanyNote{},
|
||||
&model.Note{},
|
||||
&model.Conversation{},
|
||||
&model.Message{},
|
||||
&model.Attachment{},
|
||||
))
|
||||
|
||||
account := &model.Account{Name: "CRM Smoke", Locale: "en", Active: true, Status: "active"}
|
||||
require.NoError(t, db.Create(account).Error)
|
||||
user := &model.User{Name: "Smoke Agent", Email: "smoke-agent@example.com", AccountID: account.ID}
|
||||
require.NoError(t, db.Create(user).Error)
|
||||
require.NoError(t, db.Create(&model.AccountUser{AccountID: account.ID, UserID: user.ID, Role: "administrator"}).Error)
|
||||
|
||||
inbox := &model.Inbox{AccountID: account.ID, Name: "Website", ChannelType: "web_widget", ChannelID: 1, Enabled: true}
|
||||
require.NoError(t, db.Create(inbox).Error)
|
||||
|
||||
router := buildCRMFrontendSmokeRouter(t, db, account.ID, user.ID)
|
||||
|
||||
contactID := smokeCreateContact(t, router, account.ID, inbox.ID)
|
||||
smokeAssertContactListAndSearch(t, router, account.ID, contactID)
|
||||
smokeAssertContactShowUpdateLabelsAndNestedData(t, router, db, account.ID, user.ID, contactID, inbox.ID)
|
||||
smokeAssertCompanyFlows(t, router, db, account.ID, contactID)
|
||||
}
|
||||
|
||||
func buildCRMFrontendSmokeRouter(t *testing.T, db *gorm.DB, accountID uint, userID uint) *gin.Engine {
|
||||
t.Helper()
|
||||
|
||||
contactRepo := repository.NewContactRepo(db)
|
||||
contactInboxRepo := repository.NewContactInboxRepo(db)
|
||||
noteRepo := repository.NewNoteRepo(db)
|
||||
contactNoteRepo := repository.NewContactNoteRepo(db)
|
||||
conversationRepo := repository.NewConversationRepo(db)
|
||||
companyRepo := repository.NewCompanyRepo(db)
|
||||
|
||||
contactInboxSvc := service.NewContactInboxService(contactInboxRepo)
|
||||
contactSvc := service.NewContactService(contactRepo, contactInboxSvc, noteRepo)
|
||||
mergeSvc := service.NewContactMergeService(repository.NewContactMergeRepo(db), db)
|
||||
contactNoteSvc := service.NewContactNoteService(contactRepo, contactNoteRepo)
|
||||
conversationSvc := service.NewConversationService(conversationRepo, nil, nil, nil, nil, nil, nil)
|
||||
companySvc := service.NewCompanyService(companyRepo, contactRepo, conversationRepo)
|
||||
|
||||
contactHandler := NewContactHandler(contactSvc, contactInboxSvc, mergeSvc, contactNoteSvc, conversationSvc)
|
||||
companyHandler := NewCompanyHandler(companySvc)
|
||||
|
||||
router := gin.New()
|
||||
router.Use(gin.Recovery())
|
||||
router.Use(func(c *gin.Context) {
|
||||
c.Set("account_id", accountID)
|
||||
c.Set("user_id", userID)
|
||||
c.Next()
|
||||
})
|
||||
|
||||
contacts := router.Group("/api/v1/accounts/:id/contacts")
|
||||
{
|
||||
contacts.GET("/", contactHandler.List)
|
||||
contacts.POST("/", contactHandler.Create)
|
||||
contacts.GET("/search", contactHandler.Search)
|
||||
contacts.GET("/:contact_id", contactHandler.Get)
|
||||
contacts.PATCH("/:contact_id", contactHandler.Update)
|
||||
contacts.POST("/:contact_id/destroy_custom_attributes", contactHandler.DeleteCustomAttributes)
|
||||
contacts.DELETE("/:contact_id/avatar", contactHandler.DeleteAvatar)
|
||||
contacts.GET("/:contact_id/labels", contactHandler.ListLabels)
|
||||
contacts.POST("/:contact_id/labels", contactHandler.UpdateLabels)
|
||||
contacts.GET("/:contact_id/contactable_inboxes", contactHandler.ContactableInboxes)
|
||||
contacts.GET("/:contact_id/conversations", contactHandler.ListConversations)
|
||||
contacts.GET("/:contact_id/notes", contactHandler.ListNotes)
|
||||
contacts.POST("/:contact_id/notes", contactHandler.CreateNote)
|
||||
}
|
||||
|
||||
companies := router.Group("/api/v1/accounts/:id/companies")
|
||||
{
|
||||
companies.GET("/", companyHandler.List)
|
||||
companies.POST("/", companyHandler.Create)
|
||||
companies.GET("/search", companyHandler.Search)
|
||||
companies.GET("/:company_id", companyHandler.Get)
|
||||
companies.PATCH("/:company_id", companyHandler.Update)
|
||||
companies.POST("/:company_id/destroy_custom_attributes", companyHandler.DestroyCustomAttributes)
|
||||
companies.DELETE("/:company_id/avatar", companyHandler.DeleteAvatar)
|
||||
companies.GET("/:company_id/contacts", companyHandler.ListContacts)
|
||||
companies.GET("/:company_id/contacts/search", companyHandler.SearchContacts)
|
||||
companies.POST("/:company_id/contacts", companyHandler.AddContact)
|
||||
companies.DELETE("/:company_id/contacts/:contact_id", companyHandler.RemoveContact)
|
||||
companies.GET("/:company_id/conversations", companyHandler.ListConversations)
|
||||
companies.GET("/:company_id/notes", companyHandler.ListNotes)
|
||||
companies.POST("/:company_id/notes", companyHandler.CreateNote)
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
func smokeCreateContact(t *testing.T, router *gin.Engine, accountID uint, inboxID uint) uint {
|
||||
t.Helper()
|
||||
|
||||
body := map[string]any{
|
||||
"name": "Jane Frontend",
|
||||
"email": "jane.frontend@example.com",
|
||||
"phone": "+15550101",
|
||||
"identifier": "frontend-jane",
|
||||
"inbox_id": inboxID,
|
||||
"source_id": "frontend-source",
|
||||
}
|
||||
resp := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/contacts/", accountID), body)
|
||||
require.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
|
||||
|
||||
data := smokeDecodeObject(t, resp)
|
||||
payload := smokeObject(t, data, "payload")
|
||||
contact := smokeObject(t, payload, "contact")
|
||||
require.Equal(t, "Jane Frontend", contact["name"])
|
||||
require.Equal(t, "jane.frontend@example.com", contact["email"])
|
||||
require.NotNil(t, payload["contact_inbox"])
|
||||
return smokeUint(t, contact["id"])
|
||||
}
|
||||
|
||||
func smokeAssertContactListAndSearch(t *testing.T, router *gin.Engine, accountID uint, contactID uint) {
|
||||
t.Helper()
|
||||
|
||||
listURL := fmt.Sprintf("/api/v1/accounts/%d/contacts/?include_contact_inboxes=false&page=1&sort=name", accountID)
|
||||
resp := smokeJSONRequest(t, router, http.MethodGet, listURL, nil)
|
||||
require.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
|
||||
data := smokeDecodeObject(t, resp)
|
||||
require.Equal(t, float64(1), smokeObject(t, data, "meta")["count"])
|
||||
contacts := smokeArray(t, data, "payload")
|
||||
require.Len(t, contacts, 1)
|
||||
require.Equal(t, float64(contactID), contacts[0].(map[string]any)["id"])
|
||||
|
||||
emptySearch := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/contacts/search?include_contact_inboxes=false&page=1&sort=name&q=", accountID), nil)
|
||||
require.Equal(t, http.StatusUnprocessableEntity, emptySearch.Code, emptySearch.Body.String())
|
||||
require.Equal(t, "Specify search string with parameter q", smokeDecodeObject(t, emptySearch)["error"])
|
||||
|
||||
searchURL := fmt.Sprintf("/api/v1/accounts/%d/contacts/search?include_contact_inboxes=false&page=1&sort=name&q=Jane", accountID)
|
||||
search := smokeJSONRequest(t, router, http.MethodGet, searchURL, nil)
|
||||
require.Equal(t, http.StatusOK, search.Code, search.Body.String())
|
||||
searchData := smokeDecodeObject(t, search)
|
||||
require.Equal(t, float64(1), smokeObject(t, searchData, "meta")["count"])
|
||||
require.Len(t, smokeArray(t, searchData, "payload"), 1)
|
||||
}
|
||||
|
||||
func smokeAssertContactShowUpdateLabelsAndNestedData(t *testing.T, router *gin.Engine, db *gorm.DB, accountID, userID, contactID, inboxID uint) {
|
||||
t.Helper()
|
||||
|
||||
showURL := fmt.Sprintf("/api/v1/accounts/%d/contacts/%d?include_contact_inboxes=false", accountID, contactID)
|
||||
show := smokeJSONRequest(t, router, http.MethodGet, showURL, nil)
|
||||
require.Equal(t, http.StatusOK, show.Code, show.Body.String())
|
||||
require.Equal(t, "Jane Frontend", smokeObject(t, smokeDecodeObject(t, show), "payload")["name"])
|
||||
|
||||
updateBody := map[string]any{"name": "Jane Updated", "custom_attributes": map[string]any{"plan": "pro", "tier": "gold"}}
|
||||
update := smokeJSONRequest(t, router, http.MethodPatch, showURL, updateBody)
|
||||
require.Equal(t, http.StatusOK, update.Code, update.Body.String())
|
||||
updated := smokeObject(t, smokeDecodeObject(t, update), "payload")
|
||||
require.Equal(t, "Jane Updated", updated["name"])
|
||||
require.Equal(t, "pro", smokeObject(t, updated, "custom_attributes")["plan"])
|
||||
|
||||
destroyAttrs := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/destroy_custom_attributes", accountID, contactID), map[string]any{"custom_attributes": []string{"tier"}})
|
||||
require.Equal(t, http.StatusOK, destroyAttrs.Code, destroyAttrs.Body.String())
|
||||
require.NotContains(t, smokeObject(t, smokeObject(t, smokeDecodeObject(t, destroyAttrs), "payload"), "custom_attributes"), "tier")
|
||||
|
||||
labelsURL := fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/labels", accountID, contactID)
|
||||
labels := smokeJSONRequest(t, router, http.MethodPost, labelsURL, map[string]any{"labels": []string{"customer-support", "vip"}})
|
||||
require.Equal(t, http.StatusOK, labels.Code, labels.Body.String())
|
||||
require.Equal(t, []any{"customer-support", "vip"}, smokeArray(t, smokeDecodeObject(t, labels), "payload"))
|
||||
|
||||
labelsGet := smokeJSONRequest(t, router, http.MethodGet, labelsURL, nil)
|
||||
require.Equal(t, http.StatusOK, labelsGet.Code, labelsGet.Body.String())
|
||||
require.Equal(t, []any{"customer-support", "vip"}, smokeArray(t, smokeDecodeObject(t, labelsGet), "payload"))
|
||||
|
||||
filteredURL := fmt.Sprintf("/api/v1/accounts/%d/contacts/?include_contact_inboxes=false&page=1&sort=name&labels[]=customer-support", accountID)
|
||||
filtered := smokeJSONRequest(t, router, http.MethodGet, filteredURL, nil)
|
||||
require.Equal(t, http.StatusOK, filtered.Code, filtered.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, filtered), "payload"), 1)
|
||||
|
||||
contactable := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/contactable_inboxes", accountID, contactID), nil)
|
||||
require.Equal(t, http.StatusOK, contactable.Code, contactable.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, contactable), "payload"), 1)
|
||||
|
||||
note := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/notes", accountID, contactID), map[string]any{"note": map[string]any{"content": "Frontend note"}})
|
||||
require.Equal(t, http.StatusOK, note.Code, note.Body.String())
|
||||
require.Equal(t, "Frontend note", smokeDecodeObject(t, note)["content"])
|
||||
|
||||
notes := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/notes", accountID, contactID), nil)
|
||||
require.Equal(t, http.StatusOK, notes.Code, notes.Body.String())
|
||||
require.Len(t, smokeDecodeArray(t, notes), 1)
|
||||
|
||||
createConversationForSmoke(t, db, accountID, userID, contactID, inboxID)
|
||||
conversations := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/contacts/%d/conversations", accountID, contactID), nil)
|
||||
require.Equal(t, http.StatusOK, conversations.Code, conversations.Body.String())
|
||||
payload := smokeArray(t, smokeDecodeObject(t, conversations), "payload")
|
||||
require.Len(t, payload, 1)
|
||||
conversation := payload[0].(map[string]any)
|
||||
require.Equal(t, float64(accountID), conversation["account_id"])
|
||||
require.NotEmpty(t, smokeObject(t, conversation, "meta"))
|
||||
}
|
||||
|
||||
func smokeAssertCompanyFlows(t *testing.T, router *gin.Engine, db *gorm.DB, accountID uint, contactID uint) {
|
||||
t.Helper()
|
||||
|
||||
companyCreate := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/companies/", accountID), map[string]any{
|
||||
"company": map[string]any{"name": "Acme Frontend", "domain": "acme.example", "custom_attributes": map[string]any{"plan": "enterprise", "region": "apac"}},
|
||||
})
|
||||
require.Equal(t, http.StatusOK, companyCreate.Code, companyCreate.Body.String())
|
||||
companyID := smokeUint(t, smokeObject(t, smokeDecodeObject(t, companyCreate), "payload")["id"])
|
||||
|
||||
companyList := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/?page=1&sort=name", accountID), nil)
|
||||
require.Equal(t, http.StatusOK, companyList.Code, companyList.Body.String())
|
||||
require.Equal(t, float64(1), smokeObject(t, smokeDecodeObject(t, companyList), "meta")["total_count"])
|
||||
|
||||
companySearch := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/search?q=Acme&page=1&sort=name", accountID), nil)
|
||||
require.Equal(t, http.StatusOK, companySearch.Code, companySearch.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, companySearch), "payload"), 1)
|
||||
|
||||
emptyCompanySearch := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/search?q=&page=1&sort=name", accountID), nil)
|
||||
require.Equal(t, http.StatusUnprocessableEntity, emptyCompanySearch.Code, emptyCompanySearch.Body.String())
|
||||
|
||||
companyShowURL := fmt.Sprintf("/api/v1/accounts/%d/companies/%d", accountID, companyID)
|
||||
companyShow := smokeJSONRequest(t, router, http.MethodGet, companyShowURL, nil)
|
||||
require.Equal(t, http.StatusOK, companyShow.Code, companyShow.Body.String())
|
||||
require.Equal(t, "Acme Frontend", smokeObject(t, smokeDecodeObject(t, companyShow), "payload")["name"])
|
||||
|
||||
companyUpdate := smokeJSONRequest(t, router, http.MethodPatch, companyShowURL, map[string]any{"company": map[string]any{"name": "Acme Updated", "custom_attributes": map[string]any{"segment": "platinum"}}})
|
||||
require.Equal(t, http.StatusOK, companyUpdate.Code, companyUpdate.Body.String())
|
||||
require.Equal(t, "Acme Updated", smokeObject(t, smokeDecodeObject(t, companyUpdate), "payload")["name"])
|
||||
|
||||
destroyCompanyAttrs := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/destroy_custom_attributes", accountID, companyID), map[string]any{"custom_attributes": []string{"region"}})
|
||||
require.Equal(t, http.StatusOK, destroyCompanyAttrs.Code, destroyCompanyAttrs.Body.String())
|
||||
require.NotContains(t, smokeObject(t, smokeObject(t, smokeDecodeObject(t, destroyCompanyAttrs), "payload"), "custom_attributes"), "region")
|
||||
|
||||
attach := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/contacts", accountID, companyID), map[string]any{"contact_id": contactID})
|
||||
require.Equal(t, http.StatusOK, attach.Code, attach.Body.String())
|
||||
require.True(t, smokeObject(t, smokeDecodeObject(t, attach), "payload")["linked_to_current_company"].(bool))
|
||||
|
||||
companyContacts := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/contacts?page=1", accountID, companyID), nil)
|
||||
require.Equal(t, http.StatusOK, companyContacts.Code, companyContacts.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, companyContacts), "payload"), 1)
|
||||
|
||||
candidate := &model.Contact{AccountID: accountID, Name: "Search Candidate", Email: "candidate@example.com"}
|
||||
require.NoError(t, db.Create(candidate).Error)
|
||||
searchCandidates := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/contacts/search?q=Candidate&page=1", accountID, companyID), nil)
|
||||
require.Equal(t, http.StatusOK, searchCandidates.Code, searchCandidates.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, searchCandidates), "payload"), 1)
|
||||
|
||||
companyNote := smokeJSONRequest(t, router, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/notes", accountID, companyID), map[string]any{"content": "Company frontend note"})
|
||||
require.Equal(t, http.StatusOK, companyNote.Code, companyNote.Body.String())
|
||||
require.Equal(t, "Company frontend note", smokeObject(t, smokeDecodeObject(t, companyNote), "payload")["content"])
|
||||
|
||||
companyNotes := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/notes", accountID, companyID), nil)
|
||||
require.Equal(t, http.StatusOK, companyNotes.Code, companyNotes.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, companyNotes), "payload"), 1)
|
||||
|
||||
companyConversations := smokeJSONRequest(t, router, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%d/companies/%d/conversations", accountID, companyID), nil)
|
||||
require.Equal(t, http.StatusOK, companyConversations.Code, companyConversations.Body.String())
|
||||
require.Len(t, smokeArray(t, smokeDecodeObject(t, companyConversations), "payload"), 1)
|
||||
}
|
||||
|
||||
func createConversationForSmoke(t *testing.T, db *gorm.DB, accountID, userID, contactID, inboxID uint) {
|
||||
t.Helper()
|
||||
|
||||
// This test uses direct persistence for conversation state because the CRM frontend
|
||||
// reads nested conversation endpoints after inbox/message flows have already created it.
|
||||
now := time.Now().Unix()
|
||||
displayID := uint(1)
|
||||
conversation := &model.Conversation{
|
||||
DisplayID: &displayID,
|
||||
AccountID: accountID,
|
||||
InboxID: inboxID,
|
||||
ContactID: contactID,
|
||||
Status: "open",
|
||||
Priority: "low",
|
||||
ChannelType: "Channel::WebWidget",
|
||||
Channel: "web_widget",
|
||||
LastActivityAt: &now,
|
||||
LastMessageAt: &now,
|
||||
}
|
||||
require.NoError(t, db.Create(conversation).Error)
|
||||
require.NoError(t, db.Create(&model.Message{
|
||||
ConversationID: conversation.ID,
|
||||
AccountID: accountID,
|
||||
InboxID: inboxID,
|
||||
SenderID: &userID,
|
||||
SenderType: "User",
|
||||
Content: "Hello from the frontend smoke",
|
||||
ContentType: "text",
|
||||
MessageType: "outgoing",
|
||||
Status: "sent",
|
||||
ContentAttributes: datatypes.JSON([]byte(`{}`)),
|
||||
}).Error)
|
||||
}
|
||||
|
||||
func smokeJSONRequest(t *testing.T, router *gin.Engine, method string, path string, body any) *httptest.ResponseRecorder {
|
||||
t.Helper()
|
||||
|
||||
var reader *bytes.Reader
|
||||
if body != nil {
|
||||
payload, err := json.Marshal(body)
|
||||
require.NoError(t, err)
|
||||
reader = bytes.NewReader(payload)
|
||||
} else {
|
||||
reader = bytes.NewReader(nil)
|
||||
}
|
||||
req := httptest.NewRequest(method, path, reader)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
return w
|
||||
}
|
||||
|
||||
func smokeDecodeObject(t *testing.T, resp *httptest.ResponseRecorder) map[string]any {
|
||||
t.Helper()
|
||||
var data map[string]any
|
||||
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data), resp.Body.String())
|
||||
return data
|
||||
}
|
||||
|
||||
func smokeDecodeArray(t *testing.T, resp *httptest.ResponseRecorder) []any {
|
||||
t.Helper()
|
||||
var data []any
|
||||
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data), resp.Body.String())
|
||||
return data
|
||||
}
|
||||
|
||||
func smokeObject(t *testing.T, data map[string]any, key string) map[string]any {
|
||||
t.Helper()
|
||||
value, ok := data[key].(map[string]any)
|
||||
require.Truef(t, ok, "%s should be an object in %#v", key, data)
|
||||
return value
|
||||
}
|
||||
|
||||
func smokeArray(t *testing.T, data map[string]any, key string) []any {
|
||||
t.Helper()
|
||||
value, ok := data[key].([]any)
|
||||
require.Truef(t, ok, "%s should be an array in %#v", key, data)
|
||||
return value
|
||||
}
|
||||
|
||||
func smokeUint(t *testing.T, value any) uint {
|
||||
t.Helper()
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
return uint(v)
|
||||
case uint:
|
||||
return v
|
||||
default:
|
||||
t.Fatalf("unexpected uint-compatible value %#v", value)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user