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