@@ -39,6 +39,52 @@ def parse_fixture(name)
3939 expect ( rects . size ) . to be >= 3
4040 end
4141
42+ it "renders layered architecture annotations once each" do
43+ scene = parse_fixture ( "layered_architecture.txt" )
44+ svg = renderer . render ( scene , theme : theme )
45+ doc = Nokogiri ::XML ( svg )
46+
47+ annotations = doc . css ( "text" ) . map ( &:text ) . select { |text | text . start_with? ( "← " ) }
48+ counts = annotations . each_with_object ( Hash . new ( 0 ) ) { |text , tally | tally [ text ] += 1 }
49+
50+ expect ( counts [ "← ユーザーとの対話" ] ) . to eq ( 1 )
51+ expect ( counts [ "← コマンド解析" ] ) . to eq ( 1 )
52+ expect ( counts [ "← コア機能" ] ) . to eq ( 1 )
53+ expect ( counts [ "← データ保存" ] ) . to eq ( 1 )
54+ end
55+
56+ it "renders annotations with middle baseline alignment" do
57+ scene = parse_fixture ( "layered_architecture.txt" )
58+ svg = renderer . render ( scene , theme : theme )
59+ doc = Nokogiri ::XML ( svg )
60+
61+ annotation_texts = doc . css ( "text" ) . select { |node | node . text . start_with? ( "← " ) }
62+ expect ( annotation_texts ) . not_to be_empty
63+ expect ( annotation_texts . map { |node | node [ "dominant-baseline" ] } . uniq ) . to eq ( [ "middle" ] )
64+ end
65+
66+ it "aligns annotation y with corresponding labels" do
67+ scene = parse_fixture ( "layered_architecture.txt" )
68+ svg = renderer . render ( scene , theme : theme , valign : :center )
69+ doc = Nokogiri ::XML ( svg )
70+
71+ pairs = {
72+ "REPL (UI)" => "← ユーザーとの対話" ,
73+ "Command Parser" => "← コマンド解析" ,
74+ "Database" => "← コア機能" ,
75+ "StringHashMap" => "← データ保存"
76+ }
77+
78+ pairs . each do |label_text , annotation_text |
79+ label_node = doc . css ( "text" ) . find { |node | node . text == label_text }
80+ annotation_node = doc . css ( "text" ) . find { |node | node . text == annotation_text }
81+
82+ expect ( label_node ) . not_to be_nil
83+ expect ( annotation_node ) . not_to be_nil
84+ expect ( annotation_node [ "y" ] . to_f ) . to be_within ( 0.1 ) . of ( label_node [ "y" ] . to_f )
85+ end
86+ end
87+
4288 it "includes section divider lines" do
4389 scene = parse_fixture ( "sectioned_box.txt" )
4490 svg = renderer . render ( scene , theme : theme )
0 commit comments