Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | """ |
| 3 | unit test for loop functions |
| 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 5 | |
| 6 | :copyright: 2007 by Armin Ronacher. |
| 7 | :license: BSD, see LICENSE for more details. |
| 8 | """ |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 9 | from py.test import raises |
Armin Ronacher | 105f0dc | 2008-05-23 16:12:47 +0200 | [diff] [blame^] | 10 | from jinja2.exceptions import UndefinedError |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 11 | |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 12 | |
| 13 | SIMPLE = '''{% for item in seq %}{{ item }}{% endfor %}''' |
| 14 | ELSE = '''{% for item in seq %}XXX{% else %}...{% endfor %}''' |
| 15 | EMPTYBLOCKS = '''<{% for item in seq %}{% else %}{% endfor %}>''' |
| 16 | CONTEXTVARS = '''{% for item in seq %}\ |
| 17 | {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{ |
| 18 | loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{ |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 19 | loop.length }}###{% endfor %}''' |
| 20 | CYCLING = '''{% for item in seq %}{{ loop.cycle('<1>', '<2>') }}{% endfor %}\ |
| 21 | {% for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''' |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 22 | SCOPE = '''{% for item in seq %}{% endfor %}{{ item }}''' |
Armin Ronacher | 6dba4d6 | 2007-05-21 23:41:36 +0200 | [diff] [blame] | 23 | VARLEN = '''{% for item in iter %}{{ item }}{% endfor %}''' |
Armin Ronacher | 9bcd411 | 2007-05-29 14:17:24 +0200 | [diff] [blame] | 24 | NONITER = '''{% for item in none %}...{% endfor %}''' |
Armin Ronacher | 66a9344 | 2008-05-11 23:42:19 +0200 | [diff] [blame] | 25 | RECURSIVE = '''{% for item in seq recursive -%} |
Armin Ronacher | b455c31 | 2008-05-11 23:43:07 +0200 | [diff] [blame] | 26 | [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}] |
Armin Ronacher | 66a9344 | 2008-05-11 23:42:19 +0200 | [diff] [blame] | 27 | {%- endfor %}''' |
Armin Ronacher | 24db451 | 2008-05-19 09:28:17 +0200 | [diff] [blame] | 28 | LOOPLOOP = '''{% for row in table %} |
| 29 | {%- set rowloop = loop -%} |
| 30 | {% for cell in row -%} |
| 31 | [{{ rowloop.index }}|{{ loop.index }}] |
| 32 | {%- endfor %} |
| 33 | {%- endfor %}''' |
Armin Ronacher | 105f0dc | 2008-05-23 16:12:47 +0200 | [diff] [blame^] | 34 | LOOPERROR1 = '''\ |
| 35 | {% for item in [1] if loop.index == 0 %}...{% endfor %}''' |
| 36 | LOOPERROR2 = '''\ |
| 37 | {% for item in [] %}...{% else %}{{ loop }}{% endfor %}''' |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 38 | |
| 39 | |
| 40 | def test_simple(env): |
| 41 | tmpl = env.from_string(SIMPLE) |
| 42 | assert tmpl.render(seq=range(10)) == '0123456789' |
| 43 | |
| 44 | |
| 45 | def test_else(env): |
| 46 | tmpl = env.from_string(ELSE) |
| 47 | assert tmpl.render() == '...' |
| 48 | |
| 49 | |
| 50 | def test_empty_blocks(env): |
| 51 | tmpl = env.from_string(EMPTYBLOCKS) |
| 52 | assert tmpl.render() == '<>' |
| 53 | |
| 54 | |
| 55 | def test_context_vars(env): |
| 56 | tmpl = env.from_string(CONTEXTVARS) |
| 57 | one, two, _ = tmpl.render(seq=[0, 1]).split('###') |
| 58 | (one_index, one_index0, one_revindex, one_revindex0, one_first, |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 59 | one_last, one_length) = one.split('|') |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 60 | (two_index, two_index0, two_revindex, two_revindex0, two_first, |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 61 | two_last, two_length) = two.split('|') |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 62 | |
| 63 | assert int(one_index) == 1 and int(two_index) == 2 |
| 64 | assert int(one_index0) == 0 and int(two_index0) == 1 |
| 65 | assert int(one_revindex) == 2 and int(two_revindex) == 1 |
| 66 | assert int(one_revindex0) == 1 and int(two_revindex0) == 0 |
| 67 | assert one_first == 'True' and two_first == 'False' |
| 68 | assert one_last == 'False' and two_last == 'True' |
Armin Ronacher | ab45b84 | 2007-03-18 20:47:50 +0100 | [diff] [blame] | 69 | assert one_length == two_length == '2' |
| 70 | |
| 71 | |
| 72 | def test_cycling(env): |
| 73 | tmpl = env.from_string(CYCLING) |
| 74 | output = tmpl.render(seq=range(4), through=('<1>', '<2>')) |
| 75 | assert output == '<1><2>' * 4 |
| 76 | |
| 77 | |
| 78 | def test_scope(env): |
| 79 | tmpl = env.from_string(SCOPE) |
| 80 | output = tmpl.render(seq=range(10)) |
| 81 | assert not output |
Armin Ronacher | 6dba4d6 | 2007-05-21 23:41:36 +0200 | [diff] [blame] | 82 | |
| 83 | |
| 84 | def test_varlen(env): |
| 85 | def inner(): |
| 86 | for item in range(5): |
| 87 | yield item |
| 88 | tmpl = env.from_string(VARLEN) |
| 89 | output = tmpl.render(iter=inner()) |
| 90 | assert output == '01234' |
Armin Ronacher | 9bcd411 | 2007-05-29 14:17:24 +0200 | [diff] [blame] | 91 | |
| 92 | |
| 93 | def test_noniter(env): |
| 94 | tmpl = env.from_string(NONITER) |
Armin Ronacher | 10f3ba2 | 2008-04-18 11:30:37 +0200 | [diff] [blame] | 95 | raises(TypeError, tmpl.render) |
Armin Ronacher | 66a9344 | 2008-05-11 23:42:19 +0200 | [diff] [blame] | 96 | |
| 97 | |
| 98 | def test_recursive(env): |
| 99 | tmpl = env.from_string(RECURSIVE) |
| 100 | assert tmpl.render(seq=[ |
| 101 | dict(a=1, b=[dict(a=1), dict(a=2)]), |
| 102 | dict(a=2, b=[dict(a=1), dict(a=2)]), |
| 103 | dict(a=3, b=[dict(a='a')]) |
Armin Ronacher | b455c31 | 2008-05-11 23:43:07 +0200 | [diff] [blame] | 104 | ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]' |
Armin Ronacher | 24db451 | 2008-05-19 09:28:17 +0200 | [diff] [blame] | 105 | |
| 106 | |
| 107 | def test_looploop(env): |
| 108 | tmpl = env.from_string(LOOPLOOP) |
| 109 | assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]' |
Armin Ronacher | 105f0dc | 2008-05-23 16:12:47 +0200 | [diff] [blame^] | 110 | |
| 111 | |
| 112 | def test_loop_errors(env): |
| 113 | tmpl = env.from_string(LOOPERROR1) |
| 114 | raises(UndefinedError, tmpl.render) |
| 115 | tmpl = env.from_string(LOOPERROR2) |
| 116 | assert tmpl.render() == '' |