1 |
|
2 |
|
3 | tests =
|
4 | 'Literal text':
|
5 | template: "text 'Just text'"
|
6 | expected: 'Just text'
|
7 |
|
8 | 'Default DOCTYPE':
|
9 | template: "doctype()"
|
10 | expected: '<!DOCTYPE html>'
|
11 |
|
12 | 'DOCTYPE':
|
13 | template: "doctype 'xml'"
|
14 | expected: '<?xml version="1.0" encoding="utf-8" ?>'
|
15 |
|
16 | 'Custom tag':
|
17 | template: "tag 'custom'"
|
18 | expected: '<custom></custom>'
|
19 |
|
20 | 'Custom tag with attributes':
|
21 | template: "tag 'custom', foo: 'bar', ping: 'pong'"
|
22 | expected: '<custom foo="bar" ping="pong"></custom>'
|
23 |
|
24 | 'Custom tag with attributes and inner content':
|
25 | template: "tag 'custom', foo: 'bar', ping: 'pong', -> 'zag'"
|
26 | expected: '<custom foo="bar" ping="pong">zag</custom>'
|
27 |
|
28 | 'Self-closing tags':
|
29 | template: "img src: 'icon.png', alt: 'Icon'"
|
30 | expected: '<img src="icon.png" alt="Icon" />'
|
31 |
|
32 | 'Common tag':
|
33 | template: "p 'hi'"
|
34 | expected: '<p>hi</p>'
|
35 |
|
36 | 'Attributes':
|
37 | template: "a href: '/', title: 'Home'"
|
38 | expected: '<a href="/" title="Home"></a>'
|
39 |
|
40 | 'HereDocs':
|
41 | template: '''
|
42 | script """
|
43 | $(document).ready(function(){
|
44 | alert('test');
|
45 | });
|
46 | """
|
47 | '''
|
48 | expected: "<script>$(document).ready(function(){\n alert('test');\n});</script>"
|
49 |
|
50 | 'CoffeeScript helper (function)':
|
51 | template: "coffeescript -> alert 'hi'"
|
52 | expected: "<script>(function() {\n return alert(\"hi\");\n}).call(this);</script>"
|
53 |
|
54 | 'CoffeeScript helper (string)':
|
55 | template: "coffeescript \"alert 'hi'\""
|
56 | expected: "<script>alert('hi');</script>"
|
57 |
|
58 | 'Context vars':
|
59 | template: "h1 @foo"
|
60 | expected: '<h1>bar</h1>'
|
61 | params: {foo: 'bar'}
|
62 |
|
63 | 'Local vars, hardcoded':
|
64 | template: 'h1 "harcoded: " + obj.foo'
|
65 | run: ->
|
66 | obj = {foo: 'bar'}
|
67 | @compiled = ck.compile(@template, hardcode: {obj})
|
68 | @expected = '<h1>harcoded: bar</h1>'
|
69 | @result = @compiled()
|
70 | @success = @result is @expected
|
71 | if @success
|
72 | obj.foo = 'baz'
|
73 | @result = @compiled()
|
74 | @success = @result is @expected
|
75 |
|
76 | 'Local vars, hard-coded (functions)':
|
77 | template: "h1 \"The sum is: \#{sum 1, 2}\""
|
78 | expected: '<h1>The sum is: 3</h1>'
|
79 | params: {hardcode: {sum: (a, b) -> a + b}}
|
80 |
|
81 | 'Local vars, hard-coded ("helpers")':
|
82 | template: "textbox id: 'foo'"
|
83 | expected: '<input id="foo" name="foo" type="text" />'
|
84 | params:
|
85 | hardcode:
|
86 | textbox: (attrs) ->
|
87 | tag 'input',
|
88 | id: attrs.id
|
89 | name: attrs.id
|
90 | type: 'text'
|
91 |
|
92 | 'Local vars':
|
93 | template: 'h1 "dynamic: " + obj.foo'
|
94 | run: ->
|
95 | obj = {foo: 'bar'}
|
96 | @expected = '<h1>dynamic: bar</h1>'
|
97 | @result = render(@template, locals: {obj: obj})
|
98 | @success = @result is @expected
|
99 | if @success
|
100 | obj.foo = 'baz'
|
101 | @expected = '<h1>dynamic: baz</h1>'
|
102 | @result = render(@template, locals: {obj: obj})
|
103 | @success = @result is @expected
|
104 |
|
105 | 'Comments':
|
106 | template: "comment 'Comment'"
|
107 | expected: '<!--Comment-->'
|
108 |
|
109 | 'Escaping':
|
110 | template: "h1 h(\"<script>alert('\\\"pwned\\\" by c&a ©')</script>\")"
|
111 | expected: "<h1><script>alert('"pwned" by c&a &copy;')</script></h1>"
|
112 |
|
113 | 'Autoescaping':
|
114 | template: "h1 \"<script>alert('\\\"pwned\\\" by c&a ©')</script>\""
|
115 | expected: "<h1><script>alert('"pwned" by c&a &copy;')</script></h1>"
|
116 | params:
|
117 | autoescape: yes
|
118 |
|
119 | 'ID/class shortcut (combo)':
|
120 | template: "div '#myid.myclass1.myclass2', 'foo'"
|
121 | expected: '<div id="myid" class="myclass1 myclass2">foo</div>'
|
122 |
|
123 | 'ID/class shortcut (ID only)':
|
124 | template: "div '#myid', 'foo'"
|
125 | expected: '<div id="myid">foo</div>'
|
126 |
|
127 | 'ID/class shortcut (one class only)':
|
128 | template: "div '.myclass', 'foo'"
|
129 | expected: '<div class="myclass">foo</div>'
|
130 |
|
131 | 'ID/class shortcut (multiple classes)':
|
132 | template: "div '.myclass.myclass2.myclass3', 'foo'"
|
133 | expected: '<div class="myclass myclass2 myclass3">foo</div>'
|
134 |
|
135 | 'ID/class shortcut (no string contents)':
|
136 | template: "img '#myid.myclass', src: '/pic.png'"
|
137 | expected: '<img id="myid" class="myclass" src="/pic.png" />'
|
138 |
|
139 | 'Attribute values':
|
140 | template: "br vrai: yes, faux: no, undef: @foo, nil: null, str: 'str', num: 42, arr: [1, 2, 3].join(','), obj: {foo: 'bar'}, func: ->"
|
141 | expected: '<br vrai="vrai" str="str" num="42" arr="1,2,3" obj-foo="bar" func="(function(){}).call(this);" />'
|
142 |
|
143 | 'IE conditionals':
|
144 | template: """
|
145 | html ->
|
146 | head ->
|
147 | title 'test'
|
148 | ie 'gte IE8', ->
|
149 | link href: 'ie.css', rel: 'stylesheet'
|
150 | """
|
151 | expected: '<html><head><title>test</title><!--[if gte IE8]><link href="ie.css" rel="stylesheet" /><![endif]--></head></html>'
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | 'yield':
|
166 | template: "p \"This text could use \#{yield -> strong -> a href: '/', 'a link'}.\""
|
167 | expected: '<p>This text could use <strong><a href="/">a link</a></strong>.</p>'
|
168 |
|
169 | cc = require './src/coffeecup'
|
170 | render = cc.render
|
171 |
|
172 | @run = ->
|
173 | {print} = require 'sys'
|
174 | colors = {red: "\033[31m", redder: "\033[91m", green: "\033[32m", normal: "\033[0m"}
|
175 | printc = (color, str) -> print colors[color] + str + colors.normal
|
176 |
|
177 | [total, passed, failed, errors] = [0, [], [], []]
|
178 |
|
179 | for name, test of tests
|
180 | total++
|
181 | try
|
182 | if not test.params?
|
183 | test.params =
|
184 | optimize: true
|
185 | cache: on
|
186 | else
|
187 | test.params.optimize = true
|
188 | test.params.cache = true
|
189 | test.original_params = JSON.stringify test.params
|
190 |
|
191 | if test.run
|
192 | test.run()
|
193 | else
|
194 | test.result = ck.render(test.template, test.params)
|
195 | test.success = test.result is test.expected
|
196 |
|
197 | if test.success
|
198 | passed.push name
|
199 | print "[Passed] #{name}\n"
|
200 | else
|
201 | failed.push name
|
202 | printc 'red', "[Failed] #{name}\n"
|
203 | catch ex
|
204 | test.result = ex
|
205 | errors.push name
|
206 | printc 'redder', "[Error] #{name}\n"
|
207 |
|
208 | print "\n#{total} tests, #{passed.length} passed, #{failed.length} failed, #{errors.length} errors\n\n"
|
209 |
|
210 | if failed.length > 0
|
211 | printc 'red', "FAILED:\n\n"
|
212 |
|
213 | for name in failed
|
214 | t = tests[name]
|
215 | print "- #{name}:\n"
|
216 | print t.template + "\n"
|
217 | print t.original_params + "\n" if t.params
|
218 | printc 'green', t.expected + "\n"
|
219 | printc 'red', t.result + "\n\n"
|
220 |
|
221 | if errors.length > 0
|
222 | printc 'redder', "ERRORS:\n\n"
|
223 |
|
224 | for name in errors
|
225 | t = tests[name]
|
226 | print "- #{name}:\n"
|
227 | print t.template + "\n"
|
228 | printc 'green', t.expected + "\n"
|
229 | printc 'redder', t.result.stack + "\n\n"
|
230 |
|
231 | @run()
|