Skip to content

Commit 9811d5e

Browse files
authored
Fix conditional statement (#109)
* Add tests to identify the bug * Fix the rendering bug The else branch got pre-rendered, despite the condition.
1 parent 160d18e commit 9811d5e

File tree

2 files changed

+76
-33
lines changed

2 files changed

+76
-33
lines changed

Sources/HTMLKit/Framework/Environment/Statements/BranchStatements.swift

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,16 @@
99
/// The statement is for
1010
public struct IF: GlobalElement {
1111

12-
public enum IFPrerenderErrors: Error {
13-
14-
case dynamiclyEvaluatedCondition
15-
}
16-
1712
internal class Condition {
1813

1914
internal let condition: Conditionable
2015

21-
internal var formula: Formula
22-
23-
internal var view: AnyContent
16+
internal var content: AnyContent
2417

2518
internal init(condition: Conditionable) {
2619

2720
self.condition = condition
28-
self.view = ""
29-
self.formula = Formula()
21+
self.content = ""
3022
}
3123
}
3224

@@ -39,39 +31,39 @@ public struct IF: GlobalElement {
3931
public init(_ condition: Conditionable, @ContentBuilder<AnyContent> content: () -> AnyContent) {
4032

4133
let condition = Condition(condition: condition)
42-
condition.view = content()
34+
condition.content = content()
4335

4436
self.conditions = [condition]
4537
}
4638

4739
public func elseIf(_ condition: Conditionable, @ContentBuilder<AnyContent> content: () -> AnyContent) -> IF {
4840

4941
let condition = Condition(condition: condition)
50-
condition.view = content()
42+
condition.content = content()
5143

5244
return .init(conditions: conditions + [condition])
5345
}
5446

5547
public func elseIf<T>(isNil path: TemplateValue<T?>, @ContentBuilder<AnyContent> content: () -> AnyContent) -> IF {
5648

5749
let condition = Condition(condition: IsNullCondition<T>(lhs: path))
58-
condition.view = content()
50+
condition.content = content()
5951

6052
return .init(conditions: conditions + [condition])
6153
}
6254

6355
public func elseIf<T>(isNotNil path: TemplateValue<T?>, @ContentBuilder<AnyContent> content: () -> AnyContent) -> IF {
6456

6557
let condition = Condition(condition: NotNullCondition<T>(lhs: path))
66-
condition.view = content()
58+
condition.content = content()
6759

6860
return .init(conditions: conditions + [condition])
6961
}
7062

7163
public func `else`(@ContentBuilder<AnyContent> content: () -> AnyContent) -> IF {
7264

7365
let condition = Condition(condition: AlwaysTrueCondition())
74-
condition.view = content()
66+
condition.content = content()
7567

7668
return .init(conditions: conditions + [condition])
7769
}
@@ -84,7 +76,7 @@ extension IF: AnyContent {
8476
IF(conditions: conditions.map { htmlCondition in
8577

8678
let scriptCondition = IF.Condition(condition: htmlCondition.condition)
87-
scriptCondition.view = htmlCondition.view.scripts
79+
scriptCondition.content = htmlCondition.content.scripts
8880

8981
return scriptCondition
9082
})
@@ -95,31 +87,22 @@ extension IF: AnyContent {
9587
var isStaticallyEvaluated = true
9688

9789
for condition in conditions {
98-
99-
condition.formula.calendar = formula.calendar
100-
101-
condition.formula.timeZone = formula.timeZone
10290

10391
do {
10492

10593
guard isStaticallyEvaluated else {
106-
throw IFPrerenderErrors.dynamiclyEvaluatedCondition
94+
break
10795
}
10896

109-
let testContext = ContextManager<Void>(contexts: [:])
110-
111-
if try condition.condition.evaluate(with: testContext) {
97+
if try condition.condition.evaluate(with: ContextManager<Void>(contexts: [:])) {
11298

113-
try condition.view.prerender(formula)
99+
try condition.content.prerender(formula)
114100

115-
return // Returning as the first true condition should be the only one that is rendered
101+
break
116102
}
117103

118104
} catch {
119-
120105
isStaticallyEvaluated = false
121-
122-
try condition.prerender(formula)
123106
}
124107
}
125108

@@ -144,11 +127,11 @@ extension IF: AnyContent {
144127
extension IF.Condition: AnyContent {
145128

146129
public func prerender(_ formula: Formula) throws {
147-
try view.prerender(formula)
130+
try content.prerender(formula)
148131
}
149132

150133
public func render<T>(with manager: ContextManager<T>) throws -> String {
151-
return try formula.render(with: manager)
134+
return try content.render(with: manager)
152135
}
153136
}
154137

Tests/HTMLKitTests/StatementsTests.swift

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ final class StatementsTests: XCTestCase {
1515

1616
var renderer = Renderer()
1717

18-
func testIfStatement() throws {
18+
func testIfStatementWithConstantValue() throws {
1919

2020
let isValid: TemplateValue<Bool> = .constant(true)
2121

@@ -40,7 +40,37 @@ final class StatementsTests: XCTestCase {
4040
)
4141
}
4242

43-
func testElseStatement() throws {
43+
func testIfStatementWithVariableValue() throws {
44+
45+
struct TestContext {
46+
var isValid: Bool
47+
}
48+
49+
@TemplateValue(TestContext.self)
50+
var item
51+
52+
let page = TestPage {
53+
IF(item.isValid) {
54+
Paragraph {
55+
"true"
56+
}
57+
}.else {
58+
Paragraph {
59+
"false"
60+
}
61+
}
62+
}
63+
64+
try renderer.add(layout: page)
65+
66+
XCTAssertEqual(try renderer.render(layout: TestPage.self, with: TestContext(isValid: true)),
67+
"""
68+
<p>true</p>
69+
"""
70+
)
71+
}
72+
73+
func testElseStatementWithConstantValue() throws {
4474

4575
let isValid: TemplateValue<Bool> = .constant(false)
4676

@@ -65,6 +95,36 @@ final class StatementsTests: XCTestCase {
6595
)
6696
}
6797

98+
func testElseStatementWithVariableValue() throws {
99+
100+
struct TestContext {
101+
var isValid: Bool
102+
}
103+
104+
@TemplateValue(TestContext.self)
105+
var item
106+
107+
let page = TestPage {
108+
IF(item.isValid) {
109+
Paragraph {
110+
"true"
111+
}
112+
}.else {
113+
Paragraph {
114+
"false"
115+
}
116+
}
117+
}
118+
119+
try renderer.add(layout: page)
120+
121+
XCTAssertEqual(try renderer.render(layout: TestPage.self, with: TestContext(isValid: false)),
122+
"""
123+
<p>false</p>
124+
"""
125+
)
126+
}
127+
68128
func testElseIfStatement() throws {
69129

70130
let age: TemplateValue<Int> = .constant(16)

0 commit comments

Comments
 (0)