1import pytest 2 3from jinja2 import Environment 4from jinja2 import Markup 5 6 7class MyDict(dict): 8 pass 9 10 11class TestTestsCase: 12 def test_defined(self, env): 13 tmpl = env.from_string("{{ missing is defined }}|{{ true is defined }}") 14 assert tmpl.render() == "False|True" 15 16 def test_even(self, env): 17 tmpl = env.from_string("""{{ 1 is even }}|{{ 2 is even }}""") 18 assert tmpl.render() == "False|True" 19 20 def test_odd(self, env): 21 tmpl = env.from_string("""{{ 1 is odd }}|{{ 2 is odd }}""") 22 assert tmpl.render() == "True|False" 23 24 def test_lower(self, env): 25 tmpl = env.from_string("""{{ "foo" is lower }}|{{ "FOO" is lower }}""") 26 assert tmpl.render() == "True|False" 27 28 # Test type checks 29 @pytest.mark.parametrize( 30 "op,expect", 31 ( 32 ("none is none", True), 33 ("false is none", False), 34 ("true is none", False), 35 ("42 is none", False), 36 ("none is true", False), 37 ("false is true", False), 38 ("true is true", True), 39 ("0 is true", False), 40 ("1 is true", False), 41 ("42 is true", False), 42 ("none is false", False), 43 ("false is false", True), 44 ("true is false", False), 45 ("0 is false", False), 46 ("1 is false", False), 47 ("42 is false", False), 48 ("none is boolean", False), 49 ("false is boolean", True), 50 ("true is boolean", True), 51 ("0 is boolean", False), 52 ("1 is boolean", False), 53 ("42 is boolean", False), 54 ("0.0 is boolean", False), 55 ("1.0 is boolean", False), 56 ("3.14159 is boolean", False), 57 ("none is integer", False), 58 ("false is integer", False), 59 ("true is integer", False), 60 ("42 is integer", True), 61 ("3.14159 is integer", False), 62 ("(10 ** 100) is integer", True), 63 ("none is float", False), 64 ("false is float", False), 65 ("true is float", False), 66 ("42 is float", False), 67 ("4.2 is float", True), 68 ("(10 ** 100) is float", False), 69 ("none is number", False), 70 ("false is number", True), 71 ("true is number", True), 72 ("42 is number", True), 73 ("3.14159 is number", True), 74 ("complex is number", True), 75 ("(10 ** 100) is number", True), 76 ("none is string", False), 77 ("false is string", False), 78 ("true is string", False), 79 ("42 is string", False), 80 ('"foo" is string', True), 81 ("none is sequence", False), 82 ("false is sequence", False), 83 ("42 is sequence", False), 84 ('"foo" is sequence', True), 85 ("[] is sequence", True), 86 ("[1, 2, 3] is sequence", True), 87 ("{} is sequence", True), 88 ("none is mapping", False), 89 ("false is mapping", False), 90 ("42 is mapping", False), 91 ('"foo" is mapping', False), 92 ("[] is mapping", False), 93 ("{} is mapping", True), 94 ("mydict is mapping", True), 95 ("none is iterable", False), 96 ("false is iterable", False), 97 ("42 is iterable", False), 98 ('"foo" is iterable', True), 99 ("[] is iterable", True), 100 ("{} is iterable", True), 101 ("range(5) is iterable", True), 102 ("none is callable", False), 103 ("false is callable", False), 104 ("42 is callable", False), 105 ('"foo" is callable', False), 106 ("[] is callable", False), 107 ("{} is callable", False), 108 ("range is callable", True), 109 ), 110 ) 111 def test_types(self, env, op, expect): 112 t = env.from_string(f"{{{{ {op} }}}}") 113 assert t.render(mydict=MyDict(), complex=complex(1, 2)) == str(expect) 114 115 def test_upper(self, env): 116 tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}') 117 assert tmpl.render() == "True|False" 118 119 def test_equalto(self, env): 120 tmpl = env.from_string( 121 "{{ foo is eq 12 }}|" 122 "{{ foo is eq 0 }}|" 123 "{{ foo is eq (3 * 4) }}|" 124 '{{ bar is eq "baz" }}|' 125 '{{ bar is eq "zab" }}|' 126 '{{ bar is eq ("ba" + "z") }}|' 127 "{{ bar is eq bar }}|" 128 "{{ bar is eq foo }}" 129 ) 130 assert ( 131 tmpl.render(foo=12, bar="baz") 132 == "True|False|True|True|False|True|True|False" 133 ) 134 135 @pytest.mark.parametrize( 136 "op,expect", 137 ( 138 ("eq 2", True), 139 ("eq 3", False), 140 ("ne 3", True), 141 ("ne 2", False), 142 ("lt 3", True), 143 ("lt 2", False), 144 ("le 2", True), 145 ("le 1", False), 146 ("gt 1", True), 147 ("gt 2", False), 148 ("ge 2", True), 149 ("ge 3", False), 150 ), 151 ) 152 def test_compare_aliases(self, env, op, expect): 153 t = env.from_string(f"{{{{ 2 is {op} }}}}") 154 assert t.render() == str(expect) 155 156 def test_sameas(self, env): 157 tmpl = env.from_string("{{ foo is sameas false }}|{{ 0 is sameas false }}") 158 assert tmpl.render(foo=False) == "True|False" 159 160 def test_no_paren_for_arg1(self, env): 161 tmpl = env.from_string("{{ foo is sameas none }}") 162 assert tmpl.render(foo=None) == "True" 163 164 def test_escaped(self, env): 165 env = Environment(autoescape=True) 166 tmpl = env.from_string("{{ x is escaped }}|{{ y is escaped }}") 167 assert tmpl.render(x="foo", y=Markup("foo")) == "False|True" 168 169 def test_greaterthan(self, env): 170 tmpl = env.from_string("{{ 1 is greaterthan 0 }}|{{ 0 is greaterthan 1 }}") 171 assert tmpl.render() == "True|False" 172 173 def test_lessthan(self, env): 174 tmpl = env.from_string("{{ 0 is lessthan 1 }}|{{ 1 is lessthan 0 }}") 175 assert tmpl.render() == "True|False" 176 177 def test_multiple_tests(self): 178 items = [] 179 180 def matching(x, y): 181 items.append((x, y)) 182 return False 183 184 env = Environment() 185 env.tests["matching"] = matching 186 tmpl = env.from_string( 187 "{{ 'us-west-1' is matching '(us-east-1|ap-northeast-1)'" 188 " or 'stage' is matching '(dev|stage)' }}" 189 ) 190 assert tmpl.render() == "False" 191 assert items == [ 192 ("us-west-1", "(us-east-1|ap-northeast-1)"), 193 ("stage", "(dev|stage)"), 194 ] 195 196 def test_in(self, env): 197 tmpl = env.from_string( 198 '{{ "o" is in "foo" }}|' 199 '{{ "foo" is in "foo" }}|' 200 '{{ "b" is in "foo" }}|' 201 "{{ 1 is in ((1, 2)) }}|" 202 "{{ 3 is in ((1, 2)) }}|" 203 "{{ 1 is in [1, 2] }}|" 204 "{{ 3 is in [1, 2] }}|" 205 '{{ "foo" is in {"foo": 1}}}|' 206 '{{ "baz" is in {"bar": 1}}}' 207 ) 208 assert tmpl.render() == "True|True|False|True|False|True|False|True|False" 209