@@ -3539,6 +3539,313 @@ func TestValidateConfigValues(t *testing.T) {
35393539 wantErr : true ,
35403540 errorFields : []string {"required_file" , "required_file_with_invalid_base64" },
35413541 },
3542+ {
3543+ name : "regex validation: valid email passes" ,
3544+ config : kotsv1beta1.Config {
3545+ Spec : kotsv1beta1.ConfigSpec {
3546+ Groups : []kotsv1beta1.ConfigGroup {
3547+ {
3548+ Name : "group1" ,
3549+ Items : []kotsv1beta1.ConfigItem {
3550+ {
3551+ Name : "email" ,
3552+ Type : "text" ,
3553+ Validation : & kotsv1beta1.ConfigItemValidation {
3554+ Regex : & kotsv1beta1.RegexValidator {
3555+ Pattern : `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` ,
3556+ Message : "Please enter a valid email address" ,
3557+ },
3558+ },
3559+ },
3560+ },
3561+ },
3562+ },
3563+ },
3564+ },
3565+ configValues : types.AppConfigValues {
3566+ "email" : types.
AppConfigValue {
Value :
"[email protected] " },
3567+ },
3568+ wantErr : false ,
3569+ },
3570+ {
3571+ name : "regex validation: invalid input shows custom error message" ,
3572+ config : kotsv1beta1.Config {
3573+ Spec : kotsv1beta1.ConfigSpec {
3574+ Groups : []kotsv1beta1.ConfigGroup {
3575+ {
3576+ Name : "group1" ,
3577+ Items : []kotsv1beta1.ConfigItem {
3578+ {
3579+ Name : "email" ,
3580+ Type : "text" ,
3581+ Validation : & kotsv1beta1.ConfigItemValidation {
3582+ Regex : & kotsv1beta1.RegexValidator {
3583+ Pattern : `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` ,
3584+ Message : "Please enter a valid email address" ,
3585+ },
3586+ },
3587+ },
3588+ },
3589+ },
3590+ },
3591+ },
3592+ },
3593+ configValues : types.AppConfigValues {
3594+ "email" : types.AppConfigValue {Value : "invalid-email" },
3595+ },
3596+ wantErr : true ,
3597+ errorFields : []string {"email" },
3598+ },
3599+ {
3600+ name : "regex validation: invalid input shows default message when no custom message" ,
3601+ config : kotsv1beta1.Config {
3602+ Spec : kotsv1beta1.ConfigSpec {
3603+ Groups : []kotsv1beta1.ConfigGroup {
3604+ {
3605+ Name : "group1" ,
3606+ Items : []kotsv1beta1.ConfigItem {
3607+ {
3608+ Name : "code" ,
3609+ Type : "text" ,
3610+ Validation : & kotsv1beta1.ConfigItemValidation {
3611+ Regex : & kotsv1beta1.RegexValidator {
3612+ Pattern : `^[A-Z]{3}$` ,
3613+ },
3614+ },
3615+ },
3616+ },
3617+ },
3618+ },
3619+ },
3620+ },
3621+ configValues : types.AppConfigValues {
3622+ "code" : types.AppConfigValue {Value : "abc" },
3623+ },
3624+ wantErr : true ,
3625+ errorFields : []string {"code" },
3626+ },
3627+ {
3628+ name : "regex validation: empty values skip validation (optional fields)" ,
3629+ config : kotsv1beta1.Config {
3630+ Spec : kotsv1beta1.ConfigSpec {
3631+ Groups : []kotsv1beta1.ConfigGroup {
3632+ {
3633+ Name : "group1" ,
3634+ Items : []kotsv1beta1.ConfigItem {
3635+ {
3636+ Name : "optional_email" ,
3637+ Type : "text" ,
3638+ Validation : & kotsv1beta1.ConfigItemValidation {
3639+ Regex : & kotsv1beta1.RegexValidator {
3640+ Pattern : `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` ,
3641+ },
3642+ },
3643+ },
3644+ },
3645+ },
3646+ },
3647+ },
3648+ },
3649+ configValues : types.AppConfigValues {
3650+ "optional_email" : types.AppConfigValue {Value : "" },
3651+ },
3652+ wantErr : false ,
3653+ },
3654+ {
3655+ name : "regex validation: password fields use ValuePlaintext" ,
3656+ config : kotsv1beta1.Config {
3657+ Spec : kotsv1beta1.ConfigSpec {
3658+ Groups : []kotsv1beta1.ConfigGroup {
3659+ {
3660+ Name : "group1" ,
3661+ Items : []kotsv1beta1.ConfigItem {
3662+ {
3663+ Name : "strong_password" ,
3664+ Type : "password" ,
3665+ Validation : & kotsv1beta1.ConfigItemValidation {
3666+ Regex : & kotsv1beta1.RegexValidator {
3667+ Pattern : `^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$` ,
3668+ Message : "Password must be at least 8 characters with uppercase, lowercase, and number" ,
3669+ },
3670+ },
3671+ },
3672+ },
3673+ },
3674+ },
3675+ },
3676+ },
3677+ configValues : types.AppConfigValues {
3678+ "strong_password" : types.AppConfigValue {Value : "weak" },
3679+ },
3680+ wantErr : true ,
3681+ errorFields : []string {"strong_password" },
3682+ },
3683+ {
3684+ name : "regex validation: textarea type validates correctly" ,
3685+ config : kotsv1beta1.Config {
3686+ Spec : kotsv1beta1.ConfigSpec {
3687+ Groups : []kotsv1beta1.ConfigGroup {
3688+ {
3689+ Name : "group1" ,
3690+ Items : []kotsv1beta1.ConfigItem {
3691+ {
3692+ Name : "json_config" ,
3693+ Type : "textarea" ,
3694+ Validation : & kotsv1beta1.ConfigItemValidation {
3695+ Regex : & kotsv1beta1.RegexValidator {
3696+ Pattern : `^\{.*\}$` ,
3697+ Message : "Must be a valid JSON object" ,
3698+ },
3699+ },
3700+ },
3701+ },
3702+ },
3703+ },
3704+ },
3705+ },
3706+ configValues : types.AppConfigValues {
3707+ "json_config" : types.AppConfigValue {Value : `{"key": "value"}` },
3708+ },
3709+ wantErr : false ,
3710+ },
3711+ {
3712+ name : "regex validation: when=false items skip validation" ,
3713+ config : kotsv1beta1.Config {
3714+ Spec : kotsv1beta1.ConfigSpec {
3715+ Groups : []kotsv1beta1.ConfigGroup {
3716+ {
3717+ Name : "group1" ,
3718+ Items : []kotsv1beta1.ConfigItem {
3719+ {
3720+ Name : "disabled_field" ,
3721+ Type : "text" ,
3722+ When : "false" ,
3723+ Validation : & kotsv1beta1.ConfigItemValidation {
3724+ Regex : & kotsv1beta1.RegexValidator {
3725+ Pattern : `^valid$` ,
3726+ },
3727+ },
3728+ },
3729+ },
3730+ },
3731+ },
3732+ },
3733+ },
3734+ configValues : types.AppConfigValues {
3735+ "disabled_field" : types.AppConfigValue {Value : "invalid" },
3736+ },
3737+ wantErr : false ,
3738+ },
3739+ {
3740+ name : "regex validation: unsupported types skip validation" ,
3741+ config : kotsv1beta1.Config {
3742+ Spec : kotsv1beta1.ConfigSpec {
3743+ Groups : []kotsv1beta1.ConfigGroup {
3744+ {
3745+ Name : "group1" ,
3746+ Items : []kotsv1beta1.ConfigItem {
3747+ {
3748+ Name : "bool_field" ,
3749+ Type : "bool" ,
3750+ Validation : & kotsv1beta1.ConfigItemValidation {
3751+ Regex : & kotsv1beta1.RegexValidator {
3752+ Pattern : `^0$` ,
3753+ },
3754+ },
3755+ },
3756+ {
3757+ Name : "file_field" ,
3758+ Type : "file" ,
3759+ Validation : & kotsv1beta1.ConfigItemValidation {
3760+ Regex : & kotsv1beta1.RegexValidator {
3761+ Pattern : `^valid$` ,
3762+ },
3763+ },
3764+ },
3765+ {
3766+ Name : "radio_field" ,
3767+ Type : "radio" ,
3768+ Validation : & kotsv1beta1.ConfigItemValidation {
3769+ Regex : & kotsv1beta1.RegexValidator {
3770+ Pattern : `^valid$` ,
3771+ },
3772+ },
3773+ },
3774+ },
3775+ },
3776+ },
3777+ },
3778+ },
3779+ configValues : types.AppConfigValues {
3780+ "bool_field" : types.AppConfigValue {Value : "1" },
3781+ "file_field" : types.AppConfigValue {Value : "aW52YWxpZA==" }, // base64 "invalid"
3782+ "radio_field" : types.AppConfigValue {Value : "invalid" },
3783+ },
3784+ wantErr : false ,
3785+ },
3786+ {
3787+ name : "regex validation: multiple validation errors (required + regex)" ,
3788+ config : kotsv1beta1.Config {
3789+ Spec : kotsv1beta1.ConfigSpec {
3790+ Groups : []kotsv1beta1.ConfigGroup {
3791+ {
3792+ Name : "group1" ,
3793+ Items : []kotsv1beta1.ConfigItem {
3794+ {
3795+ Name : "email" ,
3796+ Type : "text" ,
3797+ Required : true ,
3798+ },
3799+ {
3800+ Name : "phone" ,
3801+ Type : "text" ,
3802+ Validation : & kotsv1beta1.ConfigItemValidation {
3803+ Regex : & kotsv1beta1.RegexValidator {
3804+ Pattern : `^\d{3}-\d{3}-\d{4}$` ,
3805+ Message : "Phone must be in format XXX-XXX-XXXX" ,
3806+ },
3807+ },
3808+ },
3809+ },
3810+ },
3811+ },
3812+ },
3813+ },
3814+ configValues : types.AppConfigValues {
3815+ "email" : types.AppConfigValue {Value : "" },
3816+ "phone" : types.AppConfigValue {Value : "123-456" },
3817+ },
3818+ wantErr : true ,
3819+ errorFields : []string {"email" , "phone" },
3820+ },
3821+ {
3822+ name : "regex validation: invalid regex pattern returns error" ,
3823+ config : kotsv1beta1.Config {
3824+ Spec : kotsv1beta1.ConfigSpec {
3825+ Groups : []kotsv1beta1.ConfigGroup {
3826+ {
3827+ Name : "group1" ,
3828+ Items : []kotsv1beta1.ConfigItem {
3829+ {
3830+ Name : "test" ,
3831+ Type : "text" ,
3832+ Validation : & kotsv1beta1.ConfigItemValidation {
3833+ Regex : & kotsv1beta1.RegexValidator {
3834+ Pattern : `[invalid(` ,
3835+ },
3836+ },
3837+ },
3838+ },
3839+ },
3840+ },
3841+ },
3842+ },
3843+ configValues : types.AppConfigValues {
3844+ "test" : types.AppConfigValue {Value : "value" },
3845+ },
3846+ wantErr : true ,
3847+ errorFields : []string {"test" },
3848+ },
35423849 }
35433850
35443851 for _ , tt := range tests {
0 commit comments