summaryrefslogtreecommitdiff
path: root/tests/FundLab.Web.Tests/BoundaryTests.fs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/FundLab.Web.Tests/BoundaryTests.fs')
-rw-r--r--tests/FundLab.Web.Tests/BoundaryTests.fs74
1 files changed, 74 insertions, 0 deletions
diff --git a/tests/FundLab.Web.Tests/BoundaryTests.fs b/tests/FundLab.Web.Tests/BoundaryTests.fs
index 2892633..25d7867 100644
--- a/tests/FundLab.Web.Tests/BoundaryTests.fs
+++ b/tests/FundLab.Web.Tests/BoundaryTests.fs
@@ -584,6 +584,80 @@ module ConfirmationBoundaryTests =
Assert.False(updated.stockDailyInFlight)
[<Fact>]
+ let ``stock buy requires a created fund before dispatching a trade`` () =
+ let model = { init () with token = "qa-token"; stockCode = "600519"; stockTradeQuantity = "100" }
+ let updated, _ = update StockTradeRequested model
+
+ Assert.Contains("请先创建一个基金", updated.stockTradeMessage |> Option.defaultValue "")
+ Assert.False(updated.stockTradeInFlight)
+
+ [<Fact>]
+ let ``stock buy rejects a non-positive quantity without dispatching`` () =
+ let model =
+ { init () with
+ token = "qa-token"
+ createdFund = Some(FundBoundaryTests.sampleFund "3fa85f64-5717-4562-b3fc-2c963f66afa6")
+ stockCode = "600519"
+ stockTradeQuantity = "0" }
+
+ let updated, _ = update StockTradeRequested model
+
+ Assert.Contains("数量必须是大于零的整数股数", updated.stockTradeMessage |> Option.defaultValue "")
+ Assert.False(updated.stockTradeInFlight)
+
+ [<Fact>]
+ let ``stock buy failure keeps no position and surfaces a message`` () =
+ let fundId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
+
+ let model =
+ { init () with
+ token = "qa-token"
+ createdFund = Some(FundBoundaryTests.sampleFund fundId)
+ stockCode = "999999"
+ stockTradeQuantity = "100"
+ stockTradeInFlight = true
+ stockTradeSeq = 1 }
+
+ let updated, _ = update (StockTradeFailed(1, fundId, "collector exited with code 2")) model
+
+ Assert.Empty updated.stockPositions
+ Assert.Contains("买入失败", updated.stockTradeMessage |> Option.defaultValue "")
+ Assert.False(updated.stockTradeInFlight)
+
+ [<Fact>]
+ let ``stock positions read completion stores decoded rows`` () =
+ let fundId = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
+
+ let model =
+ { init () with
+ createdFund = Some(FundBoundaryTests.sampleFund fundId)
+ stockPositionsReadSeq = 1
+ stockPositionsInFlight = true }
+
+ let raw : RawStockPositions =
+ {
+ fundId = fundId
+ positions =
+ [|
+ {
+ instrumentCode = "600519"
+ stockName = box "贵州茅台"
+ quantity = "100"
+ costCash = "125257.00"
+ lastTradedAt = "2026-09-21T08:00:00Z"
+ }
+ |]
+ }
+
+ let updated, _ = update (StockPositionsReadCompleted(1, fundId, raw)) model
+
+ Assert.Equal(1, updated.stockPositions.Length)
+ Assert.Equal("600519", updated.stockPositions[0].instrumentCode)
+ Assert.Equal(Some "贵州茅台", updated.stockPositions[0].stockName)
+ Assert.Equal("100", updated.stockPositions[0].quantity)
+ Assert.False(updated.stockPositionsInFlight)
+
+ [<Fact>]
let ``order decode keeps decimal strings and decodes option fields`` () =
let confirmed = Api.decodeOrder (sampleConfirmedRaw ())
let pending = Api.decodeOrder (samplePendingRaw ())