@@ -76,6 +76,124 @@ public async Task RenderChangelogs_WithValidBundle_CreatesMarkdownFiles()
7676 indexContent . Should ( ) . Contain ( "Test feature" ) ;
7777 }
7878
79+ [ Fact ]
80+ public async Task RenderChangelogs_WithMultipleTypes_DoesNotIncludeCrossFileLinksInIndex ( )
81+ {
82+ // Arrange
83+ var changelogDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
84+ FileSystem . Directory . CreateDirectory ( changelogDir ) ;
85+
86+ // Create test changelog files with different types to trigger separated files
87+ // language=yaml
88+ var featureChangelog =
89+ """
90+ title: Test feature
91+ type: feature
92+ products:
93+ - product: elasticsearch
94+ target: 9.3.0
95+ prs:
96+ - "100"
97+ """ ;
98+
99+ // language=yaml
100+ var deprecationChangelog =
101+ """
102+ title: Deprecated API
103+ type: deprecation
104+ products:
105+ - product: elasticsearch
106+ target: 9.3.0
107+ prs:
108+ - "200"
109+ """ ;
110+
111+ // language=yaml
112+ var highlightChangelog =
113+ """
114+ title: Highlighted feature
115+ type: feature
116+ highlight: true
117+ products:
118+ - product: elasticsearch
119+ target: 9.3.0
120+ prs:
121+ - "300"
122+ """ ;
123+
124+ var featureFile = FileSystem . Path . Join ( changelogDir , "feature.yaml" ) ;
125+ var deprecationFile = FileSystem . Path . Join ( changelogDir , "deprecation.yaml" ) ;
126+ var highlightFile = FileSystem . Path . Join ( changelogDir , "highlight.yaml" ) ;
127+
128+ await FileSystem . File . WriteAllTextAsync ( featureFile , featureChangelog , TestContext . Current . CancellationToken ) ;
129+ await FileSystem . File . WriteAllTextAsync ( deprecationFile , deprecationChangelog , TestContext . Current . CancellationToken ) ;
130+ await FileSystem . File . WriteAllTextAsync ( highlightFile , highlightChangelog , TestContext . Current . CancellationToken ) ;
131+
132+ // Create bundle file
133+ var bundleFile = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) , "bundle.yaml" ) ;
134+ FileSystem . Directory . CreateDirectory ( FileSystem . Path . GetDirectoryName ( bundleFile ) ! ) ;
135+
136+ // language=yaml
137+ var bundleContent =
138+ $ """
139+ products:
140+ - product: elasticsearch
141+ target: 9.3.0
142+ entries:
143+ - file:
144+ name: feature.yaml
145+ checksum: { ComputeSha1 ( featureChangelog ) }
146+ - file:
147+ name: deprecation.yaml
148+ checksum: { ComputeSha1 ( deprecationChangelog ) }
149+ - file:
150+ name: highlight.yaml
151+ checksum: { ComputeSha1 ( highlightChangelog ) }
152+ """ ;
153+ await FileSystem . File . WriteAllTextAsync ( bundleFile , bundleContent , TestContext . Current . CancellationToken ) ;
154+
155+ var outputDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
156+
157+ var input = new RenderChangelogsArguments
158+ {
159+ Bundles = [ new BundleInput { BundleFile = bundleFile , Directory = changelogDir } ] ,
160+ Output = outputDir ,
161+ Title = "9.3.0"
162+ } ;
163+
164+ // Act
165+ var result = await Service . RenderChangelogs ( Collector , input , TestContext . Current . CancellationToken ) ;
166+
167+ // Assert
168+ result . Should ( ) . BeTrue ( ) ;
169+ Collector . Errors . Should ( ) . Be ( 0 ) ;
170+
171+ // Verify index.md exists but does NOT contain cross-file links
172+ var indexFile = FileSystem . Path . Join ( outputDir , "9.3.0" , "index.md" ) ;
173+ FileSystem . File . Exists ( indexFile ) . Should ( ) . BeTrue ( ) ;
174+ var indexContent = await FileSystem . File . ReadAllTextAsync ( indexFile , TestContext . Current . CancellationToken ) ;
175+
176+ indexContent . Should ( ) . Contain ( "## 9.3.0" ) ;
177+ indexContent . Should ( ) . Contain ( "Test feature" ) ;
178+ indexContent . Should ( ) . Contain ( "Highlighted feature" ) ;
179+
180+ // Verify NO cross-file links are present
181+ indexContent . Should ( ) . NotContain ( "[Highlights]" ) ;
182+ indexContent . Should ( ) . NotContain ( "[Deprecations]" ) ;
183+ indexContent . Should ( ) . NotContain ( "/release-notes/" ) ;
184+
185+ // Verify individual separated files are still generated
186+ var deprecationsFile = FileSystem . Path . Join ( outputDir , "9.3.0" , "deprecations.md" ) ;
187+ FileSystem . File . Exists ( deprecationsFile ) . Should ( ) . BeTrue ( ) ;
188+ var deprecationsContent = await FileSystem . File . ReadAllTextAsync ( deprecationsFile , TestContext . Current . CancellationToken ) ;
189+ deprecationsContent . Should ( ) . Contain ( "Deprecated API" ) ;
190+
191+ var highlightsFile = FileSystem . Path . Join ( outputDir , "9.3.0" , "highlights.md" ) ;
192+ FileSystem . File . Exists ( highlightsFile ) . Should ( ) . BeTrue ( ) ;
193+ var highlightsContent = await FileSystem . File . ReadAllTextAsync ( highlightsFile , TestContext . Current . CancellationToken ) ;
194+ highlightsContent . Should ( ) . Contain ( "Highlighted feature" ) ;
195+ }
196+
79197 [ Fact ]
80198 public async Task RenderChangelogs_WithMultipleBundles_MergesAndRenders ( )
81199 {
0 commit comments