@@ -132,4 +132,202 @@ public async Task RenderChangelogs_WithTitleAndNoTargets_NoWarning()
132132 d . Severity == Severity . Warning &&
133133 d . Message . Contains ( "No --title option provided" ) ) ;
134134 }
135+
136+ [ Fact ]
137+ public async Task RenderChangelogs_WithIsoDateTarget_FormatsDateInHeading ( )
138+ {
139+ // Arrange
140+ var changelogDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
141+ FileSystem . Directory . CreateDirectory ( changelogDir ) ;
142+
143+ // Create test changelog file with ISO date target
144+ // language=yaml
145+ var changelog1 =
146+ """
147+ title: Test feature
148+ type: feature
149+ products:
150+ - product: elasticsearch
151+ target: 2026-05-04
152+ prs:
153+ - "100"
154+ """ ;
155+
156+ var changelogFile = FileSystem . Path . Join ( changelogDir , "1755268130-test-feature.yaml" ) ;
157+ await FileSystem . File . WriteAllTextAsync ( changelogFile , changelog1 , TestContext . Current . CancellationToken ) ;
158+
159+ // Create bundle file with ISO date target
160+ var bundleDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
161+ FileSystem . Directory . CreateDirectory ( bundleDir ) ;
162+
163+ var bundleFile = FileSystem . Path . Join ( bundleDir , "bundle.yaml" ) ;
164+ // language=yaml
165+ var bundleContent =
166+ $ """
167+ products:
168+ - product: elasticsearch
169+ target: 2026-05-04
170+ entries:
171+ - file:
172+ name: 1755268130-test-feature.yaml
173+ checksum: { ComputeSha1 ( changelog1 ) }
174+ """ ;
175+ await FileSystem . File . WriteAllTextAsync ( bundleFile , bundleContent , TestContext . Current . CancellationToken ) ;
176+
177+ var outputDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
178+
179+ var input = new RenderChangelogsArguments
180+ {
181+ Bundles = [ new BundleInput { BundleFile = bundleFile , Directory = changelogDir } ] ,
182+ Output = outputDir
183+ // Note: Title is not set, should default to formatted date
184+ } ;
185+
186+ // Act
187+ var result = await Service . RenderChangelogs ( Collector , input , TestContext . Current . CancellationToken ) ;
188+
189+ // Assert
190+ result . Should ( ) . BeTrue ( ) ;
191+ Collector . Errors . Should ( ) . Be ( 0 ) ;
192+
193+ // Check that output directory uses raw date slug
194+ var indexFile = FileSystem . Path . Join ( outputDir , "2026-05-04" , "index.md" ) ;
195+ FileSystem . File . Exists ( indexFile ) . Should ( ) . BeTrue ( ) ;
196+
197+ // Check that heading uses formatted date but anchor uses raw date
198+ var indexContent = await FileSystem . File . ReadAllTextAsync ( indexFile , TestContext . Current . CancellationToken ) ;
199+ indexContent . Should ( ) . Contain ( "## May 4, 2026 [elastic-release-notes-2026-05-04]" ) ;
200+ }
201+
202+ [ Fact ]
203+ public async Task RenderChangelogs_WithYearMonthTarget_FormatsDateInHeading ( )
204+ {
205+ // Arrange
206+ var changelogDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
207+ FileSystem . Directory . CreateDirectory ( changelogDir ) ;
208+
209+ // Create test changelog file with year-month target
210+ // language=yaml
211+ var changelog1 =
212+ """
213+ title: Test feature
214+ type: feature
215+ products:
216+ - product: elasticsearch
217+ target: 2026-05
218+ prs:
219+ - "100"
220+ """ ;
221+
222+ var changelogFile = FileSystem . Path . Join ( changelogDir , "1755268130-test-feature.yaml" ) ;
223+ await FileSystem . File . WriteAllTextAsync ( changelogFile , changelog1 , TestContext . Current . CancellationToken ) ;
224+
225+ // Create bundle file with year-month target
226+ var bundleDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
227+ FileSystem . Directory . CreateDirectory ( bundleDir ) ;
228+
229+ var bundleFile = FileSystem . Path . Join ( bundleDir , "bundle.yaml" ) ;
230+ // language=yaml
231+ var bundleContent =
232+ $ """
233+ products:
234+ - product: elasticsearch
235+ target: 2026-05
236+ entries:
237+ - file:
238+ name: 1755268130-test-feature.yaml
239+ checksum: { ComputeSha1 ( changelog1 ) }
240+ """ ;
241+ await FileSystem . File . WriteAllTextAsync ( bundleFile , bundleContent , TestContext . Current . CancellationToken ) ;
242+
243+ var outputDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
244+
245+ var input = new RenderChangelogsArguments
246+ {
247+ Bundles = [ new BundleInput { BundleFile = bundleFile , Directory = changelogDir } ] ,
248+ Output = outputDir
249+ // Note: Title is not set, should default to formatted date
250+ } ;
251+
252+ // Act
253+ var result = await Service . RenderChangelogs ( Collector , input , TestContext . Current . CancellationToken ) ;
254+
255+ // Assert
256+ result . Should ( ) . BeTrue ( ) ;
257+ Collector . Errors . Should ( ) . Be ( 0 ) ;
258+
259+ // Check that output directory uses raw date slug
260+ var indexFile = FileSystem . Path . Join ( outputDir , "2026-05" , "index.md" ) ;
261+ FileSystem . File . Exists ( indexFile ) . Should ( ) . BeTrue ( ) ;
262+
263+ // Check that heading uses formatted date but anchor uses raw date
264+ var indexContent = await FileSystem . File . ReadAllTextAsync ( indexFile , TestContext . Current . CancellationToken ) ;
265+ indexContent . Should ( ) . Contain ( "## May 2026 [elastic-release-notes-2026-05]" ) ;
266+ }
267+
268+ [ Fact ]
269+ public async Task RenderChangelogs_WithExplicitDateTitle_DoesNotFormatTitle ( )
270+ {
271+ // Arrange
272+ var changelogDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
273+ FileSystem . Directory . CreateDirectory ( changelogDir ) ;
274+
275+ // Create test changelog file with ISO date target
276+ // language=yaml
277+ var changelog1 =
278+ """
279+ title: Test feature
280+ type: feature
281+ products:
282+ - product: elasticsearch
283+ target: 2026-05-04
284+ prs:
285+ - "100"
286+ """ ;
287+
288+ var changelogFile = FileSystem . Path . Join ( changelogDir , "1755268130-test-feature.yaml" ) ;
289+ await FileSystem . File . WriteAllTextAsync ( changelogFile , changelog1 , TestContext . Current . CancellationToken ) ;
290+
291+ // Create bundle file with ISO date target
292+ var bundleDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
293+ FileSystem . Directory . CreateDirectory ( bundleDir ) ;
294+
295+ var bundleFile = FileSystem . Path . Join ( bundleDir , "bundle.yaml" ) ;
296+ // language=yaml
297+ var bundleContent =
298+ $ """
299+ products:
300+ - product: elasticsearch
301+ target: 2026-05-04
302+ entries:
303+ - file:
304+ name: 1755268130-test-feature.yaml
305+ checksum: { ComputeSha1 ( changelog1 ) }
306+ """ ;
307+ await FileSystem . File . WriteAllTextAsync ( bundleFile , bundleContent , TestContext . Current . CancellationToken ) ;
308+
309+ var outputDir = FileSystem . Path . Join ( Paths . WorkingDirectoryRoot . FullName , Guid . NewGuid ( ) . ToString ( ) ) ;
310+
311+ var input = new RenderChangelogsArguments
312+ {
313+ Bundles = [ new BundleInput { BundleFile = bundleFile , Directory = changelogDir } ] ,
314+ Output = outputDir ,
315+ Title = "2026-05-04" // Explicit title provided - should stay literal
316+ } ;
317+
318+ // Act
319+ var result = await Service . RenderChangelogs ( Collector , input , TestContext . Current . CancellationToken ) ;
320+
321+ // Assert
322+ result . Should ( ) . BeTrue ( ) ;
323+ Collector . Errors . Should ( ) . Be ( 0 ) ;
324+
325+ // Check that output directory uses title slug
326+ var indexFile = FileSystem . Path . Join ( outputDir , "2026-05-04" , "index.md" ) ;
327+ FileSystem . File . Exists ( indexFile ) . Should ( ) . BeTrue ( ) ;
328+
329+ // Check that heading uses literal title (no formatting applied)
330+ var indexContent = await FileSystem . File . ReadAllTextAsync ( indexFile , TestContext . Current . CancellationToken ) ;
331+ indexContent . Should ( ) . Contain ( "## 2026-05-04 [elastic-release-notes-2026-05-04]" ) ;
332+ }
135333}
0 commit comments