Cutelee 6.1.0
testdefaulttags.cpp
1/*
2 This file is part of the Cutelee 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.1 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 Lesser 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 <QtCore/QDebug>
25#include <QtTest/QTest>
26
27#include "context.h"
28#include "coverageobject.h"
29#include "engine.h"
30#include "cutelee_paths.h"
31#include "metatype.h"
32#include "template.h"
33#include "util.h"
34
35typedef QList<QVariantList> Table;
36typedef QHash<QString, QVariant> Dict;
37typedef QPair<QString, QString> StringPair;
38
39Q_DECLARE_METATYPE(Cutelee::Error)
40
42{
43public:
45 {
46 m_existingMedia << QStringLiteral("existing_image.png")
47 << QStringLiteral("another_existing_image.png")
48 << QStringLiteral("this&that.png");
49 }
50
51 std::pair<QString, QString> getMediaUri(const QString &fileName) const override
52 {
53 if (m_existingMedia.contains(fileName))
54 return {QStringLiteral("/path/to/"), fileName};
55 return {};
56 }
57
58private:
59 QStringList m_existingMedia;
60};
61
62class Zoo : public QObject
63{
64 Q_OBJECT
65public:
66 Zoo(QObject *parent = {}) : QObject(parent) {}
67
68 enum Animals { Lions, Tigers, Bears };
69 Q_ENUM(Animals)
70};
71
72using namespace Cutelee;
73
75{
76 Q_OBJECT
77
78private Q_SLOTS:
79 void initTestCase();
80 void cleanupTestCase();
81
82 void testCommentTag_data();
83 void testCommentTag() { doTest(); }
84
85 void testFirstOfTag_data();
86 void testFirstOfTag() { doTest(); }
87
88 void testIfTag_data();
89 void testIfTag() { doTest(); }
90
91 void testForTag_data();
92 void testForTag() { doTest(); }
93
94 void testIfEqualTag_data();
95 void testIfEqualTag() { doTest(); }
96
97 void testIfNotEqualTag_data();
98 void testIfNotEqualTag() { doTest(); }
99
100 void testTemplateTagTag_data();
101 void testTemplateTagTag() { doTest(); }
102
103 void testWithTag_data();
104 void testWithTag() { doTest(); }
105
106 void testCycleTag_data();
107 void testCycleTag() { doTest(); }
108
109 void testWidthRatioTag_data();
110 void testWidthRatioTag() { doTest(); }
111
112 void testFilterTag_data();
113 void testFilterTag() { doTest(); }
114
115 void testNowTag_data();
116 void testNowTag() { doTest(); }
117
118 void testSpacelessTag_data();
119 void testSpacelessTag() { doTest(); }
120
121 void testRegroupTag_data();
122 void testRegroupTag() { doTest(); }
123
124 void testIfChangedTag_data();
125 void testIfChangedTag() { doTest(); }
126
127 void testAutoescapeTag_data();
128 void testAutoescapeTag() { doTest(); }
129
130 void testMediaFinderTag_data();
131 void testMediaFinderTag() { doTest(); }
132
133 void testRangeTag_data();
134 void testRangeTag() { doTest(); }
135
136 void testDebugTag_data();
137 void testDebugTag() { doTest(); }
138
139 void testLoadTag_data();
140 void testLoadTag() { doTest(); }
141
142 void testUrlTypes_data();
143 void testUrlTypes();
144
145 void testRelativePaths_data();
146 void testRelativePaths();
147
148private:
149 void doTest();
150
151 Engine *m_engine;
152};
153
154void TestDefaultTags::initTestCase()
155{
156 m_engine = new Engine(this);
157 m_engine->setPluginPaths({QStringLiteral(CUTELEE_PLUGIN_PATH)});
158
159 auto loader1 = std::shared_ptr<FakeTemplateLoader>(new FakeTemplateLoader());
160
161 m_engine->addTemplateLoader(loader1);
162}
163
164void TestDefaultTags::cleanupTestCase() { delete m_engine; }
165
166void TestDefaultTags::doTest()
167{
168 QFETCH(QString, input);
169 QFETCH(Dict, dict);
170 QFETCH(QString, output);
171 QFETCH(Cutelee::Error, error);
172
173 auto t = m_engine->newTemplate(input, QLatin1String(QTest::currentDataTag()));
174
175 if (t->error() != NoError) {
176 if (t->error() != error)
177 qDebug() << t->errorString();
178 QCOMPARE(t->error(), error);
179 return;
180 }
181
182 Context context(dict);
183
184 auto result = t->render(&context);
185
186 if (t->error() != NoError) {
187 if (t->error() != error)
188 qDebug() << t->errorString();
189 QCOMPARE(t->error(), error);
190 return;
191 }
192
193 // Didn't catch any errors, so make sure I didn't expect any.
194 QCOMPARE(NoError, error);
195
196 QCOMPARE(t->error(), NoError);
197
198 QCOMPARE(result, output);
199
200 if (!result.isEmpty()
201 && QString::fromLatin1(QTest::currentTestFunction())
202 == QStringLiteral("testMediaFinderTag")) {
203 QVERIFY(!context.externalMedia().isEmpty());
204 }
205}
206
207void TestDefaultTags::testCommentTag_data()
208{
209 QTest::addColumn<QString>("input");
210 QTest::addColumn<Dict>("dict");
211 QTest::addColumn<QString>("output");
212 QTest::addColumn<Cutelee::Error>("error");
213
214 Dict dict;
215
216 QTest::newRow("comment-tag01")
217 << QStringLiteral("{% comment %}this is hidden{% endcomment %}hello")
218 << dict << QStringLiteral("hello") << NoError;
219
220 QTest::newRow("comment-tag02")
221 << QStringLiteral("{% comment %}this is hidden{% endcomment %}hello{% "
222 "comment %}foo{% endcomment %}")
223 << dict << QStringLiteral("hello") << NoError;
224 // Comment tag can contain invalid stuff.
225 QTest::newRow("comment-tag03")
226 << QStringLiteral("foo{% comment %} {% if %} {% endcomment %}") << dict
227 << QStringLiteral("foo") << NoError;
228 QTest::newRow("comment-tag04")
229 << QStringLiteral("foo{% comment %} {% endblock %} {% endcomment %}")
230 << dict << QStringLiteral("foo") << NoError;
231 QTest::newRow("comment-tag05")
232 << QStringLiteral("foo{% comment %} {% somerandomtag %} {% endcomment %}")
233 << dict << QStringLiteral("foo") << NoError;
234 QTest::newRow("comment-tag06") << QStringLiteral("{% comment %}yes") << dict
235 << QString() << UnclosedBlockTagError;
236}
237
238void TestDefaultTags::testFirstOfTag_data()
239{
240 QTest::addColumn<QString>("input");
241 QTest::addColumn<Dict>("dict");
242 QTest::addColumn<QString>("output");
243 QTest::addColumn<Cutelee::Error>("error");
244
245 Dict dict;
246 dict.insert(QStringLiteral("a"), 0);
247 dict.insert(QStringLiteral("b"), 0);
248 dict.insert(QStringLiteral("c"), 0);
249 QTest::newRow("firstof01")
250 << QStringLiteral("{% firstof a b c %}") << dict << QString() << NoError;
251
252 dict.clear();
253 dict.insert(QStringLiteral("a"), 1);
254 dict.insert(QStringLiteral("b"), 0);
255 dict.insert(QStringLiteral("c"), 0);
256 QTest::newRow("firstof02") << QStringLiteral("{% firstof a b c %}") << dict
257 << QStringLiteral("1") << NoError;
258
259 dict.clear();
260 dict.insert(QStringLiteral("a"), 0);
261 dict.insert(QStringLiteral("b"), 2);
262 dict.insert(QStringLiteral("c"), 0);
263 QTest::newRow("firstof03") << QStringLiteral("{% firstof a b c %}") << dict
264 << QStringLiteral("2") << NoError;
265
266 dict.clear();
267 dict.insert(QStringLiteral("a"), 0);
268 dict.insert(QStringLiteral("b"), 0);
269 dict.insert(QStringLiteral("c"), 3);
270 QTest::newRow("firstof04") << QStringLiteral("{% firstof a b c %}") << dict
271 << QStringLiteral("3") << NoError;
272
273 dict.clear();
274 dict.insert(QStringLiteral("a"), 1);
275 dict.insert(QStringLiteral("b"), 2);
276 dict.insert(QStringLiteral("c"), 3);
277 QTest::newRow("firstof05") << QStringLiteral("{% firstof a b c %}") << dict
278 << QStringLiteral("1") << NoError;
279
280 dict.clear();
281 dict.insert(QStringLiteral("b"), 0);
282 dict.insert(QStringLiteral("c"), 3);
283 QTest::newRow("firstof06") << QStringLiteral("{% firstof a b c %}") << dict
284 << QStringLiteral("3") << NoError;
285
286 dict.clear();
287 dict.insert(QStringLiteral("a"), 0);
288 QTest::newRow("firstof07")
289 << "{% firstof a b \"c\" %}" << dict << QStringLiteral("c") << NoError;
290
291 dict.clear();
292 dict.insert(QStringLiteral("a"), 0);
293 dict.insert(QStringLiteral("b"), 0);
294 QTest::newRow("firstof08") << "{% firstof a b \"c and d\" %}" << dict
295 << QStringLiteral("c and d") << NoError;
296 QTest::newRow("firstof09") << QStringLiteral("{% firstof %}") << dict
297 << QStringLiteral("a") << TagSyntaxError;
298}
299
300class BadIfObject : public QObject
301{
302 Q_OBJECT
303 Q_PROPERTY(bool isTrue READ isTrue CONSTANT)
304 Q_PROPERTY(bool isFalse READ isFalse CONSTANT)
305 Q_PROPERTY(bool isBad READ isBad CONSTANT)
306public:
307 BadIfObject(QObject *parent = {}) : QObject(parent), mIsBadCalled(false) {}
308
309 bool isTrue() const { return true; }
310
311 bool isFalse() const { return false; }
312
313 bool isBad() const
314 {
315 mIsBadCalled = true;
316 return true;
317 }
318
319 bool isBadCalled() { return mIsBadCalled; }
320
321private:
322 mutable bool mIsBadCalled;
323};
324
325void TestDefaultTags::testIfTag_data()
326{
327 QTest::addColumn<QString>("input");
328 QTest::addColumn<Dict>("dict");
329 QTest::addColumn<QString>("output");
330 QTest::addColumn<Cutelee::Error>("error");
331
332 Dict dict;
333
334 dict.insert(QStringLiteral("foo"), true);
335
336 QTest::newRow("if-tag01")
337 << QStringLiteral("{% if foo %}yes{% else %}no{% endif %}") << dict
338 << QStringLiteral("yes") << NoError;
339
340 dict.clear();
341 dict.insert(QStringLiteral("foo"), false);
342 QTest::newRow("if-tag02")
343 << QStringLiteral("{% if foo %}yes{% else %}no{% endif %}") << dict
344 << QStringLiteral("no") << NoError;
345
346 dict.clear();
347 QTest::newRow("if-tag03")
348 << QStringLiteral("{% if foo %}yes{% else %}no{% endif %}") << dict
349 << QStringLiteral("no") << NoError;
350
351 dict.clear();
352 dict.insert(QStringLiteral("foo"), true);
353 QTest::newRow("if-tag04")
354 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% endif %}") << dict
355 << QStringLiteral("foo") << NoError;
356
357 dict.clear();
358 dict.insert(QStringLiteral("bar"), true);
359 QTest::newRow("if-tag05")
360 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% endif %}") << dict
361 << QStringLiteral("bar") << NoError;
362
363 dict.clear();
364 QTest::newRow("if-tag06")
365 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% endif %}") << dict
366 << QString() << NoError;
367
368 dict.clear();
369 dict.insert(QStringLiteral("foo"), true);
370 QTest::newRow("if-tag07") << QStringLiteral(
371 "{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}")
372 << dict << QStringLiteral("foo") << NoError;
373
374 dict.clear();
375 dict.insert(QStringLiteral("bar"), true);
376 QTest::newRow("if-tag08") << QStringLiteral(
377 "{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}")
378 << dict << QStringLiteral("bar") << NoError;
379
380 dict.clear();
381 QTest::newRow("if-tag09") << QStringLiteral(
382 "{% if foo %}foo{% elif bar %}bar{% else %}nothing{% endif %}")
383 << dict << QStringLiteral("nothing") << NoError;
384
385 dict.clear();
386 dict.insert(QStringLiteral("foo"), true);
387 QTest::newRow("if-tag10")
388 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% "
389 "else %}nothing{% endif %}")
390 << dict << QStringLiteral("foo") << NoError;
391
392 dict.clear();
393 dict.insert(QStringLiteral("bar"), true);
394 QTest::newRow("if-tag11")
395 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% "
396 "else %}nothing{% endif %}")
397 << dict << QStringLiteral("bar") << NoError;
398
399 dict.clear();
400 dict.insert(QStringLiteral("baz"), true);
401 QTest::newRow("if-tag12")
402 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% "
403 "else %}nothing{% endif %}")
404 << dict << QStringLiteral("baz") << NoError;
405
406 dict.clear();
407 QTest::newRow("if-tag13")
408 << QStringLiteral("{% if foo %}foo{% elif bar %}bar{% elif baz %}baz{% "
409 "else %}nothing{% endif %}")
410 << dict << QStringLiteral("nothing") << NoError;
411
412 // Filters
413
414 dict.clear();
415 dict.insert(QStringLiteral("foo"), QStringLiteral("abcde"));
416 QTest::newRow("if-tag-filter01")
417 << QStringLiteral("{% if foo|length == 5 %}yes{% else %}{{ foo|length }}{% endif %}")
418 << dict << QStringLiteral("yes") << NoError;
419
420 dict.clear();
421 QTest::newRow("if-tag-filter02") << QStringLiteral(
422 "{% if foo|upper == \'ABC\' %}yes{% else %}no{% endif %}")
423 << dict << QStringLiteral("no") << NoError;
424
425 // Equality
426
427 dict.clear();
428 QTest::newRow("if-tag-eq01")
429 << QStringLiteral("{% if foo == bar %}yes{% else %}no{% endif %}") << dict
430 << QStringLiteral("yes") << NoError;
431
432 dict.clear();
433 dict.insert(QStringLiteral("foo"), 1);
434 QTest::newRow("if-tag-eq02")
435 << QStringLiteral("{% if foo == bar %}yes{% else %}no{% endif %}") << dict
436 << QStringLiteral("no") << NoError;
437
438 dict.clear();
439 dict.insert(QStringLiteral("foo"), 1);
440 dict.insert(QStringLiteral("bar"), 1);
441 QTest::newRow("if-tag-eq03")
442 << QStringLiteral("{% if foo == bar %}yes{% else %}no{% endif %}") << dict
443 << QStringLiteral("yes") << NoError;
444
445 dict.clear();
446 dict.insert(QStringLiteral("foo"), 1);
447 dict.insert(QStringLiteral("bar"), 2);
448 QTest::newRow("if-tag-eq04")
449 << QStringLiteral("{% if foo == bar %}yes{% else %}no{% endif %}") << dict
450 << QStringLiteral("no") << NoError;
451
452 dict.clear();
453 QTest::newRow("if-tag-eq05")
454 << QStringLiteral("{% if foo == \'\' %}yes{% else %}no{% endif %}")
455 << dict << QStringLiteral("no") << NoError;
456
457 dict.clear();
458 dict.insert(QStringLiteral("foostring"), QStringLiteral("foo"));
459 QTest::newRow("if-tag-eq06") << QStringLiteral(
460 "{% if foostring == \'foo\' %}yes{% else %}no{% endif %}")
461 << dict << QStringLiteral("yes") << NoError;
462
463 dict.clear();
464 QTest::newRow("if-tag-eq07")
465 << QStringLiteral("{% if \"foo\" == \"foo\" %}yes{% else %}no{% endif %}")
466 << dict << QStringLiteral("yes") << NoError;
467 dict.clear();
468 dict.insert(QStringLiteral("foo"), QStringLiteral("bar"));
469 QTest::newRow("if-tag-eq08")
470 << QStringLiteral("{% if foo == \"bar\" %}yes{% else %}no{% endif %}")
471 << dict << QStringLiteral("yes") << NoError;
472#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
473 dict.clear();
474 dict.insert(QStringLiteral("zoo"), QVariant::fromValue(new Zoo(this)));
475 dict.insert(QStringLiteral("tigersEnum"),
476 QVariant::fromValue<int>(Zoo::Tigers));
477 QTest::newRow("if-tag-eq07") << QStringLiteral(
478 "{% if tigersEnum == zoo.Tigers %}yes{% else %}no{% endif %}")
479 << dict << QStringLiteral("yes") << NoError;
480#endif
481
482 // Comparison
483
484 dict.clear();
485 QTest::newRow("if-tag-gt-01")
486 << QStringLiteral("{% if 2 > 1 %}yes{% else %}no{% endif %}") << dict
487 << QStringLiteral("yes") << NoError;
488
489 dict.clear();
490 QTest::newRow("if-tag-gt-02")
491 << QStringLiteral("{% if 1 > 1 %}yes{% else %}no{% endif %}") << dict
492 << QStringLiteral("no") << NoError;
493
494 dict.clear();
495 QTest::newRow("if-tag-gte-01")
496 << QStringLiteral("{% if 1 >= 1 %}yes{% else %}no{% endif %}") << dict
497 << QStringLiteral("yes") << NoError;
498
499 dict.clear();
500 QTest::newRow("if-tag-gte-02")
501 << QStringLiteral("{% if 1 >= 2 %}yes{% else %}no{% endif %}") << dict
502 << QStringLiteral("no") << NoError;
503
504 dict.clear();
505 QTest::newRow("if-tag-lt-01")
506 << QStringLiteral("{% if 1 < 2 %}yes{% else %}no{% endif %}") << dict
507 << QStringLiteral("yes") << NoError;
508
509 dict.clear();
510 QTest::newRow("if-tag-lt-02")
511 << QStringLiteral("{% if 1 < 1 %}yes{% else %}no{% endif %}") << dict
512 << QStringLiteral("no") << NoError;
513
514 dict.clear();
515 QTest::newRow("if-tag-lte-01")
516 << QStringLiteral("{% if 1 <= 1 %}yes{% else %}no{% endif %}") << dict
517 << QStringLiteral("yes") << NoError;
518
519 dict.clear();
520 QTest::newRow("if-tag-lte-02")
521 << QStringLiteral("{% if 2 <= 1 %}yes{% else %}no{% endif %}") << dict
522 << QStringLiteral("no") << NoError;
523
524 // Contains
525
526 dict.clear();
527 dict.insert(QStringLiteral("x"), QVariantList{1});
528 QTest::newRow("if-tag-in-01")
529 << QStringLiteral("{% if 1 in x %}yes{% else %}no{% endif %}") << dict
530 << QStringLiteral("yes") << NoError;
531
532 dict.clear();
533 dict.insert(QStringLiteral("x"), QVariantList{1});
534 QTest::newRow("if-tag-in-02")
535 << QStringLiteral("{% if 2 in x %}yes{% else %}no{% endif %}") << dict
536 << QStringLiteral("no") << NoError;
537
538 dict.clear();
539 dict.insert(QStringLiteral("x"), QVariantList{1});
540 QTest::newRow("if-tag-not-in-01")
541 << QStringLiteral("{% if 1 not in x %}yes{% else %}no{% endif %}") << dict
542 << QStringLiteral("no") << NoError;
543
544 dict.clear();
545 dict.insert(QStringLiteral("x"), QVariantList{1});
546 QTest::newRow("if-tag-not-in-02")
547 << QStringLiteral("{% if 2 not in x %}yes{% else %}no{% endif %}") << dict
548 << QStringLiteral("yes") << NoError;
549
550 // operator in with string
551 dict.clear();
552 dict.insert(QStringLiteral("colors"), QStringLiteral("green"));
553 QTest::newRow("if-tag-operator-in-string01")
554 << QStringLiteral(
555 "{% if \"green\" in colors %}yes{% else %}no{% endif %}")
556 << dict << QStringLiteral("yes") << NoError;
557
558 dict.clear();
559 dict.insert(QStringLiteral("colors"), QStringLiteral("red"));
560 QTest::newRow("if-tag-operator-in-string02")
561 << QStringLiteral(
562 "{% if \"green\" in colors %}yes{% else %}no{% endif %}")
563 << dict << QStringLiteral("no") << NoError;
564
565 dict.clear();
566 dict.insert(QStringLiteral("colors"), QStringLiteral("green"));
567 QTest::newRow("if-tag-operator-in-string03")
568 << QStringLiteral(
569 "{% if \"green\" in colors %}yes{% else %}no{% endif %}")
570 << dict << QStringLiteral("yes") << NoError;
571
572 dict.clear();
573 dict.insert(QStringLiteral("colors"), QStringLiteral("red"));
574 QTest::newRow("if-tag-operator-in-string04")
575 << QStringLiteral(
576 "{% if \"green\" in colors %}yes{% else %}no{% endif %}")
577 << dict << QStringLiteral("no") << NoError;
578
579 dict.clear();
580 dict.insert(QStringLiteral("color"), QStringLiteral("green"));
581 dict.insert(QStringLiteral("colors"), QStringLiteral("green"));
582 QTest::newRow("if-tag-operator-in-string05")
583 << QStringLiteral("{% if color in colors %}yes{% else %}no{% endif %}")
584 << dict << QStringLiteral("yes") << NoError;
585
586 dict.clear();
587 dict.insert(QStringLiteral("color"), QStringLiteral("green"));
588 dict.insert(QStringLiteral("colors"), QStringLiteral("red"));
589 QTest::newRow("if-tag-operator-in-string06")
590 << QStringLiteral("{% if color in colors %}yes{% else %}no{% endif %}")
591 << dict << QStringLiteral("no") << NoError;
592
593 // AND
594
595 dict.clear();
596 dict.insert(QStringLiteral("foo"), true);
597 dict.insert(QStringLiteral("bar"), true);
598 QTest::newRow("if-tag-and01")
599 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
600 << dict << QStringLiteral("yes") << NoError;
601
602 dict.clear();
603 dict.insert(QStringLiteral("foo"), true);
604 dict.insert(QStringLiteral("bar"), false);
605 QTest::newRow("if-tag-and02")
606 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
607 << dict << QStringLiteral("no") << NoError;
608
609 dict.clear();
610 dict.insert(QStringLiteral("foo"), false);
611 dict.insert(QStringLiteral("bar"), true);
612 QTest::newRow("if-tag-and03")
613 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
614 << dict << QStringLiteral("no") << NoError;
615
616 dict.clear();
617 dict.insert(QStringLiteral("foo"), false);
618 dict.insert(QStringLiteral("bar"), false);
619 QTest::newRow("if-tag-and04")
620 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
621 << dict << QStringLiteral("no") << NoError;
622
623 dict.clear();
624 dict.insert(QStringLiteral("foo"), false);
625 QTest::newRow("if-tag-and05")
626 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
627 << dict << QStringLiteral("no") << NoError;
628
629 dict.clear();
630 dict.insert(QStringLiteral("bar"), false);
631 QTest::newRow("if-tag-and06")
632 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
633 << dict << QStringLiteral("no") << NoError;
634
635 dict.clear();
636 dict.insert(QStringLiteral("foo"), true);
637 QTest::newRow("if-tag-and07")
638 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
639 << dict << QStringLiteral("no") << NoError;
640
641 dict.clear();
642 dict.insert(QStringLiteral("bar"), true);
643 QTest::newRow("if-tag-and08")
644 << QStringLiteral("{% if foo and bar %}yes{% else %}no{% endif %}")
645 << dict << QStringLiteral("no") << NoError;
646
647 // OR
648
649 dict.clear();
650 dict.insert(QStringLiteral("foo"), true);
651 dict.insert(QStringLiteral("bar"), true);
652 QTest::newRow("if-tag-or01")
653 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
654 << QStringLiteral("yes") << NoError;
655
656 dict.clear();
657 dict.insert(QStringLiteral("foo"), true);
658 dict.insert(QStringLiteral("bar"), false);
659 QTest::newRow("if-tag-or02")
660 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
661 << QStringLiteral("yes") << NoError;
662
663 dict.clear();
664 dict.insert(QStringLiteral("foo"), false);
665 dict.insert(QStringLiteral("bar"), true);
666 QTest::newRow("if-tag-or03")
667 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
668 << QStringLiteral("yes") << NoError;
669
670 dict.clear();
671 dict.insert(QStringLiteral("foo"), false);
672 dict.insert(QStringLiteral("bar"), false);
673 QTest::newRow("if-tag-or04")
674 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
675 << QStringLiteral("no") << NoError;
676
677 dict.clear();
678 dict.insert(QStringLiteral("foo"), false);
679 QTest::newRow("if-tag-or05")
680 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
681 << QStringLiteral("no") << NoError;
682
683 dict.clear();
684 dict.insert(QStringLiteral("bar"), false);
685 QTest::newRow("if-tag-or06")
686 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
687 << QStringLiteral("no") << NoError;
688
689 dict.clear();
690 dict.insert(QStringLiteral("foo"), true);
691 QTest::newRow("if-tag-or07")
692 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
693 << QStringLiteral("yes") << NoError;
694
695 dict.clear();
696 dict.insert(QStringLiteral("bar"), true);
697 QTest::newRow("if-tag-or08")
698 << QStringLiteral("{% if foo or bar %}yes{% else %}no{% endif %}") << dict
699 << QStringLiteral("yes") << NoError;
700
701 dict.clear();
702 dict.insert(QStringLiteral("baz"), true);
703 QTest::newRow("if-tag-or09")
704 << QStringLiteral("{% if foo or bar or baz %}yes{% else %}no{% endif %}")
705 << dict << QStringLiteral("yes") << NoError;
706
707 // NOT
708
709 dict.clear();
710 dict.insert(QStringLiteral("foo"), true);
711 QTest::newRow("if-tag-not01")
712 << QStringLiteral("{% if not foo %}no{% else %}yes{% endif %}") << dict
713 << QStringLiteral("yes") << NoError;
714
715 dict.insert(QStringLiteral("foo"), true);
716 QTest::newRow("if-tag-not02")
717 << QStringLiteral("{% if not not foo %}no{% else %}yes{% endif %}")
718 << dict << QStringLiteral("no") << NoError;
719
720 dict.clear();
721 QTest::newRow("if-tag-not06")
722 << QStringLiteral("{% if foo and not bar %}yes{% else %}no{% endif %}")
723 << dict << QStringLiteral("no") << NoError;
724
725 dict.clear();
726 dict.insert(QStringLiteral("foo"), true);
727 dict.insert(QStringLiteral("bar"), true);
728 QTest::newRow("if-tag-not07")
729 << QStringLiteral("{% if foo and not bar %}yes{% else %}no{% endif %}")
730 << dict << QStringLiteral("no") << NoError;
731
732 dict.clear();
733 dict.insert(QStringLiteral("foo"), true);
734 dict.insert(QStringLiteral("bar"), false);
735 QTest::newRow("if-tag-not08")
736 << QStringLiteral("{% if foo and not bar %}yes{% else %}no{% endif %}")
737 << dict << QStringLiteral("yes") << NoError;
738
739 dict.clear();
740 dict.insert(QStringLiteral("foo"), false);
741 dict.insert(QStringLiteral("bar"), true);
742 QTest::newRow("if-tag-not09")
743 << QStringLiteral("{% if foo and not bar %}yes{% else %}no{% endif %}")
744 << dict << QStringLiteral("no") << NoError;
745
746 dict.clear();
747 dict.insert(QStringLiteral("foo"), false);
748 dict.insert(QStringLiteral("bar"), false);
749 QTest::newRow("if-tag-not10")
750 << QStringLiteral("{% if foo and not bar %}yes{% else %}no{% endif %}")
751 << dict << QStringLiteral("no") << NoError;
752
753 dict.clear();
754 QTest::newRow("if-tag-not11")
755 << QStringLiteral("{% if not foo and bar %}yes{% else %}no{% endif %}")
756 << dict << QStringLiteral("no") << NoError;
757
758 dict.clear();
759 dict.insert(QStringLiteral("foo"), true);
760 dict.insert(QStringLiteral("bar"), true);
761 QTest::newRow("if-tag-not12")
762 << QStringLiteral("{% if not foo and bar %}yes{% else %}no{% endif %}")
763 << dict << QStringLiteral("no") << NoError;
764
765 dict.clear();
766 dict.insert(QStringLiteral("foo"), true);
767 dict.insert(QStringLiteral("bar"), false);
768 QTest::newRow("if-tag-not13")
769 << QStringLiteral("{% if not foo and bar %}yes{% else %}no{% endif %}")
770 << dict << QStringLiteral("no") << NoError;
771
772 dict.clear();
773 dict.insert(QStringLiteral("foo"), false);
774 dict.insert(QStringLiteral("bar"), true);
775 QTest::newRow("if-tag-not14")
776 << QStringLiteral("{% if not foo and bar %}yes{% else %}no{% endif %}")
777 << dict << QStringLiteral("yes") << NoError;
778
779 dict.clear();
780 dict.insert(QStringLiteral("foo"), false);
781 dict.insert(QStringLiteral("bar"), false);
782 QTest::newRow("if-tag-not15")
783 << QStringLiteral("{% if not foo and bar %}yes{% else %}no{% endif %}")
784 << dict << QStringLiteral("no") << NoError;
785
786 dict.clear();
787 QTest::newRow("if-tag-not16")
788 << QStringLiteral("{% if foo or not bar %}yes{% else %}no{% endif %}")
789 << dict << QStringLiteral("yes") << NoError;
790
791 dict.clear();
792 dict.insert(QStringLiteral("foo"), true);
793 dict.insert(QStringLiteral("bar"), true);
794 QTest::newRow("if-tag-not17")
795 << QStringLiteral("{% if foo or not bar %}yes{% else %}no{% endif %}")
796 << dict << QStringLiteral("yes") << NoError;
797
798 dict.clear();
799 dict.insert(QStringLiteral("foo"), true);
800 dict.insert(QStringLiteral("bar"), false);
801 QTest::newRow("if-tag-not18")
802 << QStringLiteral("{% if foo or not bar %}yes{% else %}no{% endif %}")
803 << dict << QStringLiteral("yes") << NoError;
804
805 dict.clear();
806 dict.insert(QStringLiteral("foo"), false);
807 dict.insert(QStringLiteral("bar"), true);
808 QTest::newRow("if-tag-not19")
809 << QStringLiteral("{% if foo or not bar %}yes{% else %}no{% endif %}")
810 << dict << QStringLiteral("no") << NoError;
811
812 dict.clear();
813 dict.insert(QStringLiteral("foo"), false);
814 dict.insert(QStringLiteral("bar"), false);
815 QTest::newRow("if-tag-not20")
816 << QStringLiteral("{% if foo or not bar %}yes{% else %}no{% endif %}")
817 << dict << QStringLiteral("yes") << NoError;
818
819 dict.clear();
820 QTest::newRow("if-tag-not21")
821 << QStringLiteral("{% if not foo or bar %}yes{% else %}no{% endif %}")
822 << dict << QStringLiteral("yes") << NoError;
823
824 dict.clear();
825 dict.insert(QStringLiteral("foo"), true);
826 dict.insert(QStringLiteral("bar"), true);
827 QTest::newRow("if-tag-not22")
828 << QStringLiteral("{% if not foo or bar %}yes{% else %}no{% endif %}")
829 << dict << QStringLiteral("yes") << NoError;
830
831 dict.clear();
832 dict.insert(QStringLiteral("foo"), true);
833 dict.insert(QStringLiteral("bar"), false);
834 QTest::newRow("if-tag-not23")
835 << QStringLiteral("{% if not foo or bar %}yes{% else %}no{% endif %}")
836 << dict << QStringLiteral("no") << NoError;
837
838 dict.clear();
839 dict.insert(QStringLiteral("foo"), false);
840 dict.insert(QStringLiteral("bar"), true);
841 QTest::newRow("if-tag-not24")
842 << QStringLiteral("{% if not foo or bar %}yes{% else %}no{% endif %}")
843 << dict << QStringLiteral("yes") << NoError;
844
845 dict.clear();
846 dict.insert(QStringLiteral("foo"), false);
847 dict.insert(QStringLiteral("bar"), false);
848 QTest::newRow("if-tag-not25")
849 << QStringLiteral("{% if not foo or bar %}yes{% else %}no{% endif %}")
850 << dict << QStringLiteral("yes") << NoError;
851
852 dict.clear();
853 QTest::newRow("if-tag-not26") << QStringLiteral(
854 "{% if not foo and not bar %}yes{% else %}no{% endif %}")
855 << dict << QStringLiteral("yes") << NoError;
856
857 dict.clear();
858 dict.insert(QStringLiteral("foo"), true);
859 dict.insert(QStringLiteral("bar"), true);
860 QTest::newRow("if-tag-not27") << QStringLiteral(
861 "{% if not foo and not bar %}yes{% else %}no{% endif %}")
862 << dict << QStringLiteral("no") << NoError;
863
864 dict.clear();
865 dict.insert(QStringLiteral("foo"), true);
866 dict.insert(QStringLiteral("bar"), false);
867 QTest::newRow("if-tag-not28") << QStringLiteral(
868 "{% if not foo and not bar %}yes{% else %}no{% endif %}")
869 << dict << QStringLiteral("no") << NoError;
870
871 dict.clear();
872 dict.insert(QStringLiteral("foo"), false);
873 dict.insert(QStringLiteral("bar"), true);
874 QTest::newRow("if-tag-not29") << QStringLiteral(
875 "{% if not foo and not bar %}yes{% else %}no{% endif %}")
876 << dict << QStringLiteral("no") << NoError;
877
878 dict.clear();
879 dict.insert(QStringLiteral("foo"), false);
880 dict.insert(QStringLiteral("bar"), false);
881 QTest::newRow("if-tag-not30") << QStringLiteral(
882 "{% if not foo and not bar %}yes{% else %}no{% endif %}")
883 << dict << QStringLiteral("yes") << NoError;
884
885 dict.clear();
886 QTest::newRow("if-tag-not31")
887 << QStringLiteral("{% if not foo or not bar %}yes{% else %}no{% endif %}")
888 << dict << QStringLiteral("yes") << NoError;
889
890 dict.clear();
891 dict.insert(QStringLiteral("foo"), true);
892 dict.insert(QStringLiteral("bar"), true);
893 QTest::newRow("if-tag-not32")
894 << QStringLiteral("{% if not foo or not bar %}yes{% else %}no{% endif %}")
895 << dict << QStringLiteral("no") << NoError;
896
897 dict.clear();
898 dict.insert(QStringLiteral("foo"), true);
899 dict.insert(QStringLiteral("bar"), false);
900 QTest::newRow("if-tag-not33")
901 << QStringLiteral("{% if not foo or not bar %}yes{% else %}no{% endif %}")
902 << dict << QStringLiteral("yes") << NoError;
903
904 dict.clear();
905 dict.insert(QStringLiteral("foo"), false);
906 dict.insert(QStringLiteral("bar"), true);
907 QTest::newRow("if-tag-not34")
908 << QStringLiteral("{% if not foo or not bar %}yes{% else %}no{% endif %}")
909 << dict << QStringLiteral("yes") << NoError;
910
911 dict.clear();
912 dict.insert(QStringLiteral("foo"), false);
913 dict.insert(QStringLiteral("bar"), false);
914 QTest::newRow("if-tag-not35")
915 << QStringLiteral("{% if not foo or not bar %}yes{% else %}no{% endif %}")
916 << dict << QStringLiteral("yes") << NoError;
917
918 QTest::newRow("if-tag-error01") << QStringLiteral("{% if %}yes{% endif %}")
919 << dict << QString() << TagSyntaxError;
920
921 dict.clear();
922 dict.insert(QStringLiteral("foo"), true);
923 QTest::newRow("if-tag-error02")
924 << QStringLiteral("{% if foo and %}yes{% else %}no{% endif %}") << dict
925 << QString() << TagSyntaxError;
926 QTest::newRow("if-tag-error03")
927 << QStringLiteral("{% if foo or %}yes{% else %}no{% endif %}") << dict
928 << QString() << TagSyntaxError;
929 QTest::newRow("if-tag-error04")
930 << QStringLiteral("{% if not foo and %}yes{% else %}no{% endif %}")
931 << dict << QString() << TagSyntaxError;
932 QTest::newRow("if-tag-error05")
933 << QStringLiteral("{% if not foo or %}yes{% else %}no{% endif %}") << dict
934 << QString() << TagSyntaxError;
935 QTest::newRow("if-tag-error06")
936 << QStringLiteral("{% if abc def %}yes{% endif %}") << dict << QString()
937 << TagSyntaxError;
938 QTest::newRow("if-tag-error07")
939 << QStringLiteral("{% if not %}yes{% endif %}") << dict << QString()
940 << TagSyntaxError;
941 QTest::newRow("if-tag-error08")
942 << QStringLiteral("{% if and %}yes{% endif %}") << dict << QString()
943 << TagSyntaxError;
944 QTest::newRow("if-tag-error09") << QStringLiteral("{% if or %}yes{% endif %}")
945 << dict << QString() << TagSyntaxError;
946 QTest::newRow("if-tag-error10") << QStringLiteral("{% if == %}yes{% endif %}")
947 << dict << QString() << TagSyntaxError;
948 QTest::newRow("if-tag-error11")
949 << QStringLiteral("{% if 1 == %}yes{% endif %}") << dict << QString()
950 << TagSyntaxError;
951 QTest::newRow("if-tag-error12")
952 << QStringLiteral("{% if a not b %}yes{% endif %}") << dict << QString()
953 << TagSyntaxError;
954
955 // Short circuit
956 dict.clear();
957 {
958 auto bio = QSharedPointer<BadIfObject>(new BadIfObject);
959 dict.insert(QStringLiteral("x"), QVariant::fromValue(bio));
960 QTest::newRow("if-tag-shortcircuit01")
961 << QStringLiteral(
962 "{% if x.isTrue or x.isBad %}yes{% else %}no{% endif %}")
963 << dict << QStringLiteral("yes") << NoError;
964
965 QTest::newRow("if-tag-shortcircuit02")
966 << QStringLiteral(
967 "{% if x.isFalse and x.isBad %}yes{% else %}no{% endif %}")
968 << dict << QStringLiteral("no") << NoError;
969 dict.clear();
970 }
971
972 QTest::newRow("if-tag-badarg01")
973 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
974 << QString() << NoError;
975
976 dict.clear();
977 dict.insert(QStringLiteral("y"), 0);
978 QTest::newRow("if-tag-badarg02")
979 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
980 << QString() << NoError;
981
982 dict.clear();
983 dict.insert(QStringLiteral("y"), 1);
984 QTest::newRow("if-tag-badarg03")
985 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
986 << QStringLiteral("yes") << NoError;
987
988 dict.clear();
989 QTest::newRow("if-tag-badarg04") << QStringLiteral(
990 "{% if x|default_if_none:y %}yes{% else %}no{% endif %}")
991 << dict << QStringLiteral("no") << NoError;
992
993 dict.clear();
994 dict.insert(QStringLiteral("foo"), 1);
995 QTest::newRow("if-tag-single-eq")
996 << QStringLiteral("{% if foo = bar %}yes{% else %}no{% endif %}") << dict
997 << QString() << TagSyntaxError;
998
999 // Truthiness
1000 dict.clear();
1001 QVariantHash hash;
1002 dict.insert(QStringLiteral("var"), hash);
1003 QTest::newRow("if-truthiness01")
1004 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1005 << QStringLiteral("No") << NoError;
1006 hash.insert(QStringLiteral("foo"), QStringLiteral("bar"));
1007 dict.insert(QStringLiteral("var"), hash);
1008 QTest::newRow("if-truthiness02")
1009 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1010 << QStringLiteral("Yes") << NoError;
1011 QVariantList list;
1012 dict.insert(QStringLiteral("var"), list);
1013 QTest::newRow("if-truthiness03")
1014 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1015 << QStringLiteral("No") << NoError;
1016 list.append(QStringLiteral("foo"));
1017 dict.insert(QStringLiteral("var"), list);
1018 QTest::newRow("if-truthiness04")
1019 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1020 << QStringLiteral("Yes") << NoError;
1021
1022 QVariant var;
1023 dict.insert(QStringLiteral("var"), var);
1024 QTest::newRow("if-truthiness05")
1025 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1026 << QStringLiteral("No") << NoError;
1027 var = QStringLiteral("foo");
1028 dict.insert(QStringLiteral("var"), var);
1029 QTest::newRow("if-truthiness06")
1030 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1031 << QStringLiteral("Yes") << NoError;
1032
1033 QString str;
1034 dict.insert(QStringLiteral("var"), str);
1035 QTest::newRow("if-truthiness07")
1036 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1037 << QStringLiteral("No") << NoError;
1038 str = QStringLiteral("foo");
1039 dict.insert(QStringLiteral("var"), str);
1040 QTest::newRow("if-truthiness08")
1041 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1042 << QStringLiteral("Yes") << NoError;
1043
1044 auto i = 0;
1045 dict.insert(QStringLiteral("var"), i);
1046 QTest::newRow("if-truthiness07")
1047 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1048 << QStringLiteral("No") << NoError;
1049 i = 7;
1050 dict.insert(QStringLiteral("var"), i);
1051 QTest::newRow("if-truthiness08")
1052 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1053 << QStringLiteral("Yes") << NoError;
1054
1055 auto r = 0.0;
1056 dict.insert(QStringLiteral("var"), r);
1057 QTest::newRow("if-truthiness09")
1058 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1059 << QStringLiteral("No") << NoError;
1060 r = 7.1;
1061 dict.insert(QStringLiteral("var"), r);
1062 QTest::newRow("if-truthiness10")
1063 << QStringLiteral("{% if var %}Yes{% else %}No{% endif %}") << dict
1064 << QStringLiteral("Yes") << NoError;
1065
1066 dict.clear();
1067 QTest::newRow("if-tag-badarg01")
1068 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
1069 << QString() << NoError;
1070
1071 dict.insert(QStringLiteral("y"), 0);
1072
1073 QTest::newRow("if-tag-badarg02")
1074 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
1075 << QString() << NoError;
1076
1077 dict.clear();
1078 dict.insert(QStringLiteral("y"), 1);
1079
1080 QTest::newRow("if-tag-badarg03")
1081 << QStringLiteral("{% if x|default_if_none:y %}yes{% endif %}") << dict
1082 << QStringLiteral("yes") << NoError;
1083
1084 dict.clear();
1085 QTest::newRow("if-tag-badarg04") << QStringLiteral(
1086 "{% if x|default_if_none:y %}yes{% else %}no{% endif %}")
1087 << dict << QStringLiteral("no") << NoError;
1088}
1089
1090void TestDefaultTags::testForTag_data()
1091{
1092 QTest::addColumn<QString>("input");
1093 QTest::addColumn<Dict>("dict");
1094 QTest::addColumn<QString>("output");
1095 QTest::addColumn<Cutelee::Error>("error");
1096
1097 Dict dict;
1098
1099 QVariantList list{1, 2, 3};
1100 dict.insert(QStringLiteral("values"), list);
1101 QTest::newRow("for-tag01")
1102 << QStringLiteral("{% for val in values %}{{ val }}{% endfor %}") << dict
1103 << QStringLiteral("123") << NoError;
1104 QTest::newRow("for-tag02")
1105 << QStringLiteral("{% for val in values reversed %}{{ val }}{% endfor %}")
1106 << dict << QStringLiteral("321") << NoError;
1107 list.clear();
1108 dict.insert(QStringLiteral("values"), list);
1109 QTest::newRow("for-tag03") << QStringLiteral(
1110 "{% for val in values %}({{ val }} sdfsdf,){% endfor %}")
1111 << dict << QString() << NoError;
1112 QStringList emails{QStringLiteral("one"), QStringLiteral("two")};
1113 QVariantHash obj;
1114 obj.insert(QStringLiteral("emails"), emails);
1115 dict.insert(QStringLiteral("contact"), obj);
1116 QTest::newRow("for-tag04")
1117 << QStringLiteral(
1118 "{% for val in contact.emails %}({{ val }},){% endfor %}")
1119 << dict << QStringLiteral("(one,)(two,)") << NoError;
1120 emails.clear();
1121 obj.insert(QStringLiteral("emails"), emails);
1122 dict.insert(QStringLiteral("contact"), obj);
1123 QTest::newRow("for-tag05") << QStringLiteral(
1124 "{% for val in contact.emails %}({{ val }},){% endfor %}")
1125 << dict << QString() << NoError;
1126 list.clear();
1127 dict.clear();
1128 emails << QStringLiteral("one");
1129 dict.insert(QStringLiteral("emails"), emails);
1130 QTest::newRow("for-tag06")
1131 << QStringLiteral("{% for val in emails %}({{ val }},){% endfor %}")
1132 << dict << QStringLiteral("(one,)") << NoError;
1133 list.clear();
1134 dict.clear();
1135
1136 QTest::newRow("for-tag07") << QStringLiteral("{% for %}{% endfor %}") << dict
1137 << QString() << TagSyntaxError;
1138 QTest::newRow("for-tag08")
1139 << QStringLiteral("{% for foo bar bat %}{% endfor %}") << dict
1140 << QString() << TagSyntaxError;
1141 QTest::newRow("for-tag09")
1142 << QStringLiteral("{% for foo bar '' %}{% endfor %}") << dict << QString()
1143 << TagSyntaxError;
1144
1145 list << 1 << 2 << 3;
1146 dict.insert(QStringLiteral("values"), list);
1147 QTest::newRow("for-tag-vars01") << QStringLiteral(
1148 "{% for val in values %}{{ forloop.counter }}{% endfor %}")
1149 << dict << QStringLiteral("123") << NoError;
1150 QTest::newRow("for-tag-vars02") << QStringLiteral(
1151 "{% for val in values %}{{ forloop.counter0 }}{% endfor %}")
1152 << dict << QStringLiteral("012") << NoError;
1153 QTest::newRow("for-tag-vars03") << QStringLiteral(
1154 "{% for val in values %}{{ forloop.revcounter }}{% endfor %}")
1155 << dict << QStringLiteral("321") << NoError;
1156 QTest::newRow("for-tag-vars04") << QStringLiteral(
1157 "{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}")
1158 << dict << QStringLiteral("210") << NoError;
1159 QTest::newRow("for-tag-vars05")
1160 << QStringLiteral("{% for val in values %}{% if forloop.first %}f{% else "
1161 "%}x{% endif %}{% endfor %}")
1162 << dict << QStringLiteral("fxx") << NoError;
1163 QTest::newRow("for-tag-vars06")
1164 << QStringLiteral("{% for val in values %}{% if forloop.last %}l{% else "
1165 "%}x{% endif %}{% endfor %}")
1166 << dict << QStringLiteral("xxl") << NoError;
1167
1168 dict.clear();
1169 list.clear();
1170 QVariantList innerList{QStringLiteral("one"), 1};
1171 list.append(QVariant(innerList));
1172 innerList.clear();
1173 innerList << QStringLiteral("two") << 2;
1174 list.append(QVariant(innerList));
1175 dict.insert(QStringLiteral("items"), list);
1176 QTest::newRow("for-tag-unpack01")
1177 << QStringLiteral(
1178 "{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}")
1179 << dict << QStringLiteral("one:1/two:2/") << NoError;
1180
1181 QTest::newRow("for-tag-unpack03")
1182 << QStringLiteral(
1183 "{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}")
1184 << dict << QStringLiteral("one:1/two:2/") << NoError;
1185 QTest::newRow("for-tag-unpack04")
1186 << QStringLiteral(
1187 "{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}")
1188 << dict << QStringLiteral("one:1/two:2/") << NoError;
1189 QTest::newRow("for-tag-unpack05")
1190 << QStringLiteral(
1191 "{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}")
1192 << dict << QStringLiteral("one:1/two:2/") << NoError;
1193 QTest::newRow("for-tag-unpack06")
1194 << QStringLiteral(
1195 "{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}")
1196 << dict << QStringLiteral("one:1/two:2/") << NoError;
1197 QTest::newRow("for-tag-unpack07")
1198 << QStringLiteral(
1199 "{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}")
1200 << dict << QStringLiteral("one:1/two:2/") << NoError;
1201 QTest::newRow("for-tag-unpack08")
1202 << QStringLiteral(
1203 "{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}")
1204 << dict << QStringLiteral("one:1/two:2/") << NoError;
1205
1206 // Ensure that a single loopvar doesn't truncate the list in val.
1207 QTest::newRow("for-tag-unpack09")
1208 << QStringLiteral(
1209 "{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}")
1210 << dict << QStringLiteral("one:1/two:2/") << NoError;
1211
1212 // Otherwise, silently truncate if the length of loopvars differs to the
1213 // length of each set of items.
1214
1215 dict.clear();
1216 list.clear();
1217 innerList.clear();
1218 innerList << QStringLiteral("one") << 1 << QStringLiteral("carrot");
1219 list.append(QVariant(innerList));
1220 innerList.clear();
1221 innerList << QStringLiteral("two") << 2 << QStringLiteral("orange");
1222 list.append(QVariant(innerList));
1223 dict.insert(QStringLiteral("items"), list);
1224
1225 QTest::newRow("for-tag-unpack10")
1226 << QStringLiteral("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}")
1227 << dict << QStringLiteral("one:1/two:2/") << NoError;
1228
1229 dict.clear();
1230 list.clear();
1231 innerList.clear();
1232 innerList << QStringLiteral("one") << 1;
1233 list.append(QVariant(innerList));
1234 innerList.clear();
1235 innerList << QStringLiteral("two") << 2;
1236 list.append(QVariant(innerList));
1237 dict.insert(QStringLiteral("items"), list);
1238
1239 QTest::newRow("for-tag-unpack11")
1240 << QStringLiteral(
1241 "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}")
1242 << dict << QStringLiteral("one:1,/two:2,/") << NoError;
1243
1244 dict.clear();
1245 list.clear();
1246 innerList.clear();
1247 innerList << QStringLiteral("one") << 1 << QStringLiteral("carrot");
1248 list.append(QVariant(innerList));
1249 innerList.clear();
1250 innerList << QStringLiteral("two") << 2;
1251 list.append(QVariant(innerList));
1252 dict.insert(QStringLiteral("items"), list);
1253
1254 QTest::newRow("for-tag-unpack12")
1255 << QStringLiteral(
1256 "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}")
1257 << dict << QStringLiteral("one:1,carrot/two:2,/") << NoError;
1258
1259 dict.clear();
1260 list.clear();
1261 innerList.clear();
1262 innerList << QStringLiteral("one") << 1 << QStringLiteral("carrot");
1263 list.append(QVariant(innerList));
1264 innerList.clear();
1265 innerList << QStringLiteral("two") << 2 << QStringLiteral("cheese");
1266 list.append(QVariant(innerList));
1267
1268 dict.insert(QStringLiteral("items"), list);
1269
1270 QTest::newRow("for-tag-unpack13")
1271 << QStringLiteral(
1272 "{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}")
1273 << dict << QStringLiteral("one:1,carrot/two:2,cheese/") << NoError;
1274
1275 // Empty tag:
1276
1277 dict.clear();
1278 dict.insert(QStringLiteral("values"), QVariantList{1, 2, 3});
1279 QTest::newRow("for-tag-empty01") << QStringLiteral(
1280 "{% for val in values %}{{ val }}{% empty %}empty text{% endfor %}")
1281 << dict << QStringLiteral("123") << NoError;
1282
1283 dict.clear();
1284 dict.insert(QStringLiteral("values"), QVariantList());
1285 QTest::newRow("for-tag-empty02")
1286 << QStringLiteral("{% for val in values %}{{ val }}{% empty %}values "
1287 "array empty{% endfor %}")
1288 << dict << QStringLiteral("values array empty") << NoError;
1289
1290 dict.clear();
1291 QTest::newRow("for-tag-empty03")
1292 << QStringLiteral("{% for val in values %}{{ val }}{% empty %}values "
1293 "array not found{% endfor %}")
1294 << dict << QStringLiteral("values array not found") << NoError;
1295}
1296
1297void TestDefaultTags::testIfEqualTag_data()
1298{
1299 QTest::addColumn<QString>("input");
1300 QTest::addColumn<Dict>("dict");
1301 QTest::addColumn<QString>("output");
1302 QTest::addColumn<Cutelee::Error>("error");
1303
1304 Dict dict;
1305
1306 dict.insert(QStringLiteral("a"), 1);
1307 dict.insert(QStringLiteral("b"), 2);
1308
1309 QTest::newRow("ifequal01")
1310 << QStringLiteral("{% ifequal a b %}yes{% endifequal %}") << dict
1311 << QString() << NoError;
1312 QTest::newRow("ifequal03")
1313 << QStringLiteral("{% ifequal a b %}yes{% else %}no{% endifequal %}")
1314 << dict << QStringLiteral("no") << NoError;
1315
1316 dict.clear();
1317 dict.insert(QStringLiteral("a"), 1);
1318 dict.insert(QStringLiteral("b"), 1);
1319
1320 QTest::newRow("ifequal02")
1321 << QStringLiteral("{% ifequal a b %}yes{% endifequal %}") << dict
1322 << QStringLiteral("yes") << NoError;
1323 QTest::newRow("ifequal04")
1324 << QStringLiteral("{% ifequal a b %}yes{% else %}no{% endifequal %}")
1325 << dict << QStringLiteral("yes") << NoError;
1326
1327 dict.clear();
1328 dict.insert(QStringLiteral("a"), QStringLiteral("test"));
1329
1330 QTest::newRow("ifequal05")
1331 << QStringLiteral("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}")
1332 << dict << QStringLiteral("yes") << NoError;
1333
1334 dict.clear();
1335 dict.insert(QStringLiteral("a"), QStringLiteral("no"));
1336
1337 QTest::newRow("ifequal06")
1338 << QStringLiteral("{% ifequal a 'test' %}yes{% else %}no{% endifequal %}")
1339 << dict << QStringLiteral("no") << NoError;
1340
1341 dict.clear();
1342 dict.insert(QStringLiteral("a"), QStringLiteral("test"));
1343
1344 QTest::newRow("ifequal07")
1345 << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict
1346 << QStringLiteral("yes") << NoError;
1347
1348 dict.clear();
1349 dict.insert(QStringLiteral("a"), QStringLiteral("no"));
1350
1351 QTest::newRow("ifequal08")
1352 << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict
1353 << QStringLiteral("no") << NoError;
1354
1355 dict.clear();
1356
1357 QTest::newRow("ifequal09")
1358 << "{% ifequal a \"test\" %}yes{% else %}no{% endifequal %}" << dict
1359 << QStringLiteral("no") << NoError;
1360
1361 QTest::newRow("ifequal10")
1362 << QStringLiteral("{% ifequal a b %}yes{% else %}no{% endifequal %}")
1363 << dict << QStringLiteral("yes") << NoError;
1364
1365 QTest::newRow("ifequal-split01")
1366 << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict
1367 << QStringLiteral("no") << NoError;
1368
1369 dict.insert(QStringLiteral("a"), QStringLiteral("foo"));
1370 QTest::newRow("ifequal-split02")
1371 << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict
1372 << QStringLiteral("no") << NoError;
1373
1374 dict.clear();
1375 dict.insert(QStringLiteral("a"), QStringLiteral("test man"));
1376 QTest::newRow("ifequal-split03")
1377 << "{% ifequal a \"test man\" %}yes{% else %}no{% endifequal %}" << dict
1378 << QStringLiteral("yes") << NoError;
1379 QTest::newRow("ifequal-split04") << QStringLiteral(
1380 "{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}")
1381 << dict << QStringLiteral("yes") << NoError;
1382
1383 dict.clear();
1384 dict.insert(QStringLiteral("a"), QStringLiteral(""));
1385 QTest::newRow("ifequal-split05")
1386 << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}"
1387 << dict << QStringLiteral("no") << NoError;
1388
1389 dict.clear();
1390 dict.insert(QStringLiteral("a"), QStringLiteral("i \"love\" you"));
1391 QTest::newRow("ifequal-split06")
1392 << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}"
1393 << dict << QStringLiteral("yes") << NoError;
1394
1395 dict.clear();
1396 dict.insert(QStringLiteral("a"), QStringLiteral("i love you"));
1397 QTest::newRow("ifequal-split07")
1398 << "{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}"
1399 << dict << QStringLiteral("no") << NoError;
1400
1401 dict.clear();
1402 dict.insert(QStringLiteral("a"), QStringLiteral("I'm happy"));
1403 QTest::newRow("ifequal-split08")
1404 << "{% ifequal a 'I\\'m happy' %}yes{% else %}no{% endifequal %}" << dict
1405 << QStringLiteral("yes") << NoError;
1406
1407 dict.clear();
1408 dict.insert(QStringLiteral("a"), QStringLiteral("slash\\man"));
1409 QTest::newRow("ifequal-split09")
1410 << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict
1411 << QStringLiteral("yes") << NoError;
1412
1413 dict.clear();
1414 dict.insert(QStringLiteral("a"), QStringLiteral("slashman"));
1415 QTest::newRow("ifequal-split10")
1416 << "{% ifequal a 'slash\\man' %}yes{% else %}no{% endifequal %}" << dict
1417 << QStringLiteral("no") << NoError;
1418 // NUMERIC RESOLUTION
1419
1420 dict.clear();
1421 dict.insert(QStringLiteral("x"), QStringLiteral("5"));
1422
1423 QTest::newRow("ifequal-numeric01")
1424 << QStringLiteral("{% ifequal x 5 %}yes{% endifequal %}") << dict
1425 << QString() << NoError;
1426
1427 dict.clear();
1428 dict.insert(QStringLiteral("x"), 5);
1429 QTest::newRow("ifequal-numeric02")
1430 << QStringLiteral("{% ifequal x 5 %}yes{% endifequal %}") << dict
1431 << QStringLiteral("yes") << NoError;
1432
1433 dict.clear();
1434 dict.insert(QStringLiteral("x"), 5.2);
1435 QTest::newRow("ifequal-numeric03")
1436 << QStringLiteral("{% ifequal x 5 %}yes{% endifequal %}") << dict
1437 << QString() << NoError;
1438 QTest::newRow("ifequal-numeric04")
1439 << QStringLiteral("{% ifequal x 5.2 %}yes{% endifequal %}") << dict
1440 << QStringLiteral("yes") << NoError;
1441
1442 dict.clear();
1443 dict.insert(QStringLiteral("x"), .2);
1444
1445 QTest::newRow("ifequal-numeric05")
1446 << QStringLiteral("{% ifequal x 0.2 %}yes{% endifequal %}") << dict
1447 << QStringLiteral("yes") << NoError;
1448 QTest::newRow("ifequal-numeric06")
1449 << QStringLiteral("{% ifequal x .2 %}yes{% endifequal %}") << dict
1450 << QStringLiteral("yes") << NoError;
1451
1452 dict.clear();
1453 dict.insert(QStringLiteral("x"), 2);
1454
1455 QTest::newRow("ifequal-numeric07")
1456 << QStringLiteral("{% ifequal x 2. %}yes{% endifequal %}") << dict
1457 << QString() << TagSyntaxError;
1458
1459 dict.clear();
1460 dict.insert(QStringLiteral("x"), 5);
1461 QTest::newRow("ifequal-numeric08")
1462 << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict << QString()
1463 << NoError;
1464
1465 dict.clear();
1466 dict.insert(QStringLiteral("x"), QStringLiteral("5"));
1467 QTest::newRow("ifequal-numeric09")
1468 << "{% ifequal x \"5\" %}yes{% endifequal %}" << dict
1469 << QStringLiteral("yes") << NoError;
1470
1471 dict.clear();
1472 dict.insert(QStringLiteral("x"), -5);
1473 QTest::newRow("ifequal-numeric10")
1474 << QStringLiteral("{% ifequal x -5 %}yes{% endifequal %}") << dict
1475 << QStringLiteral("yes") << NoError;
1476
1477 dict.clear();
1478 dict.insert(QStringLiteral("x"), -5.2);
1479 QTest::newRow("ifequal-numeric11")
1480 << QStringLiteral("{% ifequal x -5.2 %}yes{% endifequal %}") << dict
1481 << QStringLiteral("yes") << NoError;
1482
1483 dict.clear();
1484 dict.insert(QStringLiteral("x"), 5);
1485 QTest::newRow("ifequal-numeric12")
1486 << QStringLiteral("{% ifequal x +5 %}yes{% endifequal %}") << dict
1487 << QStringLiteral("yes") << NoError;
1488
1489 // FILTER EXPRESSIONS AS ARGUMENTS
1490
1491 dict.clear();
1492 dict.insert(QStringLiteral("a"), QStringLiteral("a"));
1493 QTest::newRow("ifequal-filter01")
1494 << "{% ifequal a|upper \"A\" %}x{% endifequal %}" << dict
1495 << QStringLiteral("x") << NoError;
1496
1497 QTest::newRow("ifequal-filter02")
1498 << "{% ifequal \"A\" a|upper %}x{% endifequal %}" << dict
1499 << QStringLiteral("x") << NoError;
1500
1501 dict.clear();
1502 dict.insert(QStringLiteral("a"), QStringLiteral("x"));
1503 dict.insert(QStringLiteral("b"), QStringLiteral("X"));
1504
1505 QTest::newRow("ifequal-filter03")
1506 << QStringLiteral("{% ifequal a|upper b|upper %}x{% endifequal %}")
1507 << dict << QStringLiteral("x") << NoError;
1508
1509 dict.clear();
1510 dict.insert(QStringLiteral("x"), QStringLiteral("aaa"));
1511
1512 QTest::newRow("ifequal-filter04")
1513 << "{% ifequal x|slice:\"1\" \"a\" %}x{% endifequal %}" << dict
1514 << QStringLiteral("x") << NoError;
1515
1516 dict.clear();
1517 dict.insert(QStringLiteral("x"), QStringLiteral("aaa"));
1518
1519 QTest::newRow("ifequal-filter05")
1520 << "{% ifequal x|slice:\"1\"|upper \"A\" %}x{% endifequal %}" << dict
1521 << QStringLiteral("x") << NoError;
1522
1523 QTest::newRow("ifequal-error01")
1524 << "{% ifequal x|slice:\"1\"|upper %}x{% endifequal %}" << dict
1525 << QString() << TagSyntaxError;
1526}
1527
1528void TestDefaultTags::testIfNotEqualTag_data()
1529{
1530 QTest::addColumn<QString>("input");
1531 QTest::addColumn<Dict>("dict");
1532 QTest::addColumn<QString>("output");
1533 QTest::addColumn<Cutelee::Error>("error");
1534
1535 Dict dict;
1536
1537 dict.insert(QStringLiteral("a"), 1);
1538 dict.insert(QStringLiteral("b"), 2);
1539
1540 QTest::newRow("ifnotequal01")
1541 << QStringLiteral("{% ifnotequal a b %}yes{% endifnotequal %}") << dict
1542 << QStringLiteral("yes") << NoError;
1543 QTest::newRow("ifnotequal03") << QStringLiteral(
1544 "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}")
1545 << dict << QStringLiteral("yes") << NoError;
1546
1547 dict.clear();
1548 dict.insert(QStringLiteral("a"), 1);
1549 dict.insert(QStringLiteral("b"), 1);
1550
1551 QTest::newRow("ifnotequal02")
1552 << QStringLiteral("{% ifnotequal a b %}yes{% endifnotequal %}") << dict
1553 << QString() << NoError;
1554 QTest::newRow("ifnotequal04") << QStringLiteral(
1555 "{% ifnotequal a b %}yes{% else %}no{% endifnotequal %}")
1556 << dict << QStringLiteral("no") << NoError;
1557}
1558
1559void TestDefaultTags::testTemplateTagTag_data()
1560{
1561 QTest::addColumn<QString>("input");
1562 QTest::addColumn<Dict>("dict");
1563 QTest::addColumn<QString>("output");
1564 QTest::addColumn<Cutelee::Error>("error");
1565
1566 Dict dict;
1567
1568 QTest::newRow("templatetag01")
1569 << QStringLiteral("{% templatetag openblock %}") << dict
1570 << QStringLiteral("{%") << NoError;
1571 QTest::newRow("templatetag02")
1572 << QStringLiteral("{% templatetag closeblock %}") << dict
1573 << QStringLiteral("%}") << NoError;
1574 QTest::newRow("templatetag03")
1575 << QStringLiteral("{% templatetag openvariable %}") << dict
1576 << QStringLiteral("{{") << NoError;
1577 QTest::newRow("templatetag04")
1578 << QStringLiteral("{% templatetag closevariable %}") << dict
1579 << QStringLiteral("}}") << NoError;
1580 QTest::newRow("templatetag05") << QStringLiteral("{% templatetag %}") << dict
1581 << QString() << TagSyntaxError;
1582 QTest::newRow("templatetag06") << QStringLiteral("{% templatetag foo %}")
1583 << dict << QString() << TagSyntaxError;
1584 QTest::newRow("templatetag07")
1585 << QStringLiteral("{% templatetag openbrace %}") << dict
1586 << QStringLiteral("{") << NoError;
1587 QTest::newRow("templatetag08")
1588 << QStringLiteral("{% templatetag closebrace %}") << dict
1589 << QStringLiteral("}") << NoError;
1590 QTest::newRow("templatetag09") << QStringLiteral(
1591 "{% templatetag openbrace %}{% templatetag openbrace %}")
1592 << dict << QStringLiteral("{{") << NoError;
1593 QTest::newRow("templatetag10") << QStringLiteral(
1594 "{% templatetag closebrace %}{% templatetag closebrace %}")
1595 << dict << QStringLiteral("}}") << NoError;
1596 QTest::newRow("templatetag11")
1597 << QStringLiteral("{% templatetag opencomment %}") << dict
1598 << QStringLiteral("{#") << NoError;
1599 QTest::newRow("templatetag12")
1600 << QStringLiteral("{% templatetag closecomment %}") << dict
1601 << QStringLiteral("#}") << NoError;
1602}
1603
1604void TestDefaultTags::testWithTag_data()
1605{
1606 QTest::addColumn<QString>("input");
1607 QTest::addColumn<Dict>("dict");
1608 QTest::addColumn<QString>("output");
1609 QTest::addColumn<Cutelee::Error>("error");
1610
1611 Dict dict;
1612
1613 QVariantHash hash;
1614 hash.insert(QStringLiteral("key"), 50);
1615 dict.insert(QStringLiteral("dict"), hash);
1616 QTest::newRow("with01") << QStringLiteral(
1617 "{% with dict.key as key %}{{ key }}{% endwith %}")
1618 << dict << QStringLiteral("50") << NoError;
1619 QTest::newRow("with02") << QStringLiteral(
1620 "{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% "
1621 "endwith %}{{ key }}")
1622 << dict << QStringLiteral("50-50-50") << NoError;
1623 QTest::newRow("with03") << QStringLiteral(
1624 "{{ key }}{% with key=dict.key %}{{ key }}-{{ dict.key }}-{{ key }}{% "
1625 "endwith %}{{ key }}")
1626 << dict << QStringLiteral("50-50-50") << NoError;
1627 QTest::newRow("with04") << QStringLiteral(
1628 "{{ key1 }}{% with key1=dict.key key2=dict.key key3=dict.key %}{{ key1 }}-{{ dict.key }}-{{ key3 }}{% "
1629 "endwith %}{{ key }}")
1630 << dict << QStringLiteral("50-50-50") << NoError;
1631 QTest::newRow("with-error01")
1632 << QStringLiteral("{% with dict.key xx key %}{{ key }}{% endwith %}")
1633 << dict << QString() << TagSyntaxError;
1634 QTest::newRow("with-error02")
1635 << QStringLiteral("{% with dict.key as %}{{ key }}{% endwith %}") << dict
1636 << QString() << TagSyntaxError;
1637}
1638
1639void TestDefaultTags::testCycleTag_data()
1640{
1641 QTest::addColumn<QString>("input");
1642 QTest::addColumn<Dict>("dict");
1643 QTest::addColumn<QString>("output");
1644 QTest::addColumn<Cutelee::Error>("error");
1645
1646 Dict dict;
1647
1648 QTest::newRow("cycle01") << QStringLiteral("{% cycle a %}") << dict
1649 << QString() << TagSyntaxError;
1650 QTest::newRow("cycle02") << QStringLiteral(
1651 "{% cycle a,b,c as abc %}{% cycle abc %}")
1652 << dict << QStringLiteral("ab") << NoError;
1653 QTest::newRow("cycle03") << QStringLiteral(
1654 "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}")
1655 << dict << QStringLiteral("abc") << NoError;
1656 QTest::newRow("cycle04") << QStringLiteral(
1657 "{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}")
1658 << dict << QStringLiteral("abca") << NoError;
1659 QTest::newRow("cycle05") << QStringLiteral("{% cycle a %}") << dict
1660 << QString() << TagSyntaxError;
1661 // TODO: This is the same as cycle01. Remove.
1662 QTest::newRow("cycle06") << QStringLiteral("{% cycle a %}") << dict
1663 << QString() << TagSyntaxError;
1664 QTest::newRow("cycle07") << QStringLiteral(
1665 "{% cycle a,b,c as foo %}{% cycle bar %}")
1666 << dict << QString() << TagSyntaxError;
1667 QTest::newRow("cycle08") << QStringLiteral(
1668 "{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo "
1669 "%}{{ foo }}") << dict
1670 << QStringLiteral("abbbcc") << NoError;
1671
1672 dict.insert(QStringLiteral("test"), QVariantList{0, 1, 2, 3, 4});
1673 QTest::newRow("cycle09") << QStringLiteral(
1674 "{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}")
1675 << dict << QStringLiteral("a0,b1,a2,b3,a4,")
1676 << NoError;
1677
1678 dict.clear();
1679 QTest::newRow("cycle10") << QStringLiteral(
1680 "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}")
1681 << dict << QStringLiteral("ab") << NoError;
1682 QTest::newRow("cycle11") << QStringLiteral(
1683 "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}")
1684 << dict << QStringLiteral("abc") << NoError;
1685 QTest::newRow("cycle12") << QStringLiteral(
1686 "{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle "
1687 "abc %}") << dict << QStringLiteral("abca")
1688 << NoError;
1689
1690 dict.insert(QStringLiteral("test"), QVariantList{0, 1, 2, 3, 4});
1691 QTest::newRow("cycle13") << QStringLiteral(
1692 "{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}")
1693 << dict << QStringLiteral("a0,b1,a2,b3,a4,")
1694 << NoError;
1695
1696 dict.clear();
1697 dict.insert(QStringLiteral("one"), QStringLiteral("1"));
1698 dict.insert(QStringLiteral("two"), QStringLiteral("2"));
1699 QTest::newRow("cycle14") << QStringLiteral(
1700 "{% cycle one two as foo %}{% cycle foo %}")
1701 << dict << QStringLiteral("12") << NoError;
1702
1703 dict.clear();
1704 dict.insert(QStringLiteral("test"), QVariantList{0, 1, 2, 3, 4});
1705 dict.insert(QStringLiteral("aye"), QStringLiteral("a"));
1706 dict.insert(QStringLiteral("bee"), QStringLiteral("b"));
1707 QTest::newRow("cycle15") << QStringLiteral(
1708 "{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}")
1709 << dict << QStringLiteral("a0,b1,a2,b3,a4,")
1710 << NoError;
1711
1712 dict.clear();
1713 dict.insert(QStringLiteral("one"), QStringLiteral("A"));
1714 dict.insert(QStringLiteral("two"), QStringLiteral("2"));
1715 QTest::newRow("cycle16") << QStringLiteral(
1716 "{% cycle one|lower two as foo %}{% cycle foo %}")
1717 << dict << QStringLiteral("a2") << NoError;
1718
1719 QTest::newRow("cycle17") << QStringLiteral("{% cycle %}") << dict << QString()
1720 << TagSyntaxError;
1721 QTest::newRow("cycle18") << QStringLiteral("{% cycle var %}") << dict
1722 << QString() << TagSyntaxError;
1723
1724 dict.insert(QStringLiteral("three"), QStringLiteral("B"));
1725 dict.insert(QStringLiteral("four"), QStringLiteral("4"));
1726
1727 QTest::newRow("cycle19") << QStringLiteral("{% cycle one two three foo %}")
1728 << dict << QStringLiteral("A") << NoError;
1729 QTest::newRow("cycle20") << QStringLiteral(
1730 "{% cycle one two as foo %}{% cycle three four as bar %}")
1731 << dict << QStringLiteral("AB") << NoError;
1732}
1733
1734void TestDefaultTags::testWidthRatioTag_data()
1735{
1736 QTest::addColumn<QString>("input");
1737 QTest::addColumn<Dict>("dict");
1738 QTest::addColumn<QString>("output");
1739 QTest::addColumn<Cutelee::Error>("error");
1740
1741 Dict dict;
1742
1743 dict.insert(QStringLiteral("a"), 50);
1744 dict.insert(QStringLiteral("b"), 100);
1745 QTest::newRow("widthratio01") << QStringLiteral("{% widthratio a b 0 %}")
1746 << dict << QStringLiteral("0") << NoError;
1747
1748 dict.clear();
1749 dict.insert(QStringLiteral("a"), 0);
1750 dict.insert(QStringLiteral("b"), 0);
1751 QTest::newRow("widthratio02") << QStringLiteral("{% widthratio a b 0 %}")
1752 << dict << QString() << NoError;
1753
1754 dict.clear();
1755 dict.insert(QStringLiteral("a"), 0);
1756 dict.insert(QStringLiteral("b"), 100);
1757 QTest::newRow("widthratio03") << QStringLiteral("{% widthratio a b 100 %}")
1758 << dict << QStringLiteral("0") << NoError;
1759
1760 dict.clear();
1761 dict.insert(QStringLiteral("a"), 50);
1762 dict.insert(QStringLiteral("b"), 100);
1763 QTest::newRow("widthratio04") << QStringLiteral("{% widthratio a b 100 %}")
1764 << dict << QStringLiteral("50") << NoError;
1765
1766 dict.clear();
1767 dict.insert(QStringLiteral("a"), 100);
1768 dict.insert(QStringLiteral("b"), 100);
1769 QTest::newRow("widthratio05") << QStringLiteral("{% widthratio a b 100 %}")
1770 << dict << QStringLiteral("100") << NoError;
1771
1772 dict.clear();
1773 dict.insert(QStringLiteral("a"), 50);
1774 dict.insert(QStringLiteral("b"), 80);
1775 QTest::newRow("widthratio06") << QStringLiteral("{% widthratio a b 100 %}")
1776 << dict << QStringLiteral("63") << NoError;
1777
1778 dict.clear();
1779 dict.insert(QStringLiteral("a"), 50);
1780 dict.insert(QStringLiteral("b"), 70);
1781 QTest::newRow("widthratio07") << QStringLiteral("{% widthratio a b 100 %}")
1782 << dict << QStringLiteral("71") << NoError;
1783
1784 dict.clear();
1785 // Raise exception if we don't have 3 args, last one an integer
1786 QTest::newRow("widthratio08") << QStringLiteral("{% widthratio %}") << dict
1787 << QString() << TagSyntaxError;
1788
1789 dict.clear();
1790 QTest::newRow("widthratio09") << QStringLiteral("{% widthratio a b %}")
1791 << dict << QString() << TagSyntaxError;
1792
1793 dict.clear();
1794 dict.insert(QStringLiteral("a"), 50);
1795 dict.insert(QStringLiteral("b"), 100);
1796 QTest::newRow("widthratio10") << QStringLiteral("{% widthratio a b 100.0 %}")
1797 << dict << QStringLiteral("50") << NoError;
1798
1799 dict.clear();
1800 dict.insert(QStringLiteral("a"), 50);
1801 dict.insert(QStringLiteral("b"), 100);
1802 dict.insert(QStringLiteral("c"), 100);
1803 QTest::newRow("widthratio11") << QStringLiteral("{% widthratio a b c %}")
1804 << dict << QStringLiteral("50") << NoError;
1805}
1806
1807void TestDefaultTags::testFilterTag_data()
1808{
1809 QTest::addColumn<QString>("input");
1810 QTest::addColumn<Dict>("dict");
1811 QTest::addColumn<QString>("output");
1812 QTest::addColumn<Cutelee::Error>("error");
1813
1814 Dict dict;
1815
1816 QTest::newRow("filter01")
1817 << QStringLiteral("{% filter upper %}{% endfilter %}") << dict
1818 << QString() << NoError;
1819 QTest::newRow("filter02")
1820 << QStringLiteral("{% filter upper %}django{% endfilter %}") << dict
1821 << QStringLiteral("DJANGO") << NoError;
1822 QTest::newRow("filter03")
1823 << QStringLiteral("{% filter upper|lower %}django{% endfilter %}") << dict
1824 << QStringLiteral("django") << NoError;
1825
1826 dict.insert(QStringLiteral("remove"), QStringLiteral("spam"));
1827 QTest::newRow("filter04")
1828 << QStringLiteral("{% filter cut:remove %}djangospam{% endfilter %}")
1829 << dict << QStringLiteral("django") << NoError;
1830}
1831
1832void TestDefaultTags::testNowTag_data()
1833{
1834 QTest::addColumn<QString>("input");
1835 QTest::addColumn<Dict>("dict");
1836 QTest::addColumn<QString>("output");
1837 QTest::addColumn<Cutelee::Error>("error");
1838
1839 Dict dict;
1840
1841 auto today = QDateTime::currentDateTime().date();
1842
1843 QTest::newRow("now01") << QStringLiteral("{% now \"d M yyyy\"%}") << dict
1844 << (QString::number(today.day()) + QLatin1Char(' ')
1845 + QString::number(today.month()) + QLatin1Char(' ')
1846 + QString::number(today.year()))
1847 << NoError;
1848
1849 QTest::newRow("now02") << QStringLiteral("{% now \"d \"M\" yyyy\"%}") << dict
1850 << QString() << TagSyntaxError;
1851}
1852
1853void TestDefaultTags::testSpacelessTag_data()
1854{
1855 QTest::addColumn<QString>("input");
1856 QTest::addColumn<Dict>("dict");
1857 QTest::addColumn<QString>("output");
1858 QTest::addColumn<Cutelee::Error>("error");
1859
1860 Dict dict;
1861
1862 QTest::newRow("spaceless01")
1863 << QStringLiteral(
1864 "{% spaceless %} <b> <i> text </i> </b> {% endspaceless %}")
1865 << dict << QStringLiteral("<b><i> text </i></b>") << NoError;
1866 QTest::newRow("spaceless02")
1867 << "{% spaceless %} <b> \n <i> text </i> \n </b> {% endspaceless %}"
1868 << dict << QStringLiteral("<b><i> text </i></b>") << NoError;
1869 QTest::newRow("spaceless03")
1870 << QStringLiteral("{% spaceless %}<b><i>text</i></b>{% endspaceless %}")
1871 << dict << QStringLiteral("<b><i>text</i></b>") << NoError;
1872
1873 dict.insert(QStringLiteral("text"), QStringLiteral("This & that"));
1874 QTest::newRow("spaceless04")
1875 << QStringLiteral(
1876 "{% spaceless %}<b> <i>{{ text }}</i> </b>{% endspaceless %}")
1877 << dict << QStringLiteral("<b><i>This &amp; that</i></b>") << NoError;
1878 QTest::newRow("spaceless05")
1879 << QStringLiteral("{% autoescape off %}{% spaceless %}<b> <i>{{ text "
1880 "}}</i> </b>{% endspaceless %}{% endautoescape %}")
1881 << dict << QStringLiteral("<b><i>This & that</i></b>") << NoError;
1882 QTest::newRow("spaceless06") << QStringLiteral(
1883 "{% spaceless %}<b> <i>{{ text|safe }}</i> </b>{% endspaceless %}")
1884 << dict
1885 << QStringLiteral("<b><i>This & that</i></b>")
1886 << NoError;
1887}
1888
1889void TestDefaultTags::testRegroupTag_data()
1890{
1891 QTest::addColumn<QString>("input");
1892 QTest::addColumn<Dict>("dict");
1893 QTest::addColumn<QString>("output");
1894 QTest::addColumn<Cutelee::Error>("error");
1895
1896 Dict dict;
1897
1898 QVariantList list;
1899 QVariantHash hash;
1900
1901 hash.insert(QStringLiteral("foo"), QStringLiteral("c"));
1902 hash.insert(QStringLiteral("bar"), 1);
1903 list.append(hash);
1904
1905 hash.clear();
1906 hash.insert(QStringLiteral("foo"), QStringLiteral("d"));
1907 hash.insert(QStringLiteral("bar"), 1);
1908 list.append(hash);
1909
1910 hash.clear();
1911 hash.insert(QStringLiteral("foo"), QStringLiteral("a"));
1912 hash.insert(QStringLiteral("bar"), 2);
1913 list.append(hash);
1914
1915 hash.clear();
1916 hash.insert(QStringLiteral("foo"), QStringLiteral("b"));
1917 hash.insert(QStringLiteral("bar"), 2);
1918 list.append(hash);
1919
1920 hash.clear();
1921 hash.insert(QStringLiteral("foo"), QStringLiteral("x"));
1922 hash.insert(QStringLiteral("bar"), 3);
1923 list.append(hash);
1924
1925 dict.insert(QStringLiteral("data"), list);
1926
1927 QTest::newRow("regroup01")
1928 << QString::fromLatin1("{% regroup data by bar as grouped %}"
1929 "{% for group in grouped %}"
1930 "{{ group.grouper }}:"
1931 "{% for item in group.list %}"
1932 "{{ item.foo }}"
1933 "{% endfor %},"
1934 "{% endfor %}")
1935 << dict << QStringLiteral("1:cd,2:ab,3:x,") << NoError;
1936
1937 dict.clear();
1938 hash.clear();
1939 list.clear();
1940
1941 hash.insert(QStringLiteral("foo"), QStringLiteral("a"));
1942 hash.insert(QStringLiteral("bar"), 2);
1943 list.append(hash);
1944
1945 hash.clear();
1946 hash.insert(QStringLiteral("foo"), QStringLiteral("b"));
1947 hash.insert(QStringLiteral("bar"), 2);
1948 list.append(hash);
1949
1950 hash.clear();
1951 hash.insert(QStringLiteral("foo"), QStringLiteral("x"));
1952 hash.insert(QStringLiteral("bar"), 3);
1953 list.append(hash);
1954
1955 hash.clear();
1956 hash.insert(QStringLiteral("foo"), QStringLiteral("c"));
1957 hash.insert(QStringLiteral("bar"), 1);
1958 list.append(hash);
1959
1960 hash.clear();
1961 hash.insert(QStringLiteral("foo"), QStringLiteral("d"));
1962 hash.insert(QStringLiteral("bar"), 1);
1963 list.append(hash);
1964
1965 dict.insert(QStringLiteral("data"), list);
1966
1967 // Data is output in the order it is sent in.
1968
1969 QTest::newRow("regroup02")
1970 << QString::fromLatin1("{% regroup data by bar as grouped %}"
1971 "{% for group in grouped %}"
1972 "{{ group.grouper }}:"
1973 "{% for item in group.list %}"
1974 "{{ item.foo }}"
1975 "{% endfor %},"
1976 "{% endfor %}")
1977 << dict << QStringLiteral("2:ab,3:x,1:cd,") << NoError;
1978
1979 dict.clear();
1980 hash.clear();
1981 list.clear();
1982
1983 Table table;
1984
1985 QVariantList row;
1986 row.append(1);
1987 row.append(QStringLiteral("a"));
1988 table.append(row);
1989
1990 row.clear();
1991 row.append(1);
1992 row.append(QStringLiteral("b"));
1993 table.append(row);
1994
1995 row.clear();
1996 row.append(2);
1997 row.append(QStringLiteral("a"));
1998 table.append(row);
1999
2000 row.clear();
2001 row.append(3);
2002 row.append(QStringLiteral("c"));
2003 table.append(row);
2004
2005 row.clear();
2006 row.append(3);
2007 row.append(QStringLiteral("d"));
2008 table.append(row);
2009
2010 dict.insert(QStringLiteral("data"), QVariant::fromValue(table));
2011
2012 QTest::newRow("regroup03")
2013 << QString::fromLatin1("{% regroup data by 0 as grouped %}"
2014 "{% for group in grouped %}"
2015 "{{ group.grouper }}:"
2016 "{% for item in group.list %}"
2017 "{{ item.1 }}"
2018 "{% endfor %},"
2019 "{% endfor %}")
2020 << dict << QStringLiteral("1:ab,2:a,3:cd,") << NoError;
2021}
2022
2023void TestDefaultTags::testIfChangedTag_data()
2024{
2025 QTest::addColumn<QString>("input");
2026 QTest::addColumn<Dict>("dict");
2027 QTest::addColumn<QString>("output");
2028 QTest::addColumn<Cutelee::Error>("error");
2029
2030 Dict dict;
2031
2032 dict.insert(QStringLiteral("num"), QVariantList{1, 2, 3});
2033 QTest::newRow("ifchanged01") << QStringLiteral(
2034 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}")
2035 << dict << QStringLiteral("123") << NoError;
2036
2037 dict.clear();
2038 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 3});
2039 QTest::newRow("ifchanged02") << QStringLiteral(
2040 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}")
2041 << dict << QStringLiteral("13") << NoError;
2042
2043 dict.clear();
2044 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 1});
2045 QTest::newRow("ifchanged03") << QStringLiteral(
2046 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}")
2047 << dict << QStringLiteral("1") << NoError;
2048
2049 dict.clear();
2050 dict.insert(QStringLiteral("num"), QVariantList{1, 2, 3});
2051 dict.insert(QStringLiteral("numx"), QVariantList{2, 2, 2});
2052 QTest::newRow("ifchanged04") << QStringLiteral(
2053 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in "
2054 "numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}")
2055 << dict << QStringLiteral("122232") << NoError;
2056
2057 dict.clear();
2058 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 1});
2059 dict.insert(QStringLiteral("numx"), QVariantList{1, 2, 3});
2060 QTest::newRow("ifchanged05") << QStringLiteral(
2061 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in "
2062 "numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}")
2063 << dict << QStringLiteral("1123123123")
2064 << NoError;
2065
2066 dict.clear();
2067 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 1});
2068 dict.insert(QStringLiteral("numx"), QVariantList{2, 2, 2});
2069 QTest::newRow("ifchanged06") << QStringLiteral(
2070 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in "
2071 "numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}")
2072 << dict << QStringLiteral("1222") << NoError;
2073
2074 dict.clear();
2075 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 1});
2076 dict.insert(QStringLiteral("numx"), QVariantList{2, 2, 2});
2077 dict.insert(QStringLiteral("numy"), QVariantList{3, 3, 3});
2078 QTest::newRow("ifchanged07") << QStringLiteral(
2079 "{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in "
2080 "numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% "
2081 "ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor "
2082 "%}") << dict << QStringLiteral("1233323332333")
2083 << NoError;
2084 QTest::newRow("ifchanged08")
2085 << QStringLiteral("{% ifchanged %}{{ num.0 }}{% endifchanged %}") << dict
2086 << QStringLiteral("1") << NoError;
2087
2088 // datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1,
2089 // 'c'),
2090 // (1, 'd'), (1, 'd'), (0, 'e')]]}
2091 dict.clear();
2092 QVariantList list;
2093 QVariantList innerList;
2094 QVariantList tuple{1, QStringLiteral("a")};
2095 innerList.append(QVariant(tuple));
2096 tuple = {1, QStringLiteral("a")};
2097 innerList.append(QVariant(tuple));
2098 tuple = {0, QStringLiteral("b")};
2099 innerList.append(QVariant(tuple));
2100 tuple = {1, QStringLiteral("c")};
2101 innerList.append(QVariant(tuple));
2102 list.append(QVariant(innerList));
2103 innerList.clear();
2104
2105 tuple = {0, QStringLiteral("a")};
2106 innerList.append(QVariant(tuple));
2107 tuple = {1, QStringLiteral("c")};
2108 innerList.append(QVariant(tuple));
2109 tuple = {1, QStringLiteral("d")};
2110 innerList.append(QVariant(tuple));
2111 tuple = {1, QStringLiteral("d")};
2112 innerList.append(QVariant(tuple));
2113 tuple = {0, QStringLiteral("e")};
2114 innerList.append(QVariant(tuple));
2115 list.append(QVariant(innerList));
2116 innerList.clear();
2117
2118 dict.insert(QStringLiteral("datalist"), list);
2119 QTest::newRow("ifchanged08") << QStringLiteral(
2120 "{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged "
2121 "%}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}")
2122 << dict << QStringLiteral("accd") << NoError;
2123
2124 // Test one parameter given to ifchanged.
2125 dict.clear();
2126 dict.insert(QStringLiteral("num"), QVariantList{1, 2, 3});
2127 QTest::newRow("ifchanged-param01")
2128 << QStringLiteral("{% for n in num %}{% ifchanged n %}..{% endifchanged "
2129 "%}{{ n }}{% endfor %}")
2130 << dict << QStringLiteral("..1..2..3") << NoError;
2131
2132 dict.clear();
2133 dict.insert(QStringLiteral("num"), QVariantList{1, 2, 3});
2134 dict.insert(QStringLiteral("numx"), QVariantList{5, 6, 7});
2135 QTest::newRow("ifchanged-param02")
2136 << QStringLiteral("{% for n in num %}{% for x in numx %}{% ifchanged n "
2137 "%}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}")
2138 << dict << QStringLiteral("..567..567..567") << NoError;
2139
2140 // Test multiple parameters to ifchanged.
2141
2142 dict.clear();
2143 dict.insert(QStringLiteral("num"), QVariantList{1, 1, 2});
2144 dict.insert(QStringLiteral("numx"), QVariantList{5, 6, 6});
2145 QTest::newRow("ifchanged-param03")
2146 << QStringLiteral(
2147 "{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n "
2148 "%}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}")
2149 << dict << QStringLiteral("156156256") << NoError;
2150
2151 // Test a date+hour like construct, where the hour of the last day
2152 // is the same but the date had changed, so print the hour anyway.
2153
2154 dict.clear();
2155 QVariantList days;
2156 QVariantHash hash;
2157 hash.insert(QStringLiteral("day"), 1);
2158 hash.insert(QStringLiteral("hours"), QVariantList{1, 2, 3});
2159 days << hash;
2160 hash.clear();
2161 hash.insert(QStringLiteral("day"), 2);
2162 hash.insert(QStringLiteral("hours"), QVariantList{3});
2163 days << hash;
2164 dict.insert(QStringLiteral("days"), days);
2165 QTest::newRow("ifchanged-param04")
2166 << QStringLiteral("{% for d in days %}{% ifchanged %}{{ d.day }}{% "
2167 "endifchanged %}{% for h in d.hours %}{% ifchanged d h "
2168 "%}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}")
2169 << dict << QStringLiteral("112323") << NoError;
2170
2171 // Logically the same as above, just written with explicit
2172 // ifchanged for the day.
2173
2174 QTest::newRow("ifchanged-param05") << QStringLiteral(
2175 "{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% "
2176 "for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% "
2177 "endfor %}{% endfor %}") << dict
2178 << QStringLiteral("112323") << NoError;
2179
2180 // Test the else clause of ifchanged.
2181 dict.clear();
2182 dict.insert(QStringLiteral("ids"), QVariantList{1, 1, 2, 2, 2, 3});
2183 QTest::newRow("ifchanged-else01")
2184 << QStringLiteral("{% for id in ids %}{{ id }}{% ifchanged id %}-first{% "
2185 "else %}-other{% endifchanged %},{% endfor %}")
2186 << dict
2187 << QStringLiteral("1-first,1-other,2-first,2-other,2-other,3-first,")
2188 << NoError;
2189 QTest::newRow("ifchanged-else02")
2190 << QStringLiteral(
2191 "{% for id in ids %}{{ id }}-{% ifchanged id %}{% cycle red,blue "
2192 "%}{% else %}grey{% endifchanged %},{% endfor %}")
2193 << dict << QStringLiteral("1-red,1-grey,2-blue,2-grey,2-grey,3-red,")
2194 << NoError;
2195 QTest::newRow("ifchanged-else03")
2196 << QStringLiteral(
2197 "{% for id in ids %}{{ id }}{% ifchanged id %}-{% cycle red,blue "
2198 "%}{% else %}{% endifchanged %},{% endfor %}")
2199 << dict << QStringLiteral("1-red,1,2-blue,2,2,3-red,") << NoError;
2200
2201 dict.clear();
2202 dict.insert(QStringLiteral("ids"), QVariantList{1, 1, 2, 2, 2, 3, 4});
2203 QTest::newRow("ifchanged-else04")
2204 << QStringLiteral(
2205 "{% for id in ids %}{% ifchanged %}***{{ id }}*{% else %}...{% "
2206 "endifchanged %}{{ forloop.counter }}{% endfor %}")
2207 << dict << QStringLiteral("***1*1...2***2*3...4...5***3*6***4*7")
2208 << NoError;
2209}
2210
2211void TestDefaultTags::testAutoescapeTag_data()
2212{
2213 QTest::addColumn<QString>("input");
2214 QTest::addColumn<Dict>("dict");
2215 QTest::addColumn<QString>("output");
2216 QTest::addColumn<Cutelee::Error>("error");
2217
2218 Dict dict;
2219
2220 QTest::newRow("autoescape-tag01")
2221 << QStringLiteral("{% autoescape off %}hello{% endautoescape %}") << dict
2222 << QStringLiteral("hello") << NoError;
2223
2224 dict.insert(QStringLiteral("first"), QStringLiteral("<b>hello</b>"));
2225 QTest::newRow("autoescape-tag02")
2226 << QStringLiteral("{% autoescape off %}{{ first }}{% endautoescape %}")
2227 << dict << QStringLiteral("<b>hello</b>") << NoError;
2228 QTest::newRow("autoescape-tag03")
2229 << QStringLiteral("{% autoescape on %}{{ first }}{% endautoescape %}")
2230 << dict << QStringLiteral("&lt;b&gt;hello&lt;/b&gt;") << NoError;
2231 // Autoescape disabling and enabling nest in a predictable way.
2232 dict.insert(QStringLiteral("first"), QStringLiteral("<a>"));
2233 QTest::newRow("autoescape-tag04")
2234 << QStringLiteral("{% autoescape off %}{{ first }} {% autoescape on%}{{ "
2235 "first }}{% endautoescape %}{% endautoescape %}")
2236 << dict << QStringLiteral("<a> &lt;a&gt;") << NoError;
2237
2238 dict.insert(QStringLiteral("first"), QStringLiteral("<b>first</b>"));
2239 QTest::newRow("autoescape-tag05")
2240 << QStringLiteral("{% autoescape on %}{{ first }}{% endautoescape %}")
2241 << dict << QStringLiteral("&lt;b&gt;first&lt;/b&gt;") << NoError;
2242 // Strings (ASCII or unicode) already marked as "safe" are not
2243 // auto-escaped
2244 SafeString safeString(QStringLiteral("<b>first</b>"));
2245 auto safeStringVar = QVariant::fromValue<SafeString>(markSafe(safeString));
2246 dict.insert(QStringLiteral("first"), safeStringVar);
2247
2248 QTest::newRow("autoescape-tag06")
2249 << QStringLiteral("{{ first }}") << dict << QStringLiteral("<b>first</b>")
2250 << NoError;
2251 QTest::newRow("autoescape-tag07")
2252 << QStringLiteral("{% autoescape on %}{{ first }}{% endautoescape %}")
2253 << dict << QStringLiteral("<b>first</b>") << NoError;
2254
2255 // Literal string arguments to filters, if used in the result, are
2256 // safe.
2257 dict.clear();
2258 dict.insert(QStringLiteral("var"), QVariant());
2259 QTest::newRow("autoescape-tag08")
2260 << "{% autoescape on %}{{ var|default_if_none:\"endquote\\\" hah\" "
2261 "}}{% "
2262 "endautoescape %}"
2263 << dict << "endquote\" hah" << NoError;
2264
2265 QTest::newRow("autoescape-tag09")
2266 << "{% autoescape on extra %}{{ var|default_if_none:\"endquote\\\" "
2267 "hah\" "
2268 "}}{% endautoescape %}"
2269 << dict << "" << TagSyntaxError;
2270 QTest::newRow("autoescape-tag10")
2271 << "{% autoescape bad %}{{ var|default_if_none:\"endquote\\\" hah\" "
2272 "}}{% "
2273 "endautoescape %}"
2274 << dict << "" << TagSyntaxError;
2275
2276 // Objects which return safe strings as their __unicode__ method
2277 // won't get double-escaped.
2278 // 'autoescape-tag09': (r'{{ unsafe }}', {'unsafe':
2279 // filters.UnsafeClass()},
2280 // 'you &amp; me'),
2281 // 'autoescape-tag10': (r'{{ safe }}', {'safe': filters.SafeClass()}, 'you
2282 // &gt; me'),
2283 // The "safe" and "escape" filters cannot work due to internal
2284 // implementation details (fortunately, the (no)autoescape block
2285 // tags can be used in those cases)
2286 dict.clear();
2287 dict.insert(QStringLiteral("first"), QStringLiteral("<a>"));
2288 QTest::newRow("autoescape-filtertag01")
2289 << QStringLiteral(
2290 "{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}")
2291 << dict << QString() << TagSyntaxError;
2292 QTest::newRow("autoescape-filtertag02")
2293 << QStringLiteral(
2294 "{{ first }}{% filter escape %}{{ first }} x<y{% endfilter %}")
2295 << dict << QString() << TagSyntaxError;
2296}
2297
2298void TestDefaultTags::testMediaFinderTag_data()
2299{
2300 QTest::addColumn<QString>("input");
2301 QTest::addColumn<Dict>("dict");
2302 QTest::addColumn<QString>("output");
2303 QTest::addColumn<Cutelee::Error>("error");
2304
2305 Dict dict;
2306 QTest::newRow("media_finder-tag01")
2307 << "{% media_finder \"existing_image.png\" %}" << dict
2308 << QStringLiteral("file:///path/to/existing_image.png") << NoError;
2309 QTest::newRow("media_finder-tag02")
2310 << "{% media_finder \"does_not_exist.png\" %}" << dict << QString()
2311 << NoError;
2312 QTest::newRow("media_finder-tag03")
2313 << "{% media_finder \"existing_image.png\" \"does_not_exist.png\" %}"
2314 << dict << QStringLiteral("file:///path/to/existing_image.png")
2315 << NoError;
2316
2317 dict.insert(QStringLiteral("existing_img"),
2318 QStringLiteral("existing_image.png"));
2319 dict.insert(QStringLiteral("nonexisting_img"),
2320 QStringLiteral("does_not_exist.png"));
2321
2322 QTest::newRow("media_finder-tag04") << QStringLiteral("{% media_finder %}")
2323 << dict << QString() << TagSyntaxError;
2324 QTest::newRow("media_finder-tag05")
2325 << QStringLiteral("{% media_finder existing_img %}") << dict
2326 << QStringLiteral("file:///path/to/existing_image.png") << NoError;
2327 QTest::newRow("media_finder-tag06")
2328 << QStringLiteral("{% media_finder nonexisting_img %}") << dict
2329 << QString() << NoError;
2330 QTest::newRow("media_finder-tag07")
2331 << "{% media_finder \"does_not_exist.png\" existing_img %}" << dict
2332 << QStringLiteral("file:///path/to/existing_image.png") << NoError;
2333 QTest::newRow("media_finder-tag08")
2334 << QStringLiteral("{% media_finder nonexisting_img existing_img %}")
2335 << dict << QStringLiteral("file:///path/to/existing_image.png")
2336 << NoError;
2337 QTest::newRow("media_finder-tag09")
2338 << "{% media_finder \"existing_image.png\" "
2339 "\"another_existing_image.png\" %}"
2340 << dict << QStringLiteral("file:///path/to/existing_image.png")
2341 << NoError;
2342 QTest::newRow("media_finder-tag10")
2343 << "{% media_finder \"another_existing_image.png\" "
2344 "\"existing_image.png\" %}"
2345 << dict << QStringLiteral("file:///path/to/another_existing_image.png")
2346 << NoError;
2347
2348 dict.insert(QStringLiteral("this_and_that_img"),
2349 QStringLiteral("this&that.png"));
2350
2351 QTest::newRow("media_finder-tag11")
2352 << "{% media_finder \"this&that.png\" %}" << dict
2353 << QStringLiteral("file:///path/to/this&amp;that.png") << NoError;
2354 QTest::newRow("media_finder-tag12")
2355 << "{% media_finder this_and_that_img %}" << dict
2356 << QStringLiteral("file:///path/to/this&amp;that.png") << NoError;
2357 QTest::newRow("media_finder-tag13")
2358 << "{% autoescape off %}{% media_finder \"this&that.png\" %}{% "
2359 "endautoescape %}"
2360 << dict << QStringLiteral("file:///path/to/this&that.png") << NoError;
2361 QTest::newRow("media_finder-tag14")
2362 << "{% autoescape off %}{% media_finder this_and_that_img %}{% "
2363 "endautoescape %}"
2364 << dict << QStringLiteral("file:///path/to/this&that.png") << NoError;
2365}
2366
2367void TestDefaultTags::testRangeTag_data()
2368{
2369 QTest::addColumn<QString>("input");
2370 QTest::addColumn<Dict>("dict");
2371 QTest::addColumn<QString>("output");
2372 QTest::addColumn<Cutelee::Error>("error");
2373
2374 Dict dict;
2375
2376 QTest::newRow("range-tag01")
2377 << QStringLiteral("{% range 5 as i %}{{ i }};{% endrange %}") << dict
2378 << QStringLiteral("0;1;2;3;4;") << NoError;
2379 QTest::newRow("range-tag02")
2380 << QStringLiteral("{% range 1 6 as i %}{{ i }};{% endrange %}") << dict
2381 << QStringLiteral("1;2;3;4;5;") << NoError;
2382 QTest::newRow("range-tag03")
2383 << QStringLiteral("{% range 5 26 5 as i %}{{ i }};{% endrange %}") << dict
2384 << QStringLiteral("5;10;15;20;25;") << NoError;
2385
2386 QVariantList list{10, 15, 2};
2387 dict.insert(QStringLiteral("values"), list);
2388
2389 QTest::newRow("range-tag04") << QStringLiteral(
2390 "{% range values.0 values.1 values.2 as i %}{{ i }};{% endrange %}")
2391 << dict << QStringLiteral("10;12;14;")
2392 << NoError;
2393
2394 QTest::newRow("range-tag05")
2395 << QStringLiteral("{% range 5 %}Foo;{% endrange %}") << dict
2396 << QStringLiteral("Foo;Foo;Foo;Foo;Foo;") << NoError;
2397 QTest::newRow("range-tag06")
2398 << QStringLiteral("{% range 5 6 %}Foo;{% endrange %}") << dict
2399 << QString() << TagSyntaxError;
2400 QTest::newRow("range-tag07")
2401 << QStringLiteral("{% range 5 6 7 %}Foo;{% endrange %}") << dict
2402 << QString() << TagSyntaxError;
2403}
2404
2405void TestDefaultTags::testDebugTag_data()
2406{
2407
2408 QTest::addColumn<QString>("input");
2409 QTest::addColumn<Dict>("dict");
2410 QTest::addColumn<QString>("output");
2411 QTest::addColumn<Cutelee::Error>("error");
2412
2413 Dict dict;
2414
2415 QTest::newRow("debug-tag01")
2416 << QStringLiteral("{% debug %}") << dict
2417 << QStringLiteral("\n\nContext:\nEnd context:\n\n") << NoError;
2418 dict.insert(QStringLiteral("answer"), 42);
2419 QTest::newRow("debug-tag02")
2420 << QStringLiteral("{% debug %}") << dict
2421 << QStringLiteral("\n\nContext:\nkey answer, type int\nEnd context:\n\n")
2422 << NoError;
2423}
2424
2425void TestDefaultTags::testLoadTag_data()
2426{
2427
2428 QTest::addColumn<QString>("input");
2429 QTest::addColumn<Dict>("dict");
2430 QTest::addColumn<QString>("output");
2431 QTest::addColumn<Cutelee::Error>("error");
2432
2433 Dict dict;
2434
2435 QTest::newRow("load-tag01") << QStringLiteral("{% load does_not_exist %}foo")
2436 << dict << QString() << TagSyntaxError;
2437}
2438
2439void TestDefaultTags::testUrlTypes_data()
2440{
2441 QTest::addColumn<QString>("input");
2442 QTest::addColumn<Dict>("dict");
2443 QTest::addColumn<QPair<QString, QString>>("output");
2444
2445 Dict dict;
2446 QTest::newRow("url-types01")
2447 << "{% media_finder \"existing_image.png\" %}" << dict
2448 << qMakePair(QStringLiteral("file:///path/to/"),
2449 QStringLiteral("existing_image.png"));
2450
2451 QTest::newRow("url-types02") << "{% media_finder \"does_not_exist.png\" %}"
2452 << dict << qMakePair(QString(), QString());
2453
2454 dict.insert(QStringLiteral("existing_img"),
2455 QStringLiteral("existing_image.png"));
2456 dict.insert(QStringLiteral("nonexisting_img"),
2457 QStringLiteral("does_not_exist.png"));
2458
2459 QTest::newRow("url-types03")
2460 << QStringLiteral("{% media_finder existing_img %}") << dict
2461 << qMakePair(QStringLiteral("file:///path/to/"),
2462 QStringLiteral("existing_image.png"));
2463
2464 QTest::newRow("url-types04")
2465 << QStringLiteral("{% media_finder nonexisting_img %}") << dict
2466 << qMakePair(QString(), QString());
2467}
2468
2469void TestDefaultTags::testUrlTypes()
2470{
2471 QFETCH(QString, input);
2472 QFETCH(Dict, dict);
2473 QFETCH(StringPair, output);
2474
2475 auto t = m_engine->newTemplate(input, QLatin1String(QTest::currentDataTag()));
2476 QVERIFY(t->error() == NoError);
2477 Context c(dict);
2478 auto result = t->render(&c);
2479 QVERIFY(t->error() == NoError);
2480 QVERIFY(result == output.first + output.second);
2481
2482 c.setUrlType(Context::RelativeUrls);
2483 result = t->render(&c);
2484 QVERIFY(t->error() == NoError);
2485 QVERIFY(result == output.second);
2486}
2487
2488void TestDefaultTags::testRelativePaths_data()
2489{
2490 QTest::addColumn<QString>("input");
2491 QTest::addColumn<Dict>("dict");
2492 QTest::addColumn<QString>("output");
2493
2494 Dict dict;
2495 QTest::newRow("relativepaths01")
2496 << "{% media_finder \"existing_image.png\" %}" << dict
2497 << QStringLiteral("existing_image.png");
2498
2499 QTest::newRow("relativepaths02")
2500 << "{% media_finder \"does_not_exist.png\" %}" << dict << QString();
2501
2502 dict.insert(QStringLiteral("existing_img"),
2503 QStringLiteral("existing_image.png"));
2504 dict.insert(QStringLiteral("nonexisting_img"),
2505 QStringLiteral("does_not_exist.png"));
2506
2507 QTest::newRow("relativepaths03")
2508 << QStringLiteral("{% media_finder existing_img %}") << dict
2509 << QStringLiteral("existing_image.png");
2510
2511 QTest::newRow("relativepaths04")
2512 << QStringLiteral("{% media_finder nonexisting_img %}") << dict
2513 << QString();
2514}
2515
2516void TestDefaultTags::testRelativePaths()
2517{
2518 QFETCH(QString, input);
2519 QFETCH(Dict, dict);
2520 QFETCH(QString, output);
2521
2522 auto t = m_engine->newTemplate(input, QLatin1String(QTest::currentDataTag()));
2523 QVERIFY(t->error() == NoError);
2524 Context c(dict);
2525 auto result = t->render(&c);
2526 QVERIFY(t->error() == NoError);
2527 if (!output.isEmpty())
2528 QVERIFY(result == QStringLiteral("file:///path/to/") + output);
2529 else
2530 QVERIFY(result.isEmpty());
2531
2532 c.setUrlType(Context::RelativeUrls);
2533 auto relativePath = QStringLiteral("relative/path");
2534 c.setRelativeMediaPath(relativePath);
2535 result = t->render(&c);
2536 QVERIFY(t->error() == NoError);
2537 if (!output.isEmpty())
2538 QVERIFY(result == relativePath + QLatin1Char('/') + output);
2539 else
2540 QVERIFY(result.isEmpty());
2541}
2542
2543QTEST_MAIN(TestDefaultTags)
2544#include "testdefaulttags.moc"
2545
2546#endif
The Context class holds the context to render a Template with.
Definition context.h:119
@ RelativeUrls
Relative URLs should be put in the template.
Definition context.h:244
Cutelee::Engine is the main entry point for creating Cutelee Templates.
Definition engine.h:121
void setPluginPaths(const QStringList &dirs)
Definition engine.cpp:87
Template newTemplate(const QString &content, const QString &name) const
Definition engine.cpp:391
void addTemplateLoader(std::shared_ptr< AbstractTemplateLoader > loader)
Definition engine.cpp:68
The InMemoryTemplateLoader loads Templates set dynamically in memory.
A QString wrapper class for containing whether a string is safe or needs to be escaped.
Definition safestring.h:92
QString errorString() const
Definition template.cpp:128
std::pair< QString, QString > getMediaUri(const QString &fileName) const override
The Cutelee namespace holds all public Cutelee API.
Definition Mainpage.dox:8
Cutelee::SafeString markSafe(const Cutelee::SafeString &input)
Definition util.cpp:90
Utility functions used throughout Cutelee.