Skip to content

Commit a30e2e4

Browse files
Copilotsebastienros
andcommitted
Add comprehensive tests and update AstVisitor/AstRewriter
Co-authored-by: sebastienros <1165805+sebastienros@users.noreply.github.com>
1 parent 11e2fb5 commit a30e2e4

File tree

3 files changed

+190
-5
lines changed

3 files changed

+190
-5
lines changed

Fluid.Tests/CaseStatementTests.cs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,5 +311,106 @@ public async Task CaseEvaluateMultipleMatchingBlocks()
311311

312312
Assert.Equal("foobarbar", output);
313313
}
314+
315+
[Fact]
316+
public async Task CaseWithOrSeparatedWhenExpression()
317+
{
318+
var parser = new FluidParser();
319+
var template = "{% case title %}{% when 'foo' %}foo{% when 'bar' or 'Hello' %}bar{% endcase %}";
320+
321+
var result = parser.Parse(template);
322+
var context = new TemplateContext();
323+
context.SetValue("title", "Hello");
324+
var output = await result.RenderAsync(context);
325+
326+
Assert.Equal("bar", output);
327+
}
328+
329+
[Fact]
330+
public async Task CaseWithCommaSeparatedWhenExpression()
331+
{
332+
var parser = new FluidParser();
333+
var template = "{% case title %}{% when 'foo' %}foo{% when 'bar', 'Hello' %}bar{% endcase %}";
334+
335+
var result = parser.Parse(template);
336+
var context = new TemplateContext();
337+
context.SetValue("title", "Hello");
338+
var output = await result.RenderAsync(context);
339+
340+
Assert.Equal("bar", output);
341+
}
342+
343+
[Fact]
344+
public async Task CaseMixOrAndCommaSeparatedWhenExpression()
345+
{
346+
var parser = new FluidParser();
347+
var template = "{% case title %}{% when 'foo' %}foo{% when 'bar' or 'Hello', 'Hello' %}bar{% endcase %}";
348+
349+
var result = parser.Parse(template);
350+
var context = new TemplateContext();
351+
context.SetValue("title", "Hello");
352+
var output = await result.RenderAsync(context);
353+
354+
// Both 'bar' or 'Hello' and 'Hello' match, so bar is output twice
355+
Assert.Equal("barbar", output);
356+
}
357+
358+
[Fact]
359+
public async Task CaseNoWhensOnlyElse()
360+
{
361+
var parser = new FluidParser();
362+
var template = "{% case title %}{% else %}bar{% endcase %}";
363+
364+
var result = parser.Parse(template);
365+
var context = new TemplateContext();
366+
context.SetValue("title", "Hello");
367+
var output = await result.RenderAsync(context);
368+
369+
Assert.Equal("bar", output);
370+
}
371+
372+
[Fact]
373+
public async Task CaseNoWhensNoElse()
374+
{
375+
var parser = new FluidParser();
376+
var template = "{% case title %}{% endcase %}";
377+
378+
var result = parser.Parse(template);
379+
var context = new TemplateContext();
380+
context.SetValue("title", "Hello");
381+
var output = await result.RenderAsync(context);
382+
383+
Assert.Equal("", output);
384+
}
385+
386+
[Fact]
387+
public async Task CaseWhenExpressionUsingIdentifier()
388+
{
389+
var parser = new FluidParser();
390+
var template = "{% case title %}{% when other %}foo{% when 'goodbye' %}bar{% endcase %}";
391+
392+
var result = parser.Parse(template);
393+
var context = new TemplateContext();
394+
context.SetValue("title", "Hello");
395+
context.SetValue("other", "Hello");
396+
var output = await result.RenderAsync(context);
397+
398+
Assert.Equal("foo", output);
399+
}
400+
401+
[Fact]
402+
public async Task CaseTagsInsideWhenBlock()
403+
{
404+
var parser = new FluidParser();
405+
var template = "{% case title %}{% when other %}{% if true %}foo{% endif %}{% when 'goodbye' %}bar{% endcase %}";
406+
407+
var result = parser.Parse(template);
408+
var context = new TemplateContext();
409+
context.SetValue("title", "Hello");
410+
context.SetValue("other", "Hello");
411+
var output = await result.RenderAsync(context);
412+
413+
Assert.Equal("foo", output);
414+
}
314415
}
315416
}

Fluid/Ast/AstRewriter.cs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,66 @@ protected internal override Statement VisitCaptureStatement(CaptureStatement cap
276276

277277
protected internal override Statement VisitCaseStatement(CaseStatement caseStatement)
278278
{
279-
if (TryRewriteExpression(caseStatement.Expression, out var newExpression)
279+
// Handle new block-based structure
280+
if (caseStatement.Blocks.Count > 0)
281+
{
282+
var hasChanges = false;
283+
var newBlocks = new List<CaseBlock>();
284+
285+
if (TryRewriteExpression(caseStatement.Expression, out var newExpression))
286+
{
287+
hasChanges = true;
288+
}
289+
else
290+
{
291+
newExpression = caseStatement.Expression;
292+
}
293+
294+
foreach (var block in caseStatement.Blocks)
295+
{
296+
if (block is WhenBlock whenBlock)
297+
{
298+
var optionsChanged = TryRewriteExpressions(whenBlock.Options, out var newOptions);
299+
var statementsChanged = TryRewriteStatements(whenBlock.Statements, out var newStatements);
300+
301+
if (optionsChanged || statementsChanged)
302+
{
303+
hasChanges = true;
304+
newBlocks.Add(new WhenBlock(newOptions.ToArray(), newStatements.ToArray()));
305+
}
306+
else
307+
{
308+
newBlocks.Add(block);
309+
}
310+
}
311+
else if (block is ElseBlock elseBlock)
312+
{
313+
if (TryRewriteStatements(elseBlock.Statements, out var newStatements))
314+
{
315+
hasChanges = true;
316+
newBlocks.Add(new ElseBlock(newStatements.ToArray()));
317+
}
318+
else
319+
{
320+
newBlocks.Add(block);
321+
}
322+
}
323+
}
324+
325+
if (hasChanges)
326+
{
327+
return new CaseStatement(newExpression, newBlocks.ToArray());
328+
}
329+
330+
return caseStatement;
331+
}
332+
333+
// Handle old structure for backward compatibility
334+
if (TryRewriteExpression(caseStatement.Expression, out var newExpression2)
280335
| TryRewriteStatement(caseStatement.Else, out var newElseStatement)
281336
| TryRewriteStatements(caseStatement.Whens, out var newWhenStatements))
282337
{
283-
return new CaseStatement(newExpression, newElseStatement, newWhenStatements.ToArray());
338+
return new CaseStatement(newExpression2, newElseStatement, newWhenStatements.ToArray());
284339
}
285340

286341
return caseStatement;

Fluid/Ast/AstVisitor.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,41 @@ protected internal virtual Statement VisitCaseStatement(CaseStatement caseStatem
204204

205205
Visit(caseStatement.Expression);
206206

207-
foreach (var statement in caseStatement.Whens)
207+
// Visit new block-based structure if present
208+
if (caseStatement.Blocks.Count > 0)
208209
{
209-
Visit(statement);
210+
foreach (var block in caseStatement.Blocks)
211+
{
212+
if (block is WhenBlock whenBlock)
213+
{
214+
foreach (var option in whenBlock.Options)
215+
{
216+
Visit(option);
217+
}
218+
foreach (var statement in whenBlock.Statements)
219+
{
220+
Visit(statement);
221+
}
222+
}
223+
else if (block is ElseBlock elseBlock)
224+
{
225+
foreach (var statement in elseBlock.Statements)
226+
{
227+
Visit(statement);
228+
}
229+
}
230+
}
210231
}
232+
else
233+
{
234+
// Visit old structure for backward compatibility
235+
foreach (var statement in caseStatement.Whens)
236+
{
237+
Visit(statement);
238+
}
211239

212-
Visit(caseStatement.Else);
240+
Visit(caseStatement.Else);
241+
}
213242

214243
return caseStatement;
215244
}

0 commit comments

Comments
 (0)