Skip to content

Commit 0e5510e

Browse files
authored
Merge pull request #1284 from HubSpot/local-dt-test
Handle unknown and disabled filters inline in AstFilterChain
2 parents 5db2a86 + 96d3f35 commit 0e5510e

2 files changed

Lines changed: 105 additions & 2 deletions

File tree

src/main/java/com/hubspot/jinjava/el/ext/AstFilterChain.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ public Object eval(Bindings bindings, ELContext context) {
8585
e
8686
)
8787
);
88-
return null;
88+
value = null;
89+
continue;
8990
}
9091
if (filter == null) {
91-
return null;
92+
value = null;
93+
continue;
9294
}
9395

9496
Object[] args = evaluateFilterArgs(spec, bindings, context);

src/test/java/com/hubspot/jinjava/el/ext/AstFilterChainTest.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,19 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44

5+
import com.google.common.collect.ImmutableMap;
6+
import com.google.common.collect.ImmutableSet;
57
import com.hubspot.jinjava.Jinjava;
68
import com.hubspot.jinjava.JinjavaConfig;
9+
import com.hubspot.jinjava.interpret.Context;
10+
import com.hubspot.jinjava.interpret.RenderResult;
11+
import com.hubspot.jinjava.interpret.TemplateError.ErrorItem;
12+
import com.hubspot.jinjava.interpret.TemplateError.ErrorReason;
13+
import com.hubspot.jinjava.objects.date.PyishDate;
14+
import java.time.ZonedDateTime;
715
import java.util.HashMap;
816
import java.util.Map;
17+
import java.util.Set;
918
import org.junit.Before;
1019
import org.junit.Test;
1120

@@ -67,4 +76,96 @@ public void itHandlesFilterWithStringConversion() {
6776
String result = jinjava.render("{{ number|string|length }}", context);
6877
assertThat(result).isEqualTo("5");
6978
}
79+
80+
@Test
81+
public void itHandlesUnknownFilterInChain() {
82+
context.put("module", new PyishDate(ZonedDateTime.parse("2024-01-15T10:30:00Z")));
83+
RenderResult renderResult = jinjava.renderForResult(
84+
"{% set mid = module | local_dt|unixtimestamp | pprint | md5 %}{{ mid }}",
85+
context
86+
);
87+
assertThat(renderResult.getOutput())
88+
.as("Should produce MD5 output since chain continues past unknown filter")
89+
.hasSize(32);
90+
assertThat(
91+
renderResult
92+
.getErrors()
93+
.stream()
94+
.noneMatch(e -> e.getMessage().contains("Unknown filter"))
95+
)
96+
.as("Should not report 'Unknown filter' error")
97+
.isTrue();
98+
}
99+
100+
@Test
101+
public void itMatchesNonChainedBehaviorForUnknownFilter() {
102+
String template = "{{ name | unknown_filter | lower | md5 }}";
103+
Jinjava jinjavaUnoptimized = new Jinjava(
104+
JinjavaConfig.newBuilder().withEnableFilterChainOptimization(false).build()
105+
);
106+
RenderResult optimizedResult = jinjava.renderForResult(template, context);
107+
RenderResult unoptimizedResult = jinjavaUnoptimized.renderForResult(
108+
template,
109+
context
110+
);
111+
assertThat(optimizedResult.getOutput())
112+
.as("Optimized should match un-optimized for unknown filter in chain")
113+
.isEqualTo(unoptimizedResult.getOutput());
114+
}
115+
116+
@Test
117+
public void itSkipsDisabledFilterAndContinuesChain() {
118+
Map<Context.Library, Set<String>> disabled = ImmutableMap.of(
119+
Context.Library.FILTER,
120+
ImmutableSet.of("lower")
121+
);
122+
Jinjava jinjavaWithDisabled = new Jinjava(
123+
JinjavaConfig
124+
.newBuilder()
125+
.withEnableFilterChainOptimization(true)
126+
.withDisabled(disabled)
127+
.build()
128+
);
129+
130+
RenderResult result = jinjavaWithDisabled.renderForResult(
131+
"{{ name|trim|lower|capitalize }}",
132+
context
133+
);
134+
135+
assertThat(result.getErrors()).isNotEmpty();
136+
assertThat(result.getErrors().get(0).getItem()).isEqualTo(ErrorItem.FILTER);
137+
assertThat(result.getErrors().get(0).getReason()).isEqualTo(ErrorReason.DISABLED);
138+
assertThat(result.getErrors().get(0).getMessage()).contains("lower");
139+
}
140+
141+
@Test
142+
public void itMatchesNonChainedBehaviorForDisabledFilter() {
143+
Map<Context.Library, Set<String>> disabled = ImmutableMap.of(
144+
Context.Library.FILTER,
145+
ImmutableSet.of("lower")
146+
);
147+
String template = "{{ name|trim|lower|capitalize }}";
148+
149+
Jinjava optimized = new Jinjava(
150+
JinjavaConfig
151+
.newBuilder()
152+
.withEnableFilterChainOptimization(true)
153+
.withDisabled(disabled)
154+
.build()
155+
);
156+
Jinjava unoptimized = new Jinjava(
157+
JinjavaConfig
158+
.newBuilder()
159+
.withEnableFilterChainOptimization(false)
160+
.withDisabled(disabled)
161+
.build()
162+
);
163+
164+
RenderResult optimizedResult = optimized.renderForResult(template, context);
165+
RenderResult unoptimizedResult = unoptimized.renderForResult(template, context);
166+
167+
assertThat(optimizedResult.getOutput())
168+
.as("Optimized should match un-optimized for disabled filter in chain")
169+
.isEqualTo(unoptimizedResult.getOutput());
170+
}
70171
}

0 commit comments

Comments
 (0)