Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
121 lines
3.7 KiB
Go
121 lines
3.7 KiB
Go
//go:build test && dev
|
|
|
|
package payments
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
// TestValidateAmount_ExtraEdgeCases extends the existing ValidateAmount coverage
|
|
// with additional boundary and edge cases for the money-validation function.
|
|
func TestValidateAmount_ExtraEdgeCases(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
amount int64
|
|
wantErr bool
|
|
desc string
|
|
}{
|
|
// Zero and negative — must be rejected
|
|
{0, true, "zero is not allowed"},
|
|
{-1, true, "negative one penny"},
|
|
{-100, true, "negative £1"},
|
|
{-1000000, true, "negative £10,000 (must be rejected early, not overflow)"},
|
|
|
|
// Normal positive amounts — must pass
|
|
{1, false, "minimum valid: 1 penny"},
|
|
{50, false, "50p"},
|
|
{100, false, "£1"},
|
|
{5000, false, "£50"},
|
|
{50000, false, "£500"},
|
|
{100000, false, "£1,000"},
|
|
{500000, false, "£5,000"},
|
|
{999999, false, "£9,999.99 — just under max"},
|
|
{1000000, false, "£10,000 exactly — boundary allowed"},
|
|
|
|
// Above maximum — must be rejected
|
|
{1000001, true, "£10,000.01 — one penny over max"},
|
|
{1000050, true, "£10,000.50 — 50p over max"},
|
|
{2000000, true, "£20,000 — double max"},
|
|
{99999999, true, "very large amount"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(fmt.Sprintf("%s (%d)", tt.desc, tt.amount), func(t *testing.T) {
|
|
err := ValidateAmount(tt.amount)
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("expected error for amount %d (%s), got nil", tt.amount, tt.desc)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("unexpected error for amount %d (%s): %v", tt.amount, tt.desc, err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestValidateAmount_ErrorMessage locks the error messages for the two
|
|
// rejection paths so callers depending on string matching do not silently
|
|
// break.
|
|
func TestValidateAmount_ErrorMessage(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := ValidateAmount(0); err == nil || err.Error() != "amount must be greater than 0" {
|
|
t.Errorf("zero amount error message mismatch: %v", err)
|
|
}
|
|
if err := ValidateAmount(1000001); err == nil || err.Error() != "amount exceeds maximum (£10,000)" {
|
|
t.Errorf("over-max error message mismatch: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestValidatePartialAmount_ErrorMessage locks the error message format.
|
|
func TestValidatePartialAmount_ErrorMessage(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := ValidatePartialAmount(5000, 2500)
|
|
if err == nil {
|
|
t.Fatal("expected error for partial exceeding remaining")
|
|
}
|
|
expected := "partial amount (£50.00) exceeds remaining balance (£25.00)"
|
|
if err.Error() != expected {
|
|
t.Errorf("error message mismatch:\n got: %s\n want: %s", err.Error(), expected)
|
|
}
|
|
}
|
|
|
|
// TestValidatePaymentType_AllValidTypes verifies every entry in the
|
|
// validPaymentTypes map is accepted and unknown types are rejected.
|
|
func TestValidatePaymentType_AllValidTypes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
valid := []string{"deposit", "full", "tip", "balance", "partial"}
|
|
for _, pt := range valid {
|
|
if err := ValidatePaymentType(pt); err != nil {
|
|
t.Errorf("expected valid payment type %q to be accepted, got: %v", pt, err)
|
|
}
|
|
}
|
|
|
|
invalid := []string{"", "unknown", "deposits", "FULL", "gift_card"}
|
|
for _, pt := range invalid {
|
|
if err := ValidatePaymentType(pt); err == nil {
|
|
t.Errorf("expected invalid payment type %q to be rejected", pt)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestValidateRefundReason_Empty verifies an empty refund reason is rejected.
|
|
func TestValidateRefundReason_Empty(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := ValidateRefundReason(""); err == nil {
|
|
t.Error("expected an error for empty refund reason")
|
|
}
|
|
if err := ValidateRefundReason("customer changed mind"); err != nil {
|
|
t.Errorf("unexpected error for non-empty refund reason: %v", err)
|
|
}
|
|
if err := ValidateRefundReason(" "); err != nil {
|
|
t.Errorf("whitespace-only is arguably a reason — should not error: %v", err)
|
|
}
|
|
} |