97 lines
3.7 KiB
Go
97 lines
3.7 KiB
Go
package bitrix
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// fakeBitrix отвечает на методы REST так, как отвечает Битрикс24, и запоминает тела запросов.
|
||
func fakeBitrix(t *testing.T, answers map[string]string) (*Client, map[string]map[string]any) {
|
||
t.Helper()
|
||
got := map[string]map[string]any{}
|
||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
method := strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/rest/1/key/"), ".json")
|
||
var body map[string]any
|
||
_ = json.NewDecoder(r.Body).Decode(&body)
|
||
got[method] = body
|
||
ans, ok := answers[method]
|
||
if !ok {
|
||
w.WriteHeader(http.StatusBadRequest)
|
||
_, _ = w.Write([]byte(`{"error":"ERROR_METHOD_NOT_FOUND","error_description":"нет такого метода"}`))
|
||
return
|
||
}
|
||
_, _ = w.Write([]byte(ans))
|
||
}))
|
||
t.Cleanup(srv.Close)
|
||
return New(srv.URL + "/rest/1/key/"), got
|
||
}
|
||
|
||
func TestAddLeadSendsFieldsAndReturnsID(t *testing.T) {
|
||
c, got := fakeBitrix(t, map[string]string{"crm.lead.add": `{"result":683100,"time":{}}`})
|
||
id, err := c.AddLead(context.Background(), LeadDraft{
|
||
Title: "Онлайн-запись: Иванов — 10.10 15:00", Name: "Анна", Phone: "+79280000000",
|
||
SourceID: "112", SourceDescr: "Онлайн-запись на сайте", Comments: "строка<br>строка",
|
||
})
|
||
if err != nil || id != "683100" {
|
||
t.Fatalf("id=%q err=%v", id, err)
|
||
}
|
||
f, _ := got["crm.lead.add"]["fields"].(map[string]any)
|
||
if f["STATUS_ID"] != "NEW" || f["SOURCE_ID"] != "112" || f["NAME"] != "Анна" || f["TITLE"] == nil {
|
||
t.Fatalf("поля лида: %v", f)
|
||
}
|
||
phones, _ := f["PHONE"].([]any)
|
||
if len(phones) != 1 || phones[0].(map[string]any)["VALUE"] != "+79280000000" {
|
||
t.Fatalf("телефон: %v", f["PHONE"])
|
||
}
|
||
}
|
||
|
||
func TestAddLeadReportsBitrixError(t *testing.T) {
|
||
c, _ := fakeBitrix(t, map[string]string{"crm.lead.add": `{"error":"ACCESS_DENIED","error_description":"нет прав"}`})
|
||
if _, err := c.AddLead(context.Background(), LeadDraft{Title: "x"}); err == nil || !strings.Contains(err.Error(), "ACCESS_DENIED") {
|
||
t.Fatalf("ожидали ошибку прав, получили %v", err)
|
||
}
|
||
}
|
||
|
||
func TestLeadSemanticsFiltersByIDs(t *testing.T) {
|
||
c, got := fakeBitrix(t, map[string]string{
|
||
"crm.lead.list": `{"result":[{"ID":"1","STATUS_SEMANTIC_ID":"S"},{"ID":"2","STATUS_SEMANTIC_ID":"F"}],"total":2}`,
|
||
})
|
||
m, err := c.LeadSemantics(context.Background(), []string{"1", "2", "3"})
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
// лида 3 в ответе нет (удалён в CRM) — в карте его тоже нет
|
||
if m["1"] != SemanticSuccess || m["2"] != SemanticFailure || len(m) != 2 {
|
||
t.Fatalf("семантика: %v", m)
|
||
}
|
||
filter, _ := got["crm.lead.list"]["filter"].(map[string]any)
|
||
if ids, _ := filter["@ID"].([]any); len(ids) != 3 {
|
||
t.Fatalf("фильтр по ID: %v", filter)
|
||
}
|
||
}
|
||
|
||
func TestFailLeadAndComment(t *testing.T) {
|
||
c, got := fakeBitrix(t, map[string]string{
|
||
"crm.lead.update": `{"result":true}`,
|
||
"crm.timeline.comment.add": `{"result":55}`,
|
||
})
|
||
if err := c.FailLead(context.Background(), "7"); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if err := c.AddLeadComment(context.Background(), "7", "Запись отменена"); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
upd, _ := got["crm.lead.update"]["fields"].(map[string]any)
|
||
if got["crm.lead.update"]["id"] != "7" || upd["STATUS_ID"] != FailedStatusID {
|
||
t.Fatalf("обновление лида: %v", got["crm.lead.update"])
|
||
}
|
||
cm, _ := got["crm.timeline.comment.add"]["fields"].(map[string]any)
|
||
if cm["ENTITY_TYPE"] != "lead" || cm["ENTITY_ID"] != "7" {
|
||
t.Fatalf("комментарий: %v", cm)
|
||
}
|
||
}
|