blob: e4f0c864a63ccadd424029e69d3d0642047cecfe (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
module SomhairlesDream.Shared.Tests.ArtifactContractTests
open System
open Xunit
open SomhairlesDream.Shared
let private ids : RunIds =
{ ProjectId = "heritage-001"
RunId = "run-20260920-001"
BaseId = "heritage"
TargetId = "heritage-001" }
[<Fact>]
let ``resource ids reject path traversal and separators`` () =
Assert.True(Ids.validateResourceId "heritage-001" |> Result.isOk)
Assert.True(Ids.validateResourceId "../outside" |> Result.isError)
Assert.True(Ids.validateResourceId "heritage/001" |> Result.isError)
Assert.True(Ids.validateResourceId "heritage_001" |> Result.isError)
[<Fact>]
let ``object ids use the stable dotted namespace`` () =
Assert.True(Ids.validateObjectId "heritage.foundation" |> Result.isOk)
Assert.True(Ids.validateObjectId "heritage/frame.left" |> Result.isError)
Assert.True(Ids.validateObjectId "heritage.foundation/../../outside" |> Result.isError)
[<Fact>]
let ``start event serializes as flat camel-case json`` () =
let event =
RunEvent.Start
{ Ids = ids
At = DateTimeOffset.Parse("2026-09-20T12:00:00Z")
TotalSteps = 3 }
let json = RunEvent.toJson event
Assert.Contains("\"kind\":\"start\"", json)
Assert.Contains("\"projectId\":\"heritage-001\"", json)
Assert.Contains("\"runId\":\"run-20260920-001\"", json)
Assert.Contains("\"totalSteps\":3", json)
Assert.DoesNotContain("\"stepId\":null", json)
[<Fact>]
let ``checkpoint event includes its step and artifact path`` () =
let event =
RunEvent.Checkpoint
{ Ids = ids
At = DateTimeOffset.Parse("2026-09-20T12:00:05Z")
StepId = "01-foundation"
StepIndex = 1
TotalSteps = 3
Message = "foundation exported"
ArtifactPath = "steps/01-foundation.glb" }
let wire = RunEvent.toWire event
Assert.Equal("checkpoint", wire.Kind)
Assert.Equal(Some "01-foundation", wire.StepId)
Assert.Equal(Some 3, wire.TotalSteps)
Assert.Equal(Some "steps/01-foundation.glb", wire.ArtifactPath)
[<Fact>]
let ``checkpoint event serializes total steps`` () =
let event =
RunEvent.Checkpoint
{ Ids = ids
At = DateTimeOffset.Parse("2026-09-20T12:00:05Z")
StepId = "01-foundation"
StepIndex = 0
TotalSteps = 3
Message = "foundation exported"
ArtifactPath = "steps/01-foundation.glb" }
Assert.Contains("\"totalSteps\":3", RunEvent.toJson event)
|