136 lines
4.0 KiB
Go
136 lines
4.0 KiB
Go
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"encoding/json"
|
||
|
|
"net/http"
|
||
|
|
"net/http/httptest"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/DATA-DOG/go-sqlmock"
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
"github.com/stretchr/testify/require"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestCRMHandler_ListCustomers(t *testing.T) {
|
||
|
|
db, mock, err := sqlmock.New()
|
||
|
|
require.NoError(t, err)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
handler := NewCRMHandler(db)
|
||
|
|
|
||
|
|
mock.ExpectQuery("SELECT id, name, email, phone, company, org_number, status, source, tags, assigned_to, created_at, updated_at FROM boc_customers").
|
||
|
|
WithArgs("active").
|
||
|
|
WillReturnRows(sqlmock.NewRows([]string{
|
||
|
|
"id", "name", "email", "phone", "company", "org_number", "status", "source", "tags", "assigned_to", "created_at", "updated_at",
|
||
|
|
}).AddRow(
|
||
|
|
"cust-1", "Test AB", "test@test.com", "+46701234567", "Test AB", "559141-7042", "active", "web", "{tag1,tag2}", nil, time.Now(), time.Now(),
|
||
|
|
))
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/crm/customers?status=active", nil)
|
||
|
|
rr := httptest.NewRecorder()
|
||
|
|
|
||
|
|
handler.ListCustomers(rr, req)
|
||
|
|
|
||
|
|
assert.Equal(t, http.StatusOK, rr.Code)
|
||
|
|
|
||
|
|
var response map[string]interface{}
|
||
|
|
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
customers := response["customers"].([]interface{})
|
||
|
|
assert.Len(t, customers, 1)
|
||
|
|
assert.Equal(t, float64(1), response["total"])
|
||
|
|
|
||
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCRMHandler_CreateCustomer(t *testing.T) {
|
||
|
|
db, mock, err := sqlmock.New()
|
||
|
|
require.NoError(t, err)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
handler := NewCRMHandler(db)
|
||
|
|
|
||
|
|
mock.ExpectQuery("INSERT INTO boc_customers").
|
||
|
|
WithArgs("Test AB", "test@test.com", "+46701234567", "Test AB", "", "lead", "", nil).
|
||
|
|
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow("cust-1"))
|
||
|
|
// NOTE: pq.Array([]string(nil)) becomes nil argument — sqlmock matches nil
|
||
|
|
|
||
|
|
payload := Customer{
|
||
|
|
Name: "Test AB",
|
||
|
|
Email: "test@test.com",
|
||
|
|
Phone: "+46701234567",
|
||
|
|
Company: "Test AB",
|
||
|
|
Status: "lead",
|
||
|
|
}
|
||
|
|
body, _ := json.Marshal(payload)
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/crm/customers", bytes.NewReader(body))
|
||
|
|
req.Header.Set("Content-Type", "application/json")
|
||
|
|
rr := httptest.NewRecorder()
|
||
|
|
|
||
|
|
handler.CreateCustomer(rr, req)
|
||
|
|
|
||
|
|
assert.Equal(t, http.StatusCreated, rr.Code)
|
||
|
|
|
||
|
|
var response map[string]interface{}
|
||
|
|
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
||
|
|
require.NoError(t, err)
|
||
|
|
assert.Equal(t, "cust-1", response["id"])
|
||
|
|
|
||
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCRMHandler_GetCustomer(t *testing.T) {
|
||
|
|
db, mock, err := sqlmock.New()
|
||
|
|
require.NoError(t, err)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
_ = NewCRMHandler(db)
|
||
|
|
|
||
|
|
mock.ExpectQuery("SELECT id, name, email, phone, company, org_number, status, source, tags, assigned_to, created_at, updated_at").
|
||
|
|
WithArgs("cust-1").
|
||
|
|
WillReturnRows(sqlmock.NewRows([]string{
|
||
|
|
"id", "name", "email", "phone", "company", "org_number", "status", "source", "tags", "assigned_to", "created_at", "updated_at",
|
||
|
|
}).AddRow(
|
||
|
|
"cust-1", "Test AB", "test@test.com", "+46701234567", "Test AB", "559141-7042", "active", "web", nil, nil, time.Now(), time.Now(),
|
||
|
|
))
|
||
|
|
|
||
|
|
// Requires chi router context for URL params — test via router in integration tests
|
||
|
|
t.Skip("Requires chi router context for URL params")
|
||
|
|
|
||
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCRMHandler_GetPipeline(t *testing.T) {
|
||
|
|
db, mock, err := sqlmock.New()
|
||
|
|
require.NoError(t, err)
|
||
|
|
defer db.Close()
|
||
|
|
|
||
|
|
handler := NewCRMHandler(db)
|
||
|
|
|
||
|
|
mock.ExpectQuery("SELECT stage, COUNT\\(\\*\\), COALESCE\\(SUM\\(value\\), 0\\)").
|
||
|
|
WillReturnRows(sqlmock.NewRows([]string{"stage", "count", "sum"}).
|
||
|
|
AddRow("prospect", 5, 100000.00).
|
||
|
|
AddRow("qualified", 3, 75000.00).
|
||
|
|
AddRow("proposal", 2, 50000.00))
|
||
|
|
|
||
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/crm/pipeline", nil)
|
||
|
|
rr := httptest.NewRecorder()
|
||
|
|
|
||
|
|
handler.GetPipeline(rr, req)
|
||
|
|
|
||
|
|
assert.Equal(t, http.StatusOK, rr.Code)
|
||
|
|
|
||
|
|
var response map[string]interface{}
|
||
|
|
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
||
|
|
require.NoError(t, err)
|
||
|
|
|
||
|
|
pipeline := response["pipeline"].([]interface{})
|
||
|
|
assert.Len(t, pipeline, 3)
|
||
|
|
|
||
|
|
assert.NoError(t, mock.ExpectationsWereMet())
|
||
|
|
}
|