Handle QStringList in a loop as a special case.
[grantlee:grantlee.git] / tests / testdefaulttags.cpp
1 /*
2   This file is part of the Grantlee template system.
3
4   Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
5
6   This library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Lesser General Public
8   License as published by the Free Software Foundation; either version
9   2 of the Licence, or (at your option) any later version.
10
11   This library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with this library.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #ifndef DEFAULTTAGSTEST_H
22 #define DEFAULTTAGSTEST_H
23
24 #include <QtTest>
25 #include <QtCore/QObject>
26
27 #include "template.h"
28 #include "engine.h"
29 #include "context.h"
30 #include "util.h"
31 #include "grantlee_paths.h"
32
33 typedef QHash<QString, QVariant> Dict;
34 typedef QPair<QString, QString> StringPair;
35
36 Q_DECLARE_METATYPE( Dict )
37 Q_DECLARE_METATYPE( StringPair )
38 Q_DECLARE_METATYPE( Grantlee::Error )
39
40 class FakeTemplateLoader : public Grantlee::InMemoryTemplateLoader
41 {
42 public:
43
44   typedef QSharedPointer<FakeTemplateLoader> Ptr;
45
46   FakeTemplateLoader()
47     : Grantlee::InMemoryTemplateLoader()
48   {
49     m_existingMedia << "existing_image.png" << "another_existing_image.png";
50   }
51
52   /* reimp */ QPair<QString, QString> getMediaUri( const QString &fileName ) const {
53     if ( m_existingMedia.contains( fileName ) )
54       return qMakePair( QString( "/path/to/" ), fileName );
55     return QPair<QString, QString>();
56   }
57
58 private:
59   QStringList m_existingMedia;
60 };
61
62 using namespace Grantlee;
63
64 class TestDefaultTags : public QObject
65 {
66   Q_OBJECT
67
68 private Q_SLOTS:
69   void initTestCase();
70   void cleanupTestCase();
71
72   void testCommentTag_data();
73   void testCommentTag() {
74     doTest();
75   }
76
77   void testFirstOfTag_data();
78   void testFirstOfTag() {
79     doTest();
80   }
81
82   void testIfTag_data();
83   void testIfTag() {
84     doTest();
85   }
86
87   void testForTag_data();
88   void testForTag() {
89     doTest();
90   }
91
92   void testIfEqualTag_data();
93   void testIfEqualTag() {
94     doTest();
95   }
96
97   void testIfNotEqualTag_data();
98   void testIfNotEqualTag() {
99     doTest();
100   }
101
102   void testTemplateTagTag_data();
103   void testTemplateTagTag() {
104     doTest();
105   }
106
107   void testWithTag_data();
108   void testWithTag() {
109     doTest();
110   }
111
112   void testCycleTag_data();
113   void testCycleTag() {
114     doTest();
115   }
116
117   void testWidthRatioTag_data();
118   void testWidthRatioTag() {
119     doTest();
120   }
121
122   void testFilterTag_data();
123   void testFilterTag() {
124     doTest();
125   }
126
127   void testNowTag_data();
128   void testNowTag() {
129     doTest();
130   }
131
132   void testSpacelessTag_data();
133   void testSpacelessTag() {
134     doTest();
135   }
136
137   void testRegroupTag_data();
138   void testRegroupTag() {
139     doTest();
140   }
141
142   void testIfChangedTag_data();
143   void testIfChangedTag() {
144     doTest();
145   }
146
147   void testAutoescapeTag_data();
148   void testAutoescapeTag() {
149     doTest();
150   }
151
152   void testMediaFinderTag_data();
153   void testMediaFinderTag() {
154     doTest();
155   }
156
157   void testRangeTag_data();
158   void testRangeTag() {
159     doTest();
160   }
161
162   void testUrlTypes_data();
163   void testUrlTypes();
164
165   void testRelativePaths_data();
166   void testRelativePaths();
167
168 private:
169
170   void doTest();
171
172   Engine *m_engine;
173
174 };
175
176 void TestDefaultTags::initTestCase()
177 {
178   m_engine = new Engine( this );
179   m_engine->setPluginPaths( QStringList() << GRANTLEE_PLUGIN_PATH );
180
181   FakeTemplateLoader::Ptr loader1 = FakeTemplateLoader::Ptr( new FakeTemplateLoader() );
182
183   m_engine->addTemplateLoader( loader1 );
184 }
185
186 void TestDefaultTags::cleanupTestCase()
187 {
188   delete m_engine;
189 }
190
191 void TestDefaultTags::doTest()
192 {
193   QFETCH( QString, input );
194   QFETCH( Dict, dict );
195   QFETCH( QString, output );
196   QFETCH( Grantlee::Error, error );
197
198   Template t = m_engine->newTemplate( input, QTest::currentDataTag() );
199
200   Context context( dict );
201
202   QString result = t->render( &context );
203
204   if ( t->error() != NoError ) {
205     if ( t->error() != error )
206       qDebug() << t->errorString();
207     QCOMPARE( t->error(), error );
208     return;
209   }
210
211   // Didn't catch any errors, so make sure I didn't expect any.
212   QCOMPARE( NoError, error );
213
214   QCOMPARE( t->error(), NoError );
215
216   QCOMPARE( result, output );
217 }
218
219 void TestDefaultTags::testCommentTag_data()
220 {
221   QTest::addColumn<QString>( "input" );
222   QTest::addColumn<Dict>( "dict" );
223   QTest::addColumn<QString>( "output" );
224   QTest::addColumn<Grantlee::Error>( "error" );
225
226   Dict dict;
227
228   QTest::newRow( "comment-tag01" ) << "{% comment %}this is hidden{% endcomment %}hello" << dict << "hello" << NoError;
229
230   QTest::newRow( "comment-tag02" ) << "{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}" << dict << "hello" << NoError;
231   // Comment tag can contain invalid stuff.
232   QTest::newRow( "comment-tag03" ) << "foo{% comment %} {% if %} {% endcomment %}" << dict << "foo" << NoError;
233   QTest::newRow( "comment-tag04" ) << "foo{% comment %} {% endblock %} {% endcomment %}" << dict << "foo" << NoError;
234   QTest::newRow( "comment-tag05" ) << "foo{% comment %} {% somerandomtag %} {% endcomment %}" << dict << "foo" << NoError;
235 }
236
237 void TestDefaultTags::testFirstOfTag_data()
238 {
239   QTest::addColumn<QString>( "input" );
240   QTest::addColumn<Dict>( "dict" );
241   QTest::addColumn<QString>( "output" );
242   QTest::addColumn<Grantlee::Error>( "error" );
243
244   Dict dict;
245   dict.insert( "a", 0 );
246   dict.insert( "b", 0 );
247   dict.insert( "c", 0 );
248   QTest::newRow( "firstof01" ) << "{% firstof a b c %}" << dict << "" << NoError;
249
250   dict.clear();
251   dict.insert( "a", 1 );
252   dict.insert( "b", 0 );
253   dict.insert( "c", 0 );
254   QTest::newRow( "firstof02" ) << "{% firstof a b c %}" << dict << "1" << NoError;
255
256   dict.clear();
257   dict.insert( "a", 0 );
258   dict.insert( "b", 2 );
259   dict.insert( "c", 0 );
260   QTest::newRow( "firstof03" ) << "{% firstof a b c %}" << dict << "2" << NoError;
261
262   dict.clear();
263   dict.insert( "a", 0 );
264   dict.insert( "b", 0 );
265   dict.insert( "c", 3 );
266   QTest::newRow( "firstof04" ) << "{% firstof a b c %}" << dict << "3" << NoError;
267
268   dict.clear();
269   dict.insert( "a", 1 );
270   dict.insert( "b", 2 );
271   dict.insert( "c", 3 );
272   QTest::newRow( "firstof05" ) << "{% firstof a b c %}" << dict << "1" << NoError;
273
274   dict.clear();
275   dict.insert( "b", 0 );
276   dict.insert( "c", 3 );
277   QTest::newRow( "firstof06" ) << "{% firstof a b c %}" << dict << "3" << NoError;
278
279   dict.clear();
280   dict.insert( "a", 0 );
281   QTest::newRow( "firstof07" ) << "{% firstof a b \"c\" %}" << dict << "c" << NoError;
282
283   dict.clear();
284   dict.insert( "a", 0 );
285   dict.insert( "b", 0 );
286   QTest::newRow( "firstof08" ) << "{% firstof a b \"c and d\" %}" << dict << "c and d" << NoError;
287   QTest::newRow( "firstof09" ) << "{% firstof %}" << dict << "a" << TagSyntaxError;
288
289 }
290
291
292 void TestDefaultTags::testIfTag_data()
293 {
294   QTest::addColumn<QString>( "input" );
295   QTest::addColumn<Dict>( "dict" );
296   QTest::addColumn<QString>( "output" );
297   QTest::addColumn<Grantlee::Error>( "error" );
298
299   Dict dict;
300
301   dict.insert( "foo", true );
302
303   QTest::newRow( "if-tag01" ) << "{% if foo %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
304
305   dict.clear();
306   dict.insert( "foo", false );
307   QTest::newRow( "if-tag02" ) << "{% if foo %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
308
309   dict.clear();
310   QTest::newRow( "if-tag03" ) << "{% if foo %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
311
312   // AND
313
314   dict.clear();
315   dict.insert( "foo", true );
316   dict.insert( "bar", true );
317   QTest::newRow( "if-tag-and01" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
318
319   dict.clear();
320   dict.insert( "foo", true );
321   dict.insert( "bar", false );
322   QTest::newRow( "if-tag-and02" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
323
324   dict.clear();
325   dict.insert( "foo", false );
326   dict.insert( "bar", true );
327   QTest::newRow( "if-tag-and03" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
328
329   dict.clear();
330   dict.insert( "foo", false );
331   dict.insert( "bar", false );
332   QTest::newRow( "if-tag-and04" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
333
334   dict.clear();
335   dict.insert( "foo", false );
336   QTest::newRow( "if-tag-and05" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
337
338   dict.clear();
339   dict.insert( "bar", false );
340   QTest::newRow( "if-tag-and06" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
341
342   dict.clear();
343   dict.insert( "foo", true );
344   QTest::newRow( "if-tag-and07" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
345
346   dict.clear();
347   dict.insert( "bar", true );
348   QTest::newRow( "if-tag-and08" ) << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
349
350   // OR
351
352   dict.clear();
353   dict.insert( "foo", true );
354   dict.insert( "bar", true );
355   QTest::newRow( "if-tag-or01" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
356
357   dict.clear();
358   dict.insert( "foo", true );
359   dict.insert( "bar", false );
360   QTest::newRow( "if-tag-or02" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
361
362   dict.clear();
363   dict.insert( "foo", false );
364   dict.insert( "bar", true );
365   QTest::newRow( "if-tag-or03" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
366
367   dict.clear();
368   dict.insert( "foo", false );
369   dict.insert( "bar", false );
370   QTest::newRow( "if-tag-or04" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
371
372   dict.clear();
373   dict.insert( "foo", false );
374   QTest::newRow( "if-tag-or05" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
375
376   dict.clear();
377   dict.insert( "bar", false );
378   QTest::newRow( "if-tag-or06" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
379
380   dict.clear();
381   dict.insert( "foo", true );
382   QTest::newRow( "if-tag-or07" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
383
384   dict.clear();
385   dict.insert( "bar", true );
386   QTest::newRow( "if-tag-or08" ) << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
387
388   // TODO: multiple ORs
389
390
391   // NOT
392
393   dict.clear();
394   dict.insert( "foo", true );
395   QTest::newRow( "if-tag-not01" ) << "{% if not foo %}no{% else %}yes{% endif %}" << dict << "yes" << NoError;
396   QTest::newRow( "if-tag-not02" ) << "{% if not %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
397
398   dict.clear();
399   dict.insert( "not", true );
400   QTest::newRow( "if-tag-not03" ) << "{% if not %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
401   QTest::newRow( "if-tag-not04" ) << "{% if not not %}no{% else %}yes{% endif %}" << dict << "yes" << NoError;
402
403   dict.clear();
404   QTest::newRow( "if-tag-not05" ) << "{% if not not %}no{% else %}yes{% endif %}" << dict << "no" << NoError;
405   QTest::newRow( "if-tag-not06" ) << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
406
407   dict.clear();
408   dict.insert( "foo", true );
409   dict.insert( "bar", true );
410   QTest::newRow( "if-tag-not07" ) << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
411
412   dict.clear();
413   dict.insert( "foo", true );
414   dict.insert( "bar", false );
415   QTest::newRow( "if-tag-not08" ) << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
416
417   dict.clear();
418   dict.insert( "foo", false );
419   dict.insert( "bar", true );
420   QTest::newRow( "if-tag-not09" ) << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
421
422   dict.clear();
423   dict.insert( "foo", false );
424   dict.insert( "bar", false );
425   QTest::newRow( "if-tag-not10" ) << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
426
427   dict.clear();
428   QTest::newRow( "if-tag-not11" ) << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
429
430   dict.clear();
431   dict.insert( "foo", true );
432   dict.insert( "bar", true );
433   QTest::newRow( "if-tag-not12" ) << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
434
435   dict.clear();
436   dict.insert( "foo", true );
437   dict.insert( "bar", false );
438   QTest::newRow( "if-tag-not13" ) << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
439
440   dict.clear();
441   dict.insert( "foo", false );
442   dict.insert( "bar", true );
443   QTest::newRow( "if-tag-not14" ) << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
444
445   dict.clear();
446   dict.insert( "foo", false );
447   dict.insert( "bar", false );
448   QTest::newRow( "if-tag-not15" ) << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
449
450   dict.clear();
451   QTest::newRow( "if-tag-not16" ) << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
452
453   dict.clear();
454   dict.insert( "foo", true );
455   dict.insert( "bar", true );
456   QTest::newRow( "if-tag-not17" ) << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
457
458   dict.clear();
459   dict.insert( "foo", true );
460   dict.insert( "bar", false );
461   QTest::newRow( "if-tag-not18" ) << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
462
463   dict.clear();
464   dict.insert( "foo", false );
465   dict.insert( "bar", true );
466   QTest::newRow( "if-tag-not19" ) << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
467
468   dict.clear();
469   dict.insert( "foo", false );
470   dict.insert( "bar", false );
471   QTest::newRow( "if-tag-not20" ) << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
472
473   dict.clear();
474   QTest::newRow( "if-tag-not21" ) << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
475
476   dict.clear();
477   dict.insert( "foo", true );
478   dict.insert( "bar", true );
479   QTest::newRow( "if-tag-not22" ) << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
480
481   dict.clear();
482   dict.insert( "foo", true );
483   dict.insert( "bar", false );
484   QTest::newRow( "if-tag-not23" ) << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
485
486   dict.clear();
487   dict.insert( "foo", false );
488   dict.insert( "bar", true );
489   QTest::newRow( "if-tag-not24" ) << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
490
491   dict.clear();
492   dict.insert( "foo", false );
493   dict.insert( "bar", false );
494   QTest::newRow( "if-tag-not25" ) << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
495
496   dict.clear();
497   QTest::newRow( "if-tag-not26" ) << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
498
499   dict.clear();
500   dict.insert( "foo", true );
501   dict.insert( "bar", true );
502   QTest::newRow( "if-tag-not27" ) << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
503
504   dict.clear();
505   dict.insert( "foo", true );
506   dict.insert( "bar", false );
507   QTest::newRow( "if-tag-not28" ) << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
508
509   dict.clear();
510   dict.insert( "foo", false );
511   dict.insert( "bar", true );
512   QTest::newRow( "if-tag-not29" ) << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
513
514   dict.clear();
515   dict.insert( "foo", false );
516   dict.insert( "bar", false );
517   QTest::newRow( "if-tag-not30" ) << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
518
519   dict.clear();
520   QTest::newRow( "if-tag-not31" ) << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
521
522   dict.clear();
523   dict.insert( "foo", true );
524   dict.insert( "bar", true );
525   QTest::newRow( "if-tag-not32" ) << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
526
527   dict.clear();
528   dict.insert( "foo", true );
529   dict.insert( "bar", false );
530   QTest::newRow( "if-tag-not33" ) << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
531
532   dict.clear();
533   dict.insert( "foo", false );
534   dict.insert( "bar", true );
535   QTest::newRow( "if-tag-not34" ) << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
536
537   dict.clear();
538   dict.insert( "foo", false );
539   dict.insert( "bar", false );
540   QTest::newRow( "if-tag-not35" ) << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
541
542   // AND and OR raises a TemplateSyntaxError
543   QTest::newRow( "if-tag-error01" ) << "{% if foo or bar and baz %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
544
545   dict.clear();
546   dict.insert( "foo", true );
547   QTest::newRow( "if-tag-error02" ) << "{% if foo and %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
548   QTest::newRow( "if-tag-error03" ) << "{% if foo or %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
549   QTest::newRow( "if-tag-error04" ) << "{% if not foo and %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
550   QTest::newRow( "if-tag-error05" ) << "{% if not foo or %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
551
552   // Truthiness
553   dict.clear();
554   QVariantHash hash;
555   dict.insert( "var", hash );
556   QTest::newRow( "if-truthiness01" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
557   hash.insert( "foo", "bar" );
558   dict.insert( "var", hash );
559   QTest::newRow( "if-truthiness02" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
560   QVariantList list;
561   dict.insert( "var", list );
562   QTest::newRow( "if-truthiness03" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
563   list.append( "foo" );
564   dict.insert( "var", list );
565   QTest::newRow( "if-truthiness04" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
566
567   QVariant var;
568   dict.insert( "var", var );
569   QTest::newRow( "if-truthiness05" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
570   var = "foo";
571   dict.insert( "var", var );
572   QTest::newRow( "if-truthiness06" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
573
574   QString str;
575   dict.insert( "var", str );
576   QTest::newRow( "if-truthiness07" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
577   str = "foo";
578   dict.insert( "var", str );
579   QTest::newRow( "if-truthiness08" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
580
581   int i = 0;
582   dict.insert( "var", i );
583   QTest::newRow( "if-truthiness07" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
584   i = 7;
585   dict.insert( "var", i );
586   QTest::newRow( "if-truthiness08" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
587
588   qreal r = 0.0;
589   dict.insert( "var", r );
590   QTest::newRow( "if-truthiness09" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "No" << NoError;
591   r = 7.1;
592   dict.insert( "var", r );
593   QTest::newRow( "if-truthiness10" ) << "{% if var %}Yes{% else %}No{% endif %}" << dict << "Yes" << NoError;
594
595 }
596
597 void TestDefaultTags::testForTag_data()
598 {
599   QTest::addColumn<QString>( "input" );
600   QTest::addColumn<Dict>( "dict" );
601   QTest::addColumn<QString>( "output" );
602   QTest::addColumn<Grantlee::Error>( "error" );
603
604   Dict dict;
605
606   QVariantList list;
607   list << 1 << 2 << 3;
608   dict.insert( "values", list );
609   QTest::newRow( "for-tag01" ) << "{% for val in values %}{{ val }}{% endfor %}" << dict << "123" << NoError;
610   QTest::newRow( "for-tag02" ) << "{% for val in values reversed %}{{ val }}{% endfor %}" << dict << "321" << NoError;
611   list.clear();
612   dict.insert( "values", list );
613   QTest::newRow( "for-tag03" ) << "{% for val in values %}({{ val }} sdfsdf,){% endfor %}" << dict << "" << NoError;
614   QStringList emails;
615   emails << "one" << "two";
616   QVariantHash obj;
617   obj.insert("emails", emails);
618   dict.insert("contact", obj);
619   QTest::newRow( "for-tag04" ) << "{% for val in contact.emails %}({{ val }},){% endfor %}" << dict << "(one,)(two,)" << NoError;
620   emails.clear();
621   obj.insert("emails", emails);
622   dict.insert("contact", obj);
623   QTest::newRow( "for-tag05" ) << "{% for val in contact.emails %}({{ val }},){% endfor %}" << dict << "" << NoError;
624   list.clear();
625   list << 1 << 2 << 3;
626   dict.insert( "values", list );
627   QTest::newRow( "for-tag-vars01" ) << "{% for val in values %}{{ forloop.counter }}{% endfor %}" << dict << "123" << NoError;
628   QTest::newRow( "for-tag-vars02" ) << "{% for val in values %}{{ forloop.counter0 }}{% endfor %}" << dict << "012" << NoError;
629   QTest::newRow( "for-tag-vars03" ) << "{% for val in values %}{{ forloop.revcounter }}{% endfor %}" << dict << "321" << NoError;
630   QTest::newRow( "for-tag-vars04" ) << "{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}" << dict << "210" << NoError;
631   QTest::newRow( "for-tag-vars05" ) << "{% for val in values %}{% if forloop.first %}f{% else %}x{% endif %}{% endfor %}" << dict << "fxx" << NoError;
632   QTest::newRow( "for-tag-vars06" ) << "{% for val in values %}{% if forloop.last %}l{% else %}x{% endif %}{% endfor %}" << dict << "xxl" << NoError;
633
634   dict.clear();
635   QVariantHash hash;
636 //   hash.insert( "one", 1 );
637 //   hash.insert( "two", 2 );
638 //   dict.insert( "items", hash );
639 //   QTest::newRow( "for-tag-unpack-dict01" ) << "{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
640 //
641 //   QTest::newRow( "for-tag-unpack-dict03" ) << "{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
642 //   QTest::newRow( "for-tag-unpack-dict04" ) << "{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
643 //   QTest::newRow( "for-tag-unpack-dict05" ) << "{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
644 //   QTest::newRow( "for-tag-unpack-dict06" ) << "{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
645 //   QTest::newRow( "for-tag-unpack-dict07" ) << "{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
646 //   QTest::newRow( "for-tag-unpack-dict08" ) << "{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
647 //
648 //   // Ensure that a single loopvar doesn't truncate the list in val.
649 //   QTest::newRow( "for-tag-unpack-dict09" ) << "{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
650
651   dict.clear();
652   list.clear();
653   QVariantList innerList;
654   innerList << "one" << 1;
655   list.append( QVariant( innerList ) );
656   innerList.clear();
657   innerList << "two" << 2;
658   list.append( QVariant( innerList ) );
659   dict.insert( "items", list );
660   QTest::newRow( "for-tag-unpack01" ) << "{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
661
662   QTest::newRow( "for-tag-unpack03" ) << "{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
663   QTest::newRow( "for-tag-unpack04" ) << "{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
664   QTest::newRow( "for-tag-unpack05" ) << "{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
665   QTest::newRow( "for-tag-unpack06" ) << "{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
666   QTest::newRow( "for-tag-unpack07" ) << "{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
667   QTest::newRow( "for-tag-unpack08" ) << "{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
668
669   // Ensure that a single loopvar doesn't truncate the list in val.
670   QTest::newRow( "for-tag-unpack09" ) << "{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
671
672 // Otherwise, silently truncate if the length of loopvars differs to the length of each set of items.
673
674   dict.clear();
675   list.clear();
676   innerList.clear();
677   innerList << "one" << 1 << "carrot";
678   list.append( QVariant( innerList ) );
679   innerList.clear();
680   innerList << "two" << 2 << "orange";
681   list.append( QVariant( innerList ) );
682   dict.insert( "items", list );
683
684   QTest::newRow( "for-tag-unpack10" ) << "{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}" << dict << "one:1/two:2/" << NoError;
685
686   dict.clear();
687   list.clear();
688   innerList.clear();
689   innerList << "one" << 1;
690   list.append( QVariant( innerList ) );
691   innerList.clear();
692   innerList << "two" << 2;
693   list.append( QVariant( innerList ) );
694   dict.insert( "items", list );
695
696   QTest::newRow( "for-tag-unpack11" ) << "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}" << dict << "one:1,/two:2,/" << NoError;
697
698   dict.clear();
699   list.clear();
700   innerList.clear();
701   innerList << "one" << 1 << "carrot";
702   list.append( QVariant( innerList ) );
703   innerList.clear();
704   innerList << "two" << 2;
705   list.append( QVariant( innerList ) );
706   dict.insert( "items", list );
707
708   QTest::newRow( "for-tag-unpack12" ) << "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}" << dict << "one:1,carrot/two:2,/" << NoError;
709
710   dict.clear();
711   list.clear();
712   innerList.clear();
713   innerList << "one" << 1 << "carrot";
714   list.append( QVariant( innerList ) );
715   innerList.clear();
716   innerList << "two" << 2 << "cheese";
717   list.append( QVariant( innerList ) );
718
719   dict.insert( "items", list );
720
721   QTest::newRow( "for-tag-unpack13" ) << "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}" << dict << "one:1,carrot/two:2,cheese/" << NoError;
722
723 // Empty tag:
724
725   dict.clear();
726   dict.insert( "values", QVariantList() << 1 << 2 << 3 );
727   QTest::newRow( "for-tag-empty01" ) << "{% for val in values %}{{ val }}{% empty %}empty text{% endfor %}" << dict << "123" << NoError;
728
729   dict.clear();
730   dict.insert( "values", QVariantList() );
731   QTest::newRow( "for-tag-empty02" ) << "{% for val in values %}{{ val }}{% empty %}values array empty{% endfor %}" << dict << "values array empty" << NoError;
732
733   dict.clear();
734   QTest::newRow( "for-tag-empty03" ) << "{% for val in values %}{{ val }}{% empty %}values array not found{% endfor %}" << dict << "values array not found" << NoError;
735
736 }
737
738 void TestDefaultTags::testIfEqualTag_data()
739 {
740   QTest::addColumn<QString>( "input" );
741   QTest::addColumn<Dict>( "dict" );
742   QTest::addColumn<QString>( "output" );
743   QTest::addColumn<Grantlee::Error>( "error" );
744
745   Dict dict;
746
747   dict.insert( "a", 1 );
748   dict.insert( "b", 2 );
749
750   QTest::newRow( "ifequal01" ) << "{% ifequal a b %}yes{% endifequal %}" << dict << "" << NoError;
751   QTest::newRow( "ifequal03" ) << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
752
753   dict.clear();
754   dict.insert( "a", 1 );
755   dict.insert( "b", 1 );
756
757   QTest::newRow( "ifequal02" ) << "{% ifequal a b %}yes{% endifequal %}" << dict << "yes" << NoError;
758   QTest::newRow( "ifequal04" ) << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
759
760   dict.clear();
761   dict.insert( "a", "test" );
762
763   QTest::newRow( "ifequal05" ) << "{% ifequal a 'test' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
764
765   dict.clear();
766   dict.insert( "a", "no" );
767
768   QTest::newRow( "ifequal06" ) << "{% ifequal a 'test' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
769
770   dict.clear();
771   dict.insert( "a", "test" );
772
773   QTest::newRow( "ifequal07" ) << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
774
775   dict.clear();
776   dict.insert( "a", "no" );
777
778   QTest::newRow( "ifequal08" ) << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
779
780   dict.clear();
781
782   QTest::newRow( "ifequal09" ) << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
783
784   QTest::newRow( "ifequal10" ) << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
785
786
787   QTest::newRow( "ifequal-split01" ) << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
788
789   dict.insert( "a", "foo" );
790   QTest::newRow( "ifequal-split02" ) << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
791
792   dict.clear();
793   dict.insert( "a", "test man" );
794   QTest::newRow( "ifequal-split03" ) << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
795   QTest::newRow( "ifequal-split04" ) << "{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
796
797   dict.clear();
798   dict.insert( "a", "" );
799   QTest::newRow( "ifequal-split05" ) << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
800
801   dict.clear();
802   dict.insert( "a", "i \"love\" you" );
803   QTest::newRow( "ifequal-split06" ) << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
804
805   dict.clear();
806   dict.insert( "a", "i love you" );
807   QTest::newRow( "ifequal-split07" ) << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
808
809   dict.clear();
810   dict.insert( "a", "I'm happy" );
811   QTest::newRow( "ifequal-split08" ) << "{% ifequal a 'I\\'m happy' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
812
813   dict.clear();
814   dict.insert( "a", "slash\\man" );
815   QTest::newRow( "ifequal-split09" ) << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
816
817   dict.clear();
818   dict.insert( "a", "slashman" );
819   QTest::newRow( "ifequal-split10" ) << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
820 // NUMERIC RESOLUTION
821
822   dict.clear();
823   dict.insert( "x", "5" );
824
825   QTest::newRow( "ifequal-numeric01" ) << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "" << NoError;
826
827   dict.clear();
828   dict.insert( "x", 5 );
829   QTest::newRow( "ifequal-numeric02" ) << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "yes" << NoError;
830
831   dict.clear();
832   dict.insert( "x", 5.2 );
833   QTest::newRow( "ifequal-numeric03" ) << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "" << NoError;
834   QTest::newRow( "ifequal-numeric04" ) << "{% ifequal x 5.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
835
836   dict.clear();
837   dict.insert( "x", .2 );
838
839   QTest::newRow( "ifequal-numeric05" ) << "{% ifequal x 0.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
840   QTest::newRow( "ifequal-numeric06" ) << "{% ifequal x .2 %}yes{% endifequal %}" << dict << "yes" << NoError;
841
842   dict.clear();
843   dict.insert( "x", 2 );
844
845   QTest::newRow( "ifequal-numeric07" ) << "{% ifequal x 2. %}yes{% endifequal %}" << dict << "" << NoError;
846
847   dict.clear();
848   dict.insert( "x", 5 );
849   QTest::newRow( "ifequal-numeric08" ) << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict << "" << NoError;
850
851   dict.clear();
852   dict.insert( "x", "5" );
853   QTest::newRow( "ifequal-numeric09" ) << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict << "yes" << NoError;
854
855   dict.clear();
856   dict.insert( "x", -5 );
857   QTest::newRow( "ifequal-numeric10" ) << "{% ifequal x -5 %}yes{% endifequal %}" << dict << "yes" << NoError;
858
859   dict.clear();
860   dict.insert( "x", -5.2 );
861   QTest::newRow( "ifequal-numeric11" ) << "{% ifequal x -5.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
862
863   dict.clear();
864   dict.insert( "x", 5 );
865   QTest::newRow( "ifequal-numeric12" ) << "{% ifequal x +5 %}yes{% endifequal %}" << dict << "yes" << NoError;
866
867
868   // FILTER EXPRESSIONS AS ARGUMENTS
869
870   dict.clear();
871   dict.insert( "a", "a" );
872   QTest::newRow( "ifequal-filter01" ) << "{% ifequal a|upper \"A\" %}x{% endifequal %}" << dict << "x" << NoError;
873
874   QTest::newRow( "ifequal-filter02" ) << "{% ifequal \"A\" a|upper %}x{% endifequal %}" << dict << "x" << NoError;
875
876   dict.clear();
877   dict.insert( "a", "x" );
878   dict.insert( "b", "X" );
879
880   QTest::newRow( "ifequal-filter03" ) << "{% ifequal a|upper b|upper %}x{% endifequal %}" << dict << "x" << NoError;
881
882   dict.clear();
883   dict.insert( "x", "aaa" );
884
885   QTest::newRow( "ifequal-filter04" ) << "{% ifequal x|slice:\"1\" \"a\" %}x{% endifequal %}" << dict << "x" << NoError;
886
887   dict.clear();
888   dict.insert( "x", "aaa" );
889
890   QTest::newRow( "ifequal-filter05" ) << "{% ifequal x|slice:\"1\"|upper \"A\" %}x{% endifequal %}" << dict << "x" << NoError;
891
892 }
893
894 void TestDefaultTags::testIfNotEqualTag_data()
895 {
896   QTest::addColumn<QString>( "input" );
897   QTest::addColumn<Dict>( "dict" );
898   QTest::addColumn<QString>( "output" );
899   QTest::addColumn<Grantlee::Error>( "error" );
900
901   Dict dict;
902
903   dict.insert( "a", 1 );
904   dict.insert( "b", 2 );
905
906   QTest::newRow( "ifnotequal01" ) << "{% ifnotequal a b %}yes{% endifnotequal %}" << dict << "yes" << NoError;
907   QTest::newRow( "ifnotequal03" ) << "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}" << dict << "yes" << NoError;
908
909   dict.clear();
910   dict.insert( "a", 1 );
911   dict.insert( "b", 1 );
912
913   QTest::newRow( "ifnotequal02" ) << "{% ifnotequal a b %}yes{% endifnotequal %}" << dict << "" << NoError;
914   QTest::newRow( "ifnotequal04" ) << "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}" << dict << "no" << NoError;
915
916 }
917
918 void TestDefaultTags::testTemplateTagTag_data()
919 {
920   QTest::addColumn<QString>( "input" );
921   QTest::addColumn<Dict>( "dict" );
922   QTest::addColumn<QString>( "output" );
923   QTest::addColumn<Grantlee::Error>( "error" );
924
925   Dict dict;
926
927   QTest::newRow( "templatetag01" ) << "{% templatetag openblock %}" << dict << "{%" << NoError;
928   QTest::newRow( "templatetag02" ) << "{% templatetag closeblock %}" << dict << "%}" << NoError;
929   QTest::newRow( "templatetag03" ) << "{% templatetag openvariable %}" << dict << "{{" << NoError;
930   QTest::newRow( "templatetag04" ) << "{% templatetag closevariable %}" << dict << "}}" << NoError;
931   QTest::newRow( "templatetag05" ) << "{% templatetag %}" << dict << "" << TagSyntaxError;
932   QTest::newRow( "templatetag06" ) << "{% templatetag foo %}" << dict << "" << TagSyntaxError;
933   QTest::newRow( "templatetag07" ) << "{% templatetag openbrace %}" << dict << "{" << NoError;
934   QTest::newRow( "templatetag08" ) << "{% templatetag closebrace %}" << dict << "}" << NoError;
935   QTest::newRow( "templatetag09" ) << "{% templatetag openbrace %}{% templatetag openbrace %}" << dict << "{{" << NoError;
936   QTest::newRow( "templatetag10" ) << "{% templatetag closebrace %}{% templatetag closebrace %}" << dict << "}}" << NoError;
937   QTest::newRow( "templatetag11" ) << "{% templatetag opencomment %}" << dict << "{#" << NoError;
938   QTest::newRow( "templatetag12" ) << "{% templatetag closecomment %}" << dict << "#}" << NoError;
939
940 }
941
942 void TestDefaultTags::testWithTag_data()
943 {
944   QTest::addColumn<QString>( "input" );
945   QTest::addColumn<Dict>( "dict" );
946   QTest::addColumn<QString>( "output" );
947   QTest::addColumn<Grantlee::Error>( "error" );
948
949   Dict dict;
950
951   QVariantHash hash;
952   hash.insert( "key", 50 );
953   dict.insert( "dict", hash );
954   QTest::newRow( "with01" ) << "{% with dict.key as key %}{{ key }}{% endwith %}" << dict << "50" << NoError;
955   QTest::newRow( "with02" )
956   << "{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}"
957   << dict << "50-50-50" << NoError;
958   QTest::newRow( "with-error01" ) << "{% with dict.key xx key %}{{ key }}{% endwith %}" << dict << "" << TagSyntaxError;
959   QTest::newRow( "with-error02" ) << "{% with dict.key as %}{{ key }}{% endwith %}" << dict << "" << TagSyntaxError;
960 }
961
962 void TestDefaultTags::testCycleTag_data()
963 {
964   QTest::addColumn<QString>( "input" );
965   QTest::addColumn<Dict>( "dict" );
966   QTest::addColumn<QString>( "output" );
967   QTest::addColumn<Grantlee::Error>( "error" );
968
969   Dict dict;
970
971   QTest::newRow( "cycle01" ) << "{% cycle a %}" << dict << "" << TagSyntaxError;
972   QTest::newRow( "cycle02" ) << "{% cycle a,b,c as abc %}{% cycle abc %}" << dict << "ab" << NoError;
973   QTest::newRow( "cycle03" ) << "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}" << dict << "abc" << NoError;
974   QTest::newRow( "cycle04" ) << "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}" << dict << "abca" << NoError;
975   QTest::newRow( "cycle05" ) << "{% cycle a %}" << dict << "" << TagSyntaxError;
976   // TODO: This is the same as cycle01. Remove.
977   QTest::newRow( "cycle06" ) << "{% cycle a %}" << dict << "" << TagSyntaxError;
978   QTest::newRow( "cycle07" ) << "{% cycle a,b,c as foo %}{% cycle bar %}" << dict << "" << TagSyntaxError;
979   QTest::newRow( "cycle08" ) << "{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}" << dict << "abbbcc" << NoError;
980
981   dict.insert( "test", QVariantList() << 0 << 1 << 2 << 3 << 4 );
982   QTest::newRow( "cycle09" ) << "{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," << NoError;
983
984   dict.clear();
985   QTest::newRow( "cycle10" ) << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}" << dict << "ab" << NoError;
986   QTest::newRow( "cycle11" ) << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}" << dict << "abc" << NoError;
987   QTest::newRow( "cycle12" ) << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}" << dict << "abca" << NoError;
988
989   dict.insert( "test", QVariantList() << 0 << 1 << 2 << 3 << 4 );
990   QTest::newRow( "cycle13" ) << "{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," << NoError;
991
992   dict.clear();
993   dict.insert( "one", "1" );
994   dict.insert( "two", "2" );
995   QTest::newRow( "cycle14" ) << "{% cycle one two as foo %}{% cycle foo %}" << dict << "12" << NoError;
996
997   dict.clear();
998   dict.insert( "test", QVariantList() << 0 << 1 << 2 << 3 << 4 );
999   dict.insert( "aye", "a" );
1000   dict.insert( "bee", "b" );
1001   QTest::newRow( "cycle15" ) << "{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," << NoError;
1002
1003   dict.clear();
1004   dict.insert( "one", "A" );
1005   dict.insert( "two", "2" );
1006   QTest::newRow( "cycle16" ) << "{% cycle one|lower two as foo %}{% cycle foo %}" << dict << "a2" << NoError;
1007 }
1008
1009 void TestDefaultTags::testWidthRatioTag_data()
1010 {
1011   QTest::addColumn<QString>( "input" );
1012   QTest::addColumn<Dict>( "dict" );
1013   QTest::addColumn<QString>( "output" );
1014   QTest::addColumn<Grantlee::Error>( "error" );
1015
1016   Dict dict;
1017
1018   dict.insert( "a", 50 );
1019   dict.insert( "b", 100 );
1020   QTest::newRow( "widthratio01" ) << "{% widthratio a b 0 %}" << dict << "0" << NoError;
1021
1022   dict.clear();
1023   dict.insert( "a", 0 );
1024   dict.insert( "b", 0 );
1025   QTest::newRow( "widthratio02" ) << "{% widthratio a b 0 %}" << dict << "" << NoError;
1026
1027   dict.clear();
1028   dict.insert( "a", 0 );
1029   dict.insert( "b", 100 );
1030   QTest::newRow( "widthratio03" ) << "{% widthratio a b 100 %}" << dict << "0" << NoError;
1031
1032   dict.clear();
1033   dict.insert( "a", 50 );
1034   dict.insert( "b", 100 );
1035   QTest::newRow( "widthratio04" ) << "{% widthratio a b 100 %}" << dict << "50" << NoError;
1036
1037   dict.clear();
1038   dict.insert( "a", 100 );
1039   dict.insert( "b", 100 );
1040   QTest::newRow( "widthratio05" ) << "{% widthratio a b 100 %}" << dict << "100" << NoError;
1041
1042   dict.clear();
1043   dict.insert( "a", 50 );
1044   dict.insert( "b", 80 );
1045   QTest::newRow( "widthratio06" ) << "{% widthratio a b 100 %}" << dict << "63" << NoError;
1046
1047   dict.clear();
1048   dict.insert( "a", 50 );
1049   dict.insert( "b", 70 );
1050   QTest::newRow( "widthratio07" ) << "{% widthratio a b 100 %}" << dict << "71" << NoError;
1051
1052   dict.clear();
1053 // Raise exception if we don't have 3 args, last one an integer
1054   QTest::newRow( "widthratio08" ) << "{% widthratio %}" << dict << "" << TagSyntaxError;
1055
1056   dict.clear();
1057   QTest::newRow( "widthratio09" ) << "{% widthratio a b %}" << dict << "" << TagSyntaxError;
1058
1059   dict.clear();
1060   dict.insert( "a", 50 );
1061   dict.insert( "b", 100 );
1062   QTest::newRow( "widthratio10" ) << "{% widthratio a b 100.0 %}" << dict << "50" << NoError;
1063
1064   dict.clear();
1065   dict.insert( "a", 50 );
1066   dict.insert( "b", 100 );
1067   dict.insert( "c", 100 );
1068   QTest::newRow( "widthratio11" ) << "{% widthratio a b c %}" << dict << "50" << NoError;
1069
1070 }
1071
1072
1073 void TestDefaultTags::testFilterTag_data()
1074 {
1075   QTest::addColumn<QString>( "input" );
1076   QTest::addColumn<Dict>( "dict" );
1077   QTest::addColumn<QString>( "output" );
1078   QTest::addColumn<Grantlee::Error>( "error" );
1079
1080   Dict dict;
1081
1082   QTest::newRow( "filter01" ) << "{% filter upper %}{% endfilter %}" << dict << "" << NoError;
1083   QTest::newRow( "filter02" ) << "{% filter upper %}django{% endfilter %}" << dict << "DJANGO" << NoError;
1084   QTest::newRow( "filter03" ) << "{% filter upper|lower %}django{% endfilter %}" << dict << "django" << NoError;
1085
1086   dict.insert( "remove", "spam" );
1087   QTest::newRow( "filter04" ) << "{% filter cut:remove %}djangospam{% endfilter %}" << dict << "django" << NoError;
1088
1089 }
1090
1091 void TestDefaultTags::testNowTag_data()
1092 {
1093   QTest::addColumn<QString>( "input" );
1094   QTest::addColumn<Dict>( "dict" );
1095   QTest::addColumn<QString>( "output" );
1096   QTest::addColumn<Grantlee::Error>( "error" );
1097
1098   Dict dict;
1099
1100   QDate today = QDateTime::currentDateTime().date();
1101
1102   QTest::newRow( "now01" ) << "{% now \"d M yyyy\"%}" << dict << ( QString::number( today.day() ) + ' ' +  QString::number( today.month() ) + ' ' + QString::number( today.year() ) ) << NoError;
1103
1104   QTest::newRow( "now02" ) << "{% now \"d \"M\" yyyy\"%}" << dict << "" << TagSyntaxError;
1105
1106
1107 }
1108
1109 void TestDefaultTags::testSpacelessTag_data()
1110 {
1111   QTest::addColumn<QString>( "input" );
1112   QTest::addColumn<Dict>( "dict" );
1113   QTest::addColumn<QString>( "output" );
1114   QTest::addColumn<Grantlee::Error>( "error" );
1115
1116   Dict dict;
1117
1118   QTest::newRow( "spaceless01" ) << "{% spaceless %} <b>    <i> text </i>    </b> {% endspaceless %}" << dict << "<b><i> text </i></b>" << NoError;
1119   QTest::newRow( "spaceless02" ) << "{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}" << dict << "<b><i> text </i></b>" << NoError;
1120   QTest::newRow( "spaceless03" ) << "{% spaceless %}<b><i>text</i></b>{% endspaceless %}" << dict << "<b><i>text</i></b>" << NoError;
1121
1122 }
1123
1124 void TestDefaultTags::testRegroupTag_data()
1125 {
1126   QTest::addColumn<QString>( "input" );
1127   QTest::addColumn<Dict>( "dict" );
1128   QTest::addColumn<QString>( "output" );
1129   QTest::addColumn<Grantlee::Error>( "error" );
1130
1131   Dict dict;
1132
1133   QVariantList list;
1134   QVariantHash hash;
1135
1136   hash.insert( "foo", "c" );
1137   hash.insert( "bar", 1 );
1138   list.append( hash );
1139
1140   hash.clear();
1141   hash.insert( "foo", "d" );
1142   hash.insert( "bar", 1 );
1143   list.append( hash );
1144
1145   hash.clear();
1146   hash.insert( "foo", "a" );
1147   hash.insert( "bar", 2 );
1148   list.append( hash );
1149
1150   hash.clear();
1151   hash.insert( "foo", "b" );
1152   hash.insert( "bar", 2 );
1153   list.append( hash );
1154
1155   hash.clear();
1156   hash.insert( "foo", "x" );
1157   hash.insert( "bar", 3 );
1158   list.append( hash );
1159
1160   dict.insert( "data", list );
1161
1162   QTest::newRow( "regroup01" ) << "{% regroup data by bar as grouped %}"
1163   "{% for group in grouped %}"
1164   "{{ group.grouper }}:"
1165   "{% for item in group.list %}"
1166   "{{ item.foo }}"
1167   "{% endfor %},"
1168   "{% endfor %}" << dict << "1:cd,2:ab,3:x," << NoError;
1169
1170   dict.clear();
1171   hash.clear();
1172   list.clear();
1173
1174   hash.insert( "foo", "a" );
1175   hash.insert( "bar", 2 );
1176   list.append( hash );
1177
1178   hash.clear();
1179   hash.insert( "foo", "b" );
1180   hash.insert( "bar", 2 );
1181   list.append( hash );
1182
1183   hash.clear();
1184   hash.insert( "foo", "x" );
1185   hash.insert( "bar", 3 );
1186   list.append( hash );
1187
1188   hash.clear();
1189   hash.insert( "foo", "c" );
1190   hash.insert( "bar", 1 );
1191   list.append( hash );
1192
1193   hash.clear();
1194   hash.insert( "foo", "d" );
1195   hash.insert( "bar", 1 );
1196   list.append( hash );
1197
1198
1199   dict.insert( "data", list );
1200
1201   // Data is output in the order it is sent in.
1202
1203   QTest::newRow( "regroup02" ) << "{% regroup data by bar as grouped %}"
1204   "{% for group in grouped %}"
1205   "{{ group.grouper }}:"
1206   "{% for item in group.list %}"
1207   "{{ item.foo }}"
1208   "{% endfor %},"
1209   "{% endfor %}" << dict << "2:ab,3:x,1:cd," << NoError;
1210
1211 }
1212
1213 void TestDefaultTags::testIfChangedTag_data()
1214 {
1215   QTest::addColumn<QString>( "input" );
1216   QTest::addColumn<Dict>( "dict" );
1217   QTest::addColumn<QString>( "output" );
1218   QTest::addColumn<Grantlee::Error>( "error" );
1219
1220   Dict dict;
1221
1222   dict.insert( "num", QVariantList() << 1 << 2 << 3 );
1223   QTest::newRow( "ifchanged01" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "123" << NoError;
1224
1225   dict.clear();
1226   dict.insert( "num", QVariantList() << 1 << 1 << 3 );
1227   QTest::newRow( "ifchanged02" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "13" << NoError;
1228
1229   dict.clear();
1230   dict.insert( "num", QVariantList() << 1 << 1 << 1 );
1231   QTest::newRow( "ifchanged03" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "1" << NoError;
1232
1233   dict.clear();
1234   dict.insert( "num", QVariantList() << 1 << 2 << 3 );
1235   dict.insert( "numx", QVariantList() << 2 << 2 << 2 );
1236   QTest::newRow( "ifchanged04" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "122232" << NoError;
1237
1238   dict.clear();
1239   dict.insert( "num", QVariantList() << 1 << 1 << 1 );
1240   dict.insert( "numx", QVariantList() << 1 << 2 << 3 );
1241   QTest::newRow( "ifchanged05" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "1123123123" << NoError;
1242
1243   dict.clear();
1244   dict.insert( "num", QVariantList() << 1 << 1 << 1 );
1245   dict.insert( "numx", QVariantList() << 2 << 2 << 2 );
1246   QTest::newRow( "ifchanged06" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "1222" << NoError;
1247
1248   dict.clear();
1249   dict.insert( "num", QVariantList() << 1 << 1 << 1 );
1250   dict.insert( "numx", QVariantList() << 2 << 2 << 2 );
1251   dict.insert( "numy", QVariantList() << 3 << 3 << 3 );
1252   QTest::newRow( "ifchanged07" ) << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}" << dict << "1233323332333" << NoError;
1253
1254   // datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1, 'c'), (1, 'd'), (1, 'd'), (0, 'e')]]}
1255   dict.clear();
1256   QVariantList list;
1257   QVariantList innerList;
1258   QVariantList tuple;
1259   tuple << 1 << "a";
1260   innerList.append( QVariant( tuple ) );
1261   tuple.clear();
1262   tuple << 1 << "a";
1263   innerList.append( QVariant( tuple ) );
1264   tuple.clear();
1265   tuple << 0 << "b";
1266   innerList.append( QVariant( tuple ) );
1267   tuple.clear();
1268   tuple << 1 << "c";
1269   innerList.append( QVariant( tuple ) );
1270   tuple.clear();
1271   list.append( QVariant( innerList ) );
1272   innerList.clear();
1273
1274   tuple << 0 << "a";
1275   innerList.append( QVariant( tuple ) );
1276   tuple.clear();
1277   tuple << 1 << "c";
1278   innerList.append( QVariant( tuple ) );
1279   tuple.clear();
1280   tuple << 1 << "d";
1281   innerList.append( QVariant( tuple ) );
1282   tuple.clear();
1283   tuple << 1 << "d";
1284   innerList.append( QVariant( tuple ) );
1285   tuple.clear();
1286   tuple << 0 << "e";
1287   innerList.append( QVariant( tuple ) );
1288   tuple.clear();
1289   list.append( QVariant( innerList ) );
1290   innerList.clear();
1291
1292   dict.insert( "datalist", list );
1293   QTest::newRow( "ifchanged08" ) << "{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged %}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}" << dict << "accd" << NoError;
1294
1295 // Test one parameter given to ifchanged.
1296   dict.clear();
1297   dict.insert( "num", QVariantList() << 1 << 2 << 3 );
1298   QTest::newRow( "ifchanged-param01" ) << "{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}" << dict << "..1..2..3" << NoError;
1299
1300   dict.clear();
1301   dict.insert( "num", QVariantList() << 1 << 2 << 3 );
1302   dict.insert( "numx", QVariantList() << 5 << 6 << 7 );
1303   QTest::newRow( "ifchanged-param02" ) << "{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}" << dict << "..567..567..567" << NoError;
1304
1305 // Test multiple parameters to ifchanged.
1306
1307   dict.clear();
1308   dict.insert( "num", QVariantList() << 1 << 1 << 2 );
1309   dict.insert( "numx", QVariantList() << 5 << 6 << 6 );
1310   QTest::newRow( "ifchanged-param03" ) << "{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "156156256" << NoError;
1311
1312 // Test a date+hour like construct, where the hour of the last day
1313 // is the same but the date had changed, so print the hour anyway.
1314
1315   dict.clear();
1316   QVariantList days;
1317   QVariantHash hash;
1318   hash.insert( "day", 1 );
1319   hash.insert( "hours", QVariantList() << 1 << 2 << 3 );
1320   days << hash;
1321   hash.clear();
1322   hash.insert( "day", 2 );
1323   hash.insert( "hours", QVariantList() << 3 );
1324   days << hash;
1325   dict.insert( "days", days );
1326   QTest::newRow( "ifchanged-param04" ) << "{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "112323" << NoError;
1327
1328
1329 // Logically the same as above, just written with explicit
1330 // ifchanged for the day.
1331
1332   QTest::newRow( "ifchanged-param05" ) << "{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "112323" << NoError;
1333
1334 // Test the else clause of ifchanged.
1335   dict.clear();
1336   dict.insert( "ids", QVariantList() << 1 << 1 << 2 << 2 << 2 << 3 );
1337   QTest::newRow( "ifchanged-else01" ) << "{% for id in ids %}{{ id }}{% ifchanged id %}-first{% else %}-other{% endifchanged %},{% endfor %}" << dict << "1-first,1-other,2-first,2-other,2-other,3-first," << NoError;
1338   QTest::newRow( "ifchanged-else02" ) << "{% for id in ids %}{{ id }}-{% ifchanged id %}{% cycle red,blue %}{% else %}grey{% endifchanged %},{% endfor %}" << dict << "1-red,1-grey,2-blue,2-grey,2-grey,3-red," << NoError;
1339   QTest::newRow( "ifchanged-else03" ) << "{% for id in ids %}{{ id }}{% ifchanged id %}-{% cycle red,blue %}{% else %}{% endifchanged %},{% endfor %}" << dict << "1-red,1,2-blue,2,2,3-red," << NoError;
1340
1341   dict.clear();
1342   dict.insert( "ids", QVariantList() << 1 << 1 << 2 << 2 << 2 << 3 << 4 );
1343   QTest::newRow( "ifchanged-else04" ) << "{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% endifchanged %}{{ forloop.counter }}{% endfor %}" << dict << "***1*1...2***2*3...4...5***3*6***4*7" << NoError;
1344
1345 }
1346
1347
1348 void TestDefaultTags::testAutoescapeTag_data()
1349 {
1350   QTest::addColumn<QString>( "input" );
1351   QTest::addColumn<Dict>( "dict" );
1352   QTest::addColumn<QString>( "output" );
1353   QTest::addColumn<Grantlee::Error>( "error" );
1354
1355   Dict dict;
1356
1357   QTest::newRow( "autoescape-tag01" ) << "{% autoescape off %}hello{% endautoescape %}" << dict << "hello" << NoError;
1358
1359   dict.insert( "first", "<b>hello</b>" );
1360   QTest::newRow( "autoescape-tag02" ) << "{% autoescape off %}{{ first }}{% endautoescape %}" << dict << "<b>hello</b>" << NoError;
1361   QTest::newRow( "autoescape-tag03" ) << "{% autoescape on %}{{ first }}{% endautoescape %}" << dict << "&lt;b&gt;hello&lt;/b&gt;" << NoError;
1362   // Autoescape disabling and enabling nest in a predictable way.
1363   dict.insert( "first", "<a>" );
1364   QTest::newRow( "autoescape-tag04" ) << "{% autoescape off %}{{ first }} {% autoescape  on%}{{ first }}{% endautoescape %}{% endautoescape %}" << dict << "<a> &lt;a&gt;" << NoError;
1365
1366   dict.insert( "first", "<b>first</b>" );
1367   QTest::newRow( "autoescape-tag05" ) << "{% autoescape on %}{{ first }}{% endautoescape %}" << dict << "&lt;b&gt;first&lt;/b&gt;" << NoError;
1368   // Strings (ASCII or unicode) already marked as "safe" are not
1369   // auto-escaped
1370   SafeString safeString( "<b>first</b>" );
1371   QVariant safeStringVar = QVariant::fromValue<SafeString>( markSafe( safeString ) );
1372   dict.insert( "first", safeStringVar );
1373
1374   QTest::newRow( "autoescape-tag06" ) << "{{ first }}" << dict << "<b>first</b>" << NoError;
1375   QTest::newRow( "autoescape-tag07" ) << "{% autoescape on %}{{ first }}{% endautoescape %}" << dict << "<b>first</b>" << NoError;
1376
1377   // Literal string arguments to filters, if used in the result, are
1378   // safe.
1379   dict.clear();
1380   dict.insert( "var", QVariant() );
1381   QTest::newRow( "autoescape-tag08" ) << "{% autoescape on %}{{ var|default_if_none:\"endquote\\\" hah\" }}{% endautoescape %}" << dict << "endquote\" hah" << NoError;
1382   // Objects which return safe strings as their __unicode__ method
1383   // won't get double-escaped.
1384 //   'autoescape-tag09': (r'{{ unsafe }}', {'unsafe': filters.UnsafeClass()}, 'you &amp; me'),
1385 //   'autoescape-tag10': (r'{{ safe }}', {'safe': filters.SafeClass()}, 'you &gt; me'),
1386   // The "safe" and "escape" filters cannot work due to internal
1387   // implementation details (fortunately, the (no)autoescape block
1388   // tags can be used in those cases)
1389   dict.clear();
1390   dict.insert( "first", "<a>" );
1391   QTest::newRow( "autoescape-filtertag01" ) << "{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}" << dict << "" << TagSyntaxError;
1392 }
1393
1394
1395 void TestDefaultTags::testMediaFinderTag_data()
1396 {
1397   QTest::addColumn<QString>( "input" );
1398   QTest::addColumn<Dict>( "dict" );
1399   QTest::addColumn<QString>( "output" );
1400   QTest::addColumn<Grantlee::Error>( "error" );
1401
1402   Dict dict;
1403   QTest::newRow( "media_finder-tag01" ) << "{% media_finder \"existing_image.png\" %}" << dict << "file:///path/to/existing_image.png" << NoError;
1404   QTest::newRow( "media_finder-tag02" ) << "{% media_finder \"does_not_exist.png\" %}" << dict << "" << NoError;
1405   QTest::newRow( "media_finder-tag03" ) << "{% media_finder \"existing_image.png\" \"does_not_exist.png\" %}" << dict << "file:///path/to/existing_image.png" << NoError;
1406   QTest::newRow( "media_finder-tag04" ) << "{% media_finder \"existing_image.png\" \"does_not_exist.png\" %}" << dict << "file:///path/to/existing_image.png" << NoError;
1407
1408   dict.insert( "existing_img", "existing_image.png" );
1409   dict.insert( "nonexisting_img", "does_not_exist.png" );
1410
1411   QTest::newRow( "media_finder-tag05" ) << "{% media_finder %}" << dict << "" << TagSyntaxError;
1412   QTest::newRow( "media_finder-tag05" ) << "{% media_finder existing_img %}" << dict << "file:///path/to/existing_image.png" << NoError;
1413   QTest::newRow( "media_finder-tag06" ) << "{% media_finder nonexisting_img %}" << dict << "" << NoError;
1414   QTest::newRow( "media_finder-tag07" ) << "{% media_finder \"does_not_exist.png\" existing_img %}" << dict << "file:///path/to/existing_image.png" << NoError;
1415   QTest::newRow( "media_finder-tag08" ) << "{% media_finder nonexisting_img existing_img %}" << dict << "file:///path/to/existing_image.png" << NoError;
1416   QTest::newRow( "media_finder-tag09" ) << "{% media_finder \"existing_image.png\" \"another_existing_image.png\" %}" << dict << "file:///path/to/existing_image.png" << NoError;
1417   QTest::newRow( "media_finder-tag10" ) << "{% media_finder \"another_existing_image.png\" \"existing_image.png\" %}" << dict << "file:///path/to/another_existing_image.png" << NoError;
1418 }
1419
1420 void TestDefaultTags::testRangeTag_data()
1421 {
1422   QTest::addColumn<QString>( "input" );
1423   QTest::addColumn<Dict>( "dict" );
1424   QTest::addColumn<QString>( "output" );
1425   QTest::addColumn<Grantlee::Error>( "error" );
1426
1427   Dict dict;
1428
1429   QTest::newRow( "range-tag01" ) << "{% range 5 as i %}{{ i }};{% endrange %}" << dict << "0;1;2;3;4;" << NoError;
1430   QTest::newRow( "range-tag02" ) << "{% range 1 6 as i %}{{ i }};{% endrange %}" << dict << "1;2;3;4;5;" << NoError;
1431   QTest::newRow( "range-tag03" ) << "{% range 5 26 5 as i %}{{ i }};{% endrange %}" << dict << "5;10;15;20;25;" << NoError;
1432
1433   QVariantList list;
1434   list << 10 << 15 << 2;
1435   dict.insert( "values", list );
1436
1437   QTest::newRow( "range-tag04" ) << "{% range values.0 values.1 values.2 as i %}{{ i }};{% endrange %}" << dict << "10;12;14;" << NoError;
1438
1439   QTest::newRow( "range-tag05" ) << "{% range 5 %}Foo;{% endrange %}" << dict << "Foo;Foo;Foo;Foo;Foo;" << NoError;
1440 }
1441
1442 void TestDefaultTags::testUrlTypes_data()
1443 {
1444   QTest::addColumn<QString>( "input" );
1445   QTest::addColumn<Dict>( "dict" );
1446   QTest::addColumn<QPair<QString, QString> >( "output" );
1447
1448   Dict dict;
1449   QTest::newRow( "url-types01" ) << "{% media_finder \"existing_image.png\" %}" << dict
1450                                  << qMakePair( QString( "file:///path/to/" ), QString( "existing_image.png" ) );
1451
1452   QTest::newRow( "url-types02" ) << "{% media_finder \"does_not_exist.png\" %}" << dict
1453                                  << qMakePair( QString(), QString() );
1454
1455   dict.insert( "existing_img", "existing_image.png" );
1456   dict.insert( "nonexisting_img", "does_not_exist.png" );
1457
1458   QTest::newRow( "url-types03" ) << "{% media_finder existing_img %}" << dict
1459                                  << qMakePair( QString( "file:///path/to/" ), QString( "existing_image.png" ) );
1460
1461
1462   QTest::newRow( "url-types04" ) << "{% media_finder nonexisting_img %}" << dict
1463                                  << qMakePair( QString(), QString() );
1464 }
1465
1466 void TestDefaultTags::testUrlTypes()
1467 {
1468   QFETCH(QString, input);
1469   QFETCH(Dict, dict);
1470   QFETCH(StringPair, output);
1471
1472   Template t = m_engine->newTemplate( input, QTest::currentDataTag() );
1473   QVERIFY( t->error() == NoError );
1474   Context c(dict);
1475   QString result = t->render( &c );
1476   QVERIFY( t->error() == NoError );
1477   QVERIFY( result == output.first + output.second );
1478
1479   c.setUrlType( Context::RelativeUrls );
1480   result = t->render( &c );
1481   QVERIFY( t->error() == NoError );
1482   QVERIFY( result == output.second );
1483 }
1484
1485 void TestDefaultTags::testRelativePaths_data()
1486 {
1487   QTest::addColumn<QString>( "input" );
1488   QTest::addColumn<Dict>( "dict" );
1489   QTest::addColumn<QString>( "output" );
1490
1491   Dict dict;
1492   QTest::newRow( "relativepaths01" ) << "{% media_finder \"existing_image.png\" %}" << dict << "existing_image.png";
1493
1494   QTest::newRow( "relativepaths02" ) << "{% media_finder \"does_not_exist.png\" %}" << dict << QString();
1495
1496   dict.insert( "existing_img", "existing_image.png" );
1497   dict.insert( "nonexisting_img", "does_not_exist.png" );
1498
1499   QTest::newRow( "relativepaths03" ) << "{% media_finder existing_img %}" << dict << "existing_image.png";
1500
1501
1502   QTest::newRow( "relativepaths04" ) << "{% media_finder nonexisting_img %}" << dict << QString();
1503 }
1504
1505 void TestDefaultTags::testRelativePaths()
1506 {
1507   QFETCH(QString, input);
1508   QFETCH(Dict, dict);
1509   QFETCH(QString, output);
1510
1511   Template t = m_engine->newTemplate( input, QTest::currentDataTag() );
1512   QVERIFY( t->error() == NoError );
1513   Context c(dict);
1514   QString result = t->render( &c );
1515   QVERIFY( t->error() == NoError );
1516   if ( !output.isEmpty() )
1517     QVERIFY( result == "file:///path/to/" + output );
1518   else
1519     QVERIFY( result.isEmpty() );
1520
1521   c.setUrlType( Context::RelativeUrls );
1522   QString relativePath = "relative/path";
1523   c.setRelativeMediaPath( relativePath );
1524   result = t->render( &c );
1525   QVERIFY( t->error() == NoError );
1526   if ( !output.isEmpty() )
1527     QVERIFY( result == relativePath + QLatin1Char( '/' ) + output );
1528   else
1529     QVERIFY( result.isEmpty() );
1530 }
1531
1532
1533
1534 QTEST_MAIN( TestDefaultTags )
1535 #include "testdefaulttags.moc"
1536
1537 #endif
1538