mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-17 16:10:09 +01:00
440 lines
11 KiB
Go
440 lines
11 KiB
Go
package changelog
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewValidator(t *testing.T) {
|
|
validator := NewValidator()
|
|
if validator == nil {
|
|
t.Fatal("NewValidator() returned nil")
|
|
}
|
|
if validator.sectionHeaderRegex == nil {
|
|
t.Error("sectionHeaderRegex not initialized")
|
|
}
|
|
if validator.bulletPointRegex == nil {
|
|
t.Error("bulletPointRegex not initialized")
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_ValidContent(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
## Added
|
|
- Add support for custom window icons in application options
|
|
- Add new SetWindowIcon() method to runtime API (#1234)
|
|
|
|
## Changed
|
|
- Update minimum Go version requirement to 1.21
|
|
- Improve error messages for invalid configuration files
|
|
|
|
## Fixed
|
|
- Fix memory leak in event system during window close operations (#5678)
|
|
- Fix crash when using context menus on Linux with Wayland`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if !result.Valid {
|
|
t.Errorf("ValidateContent() should be valid, got errors: %s", result.GetValidationSummary())
|
|
}
|
|
if len(result.Errors) != 0 {
|
|
t.Errorf("Expected 0 errors, got %d", len(result.Errors))
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_InvalidSectionHeaders(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
## InvalidSection
|
|
- Some content
|
|
|
|
### Added
|
|
- This should be ## not ###
|
|
|
|
##Added
|
|
- Missing space after ##`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if result.Valid {
|
|
t.Error("ValidateContent() should be invalid for malformed section headers")
|
|
}
|
|
|
|
// Should have errors for invalid section headers
|
|
foundInvalidSection := false
|
|
foundMissingSpace := false
|
|
foundWrongLevel := false
|
|
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "InvalidSection") {
|
|
foundInvalidSection = true
|
|
}
|
|
if strings.Contains(err.Message, "##Added") {
|
|
foundMissingSpace = true
|
|
}
|
|
if strings.Contains(err.Message, "### Added") {
|
|
foundWrongLevel = true
|
|
}
|
|
}
|
|
|
|
if !foundInvalidSection {
|
|
t.Error("Should have error for invalid section name")
|
|
}
|
|
if !foundMissingSpace {
|
|
t.Error("Should have error for missing space after ##")
|
|
}
|
|
if !foundWrongLevel {
|
|
t.Error("Should have error for wrong header level")
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_BulletPointsOutsideSection(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
- This bullet point is outside any section
|
|
|
|
## Added
|
|
- This one is properly inside a section`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if result.Valid {
|
|
t.Error("ValidateContent() should be invalid for bullet points outside sections")
|
|
}
|
|
|
|
foundOutsideError := false
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "bullet point found outside of any section") {
|
|
foundOutsideError = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundOutsideError {
|
|
t.Error("Should have error for bullet point outside section")
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_EmptyBulletPoints(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
## Added
|
|
- Valid bullet point
|
|
-
|
|
-
|
|
- Another valid bullet point`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if result.Valid {
|
|
t.Error("ValidateContent() should be invalid for empty bullet points")
|
|
}
|
|
|
|
emptyBulletErrors := 0
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "empty bullet point content") {
|
|
emptyBulletErrors++
|
|
}
|
|
}
|
|
|
|
if emptyBulletErrors != 2 {
|
|
t.Errorf("Expected 2 empty bullet point errors, got %d", emptyBulletErrors)
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_MalformedBulletPoints(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
## Added
|
|
- Valid bullet point
|
|
-Invalid bullet point (no space)
|
|
* Valid asterisk bullet
|
|
*Invalid asterisk bullet (no space)`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if result.Valid {
|
|
t.Error("ValidateContent() should be invalid for malformed bullet points")
|
|
}
|
|
|
|
malformedErrors := 0
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "malformed bullet point") {
|
|
malformedErrors++
|
|
}
|
|
}
|
|
|
|
if malformedErrors != 2 {
|
|
t.Errorf("Expected 2 malformed bullet point errors, got %d", malformedErrors)
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_NoValidSections(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
Some random content without proper sections.
|
|
|
|
More content here.`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if result.Valid {
|
|
t.Error("ValidateContent() should be invalid when no valid sections found")
|
|
}
|
|
|
|
foundNoSectionsError := false
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "no valid changelog sections found") {
|
|
foundNoSectionsError = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundNoSectionsError {
|
|
t.Error("Should have error for no valid sections")
|
|
}
|
|
}
|
|
|
|
func TestValidateContent_WithExampleSection(t *testing.T) {
|
|
validator := NewValidator()
|
|
content := `# Unreleased Changes
|
|
|
|
## Added
|
|
- Real feature addition
|
|
|
|
---
|
|
|
|
### Example Entries:
|
|
|
|
**Added:**
|
|
- Example feature that should be ignored
|
|
- Another example that should be ignored`
|
|
|
|
result := validator.ValidateContent(content)
|
|
if !result.Valid {
|
|
t.Errorf("ValidateContent() should be valid when example section is present, got errors: %s", result.GetValidationSummary())
|
|
}
|
|
}
|
|
|
|
func TestValidateEntry_ValidEntry(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{
|
|
Added: []string{"Add support for custom window icons in application options"},
|
|
Changed: []string{"Update minimum Go version requirement to 1.21"},
|
|
Fixed: []string{"Fix memory leak in event system during window close operations"},
|
|
}
|
|
|
|
result := validator.ValidateEntry(entry)
|
|
if !result.Valid {
|
|
t.Errorf("ValidateEntry() should be valid, got errors: %s", result.GetValidationSummary())
|
|
}
|
|
}
|
|
|
|
func TestValidateEntry_EmptyEntry(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{}
|
|
|
|
result := validator.ValidateEntry(entry)
|
|
if result.Valid {
|
|
t.Error("ValidateEntry() should be invalid for empty entry")
|
|
}
|
|
|
|
foundNoContentError := false
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "changelog entry has no content") {
|
|
foundNoContentError = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !foundNoContentError {
|
|
t.Error("Should have error for empty entry")
|
|
}
|
|
}
|
|
|
|
func TestValidateEntry_ShortContent(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{
|
|
Added: []string{"Short", "Add feature with proper length description"},
|
|
Fixed: []string{"Fix bug"},
|
|
}
|
|
|
|
result := validator.ValidateEntry(entry)
|
|
if result.Valid {
|
|
t.Error("ValidateEntry() should be invalid for short content")
|
|
}
|
|
|
|
shortContentErrors := 0
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "bullet point content too short") {
|
|
shortContentErrors++
|
|
}
|
|
}
|
|
|
|
if shortContentErrors != 2 {
|
|
t.Errorf("Expected 2 short content errors, got %d", shortContentErrors)
|
|
}
|
|
}
|
|
|
|
func TestValidateEntry_PlaceholderContent(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{
|
|
Added: []string{
|
|
"Add TODO feature that needs implementation",
|
|
"Add proper feature with good description",
|
|
"This is just a placeholder for now",
|
|
"FIXME: need to write proper description",
|
|
},
|
|
Fixed: []string{
|
|
"Fix example bug that was reported",
|
|
"TBD - will add description later",
|
|
},
|
|
}
|
|
|
|
result := validator.ValidateEntry(entry)
|
|
if result.Valid {
|
|
t.Error("ValidateEntry() should be invalid for placeholder content")
|
|
}
|
|
|
|
placeholderErrors := 0
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "placeholder text") {
|
|
placeholderErrors++
|
|
}
|
|
}
|
|
|
|
// Expecting 4 placeholder errors: TODO, placeholder, example, TBD
|
|
// FIXME should also be caught but let's check what we actually get
|
|
if placeholderErrors < 2 {
|
|
t.Errorf("Expected at least 2 placeholder errors, got %d", placeholderErrors)
|
|
}
|
|
}
|
|
|
|
func TestValidateEntry_EmptyItems(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{
|
|
Added: []string{
|
|
"Valid addition with proper description",
|
|
"",
|
|
" ",
|
|
},
|
|
Fixed: []string{
|
|
"",
|
|
"Valid fix with proper description",
|
|
},
|
|
}
|
|
|
|
result := validator.ValidateEntry(entry)
|
|
if result.Valid {
|
|
t.Error("ValidateEntry() should be invalid for empty items")
|
|
}
|
|
|
|
emptyItemErrors := 0
|
|
for _, err := range result.Errors {
|
|
if strings.Contains(err.Message, "empty item") {
|
|
emptyItemErrors++
|
|
}
|
|
}
|
|
|
|
if emptyItemErrors != 3 {
|
|
t.Errorf("Expected 3 empty item errors, got %d", emptyItemErrors)
|
|
}
|
|
}
|
|
|
|
func TestValidateRequiredSections_HasContent(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{
|
|
Added: []string{"Add new feature"},
|
|
}
|
|
|
|
result := validator.ValidateRequiredSections(entry)
|
|
if !result.Valid {
|
|
t.Errorf("ValidateRequiredSections() should be valid when entry has content, got errors: %s", result.GetValidationSummary())
|
|
}
|
|
}
|
|
|
|
func TestValidateRequiredSections_EmptyEntry(t *testing.T) {
|
|
validator := NewValidator()
|
|
entry := &ChangelogEntry{}
|
|
|
|
result := validator.ValidateRequiredSections(entry)
|
|
// Currently, we don't enforce required sections, so this should pass
|
|
if !result.Valid {
|
|
t.Errorf("ValidateRequiredSections() should be valid (no strict requirements), got errors: %s", result.GetValidationSummary())
|
|
}
|
|
}
|
|
|
|
func TestValidationError_Error(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
err ValidationError
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Error with line number",
|
|
err: ValidationError{
|
|
Field: "test_field",
|
|
Message: "test message",
|
|
Line: 42,
|
|
},
|
|
expected: "validation error at line 42 in test_field: test message",
|
|
},
|
|
{
|
|
name: "Error without line number",
|
|
err: ValidationError{
|
|
Field: "test_field",
|
|
Message: "test message",
|
|
Line: 0,
|
|
},
|
|
expected: "validation error in test_field: test message",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.err.Error(); got != tt.expected {
|
|
t.Errorf("ValidationError.Error() = %v, want %v", got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidationResult_GetValidationSummary(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
result ValidationResult
|
|
contains []string
|
|
}{
|
|
{
|
|
name: "Valid result",
|
|
result: ValidationResult{
|
|
Valid: true,
|
|
Errors: []ValidationError{},
|
|
},
|
|
contains: []string{"Validation passed"},
|
|
},
|
|
{
|
|
name: "Invalid result with errors",
|
|
result: ValidationResult{
|
|
Valid: false,
|
|
Errors: []ValidationError{
|
|
{Field: "test1", Message: "error 1", Line: 1},
|
|
{Field: "test2", Message: "error 2", Line: 2},
|
|
},
|
|
},
|
|
contains: []string{"Validation failed", "2 error(s)", "error 1", "error 2"},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
summary := tt.result.GetValidationSummary()
|
|
for _, expected := range tt.contains {
|
|
if !strings.Contains(summary, expected) {
|
|
t.Errorf("GetValidationSummary() should contain '%s', got: %s", expected, summary)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|