@@ -14,7 +14,7 @@ func TestGraphSVGRendersNeighborhood(t *testing.T) {
1414 Out : []domain.Ref {{World : "soul" , Path : "/out.md" }},
1515 In : []domain.Ref {{World : "soul" , Path : "/in.md" }},
1616 }
17- svg := string (graphSVG (n , func (r domain.Ref ) string { return docRoute (r .World , r .Path ) }))
17+ svg := string (graphSVG (n , func (r domain.Ref ) string { return docRoute (r .World , r .Path ) }, nil ))
1818
1919 if ! strings .Contains (svg , "<svg class=\" graph\" " ) {
2020 t .Errorf ("not an svg: %s" , svg )
@@ -32,7 +32,7 @@ func TestGraphSVGRendersNeighborhood(t *testing.T) {
3232
3333func TestGraphSVGEmptyNeighborhood (t * testing.T ) {
3434 n := domain.Neighborhood {Center : domain.Ref {World : "soul" , Path : "/lonely.md" }}
35- svg := string (graphSVG (n , func (_ domain.Ref ) string { return "" }))
35+ svg := string (graphSVG (n , func (_ domain.Ref ) string { return "" }, nil ))
3636 if ! strings .Contains (svg , "graph-empty" ) {
3737 t .Errorf ("empty neighborhood should render the honest empty state: %s" , svg )
3838 }
@@ -76,6 +76,45 @@ func TestTrailGraphPaneContinuesTrail(t *testing.T) {
7676 }
7777}
7878
79+ func TestGraphOverlayForFocusedDoc (t * testing.T ) {
80+ svc := & fakeReading {
81+ docs : map [string ]domain.Document {"/x.md" : {Title : "X" , Path : "/x.md" , HTML : "<p>x</p>" }},
82+ neighbor : map [string ]domain.Neighborhood {
83+ "/x.md" : {Center : domain.Ref {World : "w.io" , Path : "/x.md" },
84+ Out : []domain.Ref {{World : "w.io" , Path : "/y.md" }}},
85+ },
86+ }
87+ body := get (readingApp (t , svc ), "/t/w.io/d/x.md" ).Body .String ()
88+
89+ // The focused doc's graph overlay is embedded (summoned by `g`), not a pane.
90+ if ! strings .Contains (body , `id="graph-overlay"` ) {
91+ t .Errorf ("graph overlay missing for focused doc: %s" , body )
92+ }
93+ // A node click is a trail jump from the focus (navigating dismisses the overlay).
94+ if ! strings .Contains (body , `href="/t/w.io/d/x.md/~/w.io/d/y.md"` ) {
95+ t .Errorf ("graph overlay node should jump the trail: %s" , body )
96+ }
97+ }
98+
99+ func TestGraphOverlayMarksWalkedNeighbors (t * testing.T ) {
100+ // Trail y → x (focus x); x links to y, and y is on the trail, so y renders
101+ // as a walked node in x's overlay.
102+ svc := & fakeReading {
103+ docs : map [string ]domain.Document {
104+ "/x.md" : {Title : "X" , Path : "/x.md" , HTML : "<p>x</p>" },
105+ "/y.md" : {Title : "Y" , Path : "/y.md" , HTML : "<p>y</p>" },
106+ },
107+ neighbor : map [string ]domain.Neighborhood {
108+ "/x.md" : {Center : domain.Ref {World : "w.io" , Path : "/x.md" },
109+ Out : []domain.Ref {{World : "w.io" , Path : "/y.md" }}},
110+ },
111+ }
112+ body := get (readingApp (t , svc ), "/t/w.io/d/y.md/~/w.io/d/x.md" ).Body .String ()
113+ if ! strings .Contains (body , "graph-walked" ) {
114+ t .Errorf ("neighbor on the trail should render as walked: %s" , body )
115+ }
116+ }
117+
79118func TestDocMarginOffersGraphAndBacklinks (t * testing.T ) {
80119 svc := & fakeReading {
81120 docs : map [string ]domain.Document {
@@ -87,8 +126,9 @@ func TestDocMarginOffersGraphAndBacklinks(t *testing.T) {
87126 }
88127 body := get (readingApp (t , svc ), "/t/w.io/d/x.md" ).Body .String ()
89128
90- // The margin's graph affordance opens this doc's graph pane on the trail.
91- if ! strings .Contains (body , `href="/t/w.io/d/x.md/~/w.io/g/x.md"` ) {
129+ // The margin's graph affordance opens the graph overlay (ADR 0006 §4): a /g/
130+ // permalink (degrade) that islands.js intercepts on the canvas.
131+ if ! strings .Contains (body , `href="/w/w.io/g/x.md" class="graph-open"` ) {
92132 t .Errorf ("margin graph affordance missing: %s" , body )
93133 }
94134 // The backlinks block lists the referrer with a hover-preview link.
0 commit comments