fee_test.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package payment
  2. import (
  3. "testing"
  4. )
  5. func TestCalculatePayAmount(t *testing.T) {
  6. t.Parallel()
  7. tests := []struct {
  8. name string
  9. amount float64
  10. feeRate float64
  11. expected string
  12. }{
  13. {
  14. name: "zero fee rate returns same amount",
  15. amount: 100.00,
  16. feeRate: 0,
  17. expected: "100.00",
  18. },
  19. {
  20. name: "negative fee rate returns same amount",
  21. amount: 50.00,
  22. feeRate: -5,
  23. expected: "50.00",
  24. },
  25. {
  26. name: "1 percent fee rate",
  27. amount: 100.00,
  28. feeRate: 1,
  29. expected: "101.00",
  30. },
  31. {
  32. name: "5 percent fee on 200",
  33. amount: 200.00,
  34. feeRate: 5,
  35. expected: "210.00",
  36. },
  37. {
  38. name: "fee rounds UP to 2 decimal places",
  39. amount: 100.00,
  40. feeRate: 3,
  41. expected: "103.00",
  42. },
  43. {
  44. name: "fee rounds UP small remainder",
  45. amount: 10.00,
  46. feeRate: 3.33,
  47. expected: "10.34", // 10 * 3.33 / 100 = 0.333 -> round up -> 0.34
  48. },
  49. {
  50. name: "very small amount",
  51. amount: 0.01,
  52. feeRate: 1,
  53. expected: "0.02", // 0.01 * 1/100 = 0.0001 -> round up -> 0.01 -> total 0.02
  54. },
  55. {
  56. name: "large amount",
  57. amount: 99999.99,
  58. feeRate: 10,
  59. expected: "109999.99", // 99999.99 * 10/100 = 9999.999 -> round up -> 10000.00 -> total 109999.99
  60. },
  61. {
  62. name: "100 percent fee rate doubles amount",
  63. amount: 50.00,
  64. feeRate: 100,
  65. expected: "100.00",
  66. },
  67. {
  68. name: "precision 0.01 fee difference",
  69. amount: 100.00,
  70. feeRate: 1.01,
  71. expected: "101.01", // 100 * 1.01/100 = 1.01
  72. },
  73. {
  74. name: "precision 0.02 fee",
  75. amount: 100.00,
  76. feeRate: 1.02,
  77. expected: "101.02",
  78. },
  79. {
  80. name: "zero amount with positive fee",
  81. amount: 0,
  82. feeRate: 5,
  83. expected: "0.00",
  84. },
  85. {
  86. name: "fractional amount no fee",
  87. amount: 19.99,
  88. feeRate: 0,
  89. expected: "19.99",
  90. },
  91. {
  92. name: "fractional fee that causes rounding up",
  93. amount: 33.33,
  94. feeRate: 7.77,
  95. expected: "35.92", // 33.33 * 7.77 / 100 = 2.589741 -> round up -> 2.59 -> total 35.92
  96. },
  97. }
  98. for _, tt := range tests {
  99. t.Run(tt.name, func(t *testing.T) {
  100. t.Parallel()
  101. got := CalculatePayAmount(tt.amount, tt.feeRate)
  102. if got != tt.expected {
  103. t.Fatalf("CalculatePayAmount(%v, %v) = %q, want %q", tt.amount, tt.feeRate, got, tt.expected)
  104. }
  105. })
  106. }
  107. }
  108. func TestCalculatePayAmountForCurrency(t *testing.T) {
  109. t.Parallel()
  110. tests := []struct {
  111. name string
  112. amount float64
  113. feeRate float64
  114. currency string
  115. expected string
  116. }{
  117. {
  118. name: "zero decimal currency rounds fee up to whole unit",
  119. amount: 100,
  120. feeRate: 2.5,
  121. currency: "JPY",
  122. expected: "103",
  123. },
  124. {
  125. name: "three decimal currency keeps three decimal places",
  126. amount: 12.345,
  127. feeRate: 1,
  128. currency: "KWD",
  129. expected: "12.469",
  130. },
  131. {
  132. name: "stripe legacy zero decimal currency displays whole unit",
  133. amount: 100,
  134. feeRate: 2.5,
  135. currency: "ISK",
  136. expected: "103",
  137. },
  138. {
  139. name: "default currency keeps existing two decimal behavior",
  140. amount: 10,
  141. feeRate: 3.33,
  142. currency: "CNY",
  143. expected: "10.34",
  144. },
  145. }
  146. for _, tt := range tests {
  147. t.Run(tt.name, func(t *testing.T) {
  148. t.Parallel()
  149. got := CalculatePayAmountForCurrency(tt.amount, tt.feeRate, tt.currency)
  150. if got != tt.expected {
  151. t.Fatalf("CalculatePayAmountForCurrency(%v, %v, %q) = %q, want %q", tt.amount, tt.feeRate, tt.currency, got, tt.expected)
  152. }
  153. })
  154. }
  155. }