package lang // Page and UI component comparison functions for parser tests func pageEqual(got, want Page) bool { if got.Name != want.Name || got.Path != want.Path || got.Layout != want.Layout { return false } if !stringPtrEqual(got.Title, want.Title) { return false } if !stringPtrEqual(got.Description, want.Description) { return false } if got.Auth != want.Auth { return false } // Compare meta tags if len(got.Meta) != len(want.Meta) { return false } for i, meta := range got.Meta { if !metaTagEqual(meta, want.Meta[i]) { return false } } // Compare elements (unified model) if len(got.Elements) != len(want.Elements) { return false } for i, element := range got.Elements { if !pageElementEqual(element, want.Elements[i]) { return false } } return true } func pageElementEqual(got, want PageElement) bool { // Both should have either a Section or Component, but not both if (got.Section == nil) != (want.Section == nil) { return false } if (got.Component == nil) != (want.Component == nil) { return false } // Compare sections if present if got.Section != nil && want.Section != nil { return sectionEqual(*got.Section, *want.Section) } // Compare components if present if got.Component != nil && want.Component != nil { return componentEqual(*got.Component, *want.Component) } return false } func metaTagEqual(got, want MetaTag) bool { return got.Name == want.Name && got.Content == want.Content } func sectionEqual(got, want Section) bool { if got.Name != want.Name { return false } if !stringPtrEqual(got.Type, want.Type) { return false } if !stringPtrEqual(got.Class, want.Class) { return false } if !stringPtrEqual(got.Label, want.Label) { return false } if got.Active != want.Active { return false } if !stringPtrEqual(got.Trigger, want.Trigger) { return false } if !stringPtrEqual(got.Position, want.Position) { return false } if !stringPtrEqual(got.Entity, want.Entity) { return false } // Extract different element types from the unified elements gotAttributes := extractSectionAttributes(got.Elements) gotComponents := extractSectionComponents(got.Elements) gotSections := extractSectionSections(got.Elements) gotWhen := extractSectionWhen(got.Elements) wantAttributes := extractSectionAttributes(want.Elements) wantComponents := extractSectionComponents(want.Elements) wantSections := extractSectionSections(want.Elements) wantWhen := extractSectionWhen(want.Elements) // Compare attributes if len(gotAttributes) != len(wantAttributes) { return false } for i, attr := range gotAttributes { if !sectionAttributeEqual(attr, wantAttributes[i]) { return false } } // Compare components if len(gotComponents) != len(wantComponents) { return false } for i, comp := range gotComponents { if !componentEqual(comp, wantComponents[i]) { return false } } // Compare nested sections if len(gotSections) != len(wantSections) { return false } for i, sect := range gotSections { if !sectionEqual(sect, wantSections[i]) { return false } } // Compare when conditions if len(gotWhen) != len(wantWhen) { return false } for i, when := range gotWhen { if !whenConditionEqual(when, wantWhen[i]) { return false } } return true } // Helper functions to extract different element types from unified elements func extractSectionAttributes(elements []SectionElement) []SectionAttribute { var attrs []SectionAttribute for _, elem := range elements { if elem.Attribute != nil { attrs = append(attrs, *elem.Attribute) } } return attrs } func extractSectionComponents(elements []SectionElement) []Component { var comps []Component for _, elem := range elements { if elem.Component != nil { comps = append(comps, *elem.Component) } } return comps } func extractSectionSections(elements []SectionElement) []Section { var sects []Section for _, elem := range elements { if elem.Section != nil { sects = append(sects, *elem.Section) } } return sects } func extractSectionWhen(elements []SectionElement) []WhenCondition { var whens []WhenCondition for _, elem := range elements { if elem.When != nil { whens = append(whens, *elem.When) } } return whens } func sectionAttributeEqual(got, want SectionAttribute) bool { return stringPtrEqual(got.DataSource, want.DataSource) && stringPtrEqual(got.Style, want.Style) && stringPtrEqual(got.Classes, want.Classes) && intPtrEqual(got.Size, want.Size) && stringPtrEqual(got.Theme, want.Theme) } func componentEqual(got, want Component) bool { if got.Type != want.Type { return false } if !stringPtrEqual(got.Entity, want.Entity) { return false } if len(got.Elements) != len(want.Elements) { return false } for i, elem := range got.Elements { if !componentElementEqual(elem, want.Elements[i]) { return false } } return true } func componentElementEqual(got, want ComponentElement) bool { // Compare attributes if (got.Attribute == nil) != (want.Attribute == nil) { return false } if got.Attribute != nil && want.Attribute != nil { if !componentAttrEqual(*got.Attribute, *want.Attribute) { return false } } // Compare fields if (got.Field == nil) != (want.Field == nil) { return false } if got.Field != nil && want.Field != nil { if !componentFieldEqual(*got.Field, *want.Field) { return false } } // Compare sections if (got.Section == nil) != (want.Section == nil) { return false } if got.Section != nil && want.Section != nil { if !sectionEqual(*got.Section, *want.Section) { return false } } // Compare buttons if (got.Button == nil) != (want.Button == nil) { return false } if got.Button != nil && want.Button != nil { if !componentButtonEqual(*got.Button, *want.Button) { return false } } // Compare when conditions if (got.When == nil) != (want.When == nil) { return false } if got.When != nil && want.When != nil { if !whenConditionEqual(*got.When, *want.When) { return false } } return true } func componentAttrEqual(got, want ComponentAttr) bool { return stringPtrEqual(got.DataSource, want.DataSource) && stringSliceEqual(got.Fields, want.Fields) && stringSliceEqual(got.Actions, want.Actions) && stringPtrEqual(got.Style, want.Style) && stringPtrEqual(got.Classes, want.Classes) && intPtrEqual(got.PageSize, want.PageSize) && got.Validate == want.Validate } func componentFieldEqual(got, want ComponentField) bool { if got.Name != want.Name || got.Type != want.Type { return false } if len(got.Attributes) != len(want.Attributes) { return false } for i, attr := range got.Attributes { if !componentFieldAttributeEqual(attr, want.Attributes[i]) { return false } } return true } func componentFieldAttributeEqual(got, want ComponentFieldAttribute) bool { return stringPtrEqual(got.Label, want.Label) && stringPtrEqual(got.Placeholder, want.Placeholder) && got.Required == want.Required && got.Sortable == want.Sortable && got.Searchable == want.Searchable && got.Thumbnail == want.Thumbnail && stringPtrEqual(got.Default, want.Default) && stringSliceEqual(got.Options, want.Options) && stringPtrEqual(got.Accept, want.Accept) && intPtrEqual(got.Rows, want.Rows) && stringPtrEqual(got.Format, want.Format) && stringPtrEqual(got.Size, want.Size) && stringPtrEqual(got.Display, want.Display) && stringPtrEqual(got.Value, want.Value) && stringPtrEqual(got.Source, want.Source) && fieldRelationEqual(got.Relates, want.Relates) && componentValidationEqual(got.Validation, want.Validation) } func componentButtonEqual(got, want ComponentButton) bool { if got.Name != want.Name || got.Label != want.Label { return false } // Extract attributes from both buttons for comparison gotStyle, gotIcon, gotLoading, gotDisabled, gotConfirm, gotTarget, gotPosition, gotVia := extractButtonAttributesNew(got.Attributes) wantStyle, wantIcon, wantLoading, wantDisabled, wantConfirm, wantTarget, wantPosition, wantVia := extractButtonAttributesNew(want.Attributes) return stringPtrEqual(gotStyle, wantStyle) && stringPtrEqual(gotIcon, wantIcon) && stringPtrEqual(gotLoading, wantLoading) && stringPtrEqual(gotDisabled, wantDisabled) && stringPtrEqual(gotConfirm, wantConfirm) && stringPtrEqual(gotTarget, wantTarget) && stringPtrEqual(gotPosition, wantPosition) && stringPtrEqual(gotVia, wantVia) } // Helper function to extract button attributes from the new structure func extractButtonAttributesNew(attrs []ComponentButtonAttr) (*string, *string, *string, *string, *string, *string, *string, *string) { var style, icon, loading, disabled, confirm, target, position, via *string for _, attr := range attrs { if attr.Style != nil { style = &attr.Style.Value } if attr.Icon != nil { icon = &attr.Icon.Value } if attr.Loading != nil { loading = &attr.Loading.Value } if attr.Disabled != nil { disabled = &attr.Disabled.Value } if attr.Confirm != nil { confirm = &attr.Confirm.Value } if attr.Target != nil { target = &attr.Target.Value } if attr.Position != nil { position = &attr.Position.Value } if attr.Via != nil { via = &attr.Via.Value } } return style, icon, loading, disabled, confirm, target, position, via } func whenConditionEqual(got, want WhenCondition) bool { if got.Field != want.Field || got.Operator != want.Operator || got.Value != want.Value { return false } // Compare fields if len(got.Fields) != len(want.Fields) { return false } for i, field := range got.Fields { if !componentFieldEqual(field, want.Fields[i]) { return false } } // Compare sections if len(got.Sections) != len(want.Sections) { return false } for i, section := range got.Sections { if !sectionEqual(section, want.Sections[i]) { return false } } // Compare components if len(got.Components) != len(want.Components) { return false } for i, component := range got.Components { if !componentEqual(component, want.Components[i]) { return false } } // Compare buttons if len(got.Buttons) != len(want.Buttons) { return false } for i, button := range got.Buttons { if !componentButtonEqual(button, want.Buttons[i]) { return false } } return true }