add Block + Component, add TextComponent with min, max and regex validators and early NumberComponent

This commit is contained in:
2026-02-12 15:47:52 +00:00
parent 4f77702125
commit 6099538fa8
16 changed files with 488 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"fmt"
)
func MaxLength(max int) text_component.TextComponentOption {
return func(c *text_component.TextComponentConfig) {
c.Validators = append(c.Validators, func(value any) error {
s, ok := value.(string)
if !ok {
return fmt.Errorf("provided value bust be a string: %v", value)
}
if len(s) > max {
return fmt.Errorf("must be at most %d characters", max)
}
return nil
})
}
}

View File

@@ -0,0 +1,36 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"testing"
)
func TestMaxLength(t *testing.T) {
cfg := &text_component.TextComponentConfig{}
MaxLength(10)(cfg)
if len(cfg.Validators) != 1 {
t.Fatalf("expect 1 validator, got %d", len(cfg.Validators))
}
validate := cfg.Validators[0]
tests := []struct {
name string
value string
wantErr bool
}{
{"below value", "01234", false},
{"equal to value", "0123456789", false},
{"above value", "abcdefghjilkmnopqrstuvwxyz", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validate(tt.value)
if (err != nil) != tt.wantErr {
t.Errorf("validate(%v) error = %v, wantErr %v", tt.value, err, tt.wantErr)
}
})
}
}

View File

@@ -0,0 +1,21 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"fmt"
)
func MinLength(min int) text_component.TextComponentOption {
return func(c *text_component.TextComponentConfig) {
c.Validators = append(c.Validators, func(value any) error {
s, ok := value.(string)
if !ok {
return fmt.Errorf("provided value bust be a string: %v", value)
}
if len(s) < min {
return fmt.Errorf("must be at least %d characters", min)
}
return nil
})
}
}

View File

@@ -0,0 +1,36 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"testing"
)
func TestMinLength(t *testing.T) {
cfg := &text_component.TextComponentConfig{}
MinLength(10)(cfg)
if len(cfg.Validators) != 1 {
t.Fatalf("expect 1 validator, got %d", len(cfg.Validators))
}
validate := cfg.Validators[0]
tests := []struct {
name string
value string
wantErr bool
}{
{"below value", "01234", true},
{"equal to value", "0123456789", false},
{"above value", "abcdefghjilkmnopqrstuvwxyz", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validate(tt.value)
if (err != nil) != tt.wantErr {
t.Errorf("validate(%v) error = %v, wantErr %v", tt.value, err, tt.wantErr)
}
})
}
}

View File

@@ -0,0 +1,24 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"fmt"
"regexp"
)
func Regex(pattern string) text_component.TextComponentOption {
re := regexp.MustCompile(pattern)
return func(c *text_component.TextComponentConfig) {
c.Validators = append(c.Validators, func(value any) error {
s, ok := value.(string)
if !ok {
return fmt.Errorf("provided value bust be a string: %v", value)
}
if !re.MatchString(s) {
return fmt.Errorf("must match pattern %s", pattern)
}
return nil
})
}
}

View File

@@ -0,0 +1,33 @@
package text_component_validators
import (
"blocky/internal/block/text_component"
"testing"
)
func TestRegex(t *testing.T) {
cfg := &text_component.TextComponentConfig{}
Regex("^\\d+$")(cfg)
validate := cfg.Validators[0]
tests := []struct {
name string
value string
wantErr bool
}{
{"just numbers", "123", false},
{"just letters", "abc", true},
{"numbers and letters", "abc", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validate(tt.value)
if (err != nil) != tt.wantErr {
t.Errorf("validate(%v) error = %v, wantErr %v", tt.value, err, tt.wantErr)
}
})
}
}