4 use Test::More tests=>147;
8 my $cgidir = File::Spec->catdir(BSE::Test::base_dir, 'cgi-bin');
9 ok(chdir $cgidir, "switch to CGI directory");
12 use BSE::API qw(bse_init bse_cfg bse_make_article);
18 use BSE::Util::SQL qw/sql_datetime/;
19 use DevHelp::Date qw(dh_strftime_sql_datetime);
21 sub template_test($$$$);
22 sub dyn_template_test($$$$);
24 my $parent = add_article
27 body=>'parent article doclink[shop|foo]',
28 lastModified => '2004-09-23 06:00:00',
31 ok($parent, "create section");
33 for my $name ('One', 'Two', 'Three') {
36 title => $name, parentid => $parent->{id},
37 body => "b[$name] - alpha, beta, gamma, delta, epsilon",
40 ok($kid, "creating kid $name");
44 my $grandkid = add_article
46 parentid => $kids[1]{id},
51 my $base_securl = $cfg->entryVar("site", "secureurl");
53 # make parent a step child of itself
54 require BSE::Admin::StepParents;
55 BSE::Admin::StepParents->add($parent, $parent);
57 is($parent->section->{id}, $parent->{id}, "parent should be it's own section");
58 is($kids[0]->section->{id}, $parent->{id}, "kids section should be the parent");
60 my $top = Articles->getByPkey(1);
61 ok($top, "grabbing Home page");
63 template_test "cfg", $top, <<TEMPLATE, <<EXPECTED;
64 <:cfg "no such section" somekey "default / value":>
69 template_test "formats", $top, <<TEMPLATE, <<EXPECTED;
70 <:arithmetic 10 |%05d:>
75 template_test "children_of", $top, <<TEMPLATE, <<EXPECTED;
76 <:iterator begin children_of $parent->{id}:><:
78 <:iterator end children_of:>
79 <:-.set myart = articles.getByPkey($parent->{id}):>
80 <:-.for a in [ myart.visible_kids ]:>
92 template_test "allkids_of", $top, <<TEMPLATE, <<EXPECTED;
93 <:iterator begin allkids_of $parent->{id}:><:
95 <:iterator end allkids_of:>
104 template_test "allkids_of filtered", $top, <<TEMPLATE, <<EXPECTED;
105 <:iterator begin allkids_of $parent->{id} filter: [title] =~ /o/i :><:
107 <:iterator end allkids_of:>
114 my @kidids = map $_->{id}, @kids;
115 template_test "inlines", $top, <<TEMPLATE, <<EXPECTED;
116 <:iterator begin inlines @kidids:><:
117 inline title:><:iterator end inlines:>
122 template_test "inlines filtered", $top, <<TEMPLATE, <<EXPECTED;
123 <:iterator begin inlines @kidids filter: [title] =~ /^T/ :><:
124 inline title:><:iterator end inlines:>
129 template_test "ifancestor positive", $kids[0], <<TEMPLATE, <<EXPECTED;
130 <:ifAncestor $parent->{id}:>Yes<:or:>No<:eif:>
135 template_test "ifancestor equal", $kids[0], <<TEMPLATE, <<EXPECTED;
136 <:ifAncestor $kids[0]{id}:>Yes<:or:>No<:eif:>
141 template_test "ifancestor negative", $kids[0], <<TEMPLATE, <<EXPECTED;
142 <:ifAncestor $kids[1]{id}:>Yes<:or:>No<:eif:>
147 template_test "children", $parent, <<TEMPLATE, <<EXPECTED;
148 <:iterator begin children:><:
150 <:iterator end children:>
158 template_test "embed children", $top, <<TEMPLATE, <<EXPECTED;
159 <:embed $parent->{id} test/children.tmpl:>
168 # test some of the newer basic tags
169 template_test "add", $top, <<TEMPLATE, <<EXPECTED;
179 template_test "concatenate", $top, <<TEMPLATE, <<EXPECTED;
180 <:concatenate one two:>
181 <:concatenate one "two " three:>
182 <:concatenate one [concatenate "two " three]:>
183 <:concatenate [concatenate "one" [concatenate "two" "three"]]:>
184 <:cat [cat "one" "two"] [concatenate "three" "four"]:>
193 template_test "cond", $top, <<TEMPLATE, <<EXPECTED;
194 <:cond 1 "true" false:>
195 <:cond 0 true false:>
196 <:cond "" true false:>
203 template_test "match", $top, <<'TEMPLATE', <<EXPECTED;
204 <:match "abc123" "(\d+)":>
205 <:match "abc 123" "(\w+)\s+(\w+)" "$2$1":>
206 <:match "abc 123" "(\w+)X(\w+)" "$2$1":>
207 <:match "abc 123" "(\w+)X(\w+)" "$2$1" "default":>
215 template_test "replace", $top, <<'TEMPLATE', <<EXPECTED;
216 <:replace "abc123" "(\d+)" "XXX" :>
217 <:replace "!!abc 123!!" "(\w+)\s+(\w+)" "$2$1":>
218 <:replace "abc 123" "(\w+)" "XXX" g:>
219 <:replace "abc 123" "X" "$1" :>
231 template_test "cases", $top, <<'TEMPLATE', <<EXPECTED;
234 <:lcfirst "AbC123 XYZ":>
235 <:ucfirst "aBc123 xyz":>
236 <:capitalize "alpha beta gamma":>
237 <:capitalize "'one day, but don't', 'we know'":>
238 <:capitalize "IBM stock soars":>
245 'One Day, But Don't', 'We Know'
249 template_test "arithmetic", $top, <<'TEMPLATE', <<EXPECTED;
251 <:arithmetic 2+[add 1 1]:>
252 <:arithmetic d2:1.234+1.542:>
253 <:arithmetic 2+ [add 1 2] + [undefinedtag x] + [add 1 1] + [undefinedtag2]:>
258 <:arithmetic 2+ [add 1 2] + [undefinedtag x] + [add 1 1] + [undefinedtag2]:>
261 template_test "nobodytext", $kids[0], <<'TEMPLATE', <<EXPECTED;
262 <:nobodytext article body:>
264 One - alpha, beta, gamma, delta, epsilon
268 my $formatted = dh_strftime_sql_datetime("%a %d/%m/%Y", $parent->lastModified);
269 template_test "date", $parent, <<'TEMPLATE', <<EXPECTED;
270 <:date "%a %d/%m/%Y" article lastModified:>
277 template_test "today", $parent, <<'TEMPLATE', strftime("%Y-%m-%d %d-%b-%Y\n", localtime);
278 <:today "%Y-%m-%d":> <:today:>
284 require Date::Format;
288 and skip("No Date::Format", 3);
290 my $today = Date::Format::strftime("%a %o %B %Y", [ localtime ]);
291 my $mod = dh_strftime_sql_datetime("%A %o %B %Y", $parent->lastModified);
292 template_test "date/today w/Date::Format", $parent, <<'TEMPLATE', <<EXPECTED;
293 <:date "%A %o %B %Y" article lastModified:> <:today "%a %o %B %Y":>
299 template_test "strepeats", $parent, <<'TEMPLATE', <<EXPECTED;
300 <:iterator begin strepeats [arithmetic 1+1]:><:strepeat index:> <:strepeat value:>
301 <:iterator end strepeats:>
308 template_test "strepeats2", $parent, <<'TEMPLATE', <<EXPECTED;
309 <:iterator begin strepeats [arithmetic 1+1] 5:><:strepeat index:> <:strepeat value:>
310 <:iterator end strepeats:>
320 my $mod_iso = dh_strftime_sql_datetime("%FT%T%z", $parent->lastModified);
321 (my $mod_iso2 = $mod_iso) =~ s/(\d\d)$/:$1/;
322 template_test "quotedreplace", $parent, <<'TEMPLATE', <<EXPECTED;
323 <:date "%FT%T%z" article lastModified:>
324 <meta name="DC.title" content="<:article title:>" />
325 <meta name="DC.date" content="<:replace [date "%FT%T%z" article lastModified] "(\d\d)$" ":$1":>" />
326 <meta name="DC.format" content="<:cfg site format "text/html":>" />
329 <meta name="DC.title" content="Parent" />
330 <meta name="DC.date" content="$mod_iso2" />
331 <meta name="DC.format" content="text/html" />
335 template_test "report", $parent, <<'TEMPLATE', <<EXPECTED;
336 <:report bse_test test/testrep 2:>
337 <:report bse_test test/testrep [article id]:>
347 template_test "body", $parent, <<'TEMPLATE', <<EXPECTED;
350 <p>parent article <a href="$base_securl/shop/" title="The Shop" class="doclink">foo</a></p>
353 # not actually generation tests, but chekcs that the is_step_ancestor works
354 ok($kids[0]->is_step_ancestor($parent->{id}),
355 "is_step_ancestor - check normal parent");
356 ok($parent->is_step_ancestor($parent->{id}),
357 "is_step_ancestor - check step parent");
358 ok(!$parent->is_step_ancestor($kids[0]),
359 "is_step_ancestor - failure check");
361 # and test the static tag
362 template_test "ifStepAncestor 1", $parent, <<'TEMPLATE', <<EXPECTED;
363 <:ifStepAncestor article:>Good<:or:>bad<:eif:>
364 <:ifStepAncestor 3:>Bad<:or:>Good<:eif:>
370 template_test "ifStepAncestor 2", $kids[0], <<TEMPLATE, <<EXPECTED;
371 <:ifStepAncestor parent:>Good<:or:>bad<:eif:>
372 <:ifStepAncestor article:>Good<:or:>Bad<:eif:>
373 <:ifStepAncestor $kids[2]{id}:>Bad<:or:>Good<:eif:>
380 template_test "ifAnd dynamic cfg ajax", $parent, <<TEMPLATE, <<EXPECTED;
381 <:ifAnd [ifDynamic] [cfg basic ajax]:>1<:or:>0<:eif:>
386 template_test "replace complex re", $parent, <<'TEMPLATE', <<EXPECTED;
387 <:replace "test&test 01234567890123456789" ((?:&[^;]*;|[^&]){16}).* $1...:>
389 test&test 012345...
392 template_test "summary", $kids[0], <<'TEMPLATE', <<EXPECTED;
394 <:summary article 14:>
396 One - alpha, beta, gamma, delta,...
400 template_test "ifUnderThreshold parent children", $parent, <<'TEMPLATE', <<EXPECTED;
401 <:ifUnderThreshold:>1<:or:>0<:eif:>
402 <:ifUnderThreshold children:>1<:or:>0<:eif:>
408 template_test "ifUnderThreshold parent allkids", $parent, <<'TEMPLATE', <<EXPECTED;
409 <:ifUnderThreshold allkids:>1<:or:>0<:eif:>
414 template_test "ifUnderThreshold parent stepkids", $parent, <<'TEMPLATE', <<EXPECTED;
415 <:ifUnderThreshold stepkids:>1<:or:>0<:eif:>
420 template_test "ifUnderThreshold child children", $kids[0], <<'TEMPLATE', <<EXPECTED;
421 <:ifUnderThreshold:>1<:or:>0<:eif:>
422 <:ifUnderThreshold children:>1<:or:>0<:eif:>
428 template_test "ifUnderThreshold child allkids", $kids[0], <<'TEMPLATE', <<EXPECTED;
429 <:ifUnderThreshold allkids:>1<:or:>0<:eif:>
434 template_test "ifUnderThreshold child stepkids", $kids[0], <<'TEMPLATE', <<EXPECTED;
435 <:ifUnderThreshold stepkids:>1<:or:>0<:eif:>
440 template_test "noreplace undefined", $parent, <<'TEMPLATE', <<'EXPECTED';
441 <:switch:><:case Dynallkids_of2 dynofallkid filter: [listed] != 2 :><:if Or [ifAncestor dynofallkid] [ifEq [cgi catid] [dynofallkid id]]:>
443 <:iterator begin dynallkids_of2 dynofallkid filter: [listed] != 2 && [generator] =~ /Catalog/ :>
445 <:ifEq [dynarticle id] [dynofallkid2 id]:> focus<:or:><:eif:>
446 <:ifAncestor dynofallkid2:> hilite<:or:><:eif:>
447 <:ifFirstDynofallkid2:> first<:or:><:eif:>
448 <:ifLastDynofallkid2:> last<:or:><:eif:>
449 <:ifDynallkids_of3 dynofallkid2 filter: [listed] != 2 :> parent<:or:><:eif:>
450 <:ifDynofallkid2 titleAlias:><:dynofallkid2 titleAlias:><:or:><:dynofallkid2 title:><:eif:>
451 <:iterator separator dynallkids_of2:>
452 <:iterator end dynallkids_of2:>
453 <:or Or:><:eif Or:><:endswitch:>
455 <:switch:><:case Dynallkids_of2 dynofallkid filter: [listed] != 2 :><:if Or [ifAncestor dynofallkid] [ifEq [cgi catid] [dynofallkid id]]:>
457 <:iterator begin dynallkids_of2 dynofallkid filter: [listed] != 2 && [generator] =~ /Catalog/ :>
459 <:ifEq [dynarticle id] [dynofallkid2 id]:> focus<:or:><:eif:>
460 <:ifAncestor dynofallkid2:> hilite<:or:><:eif:>
461 <:ifFirstDynofallkid2:> first<:or:><:eif:>
462 <:ifLastDynofallkid2:> last<:or:><:eif:>
463 <:ifDynallkids_of3 dynofallkid2 filter: [listed] != 2 :> parent<:or:><:eif:>
464 <:ifDynofallkid2 titleAlias:><:dynofallkid2 titleAlias:><:or:><:dynofallkid2 title:><:eif:>
465 <:iterator separator dynallkids_of2:>
466 <:iterator end dynallkids_of2:>
467 <:or Or:><:eif Or:><:endswitch:>
470 ############################################################
472 require BSE::Dynamic::Article;
473 require BSE::Request::Test;
474 my $req = BSE::Request::Test->new(cfg => $cfg);
475 my $gen = BSE::Dynamic::Article->new($req);
477 dyn_template_test "dynallkidsof", $parent, <<TEMPLATE, <<EXPECTED;
478 <:iterator begin dynallkids_of $parent->{id} filter: [title] =~ /o/i :><:
479 dynofallkid title:> <:next_dynofallkid title:> <:previous_dynofallkid title:>
480 next: <:ifNextDynofallkid:>Y<:or:>N<:eif:>
481 previous: <:ifPreviousDynofallkid:>Y<:or:>N<:eif:>
482 <:iterator end dynallkids_of:>
493 dyn_template_test "dynallkidsof nested", $parent, <<TEMPLATE, <<EXPECTED;
494 <:iterator begin dynallkids_of $parent->{id} filter: [title] =~ /o/i :><:
495 dynofallkid title:><:iterator begin dynallkids_of2 dynofallkid:>
496 <:dynofallkid2 title:><:iterator end dynallkids_of2:>
497 <:iterator end dynallkids_of:>
505 dyn_template_test "dynallkidsof nested filtered cond", $parent, <<TEMPLATE, <<EXPECTED;
506 <:iterator begin dynallkids_of dynarticle:><:dynofallkid title:><:if Dynallkids_of2 dynofallkid filter: [title] =~ /G/:><:iterator begin dynallkids_of2 dynofallkid filter: [title] =~ /G/:>
507 <:dynofallkid2 title:><:iterator end dynallkids_of2:><:or Dynallkids_of2:>
508 No G kids<:eif Dynallkids_of2:>
509 <:iterator end dynallkids_of:>
522 dyn_template_test "dynallkids_of move_dynofallkid", $parent, <<TEMPLATE, <<EXPECTED;
523 <:iterator begin dynallkids_of dynarticle:><:dynofallkid title:><:move_dynofallkid:>
524 <:iterator end dynallkids_of:>
533 ############################################################
536 BSE::Admin::StepParents->del($parent, $parent);
537 $grandkid->remove($cfg);
538 for my $kid (reverse @kids) {
539 my $name = $kid->{title};
540 my $kidid = $kid->{id};
542 ok(1, "removing kid $name ($kidid)");
544 $parent->remove($cfg);
545 ok(1, "removed parent");
550 my $article = bse_make_article(cfg => $cfg, parentid => -1, %parms);
555 sub template_test($$$$) {
556 my ($tag, $article, $template, $expected) = @_;
558 #diag "Template >$template<";
561 (my $filename = $article->{generator}) =~ s!::!/!g;
564 $article->{generator}->new(cfg => $cfg, top => $article);
566 ok($gen, "$tag: created generator $article->{generator}");
570 skip "$tag: couldn't make generator", 1 unless $gen;
573 $gen->generate_low($template, $article, 'Articles', 0);
575 ok($content, "$tag: generate content");
576 diag $@ unless $content;
579 skip "$tag: couldn't gen content", 1 unless $content;
580 is($content, $expected, "$tag: comparing");
584 sub dyn_template_test($$$$) {
585 my ($tag, $article, $template, $expected) = @_;
587 #diag "Template >$template<";
590 my $gen_class = $article->{generator};
591 $gen_class =~ s/.*\W//;
592 $gen_class = "BSE::Dynamic::".$gen_class;
593 (my $filename = $gen_class) =~ s!::!/!g;
596 $gen_class->new($req);
598 ok($gen, "$tag: created generator $article->{generator}");
601 # get the template - always regen it
602 my $work_template = _generate_dyn_template($article, $template);
606 skip "$tag: couldn't make generator", 1 unless $gen;
609 $gen->generate($article, $work_template);
611 ok($result, "$tag: generate content");
612 diag $@ unless $result;
615 skip "$tag: couldn't gen content", 1 unless $result;
616 is($result->{content}, $expected, "$tag: comparing");
620 sub _generate_dyn_template {
621 my ($article, $template) = @_;
623 my $articles = 'Articles';
624 my $genname = $article->{generator};
627 my $gen = $genname->new(articles=>$articles, cfg=>$cfg, top=>$article);
629 return $gen->generate_low($template, $article, $articles, 0);