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