summaryrefslogtreecommitdiff
path: root/specs/~lambdas.yml
blob: 741a98a4d27d1543e7e6ff512b7e606df0c85bee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
overview: |
  Lambdas are a special-cased data type for use in interpolations and
  sections.

  When used as the data value for an Interpolation tag, the lambda MUST be
  treatable as an arity 0 function, and invoked as such.  The returned value
  MUST be rendered, then interpolated in place of the lambda.

  When used as the data value for a Section tag, the lambda MUST be treatable
  as an arity 1 function, and invoked as such (passing a String containing the
  unprocessed section contents).  The returned value MUST be rendered, then
  interpolated in place of the section.
tests:
  - name: Interpolation
    desc: A lambda's return value should be interpolated.
    data:
      lambda: !code
        ruby:   'proc { "world" }'
        perl:   'sub { "world" }'
        js:     'function() { return "world" }'
        php:    'return "world";'
        python: 'lambda: "world"'
    template: "Hello, {{lambda}}!"
    expected: "Hello, world!"

  - name: Interpolation - Expansion
    desc: A lambda's return value should be parsed.
    data:
      planet: "world"
      lambda: !code
        ruby:   'proc { "{{planet}}" }'
        perl:   'sub { "{{planet}}" }'
        js:     'function() { return "{{planet}}" }'
        php:    'return "{{planet}}";'
        python: 'lambda: "{{planet}}"'
    template: "Hello, {{lambda}}!"
    expected: "Hello, world!"

  - name: Interpolation - Multiple Calls
    desc: Interpolated lambdas should not be cached.
    data:
      lambda: !code
        ruby:   'proc { $calls ||= 0; $calls += 1 }'
        perl:   'sub { no strict; $calls += 1 }'
        js:     'function() { return (g=(function(){return this})()).calls=(g.calls||0)+1 }'
        php:    'global $calls; return ++$calls;'
        python: 'lambda: globals().update(calls=globals().get("calls",0)+1) or calls'
    template: '{{lambda}} == {{{lambda}}} == {{lambda}}'
    expected: '1 == 2 == 3'

  - name: Escaping
    desc: Lambda results should be appropriately escaped.
    data:
      lambda: !code
        ruby:   'proc { ">" }'
        perl:   'sub { ">" }'
        js:     'function() { return ">" }'
        php:    'return ">";'
        python: 'lambda: ">"'
    template: "<{{lambda}}{{{lambda}}}"
    expected: "<&gt;>"

  - name: Section
    desc: Lambdas used for sections should receive the raw section string.
    data:
      x: 'Error!'
      lambda: !code
        ruby:   'proc { |text| text == "{{x}}" ? "yes" : "no" }'
        perl:   'sub { $_[0] eq "{{x}}" ? "yes" : "no" }'
        js:     'function(txt) { return (txt == "{{x}}" ? "yes" : "no") }'
        php:    'return ($text == "{{x}}") ? "yes" : "no";'
        python: 'lambda text: text == "{{x}}" and "yes" or "no"'
    template: "<{{#lambda}}{{x}}{{/lambda}}>"
    expected: "<yes>"

  - name: Section - Expansion
    desc: Lambdas used for sections should have their results parsed.
    data:
      planet: "Earth"
      lambda: !code
        ruby:   'proc { |text| "#{text}{{planet}}#{text}" }'
        perl:   'sub { $_[0] . "{{planet}}" . $_[0] }'
        js:     'function(txt) { return txt + "{{planet}}" + txt }'
        php:    'return $text . "{{planet}}" . $text;'
        python: 'lambda text: "%s{{planet}}%s" % (text, text)'
    template: "<{{#lambda}}-{{/lambda}}>"
    expected: "<-Earth->"

  - name: Section - Multiple Calls
    desc: Lambdas used for sections should not be cached.
    data:
      lambda: !code
        ruby:   'proc { |text| "__#{text}__" }'
        perl:   'sub { "__" . $_[0] . "__" }'
        js:     'function(txt) { return "__" + txt + "__" }'
        php:    'return "__" . $text . "__";'
        python: 'lambda text: "__%s__" % (text)'
    template: '{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}'
    expected: '__FILE__ != __LINE__'

  - name: Inverted Section
    desc: Lambdas used for inverted sections should be considered truthy.
    data:
      static: 'static'
      lambda: !code
        ruby:   'proc { |text| false }'
        perl:   'sub { 0 }'
        js:     'function(txt) { return false }'
        php:    'return false;'
        python: 'lambda text: 0'
    template: "<{{^lambda}}{{static}}{{/lambda}}>"
    expected: "<>"