flamingo.me/flamingo-commerce/v3@v3.11.0/price/domain/price_test.go (about) 1 package domain_test 2 3 import ( 4 "bytes" 5 "encoding/gob" 6 "encoding/json" 7 "fmt" 8 "math" 9 "math/big" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "flamingo.me/flamingo-commerce/v3/price/domain" 16 ) 17 18 func TestPrice_IsLessThen(t *testing.T) { 19 type fields struct { 20 Amount float64 21 Currency string 22 } 23 type args struct { 24 amount big.Float 25 } 26 tests := []struct { 27 name string 28 fields fields 29 args args 30 want bool 31 }{ 32 { 33 name: "simple is less", 34 fields: fields{ 35 Amount: 11.0, 36 }, 37 args: args{ 38 amount: *big.NewFloat(12.2), 39 }, 40 want: true, 41 }, 42 { 43 name: "simple is not less", 44 fields: fields{ 45 Amount: 13.0, 46 }, 47 args: args{ 48 amount: *big.NewFloat(12.2), 49 }, 50 want: false, 51 }, 52 } 53 for _, tt := range tests { 54 t.Run(tt.name, func(t *testing.T) { 55 p := domain.NewFromFloat(tt.fields.Amount, tt.fields.Currency) 56 57 if got := p.IsLessThenValue(tt.args.amount); got != tt.want { 58 t.Errorf("Amount.IsLessThen() = %v, want %v", got, tt.want) 59 } 60 }) 61 } 62 } 63 64 func TestPrice_Multiply(t *testing.T) { 65 p := domain.NewFromFloat(2.5, "EUR") 66 resultPrice := p.Multiply(3) 67 assert.Equal(t, domain.NewFromFloat(7.5, "EUR").GetPayable().Amount(), resultPrice.GetPayable().Amount()) 68 } 69 70 func TestPrice_GetPayable(t *testing.T) { 71 t.Parallel() 72 73 t.Run("rounding with valid currency code", func(t *testing.T) { 74 t.Parallel() 75 76 price := domain.NewFromFloat(12.34567, "EUR") 77 78 payable := price.GetPayable() 79 assert.Equal(t, float64(12.35), payable.FloatAmount()) 80 81 price = domain.NewFromFloat(math.MaxInt64, "EUR").GetPayable() 82 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 83 }) 84 85 t.Run("rounding with miles currency code for back compatibility", func(t *testing.T) { 86 t.Parallel() 87 88 price := domain.NewFromFloat(12.34567, "MILES") 89 90 payable := price.GetPayable() 91 assert.Equal(t, float64(12), payable.FloatAmount()) 92 93 price = domain.NewFromFloat(math.MaxInt64, "MILES").GetPayable() 94 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 95 }) 96 97 t.Run("rounding with points currency code for back compatibility", func(t *testing.T) { 98 t.Parallel() 99 100 price := domain.NewFromFloat(12.34567, "Points") 101 102 payable := price.GetPayable() 103 assert.Equal(t, float64(12), payable.FloatAmount()) 104 105 price = domain.NewFromFloat(math.MaxInt64, "Points").GetPayable() 106 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 107 }) 108 109 t.Run("rounding with random currency code", func(t *testing.T) { 110 t.Parallel() 111 112 price := domain.NewFromFloat(12.34567, "asdasdasd") 113 114 payable := price.GetPayable() 115 assert.Equal(t, float64(12), payable.FloatAmount()) 116 117 price = domain.NewFromFloat(math.MaxInt64, "asdasdasd").GetPayable() 118 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 119 }) 120 121 t.Run("rounding with Bahraini dinar currency code", func(t *testing.T) { 122 t.Parallel() 123 124 price := domain.NewFromFloat(12.34567, "BHD") 125 126 payable := price.GetPayable() 127 assert.Equal(t, 12.346, payable.FloatAmount()) 128 129 price = domain.NewFromFloat(math.MaxInt64, "BHD").GetPayable() 130 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 131 }) 132 133 t.Run("rounding with Chilean Unit of Account currency code", func(t *testing.T) { 134 t.Parallel() 135 136 price := domain.NewFromFloat(12.34567, "CLF") 137 138 payable := price.GetPayable() 139 assert.Equal(t, 12.3457, payable.FloatAmount()) 140 141 price = domain.NewFromFloat(math.MaxInt64, "CLF").GetPayable() 142 assert.Equal(t, float64(math.MaxInt64), price.FloatAmount()) 143 }) 144 } 145 146 func TestNewFromInt(t *testing.T) { 147 price1 := domain.NewFromInt(1245, 100, "EUR") 148 price2 := domain.NewFromFloat(12.45, "EUR") 149 assert.Equal(t, price2.GetPayable().Amount(), price1.GetPayable().Amount()) 150 pricePayable := price1.GetPayable() 151 assert.True(t, price2.GetPayable().Equal(pricePayable)) 152 } 153 154 func TestPrice_SplitInPayables(t *testing.T) { 155 originalPrice := domain.NewFromFloat(32.1, "EUR") // float edge case 156 payableSplitPrices, _ := originalPrice.SplitInPayables(1) 157 158 sumPrice := domain.NewZero("EUR") 159 for _, price := range payableSplitPrices { 160 sumPrice, _ = sumPrice.Add(price) 161 } 162 // sum of the splitted payable need to match original price payable 163 assert.Equal(t, originalPrice.GetPayable().Amount(), sumPrice.GetPayable().Amount()) 164 165 originalPrice = domain.NewFromFloat(12.456, "EUR") 166 payableSplitPrices, _ = originalPrice.SplitInPayables(6) 167 168 sumPrice = domain.NewZero("EUR") 169 for _, price := range payableSplitPrices { 170 sumPrice, _ = sumPrice.Add(price) 171 } 172 // sum of the splitted payable need to match original price payable 173 assert.Equal(t, originalPrice.GetPayable().Amount(), sumPrice.GetPayable().Amount()) 174 175 // edge case for negative input (happens when discounts are split) 176 originalPrice = domain.NewFromFloat(-152.99, "EUR") 177 payableSplitPrices, _ = originalPrice.SplitInPayables(3) 178 179 sumPrice = domain.NewZero("EUR") 180 for _, price := range payableSplitPrices { 181 sumPrice, _ = sumPrice.Add(price) 182 } 183 assert.Equal(t, originalPrice.GetPayable().Amount(), sumPrice.GetPayable().Amount()) 184 } 185 186 func TestPrice_Discounted(t *testing.T) { 187 originalPrice := domain.NewFromFloat(12.45, "EUR") 188 discountedPrice := originalPrice.Discounted(10).GetPayable() 189 // 10% of - expected rounded value of 11.21 190 assert.Equal(t, domain.NewFromInt(1121, 100, "").Amount(), discountedPrice.Amount()) 191 } 192 193 func TestPrice_IsZero(t *testing.T) { 194 var price domain.Price 195 assert.Equal(t, domain.NewZero("").Amount(), price.GetPayable().Amount()) 196 } 197 198 func TestSumAll(t *testing.T) { 199 price1 := domain.NewFromInt(1200, 100, "EUR") 200 price2 := domain.NewFromInt(1200, 100, "EUR") 201 price3 := domain.NewFromInt(1200, 100, "EUR") 202 203 result, err := domain.SumAll(price1, price2, price3) 204 assert.NoError(t, err) 205 assert.Equal(t, result, domain.NewFromInt(3600, 100, "EUR")) 206 207 } 208 209 func TestPrice_TaxFromGross(t *testing.T) { 210 // 119 EUR 211 price := domain.NewFromInt(119, 1, "EUR") 212 tax := price.TaxFromGross(*new(big.Float).SetInt64(19)) 213 assert.Equal(t, tax, domain.NewFromInt(19, 1, "EUR")) 214 } 215 216 func TestPrice_TaxFromNet(t *testing.T) { 217 // 100 EUR 218 price := domain.NewFromInt(100, 1, "EUR") 219 tax := price.TaxFromNet(*new(big.Float).SetInt64(19)) 220 assert.Equal(t, tax, domain.NewFromInt(19, 1, "EUR"), "expect 19 EUR tax fromm 100EUR") 221 222 taxedPrice := price.Taxed(*new(big.Float).SetInt64(19)) 223 assert.Equal(t, taxedPrice, domain.NewFromInt(119, 1, "EUR")) 224 } 225 226 func TestPrice_LikelyEqual(t *testing.T) { 227 price1 := domain.NewFromFloat(100, "EUR") 228 price2 := domain.NewFromFloat(100.000000000000001, "EUR") 229 price3 := domain.NewFromFloat(100.1, "EUR") 230 assert.True(t, price1.LikelyEqual(price2)) 231 assert.False(t, price1.LikelyEqual(price3)) 232 } 233 234 func TestPrice_MarshalBinaryForGob(t *testing.T) { 235 type ( 236 SomeTypeWithPrice struct { 237 Price domain.Price 238 } 239 ) 240 gob.Register(SomeTypeWithPrice{}) 241 var network bytes.Buffer 242 enc := gob.NewEncoder(&network) // Will write to network. 243 dec := gob.NewDecoder(&network) // Will read from network. 244 245 err := enc.Encode(&SomeTypeWithPrice{Price: domain.NewFromInt(1111, 100, "EUR")}) 246 if err != nil { 247 t.Fatal("encode error:", err) 248 } 249 var receivedPrice SomeTypeWithPrice 250 err = dec.Decode(&receivedPrice) 251 if err != nil { 252 t.Fatal("decode error 1:", err) 253 } 254 float, _ := receivedPrice.Price.Amount().Float64() 255 assert.Equal(t, 11.11, float) 256 } 257 258 func TestPrice_GetPayableByRoundingMode(t *testing.T) { 259 price := domain.NewFromFloat(12.34567, "EUR") 260 261 payable := price.GetPayableByRoundingMode(domain.RoundingModeCeil, 100) 262 assert.Equal(t, domain.NewFromInt(1235, 100, "EUR").Amount(), payable.Amount()) 263 264 payable = price.GetPayableByRoundingMode(domain.RoundingModeFloor, 100) 265 assert.Equal(t, domain.NewFromInt(1234, 100, "EUR").Amount(), payable.Amount()) 266 267 payable = price.GetPayableByRoundingMode(domain.RoundingModeFloor, 1) 268 assert.Equal(t, domain.NewFromInt(12, 1, "EUR").Amount(), payable.Amount()) 269 270 price = domain.NewFromFloat(-0.119, "EUR") 271 payable = price.GetPayableByRoundingMode(domain.RoundingModeFloor, 100) 272 assert.Equal(t, domain.NewFromInt(-12, 100, "EUR").Amount(), payable.Amount()) 273 } 274 275 func TestPrice_GetPayableByRoundingMode_RoundingModeCeil(t *testing.T) { 276 tests := []struct { 277 price float64 278 precision int 279 expected int64 280 }{ 281 {price: 12.34567, precision: 100, expected: 1235}, 282 {price: -12.34567, precision: 100, expected: -1234}, 283 {price: 5.5, precision: 1, expected: 6}, 284 {price: 2.5, precision: 1, expected: 3}, 285 {price: 1.6, precision: 1, expected: 2}, 286 {price: 1.1, precision: 1, expected: 2}, 287 {price: 1.0, precision: 1, expected: 1}, 288 {price: -1.0, precision: 1, expected: -1}, 289 {price: -1.1, precision: 1, expected: -1}, 290 {price: -1.6, precision: 1, expected: -1}, 291 {price: -2.5, precision: 1, expected: -2}, 292 {price: -5.5, precision: 1, expected: -5}, 293 } 294 295 for _, tt := range tests { 296 t.Run(fmt.Sprintf("rounding %f", tt.price), func(t *testing.T) { 297 price := domain.NewFromFloat(tt.price, "EUR") 298 299 payable := price.GetPayableByRoundingMode(domain.RoundingModeCeil, tt.precision) 300 assert.Equal(t, domain.NewFromInt(tt.expected, tt.precision, "EUR").Amount(), payable.Amount()) 301 }) 302 } 303 } 304 305 func TestPrice_GetPayableByRoundingMode_RoundingModeFloor(t *testing.T) { 306 tests := []struct { 307 price float64 308 precision int 309 expected int64 310 }{ 311 {price: 12.34567, precision: 100, expected: 1234}, 312 {price: -12.34567, precision: 100, expected: -1235}, 313 {price: 5.5, precision: 1, expected: 5}, 314 {price: 2.5, precision: 1, expected: 2}, 315 {price: 1.6, precision: 1, expected: 1}, 316 {price: 1.1, precision: 1, expected: 1}, 317 {price: 1.0, precision: 1, expected: 1}, 318 {price: -1.0, precision: 1, expected: -1}, 319 {price: -1.1, precision: 1, expected: -2}, 320 {price: -1.6, precision: 1, expected: -2}, 321 {price: -2.5, precision: 1, expected: -3}, 322 {price: -5.5, precision: 1, expected: -6}, 323 } 324 325 for _, tt := range tests { 326 t.Run(fmt.Sprintf("rounding %f", tt.price), func(t *testing.T) { 327 price := domain.NewFromFloat(tt.price, "EUR") 328 329 payable := price.GetPayableByRoundingMode(domain.RoundingModeFloor, tt.precision) 330 assert.Equal(t, domain.NewFromInt(tt.expected, tt.precision, "EUR").Amount(), payable.Amount()) 331 }) 332 } 333 } 334 335 func TestPrice_GetPayableByRoundingMode_RoundingModeHalfUp(t *testing.T) { 336 tests := []struct { 337 price float64 338 precision int 339 expected int64 340 msg string 341 }{ 342 {price: 7.6, precision: 1, expected: 8, msg: "7.6 should be rounded to 8"}, 343 {price: 7.5, precision: 1, expected: 8, msg: "7.5 should be rounded to 8"}, 344 {price: 7.4, precision: 1, expected: 7, msg: "7.4 should be rounded to 7"}, 345 {price: 12.34567, precision: 100, expected: 1235, msg: "12.34567 should be rounded to 12.35"}, 346 {price: -7.4, precision: 1, expected: -7, msg: "-7.4 should be rounded to -7"}, 347 {price: -7.45, precision: 1, expected: -7, msg: "-7.45 should be rounded to -7"}, 348 {price: -7.5, precision: 1, expected: -8, msg: "-7.5 should be rounded to -8"}, 349 {price: -7.55, precision: 1, expected: -8, msg: "-7.55 should be rounded to -8"}, 350 {price: -7.6, precision: 1, expected: -8, msg: "-7.6 should be rounded to -8"}, 351 352 {price: 5.5, precision: 1, expected: 6, msg: "5.5 should be rounded to 6"}, 353 {price: 2.5, precision: 1, expected: 3, msg: "2.5 should be rounded to 3"}, 354 {price: 1.6, precision: 1, expected: 2, msg: "1.6 should be rounded to 2"}, 355 {price: 1.1, precision: 1, expected: 1, msg: "1.1 should be rounded to 1"}, 356 {price: 1.0, precision: 1, expected: 1, msg: "1.0 should be rounded to 1"}, 357 {price: -1.0, precision: 1, expected: -1, msg: "-1.0 should be rounded to -1"}, 358 {price: -1.1, precision: 1, expected: -1, msg: "-1.1 should be rounded to -1"}, 359 {price: -1.6, precision: 1, expected: -2, msg: "-1.6 should be rounded to -2"}, 360 {price: -2.5, precision: 1, expected: -3, msg: "-2.5 should be rounded to -3"}, 361 {price: -5.5, precision: 1, expected: -6, msg: "-5.5 should be rounded to -6"}, 362 } 363 364 for _, tt := range tests { 365 t.Run(fmt.Sprintf("rounding %f", tt.price), func(t *testing.T) { 366 price := domain.NewFromFloat(tt.price, "EUR") 367 368 payable := price.GetPayableByRoundingMode(domain.RoundingModeHalfUp, tt.precision) 369 assert.Equal(t, domain.NewFromInt(tt.expected, tt.precision, "EUR").Amount(), payable.Amount(), tt.msg) 370 }) 371 } 372 } 373 374 func TestPrice_GetPayableByRoundingMode_RoundingModeHalfDown(t *testing.T) { 375 tests := []struct { 376 price float64 377 precision int 378 expected int64 379 msg string 380 }{ 381 {price: 7.6, precision: 1, expected: 8, msg: "7.6 should be rounded to 8"}, 382 {price: 7.5, precision: 1, expected: 7, msg: "7.5 should be rounded to 7"}, 383 {price: 7.4, precision: 1, expected: 7, msg: "7.4 should be rounded to 7"}, 384 {price: 12.34567, precision: 100, expected: 1235, msg: "12.34567 should be rounded to 12.35"}, 385 386 {price: -7.4, precision: 1, expected: -7, msg: "-7.4 should be rounded to -7"}, 387 {price: -7.5, precision: 1, expected: -7, msg: "-7.5 should be rounded to -7"}, 388 {price: -7.6, precision: 1, expected: -8, msg: "-7.6 should be rounded to -8"}, 389 390 {price: 5.5, precision: 1, expected: 5, msg: "5.5 should be rounded to 5"}, 391 {price: 2.5, precision: 1, expected: 2, msg: "2.5 should be rounded to 2"}, 392 {price: 1.6, precision: 1, expected: 2, msg: "1.6 should be rounded to 2"}, 393 {price: 1.1, precision: 1, expected: 1, msg: "1.1 should be rounded to 1"}, 394 {price: 1.0, precision: 1, expected: 1, msg: "1.0 should be rounded to 1"}, 395 {price: -1.0, precision: 1, expected: -1, msg: "-1.0 should be rounded to -1"}, 396 {price: -1.1, precision: 1, expected: -1, msg: "-1.1 should be rounded to -1"}, 397 {price: -1.6, precision: 1, expected: -2, msg: "-1.6 should be rounded to -2"}, 398 {price: -2.5, precision: 1, expected: -2, msg: "-2.5 should be rounded to -2"}, 399 {price: -5.5, precision: 1, expected: -5, msg: "-5.5 should be rounded to -5"}, 400 } 401 for _, tt := range tests { 402 t.Run(fmt.Sprintf("rounding %f", tt.price), func(t *testing.T) { 403 price := domain.NewFromFloat(tt.price, "EUR") 404 405 payable := price.GetPayableByRoundingMode(domain.RoundingModeHalfDown, tt.precision) 406 assert.Equal(t, domain.NewFromInt(tt.expected, tt.precision, "EUR").Amount(), payable.Amount(), tt.msg) 407 }) 408 } 409 410 } 411 412 func TestCharges_Add(t *testing.T) { 413 c1 := domain.Charges{} 414 415 byType := make(map[string]domain.Charge) 416 byType["main"] = domain.Charge{ 417 Type: "main", 418 Price: domain.NewFromInt(100, 1, "EUR"), 419 Value: domain.NewFromInt(50, 1, "EUR"), 420 } 421 c2 := domain.NewCharges(byType) 422 423 byType = make(map[string]domain.Charge) 424 byType["main"] = domain.Charge{ 425 Type: "main", 426 Price: domain.NewFromInt(100, 1, "EUR"), 427 Value: domain.NewFromInt(100, 1, "EUR"), 428 } 429 c3 := domain.NewCharges(byType) 430 431 c1and2 := c1.Add(*c2) 432 charge, found := c1and2.GetByType("main") 433 assert.True(t, found) 434 assert.Equal(t, domain.Charge{ 435 Price: domain.NewFromInt(100, 1, "EUR"), 436 Value: domain.NewFromInt(50, 1, "EUR"), 437 Type: "main", 438 }, charge) 439 440 c2and3 := c2.Add(*c3) 441 charge, found = c2and3.GetByType("main") 442 assert.True(t, found) 443 assert.Equal(t, domain.Charge{ 444 Price: domain.NewFromInt(200, 1, "EUR"), 445 Value: domain.NewFromInt(150, 1, "EUR"), 446 Type: "main", 447 }, charge) 448 } 449 450 func TestCharges_GetAllByType(t *testing.T) { 451 charges := domain.Charges{} 452 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 453 charges = charges.AddCharge(domain.Charge{Type: "type-a", Price: domain.NewFromInt(200, 1, "EUR")}) 454 charges = charges.AddCharge(domain.Charge{Type: "type-x", Price: domain.NewFromInt(200, 1, "EUR")}) 455 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Price: domain.NewFromInt(200, 1, "EUR")}) 456 charges = charges.AddCharge(domain.Charge{Type: "type-c", Reference: "HUHUWHHUHX", Price: domain.NewFromInt(200, 1, "EUR")}) 457 charges = charges.AddCharge(domain.Charge{Type: "type-a", Price: domain.NewFromInt(200, 1, "EUR")}) 458 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "ABC123", Price: domain.NewFromInt(200, 1, "EUR")}) 459 460 assert.Len(t, charges.GetAllByType(domain.ChargeTypeMain), 3) 461 assert.Len(t, charges.GetAllByType("type-a"), 1) 462 assert.Len(t, charges.GetAllByType("type-c"), 1) 463 assert.Len(t, charges.GetAllByType("type-x"), 1) 464 } 465 466 func TestCharges_GetByType(t *testing.T) { 467 charges := domain.Charges{} 468 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 469 charges = charges.AddCharge(domain.Charge{Type: "type-a", Price: domain.NewFromInt(200, 1, "EUR")}) 470 charges = charges.AddCharge(domain.Charge{Type: "type-x", Price: domain.NewFromInt(200, 1, "EUR")}) 471 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Price: domain.NewFromInt(200, 1, "EUR")}) 472 charges = charges.AddCharge(domain.Charge{Type: "type-c", Reference: "HUHUWHHUHX", Price: domain.NewFromInt(200, 1, "EUR")}) 473 charges = charges.AddCharge(domain.Charge{Type: "type-a", Price: domain.NewFromInt(200, 1, "EUR")}) 474 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "ABC123", Price: domain.NewFromInt(200, 1, "EUR")}) 475 476 charge, found := charges.GetByType(domain.ChargeTypeMain) 477 assert.True(t, found) 478 assert.Equal(t, charge, domain.Charge{Type: domain.ChargeTypeMain, Price: domain.NewFromInt(600, 1, "EUR")}) 479 480 charge, found = charges.GetByType("type-a") 481 assert.True(t, found) 482 483 want := domain.Charge{Type: "type-a", Price: domain.NewFromInt(400, 1, "EUR")} 484 assert.Equal(t, charge.Price, want.Price) 485 } 486 487 func TestCharges_GetByTypeForced(t *testing.T) { 488 charges := domain.Charges{} 489 490 charge := charges.GetByTypeForced(domain.ChargeTypeMain) 491 assert.Equal(t, charge, domain.Charge{}) 492 493 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 494 charge = charges.GetByTypeForced(domain.ChargeTypeMain) 495 496 assert.Equal(t, charge, domain.Charge{Type: domain.ChargeTypeMain, Price: domain.NewFromInt(200, 1, "EUR")}) 497 } 498 499 func TestCharges_GetByChargeQualifier(t *testing.T) { 500 charges := domain.Charges{} 501 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 502 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Price: domain.NewFromInt(200, 1, "EUR")}) 503 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "ABC123", Price: domain.NewFromInt(200, 1, "EUR")}) 504 505 charge, found := charges.GetByChargeQualifier(domain.ChargeQualifier{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82"}) 506 assert.True(t, found) 507 assert.Equal(t, charge, domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 508 509 } 510 511 func TestCharges_GetByChargeQualifierForced(t *testing.T) { 512 charges := domain.Charges{} 513 charge := charges.GetByChargeQualifierForced(domain.ChargeQualifier{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82"}) 514 assert.Equal(t, charge, domain.Charge{}) 515 516 charges = charges.AddCharge(domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 517 charge = charges.GetByChargeQualifierForced(domain.ChargeQualifier{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82"}) 518 assert.Equal(t, charge, domain.Charge{Type: domain.ChargeTypeMain, Reference: "SJHHQWAXX6HJSDZ82", Price: domain.NewFromInt(200, 1, "EUR")}) 519 520 } 521 522 func TestPrice_MarshalJSON(t *testing.T) { 523 t.Run("JSON marshalling works", func(t *testing.T) { 524 price := domain.NewFromFloat(55.111111, "USD") 525 526 priceJSON, err := price.MarshalJSON() 527 require.NoError(t, err) 528 assert.Equal(t, `{"Amount":"55.11","Currency":"USD"}`, string(priceJSON)) 529 }) 530 531 t.Run("JSON price is rounded", func(t *testing.T) { 532 price := domain.NewFromFloat(55.119, "USD") 533 534 priceJSON, err := price.MarshalJSON() 535 require.NoError(t, err) 536 assert.Equal(t, `{"Amount":"55.12","Currency":"USD"}`, string(priceJSON)) 537 }) 538 } 539 540 func TestPrice_UnmarshalJSON(t *testing.T) { 541 var p domain.Price 542 543 err := json.Unmarshal([]byte(`{"Amount":"55.12","Currency":"USD"}`), &p) 544 require.NoError(t, err) 545 assert.Equal(t, domain.NewFromFloat(55.12, "USD").GetPayable(), p.GetPayable()) 546 }