summaryrefslogtreecommitdiff
path: root/tests/FundLab.Domain.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/FundLab.Domain.Tests')
-rw-r--r--tests/FundLab.Domain.Tests/DomainTests.fs75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/FundLab.Domain.Tests/DomainTests.fs b/tests/FundLab.Domain.Tests/DomainTests.fs
index b2a2f0b..ff5245e 100644
--- a/tests/FundLab.Domain.Tests/DomainTests.fs
+++ b/tests/FundLab.Domain.Tests/DomainTests.fs
@@ -757,3 +757,78 @@ module RebalancePolicyTests =
Assert.Equal("rebalance-redeem:7c9e6679-7425-40de-944b-e07fc1f90ae7:2026-09-21:000001", RebalancePolicy.redemptionKey planId runDate "000001")
Assert.Equal(RebalancePolicy.orderKey planId runDate "000001", RebalancePolicy.orderKey planId runDate "000001")
+
+module DividendPolicyTests =
+
+ open Xunit
+ open FundLab.Domain
+
+ let private unwrap result =
+ match result with
+ | Ok value -> value
+ | Error error -> failwithf "%A" error
+
+ [<Fact>]
+ let ``dividend per unit validation rejects non positive or imprecise values`` () =
+ Assert.Equal(Error "dividend per unit must be positive", DividendPolicy.validateDps 0m)
+ Assert.Equal(Error "dividend per unit must be positive", DividendPolicy.validateDps -0.05m)
+ Assert.Equal(Error "dividend per unit exceeds supported precision", DividendPolicy.validateDps 0.015000001m)
+ Assert.Equal(Ok(), DividendPolicy.validateDps 0.01500000m)
+
+ [<Fact>]
+ let ``future dividend dates are rejected without look-ahead`` () =
+ let today = System.DateOnly(2026, 9, 21)
+
+ Assert.Equal(
+ Error "dividend nav date is in the future",
+ DividendPolicy.validateNavDate (System.DateOnly(2026, 9, 22)) today
+ )
+ Assert.Equal(Ok(), DividendPolicy.validateNavDate today today)
+
+ [<Fact>]
+ let ``cash dividend payout truncates to two decimals and keeps units untouched`` () =
+ let payout: DividendPolicy.CashDividendOutcome =
+ DividendPolicy.computeCashPayout 500.00000000m 0.1m
+ |> unwrap
+
+ Assert.Equal(50.00m, payout.GrossCash)
+
+ let uneven: DividendPolicy.CashDividendOutcome =
+ DividendPolicy.computeCashPayout 123.45678900m 0.12345678m
+ |> unwrap
+
+ Assert.Equal(15.24m, uneven.GrossCash)
+ Assert.Equal(Error "held units must be positive for a cash dividend", DividendPolicy.computeCashPayout 0m 0.1m)
+ Assert.Equal(Error "dividend per unit must be positive", DividendPolicy.computeCashPayout 500m -0.1m)
+
+ [<Fact>]
+ let ``reinvestment follows the subscription math`` () =
+ let reinvest: DividendPolicy.ReinvestDividendOutcome =
+ DividendPolicy.computeReinvest 500.00000000m 0.1m 2.5m
+ |> unwrap
+
+ // gross 50.00 -> units 20.00000000 at nav 2.5
+ Assert.Equal(50.00m, 50.00m)
+ Assert.Equal(20.00000000m, reinvest.RequestedUnits)
+ Assert.Equal(2.5m, reinvest.NAV)
+
+ let proceedsZero =
+ DividendPolicy.computeReinvest 1.00000000m 0.00000001m 2.5m
+
+ Assert.Equal(Error "dividend proceeds round to zero", proceedsZero)
+
+ let badNav =
+ DividendPolicy.computeReinvest 500.00000000m 0.1m 0m
+
+ Assert.Equal(Error "unit nav must be positive", badNav)
+
+ [<Fact>]
+ let ``mode parsing roundtrips and record keys are deterministic`` () =
+ Assert.Equal(Some DividendPolicy.Cash, DividendPolicy.parseMode "cash")
+ Assert.Equal(Some DividendPolicy.Reinvest, DividendPolicy.parseMode "reinvest")
+ Assert.Equal(None, DividendPolicy.parseMode "stock")
+
+ let recordId = System.Guid "7c9e6679-7425-40de-944b-e07fc1f90ae7"
+
+ Assert.Equal("dividend:7c9e6679-7425-40de-944b-e07fc1f90ae7", DividendPolicy.recordKey recordId)
+ Assert.Equal("dividend-confirm:7c9e6679-7425-40de-944b-e07fc1f90ae7", DividendPolicy.confirmKey recordId)