package cassandra import ( "testing" "github.com/scylladb/gocqlx/v2/qb" "github.com/stretchr/testify/assert" ) func TestEq(t *testing.T) { tests := []struct { name string column string value any validate func(*testing.T, Condition) }{ { name: "string value", column: "name", value: "Alice", validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, "Alice", binds["name"]) }, }, { name: "int value", column: "age", value: 25, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 25, binds["age"]) }, }, { name: "nil value", column: "description", value: nil, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Nil(t, binds["description"]) }, }, { name: "empty string", column: "email", value: "", validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, "", binds["email"]) }, }, { name: "boolean value", column: "active", value: true, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, true, binds["active"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cond := Eq(tt.column, tt.value) assert.NotNil(t, cond) tt.validate(t, cond) }) } } func TestIn(t *testing.T) { tests := []struct { name string column string values []any validate func(*testing.T, Condition) }{ { name: "string values", column: "status", values: []any{"active", "pending", "completed"}, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, []any{"active", "pending", "completed"}, binds["status"]) }, }, { name: "int values", column: "ids", values: []any{1, 2, 3, 4, 5}, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, []any{1, 2, 3, 4, 5}, binds["ids"]) }, }, { name: "empty slice", column: "tags", values: []any{}, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, []any{}, binds["tags"]) }, }, { name: "single value", column: "id", values: []any{1}, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, []any{1}, binds["id"]) }, }, { name: "mixed types", column: "values", values: []any{"string", 123, true}, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, []any{"string", 123, true}, binds["values"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cond := In(tt.column, tt.values) assert.NotNil(t, cond) tt.validate(t, cond) }) } } func TestGt(t *testing.T) { tests := []struct { name string column string value any validate func(*testing.T, Condition) }{ { name: "int value", column: "age", value: 18, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 18, binds["age"]) }, }, { name: "float value", column: "price", value: 99.99, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 99.99, binds["price"]) }, }, { name: "zero value", column: "count", value: 0, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 0, binds["count"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cond := Gt(tt.column, tt.value) assert.NotNil(t, cond) tt.validate(t, cond) }) } } func TestLt(t *testing.T) { tests := []struct { name string column string value any validate func(*testing.T, Condition) }{ { name: "int value", column: "age", value: 65, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 65, binds["age"]) }, }, { name: "float value", column: "price", value: 199.99, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, 199.99, binds["price"]) }, }, { name: "negative value", column: "balance", value: -100, validate: func(t *testing.T, cond Condition) { cmp, binds := cond.Build() assert.NotNil(t, cmp) assert.Equal(t, -100, binds["balance"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cond := Lt(tt.column, tt.value) assert.NotNil(t, cond) tt.validate(t, cond) }) } } func TestCondition_Build(t *testing.T) { tests := []struct { name string cond Condition validate func(*testing.T, qb.Cmp, map[string]any) }{ { name: "Eq condition", cond: Eq("name", "test"), validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) { assert.NotNil(t, cmp) assert.Equal(t, "test", binds["name"]) }, }, { name: "In condition", cond: In("ids", []any{1, 2, 3}), validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) { assert.NotNil(t, cmp) assert.Equal(t, []any{1, 2, 3}, binds["ids"]) }, }, { name: "Gt condition", cond: Gt("age", 18), validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) { assert.NotNil(t, cmp) assert.Equal(t, 18, binds["age"]) }, }, { name: "Lt condition", cond: Lt("price", 100), validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) { assert.NotNil(t, cmp) assert.Equal(t, 100, binds["price"]) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cmp, binds := tt.cond.Build() tt.validate(t, cmp, binds) }) } } func TestQueryBuilder_Where(t *testing.T) { tests := []struct { name string condition Condition validate func(*testing.T, *queryBuilder[testUser]) }{ { name: "single condition", condition: Eq("name", "Alice"), validate: func(t *testing.T, qb *queryBuilder[testUser]) { assert.Len(t, qb.conditions, 1) }, }, { name: "multiple conditions", condition: In("status", []any{"active", "pending"}), validate: func(t *testing.T, qb *queryBuilder[testUser]) { // 添加多個條件 cond := In("status", []any{"active", "pending"}) qb.Where(Eq("name", "test")) qb.Where(cond) assert.Len(t, qb.conditions, 2) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要一個有效的 repository,但我們可以測試鏈式調用 // 實際的執行需要資料庫連接 _ = tt }) } } func TestQueryBuilder_OrderBy(t *testing.T) { tests := []struct { name string column string order Order validate func(*testing.T, *queryBuilder[testUser]) }{ { name: "ASC order", column: "created_at", order: ASC, validate: func(t *testing.T, qb *queryBuilder[testUser]) { assert.Len(t, qb.orders, 1) assert.Equal(t, "created_at", qb.orders[0].column) assert.Equal(t, ASC, qb.orders[0].order) }, }, { name: "DESC order", column: "updated_at", order: DESC, validate: func(t *testing.T, qb *queryBuilder[testUser]) { assert.Len(t, qb.orders, 1) assert.Equal(t, "updated_at", qb.orders[0].column) assert.Equal(t, DESC, qb.orders[0].order) }, }, { name: "multiple orders", column: "name", order: ASC, validate: func(t *testing.T, qb *queryBuilder[testUser]) { qb.OrderBy("created_at", DESC) qb.OrderBy("name", ASC) assert.Len(t, qb.orders, 2) }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要一個有效的 repository _ = tt }) } } func TestQueryBuilder_Limit(t *testing.T) { tests := []struct { name string limit int expected int }{ { name: "positive limit", limit: 10, expected: 10, }, { name: "zero limit", limit: 0, expected: 0, }, { name: "large limit", limit: 1000, expected: 1000, }, { name: "negative limit", limit: -1, expected: -1, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要一個有效的 repository _ = tt }) } } func TestQueryBuilder_Select(t *testing.T) { tests := []struct { name string columns []string expected int }{ { name: "single column", columns: []string{"name"}, expected: 1, }, { name: "multiple columns", columns: []string{"name", "email", "age"}, expected: 3, }, { name: "empty columns", columns: []string{}, expected: 0, }, { name: "duplicate columns", columns: []string{"name", "name"}, expected: 2, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要一個有效的 repository _ = tt }) } } func TestQueryBuilder_Chaining(t *testing.T) { t.Run("chain multiple methods", func(t *testing.T) { // 注意:這需要一個有效的 repository // 實際的執行需要資料庫連接 // 這裡只是展示測試結構 }) } func TestQueryBuilder_Scan_ErrorCases(t *testing.T) { tests := []struct { name string description string }{ { name: "nil destination", description: "should return error when destination is nil", }, { name: "invalid query", description: "should return error when query is invalid", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要 mock session 或實際的資料庫連接 _ = tt }) } } func TestQueryBuilder_One_ErrorCases(t *testing.T) { tests := []struct { name string description string }{ { name: "no results", description: "should return ErrNotFound when no results found", }, { name: "query error", description: "should return error when query fails", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要 mock session 或實際的資料庫連接 _ = tt }) } } func TestQueryBuilder_Count_ErrorCases(t *testing.T) { tests := []struct { name string description string }{ { name: "query error", description: "should return error when query fails", }, { name: "ErrNotFound should return 0", description: "should return 0 when ErrNotFound", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // 注意:這需要 mock session 或實際的資料庫連接 _ = tt }) } }