Cutelee  6.1.0
testloadertags.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 LOADERTAGSTEST_H
22 #define LOADERTAGSTEST_H
23 
24 #include <QtCore/QDebug>
25 #include <QtCore/QDir>
26 #include <QtCore/QFileInfo>
27 #include <QtTest/QTest>
28 
29 #include "context.h"
30 #include "coverageobject.h"
31 #include "engine.h"
32 #include "cutelee_paths.h"
33 #include "template.h"
34 
35 typedef QHash<QString, QVariant> Dict;
36 
37 Q_DECLARE_METATYPE(Cutelee::Error)
38 
39 using namespace Cutelee;
40 
42 {
43  Q_OBJECT
44 
45 private Q_SLOTS:
46  void initTestCase();
47  void cleanupTestCase();
48 
49  void testTemplateFromQrc();
50 
51  void testIncludeTag_data();
52  void testIncludeTag() { doTest(); }
53 
54  void testExtendsTag_data();
55  void testExtendsTag() { doTest(); }
56 
57  void testIncludeAndExtendsTag_data();
58  void testIncludeAndExtendsTag() { doTest(); }
59 
60  void testBlockTagErrors_data();
61  void testBlockTagErrors() { doTest(); }
62 
63 private:
64  void doTest();
65 
66  std::shared_ptr<InMemoryTemplateLoader> loader;
67  Engine *m_engine;
68 };
69 
70 void TestLoaderTags::initTestCase()
71 {
72  Q_INIT_RESOURCE(testresource);
73 
74  m_engine = new Engine(this);
75 
76  loader = std::shared_ptr<InMemoryTemplateLoader>(new InMemoryTemplateLoader());
77  m_engine->addTemplateLoader(loader);
78 
79  m_engine->setPluginPaths({
80  QStringLiteral(CUTELEE_PLUGIN_PATH),
81  QStringLiteral(":/plugins/") // For testtags.qs
82  });
83 #ifdef HAVE_QTQML_LIB
84  m_engine->addDefaultLibrary(QStringLiteral("cutelee_scriptabletags"));
85 #endif
86 }
87 
88 void TestLoaderTags::cleanupTestCase() { delete m_engine; }
89 
90 void TestLoaderTags::testTemplateFromQrc()
91 {
92  Engine engine;
93 
94  auto loader = std::shared_ptr<Cutelee::FileSystemTemplateLoader>(new Cutelee::FileSystemTemplateLoader);
95  loader->setTemplateDirs({QStringLiteral(":/templates/")});
96  engine.addTemplateLoader(loader);
97  engine.setPluginPaths({QStringLiteral(CUTELEE_PLUGIN_PATH)});
98 
99  auto t = engine.loadByName(QStringLiteral("resourcetemplate1.html"));
100 
101  if (t->error() != NoError) {
102  qDebug() << t->errorString();
103  QCOMPARE(t->error(), NoError);
104  return;
105  }
106 
107  Context context;
108  context.insert(QStringLiteral("numbertwo"), QStringLiteral("two"));
109  context.insert(QStringLiteral("numberfour"), QStringLiteral("four"));
110 
111  auto result = t->render(&context);
112 
113  if (t->error() != NoError) {
114  qDebug() << t->errorString();
115  QCOMPARE(t->error(), NoError);
116  return;
117  }
118 
119  QCOMPARE(result, QStringLiteral("one-two-three-four\n\n"));
120 }
121 
122 void TestLoaderTags::doTest()
123 {
124  QFETCH(QString, input);
125  QFETCH(Dict, dict);
126  QFETCH(QString, output);
127  QFETCH(Cutelee::Error, error);
128 
129  auto t = m_engine->newTemplate(input, QLatin1String(QTest::currentDataTag()));
130 
131  if (t->error() != NoError) {
132  if (t->error() != error)
133  qDebug() << t->errorString();
134  QCOMPARE(t->error(), error);
135  return;
136  }
137 
138  Context context(dict);
139 
140  auto result = t->render(&context);
141 
142  if (t->error() != NoError) {
143  if (t->error() != error)
144  qDebug() << t->errorString();
145  QCOMPARE(t->error(), error);
146  return;
147  }
148 
149  // Didn't catch any errors, so make sure I didn't expect any.
150  QCOMPARE(NoError, error);
151 
152  QCOMPARE(t->error(), NoError);
153 
154  QCOMPARE(result, output);
155 }
156 
157 void TestLoaderTags::testIncludeTag_data()
158 {
159  QTest::addColumn<QString>("input");
160  QTest::addColumn<Dict>("dict");
161  QTest::addColumn<QString>("output");
162  QTest::addColumn<Cutelee::Error>("error");
163 
164  Dict dict;
165 
166  loader->setTemplate(QStringLiteral("basic-syntax01"),
167  QStringLiteral("Something cool"));
168  loader->setTemplate(QStringLiteral("basic-syntax02"),
169  QStringLiteral("{{ headline }}"));
170 
171  QTest::newRow("include01") << "{% include \"basic-syntax01\" %}" << dict
172  << QStringLiteral("Something cool") << NoError;
173 
174  dict.insert(QStringLiteral("headline"), QStringLiteral("Included"));
175 
176  QTest::newRow("include02") << "{% include \"basic-syntax02\" %}" << dict
177  << QStringLiteral("Included") << NoError;
178 
179  dict.insert(QStringLiteral("templateName"), QStringLiteral("basic-syntax02"));
180 
181  QTest::newRow("include03") << QStringLiteral("{% include templateName %}")
182  << dict << QStringLiteral("Included") << NoError;
183 
184  dict.clear();
185  QTest::newRow("include04") << "a{% include \"nonexistent\" %}b" << dict
186  << QStringLiteral("ab") << TagSyntaxError;
187 
188  auto incl05 = QStringLiteral("template with a space");
189  loader->setTemplate(QStringLiteral("include 05"), incl05);
190 
191  QTest::newRow("include 05")
192  << incl05 << dict << QStringLiteral("template with a space") << NoError;
193 
194  QTest::newRow("include06")
195  << "{% include \"include 05\" %}" << dict
196  << QStringLiteral("template with a space") << NoError;
197 
198  dict.clear();
199  dict.insert(QStringLiteral("list"), QVariantList{QVariant(), QVariant()});
200  QTest::newRow("include07")
201  << "{% for i in list %}{% include \"include 05\" %}{% endfor %}" << dict
202  << QStringLiteral("template with a spacetemplate with a space")
203  << NoError;
204 }
205 
206 void TestLoaderTags::testExtendsTag_data()
207 {
208  QTest::addColumn<QString>("input");
209  QTest::addColumn<Dict>("dict");
210  QTest::addColumn<QString>("output");
211  QTest::addColumn<Cutelee::Error>("error");
212 
213  Dict dict;
214  // Basic test
215  QTest::newRow("namedendblocks01")
216  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
217  "second %}_{% endblock first %}3")
218  << dict << QStringLiteral("1_2_3") << NoError;
219  // Unbalanced blocks
220  QTest::newRow("namedendblocks02")
221  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
222  "first %}_{% endblock second %}3")
223  << dict << QString() << InvalidBlockTagError;
224  QTest::newRow("namedendblocks03")
225  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
226  "%}_{% endblock second %}3")
227  << dict << QString() << InvalidBlockTagError;
228  QTest::newRow("namedendblocks04")
229  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
230  "second %}_{% endblock third %}3")
231  << dict << QString() << InvalidBlockTagError;
232  QTest::newRow("namedendblocks05")
233  << QStringLiteral(
234  "1{% block first %}_{% block second %}2{% endblock first %}")
235  << dict << QString() << InvalidBlockTagError;
236  // Mixed named and unnamed endblocks
237  QTest::newRow("namedendblocks06")
238  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
239  "%}_{% endblock first %}3")
240  << dict << QStringLiteral("1_2_3") << NoError;
241  QTest::newRow("namedendblocks07")
242  << QStringLiteral("1{% block first %}_{% block second %}2{% endblock "
243  "second %}_{% endblock %}3")
244  << dict << QStringLiteral("1_2_3") << NoError;
245 
246  //## INHERITANCE ###########################################################
247  // Standard template with no inheritance
248 
249  auto inh1 = QStringLiteral(
250  "1{% block first %}&{% endblock %}3{% block second %}_{% endblock %}");
251  loader->setTemplate(QStringLiteral("inheritance01"), inh1);
252 
253  QTest::newRow("inheritance01")
254  << inh1 << dict << QStringLiteral("1&3_") << NoError;
255 
256  auto inh2
257  = QStringLiteral("{% extends \"inheritance01\" %}{% block first %}2{% "
258  "endblock %}{% block second %}4{% endblock %}");
259  loader->setTemplate(QStringLiteral("inheritance02"), inh2);
260 
261  // Standard two-level inheritance
262  QTest::newRow("inheritance02")
263  << inh2 << dict << QStringLiteral("1234") << NoError;
264  // Three-level with no redefinitions on third level
265  QTest::newRow("inheritance03")
266  << QStringLiteral("{% extends 'inheritance02' %}") << dict
267  << QStringLiteral("1234") << NoError;
268  // Two-level with no redefinitions on second level
269 
270  auto inh4 = QStringLiteral("{% extends \"inheritance01\" %}");
271  loader->setTemplate(QStringLiteral("inheritance04"), inh4);
272 
273  QTest::newRow("inheritance04")
274  << inh4 << dict << QStringLiteral("1&3_") << NoError;
275  // Two-level with double quotes instead of single quotes
276  QTest::newRow("inheritance05") << "{% extends \"inheritance02\" %}" << dict
277  << QStringLiteral("1234") << NoError;
278 
279  dict.insert(QStringLiteral("foo"), QStringLiteral("inheritance02"));
280  // Three-level with variable parent-template name
281  QTest::newRow("inheritance06") << QStringLiteral("{% extends foo %}") << dict
282  << QStringLiteral("1234") << NoError;
283 
284  auto inh7 = QStringLiteral(
285  "{% extends 'inheritance01' %}{% block second %}5{% endblock %}");
286  loader->setTemplate(QStringLiteral("inheritance07"), inh7);
287 
288  dict.clear();
289  // Two-level with one block defined, one block not defined
290  QTest::newRow("inheritance07")
291  << inh7 << dict << QStringLiteral("1&35") << NoError;
292  // Three-level with one block defined on this level, two blocks defined next
293  // level
294  QTest::newRow("inheritance08") << QStringLiteral(
295  "{% extends 'inheritance02' %}{% block second %}5{% endblock %}")
296  << dict << QStringLiteral("1235") << NoError;
297 
298  // Three-level with second and third levels blank
299  QTest::newRow("inheritance09")
300  << QStringLiteral("{% extends 'inheritance04' %}") << dict
301  << QStringLiteral("1&3_") << NoError;
302 
303  dict.clear();
304 
305  // Three-level with space NOT in a block -- should be ignored
306  QTest::newRow("inheritance10")
307  << QStringLiteral("{% extends 'inheritance04' %} ") << dict
308  << QStringLiteral("1&3_") << NoError;
309  // Three-level with both blocks defined on this level, but none on second
310  // level
311  QTest::newRow("inheritance11")
312  << QStringLiteral("{% extends 'inheritance04' %}{% block first %}2{% "
313  "endblock %}{% block second %}4{% endblock %}")
314  << dict << QStringLiteral("1234") << NoError;
315  // Three-level with this level providing one and second level providing the
316  // other
317  QTest::newRow("inheritance12") << QStringLiteral(
318  "{% extends 'inheritance07' %}{% block first %}2{% endblock %}")
319  << dict << QStringLiteral("1235") << NoError;
320  // Three-level with this level overriding second level
321  QTest::newRow("inheritance13")
322  << QStringLiteral("{% extends 'inheritance02' %}{% block first %}a{% "
323  "endblock %}{% block second %}b{% endblock %}")
324  << dict << QStringLiteral("1a3b") << NoError;
325  // A block defined only in a child template shouldn't be displayed
326  QTest::newRow("inheritance14")
327  << QStringLiteral("{% extends 'inheritance01' %}{% block newblock %}NO "
328  "DISPLAY{% endblock %}")
329  << dict << QStringLiteral("1&3_") << NoError;
330 
331  auto inh15
332  = QStringLiteral("{% extends 'inheritance01' %}{% block first %}2{% "
333  "block inner %}inner{% endblock %}{% endblock %}");
334  loader->setTemplate(QStringLiteral("inheritance15"), inh15);
335 
336  // A block within another block
337  QTest::newRow("inheritance15")
338  << inh15 << dict << QStringLiteral("12inner3_") << NoError;
339  // A block within another block (level 2)
340 
341  QTest::newRow("inheritance16")
342  << QStringLiteral(
343  "{% extends 'inheritance15' %}{% block inner %}out{% endblock %}")
344  << dict << QStringLiteral("12out3_") << NoError;
345 
346 #ifdef HAVE_QTQML_LIB
347  // {% load %} tag (parent -- setup for exception04)
348  auto inh17 = QStringLiteral(
349  "{% load testtags %}{% block first %}1234{% endblock %}");
350  loader->setTemplate(QStringLiteral("inheritance17"), inh17);
351 
352  dict.clear();
353  QTest::newRow("inheritance17")
354  << inh17 << dict << QStringLiteral("1234") << NoError;
355 
356  // {% load %} tag (standard usage, without inheritance)
357  QTest::newRow("inheritance18")
358  << QStringLiteral("{% load testtags %}{% echo this that theother %}5678")
359  << dict << QStringLiteral("this that theother5678") << NoError;
360 
361  // {% load %} tag (within a child template)
362  QTest::newRow("inheritance19")
363  << QStringLiteral("{% extends 'inheritance01' %}{% block first %}{% load "
364  "testtags %}{% echo 400 %}5678{% endblock %}")
365  << dict << QStringLiteral("140056783_") << NoError;
366 #endif
367 
368  auto inh20 = QStringLiteral("{% extends 'inheritance01' %}{% block first "
369  "%}{{ block.super }}a{% endblock %}");
370  loader->setTemplate(QStringLiteral("inheritance20"), inh20);
371 
372  // Two-level inheritance with {{ block.super }}
373  QTest::newRow("inheritance20")
374  << inh20 << dict << QStringLiteral("1&a3_") << NoError;
375  // Three-level inheritance with {{ block.super }} from parent
376  QTest::newRow("inheritance21")
377  << QStringLiteral("{% extends 'inheritance02' %}{% block first %}{{ "
378  "block.super }}a{% endblock %}")
379  << dict << QStringLiteral("12a34") << NoError;
380  // Three-level inheritance with {{ block.super }} from grandparent
381  QTest::newRow("inheritance22")
382  << QStringLiteral("{% extends 'inheritance04' %}{% block first %}{{ "
383  "block.super }}a{% endblock %}")
384  << dict << QStringLiteral("1&a3_") << NoError;
385  // Three-level inheritance with {{ block.super }} from parent and
386  // grandparent
387  QTest::newRow("inheritance23")
388  << QStringLiteral("{% extends 'inheritance20' %}{% block first %}{{ "
389  "block.super }}b{% endblock %}")
390  << dict << QStringLiteral("1&ab3_") << NoError;
391 
392  // Inheritance from local context without use of template loader
393 
394  auto t = m_engine->newTemplate(
395  QStringLiteral("1{% block first %}_{% endblock %}3{% block second %}_{% "
396  "endblock %}"),
397  QStringLiteral("context_template"));
398  dict.insert(QStringLiteral("context_template"), QVariant::fromValue(t));
399 
400  QTest::newRow("inheritance24")
401  << QStringLiteral("{% extends context_template %}{% block first %}2{% "
402  "endblock %}{% block second %}4{% endblock %}")
403  << dict << QStringLiteral("1234") << NoError;
404 
405  dict.clear();
406 
407  auto t1 = m_engine->newTemplate(QStringLiteral("Wrong"),
408  QStringLiteral("context_template_1"));
409  auto t2 = m_engine->newTemplate(
410  QStringLiteral("1{% block first %}_{% endblock %}3{% block second %}_{% "
411  "endblock %}"),
412  QStringLiteral("context_template_2"));
413  QVariantList list{QVariant::fromValue(t1), QVariant::fromValue(t2)};
414 
415  dict.insert(QStringLiteral("context_template"), list);
416 
417  // Inheritance from local context with variable parent template
418  QTest::newRow("inheritance25")
419  << QStringLiteral("{% extends context_template.1 %}{% block first %}2{% "
420  "endblock %}{% block second %}4{% endblock %}")
421  << dict << QStringLiteral("1234") << NoError;
422 
423  dict.clear();
424 
425  // Set up a base template to extend
426  auto inh26 = QStringLiteral("no tags");
427  loader->setTemplate(QStringLiteral("inheritance26"), inh26);
428 
429  // Inheritance from a template that doesn't have any blocks
430  QTest::newRow("inheritance27")
431  << QStringLiteral("{% extends 'inheritance26' %}") << dict
432  << QStringLiteral("no tags") << NoError;
433 
434  auto inh28 = QStringLiteral("{% block first %}!{% endblock %}");
435  loader->setTemplate(QStringLiteral("inheritance 28"), inh28);
436 
437  QTest::newRow("inheritance 28")
438  << inh28 << dict << QStringLiteral("!") << NoError;
439 
440  // Inheritance from a template with a space in its name should work.
441  QTest::newRow("inheritance29")
442  << QStringLiteral("{% extends 'inheritance 28' %}") << dict
443  << QStringLiteral("!") << NoError;
444 
445  dict.insert(QStringLiteral("optional"), QStringLiteral("True"));
446 
447  auto inh30 = QStringLiteral(
448  "1{% if optional %}{% block opt %}2{% endblock %}{% endif %}3");
449  loader->setTemplate(QStringLiteral("inheritance30"), inh30);
450 
451  QTest::newRow("inheritance30")
452  << inh30 << dict << QStringLiteral("123") << NoError;
453  QTest::newRow("inheritance31") << QStringLiteral(
454  "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}")
455  << dict << QStringLiteral("1two3") << NoError;
456  dict.clear();
457  QTest::newRow("inheritance32") << QStringLiteral(
458  "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}")
459  << dict << QStringLiteral("13") << NoError;
460 
461  dict.insert(QStringLiteral("optional"), 1);
462  auto inh33 = QStringLiteral("1{% ifequal optional 1 %}{% block opt %}2{% "
463  "endblock %}{% endifequal %}3");
464  loader->setTemplate(QStringLiteral("inheritance33"), inh33);
465 
466  QTest::newRow("inheritance33")
467  << inh33 << dict << QStringLiteral("123") << NoError;
468 
469  QTest::newRow("inheritance34") << QStringLiteral(
470  "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}")
471  << dict << QStringLiteral("1two3") << NoError;
472  dict.clear();
473  QTest::newRow("inheritance35") << QStringLiteral(
474  "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}")
475  << dict << QStringLiteral("13") << NoError;
476 
477  dict.clear();
478  dict.insert(QStringLiteral("numbers"), QVariantList{1, 2, 3});
479 
480  auto inh36 = QStringLiteral("{% for n in numbers %}_{% block opt %}{{ n }}{% "
481  "endblock %}{% endfor %}_");
482  loader->setTemplate(QStringLiteral("inheritance36"), inh36);
483 
484  QTest::newRow("inheritance36")
485  << inh36 << dict << QStringLiteral("_1_2_3_") << NoError;
486  QTest::newRow("inheritance37")
487  << QStringLiteral(
488  "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}")
489  << dict << QStringLiteral("_X_X_X_") << NoError;
490  dict.clear();
491  QTest::newRow("inheritance38") << QStringLiteral(
492  "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}")
493  << dict << QStringLiteral("_") << NoError;
494 
495  dict.insert(QStringLiteral("optional"), QStringLiteral("True"));
496 
497  QTest::newRow("inheritance39")
498  << QStringLiteral("{% extends 'inheritance30' %}{% block opt %}new{{ "
499  "block.super }}{% endblock %}")
500  << dict << QStringLiteral("1new23") << NoError;
501 
502  dict.insert(QStringLiteral("optional"), 1);
503 
504  QTest::newRow("inheritance40")
505  << QStringLiteral("{% extends 'inheritance33' %}{% block opt %}new{{ "
506  "block.super }}{% endblock %}")
507  << dict << QStringLiteral("1new23") << NoError;
508 
509  dict.clear();
510  dict.insert(QStringLiteral("numbers"), QVariantList{1, 2, 3});
511 
512  QTest::newRow("inheritance41")
513  << QStringLiteral("{% extends 'inheritance36' %}{% block opt %}new{{ "
514  "block.super }}{% endblock %}")
515  << dict << QStringLiteral("_new1_new2_new3_") << NoError;
516 
517  QTest::newRow("inheritance42")
518  << QStringLiteral("{% extends 'inheritance02'|cut:' ' %}") << dict
519  << QStringLiteral("1234") << NoError;
520 
521  dict.clear();
522  // Raise exception for invalid template name
523  QTest::newRow("exception01") << QStringLiteral("{% extends 'nonexistent' %}")
524  << dict << QString() << TagSyntaxError;
525  // Raise exception for invalid template name (in variable)
526  QTest::newRow("exception02") << QStringLiteral("{% extends nonexistent %}")
527  << dict << QString() << TagSyntaxError;
528  // Raise exception for extra {% extends %} tags
529  QTest::newRow("exception03")
530  << QStringLiteral("{% extends 'inheritance01' %}{% block first %}2{% "
531  "endblock %}{% extends 'inheritance16' %}")
532  << dict << QString() << TagSyntaxError;
533  // Raise exception for custom tags used in child with {% load %} tag in
534  // parent, not in child
535  QTest::newRow("exception04")
536  << QStringLiteral("{% extends 'inheritance17' %}{% block first %}{% echo "
537  "400 %}5678{% endblock %}")
538  << dict << QString() << InvalidBlockTagError;
539 }
540 
541 void TestLoaderTags::testBlockTagErrors_data()
542 {
543  QTest::addColumn<QString>("input");
544  QTest::addColumn<Dict>("dict");
545  QTest::addColumn<QString>("output");
546  QTest::addColumn<Cutelee::Error>("error");
547 
548  Dict dict;
549 
550  QTest::newRow("block-error-01") << QStringLiteral(
551  "{% block repeat %}{% endblock %}{% block repeat %}{% endblock %}")
552  << dict << QString() << TagSyntaxError;
553  QTest::newRow("block-error-02") << QStringLiteral("{% block %}{% endblock %}")
554  << dict << QString() << TagSyntaxError;
555  QTest::newRow("block-error-03")
556  << QStringLiteral("{% block foo bar %}{% endblock %}") << dict
557  << QString() << TagSyntaxError;
558 }
559 
560 void TestLoaderTags::testIncludeAndExtendsTag_data()
561 {
562  QTest::addColumn<QString>("input");
563  QTest::addColumn<Dict>("dict");
564  QTest::addColumn<QString>("output");
565  QTest::addColumn<Cutelee::Error>("error");
566 
567  Dict dict;
568 
569  loader->setTemplate(QStringLiteral("ext_base"),
570  QStringLiteral("{% block block1 %}block1{% endblock %}"));
571 
572  loader->setTemplate(QStringLiteral("extender"),
573  QStringLiteral("{% extends 'ext_base' %}{% block block1 "
574  "%}block1override{% endblock %}"));
575 
576  QTest::newRow("include-extender-twice") << QStringLiteral(R"django(
577 {% include "extender" %}
578 {% include "extender" %}
579 )django") << dict << QStringLiteral("\nblock1override\nblock1override\n")
580  << NoError;
581 
582  loader->setTemplate(QStringLiteral("anotherextender"),
583  QStringLiteral("{% extends 'extender' %}{% block block1 "
584  "%}block1overrideagain{% endblock %}"));
585 
586  QTest::newRow("include-deeper-extender-twice")
587  << QStringLiteral(R"django(
588 {% include "anotherextender" %}
589 {% include "anotherextender" %}
590 )django")
591  << dict << QStringLiteral("\nblock1overrideagain\nblock1overrideagain\n")
592  << NoError;
593 }
594 
595 QTEST_MAIN(TestLoaderTags)
596 #include "testloadertags.moc"
597 
598 #endif
The Context class holds the context to render a Template with.
Definition: context.h:119
void insert(const QString &name, QObject *object)
Definition: context.cpp:145
Cutelee::Engine is the main entry point for creating Cutelee Templates.
Definition: engine.h:121
Template loadByName(const QString &name) const
Definition: engine.cpp:370
void setPluginPaths(const QStringList &dirs)
Definition: engine.cpp:87
void addTemplateLoader(std::shared_ptr< AbstractTemplateLoader > loader)
Definition: engine.cpp:68
The FileSystemTemplateLoader loads Templates from the file system.
The InMemoryTemplateLoader loads Templates set dynamically in memory.
QString errorString() const
Definition: template.cpp:128
The Cutelee namespace holds all public Cutelee API.
Definition: Mainpage.dox:8