Skip to content

Commit 9d1ac12

Browse files
committed
fix(postgres): handle UUID byte array comparison in table assertions
PostgreSQL returns UUID columns as []byte when scanned into interface{}. The previous implementation used fmt.Sprintf("%v", v) which converts []byte to its array representation like "[49 49 49 ...]" instead of the actual string content. This caused table assertion failures when comparing UUID values: - Expected: "11111111-1111-4111-a111-111111111111" - Got: "[49 49 49 49 49 49 49 49 45 ...]" The fix adds a formatDBValue() helper function that properly converts []byte to string, enabling correct UUID comparisons in "contains" steps.
1 parent 55e8e18 commit 9d1ac12

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

internal/handler/postgres.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ func (r *Postgres) tableShouldContain(table string, expected *godog.Table) error
266266
}
267267
row := make([]string, len(columns))
268268
for i, v := range values {
269-
row[i] = fmt.Sprintf("%v", v)
269+
row[i] = formatDBValue(v)
270270
}
271271
actual = append(actual, row)
272272
}
@@ -338,5 +338,22 @@ func (r *Postgres) Cleanup(ctx context.Context) error {
338338
return nil
339339
}
340340

341+
// formatDBValue converts a database value to its string representation.
342+
// This handles special types like []byte (used for UUIDs) that need
343+
// to be converted to strings rather than byte array representations.
344+
func formatDBValue(v interface{}) string {
345+
if v == nil {
346+
return "<nil>"
347+
}
348+
switch val := v.(type) {
349+
case []byte:
350+
// PostgreSQL returns UUIDs and other binary types as []byte
351+
// Convert to string for proper comparison
352+
return string(val)
353+
default:
354+
return fmt.Sprintf("%v", v)
355+
}
356+
}
357+
341358
var _ Handler = (*Postgres)(nil)
342359
var _ SQLExecutor = (*Postgres)(nil)

internal/handler/postgres_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package handler
2+
3+
import "testing"
4+
5+
func TestFormatDBValue(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
input interface{}
9+
expected string
10+
}{
11+
{
12+
name: "nil value",
13+
input: nil,
14+
expected: "<nil>",
15+
},
16+
{
17+
name: "string value",
18+
input: "hello",
19+
expected: "hello",
20+
},
21+
{
22+
name: "int value",
23+
input: 42,
24+
expected: "42",
25+
},
26+
{
27+
name: "bool true",
28+
input: true,
29+
expected: "true",
30+
},
31+
{
32+
name: "bool false",
33+
input: false,
34+
expected: "false",
35+
},
36+
{
37+
name: "byte slice (UUID)",
38+
input: []byte("11111111-1111-4111-a111-111111111111"),
39+
expected: "11111111-1111-4111-a111-111111111111",
40+
},
41+
{
42+
name: "byte slice (simple string)",
43+
input: []byte("hello world"),
44+
expected: "hello world",
45+
},
46+
{
47+
name: "empty byte slice",
48+
input: []byte{},
49+
expected: "",
50+
},
51+
{
52+
name: "float value",
53+
input: 3.14,
54+
expected: "3.14",
55+
},
56+
}
57+
58+
for _, tt := range tests {
59+
t.Run(tt.name, func(t *testing.T) {
60+
result := formatDBValue(tt.input)
61+
if result != tt.expected {
62+
t.Errorf("formatDBValue(%v) = %q, want %q", tt.input, result, tt.expected)
63+
}
64+
})
65+
}
66+
}

0 commit comments

Comments
 (0)