Skip to content

Commit d040d30

Browse files
authored
Merge pull request #639 from Handlebars-Net/fix/issue-285
fix: support includeZero=true on #if helper (issue #285)
2 parents 3dfe95a + 5b483d7 commit d040d30

3 files changed

Lines changed: 107 additions & 4 deletions

File tree

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using Xunit;
2+
3+
namespace HandlebarsDotNet.Test.Issues
4+
{
5+
/// <summary>
6+
/// Regression tests for GitHub issue #285:
7+
/// Support the <c>includeZero=true</c> hash argument on the built-in <c>#if</c> helper,
8+
/// matching Handlebars.js behaviour (https://handlebarsjs.com/guide/builtin-helpers.html#if).
9+
/// </summary>
10+
public class Issue285Tests
11+
{
12+
[Fact]
13+
public void IfWithIncludeZeroTrue_ZeroInt_RendersBlock()
14+
{
15+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
16+
var template = Handlebars.Compile(source);
17+
var result = template(new { value = 0 });
18+
Assert.Equal("yes", result);
19+
}
20+
21+
[Fact]
22+
public void IfWithIncludeZeroTrue_ZeroDouble_RendersBlock()
23+
{
24+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
25+
var template = Handlebars.Compile(source);
26+
var result = template(new { value = 0.0 });
27+
Assert.Equal("yes", result);
28+
}
29+
30+
[Fact]
31+
public void IfWithIncludeZeroTrue_NonZeroInt_RendersBlock()
32+
{
33+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
34+
var template = Handlebars.Compile(source);
35+
var result = template(new { value = 1 });
36+
Assert.Equal("yes", result);
37+
}
38+
39+
[Fact]
40+
public void IfWithIncludeZeroFalse_ZeroInt_DoesNotRenderBlock()
41+
{
42+
var source = "{{#if value includeZero=false}}yes{{else}}no{{/if}}";
43+
var template = Handlebars.Compile(source);
44+
var result = template(new { value = 0 });
45+
Assert.Equal("no", result);
46+
}
47+
48+
[Fact]
49+
public void IfWithoutIncludeZero_ZeroInt_StillTreatedAsFalsy()
50+
{
51+
var source = "{{#if value}}yes{{else}}no{{/if}}";
52+
var template = Handlebars.Compile(source);
53+
var result = template(new { value = 0 });
54+
Assert.Equal("no", result);
55+
}
56+
57+
[Fact]
58+
public void IfWithIncludeZeroTrue_NullValue_StillTreatedAsFalsy()
59+
{
60+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
61+
var template = Handlebars.Compile(source);
62+
var result = template(new { value = (object)null });
63+
Assert.Equal("no", result);
64+
}
65+
66+
[Fact]
67+
public void IfWithIncludeZeroTrue_EmptyString_StillTreatedAsFalsy()
68+
{
69+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
70+
var template = Handlebars.Compile(source);
71+
var result = template(new { value = string.Empty });
72+
Assert.Equal("no", result);
73+
}
74+
75+
[Fact]
76+
public void IfWithIncludeZeroTrue_FalseBool_StillTreatedAsFalsy()
77+
{
78+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
79+
var template = Handlebars.Compile(source);
80+
var result = template(new { value = false });
81+
Assert.Equal("no", result);
82+
}
83+
84+
[Fact]
85+
public void IfWithIncludeZeroTrue_TrueBool_RendersBlock()
86+
{
87+
var source = "{{#if value includeZero=true}}yes{{else}}no{{/if}}";
88+
var template = Handlebars.Compile(source);
89+
var result = template(new { value = true });
90+
Assert.Equal("yes", result);
91+
}
92+
93+
[Fact]
94+
public void IfWithHashArgument_DoesNotCrash()
95+
{
96+
// Regression test: passing any hash arg to #if previously threw
97+
// InvalidOperationException: "Sequence contains more than one element".
98+
var source = "{{#if value includeZero=true}}yes{{/if}}";
99+
var template = Handlebars.Compile(source);
100+
var result = template(new { value = 42 });
101+
Assert.Equal("yes", result);
102+
}
103+
}
104+
}

source/Handlebars/Compiler/Lexer/Converter/BlockAccumulators/ConditionalBlockAccumulatorContext.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ namespace HandlebarsDotNet.Compiler
88
internal class ConditionalBlockAccumulatorContext : BlockAccumulatorContext
99
{
1010
private enum TestType { Direct, Reverse }
11-
11+
1212
private static readonly HashSet<string> ValidHelperNames = new HashSet<string> { "if", "unless" };
13-
13+
1414
private readonly List<ConditionalExpression> _conditionalBlock = new List<ConditionalExpression>();
1515
private Expression _currentCondition;
1616
private List<Expression> _bodyBuffer = new List<Expression>();
17-
17+
1818
public sealed override string BlockName { get; protected set; }
1919

2020
public ConditionalBlockAccumulatorContext(Expression startingNode)

source/Handlebars/Compiler/Translation/Expression/BoolishConverter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ protected override Expression VisitBoolishExpression(BoolishExpression bex)
3030
var @object = Arg<object>(condition);
3131
var includeZero = Arg<bool>(hashParameters.Parameters.Count == 1 ? hashParameters.Parameters[IncludeZero] : Expression.Constant(false));
3232
return Call(() => HandlebarsUtils.IsTruthyOrNonEmpty(@object, includeZero));
33-
3433
}
3534
}
3635
}

0 commit comments

Comments
 (0)