PageTemplate 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/CVS/Entries +10 -0
  2. data/CVS/Repository +1 -0
  3. data/CVS/Root +1 -0
  4. data/Changes +13 -0
  5. data/Changes~ +7 -0
  6. data/InstalledFiles +7 -0
  7. data/README.txt +1 -1
  8. data/Rakefile +1 -1
  9. data/Rakefile~ +54 -0
  10. data/TC_PageTemplate.rb +137 -19
  11. data/TC_PageTemplate.rb~ +965 -0
  12. data/doc/classes/BlockCommand.html +1 -1
  13. data/doc/classes/BlockCommand.src/M000004.html +1 -1
  14. data/doc/classes/BlockCommand.src/M000005.html +1 -1
  15. data/doc/classes/BlockCommand.src/M000006.html +1 -1
  16. data/doc/classes/BlockCommand.src/M000007.html +1 -1
  17. data/doc/classes/BlockCommand.src/M000008.html +1 -1
  18. data/doc/classes/Command.html +10 -10
  19. data/doc/classes/Command.src/{M000029.html → M000032.html} +0 -0
  20. data/doc/classes/Command.src/{M000030.html → M000033.html} +0 -0
  21. data/doc/classes/CommentCommand.html +146 -0
  22. data/doc/classes/CommentCommand.src/M000009.html +18 -0
  23. data/doc/classes/IfCommand.html +15 -15
  24. data/doc/classes/IfCommand.src/{M000039.html → M000042.html} +1 -1
  25. data/doc/classes/IfCommand.src/{M000040.html → M000043.html} +1 -1
  26. data/doc/classes/IfCommand.src/{M000041.html → M000044.html} +1 -1
  27. data/doc/classes/IfElseCommand.html +15 -15
  28. data/doc/classes/IfElseCommand.src/M000025.html +5 -6
  29. data/doc/classes/IfElseCommand.src/{M000024.html → M000026.html} +1 -1
  30. data/doc/classes/IfElseCommand.src/M000027.html +20 -0
  31. data/doc/classes/IncludeCommand.html +16 -23
  32. data/doc/classes/IncludeCommand.src/M000019.html +12 -4
  33. data/doc/classes/IncludeCommand.src/{M000018.html → M000020.html} +10 -5
  34. data/doc/classes/IncludeCommand.src/M000021.html +18 -0
  35. data/doc/classes/IncludeCommandError.html +118 -0
  36. data/doc/classes/LoopCommand.src/M000001.html +1 -1
  37. data/doc/classes/LoopCommand.src/M000002.html +11 -2
  38. data/doc/classes/LoopCommand.src/M000003.html +1 -1
  39. data/doc/classes/LoopElseCommand.html +15 -15
  40. data/doc/classes/LoopElseCommand.src/M000022.html +5 -6
  41. data/doc/classes/LoopElseCommand.src/{M000021.html → M000023.html} +1 -1
  42. data/doc/classes/LoopElseCommand.src/M000024.html +20 -0
  43. data/doc/classes/Namespace.html +42 -42
  44. data/doc/classes/Namespace.src/M000034.html +5 -5
  45. data/doc/classes/Namespace.src/M000035.html +4 -22
  46. data/doc/classes/Namespace.src/M000036.html +4 -7
  47. data/doc/classes/Namespace.src/M000037.html +5 -4
  48. data/doc/classes/Namespace.src/M000038.html +22 -4
  49. data/doc/classes/Namespace.src/M000039.html +21 -0
  50. data/doc/classes/Namespace.src/M000040.html +18 -0
  51. data/doc/classes/Namespace.src/{M000031.html → M000041.html} +4 -5
  52. data/doc/classes/PageTemplate.html +72 -44
  53. data/doc/classes/PageTemplate.src/M000010.html +31 -11
  54. data/doc/classes/PageTemplate.src/M000011.html +4 -4
  55. data/doc/classes/PageTemplate.src/M000012.html +15 -4
  56. data/doc/classes/PageTemplate.src/M000013.html +4 -4
  57. data/doc/classes/PageTemplate.src/M000014.html +4 -4
  58. data/doc/classes/PageTemplate.src/M000015.html +4 -4
  59. data/doc/classes/PageTemplate.src/M000016.html +4 -5
  60. data/doc/classes/PageTemplate.src/M000017.html +18 -0
  61. data/doc/classes/PageTemplate.src/M000018.html +19 -0
  62. data/doc/classes/Syntax/CachedParser.html +10 -10
  63. data/doc/classes/Syntax/CachedParser.src/{M000045.html → M000048.html} +1 -1
  64. data/doc/classes/Syntax/CachedParser.src/{M000046.html → M000049.html} +2 -1
  65. data/doc/classes/Syntax/Glossary.html +16 -10
  66. data/doc/classes/Syntax/Glossary.src/{M000047.html → M000050.html} +1 -1
  67. data/doc/classes/Syntax/Glossary.src/{M000048.html → M000051.html} +1 -1
  68. data/doc/classes/Syntax/Parser.html +31 -31
  69. data/doc/classes/Syntax/Parser.src/M000052.html +6 -5
  70. data/doc/classes/Syntax/Parser.src/M000053.html +20 -37
  71. data/doc/classes/Syntax/Parser.src/M000054.html +4 -93
  72. data/doc/classes/Syntax/Parser.src/{M000049.html → M000055.html} +5 -6
  73. data/doc/classes/Syntax/Parser.src/M000056.html +53 -0
  74. data/doc/classes/Syntax/Parser.src/M000057.html +111 -0
  75. data/doc/classes/Syntax.html +1 -1
  76. data/doc/classes/TextCommand.html +15 -15
  77. data/doc/classes/TextCommand.src/{M000042.html → M000045.html} +1 -1
  78. data/doc/classes/TextCommand.src/{M000043.html → M000046.html} +1 -1
  79. data/doc/classes/TextCommand.src/{M000044.html → M000047.html} +1 -1
  80. data/doc/classes/UnlessCommand.html +151 -0
  81. data/doc/classes/UnlessCommand.src/M000028.html +20 -0
  82. data/doc/classes/ValueCommand.html +15 -15
  83. data/doc/classes/ValueCommand.src/{M000026.html → M000029.html} +1 -1
  84. data/doc/classes/ValueCommand.src/{M000027.html → M000030.html} +1 -1
  85. data/doc/classes/ValueCommand.src/{M000028.html → M000031.html} +1 -1
  86. data/doc/created.rid +1 -1
  87. data/doc/files/README_txt.html +2 -2
  88. data/doc/files/lib/PageTemplate_rb.html +1 -1
  89. data/doc/fr_class_index.html +3 -0
  90. data/doc/fr_method_index.html +52 -49
  91. data/lib/CVS/Entries +2 -0
  92. data/lib/CVS/Repository +1 -0
  93. data/lib/CVS/Root +1 -0
  94. data/lib/PageTemplate.rb +103 -26
  95. data/lib/PageTemplate.rb~ +1004 -0
  96. data/pkg/PageTemplate-1.2.0.gem +0 -0
  97. data/tdata/CVS/Entries +28 -0
  98. data/tdata/CVS/Repository +1 -0
  99. data/tdata/CVS/Root +1 -0
  100. data/tdata/cm.txt +3 -0
  101. data/tdata/include.4.nf.out.txt +2 -0
  102. data/tdata/metadata.1.txt +5 -0
  103. data/tdata/metadata.2.txt +5 -0
  104. data/tdata/metadata.3.txt +5 -0
  105. data/tdata/metadata.4.txt +5 -0
  106. data/tdata/p/CVS/Entries +5 -0
  107. data/tdata/p/CVS/Repository +1 -0
  108. data/tdata/p/CVS/Root +1 -0
  109. data/tdata/p/CVS/b2.txt,t +0 -0
  110. data/tdata/p/b2.txt +4 -0
  111. data/tdata/p/b2.txt~ +4 -0
  112. metadata +70 -32
  113. data/doc/classes/IfElseCommand.src/M000023.html +0 -19
  114. data/doc/classes/IncludeCommand.src/M000017.html +0 -21
  115. data/doc/classes/LoopElseCommand.src/M000020.html +0 -19
  116. data/doc/classes/Namespace.src/M000032.html +0 -18
  117. data/doc/classes/Namespace.src/M000033.html +0 -18
  118. data/doc/classes/PageTemplate.src/M000009.html +0 -46
  119. data/doc/classes/Syntax/Parser.src/M000050.html +0 -35
  120. data/doc/classes/Syntax/Parser.src/M000051.html +0 -18
  121. data/lib/MANIFEST +0 -2
  122. data/pkg/PageTemplate-1.1.2.gem +0 -0
@@ -0,0 +1,965 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ require 'test/unit'
4
+ require './lib/PageTemplate.rb'
5
+
6
+ require "date"
7
+
8
+ class TC_Namespace < Test::Unit::TestCase
9
+ @@namespace = Namespace.new()
10
+
11
+ def testNamespaceSet
12
+ assert(@@namespace.set("name", "Frank"))
13
+ end
14
+
15
+ def testNamespaceGet
16
+ @@namespace.set("name", "Frank")
17
+ assert_equal("Frank", @@namespace.get("name"))
18
+ end
19
+
20
+ def testTrue
21
+ assert_not_nil(@@namespace.true?("name"))
22
+ assert_nil(@@namespace.true?("null"))
23
+ @@namespace.set("falseFlag", false)
24
+ assert_nil(@@namespace.true?("falseFlag"))
25
+ end
26
+
27
+ def testNamespacePush
28
+ assert_equal("Frank", @@namespace.get("name"))
29
+ names = { 'name' => "Eddie Baby" }
30
+
31
+ # Pushing a hash (and nested namespace)
32
+ assert(@@namespace.push(names))
33
+ assert_equal("Eddie Baby", @@namespace.get("name"))
34
+
35
+ # Pushing an object
36
+ date = Date.today()
37
+ date2 = Date.today()
38
+
39
+ @@namespace.push(date)
40
+ assert_equal(date2.year, @@namespace.get("year"))
41
+ end
42
+
43
+ def testNamespacePop
44
+ names = { 'name' => "Eddie Baby" }
45
+ @@namespace.push(names)
46
+ assert_equal("Eddie Baby", @@namespace.get("name"))
47
+ assert(@@namespace.pop())
48
+ assert_equal("Frank", @@namespace.get("name"))
49
+ assert_nil(@@namespace.pop())
50
+ end
51
+
52
+ end
53
+
54
+ class TC_Command < Test::Unit::TestCase
55
+ @@command = Command.new()
56
+
57
+ def testCommandOutput
58
+ assert_raises(NotImplementedError) { @@command.output() }
59
+ end
60
+
61
+ end
62
+
63
+ class TC_CommentCommand < Test::Unit::TestCase
64
+ @@command = CommentCommand.new()
65
+
66
+ def testCommentCommand
67
+ assert_equal(nil, @@command.output,
68
+ "CommentCommands don't have any output")
69
+ end
70
+
71
+ end
72
+
73
+ class TC_BlockCommand < Test::Unit::TestCase
74
+ @@command = BlockCommand.new()
75
+
76
+ def testAddCommand
77
+ aCommand = TextCommand.new("Hello")
78
+ assert(@@command.add(aCommand))
79
+
80
+ assert_raises(TypeError) { @@command.add("Hello") }
81
+ end
82
+
83
+ def testOutput
84
+ bCommand = TextCommand.new(", ")
85
+ cCommand = TextCommand.new("World")
86
+
87
+ @@command.add(bCommand)
88
+ @@command.add(cCommand)
89
+
90
+ assert_equal("Hello, World", @@command.output)
91
+ end
92
+ end
93
+
94
+ class TC_TextCommand < Test::Unit::TestCase
95
+ @@command = TextCommand.new("Just testing")
96
+
97
+ def testCommandOutput
98
+ assert_equal("Just testing", @@command.output)
99
+ end
100
+
101
+ end
102
+
103
+ class TC_ValueCommand < Test::Unit::TestCase
104
+ @@valueCommand = ValueCommand.new("name")
105
+
106
+ def testOutput
107
+ ns = Namespace.new()
108
+ ns.set("name", "Frank")
109
+ assert_equal(ns.get("name"), @@valueCommand.output(ns))
110
+ end
111
+ end
112
+
113
+ class TC_IfCommand < Test::Unit::TestCase
114
+
115
+ def testOutput
116
+ aCommand = TextCommand.new("Programming ")
117
+ bCommand = TextCommand.new("Ruby")
118
+ commandBlock = BlockCommand.new()
119
+ commandBlock.add(aCommand)
120
+ commandBlock.add(bCommand)
121
+
122
+ ns = Namespace.new()
123
+ ns.set("testing", 1)
124
+
125
+ # First test for output with true condition
126
+ ifCommand = IfCommand.new("testing", commandBlock)
127
+ assert_equal("Programming Ruby", ifCommand.output(ns))
128
+
129
+ # Test for nil output with false condition
130
+ ifCommand = IfCommand.new("production", commandBlock)
131
+ assert_nil(ifCommand.output(ns))
132
+
133
+ ns.set("production", false)
134
+ assert_nil(ifCommand.output(ns))
135
+ end
136
+ end
137
+
138
+ class TC_UnlessCommand < Test::Unit::TestCase
139
+ def testOutput
140
+ aCommand = TextCommand.new("Dude!")
141
+ bCommand = TextCommand.new("Sweet!")
142
+ commandBlock = BlockCommand.new()
143
+ commandBlock.add(aCommand)
144
+ commandBlock.add(bCommand)
145
+ ns = Namespace.new()
146
+ ns["testing"] = false
147
+
148
+ # First test for output with false condition
149
+ unlessCommand = UnlessCommand.new("testing", commandBlock)
150
+ assert_equal("Dude!Sweet!", unlessCommand.output(ns))
151
+ ns["testing"] = true
152
+ assert_nil(unlessCommand.output(ns))
153
+ end
154
+ end
155
+
156
+ class TC_IfElseCommand < Test::Unit::TestCase
157
+
158
+ def testOutput
159
+ aCommand = TextCommand.new("This is ")
160
+ bCommand = TextCommand.new("True")
161
+ cCommand = TextCommand.new("False")
162
+ ifBlock = BlockCommand.new()
163
+ ifBlock.add(aCommand)
164
+ ifBlock.add(bCommand)
165
+ elseBlock = BlockCommand.new()
166
+ elseBlock.add(aCommand)
167
+ elseBlock.add(cCommand)
168
+
169
+ ns = Namespace.new()
170
+ ns.set("testing", 1)
171
+
172
+ # First test for output with true condition
173
+ ifElseCommand = IfElseCommand.new("testing", ifBlock, elseBlock)
174
+ assert_equal("This is True", ifElseCommand.output(ns))
175
+
176
+ # Test for output with false condition
177
+ ifElseCommand = IfElseCommand.new("live", ifBlock, elseBlock)
178
+ assert_equal("This is False", ifElseCommand.output(ns))
179
+ end
180
+
181
+ end
182
+
183
+ class TC_LoopCommand < Test::Unit::TestCase
184
+
185
+ def testOutput
186
+ # Build a list of hashes for the namespace
187
+ loopItems = [
188
+ { 'x'=> '1 ', 'y'=> '2 ', 'z'=> '3' },
189
+ { 'x'=> 'a ', 'y'=> 'b ', 'z'=> 'c' },
190
+ ]
191
+ ns = Namespace.new()
192
+ ns.set('list', loopItems)
193
+
194
+ # Build a command list
195
+ xCommand = ValueCommand.new('x')
196
+ yCommand = ValueCommand.new('y')
197
+ zCommand = ValueCommand.new('z')
198
+ commandBlock = BlockCommand.new()
199
+ commandBlock.add(xCommand)
200
+ commandBlock.add(yCommand)
201
+ commandBlock.add(zCommand)
202
+
203
+ loopCommand = LoopCommand.new('list', commandBlock)
204
+ assert_equal("1 2 3a b c", loopCommand.output(ns))
205
+ loopCommand = LoopCommand.new('noshow', commandBlock)
206
+ assert_nil(loopCommand.output(ns))
207
+ ns.set("string", "hello")
208
+ loopCommand = LoopCommand.new("string", commandBlock)
209
+ assert_raises(TypeError) { loopCommand.output(ns) }
210
+ end
211
+ end
212
+
213
+ class TC_LoopElseCommand < Test::Unit::TestCase
214
+
215
+ def testOutput
216
+ # Build a list of hashes for the namespace
217
+ loopItems = [
218
+ { 'x'=> '1 ', 'y'=> '2 ', 'z'=> '3' },
219
+ { 'x'=> 'a ', 'y'=> 'b ', 'z'=> 'c' },
220
+ ]
221
+ ns = Namespace.new()
222
+ ns.set('list', loopItems)
223
+
224
+ # Build a command list
225
+ xCommand = ValueCommand.new('x')
226
+ yCommand = ValueCommand.new('y')
227
+ zCommand = ValueCommand.new('z')
228
+ commandBlock = BlockCommand.new()
229
+ commandBlock.add(xCommand)
230
+ commandBlock.add(yCommand)
231
+ commandBlock.add(zCommand)
232
+
233
+ # Build a command list for the else block
234
+ aCommand = TextCommand.new("In the else block")
235
+ elseCommands = BlockCommand.new()
236
+ elseCommands.add(aCommand)
237
+
238
+ # Build the LoopCommand
239
+ loopCommand =
240
+ LoopElseCommand.new('list', commandBlock, elseCommands)
241
+
242
+ # Test for output when loop variable is true
243
+ assert_equal("1 2 3a b c", loopCommand.output(ns))
244
+
245
+ # Test for nil when loop variable is false
246
+ loopCommand =
247
+ LoopElseCommand.new('noshow', commandBlock, elseCommands)
248
+ assert_equal("In the else block", loopCommand.output(ns))
249
+ end
250
+
251
+ end
252
+
253
+
254
+ class TC_NestedCommands < Test::Unit::TestCase
255
+
256
+ def testNestedIfs
257
+ ns = Namespace.new()
258
+
259
+ innerBlock = BlockCommand.new()
260
+ innerBlock.add(TextCommand.new("Inner"))
261
+ innerIf = IfCommand.new("inner", innerBlock)
262
+
263
+ outerBlock = BlockCommand.new()
264
+ outerBlock.add(TextCommand.new("Outer"))
265
+ outerBlock.add(innerIf)
266
+ outerIf = IfCommand.new("outer", outerBlock)
267
+
268
+ mainBlock = BlockCommand.new()
269
+ mainBlock.add(outerIf)
270
+
271
+ # True in a true should yield result of both command lists
272
+ ns.set("outer", 1)
273
+ ns.set("inner", 1)
274
+ assert_equal("OuterInner", mainBlock.output(ns))
275
+
276
+ # False in a true should yield result of outside list
277
+ ns.set("inner", false)
278
+ assert_equal("Outer", mainBlock.output(ns))
279
+
280
+ # False in a false should yield nil
281
+ ns.set("outer", false)
282
+ assert_nil(mainBlock.output(ns))
283
+
284
+ # True in a false should yield nil
285
+ ns.set("inner", 1)
286
+ ns.set("outer", false)
287
+ assert_nil(mainBlock.output(ns))
288
+ end
289
+
290
+ def testNestedLoops
291
+ loop1 = [
292
+ { 'a' => 'o1 ', 'b' => 'o2 ', 'c' => [
293
+ { 'x' => 'i1 ', 'y' => 'i2 ', 'z' => 'i3 ' },
294
+ { 'x' => 'i4 ', 'y' => 'i5 ', 'z' => 'i6 ' } ]
295
+ },
296
+ { 'a' => 'o3 ', 'b' => 'o4 ', 'c' => [
297
+ { 'x' => 'j1 ', 'y' => 'j2 ', 'z' => 'j3 ' },
298
+ { 'x' => 'j4 ', 'y' => 'j5 ', 'z' => 'j6 ' } ]
299
+ }
300
+ ]
301
+ ns = Namespace.new()
302
+ ns.set("loop", loop1)
303
+
304
+ aCommand = ValueCommand.new('a')
305
+ bCommand = ValueCommand.new('b')
306
+ xCommand = ValueCommand.new('x')
307
+ yCommand = ValueCommand.new('y')
308
+ zCommand = ValueCommand.new('z')
309
+ innerBlock = BlockCommand.new()
310
+ innerBlock.add(xCommand)
311
+ innerBlock.add(yCommand)
312
+ innerBlock.add(zCommand)
313
+ cCommand = LoopCommand.new('c', innerBlock)
314
+ outerBlock = BlockCommand.new()
315
+ outerBlock.add(aCommand)
316
+ outerBlock.add(bCommand)
317
+ outerBlock.add(cCommand)
318
+ loopCommand = LoopCommand.new('loop', outerBlock)
319
+
320
+ # Loop in a loop should yield lots of text ;-)
321
+ # 'o1 o2 i1 i2 i3 i4 i5 i6 o3 o4 j1 j2 j3 j4 j5 j6 '
322
+ assert_equal('o1 o2 i1 i2 i3 i4 i5 i6 o3 o4 j1 j2 j3 j4 j5 j6 ',
323
+ loopCommand.output(ns))
324
+
325
+ # False in a loop should yield outside loop
326
+ # 'o1 o2 o3 o4 '
327
+ loop1.each { |item| item['c'] = [] }
328
+ assert_equal('o1 o2 o3 o4 ', loopCommand.output(ns))
329
+ end
330
+
331
+ def testMixedNesting
332
+ # Loop in If
333
+ loop1 = [
334
+ { 'a' => '1 ', 'b' => '2 ', 'c' => '3 ' },
335
+ { 'a' => 'x ', 'b' => 'y ', 'c' => 'z ' }
336
+ ]
337
+
338
+ aCommand = ValueCommand.new('a')
339
+ bCommand = ValueCommand.new('b')
340
+ cCommand = ValueCommand.new('c')
341
+ loopBlock = BlockCommand.new()
342
+ loopBlock.add(aCommand)
343
+ loopBlock.add(bCommand)
344
+ loopBlock.add(cCommand)
345
+ loopCommand = LoopCommand.new("loop", loopBlock)
346
+ ifBlock = BlockCommand.new()
347
+ ifBlock.add(loopCommand)
348
+ ifCommand = IfCommand.new("flag", ifBlock)
349
+
350
+ ns = Namespace.new()
351
+ ns.set("loop", loop1)
352
+ ns.set("flag", 1)
353
+ assert_equal("1 2 3 x y z ", ifCommand.output(ns))
354
+ ns.set("flag", false)
355
+ assert_nil(ifCommand.output(ns))
356
+
357
+ # If in Loop
358
+
359
+ dCommand = TextCommand.new("(true)")
360
+ ifBlock = BlockCommand.new()
361
+ ifBlock.add(dCommand)
362
+ ifCommand = IfCommand.new("flag", ifBlock)
363
+ loopBlock = BlockCommand.new()
364
+ loopBlock.add(aCommand)
365
+ loopBlock.add(bCommand)
366
+ loopBlock.add(cCommand)
367
+ loopBlock.add(ifCommand)
368
+ loopCommand = LoopCommand.new("loop", loopBlock)
369
+
370
+ loop1[-1]['flag'] = 1
371
+ assert_equal("1 2 3 x y z (true)", loopCommand.output(ns))
372
+ loop1[-1]['flag'] = false
373
+ assert_equal("1 2 3 x y z ", loopCommand.output(ns))
374
+ end
375
+
376
+ end
377
+
378
+ class TC_SyntaxGlossary < Test::Unit::TestCase
379
+ @@syntax = Syntax::Glossary.new( /\[%(.+?)%\]/,
380
+ 'value' => /var (\w+)/,
381
+ 'ifopen' => /if (\w+)/,
382
+ 'ifclose' => /endif/,
383
+ 'unlessopen' => /unless (\w+)/,
384
+ 'unlessclose' => /endunless/,
385
+ 'ifbranch' => /else/,
386
+ 'loopopen' => /in (\w+)/,
387
+ 'loopclose' => /endin/,
388
+ 'loopbranch' => /no/,
389
+ 'include' => /include (\w+)/,
390
+ 'comment' => /--.+?--/
391
+ )
392
+
393
+ def testGlossary
394
+ assert_equal(/\[%(.+?)%\]/, @@syntax.directive)
395
+ assert_equal(/in (\w+)/, @@syntax.glossary['loopopen'])
396
+
397
+ badSyntax = {
398
+ 'flargle' => /flargle/
399
+ }
400
+ assert_raises(ArgumentError) {
401
+ Syntax::Glossary.new(/%(.+?)%/, badSyntax)
402
+ }
403
+ end
404
+
405
+ def testLookup
406
+ assert_equal(["value", "name"], @@syntax.lookup("var name"))
407
+ assert_equal(["ifopen", "name"], @@syntax.lookup("if name"))
408
+ assert_equal(["ifclose", nil], @@syntax.lookup("endif"))
409
+ assert_equal(["ifbranch", nil], @@syntax.lookup("else"))
410
+ assert_equal(["loopopen", "x"], @@syntax.lookup("in x"))
411
+ assert_equal(["loopclose", nil], @@syntax.lookup("endin"))
412
+ assert_equal(["loopbranch", nil], @@syntax.lookup("no"))
413
+ assert_equal(["include", "foo"], @@syntax.lookup("include foo"))
414
+ assert_equal(["comment", nil], @@syntax.lookup("-- blarg! --"))
415
+ assert_nil(@@syntax.lookup("foo"))
416
+ assert_nil(@@syntax.lookup("foo bar"))
417
+ end
418
+
419
+ end
420
+
421
+ class TC_SyntaxParser < Test::Unit::TestCase
422
+ @@parser = Syntax::Parser.new(Syntax::DEFAULT)
423
+
424
+ def testParse
425
+ assert_equal([[1, ""]], @@parser.parse([""]))
426
+ assert_equal([
427
+ [1, "Hello "],
428
+ [1, ["value", "world"]],
429
+ [1, ""]
430
+ ], @@parser.parse(["Hello [%var world%]"])
431
+ )
432
+
433
+ assert_equal([
434
+ [1, ""],
435
+ [1, ["value", "articleno"]],
436
+ [1, ""]
437
+ ], @@parser.parse(["[%var articleno%]"]))
438
+ assert_equal([
439
+ [1, ""],
440
+ [1, ["value", "articleno"]],
441
+ [1, ""]
442
+ ], @@parser.parse(["[% var articleno %\]"]))
443
+
444
+ multiline = [
445
+ "Hello [%var world%\]",
446
+ "[%if return%]",
447
+ "Welcome Back!",
448
+ "[%endif%]"
449
+ ]
450
+
451
+ mResult = [
452
+ [1, "Hello "],
453
+ [1, ["value", "world"]],
454
+ [1, ""],
455
+ [2, ""],
456
+ [2, ["ifopen", "return"]],
457
+ [2, ""],
458
+ [3, "Welcome Back!"],
459
+ [4, ""],
460
+ [4, ["ifclose", nil]],
461
+ [4, ""]
462
+ ]
463
+
464
+ assert_equal(mResult, @@parser.parse(multiline))
465
+
466
+ multiline = [
467
+ "Hello [%var world%\]",
468
+ "[%unless return%]",
469
+ "Welcome!",
470
+ "[%endunless%]"
471
+ ]
472
+
473
+ mResult = [
474
+ [1, "Hello "],
475
+ [1, ["value", "world"]],
476
+ [1, ""],
477
+ [2, ""],
478
+ [2, ["unlessopen", "return"]],
479
+ [2, ""],
480
+ [3, "Welcome!"],
481
+ [4, ""],
482
+ [4, ["unlessclose", nil]],
483
+ [4, ""]
484
+ ]
485
+
486
+ assert_equal(mResult, @@parser.parse(multiline))
487
+
488
+ end
489
+
490
+ def testCompile
491
+ directives = [
492
+ "Hello [%var world%]",
493
+ "[%if return%]",
494
+ "Welcome Back!",
495
+ "[%endif%]"
496
+ ]
497
+ assert(@@parser.compile(@@parser.parse(directives)))
498
+
499
+ directives = [
500
+ "Hello [%var world%]",
501
+ "[%unless return%]",
502
+ "Welcome!",
503
+ "[%endunless%]"
504
+ ]
505
+ assert(@@parser.compile(@@parser.parse(directives)))
506
+ end
507
+
508
+ def testBuild
509
+ assert(@@parser.build("tdata/p/b1.txt"))
510
+ # Make sure nothing panics if we ask for the commands again.
511
+ assert(@@parser.build("tdata/p/b1.txt"))
512
+ end
513
+ end
514
+
515
+ class TC_SyntaxCachedParser < Test::Unit::TestCase
516
+ @@parser = Syntax::CachedParser.new(Syntax::DEFAULT)
517
+
518
+ def testBuild
519
+ assert(@@parser.build("tdata/p/b1.txt"))
520
+ assert(File.exists?("tdata/p/_b1.txt"))
521
+
522
+ ns = Namespace.new()
523
+ ns["world"] = "World"
524
+ assert(@@parser.output(ns))
525
+ end
526
+
527
+ def testCachedBuild
528
+ assert(@@parser.build("tdata/p/cb1.txt"))
529
+ assert(File.exists?("tdata/p/_cb1.txt"))
530
+ assert(@@parser.reset)
531
+ assert(@@parser.build("tdata/p/cb1.txt"))
532
+ end
533
+
534
+ def testCachedRebuild
535
+ # Create a new parser and build with the cached information.
536
+ p2 = Syntax::CachedParser.new(Syntax::DEFAULT)
537
+ assert(p2.build("tdata/p/cb1.txt"))
538
+
539
+ # Clean up after ourselves.
540
+ system("rm -f tdata/p/_cb1.txt")
541
+ end
542
+ end
543
+
544
+ class TC_PageTemplate < Test::Unit::TestCase
545
+ @@template = PageTemplate.new( 'syntax' => Syntax::DEFAULT )
546
+
547
+ def testLoadFile
548
+ assert(@@template.load("tdata/t.txt"))
549
+ assert_equal("tdata/t.txt", @@template.file)
550
+ assert_raises(ArgumentError) { @@template.load("tdata/null") }
551
+ end
552
+
553
+ def testInitializeTemplate
554
+ assert(PageTemplate.new())
555
+ assert(PageTemplate.new("filename" => "tdata/t.txt"))
556
+ assert_raises(ArgumentError) { PageTemplate.new("filename" => "tdata/null") }
557
+ end
558
+
559
+ def testSetParameter
560
+ assert(@@template.setParameter("name", "PageTemplate"))
561
+ end
562
+
563
+ def testGetParameter
564
+ @@template.setParameter("name", "PageTemplate")
565
+ assert_equal("PageTemplate", @@template.getParameter("name"))
566
+ assert_nil(@@template.getParameter("null"))
567
+ end
568
+
569
+ def testHashAccess
570
+ @@template['hash'] = 'test'
571
+ assert_equal('test', @@template['hash'])
572
+ end
573
+
574
+ def testOutputNoMarkup
575
+ @@template.load("tdata/nm.txt")
576
+ cmpFile = File.open("tdata/nm.txt").read()
577
+ assert_equal(cmpFile, @@template.output())
578
+ end
579
+
580
+ def testOutputCommentMarkup
581
+ @@template.load("tdata/cm.txt")
582
+ assert(@@template.output !~ /\[%--/)
583
+ end
584
+
585
+ def testOutputValueMarkup
586
+
587
+ # Valid markup, value exists.
588
+ @@template['title'] = "ValueMarkup"
589
+ @@template.load("tdata/v1.txt")
590
+ assert(@@template.output =~ /<h1>ValueMarkup<\/h1>/)
591
+
592
+ # Valid markup, value does not exist.
593
+ @@template['title'] = ""
594
+ assert(@@template.output =~ /<h1><\/h1>/)
595
+
596
+ # Invalid markup.
597
+ @@template.load("tdata/v2.txt")
598
+ assert(@@template.output =~ /<h1>title%\]<\/h1>/)
599
+ end
600
+
601
+ def testOutputIfMarkup
602
+ @@template['flag'] = true
603
+ @@template.load("tdata/i1.txt")
604
+ assert(@@template.output =~ /It's all true!/)
605
+
606
+ @@template['flag'] = false
607
+ assert(@@template.output !~ /It's all true!/)
608
+
609
+ # Nested if expressions
610
+ @@template.load("tdata/i2.txt")
611
+
612
+ # 1. Both true.
613
+ @@template['outer'] = true
614
+ @@template['inner'] = true
615
+ assert(@@template.output =~ /This is outer text/)
616
+ assert(@@template.output =~ /This is inner text/)
617
+
618
+ # 2. Outer true, inner false.
619
+ @@template['outer'] = true
620
+ @@template['inner'] = false
621
+ assert(@@template.output =~ /This is outer text/)
622
+ assert(@@template.output !~ /This is inner text/)
623
+
624
+ # 3. Inner true, outer false.
625
+ @@template['outer'] = false
626
+ @@template['inner'] = true
627
+ assert(@@template.output !~ /This is outer text/)
628
+ assert(@@template.output !~ /This is inner text/)
629
+ end
630
+
631
+ def testOutputIfBranchMarkup
632
+ @@template.load("tdata/ie1.txt")
633
+
634
+ # True: if block executes, not else block
635
+ @@template["flag"] = true
636
+ assert(@@template.output =~ /It's all true!/)
637
+ assert(@@template.output !~ /Nothing is true/)
638
+
639
+ # False: else block executes, not if block
640
+ @@template["flag"] = false
641
+ assert(@@template.output =~ /Nothing is true/)
642
+ assert(@@template.output !~ /It's all true!/)
643
+ end
644
+
645
+ def testOutputNestedIfBranchMarkup
646
+ @@template.load("tdata/ie2.txt")
647
+
648
+ # Outer true, inner true
649
+ @@template['outer'] = true
650
+ @@template['inner'] = true
651
+ assert(@@template.output =~ /Outer is true/)
652
+ assert(@@template.output =~ /Inner is true/)
653
+
654
+ # Outer true, inner false
655
+ @@template['outer'] = true
656
+ @@template['inner'] = false
657
+ assert(@@template.output =~ /Outer is true/)
658
+ assert(@@template.output =~ /Inner is false/)
659
+
660
+ # Outer false, inner true
661
+ @@template['outer'] = false
662
+ @@template['inner'] = true
663
+ assert(@@template.output =~ /Outer is false/)
664
+ assert(@@template.output =~ /Inner is true/)
665
+
666
+ # Outer false, inner false
667
+ @@template['outer'] = false
668
+ @@template['inner'] = false
669
+ assert(@@template.output =~ /Outer is false/)
670
+ assert(@@template.output =~ /Inner is false/)
671
+ end
672
+
673
+ def testOutputLoopMarkup
674
+ @@template.load("tdata/l1.txt")
675
+
676
+ # Loop Exists
677
+ myLoop = []
678
+ 1.upto(5) { |v| myLoop << {'value' => v} }
679
+
680
+ @@template['loop'] = myLoop
681
+ assert(@@template.output =~ /<li>3<\/li>/)
682
+
683
+ # Loop Doesn't Exist
684
+ @@template['loop'] = false
685
+ assert(@@template.output !~ /<li>3<\/li>/)
686
+
687
+ # Loop Is Empty List
688
+ @@template['loop'] = []
689
+ assert(@@template.output !~ /<li>.*?<\/li>/)
690
+ end
691
+
692
+ def testLoopMetavariables
693
+ @@template.load("tdata/metadata.1.txt")
694
+ myLoop = []
695
+ 1.upto(5) { |v| myLoop << {'v' => v} }
696
+
697
+ @@template['loop'] = myLoop
698
+ assert(@@template.output =~ /<li>--1--<\/li>/,
699
+ "__FIRST__ is set for the first iteration through a loop")
700
+ assert(@@template.output =~ /<li>5<\/li>/,
701
+ "__FIRST__ is unset after the first iteration through a loop")
702
+
703
+ @@template.load("tdata/metadata.2.txt")
704
+ assert(@@template.output =~ /<li>--5--<\/li>/,
705
+ "__LAST__ is set for the last iteration through a loop")
706
+ assert(@@template.output =~ /<li>1<\/li>/,
707
+ "__LAST__ is unset before the last iteration through a loop")
708
+
709
+ @@template.load("tdata/metadata.3.txt")
710
+ assert(@@template.output =~ /<li>--1--<\/li>/,
711
+ "__ODD__ is set for odd-numbered iterations through a loop (1st, 3rd, etc)")
712
+ assert(@@template.output =~ /<li>2<\/li>/,
713
+ "__ODD__ is unset for even-numbered iterations through a loop (2nd, 4th, etc)")
714
+ end
715
+
716
+ def testOutputNestedLoopMarkup
717
+ @@template.load("tdata/l2.txt")
718
+
719
+ # Outer Loop Exists, Inner Loop Exists
720
+ innerLoop = []
721
+ 'a'.upto('f') { |v| innerLoop << { 'value' => v } }
722
+ outerLoop = []
723
+ 1.upto(5) do |v|
724
+ outerLoop << {'value' => v, 'inner' => innerLoop}
725
+ end
726
+ @@template['loop'] = outerLoop
727
+ assert(@@template.output =~ /<li>\d/)
728
+ assert(@@template.output =~ /<li>[a-f]<\/li>/)
729
+
730
+ # Outer Loop Exists, Inner Loop Empty
731
+ outerLoop.each { |x| x['inner'] = [] }
732
+ assert(@@template.output !~ /<li>[a-f]<\/li>/)
733
+
734
+ # Outer Loop Exists, Alternate Inner Loops Empty
735
+ outerLoop.each_with_index do |x, i|
736
+ x['inner'] = innerLoop if i % 2 == 0
737
+ end
738
+ assert(@@template.output =~ /<li>4\s+?<ul><\/ul>/m)
739
+ assert(@@template.output =~ /<li>3\s+?<ul><li>a/m)
740
+
741
+ # Outer Loop Empty
742
+ @@template['loop'] = false
743
+ assert(@@template.output !~ /<li>/)
744
+ end
745
+
746
+ def testOutputLoopBranchMarkup
747
+ @@template.load("tdata/ib1.txt")
748
+
749
+ # Loop exists
750
+ myLoop = []
751
+ 1.upto(5) { |v| myLoop << {'value' => v} }
752
+ @@template['loop'] = myLoop
753
+ assert(@@template.output =~ /<li>\d<\/li>/)
754
+ assert(@@template.output !~ /No values/)
755
+
756
+ # No loop
757
+ @@template['loop'] = []
758
+ assert(@@template.output !~ /<li>\d<\/li>/)
759
+ assert(@@template.output =~ /No values/)
760
+ end
761
+
762
+ def testOutputNestedLoopBranchMarkup
763
+ @@template.load("tdata/ib2.txt")
764
+ # Outer Loop Exists, Inner Loop Exists
765
+ innerLoop = []
766
+ 'a'.upto('f') { |v| innerLoop << { 'value' => v } }
767
+ outerLoop = []
768
+ 1.upto(5) do |v|
769
+ outerLoop << {'value' => v, 'inner' => innerLoop}
770
+ end
771
+ @@template['loop'] = outerLoop
772
+ assert(@@template.output =~ /<li>\d/)
773
+ assert(@@template.output =~ /<li>[a-f]<\/li>/)
774
+
775
+ # Outer Loop Exists, Inner Loop Empty
776
+ outerLoop.each { |x| x['inner'] = [] }
777
+ assert(@@template.output =~ /No inner values/)
778
+
779
+ # Outer Loop Exists, Alternate Inner Loops Empty
780
+ outerLoop.each_with_index do |x, i|
781
+ x['inner'] = innerLoop if i % 2 == 0
782
+ end
783
+ assert(@@template.output =~ /<li>4\s+?<ul>.+?No inner values/m)
784
+ assert(@@template.output =~ /<li>3\s+?<ul>.+?<li>a/m)
785
+
786
+ # Outer Loop Empty
787
+ @@template['loop'] = false
788
+ assert(@@template.output =~ /No values/)
789
+ end
790
+
791
+ def testOutputComplexMarkup
792
+ title = "Testing"
793
+ reverse = true
794
+
795
+ languages = [
796
+ { 'name'=> 'C', 'author'=> 'Dennis Ritchie' },
797
+ { 'name'=> 'C++', 'author'=> 'Bjarne Stroustrup' },
798
+ { 'name'=> 'Perl', 'author'=> 'Larry Wall',
799
+ 'guideline'=> 'TMTOWTDI - There\'s More Than One Way To Do It'},
800
+ { 'name'=> 'Python', 'author'=> 'Guido van Rossum',
801
+ 'guideline'=> 'There Should Be One Obvious Way To Do It' },
802
+ { 'name'=> 'Ruby', 'author'=> 'Yukihiro Matsumoto',
803
+ 'guideline'=> 'TPOL - The Principle Of Least Surprise'}
804
+ ]
805
+
806
+ favorites = [
807
+ { 'topic'=> 'Interesting Comic Books',
808
+ 'items'=> [
809
+ {'title'=> 'Dropsie Avenue',
810
+ 'creator'=> 'Will Eisner'},
811
+ {'title'=> 'Cerebus',
812
+ 'creator'=> 'Dave Sim'},
813
+ {'title'=> 'Jar Of Fools',
814
+ 'creator'=> 'Jason Lutes'}]},
815
+ { 'topic'=> 'Favorite Albums',
816
+ 'items'=> [
817
+ {'title'=> 'Amnesiac',
818
+ 'creator'=> 'Radiohead'},
819
+ {'title'=> 'The Moon and Antarctica',
820
+ 'creator'=> 'Modest Mouse'},
821
+ {'title'=> 'Dirt Track Date',
822
+ 'creator'=> 'Southern Culture On The Skids'},
823
+ {'title'=> 'My Motor',
824
+ 'creator'=> 'Dorkweed'},
825
+ {'title'=> 'Swordfishtrombones',
826
+ 'creator'=> 'Tom Waits'}]}
827
+ ]
828
+
829
+ page = PageTemplate.new('filename' => "tdata/complex.txt")
830
+ page.setParameter("title", title)
831
+ page.setParameter("ifTest", 1)
832
+ page.setParameter("languages", languages)
833
+ page.setParameter("favorites", favorites)
834
+ if reverse == 1
835
+ page.setParameter("reverse", 1)
836
+ end
837
+
838
+ assert(page.output)
839
+ end
840
+
841
+ def testCachedTemplate
842
+ assert(ct = PageTemplate.new('filename' => "tdata/complex.txt",
843
+ 'use_cache' => true
844
+ ))
845
+
846
+ languages = [
847
+ { 'name'=> 'C', 'author'=> 'Dennis Ritchie' },
848
+ { 'name'=> 'C++', 'author'=> 'Bjarne Stroustrup' },
849
+ { 'name'=> 'Perl', 'author'=> 'Larry Wall',
850
+ 'guideline'=> 'TMTOWTDI - There\'s More Than One Way To Do It'},
851
+ { 'name'=> 'Python', 'author'=> 'Guido van Rossum',
852
+ 'guideline'=> 'There Should Be One Obvious Way To Do It' },
853
+ { 'name'=> 'Ruby', 'author'=> 'Yukihiro Matsumoto',
854
+ 'guideline'=> 'TPOL - The Principle Of Least Surprise'}
855
+ ]
856
+
857
+ favorites = [
858
+ { 'topic'=> 'Interesting Comic Books',
859
+ 'items'=> [
860
+ {'title'=> 'Dropsie Avenue',
861
+ 'creator'=> 'Will Eisner'},
862
+ {'title'=> 'Cerebus',
863
+ 'creator'=> 'Dave Sim'},
864
+ {'title'=> 'Jar Of Fools',
865
+ 'creator'=> 'Jason Lutes'}]},
866
+ { 'topic'=> 'Favorite Albums',
867
+ 'items'=> [
868
+ {'title'=> 'Amnesiac',
869
+ 'creator'=> 'Radiohead'},
870
+ {'title'=> 'The Moon and Antarctica',
871
+ 'creator'=> 'Modest Mouse'},
872
+ {'title'=> 'Dirt Track Date',
873
+ 'creator'=> 'Southern Culture On The Skids'},
874
+ {'title'=> 'My Motor',
875
+ 'creator'=> 'Dorkweed'},
876
+ {'title'=> 'Swordfishtrombones',
877
+ 'creator'=> 'Tom Waits'}]}
878
+ ]
879
+ ct["languages"] = languages
880
+ ct["favorites"] = favorites
881
+ assert(ct.output)
882
+ assert(File.exists?("tdata/_complex.txt"))
883
+ system("rm -f tdata/_complex.txt")
884
+
885
+ end
886
+
887
+ def testClearFile
888
+ assert(@@template.clearFile)
889
+ end
890
+ end
891
+
892
+ class TC_Include < Test::Unit::TestCase
893
+ def testIncludeCommand()
894
+ ns = Namespace.new()
895
+
896
+ incCommand = IncludeCommand.new("tdata/include.1.txt")
897
+ text = File.open("tdata/include.1.txt").read()
898
+ assert_equal(text, incCommand.output(ns),
899
+ "IncludeCommands can be initialized with relative filenames")
900
+
901
+ text = File.open("tdata/include.2.txt").read()
902
+ incCommand = IncludeCommand.new("tdata/include.2.txt")
903
+ assert_equal(text, incCommand.output(ns))
904
+
905
+ # Including text with template markup.
906
+ ns["x"] = "Dude!"
907
+ pt = PageTemplate.new()
908
+ pt.load("tdata/include.3.txt")
909
+ pt["x"] = "Dude!"
910
+ incCommand = IncludeCommand.new("tdata/include.3.txt")
911
+ assert_equal(pt.output(), incCommand.output(ns),
912
+ "Include Commands can parse standard Template markup")
913
+ end
914
+
915
+ def testIncludePath
916
+ incCommand = IncludeCommand.new("include.4.txt", [ "tdata" ])
917
+ text = File.open("tdata/include.4.out.txt").read()
918
+ assert_equal(text, incCommand.output,
919
+ "IncludeCommand accepts an array of paths as a second arg")
920
+
921
+ incCommand = IncludeCommand.new("include.4.txt", [ "/etc", "tdata" ])
922
+ text = File.open("tdata/include.4.out.txt").read()
923
+ assert_equal(text, incCommand.output,
924
+ "IncludeCommand accepts an array of paths as a second arg")
925
+
926
+ pt = PageTemplate.new('include_path' => "tdata")
927
+ pt.load("tdata/include.4b.txt")
928
+ pt["file"] = "include.4a.txt"
929
+ text = File.open("tdata/include.4.out.txt").read()
930
+ assert_equal(text, pt.output,
931
+ "Include Commands can be given a variable name as an argument")
932
+
933
+ pt = PageTemplate.new('include_path' => "tdata")
934
+ pt.load("tdata/include.4b.txt")
935
+ pt["file"] = "secret-of-life.txt"
936
+ text = File.open("tdata/include.4.nf.out.txt").read()
937
+ assert_equal(text, pt.output,
938
+ "Include Commands will output a warning if file isn't found.")
939
+
940
+ # Support for multiple include paths.
941
+ pt = PageTemplate.new()
942
+ assert_equal([ Dir.getwd() ], pt.path)
943
+ assert(pt.add_path('tdata'),
944
+ "Use #add_path(path) to add an include path.")
945
+ assert_equal([ Dir.getwd(), 'tdata'], pt.path)
946
+ pt.add_path('tdata/inc-1')
947
+ assert_equal([ Dir.getwd, "tdata", "tdata/inc-1"], pt.path)
948
+ pt = PageTemplate.new('include_path' => %w{tdata tdata/inc-1})
949
+ assert_equal([ Dir.getwd, "tdata", "tdata/inc-1"], pt.path)
950
+ end
951
+
952
+ def testIncludeSyntax
953
+ text = File.open("tdata/include.4.out.txt").read()
954
+ pt = PageTemplate.new("include_path" => "tdata")
955
+ pt.load("include.4.txt")
956
+ assert_equal(text, pt.output(),
957
+ "PageTemplate supports 'include' syntax")
958
+ pt = PageTemplate.new('include_path' => "tdata")
959
+ pt.load("include.5.txt")
960
+ assert_equal(text, pt.output(),
961
+ "PageTemplate supports 'include' syntax")
962
+
963
+ end
964
+
965
+ end