mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-21 23:33:42 +08:00
161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
package server
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"vocat/internal/modem"
|
|
)
|
|
|
|
func TestIncomingCallNotificationTextFormatting(t *testing.T) {
|
|
now := time.Date(2026, 8, 20, 10, 30, 0, 0, time.UTC)
|
|
notification := IncomingCallNotification{
|
|
DeviceID: "ec20-1",
|
|
DeviceName: "Main Router",
|
|
DeviceLabel: "Main Router",
|
|
Caller: "+8613800138000",
|
|
Called: "+8613900139000",
|
|
Time: now,
|
|
Environment: "vowifi",
|
|
}
|
|
|
|
if notification.Title() != "收到来电" {
|
|
t.Errorf("Title() = %q, want '收到来电'", notification.Title())
|
|
}
|
|
|
|
text := notification.Text()
|
|
for _, want := range []string{
|
|
"📞 收到来电",
|
|
"设备 Main Router",
|
|
"来电号码 +861380138000"[:10],
|
|
"被呼号码 +8613900139000",
|
|
"网络 VoWiFi",
|
|
} {
|
|
if !strings.Contains(text, want) {
|
|
t.Errorf("Text() omitted %q:\n%s", want, text)
|
|
}
|
|
}
|
|
|
|
notification.Environment = "cellular"
|
|
if !strings.Contains(notification.Text(), "网络 基站直连") {
|
|
t.Errorf("Text() in cellular mode omitted '网络 基站直连':\n%s", notification.Text())
|
|
}
|
|
}
|
|
|
|
func TestIncomingCallDeduplication(t *testing.T) {
|
|
now := time.Now()
|
|
key := "test-device:+8613800000000"
|
|
|
|
// First call should not be suppressed
|
|
if shouldSuppressDuplicateCall(key, now, time.Minute) {
|
|
t.Fatal("first call unexpectedly suppressed")
|
|
}
|
|
|
|
// Immediate duplicate should be suppressed
|
|
if !shouldSuppressDuplicateCall(key, now.Add(5*time.Second), time.Minute) {
|
|
t.Fatal("duplicate call within window was not suppressed")
|
|
}
|
|
|
|
// Call after window should be allowed
|
|
if shouldSuppressDuplicateCall(key, now.Add(70*time.Second), time.Minute) {
|
|
t.Fatal("call after window was suppressed")
|
|
}
|
|
}
|
|
|
|
func TestIncomingVoiceCLCCIgnoresDataSessions(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
call map[string]any
|
|
want bool
|
|
}{
|
|
{
|
|
name: "incoming voice ringing",
|
|
call: map[string]any{"direction": 1, "state": 4, "mode": 0},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "incoming voice active",
|
|
call: map[string]any{"direction": 1, "state": 0, "mode": 0},
|
|
want: true,
|
|
},
|
|
{
|
|
name: "incoming packet data active",
|
|
call: map[string]any{"direction": 1, "state": 0, "mode": 1},
|
|
want: false,
|
|
},
|
|
{
|
|
name: "outgoing voice alerting",
|
|
call: map[string]any{"direction": 0, "state": 3, "mode": 0},
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if got := isIncomingVoiceCLCC(test.call); got != test.want {
|
|
t.Fatalf("isIncomingVoiceCLCC() = %v, want %v", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
|
|
// EC20/EC25 firmware may expose an active packet-data session in CLCC.
|
|
// It must not be treated as an incoming voice call.
|
|
dataCalls := parseCLCC(modem.Response{
|
|
Lines: []string{`+CLCC: 1,1,0,1,0,"",128`},
|
|
Final: "OK",
|
|
})
|
|
if len(dataCalls) != 1 {
|
|
t.Fatalf("parseCLCC() returned %d data calls, want 1", len(dataCalls))
|
|
}
|
|
if isIncomingVoiceCLCC(dataCalls[0]) {
|
|
t.Fatal("active packet-data CLCC record was treated as an incoming voice call")
|
|
}
|
|
}
|
|
|
|
func TestRenderCallWebhookTemplate(t *testing.T) {
|
|
now := time.Date(2026, 8, 20, 10, 30, 0, 0, time.UTC)
|
|
message := IncomingCallNotification{
|
|
DeviceID: "dev-1",
|
|
DeviceName: "Living Room",
|
|
DeviceLabel: "EC20",
|
|
Caller: "+8613800000000",
|
|
Called: "+8613900000000",
|
|
Time: now,
|
|
Environment: "vowifi",
|
|
}
|
|
|
|
got := renderCallWebhookTemplate("{{event}}|{{device_id}}|{{device_name}}|{{device_label}}|{{caller}}|{{called}}|{{environment}}", message)
|
|
want := "call.received|dev-1|Living Room|EC20|+8613800000000|+8613900000000|vowifi"
|
|
if got != want {
|
|
t.Fatalf("renderCallWebhookTemplate() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestWecomAndLarkCallValues(t *testing.T) {
|
|
location := time.FixedZone("UTC+8", 8*60*60)
|
|
now := time.Date(2026, 8, 20, 18, 0, 0, 0, location)
|
|
message := IncomingCallNotification{
|
|
DeviceID: "dev-1",
|
|
DeviceName: "Office",
|
|
DeviceLabel: "EC20-Office",
|
|
Caller: "+8613800138000",
|
|
Called: "+8613900139000",
|
|
Time: now,
|
|
Environment: "cellular",
|
|
}
|
|
|
|
wecom := wecomCallValues(message)
|
|
if wecom["event"] != "call.received" || wecom["title"] != "收到来电" || wecom["number"] != "+8613800138000" {
|
|
t.Fatalf("wecomCallValues = %#v", wecom)
|
|
}
|
|
if !strings.Contains(wecom["message"], "网络 基站直连") {
|
|
t.Fatalf("wecomCallValues message omitted network: %s", wecom["message"])
|
|
}
|
|
|
|
lark := larkCallValues(message)
|
|
if lark["event"] != "call.received" || lark["title"] != "收到来电" || lark["device_label"] != "EC20-Office" {
|
|
t.Fatalf("larkCallValues = %#v", lark)
|
|
}
|
|
}
|