Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-docgen

Documentation publishing for Pudu: articles, API references, navigation, search, and static websites

0.1.0Apache-2.01

InstallClose

TemplateTest.pudu

Pudu55 lines3.1 KB

GitHub ↗
1/** @Docgen.Template.Tests — templates fill metadata exactly and refuse malformed tags */2module PuduLangDocgen.TemplateTest34import Std.Io as Io5import Std.Test as Test6import PuduLangDocgen as Docgen7import PuduLangDocgen.Template as Template89/// Metadata used by every check.10fn context() -> Docgen.Meta {11  Docgen.Fields([12      ("title", Docgen.Text("A & B")), ("html", Docgen.Text("<b>x</b>")), ("count", Docgen.Whole(2)), ("on", Docgen.Flag(true)),13      ("off", Docgen.Flag(false)), ("empty", Docgen.Items([])), ("items", Docgen.Items([Docgen.Fields([("name", Docgen.Text("one"))]), Docgen.Fields([("name", Docgen.Text("two"))])])),14      ("words", Docgen.Items([Docgen.Text("a"), Docgen.Text("b")])), ("site", Docgen.Fields([("name", Docgen.Text("Docs")), ("owner", Docgen.Fields([("name", Docgen.Text("Team"))]))]))15    ])16}1718/// A template rendered against the shared metadata and one partial.19fn rendered(text: Str) -> Str {20  let partial = match Template.parse("[\{\{name\}\}]") {21    case Ok(nodes) => nodes22    case Err(_) => []23  }24  match Template.parse(text) {25    case Ok(nodes) => Template.render(&nodes, &context(), &mapOf([("item", partial)]))26    case Err(reason) => "error: " + reason27  }28}2930/// Runs every tag, section, lookup, and failure contract.31fn main() -> Int {32  let checks = Test.suite("Template", &[33      Test.equals("escaped value", &rendered("\{\{title\}\}"), &"A &amp; B"),34      Test.equals("raw values", &rendered("\{\{\{html\}\}\} \{\{& html\}\}"), &"<b>x</b> <b>x</b>"),35      Test.equals("numbers and flags", &rendered("\{\{count\}\} \{\{on\}\}"), &"2 true"),36      Test.equals("missing value empty", &rendered("[\{\{nope\}\}]"), &"[]"),37      Test.equals("list section", &rendered("\{\{#items\}\}<\{\{name\}\}>\{\{/items\}\}"), &"<one><two>"),38      Test.equals("scalar list with dot", &rendered("\{\{#words\}\}\{\{.\}\},\{\{/words\}\}"), &"a,b,"),39      Test.equals("truthy and falsy sections", &rendered("\{\{#on\}\}yes\{\{/on\}\}\{\{#off\}\}no\{\{/off\}\}\{\{#empty\}\}no\{\{/empty\}\}"), &"yes"),40      Test.equals("inverted sections", &rendered("\{\{^off\}\}a\{\{/off\}\}\{\{^empty\}\}b\{\{/empty\}\}\{\{^on\}\}c\{\{/on\}\}"), &"ab"),41      Test.equals("object section scopes", &rendered("\{\{#site\}\}\{\{name\}\}/\{\{title\}\}\{\{/site\}\}"), &"Docs/A &amp; B"),42      Test.equals("dotted names", &rendered("\{\{site.owner.name\}\}"), &"Team"),43      Test.equals("partials see the context", &rendered("\{\{#items\}\}\{\{>item\}\}\{\{/items\}\}"), &"[one][two]"),44      Test.equals("unknown partial empty", &rendered("a\{\{>none\}\}b"), &"ab"),45      Test.equals("comments dropped", &rendered("a\{\{! note \}\}b"), &"ab"),46      Test.equals("unclosed section", &rendered("\{\{#on\}\}x"), &"error: section on is not closed"),47      Test.equals("mismatched section", &rendered("\{\{#on\}\}x\{\{/off\}\}"), &"error: section on is closed by off"),48      Test.equals("stray close", &rendered("x\{\{/on\}\}"), &"error: section on is closed without being opened"),49      Test.equals("unclosed tag", &rendered("\{\{title"), &"error: tag is not closed")50    ])51  let ran = Test.run(&checks)52  for failure in Test.failuresOf(&ran) { let _printed = Io.writeErrorLine(failure) }53  Test.report(&ran)54}55