From c2190befb69d31108fa50851ef3277886e0ca3aa Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Sun, 20 Sep 2026 22:45:41 +0330 Subject: [PATCH] feat(validation): add card number validation --- backend/internal/card/validation.go | 27 ++++++++++++ backend/internal/card/validation_test.go | 55 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 backend/internal/card/validation.go create mode 100644 backend/internal/card/validation_test.go diff --git a/backend/internal/card/validation.go b/backend/internal/card/validation.go new file mode 100644 index 0000000..a750bc6 --- /dev/null +++ b/backend/internal/card/validation.go @@ -0,0 +1,27 @@ +package card + +import "errors" + +var ( + ErrCardRequired = errors.New("card number is required") + ErrCardLength = errors.New("card number must contain exactly 16 digits") + ErrCardNumeric = errors.New("card number must contain only digits") +) + +func Validate(number string) error { + if number == "" { + return ErrCardRequired + } + + if len(number) != 16 { + return ErrCardLength + } + + for _, char := range number { + if char < '0' || char > '9' { + return ErrCardNumeric + } + } + + return nil +} diff --git a/backend/internal/card/validation_test.go b/backend/internal/card/validation_test.go new file mode 100644 index 0000000..418eb2e --- /dev/null +++ b/backend/internal/card/validation_test.go @@ -0,0 +1,55 @@ +package card + +import ( + "errors" + "testing" +) + +func TestValidate(t *testing.T) { + tests := []struct { + name string + number string + wantErr error + }{ + { + name: "empty card number", + number: "", + wantErr: ErrCardRequired, + }, + { + name: "card number is too short", + number: "123456789", + wantErr: ErrCardLength, + }, + { + name: "card number is too long", + number: "12345678901234567", + wantErr: ErrCardLength, + }, + { + name: "card number contains letters", + number: "603799ABC4567890", + wantErr: ErrCardNumeric, + }, + { + name: "card number contains spaces", + number: "6037 912 3456 78", + wantErr: ErrCardNumeric, + }, + { + name: "valid card number structure", + number: "6037991234567890", + wantErr: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := Validate(tt.number) + + if !errors.Is(err, tt.wantErr) { + t.Errorf("Validate() error = %v, want %v", err, tt.wantErr) + } + }) + } +}