- Add auth handlers (signup, login, logout, account management) with bcrypt - Add client, customer, service, scheduling, payment, question, answer handlers - Add dashboard, monthly report, and lead pipeline pages - Add UTF-8 middleware to force charset on HTML responses - Add config package with env-based overrides for DB path, secrets, endpoints - Add parser package for WhatsApp message ingestion - Add clean-arch layers: pkg/domain, pkg/repo, pkg/usecase for leads - Add cmd/migrate utility for DB migrations - Add Makefile, README, run-tests.sh, and dev scripts - Update docker-compose.yml with memory limits - Update .air.toml to exclude DB files and stop on errors - Update whatsapp-sync dependencies and add src/index.js entrypoint - Add whatsme standalone WhatsApp reader app (source only) - Untrack .opencode-sandbox/data/go-crm.db from git history - Expand root .gitignore: ngrok, tmp dirs, sandbox DBs, compiled binaries
118 lines
3.0 KiB
Go
118 lines
3.0 KiB
Go
package parser_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"go-crm/internal/parser"
|
|
)
|
|
|
|
func TestExtractService_KnownKeywords(t *testing.T) {
|
|
keywords := map[string]string{
|
|
"head spa": "Head Spa",
|
|
"head-spa": "Head Spa",
|
|
"headspa": "Head Spa",
|
|
"massagem": "Massagem completa",
|
|
"massagem completa": "Massagem completa",
|
|
"drenagem": "Drenagem linfatica",
|
|
"linfática": "Drenagem linfatica",
|
|
"hydra": "Hydra Boost",
|
|
"hydra boost": "Hydra Boost",
|
|
"henna": "Design Henna",
|
|
"design henna": "Design Henna",
|
|
"masculino": "Masculino",
|
|
"masc": "Masculino",
|
|
}
|
|
|
|
mapping := map[string]string{
|
|
"head spa": "Head Spa",
|
|
"head-spa": "Head Spa",
|
|
"headspa": "Head Spa",
|
|
"massagem": "Massagem completa",
|
|
"massagem completa": "Massagem completa",
|
|
"drenagem": "Drenagem linfatica",
|
|
"linfática": "Drenagem linfatica",
|
|
"hydra": "Hydra Boost",
|
|
"hydra boost": "Hydra Boost",
|
|
"henna": "Design Henna",
|
|
"design henna": "Design Henna",
|
|
"masculino": "Masculino",
|
|
"masc": "Masculino",
|
|
}
|
|
|
|
for kw, expected := range keywords {
|
|
// Build messages in Portuguese with the keyword embedded in natural phrasing.
|
|
messages := []string{
|
|
"Olá, gostaria de agendar um " + kw,
|
|
"Boa tarde! Quero fazer " + kw + " por favor",
|
|
"Quanto custa " + kw + "?",
|
|
kw,
|
|
}
|
|
for _, msg := range messages {
|
|
got := parser.ExtractService(msg, mapping)
|
|
if got != expected {
|
|
t.Errorf("message %q with keyword %q: got %q, want %q", msg, kw, got, expected)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExtractService_UnknownMessage_ReturnsNaoEspecificou(t *testing.T) {
|
|
mapping := map[string]string{
|
|
"massagem": "Massagem completa",
|
|
}
|
|
|
|
messages := []string{
|
|
"Olá, tudo bem?",
|
|
"Qual o horário de funcionamento?",
|
|
"Vocês atendem no sábado?",
|
|
"",
|
|
}
|
|
|
|
for _, msg := range messages {
|
|
got := parser.ExtractService(msg, mapping)
|
|
if got != "Não especificou" {
|
|
t.Errorf("message %q: got %q, want %q", msg, got, "Não especificou")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExtractService_CaseInsensitive(t *testing.T) {
|
|
mapping := map[string]string{
|
|
"head spa": "Head Spa",
|
|
"henna": "Design Henna",
|
|
}
|
|
|
|
cases := map[string]string{
|
|
"Quero HEAD SPA": "Head Spa",
|
|
"HENNA por favor": "Design Henna",
|
|
"Head Spa agora": "Head Spa",
|
|
}
|
|
|
|
for msg, expected := range cases {
|
|
got := parser.ExtractService(msg, mapping)
|
|
if got != expected {
|
|
t.Errorf("message %q: got %q, want %q", msg, got, expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNormalizePhone(t *testing.T) {
|
|
cases := []struct {
|
|
raw string
|
|
want string
|
|
}{
|
|
{"5511999999999@s.whatsapp.net", "+5511999999999"},
|
|
{"5511999999999", "+5511999999999"},
|
|
{"+5511999999999", "+5511999999999"},
|
|
{"55 11 99999-9999", "+5511999999999"},
|
|
{"11999999999", "+11999999999"},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
got := parser.NormalizePhone(c.raw)
|
|
if got != c.want {
|
|
t.Errorf("NormalizePhone(%q) = %q, want %q", c.raw, got, c.want)
|
|
}
|
|
}
|
|
}
|