191 lines
4.6 KiB
Go
191 lines
4.6 KiB
Go
package session
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSession_ID(t *testing.T) {
|
|
sess := Session{
|
|
ID: "channel:openid-123",
|
|
}
|
|
if sess.ID != "channel:openid-123" {
|
|
t.Errorf("expected ID 'channel:openid-123', got %q", sess.ID)
|
|
}
|
|
}
|
|
|
|
func TestSession_Channel(t *testing.T) {
|
|
sess := Session{
|
|
Channel: "wechat",
|
|
}
|
|
if sess.Channel != "wechat" {
|
|
t.Errorf("expected Channel 'wechat', got %q", sess.Channel)
|
|
}
|
|
}
|
|
|
|
func TestSession_OpenID(t *testing.T) {
|
|
sess := Session{
|
|
OpenID: "ou_abc123",
|
|
}
|
|
if sess.OpenID != "ou_abc123" {
|
|
t.Errorf("expected OpenID 'ou_abc123', got %q", sess.OpenID)
|
|
}
|
|
}
|
|
|
|
func TestSession_StatusConstants(t *testing.T) {
|
|
if StatusIdle != "idle" {
|
|
t.Errorf("StatusIdle: expected 'idle', got %q", StatusIdle)
|
|
}
|
|
if StatusProcessing != "processing" {
|
|
t.Errorf("StatusProcessing: expected 'processing', got %q", StatusProcessing)
|
|
}
|
|
if StatusHandoff != "handoff" {
|
|
t.Errorf("StatusHandoff: expected 'handoff', got %q", StatusHandoff)
|
|
}
|
|
if StatusClosed != "closed" {
|
|
t.Errorf("StatusClosed: expected 'closed', got %q", StatusClosed)
|
|
}
|
|
}
|
|
|
|
func TestSession_StatusTransitions(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
initial Status
|
|
transition Status
|
|
}{
|
|
{"idle to processing", StatusIdle, StatusProcessing},
|
|
{"processing to handoff", StatusProcessing, StatusHandoff},
|
|
{"handoff to closed", StatusHandoff, StatusClosed},
|
|
{"idle directly to closed", StatusIdle, StatusClosed},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
sess := Session{Status: tt.initial}
|
|
if sess.Status != tt.initial {
|
|
t.Errorf("%s: expected status %q, got %q", tt.name, tt.initial, sess.Status)
|
|
}
|
|
sess.Status = tt.transition
|
|
if sess.Status != tt.transition {
|
|
t.Errorf("%s: expected transitioned status %q, got %q", tt.name, tt.transition, sess.Status)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSession_TurnCount(t *testing.T) {
|
|
sess := Session{TurnCount: 0}
|
|
if sess.TurnCount != 0 {
|
|
t.Errorf("expected TurnCount 0, got %d", sess.TurnCount)
|
|
}
|
|
|
|
sess.TurnCount = 5
|
|
if sess.TurnCount != 5 {
|
|
t.Errorf("expected TurnCount 5, got %d", sess.TurnCount)
|
|
}
|
|
}
|
|
|
|
func TestSession_LastMessageAt(t *testing.T) {
|
|
now := time.Now()
|
|
sess := Session{LastMessageAt: now}
|
|
if !sess.LastMessageAt.Equal(now) {
|
|
t.Errorf("LastMessageAt: expected %v, got %v", now, sess.LastMessageAt)
|
|
}
|
|
}
|
|
|
|
func TestSession_Context(t *testing.T) {
|
|
now := time.Now()
|
|
sess := Session{
|
|
Context: []MessageContext{
|
|
{Direction: "inbound", Content: "hello", Timestamp: now},
|
|
{Direction: "outbound", Content: "hi there", Timestamp: now},
|
|
},
|
|
}
|
|
|
|
if len(sess.Context) != 2 {
|
|
t.Errorf("expected 2 context entries, got %d", len(sess.Context))
|
|
}
|
|
if sess.Context[0].Content != "hello" {
|
|
t.Errorf("expected first content 'hello', got %q", sess.Context[0].Content)
|
|
}
|
|
if sess.Context[1].Direction != "outbound" {
|
|
t.Errorf("expected second direction 'outbound', got %q", sess.Context[1].Direction)
|
|
}
|
|
}
|
|
|
|
func TestSession_EmptyContext(t *testing.T) {
|
|
sess := Session{Context: []MessageContext{}}
|
|
if len(sess.Context) != 0 {
|
|
t.Errorf("expected empty context, got %d entries", len(sess.Context))
|
|
}
|
|
}
|
|
|
|
func TestSession_UserID(t *testing.T) {
|
|
sess := Session{UserID: "user-456"}
|
|
if sess.UserID != "user-456" {
|
|
t.Errorf("expected UserID 'user-456', got %q", sess.UserID)
|
|
}
|
|
|
|
// UserID can be empty
|
|
sess2 := Session{}
|
|
if sess2.UserID != "" {
|
|
t.Errorf("expected empty UserID, got %q", sess2.UserID)
|
|
}
|
|
}
|
|
|
|
func TestMessageContext(t *testing.T) {
|
|
now := time.Now()
|
|
msg := MessageContext{
|
|
Direction: "inbound",
|
|
Content: "test message",
|
|
Timestamp: now,
|
|
}
|
|
|
|
if msg.Direction != "inbound" {
|
|
t.Errorf("Direction: expected 'inbound', got %q", msg.Direction)
|
|
}
|
|
if msg.Content != "test message" {
|
|
t.Errorf("Content: expected 'test message', got %q", msg.Content)
|
|
}
|
|
if !msg.Timestamp.Equal(now) {
|
|
t.Errorf("Timestamp: expected %v, got %v", now, msg.Timestamp)
|
|
}
|
|
}
|
|
|
|
func TestSession_FullLifecycle(t *testing.T) {
|
|
now := time.Now()
|
|
sess := Session{
|
|
ID: "wechat:ou_abc",
|
|
Channel: "wechat",
|
|
OpenID: "ou_abc",
|
|
Status: StatusIdle,
|
|
TurnCount: 0,
|
|
LastMessageAt: now,
|
|
Context: []MessageContext{},
|
|
}
|
|
|
|
// Idle -> Processing
|
|
sess.Status = StatusProcessing
|
|
sess.TurnCount++
|
|
if sess.Status != StatusProcessing {
|
|
t.Error("failed to transition to Processing")
|
|
}
|
|
|
|
// Add message
|
|
sess.Context = append(sess.Context, MessageContext{
|
|
Direction: "inbound",
|
|
Content: "I need help",
|
|
Timestamp: now,
|
|
})
|
|
|
|
// Processing -> Handoff
|
|
sess.Status = StatusHandoff
|
|
if sess.Status != StatusHandoff {
|
|
t.Error("failed to transition to Handoff")
|
|
}
|
|
|
|
// Handoff -> Closed
|
|
sess.Status = StatusClosed
|
|
if sess.Status != StatusClosed {
|
|
t.Error("failed to transition to Closed")
|
|
}
|
|
}
|