420 lines
9.4 KiB
Gleam
420 lines
9.4 KiB
Gleam
import gleam/map
|
|
import gleam/string_builder
|
|
import gleeunit/should
|
|
import glemplate/assigns.{Assigns, Bool, Int, Lazy, List, Map, String}
|
|
import glemplate/ast.{
|
|
Assign, Dynamic, FieldAccess, If, IndexAccess, Iter, NodeList, Nodes, Output,
|
|
RawOutput, Render, Template, Text,
|
|
}
|
|
import glemplate/renderer
|
|
|
|
pub fn empty_test() {
|
|
should.equal(render_to_string([], map.new()), "")
|
|
}
|
|
|
|
pub fn text_test() {
|
|
should.equal(
|
|
render_to_string([Text("foo"), Text(" bar "), Text("baz")], map.new()),
|
|
"foo bar baz",
|
|
)
|
|
}
|
|
|
|
pub fn nested_test() {
|
|
should.equal(
|
|
render_to_string(
|
|
[Nodes([Nodes([Text("foo")])]), Nodes([Nodes([Nodes([])])])],
|
|
map.new(),
|
|
),
|
|
"foo",
|
|
)
|
|
}
|
|
|
|
pub fn var_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", String("bar"))
|
|
should.equal(
|
|
render_to_string(
|
|
[Text("<b>"), Dynamic(Output(Assign("foo"))), Text("</b>")],
|
|
assigns,
|
|
),
|
|
"<b>bar</b>",
|
|
)
|
|
}
|
|
|
|
pub fn encoder_test() {
|
|
let assert Ok(builder) =
|
|
renderer.render(
|
|
Template(
|
|
name: "TestTpl",
|
|
nodes: [
|
|
Dynamic(Output(Assign("foo"))),
|
|
Dynamic(RawOutput(Assign("foo"))),
|
|
],
|
|
),
|
|
map.new()
|
|
|> map.insert("foo", String("🙂")),
|
|
renderer.RenderOptions(
|
|
encoder: fn(_content) { string_builder.from_string("🙃") },
|
|
template_cache: map.new(),
|
|
),
|
|
)
|
|
should.equal(string_builder.to_string(builder), "🙃🙂")
|
|
}
|
|
|
|
pub fn int_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Int(1_000_000))
|
|
should.equal(
|
|
render_to_string([Dynamic(Output(Assign("foo")))], assigns),
|
|
"1000000",
|
|
)
|
|
}
|
|
|
|
pub fn lazy_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Lazy(fn() { String("awesome") }))
|
|
should.equal(
|
|
render_to_string([Dynamic(Output(Assign("foo")))], assigns),
|
|
"awesome",
|
|
)
|
|
}
|
|
|
|
pub fn if_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Bool(True))
|
|
should.equal(
|
|
render_to_string(
|
|
[Dynamic(If(Assign("foo"), [Text("yes")], [Text("no")]))],
|
|
assigns,
|
|
),
|
|
"yes",
|
|
)
|
|
}
|
|
|
|
// Lazy function should not be called in code path that is not entered
|
|
pub fn if_lazy_test() {
|
|
let assigns: Assigns =
|
|
map.from_list([
|
|
#("foo", Bool(True)),
|
|
#(
|
|
"lazy",
|
|
Lazy(fn() {
|
|
should.fail()
|
|
Bool(False)
|
|
}),
|
|
),
|
|
])
|
|
should.equal(
|
|
render_to_string(
|
|
[
|
|
Dynamic(If(
|
|
Assign("foo"),
|
|
[Text("yes")],
|
|
[Dynamic(Output(Assign("lazy")))],
|
|
)),
|
|
],
|
|
assigns,
|
|
),
|
|
"yes",
|
|
)
|
|
}
|
|
|
|
pub fn iter_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", List([String("first"), Int(2), String("third")]))
|
|
should.equal(
|
|
render_to_string(
|
|
[
|
|
Dynamic(Iter(
|
|
Assign("foo"),
|
|
"bar",
|
|
[Text("* "), Dynamic(Output(Assign("bar"))), Text("\n")],
|
|
)),
|
|
],
|
|
assigns,
|
|
),
|
|
"* first\n* 2\n* third\n",
|
|
)
|
|
}
|
|
|
|
pub fn render_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("parent_assign", Bool(False))
|
|
should.equal(
|
|
render_to_string(
|
|
[
|
|
Text("child tpl -- "),
|
|
Dynamic(Render("ChildTpl", [#(Assign("parent_assign"), "child_assign")])),
|
|
Text(" -- end child tpl"),
|
|
],
|
|
assigns,
|
|
),
|
|
"child tpl -- child_assign is false -- end child tpl",
|
|
)
|
|
}
|
|
|
|
pub fn field_access_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Map(map.from_list([#("bar", String("baz"))])))
|
|
should.equal(
|
|
render_to_string(
|
|
[
|
|
Text("<b>"),
|
|
Dynamic(Output(FieldAccess(Assign("foo"), "bar"))),
|
|
Text("</b>"),
|
|
],
|
|
assigns,
|
|
),
|
|
"<b>baz</b>",
|
|
)
|
|
}
|
|
|
|
pub fn index_access_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", List([String("bar"), String("baz")]))
|
|
should.equal(
|
|
render_to_string(
|
|
[
|
|
Text("<b>"),
|
|
Dynamic(Output(IndexAccess(Assign("foo"), 1))),
|
|
Text("</b>"),
|
|
],
|
|
assigns,
|
|
),
|
|
"<b>baz</b>",
|
|
)
|
|
}
|
|
|
|
pub fn complex_test() {
|
|
let assigns: Assigns =
|
|
map.from_list([
|
|
#(
|
|
"user",
|
|
Map(map.from_list([
|
|
#("name", String("Nicd")),
|
|
#("registered", Lazy(fn() { String("2023-01-31") })),
|
|
#("points", Int(13_992_355_986)),
|
|
#("level", Int(32)),
|
|
#("paid", Bool(True)),
|
|
#(
|
|
"top_languages",
|
|
List([
|
|
String("Gleam"),
|
|
String("Elixir"),
|
|
String("TypeScript"),
|
|
String("JavaScript"),
|
|
String("Python"),
|
|
String("YaBasic"),
|
|
String("VHDL"),
|
|
String("GTLT"),
|
|
]),
|
|
),
|
|
])),
|
|
),
|
|
])
|
|
|
|
let str =
|
|
render_to_string(
|
|
[
|
|
Text("User information:\n"),
|
|
Text("\n"),
|
|
Nodes([
|
|
Dynamic(Output(FieldAccess(Assign("user"), "name"))),
|
|
Text(" - "),
|
|
Dynamic(Render(
|
|
"points.txt.glemp",
|
|
assigns_map: [
|
|
#(FieldAccess(Assign("user"), "level"), "level"),
|
|
#(FieldAccess(Assign("user"), "points"), "points"),
|
|
],
|
|
)),
|
|
Text("\n"),
|
|
]),
|
|
Text("Registered on "),
|
|
Dynamic(Output(FieldAccess(Assign("user"), "registered"))),
|
|
Dynamic(If(
|
|
FieldAccess(Assign("user"), "paid"),
|
|
[Text(" (awesome supporter).")],
|
|
[Text(".")],
|
|
)),
|
|
Text("\n\n"),
|
|
Text("User's top languages\n"),
|
|
Text("--------------------\n"),
|
|
Dynamic(Iter(
|
|
FieldAccess(Assign("user"), "top_languages"),
|
|
"lang",
|
|
[Text("* "), Dynamic(Output(Assign("lang"))), Text("\n")],
|
|
)),
|
|
],
|
|
assigns,
|
|
)
|
|
|
|
should.equal(
|
|
str,
|
|
"User information:
|
|
|
|
Nicd - 13992355986 XP (level 32)
|
|
Registered on 2023-01-31 (awesome supporter).
|
|
|
|
User's top languages
|
|
--------------------
|
|
* Gleam
|
|
* Elixir
|
|
* TypeScript
|
|
* JavaScript
|
|
* Python
|
|
* YaBasic
|
|
* VHDL
|
|
* GTLT
|
|
",
|
|
)
|
|
}
|
|
|
|
pub fn hayleigh_test() {
|
|
let assigns: Assigns =
|
|
map.from_list([
|
|
#("my_var", String(":)")),
|
|
#("pekka", Bool(False)),
|
|
#("some_items", List([String("first"), Int(2), String("third")])),
|
|
#("user", String("Nicd")),
|
|
])
|
|
|
|
let str =
|
|
render_to_string(
|
|
[
|
|
Text("<% <-- Escaped\n\n\n\nJotain tämmöstä <b>"),
|
|
Dynamic(Output(Assign("my_var"))),
|
|
Text("</b>.\nRaw variable: "),
|
|
Dynamic(RawOutput(Assign("my_var"))),
|
|
Text(".\n\n"),
|
|
Dynamic(If(
|
|
Assign("pekka"),
|
|
[Text("Olen pekka.\n")],
|
|
[Text("En ole pekka.\n")],
|
|
)),
|
|
Text("\n\n"),
|
|
Dynamic(Iter(
|
|
Assign("some_items"),
|
|
"item",
|
|
[Text(" * "), Dynamic(Output(Assign("item"))), Text("\n")],
|
|
)),
|
|
Text("\n\n\n"),
|
|
Dynamic(Render("some_template", [#(Assign("user"), "user")])),
|
|
],
|
|
assigns,
|
|
)
|
|
|
|
should.equal(
|
|
str,
|
|
"<% <-- Escaped\n\n\n\nJotain tämmöstä <b>:)</b>.\nRaw variable: :).\n\nEn ole pekka.\n\n\n * first\n * 2\n * third\n\n\n\n",
|
|
)
|
|
}
|
|
|
|
pub fn unstringifiable_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Bool(True))
|
|
should.be_error(render_tpl([Dynamic(Output(Assign("foo")))], assigns))
|
|
}
|
|
|
|
pub fn missing_assign_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo2", String("bar"))
|
|
should.be_error(render_tpl([Dynamic(Output(Assign("foo")))], assigns))
|
|
}
|
|
|
|
pub fn not_iterable_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", String("bar"))
|
|
should.be_error(render_tpl(
|
|
[Dynamic(Iter(Assign("foo"), "binding", []))],
|
|
assigns,
|
|
))
|
|
}
|
|
|
|
pub fn missing_child_test() {
|
|
let assigns: Assigns = map.new()
|
|
should.be_error(render_tpl([Dynamic(Render("no", []))], assigns))
|
|
}
|
|
|
|
fn render_to_string(nodes: NodeList, assigns: Assigns) {
|
|
let assert Ok(builder) = render_tpl(nodes, assigns)
|
|
|
|
string_builder.to_string(builder)
|
|
}
|
|
|
|
fn render_tpl(nodes: NodeList, assigns: Assigns) {
|
|
renderer.render(
|
|
Template(name: "TestTpl", nodes: nodes),
|
|
assigns,
|
|
renderer.RenderOptions(
|
|
encoder: fn(content) { string_builder.from_string(content) },
|
|
template_cache: map.from_list([
|
|
#(
|
|
"ChildTpl",
|
|
Template(
|
|
name: "ChildTpl",
|
|
nodes: [
|
|
Dynamic(If(
|
|
Assign("child_assign"),
|
|
[],
|
|
[Text("child_assign is false")],
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
#(
|
|
"points.txt.glemp",
|
|
Template(
|
|
name: "points.txt.glemp",
|
|
nodes: [
|
|
Dynamic(Output(Assign("points"))),
|
|
Text(" XP (level "),
|
|
Dynamic(Output(Assign("level"))),
|
|
Text(")"),
|
|
],
|
|
),
|
|
),
|
|
#("some_template", Template(name: "some_template", nodes: [])),
|
|
]),
|
|
),
|
|
)
|
|
}
|
|
|
|
pub fn missing_field_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", Map(map.from_list([#("bar", String("baz"))])))
|
|
should.be_error(render_tpl(
|
|
[
|
|
Text("<b>"),
|
|
Dynamic(Output(FieldAccess(Assign("foo"), "noooooo"))),
|
|
Text("</b>"),
|
|
],
|
|
assigns,
|
|
))
|
|
}
|
|
|
|
pub fn out_of_bounds_test() {
|
|
let assigns: Assigns =
|
|
map.new()
|
|
|> map.insert("foo", List([String("bar"), String("baz")]))
|
|
should.be_error(render_tpl(
|
|
[
|
|
Text("<b>"),
|
|
Dynamic(Output(IndexAccess(Assign("foo"), 100_000))),
|
|
Text("</b>"),
|
|
],
|
|
assigns,
|
|
))
|
|
}
|