Implement ifchanged tag.
[grantlee:grantlee.git] / tests / testdefaulttags.cpp
1 /*
2     Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
3 */
4
5 #ifndef DEFAULTTAGSTEST_H
6 #define DEFAULTTAGSTEST_H
7
8 #include <QtTest>
9 #include <QtCore>
10 #include <QObject>
11
12 #include "template.h"
13 #include "context.h"
14
15 #include "grantlee.h"
16
17 typedef QHash<QString, QVariant> Dict;
18
19 Q_DECLARE_METATYPE(Dict)
20 Q_DECLARE_METATYPE(Grantlee::Error)
21
22 using namespace Grantlee;
23
24 class TestDefaultTags : public QObject
25 {
26   Q_OBJECT
27
28 private slots:
29   void initTestCase();
30
31   void testCommentTag_data();
32   void testCommentTag() { doTest(); }
33
34   void testFirstOfTag_data();
35   void testFirstOfTag() {  doTest(); }
36
37   void testIfTag_data();
38   void testIfTag() {  doTest();  }
39
40   void testForTag_data();
41   void testForTag() {  doTest();  }
42
43   void testIfEqualTag_data();
44   void testIfEqualTag() {  doTest();  }
45
46   void testIfNotEqualTag_data();
47   void testIfNotEqualTag() {  doTest();  }
48
49   void testTemplateTagTag_data();
50   void testTemplateTagTag() {  doTest();  }
51
52   void testWithTag_data();
53   void testWithTag() {  doTest();  }
54
55   void testCycleTag_data();
56   void testCycleTag() {  /* doTest(); */ }
57
58   void testWidthRatioTag_data();
59   void testWidthRatioTag() {  doTest();  }
60
61   void testFilterTag_data();
62   void testFilterTag() {  doTest();  }
63
64   void testNowTag_data();
65   void testNowTag() {  doTest();  }
66
67   void testSpacelessTag_data();
68   void testSpacelessTag() {  doTest();  }
69
70   void testRegroupTag_data();
71   void testRegroupTag() {  doTest();  }
72
73   void testIfChangedTag_data();
74   void testIfChangedTag() {  doTest();  }
75
76 private:
77
78   void doTest();
79
80   TemplateLoader *m_tl;
81
82 };
83
84 void TestDefaultTags::initTestCase()
85 {
86   m_tl = TemplateLoader::instance();
87
88   m_tl->setPluginDirs(QStringList() << "/home/kde-devel/kde/lib/");
89
90 }
91
92 void TestDefaultTags::doTest()
93 {
94   QFETCH(QString, input);
95   QFETCH(Dict, dict);
96   QFETCH(QString, output);
97   QFETCH(Grantlee::Error, error);
98
99   Template* t = m_tl->getTemplate();
100
101   QSignalSpy spy(t, SIGNAL(error(int, const QString &)));
102   t->setContent(input);
103
104   if (spy.count() > 0)
105   {
106     QVariantList l = spy.takeFirst();
107     QCOMPARE(l.at(0).toInt(), (int)error );
108     return;
109   }
110
111   Context context(dict);
112
113   QString result = t->render(&context);
114
115   if (spy.count() > 0)
116   {
117     QVariantList l = spy.takeFirst();
118     QCOMPARE(l.at(0).toInt(), (int)error );
119     QCOMPARE(result, QString());
120     return;
121   }
122
123   // Didn't catch any errors, so make sure I didn't expect any.
124   QCOMPARE(NoError, error);
125
126   QCOMPARE(result, output);
127 }
128
129 void TestDefaultTags::testCommentTag_data()
130 {
131   QTest::addColumn<QString>("input");
132   QTest::addColumn<Dict>("dict");
133   QTest::addColumn<QString>("output");
134   QTest::addColumn<Grantlee::Error>("error");
135
136   Dict dict;
137
138   QTest::newRow("comment-tag01") << "{% comment %}this is hidden{% endcomment %}hello" << dict << "hello" << NoError;
139
140   QTest::newRow("comment-tag02") << "{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}" << dict << "hello" << NoError;
141   // Comment tag can contain invalid stuff.
142   QTest::newRow("comment-tag03") << "foo{% comment %} {% if %} {% endcomment %}" << dict << "foo" << NoError;
143   QTest::newRow("comment-tag04") << "foo{% comment %} {% endblock %} {% endcomment %}" << dict << "foo" << NoError;
144   QTest::newRow("comment-tag05") << "foo{% comment %} {% somerandomtag %} {% endcomment %}" << dict << "foo" << NoError;
145 }
146
147 void TestDefaultTags::testFirstOfTag_data()
148 {
149   QTest::addColumn<QString>("input");
150   QTest::addColumn<Dict>("dict");
151   QTest::addColumn<QString>("output");
152   QTest::addColumn<Grantlee::Error>("error");
153
154   Dict dict;
155   dict.insert("a", 0);
156   dict.insert("b", 0);
157   dict.insert("c", 0);
158   QTest::newRow("firstof01") << "{% firstof a b c %}" << dict << "" << NoError;
159
160   dict.clear();
161   dict.insert("a", 1);
162   dict.insert("b", 0);
163   dict.insert("c", 0);
164   QTest::newRow("firstof02") << "{% firstof a b c %}" << dict << "1" << NoError;
165
166   dict.clear();
167   dict.insert("a", 0);
168   dict.insert("b", 2);
169   dict.insert("c", 0);
170   QTest::newRow("firstof03") << "{% firstof a b c %}" << dict << "2" << NoError;
171
172   dict.clear();
173   dict.insert("a", 0);
174   dict.insert("b", 0);
175   dict.insert("c", 3);
176   QTest::newRow("firstof04") << "{% firstof a b c %}" << dict << "3" << NoError;
177
178   dict.clear();
179   dict.insert("a", 1);
180   dict.insert("b", 2);
181   dict.insert("c", 3);
182   QTest::newRow("firstof05") << "{% firstof a b c %}" << dict << "1" << NoError;
183
184   dict.clear();
185   dict.insert("b", 0);
186   dict.insert("c", 3);
187   QTest::newRow("firstof06") << "{% firstof a b c %}" << dict << "3" << NoError;
188
189   dict.clear();
190   dict.insert("a", 0);
191   QTest::newRow("firstof07") << "{% firstof a b \"c\" %}" << dict << "c" << NoError;
192
193   dict.clear();
194   dict.insert("a", 0);
195   dict.insert("b", 0);
196   QTest::newRow("firstof08") << "{% firstof a b \"c and d\" %}" << dict << "c and d" << NoError;
197   QTest::newRow("firstof09") << "{% firstof %}" << dict << "a" << TagSyntaxError;
198
199 }
200
201
202 void TestDefaultTags::testIfTag_data()
203 {
204   QTest::addColumn<QString>("input");
205   QTest::addColumn<Dict>("dict");
206   QTest::addColumn<QString>("output");
207   QTest::addColumn<Grantlee::Error>("error");
208
209   Dict dict;
210
211   dict.insert("foo", true);
212
213   QTest::newRow("if-tag01") << "{% if foo %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
214
215   dict.clear();
216   dict.insert("foo", false);
217   QTest::newRow("if-tag02") << "{% if foo %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
218
219   dict.clear();
220   QTest::newRow("if-tag03") << "{% if foo %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
221
222   // AND
223
224   dict.clear();
225   dict.insert("foo", true);
226   dict.insert("bar", true);
227   QTest::newRow("if-tag-and01") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
228
229   dict.clear();
230   dict.insert("foo", true);
231   dict.insert("bar", false);
232   QTest::newRow("if-tag-and02") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
233
234   dict.clear();
235   dict.insert("foo", false);
236   dict.insert("bar", true);
237   QTest::newRow("if-tag-and03") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
238
239   dict.clear();
240   dict.insert("foo", false);
241   dict.insert("bar", false);
242   QTest::newRow("if-tag-and04") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
243
244   dict.clear();
245   dict.insert("foo", false);
246   QTest::newRow("if-tag-and05") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
247
248   dict.clear();
249   dict.insert("bar", false);
250   QTest::newRow("if-tag-and06") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
251
252   dict.clear();
253   dict.insert("foo", true);
254   QTest::newRow("if-tag-and07") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
255
256   dict.clear();
257   dict.insert("bar", true);
258   QTest::newRow("if-tag-and08") << "{% if foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
259
260   // OR
261
262   dict.clear();
263   dict.insert("foo", true);
264   dict.insert("bar", true);
265   QTest::newRow("if-tag-or01") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
266
267   dict.clear();
268   dict.insert("foo", true);
269   dict.insert("bar", false);
270   QTest::newRow("if-tag-or02") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
271
272   dict.clear();
273   dict.insert("foo", false);
274   dict.insert("bar", true);
275   QTest::newRow("if-tag-or03") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
276
277   dict.clear();
278   dict.insert("foo", false);
279   dict.insert("bar", false);
280   QTest::newRow("if-tag-or04") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
281
282   dict.clear();
283   dict.insert("foo", false);
284   QTest::newRow("if-tag-or05") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
285
286   dict.clear();
287   dict.insert("bar", false);
288   QTest::newRow("if-tag-or06") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
289
290   dict.clear();
291   dict.insert("foo", true);
292   QTest::newRow("if-tag-or07") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
293
294   dict.clear();
295   dict.insert("bar", true);
296   QTest::newRow("if-tag-or08") << "{% if foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
297
298   // TODO: multiple ORs
299
300
301   // NOT
302
303   dict.clear();
304   dict.insert("foo", true);
305   QTest::newRow("if-tag-not01") << "{% if not foo %}no{% else %}yes{% endif %}" << dict << "yes" << NoError;
306   QTest::newRow("if-tag-not02") << "{% if not %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
307
308   dict.clear();
309   dict.insert("not", true);
310   QTest::newRow("if-tag-not03") << "{% if not %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
311   QTest::newRow("if-tag-not04") << "{% if not not %}no{% else %}yes{% endif %}" << dict << "yes" << NoError;
312
313   dict.clear();
314   QTest::newRow("if-tag-not05") << "{% if not not %}no{% else %}yes{% endif %}" << dict << "no" << NoError;
315   QTest::newRow("if-tag-not06") << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
316
317   dict.clear();
318   dict.insert("foo", true);
319   dict.insert("bar", true);
320   QTest::newRow("if-tag-not07") << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
321
322   dict.clear();
323   dict.insert("foo", true);
324   dict.insert("bar", false);
325   QTest::newRow("if-tag-not08") << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
326
327   dict.clear();
328   dict.insert("foo", false);
329   dict.insert("bar", true);
330   QTest::newRow("if-tag-not09") << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
331
332   dict.clear();
333   dict.insert("foo", false);
334   dict.insert("bar", false);
335   QTest::newRow("if-tag-not10") << "{% if foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
336
337   dict.clear();
338   QTest::newRow("if-tag-not11") << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
339
340   dict.clear();
341   dict.insert("foo", true);
342   dict.insert("bar", true);
343   QTest::newRow("if-tag-not12") << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
344
345   dict.clear();
346   dict.insert("foo", true);
347   dict.insert("bar", false);
348   QTest::newRow("if-tag-not13") << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
349
350   dict.clear();
351   dict.insert("foo", false);
352   dict.insert("bar", true);
353   QTest::newRow("if-tag-not14") << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
354
355   dict.clear();
356   dict.insert("foo", false);
357   dict.insert("bar", false);
358   QTest::newRow("if-tag-not15") << "{% if not foo and bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
359
360   dict.clear();
361   QTest::newRow("if-tag-not16") << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
362
363   dict.clear();
364   dict.insert("foo", true);
365   dict.insert("bar", true);
366   QTest::newRow("if-tag-not17") << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
367
368   dict.clear();
369   dict.insert("foo", true);
370   dict.insert("bar", false);
371   QTest::newRow("if-tag-not18") << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
372
373   dict.clear();
374   dict.insert("foo", false);
375   dict.insert("bar", true);
376   QTest::newRow("if-tag-not19") << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
377
378   dict.clear();
379   dict.insert("foo", false);
380   dict.insert("bar", false);
381   QTest::newRow("if-tag-not20") << "{% if foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
382
383   dict.clear();
384   QTest::newRow("if-tag-not21") << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
385
386   dict.clear();
387   dict.insert("foo", true);
388   dict.insert("bar", true);
389   QTest::newRow("if-tag-not22") << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
390
391   dict.clear();
392   dict.insert("foo", true);
393   dict.insert("bar", false);
394   QTest::newRow("if-tag-not23") << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
395
396   dict.clear();
397   dict.insert("foo", false);
398   dict.insert("bar", true);
399   QTest::newRow("if-tag-not24") << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
400
401   dict.clear();
402   dict.insert("foo", false);
403   dict.insert("bar", false);
404   QTest::newRow("if-tag-not25") << "{% if not foo or bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
405
406   dict.clear();
407   QTest::newRow("if-tag-not26") << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
408
409   dict.clear();
410   dict.insert("foo", true);
411   dict.insert("bar", true);
412   QTest::newRow("if-tag-not27") << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
413
414   dict.clear();
415   dict.insert("foo", true);
416   dict.insert("bar", false);
417   QTest::newRow("if-tag-not28") << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
418
419   dict.clear();
420   dict.insert("foo", false);
421   dict.insert("bar", true);
422   QTest::newRow("if-tag-not29") << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
423
424   dict.clear();
425   dict.insert("foo", false);
426   dict.insert("bar", false);
427   QTest::newRow("if-tag-not30") << "{% if not foo and not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
428
429   dict.clear();
430   QTest::newRow("if-tag-not31") << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
431
432   dict.clear();
433   dict.insert("foo", true);
434   dict.insert("bar", true);
435   QTest::newRow("if-tag-not32") << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "no" << NoError;
436
437   dict.clear();
438   dict.insert("foo", true);
439   dict.insert("bar", false);
440   QTest::newRow("if-tag-not33") << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
441
442   dict.clear();
443   dict.insert("foo", false);
444   dict.insert("bar", true);
445   QTest::newRow("if-tag-not34") << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
446
447   dict.clear();
448   dict.insert("foo", false);
449   dict.insert("bar", false);
450   QTest::newRow("if-tag-not35") << "{% if not foo or not bar %}yes{% else %}no{% endif %}" << dict << "yes" << NoError;
451
452   // AND and OR raises a TemplateSyntaxError
453   QTest::newRow("if-tag-error01") << "{% if foo or bar and baz %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
454
455   dict.clear();
456   dict.insert("foo", true);
457   QTest::newRow("if-tag-error02") << "{% if foo and %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
458   QTest::newRow("if-tag-error03") << "{% if foo or %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
459   QTest::newRow("if-tag-error04") << "{% if not foo and %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
460   QTest::newRow("if-tag-error05") << "{% if not foo or %}yes{% else %}no{% endif %}" << dict << "" << TagSyntaxError;
461
462 }
463
464 void TestDefaultTags::testForTag_data()
465 {
466   QTest::addColumn<QString>("input");
467   QTest::addColumn<Dict>("dict");
468   QTest::addColumn<QString>("output");
469   QTest::addColumn<Grantlee::Error>("error");
470
471   Dict dict;
472
473   QVariantList list;
474   list << 1 << 2 << 3;
475   dict.insert("values", list);
476   QTest::newRow("for-tag01") << "{% for val in values %}{{ val }}{% endfor %}" << dict << "123" << NoError;
477   QTest::newRow("for-tag02") << "{% for val in values reversed %}{{ val }}{% endfor %}" << dict << "321" << NoError;
478   list.clear();
479   list << 6 << 6 << 6;
480   QTest::newRow("for-tag-vars01") << "{% for val in values %}{{ forloop.counter }}{% endfor %}" << dict << "123" << NoError;
481   QTest::newRow("for-tag-vars02") << "{% for val in values %}{{ forloop.counter0 }}{% endfor %}" << dict << "012" << NoError;
482   QTest::newRow("for-tag-vars03") << "{% for val in values %}{{ forloop.revcounter }}{% endfor %}" << dict << "321" << NoError;
483   QTest::newRow("for-tag-vars04") << "{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}" << dict << "210" << NoError;
484   QTest::newRow("for-tag-vars05") << "{% for val in values %}{% if forloop.first %}f{% else %}x{% endif %}{% endfor %}" << dict << "fxx" << NoError;
485   QTest::newRow("for-tag-vars06") << "{% for val in values %}{% if forloop.last %}l{% else %}x{% endif %}{% endfor %}" << dict << "xxl" << NoError;
486 }
487
488 void TestDefaultTags::testIfEqualTag_data()
489 {
490   QTest::addColumn<QString>("input");
491   QTest::addColumn<Dict>("dict");
492   QTest::addColumn<QString>("output");
493   QTest::addColumn<Grantlee::Error>("error");
494
495   Dict dict;
496
497   dict.insert("a", 1);
498   dict.insert("b", 2);
499
500   QTest::newRow("ifequal01") << "{% ifequal a b %}yes{% endifequal %}" << dict << "" << NoError;
501   QTest::newRow("ifequal03") << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
502
503   dict.clear();
504   dict.insert("a", 1);
505   dict.insert("b", 1);
506
507   QTest::newRow("ifequal02") << "{% ifequal a b %}yes{% endifequal %}" << dict << "yes" << NoError;
508   QTest::newRow("ifequal04") << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
509
510   dict.clear();
511   dict.insert("a", "test");
512
513   QTest::newRow("ifequal05") << "{% ifequal a 'test' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
514
515   dict.clear();
516   dict.insert("a", "no");
517
518   QTest::newRow("ifequal06") << "{% ifequal a 'test' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
519
520   dict.clear();
521   dict.insert("a", "test");
522
523   QTest::newRow("ifequal07") << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
524
525   dict.clear();
526   dict.insert("a", "no");
527
528   QTest::newRow("ifequal08") << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
529
530   dict.clear();
531
532   QTest::newRow("ifequal09") << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
533
534   QTest::newRow("ifequal10") << "{% ifequal a b %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
535
536
537   QTest::newRow("ifequal-split01") << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
538
539   dict.insert("a", "foo");
540   QTest::newRow("ifequal-split01") << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
541   QTest::newRow("ifequal-split02") << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
542
543   dict.clear();
544   dict.insert("a", "test man");
545   QTest::newRow("ifequal-split03") << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
546   QTest::newRow("ifequal-split04") << "{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
547
548   dict.clear();
549   dict.insert("a", "");
550   QTest::newRow("ifequal-split05") << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
551
552   dict.clear();
553   dict.insert("a", "i \"love\" you");
554   QTest::newRow("ifequal-split06") << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
555
556   dict.clear();
557   dict.insert("a", "i love you");
558   QTest::newRow("ifequal-split07") << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
559
560   dict.clear();
561   dict.insert("a", "I'm happy");
562   QTest::newRow("ifequal-split08") << "{% ifequal a 'I\\'m happy' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
563
564   dict.clear();
565   dict.insert("a", "slash\\man");
566   QTest::newRow("ifequal-split09") << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict << "yes" << NoError;
567
568   dict.clear();
569   dict.insert("a", "slashman");
570   QTest::newRow("ifequal-split10") << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict << "no" << NoError;
571 // NUMERIC RESOLUTION
572
573   dict.clear();
574   dict.insert("x", "5");
575
576   QTest::newRow("ifequal-numeric01") << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "" << NoError;
577
578   dict.clear();
579   dict.insert("x", 5);
580   QTest::newRow("ifequal-numeric02") << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "yes" << NoError;
581
582   dict.clear();
583   dict.insert("x", 5.2);
584   QTest::newRow("ifequal-numeric03") << "{% ifequal x 5 %}yes{% endifequal %}" << dict << "" << NoError;
585   QTest::newRow("ifequal-numeric04") << "{% ifequal x 5.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
586
587   dict.clear();
588   dict.insert("x", .2);
589
590   QTest::newRow("ifequal-numeric05") << "{% ifequal x 0.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
591   QTest::newRow("ifequal-numeric06") << "{% ifequal x .2 %}yes{% endifequal %}" << dict << "yes" << NoError;
592
593   dict.clear();
594   dict.insert("x", 2);
595
596   QTest::newRow("ifequal-numeric07") << "{% ifequal x 2. %}yes{% endifequal %}" << dict << "" << NoError;
597
598   dict.clear();
599   dict.insert("x", 5);
600   QTest::newRow("ifequal-numeric08") << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict << "" << NoError;
601
602   dict.clear();
603   dict.insert("x", "5");
604   QTest::newRow("ifequal-numeric09") << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict << "yes" << NoError;
605
606   dict.clear();
607   dict.insert("x", -5);
608   QTest::newRow("ifequal-numeric10") << "{% ifequal x -5 %}yes{% endifequal %}" << dict << "yes" << NoError;
609
610   dict.clear();
611   dict.insert("x", -5.2);
612   QTest::newRow("ifequal-numeric11") << "{% ifequal x -5.2 %}yes{% endifequal %}" << dict << "yes" << NoError;
613
614   dict.clear();
615   dict.insert("x", 5);
616   QTest::newRow("ifequal-numeric12") << "{% ifequal x +5 %}yes{% endifequal %}" << dict << "yes" << NoError;
617
618 }
619
620 void TestDefaultTags::testIfNotEqualTag_data()
621 {
622   QTest::addColumn<QString>("input");
623   QTest::addColumn<Dict>("dict");
624   QTest::addColumn<QString>("output");
625   QTest::addColumn<Grantlee::Error>("error");
626
627   Dict dict;
628
629   dict.insert("a", 1);
630   dict.insert("b", 2);
631
632   QTest::newRow("ifnotequal01") << "{% ifnotequal a b %}yes{% endifnotequal %}" << dict << "yes" << NoError;
633   QTest::newRow("ifnotequal03") << "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}" << dict << "yes" << NoError;
634
635   dict.clear();
636   dict.insert("a", 1);
637   dict.insert("b", 1);
638
639   QTest::newRow("ifnotequal02") << "{% ifnotequal a b %}yes{% endifnotequal %}" << dict << "" << NoError;
640   QTest::newRow("ifnotequal04") << "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}" << dict << "no" << NoError;
641
642 }
643
644 void TestDefaultTags::testTemplateTagTag_data()
645 {
646   QTest::addColumn<QString>("input");
647   QTest::addColumn<Dict>("dict");
648   QTest::addColumn<QString>("output");
649   QTest::addColumn<Grantlee::Error>("error");
650
651   Dict dict;
652
653   QTest::newRow("templatetag01") << "{% templatetag openblock %}" << dict << "{%" << NoError;
654   QTest::newRow("templatetag02") << "{% templatetag closeblock %}" << dict << "%}" << NoError;
655   QTest::newRow("templatetag03") << "{% templatetag openvariable %}" << dict << "{{" << NoError;
656   QTest::newRow("templatetag04") << "{% templatetag closevariable %}" << dict << "}}" << NoError;
657   QTest::newRow("templatetag05") << "{% templatetag %}" << dict << "" << TagSyntaxError;
658   QTest::newRow("templatetag06") << "{% templatetag foo %}" << dict << "" << TagSyntaxError;
659   QTest::newRow("templatetag07") << "{% templatetag openbrace %}" << dict << "{" << NoError;
660   QTest::newRow("templatetag08") << "{% templatetag closebrace %}" << dict << "}" << NoError;
661   QTest::newRow("templatetag09") << "{% templatetag openbrace %}{% templatetag openbrace %}" << dict << "{{" << NoError;
662   QTest::newRow("templatetag10") << "{% templatetag closebrace %}{% templatetag closebrace %}" << dict << "}}" << NoError;
663   QTest::newRow("templatetag11") << "{% templatetag opencomment %}" << dict << "{#" << NoError;
664   QTest::newRow("templatetag12") << "{% templatetag closecomment %}" << dict << "#}" << NoError;
665
666 }
667
668 void TestDefaultTags::testWithTag_data()
669 {
670   QTest::addColumn<QString>("input");
671   QTest::addColumn<Dict>("dict");
672   QTest::addColumn<QString>("output");
673   QTest::addColumn<Grantlee::Error>("error");
674
675   Dict dict;
676
677   QVariantMap map;
678   map.insert("key", 50);
679   dict.insert("dict", map);
680   QTest::newRow("with01") << "{% with dict.key as key %}{{ key }}{% endwith %}" << dict << "50" << NoError;
681   QTest::newRow("with02")
682         << "{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}"
683         << dict << "50-50-50" << NoError;
684   QTest::newRow("with03") << "{% with dict.key xx key %}{{ key }}{% endwith %}" << dict << "" << TagSyntaxError;
685   QTest::newRow("with04") << "{% with dict.key as %}{{ key }}{% endwith %}" << dict << "" << TagSyntaxError;
686 }
687
688 void TestDefaultTags::testCycleTag_data()
689 {
690   QTest::addColumn<QString>("input");
691   QTest::addColumn<Dict>("dict");
692   QTest::addColumn<QString>("output");
693   QTest::addColumn<Grantlee::Error>("error");
694
695   Dict dict;
696
697   QTest::newRow("cycle01") << "{% cycle a %}" << dict << "" << TagSyntaxError;
698   QTest::newRow("cycle02") << "{% cycle a,b,c as abc %}{% cycle abc %}" << dict << "ab" << NoError;
699   QTest::newRow("cycle03") << "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}" << dict << "abc" << NoError;
700   QTest::newRow("cycle04") << "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}" << dict << "abca" << NoError;
701   QTest::newRow("cycle05") << "{% cycle a %}" << dict << "" << TagSyntaxError;
702   // TODO: This is the same as cycle01. Remove.
703   QTest::newRow("cycle06") << "{% cycle a %}" << dict << "" << TagSyntaxError;
704   QTest::newRow("cycle06") << "{% cycle a,b,c as foo %}{% cycle bar %}" << dict << "" << TagSyntaxError;
705   QTest::newRow("cycle06") << "{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}" << dict << "abbbcc" << TagSyntaxError;
706
707   dict.insert("test", QVariantList() << 0 << 1 << 2 << 3 << 4);
708   QTest::newRow("cycle09") << "{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," << NoError;
709
710   dict.clear();
711   QTest::newRow("cycle10") << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}" << dict << "ab" << NoError;
712   QTest::newRow("cycle11") << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}" << dict << "abc" << NoError;
713   QTest::newRow("cycle12") << "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}" << dict << "abca" << NoError;
714
715   dict.insert("test", QVariantList() << 0 << 1 << 2 << 3 << 4);
716   QTest::newRow("cycle13") << "{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," << NoError;
717
718   dict.clear();
719   dict.insert("one", "1");
720   dict.insert("two", "2");
721   QTest::newRow("cycle14") << "{% cycle one two as foo %}{% cycle foo %}" << dict << "12" << NoError;
722   dict.insert("test", QVariantList() << 0 << 1 << 2 << 3 << 4);
723   // TODO: Same name as cycle13 in Django. Fix upstream.
724   //  'aye': 'a', 'bee': 'b'}, '
725 //   QTest::newRow("cycle15") << "{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}" << dict << "a0,b1,a2,b3,a4," ;
726 }
727
728 void TestDefaultTags::testWidthRatioTag_data()
729 {
730   QTest::addColumn<QString>("input");
731   QTest::addColumn<Dict>("dict");
732   QTest::addColumn<QString>("output");
733   QTest::addColumn<Grantlee::Error>("error");
734
735   Dict dict;
736
737   dict.insert("a", 50);
738   dict.insert("b", 100);
739   QTest::newRow("widthratio01") << "{% widthratio a b 0 %}" << dict << "0" << NoError;
740
741   dict.clear();
742   dict.insert("a", 0);
743   dict.insert("b", 0);
744   QTest::newRow("widthratio02") << "{% widthratio a b 0 %}" << dict << "" << NoError;
745
746   dict.clear();
747   dict.insert("a", 0);
748   dict.insert("b", 100);
749   QTest::newRow("widthratio03") << "{% widthratio a b 100 %}" << dict << "0" << NoError;
750
751   dict.clear();
752   dict.insert("a", 50);
753   dict.insert("b", 100);
754   QTest::newRow("widthratio04") << "{% widthratio a b 100 %}" << dict << "50" << NoError;
755
756   dict.clear();
757   dict.insert("a", 100);
758   dict.insert("b", 100);
759   QTest::newRow("widthratio05") << "{% widthratio a b 100 %}" << dict << "100" << NoError;
760
761   dict.clear();
762   dict.insert("a", 50);
763   dict.insert("b", 80);
764   QTest::newRow("widthratio06") << "{% widthratio a b 100 %}" << dict << "63" << NoError;
765
766   dict.clear();
767   dict.insert("a", 50);
768   dict.insert("b", 70);
769   QTest::newRow("widthratio07") << "{% widthratio a b 100 %}" << dict << "71" << NoError;
770
771   dict.clear();
772 // Raise exception if we don't have 3 args, last one an integer
773   QTest::newRow("widthratio08") << "{% widthratio %}" << dict << "" << TagSyntaxError;
774
775   dict.clear();
776   QTest::newRow("widthratio09") << "{% widthratio a b %}" << dict << "" << TagSyntaxError;
777
778   dict.clear();
779   QTest::newRow("widthratio10") << "{% widthratio a b 100.0 %}" << dict << "" << TagSyntaxError;
780 }
781
782
783 void TestDefaultTags::testFilterTag_data()
784 {
785   QTest::addColumn<QString>("input");
786   QTest::addColumn<Dict>("dict");
787   QTest::addColumn<QString>("output");
788   QTest::addColumn<Grantlee::Error>("error");
789
790   Dict dict;
791
792   QTest::newRow("filter01") << "{% filter upper %}{% endfilter %}" << dict << "" << NoError;
793   QTest::newRow("filter02") << "{% filter upper %}django{% endfilter %}" << dict << "DJANGO" << NoError;
794   QTest::newRow("filter03") << "{% filter upper|lower %}django{% endfilter %}" << dict << "django" << NoError;
795
796   dict.insert("remove", "spam");
797   QTest::newRow("filter04") << "{% filter cut:remove %}djangospam{% endfilter %}" << dict << "django" << NoError;
798
799 }
800
801 void TestDefaultTags::testNowTag_data()
802 {
803   QTest::addColumn<QString>("input");
804   QTest::addColumn<Dict>("dict");
805   QTest::addColumn<QString>("output");
806   QTest::addColumn<Grantlee::Error>("error");
807
808   Dict dict;
809
810   QDate today = QDateTime::currentDateTime().date();
811
812   QTest::newRow("now01") << "{% now \"d M yyyy\"%}" << dict << (QString::number(today.day()) + " " +  QString::number(today.month()) + " " + QString::number(today.year())) << NoError;
813
814
815 }
816
817 void TestDefaultTags::testSpacelessTag_data()
818 {
819   QTest::addColumn<QString>("input");
820   QTest::addColumn<Dict>("dict");
821   QTest::addColumn<QString>("output");
822   QTest::addColumn<Grantlee::Error>("error");
823
824   Dict dict;
825
826   QTest::newRow("spaceless01") << "{% spaceless %} <b>    <i> text </i>    </b> {% endspaceless %}" << dict << "<b><i> text </i></b>" << NoError;
827   QTest::newRow("spaceless02") << "{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}" << dict << "<b><i> text </i></b>" << NoError;
828   QTest::newRow("spaceless03") << "{% spaceless %}<b><i>text</i></b>{% endspaceless %}" << dict << "<b><i>text</i></b>" << NoError;
829
830 }
831
832 void TestDefaultTags::testRegroupTag_data()
833 {
834   QTest::addColumn<QString>("input");
835   QTest::addColumn<Dict>("dict");
836   QTest::addColumn<QString>("output");
837   QTest::addColumn<Grantlee::Error>("error");
838
839   Dict dict;
840
841   QVariantList list;
842   QVariantMap map;
843
844   map.insert("foo", "c");
845   map.insert("bar", 1);
846   list.append(map);
847
848   map.clear();
849   map.insert("foo", "d");
850   map.insert("bar", 1);
851   list.append(map);
852
853   map.clear();
854   map.insert("foo", "a");
855   map.insert("bar", 2);
856   list.append(map);
857
858   map.clear();
859   map.insert("foo", "b");
860   map.insert("bar", 2);
861   list.append(map);
862
863   map.clear();
864   map.insert("foo", "x");
865   map.insert("bar", 3);
866   list.append(map);
867
868   dict.insert("data", list);
869
870   QTest::newRow("regroup01") << "{% regroup data by bar as grouped %}"
871                                   "{% for group in grouped %}"
872                                     "{{ group.grouper }}:"
873                                     "{% for item in group.list %}"
874                                       "{{ item.foo }}"
875                                     "{% endfor %},"
876                                   "{% endfor %}" << dict << "1:cd,2:ab,3:x," << NoError;
877
878 }
879
880 void TestDefaultTags::testIfChangedTag_data()
881 {
882   QTest::addColumn<QString>("input");
883   QTest::addColumn<Dict>("dict");
884   QTest::addColumn<QString>("output");
885   QTest::addColumn<Grantlee::Error>("error");
886
887   Dict dict;
888
889   dict.insert("num", QVariantList() << 1 << 2 << 3 );
890   QTest::newRow("ifchanged01") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "123" << NoError;
891
892   dict.clear();
893   dict.insert("num", QVariantList() << 1 << 1 << 3 );
894   QTest::newRow("ifchanged02") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "13" << NoError;
895
896   dict.clear();
897   dict.insert("num", QVariantList() << 1 << 1 << 1 );
898   QTest::newRow("ifchanged03") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}" << dict << "1" << NoError;
899
900   dict.clear();
901   dict.insert("num", QVariantList() << 1 << 2 << 3 );
902   dict.insert("numx", QVariantList() << 2 << 2 << 2 );
903   QTest::newRow("ifchanged04") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "122232" << NoError;
904
905   dict.clear();
906   dict.insert("num", QVariantList() << 1 << 1 << 1 );
907   dict.insert("numx", QVariantList() << 1 << 2 << 3 );
908   QTest::newRow("ifchanged05") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "1123123123" << NoError;
909
910   dict.clear();
911   dict.insert("num", QVariantList() << 1 << 1 << 1 );
912   dict.insert("numx", QVariantList() << 2 << 2 << 2 );
913   QTest::newRow("ifchanged06") << "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "1222" << NoError;
914
915   dict.clear();
916   dict.insert("num", QVariantList() << 1 << 1 << 1 );
917   dict.insert("numx", QVariantList() << 2 << 2 << 2 );
918   dict.insert("numy", QVariantList() << 3 << 3 << 3 );
919   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;
920
921   // datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1, 'c'), (1, 'd'), (1, 'd'), (0, 'e')]]}
922   dict.clear();
923   QVariantList list;
924   QVariantList innerList;
925   QVariantList tuple;
926   tuple << 1 << "a";
927   innerList << tuple;
928   tuple.clear();
929   tuple << 1 << "a";
930   innerList << tuple;
931   tuple.clear();
932   tuple << 0 << "b";
933   innerList << tuple;
934   tuple.clear();
935   tuple << 1 << "c";
936   innerList << tuple;
937   tuple.clear();
938   list << innerList;
939   innerList.clear();
940
941   tuple << 0 << "a";
942   innerList << tuple;
943   tuple.clear();
944   tuple << 1 << "c";
945   innerList << tuple;
946   tuple.clear();
947   tuple << 1 << "d";
948   innerList << tuple;
949   tuple.clear();
950   tuple << 1 << "d";
951   innerList << tuple;
952   tuple.clear();
953   tuple << 0 << "e";
954   innerList << tuple;
955   tuple.clear();
956   list << innerList;
957   innerList.clear();
958
959 //   dict.insert("datalist", list);
960 //   QTest::newRow("ifchanged08") << "{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged %}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}" << dict << "accd" << NoError;
961
962 // Test one parameter given to ifchanged.
963   dict.clear();
964   dict.insert("num", QVariantList() << 1 << 2 << 3 );
965   QTest::newRow("ifchanged-param01") << "{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}" << dict << "..1..2..3" << NoError;
966
967   dict.clear();
968   dict.insert("num", QVariantList() << 1 << 2 << 3 );
969   dict.insert("numx", QVariantList() << 5 << 6 << 7 );
970   QTest::newRow("ifchanged-param02") << "{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}" << dict << "..567..567..567" << NoError;
971
972 // Test multiple parameters to ifchanged.
973
974   dict.clear();
975   dict.insert("num", QVariantList() << 1 << 1 << 2 );
976   dict.insert("numx", QVariantList() << 5 << 6 << 6 );
977   QTest::newRow("ifchanged-param03") << "{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}" << dict << "156156256" << NoError;
978
979 // Test a date+hour like construct, where the hour of the last day
980 // is the same but the date had changed, so print the hour anyway.
981
982   dict.clear();
983   QVariantList days;
984   QVariantMap day;
985   day.insert("day", 1);
986   day.insert("hours", QVariantList() << 1 << 2 << 3 );
987   days << day;
988   day.clear();
989   day.insert("day", 2);
990   day.insert("hours", QVariantList() << 3 );
991   days << day;
992   dict.insert("days", days );
993   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;
994
995
996 // Logically the same as above, just written with explicit
997 // ifchanged for the day.
998
999   // TODO: fix name conflict upstream
1000   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;
1001
1002 // Test the else clause of ifchanged.
1003   dict.clear();
1004   dict.insert("ids", QVariantList() << 1 << 1 << 2 << 2 << 2 << 3 );
1005   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;
1006
1007 //   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;
1008 //
1009 //   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;
1010
1011   dict.clear();
1012   dict.insert("ids", QVariantList() << 1 << 1 << 2 << 2 << 2 << 3 << 4 );
1013   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;
1014
1015 }
1016
1017
1018 QTEST_MAIN(TestDefaultTags)
1019 #include "testdefaulttags.moc"
1020
1021 #endif