1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
package tuigen
import (
"testing"
)
func TestLexer_GoExpressions(t *testing.T) {
type tc struct {
input string
literal string
}
tests := map[string]tc{
"simple": {input: "{x}", literal: "x"},
"with spaces": {input: "{ x + y }", literal: " x + y "},
"nested braces": {input: "{map[string]int{}}", literal: "map[string]int{}"},
"deeply nested": {input: "{func() { if true { x } }()}", literal: "func() { if true { x } }()"},
"with string": {input: `{fmt.Sprintf("%d", x)}`, literal: `fmt.Sprintf("%d", x)`},
"with raw string": {input: "{`hello`}", literal: "`hello`"},
"function call": {input: "{onClick()}", literal: "onClick()"},
"method call": {input: "{s.Method(a, b)}", literal: "s.Method(a, b)"},
"struct literal": {input: "{Point{X: 1, Y: 2}}", literal: "Point{X: 1, Y: 2}"},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
l := NewLexer("test.gsx", tt.input)
brace := l.Next()
if brace.Type != TokenLBrace {
t.Fatalf("expected TokenLBrace, got %v", brace.Type)
}
tok := l.ReadGoExpr()
if tok.Type != TokenGoExpr {
t.Errorf("Type = %v, want TokenGoExpr", tok.Type)
}
if tok.Literal != tt.literal {
t.Errorf("Literal = %q, want %q", tok.Literal, tt.literal)
}
})
}
}
func TestLexer_ReadBalancedBracesFrom(t *testing.T) {
type tc struct {
input string
startPos int
expected string
hasError bool
}
tests := map[string]tc{
"simple": {input: "{x}", startPos: 0, expected: "x"},
"with spaces": {input: "{ x + y }", startPos: 0, expected: " x + y "},
"nested braces": {input: "{map[string]int{}}", startPos: 0, expected: "map[string]int{}"},
"with string": {input: `{fmt.Sprintf("%d", x)}`, startPos: 0, expected: `fmt.Sprintf("%d", x)`},
"with raw string": {input: "{`hello`}", startPos: 0, expected: "`hello`"},
"deeply nested": {input: "{func() { if true { x } }()}", startPos: 0, expected: "func() { if true { x } }()"},
"not at brace": {input: "abc{x}", startPos: 0, hasError: true},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
l := NewLexer("test.tui", tt.input)
result, err := l.ReadBalancedBracesFrom(tt.startPos)
if tt.hasError {
if err == nil {
t.Error("expected error, got nil")
}
return
}
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if result != tt.expected {
t.Errorf("ReadBalancedBracesFrom(%d) = %q, want %q", tt.startPos, result, tt.expected)
}
})
}
}
func TestLexer_ComponentCall(t *testing.T) {
type tc struct {
input string
wantType TokenType
wantLiteral string
}
tests := map[string]tc{
"simple call": {
input: "@Card",
wantType: TokenAtCall,
wantLiteral: "Card",
},
"multi-word name": {
input: "@MyCustomComponent",
wantType: TokenAtCall,
wantLiteral: "MyCustomComponent",
},
"header component": {
input: "@Header",
wantType: TokenAtCall,
wantLiteral: "Header",
},
"lowercase is component expr": {
input: "@unknown",
wantType: TokenAtExpr,
wantLiteral: "unknown",
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
l := NewLexer("test.gsx", tt.input)
tok := l.Next()
if tok.Type != tt.wantType {
t.Errorf("token type = %v, want %v", tok.Type, tt.wantType)
}
if tt.wantLiteral != "" && tok.Literal != tt.wantLiteral {
t.Errorf("token literal = %q, want %q", tok.Literal, tt.wantLiteral)
}
})
}
}
|