305 lines
7.3 KiB
Go
305 lines
7.3 KiB
Go
package lang
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestAdvancedParsingFeatures(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
want AST
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "component with conditional rendering",
|
|
input: `page ConditionalForm at "/conditional" layout MainLayout
|
|
component UserForm for User
|
|
field role type select options ["admin", "user"]
|
|
|
|
when role equals "admin"
|
|
field permissions type multiselect label "Admin Permissions"
|
|
options ["users.manage", "posts.manage"]`,
|
|
want: AST{
|
|
Definitions: []Definition{
|
|
{
|
|
Page: &Page{
|
|
Name: "ConditionalForm",
|
|
Path: "/conditional",
|
|
Layout: "MainLayout",
|
|
Components: []Component{
|
|
{
|
|
Type: "UserForm",
|
|
Entity: stringPtr("User"),
|
|
Elements: []ComponentElement{
|
|
{
|
|
Field: &ComponentField{
|
|
Name: "role",
|
|
Type: "select",
|
|
Attributes: []ComponentFieldAttribute{
|
|
{Options: []string{"admin", "user"}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Condition: &WhenCondition{
|
|
Field: "role",
|
|
Operator: "equals",
|
|
Value: "admin",
|
|
Fields: []ComponentField{
|
|
{
|
|
Name: "permissions",
|
|
Type: "multiselect",
|
|
Attributes: []ComponentFieldAttribute{
|
|
{Label: stringPtr("Admin Permissions")},
|
|
{Options: []string{"users.manage", "posts.manage"}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "page with tabs container",
|
|
input: `page Dashboard at "/dashboard" layout MainLayout
|
|
container tabs
|
|
tab overview label "Overview" active
|
|
component StatsCards
|
|
tab users label "Users"
|
|
component UserTable for User`,
|
|
want: AST{
|
|
Definitions: []Definition{
|
|
{
|
|
Page: &Page{
|
|
Name: "Dashboard",
|
|
Path: "/dashboard",
|
|
Layout: "MainLayout",
|
|
Containers: []Container{
|
|
{
|
|
Type: "tabs",
|
|
Tabs: []Tab{
|
|
{
|
|
Name: "overview",
|
|
Label: "Overview",
|
|
Active: true,
|
|
Components: []Component{
|
|
{
|
|
Type: "StatsCards",
|
|
Elements: []ComponentElement{},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "users",
|
|
Label: "Users",
|
|
Components: []Component{
|
|
{
|
|
Type: "UserTable",
|
|
Entity: stringPtr("User"),
|
|
Elements: []ComponentElement{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "page with modal",
|
|
input: `page UserList at "/users" layout MainLayout
|
|
modal CreateUserModal trigger "create-user"
|
|
component UserForm for User
|
|
field email type text required
|
|
button save label "Create" via "/users"`,
|
|
want: AST{
|
|
Definitions: []Definition{
|
|
{
|
|
Page: &Page{
|
|
Name: "UserList",
|
|
Path: "/users",
|
|
Layout: "MainLayout",
|
|
Modals: []Modal{
|
|
{
|
|
Name: "CreateUserModal",
|
|
Trigger: "create-user",
|
|
Components: []Component{
|
|
{
|
|
Type: "UserForm",
|
|
Entity: stringPtr("User"),
|
|
Elements: []ComponentElement{
|
|
{
|
|
Field: &ComponentField{
|
|
Name: "email",
|
|
Type: "text",
|
|
Attributes: []ComponentFieldAttribute{
|
|
{Required: true},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Action: &ComponentButtonAttr{
|
|
Name: "save",
|
|
Label: "Create",
|
|
Via: stringPtr("/users"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "page with master-detail layout",
|
|
input: `page PostManagement at "/admin/posts" layout AdminLayout
|
|
layout "master-detail"
|
|
|
|
master PostList
|
|
component Table for Post
|
|
field title type text sortable
|
|
|
|
detail PostEditor trigger "edit"
|
|
component Form for Post
|
|
field title type text required`,
|
|
want: AST{
|
|
Definitions: []Definition{
|
|
{
|
|
Page: &Page{
|
|
Name: "PostManagement",
|
|
Path: "/admin/posts",
|
|
Layout: "AdminLayout",
|
|
LayoutType: stringPtr("master-detail"),
|
|
MasterDetail: &MasterDetail{
|
|
Master: &MasterSection{
|
|
Name: "PostList",
|
|
Components: []Component{
|
|
{
|
|
Type: "Table",
|
|
Entity: stringPtr("Post"),
|
|
Elements: []ComponentElement{
|
|
{
|
|
Field: &ComponentField{
|
|
Name: "title",
|
|
Type: "text",
|
|
Attributes: []ComponentFieldAttribute{
|
|
{Sortable: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Detail: &DetailSection{
|
|
Name: "PostEditor",
|
|
Trigger: stringPtr("edit"),
|
|
Components: []Component{
|
|
{
|
|
Type: "Form",
|
|
Entity: stringPtr("Post"),
|
|
Elements: []ComponentElement{
|
|
{
|
|
Field: &ComponentField{
|
|
Name: "title",
|
|
Type: "text",
|
|
Attributes: []ComponentFieldAttribute{
|
|
{Required: true},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid syntax should error",
|
|
input: `invalid syntax here`,
|
|
want: AST{},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := ParseInput(tt.input)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("ParseInput() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
if !tt.wantErr && !astEqual(got, tt.want) {
|
|
t.Errorf("ParseInput() mismatch.\nGot: %+v\nWant: %+v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Test for conditional rendering
|
|
func TestConditionalRendering(t *testing.T) {
|
|
input := `page ConditionalTest at "/test" layout MainLayout
|
|
component Form for User
|
|
field role type select options ["admin", "user"]
|
|
|
|
when role equals "admin"
|
|
field permissions type multiselect options ["manage_users", "manage_posts"]
|
|
section admin_tools
|
|
field audit_log type toggle`
|
|
|
|
ast, err := ParseInput(input)
|
|
if err != nil {
|
|
t.Fatalf("Failed to parse: %v", err)
|
|
}
|
|
|
|
component := ast.Definitions[0].Page.Components[0]
|
|
|
|
// Extract conditions from elements
|
|
var conditions []WhenCondition
|
|
for _, element := range component.Elements {
|
|
if element.Condition != nil {
|
|
conditions = append(conditions, *element.Condition)
|
|
}
|
|
}
|
|
|
|
if len(conditions) != 1 {
|
|
t.Errorf("Expected 1 condition, got %d", len(conditions))
|
|
}
|
|
|
|
condition := conditions[0]
|
|
if condition.Field != "role" || condition.Operator != "equals" || condition.Value != "admin" {
|
|
t.Error("Condition parameters incorrect")
|
|
}
|
|
|
|
if len(condition.Fields) != 1 {
|
|
t.Errorf("Expected 1 conditional field, got %d", len(condition.Fields))
|
|
}
|
|
|
|
if len(condition.Sections) != 1 {
|
|
t.Errorf("Expected 1 conditional section, got %d", len(condition.Sections))
|
|
}
|
|
}
|