zdt-prov/src/renderer_test.zig
2026-01-20 19:04:08 -03:00

1100 lines
32 KiB
Zig

const std = @import("std");
const testing = std.testing;
const Renderer = @import("renderer.zig").Renderer;
const RenderError = @import("renderer.zig").RenderError;
const Context = @import("context.zig").Context;
const Value = @import("context.zig").Value;
const TemplateCache = @import("cache.zig").TemplateCache;
test "renderer: literal + variável simples" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("1 - renderer: literal + variável simples\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("nome", Value{ .string = "Fulana" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
const template =
\\Olá, {{ nome }}! Bem-vinda.
;
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings("Olá, Fulana! Bem-vinda.", buf.items);
}
test "renderer: filtros + autoescape" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("2 - renderer: filtros + autoescape\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("html", Value{ .string = "<script>alert()</script>" });
try ctx.set("texto", Value{ .string = "maiusculo e slug" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
const template =
\\Normal: {{ html }}
\\Safe: {{ html|safe }}
\\Filtrado: {{ texto|upper|slugify }}
;
try renderer.renderString(template, buf.writer(alloc));
const expected =
\\Normal: &lt;script&gt;alert()&lt;/script&gt;
\\Safe: <script>alert()</script>
\\Filtrado: maiusculo-e-slug
;
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "literal simples" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("3 - literal simples\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
const template = "Texto literal com acentos: Olá, mundo!";
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings("Texto literal com acentos: Olá, mundo!", buf.items);
}
test "variável com filtro encadeado e autoescape" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("4 - variável com filtro encadeado e autoescape\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("texto", Value{ .string = "Exemplo de Texto" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
const template = "Resultado: {{ texto|lower|upper }}";
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings("Resultado: EXEMPLO DE TEXTO", buf.items); // assume lower then upper
}
test "autoescape com safe" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("5 - autoescape com safe\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("html", Value{ .string = "<div>conteúdo</div>" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
const template = "Escape: {{ html }} | Safe: {{ html|safe }}";
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings("Escape: &lt;div&gt;conteúdo&lt;/div&gt; | Safe: <div>conteúdo</div>", buf.items);
}
// // TODO: evaluationConditions more complex
test "renderer - if and for" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("6 - renderer - if and for\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("ativo", Value{ .bool = true });
try ctx.set("nomes", Value{ .list = &[_]Value{
Value{ .string = "Ana" },
Value{ .string = "Bia" },
Value{ .string = "Cris" },
} });
const template =
\\{% if ativo %}Sim!{% endif %}
\\{% if not ativo %}Não{% endif %}
\\Lista:
\\{% for nome in nomes %}
\\- {{ nome }}
\\{% endfor %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, buf.items, "Sim!") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "Não") == null);
try testing.expect(std.mem.indexOf(u8, buf.items, "- Ana") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "- Bia") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "- Cris") != null);
}
test "renderer - block and extends" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("7 - renderer - block and extends\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
const base =
\\<html>
\\<head><title>{% block title %}Título Padrão{% endblock %}</title></head>
\\<body>
\\{% block content %}Conteúdo padrão{% endblock %}
\\</body>
\\</html>
;
const child =
\\{% extends "base.html" %}
\\{% block title %}Meu Título{% endblock %}
\\{% block content %}
\\Olá {{ nome }}!
\\{% endblock %}
;
const expected =
\\<html>
\\<head><title>Meu Título</title></head>
\\<body>
\\
\\Olá Lucas!
\\
\\</body>
\\</html>
;
// Simula arquivos (ou usa renderString com base se quiser simplificar)
try std.fs.cwd().writeFile(.{ .sub_path = "base.html", .data = base });
try std.fs.cwd().writeFile(.{ .sub_path = "child.html", .data = child });
defer std.fs.cwd().deleteFile("base.html") catch {};
defer std.fs.cwd().deleteFile("child.html") catch {};
try ctx.set("nome", Value{ .string = "Lucas" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("child.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{output});
try testing.expect(std.mem.indexOf(u8, output, "<html>") != null);
try testing.expect(std.mem.indexOf(u8, output, "Meu Título") != null);
try testing.expect(std.mem.indexOf(u8, output, "Olá Lucas!") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo padrão") == null);
try testing.expectEqualStrings(expected, output);
}
test "renderer - block and extends with super" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("8 - renderer - block and extends with super\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
const base =
\\<html>
\\<head><title>{% block title %}Título Padrão{% endblock %}</title></head>
\\<body>
\\{% block content %}Conteúdo padrão{% endblock %}
\\</body>
\\</html>
;
const child =
\\{% extends "base.html" %}
\\{% block title %}Meu Título{% endblock %}
\\{% block content %}
\\{{ block.super }}
\\Olá {{ nome }}!
\\{% endblock %}
;
const expected =
\\<html>
\\<head><title>Meu Título</title></head>
\\<body>
\\
\\Conteúdo padrão
\\Olá Lucas!
\\
\\</body>
\\</html>
;
// Simula arquivos (ou usa renderString com base se quiser simplificar)
try std.fs.cwd().writeFile(.{ .sub_path = "base.html", .data = base });
try std.fs.cwd().writeFile(.{ .sub_path = "child.html", .data = child });
defer std.fs.cwd().deleteFile("base.html") catch {};
defer std.fs.cwd().deleteFile("child.html") catch {};
try ctx.set("nome", Value{ .string = "Lucas" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("child.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, output, "<html>") != null);
try testing.expect(std.mem.indexOf(u8, output, "Meu Título") != null);
try testing.expect(std.mem.indexOf(u8, output, "Olá Lucas!") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo padrão") != null);
try testing.expectEqualStrings(expected, output);
}
test "renderer - include" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("9 - renderer - include\n", .{});
const alloc = testing.allocator;
const header =
\\<header>
\\ <h1>Bem-vindo</h1>
\\</header>
;
const main =
\\{% include "header.html" %}
\\<main>
\\ <p>Conteúdo principal</p>
\\ Olá {{ nome }}!
\\</main>
;
const expected =
\\<header>
\\ <h1>Bem-vindo</h1>
\\</header>
\\<main>
\\ <p>Conteúdo principal</p>
\\ Olá Lucas!
\\</main>
;
try std.fs.cwd().writeFile(.{ .sub_path = "header.html", .data = header });
try std.fs.cwd().writeFile(.{ .sub_path = "main.html", .data = main });
defer std.fs.cwd().deleteFile("header.html") catch {};
defer std.fs.cwd().deleteFile("main.html") catch {};
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("nome", Value{ .string = "Lucas" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("main.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, output, "<h1>Bem-vindo</h1>") != null);
try testing.expect(std.mem.indexOf(u8, output, "Olá Lucas!") != null);
try testing.expectEqualStrings(expected, output);
}
test "renderer - comment" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("10 - renderer - comment\n", .{});
const alloc = testing.allocator;
const template =
\\Normal: Olá {{ nome }}
\\{% comment %}
\\ Isso é um comentário
\\ que não deve aparecer
\\ nem processar variáveis {{ nome }}
\\{% endcomment %}
\\Fim: {{ nome }}
;
const expected =
\\Normal: Olá Lucas
\\
\\Fim: Lucas
;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("nome", Value{ .string = "Lucas" });
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, output, "Olá Lucas") != null);
try testing.expect(std.mem.indexOf(u8, output, "Fim: Lucas") != null);
try testing.expect(std.mem.indexOf(u8, output, "Isso é um comentário") == null);
try testing.expect(std.mem.indexOf(u8, output, "que não deve aparecer") == null);
try testing.expect(std.mem.indexOf(u8, output, "nem processar variáveis") == null);
try testing.expectEqualStrings(expected, output);
}
test "renderer - full template with extends, super, include, comment" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("11 - renderer - full template with extends, super, include, comment\n", .{});
const alloc = testing.allocator;
const header = "<header>Bem-vindo</header>";
const base =
\\{% include "header.html" %}
\\<main>
\\ {% block content %}
\\ Conteúdo padrão
\\ {% endblock %}
\\</main>
;
const child =
\\{% extends "base.html" %}
\\{% block content %}
\\ {{ block.super }}
\\ Conteúdo do filho
\\ {% comment %} Isso não aparece {% endcomment %}
\\{% endblock %}
\\{% comment %} bazinga {% endcomment %}
;
try std.fs.cwd().writeFile(.{ .sub_path = "header.html", .data = header });
try std.fs.cwd().writeFile(.{ .sub_path = "base.html", .data = base });
try std.fs.cwd().writeFile(.{ .sub_path = "child.html", .data = child });
defer std.fs.cwd().deleteFile("header.html") catch {};
defer std.fs.cwd().deleteFile("base.html") catch {};
defer std.fs.cwd().deleteFile("child.html") catch {};
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("child.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{output});
try testing.expect(std.mem.indexOf(u8, output, "<header>Bem-vindo</header>") != null);
try testing.expect(std.mem.indexOf(u8, output, "<main>") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo padrão") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo do filho") != null);
try testing.expect(std.mem.indexOf(u8, output, "Isso não aparece") == null);
try testing.expect(std.mem.indexOf(u8, output, "bazinga") == null);
}
test "renderer - if inside block" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("12 - render - if inside block\n", .{});
const alloc = testing.allocator;
const base =
\\<main>
\\ {% block content %}
\\ Conteúdo padrão
\\ {% endblock %}
\\</main>
;
const child =
\\{% extends "base.html" %}
\\{% block content %}
\\ {{ block.super }}
\\ Conteúdo do filho
\\{% if idade > 18 %}
\\ Idade: {{ idade }}
\\{% else %}
\\ Oops
\\{% endif %}
\\{% endblock %}
;
try std.fs.cwd().writeFile(.{ .sub_path = "base.html", .data = base });
try std.fs.cwd().writeFile(.{ .sub_path = "child.html", .data = child });
defer std.fs.cwd().deleteFile("base.html") catch {};
defer std.fs.cwd().deleteFile("child.html") catch {};
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("idade", 23);
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("child.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{output});
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo padrão") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo do filho") != null);
try testing.expect(std.mem.indexOf(u8, output, "Oops") == null);
try testing.expect(std.mem.indexOf(u8, output, "Idade: 23") != null);
}
test "renderer - if with operators" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("13 - render - if inside block\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("idade", Value{ .int = 20 });
try ctx.set("nome", Value{ .string = "Lucas" });
try ctx.set("ativo", Value{ .bool = true });
try ctx.set("order", 1);
const template =
\\{% if idade > 18 %}Maior{% endif %}
\\{% if idade < 18 %}Menor{% endif %}
\\{% if nome == "Lucas" %}Olá Lucas{% endif %}
\\{% if ativo %}Ativo{% endif %}
\\{% if order >= 2 %}High Order{% else %}Low Order{% endif %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, buf.items, "Maior") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "Olá Lucas") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "Ativo") != null);
try testing.expect(std.mem.indexOf(u8, buf.items, "Menor") == null);
try testing.expect(std.mem.indexOf(u8, buf.items, "Low Order") != null);
}
test "renderer - widthratio inside block" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("14 - render - widthratio inside block\n", .{});
const alloc = testing.allocator;
const base =
\\<main>
\\ {% block content %}
\\ Conteúdo padrão
\\ {% endblock %}
\\</main>
;
const child =
\\{% extends "base.html" %}
\\{% block content %}
\\ Conteúdo do filho
\\<img src="bar.png" alt="Bar" height="10" width="{% widthratio value 400 %}">
\\ {{ block.super }}
\\{% endblock %}
;
try std.fs.cwd().writeFile(.{ .sub_path = "base.html", .data = base });
try std.fs.cwd().writeFile(.{ .sub_path = "child.html", .data = child });
defer std.fs.cwd().deleteFile("base.html") catch {};
defer std.fs.cwd().deleteFile("child.html") catch {};
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
cache.default_path = ".";
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("value", 50);
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.render("child.html", buf.writer(alloc));
const output = buf.items;
// std.debug.print("OUTPUT:\n\n{s}\n", .{output});
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo padrão") != null);
try testing.expect(std.mem.indexOf(u8, output, "Conteúdo do filho") != null);
}
test "renderer - now" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("15 - render now\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("idade", Value{ .int = 20 });
const template =
\\{% now %}
\\{% now \"Y-m-d H:i:s\" %}
\\{% now \"Y" %}
\\{% now \"m\" %}
\\{% now \"n\" %}
\\{% now \"d\" %}
\\{% now \"j\" %}
\\{% now \"F\" %}
\\{% now \"M\" %}
\\{% now \"l\" %}
\\{% now \"D\" %}
\\{% now \"H:i:s\" %}
\\{% now \"H\" %}
\\{% now \"G\" %}
\\{% now \"i\" %}
\\{% now \"s\" %}
\\{% now \"a\" %}
\\{% now \"A\" %}
\\{% now \"P\" %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
// try testing.expect(std.mem.indexOf(u8, buf.items, "Maior") != null);
}
test "renderer - csrf_token in context" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("15 - csrf_token in context\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const token: []const u8 = "zh5fyUSICjXNsDTtJCjl9A3O2dDSHhYFlIngAEO6PXK9NX56Z1XLEy7doYuPcE0u";
try ctx.set("csrf_token", token);
const template =
\\{% csrf_token %}
;
const expected =
\\<input type="hidden" name="csrfmiddlewaretoken" value="zh5fyUSICjXNsDTtJCjl9A3O2dDSHhYFlIngAEO6PXK9NX56Z1XLEy7doYuPcE0u">
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - csrf_token not in context" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("16 - csrf_token not in context\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% csrf_token %}
;
const expected =
\\
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
// TODO: add parse filters to variables
test "renderer - firstof withtout fallback" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("17 - firstof without fallback\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("var1", "");
try ctx.set("var2", "baz");
const template =
\\{% firstof var1 var2 %}
;
const expected =
\\baz
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - firstof with fallback" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("18 - firstof with fallback\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
try ctx.set("var1", "");
try ctx.set("var2", 0);
const template =
\\{% firstof var1 var2 "Oops no value!" %}
;
const expected =
\\Oops no value!
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - firstof without value in context" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("19 - firstof without value in context\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% firstof 0 true "Oops no value!" %}
;
const expected =
\\true
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - firstof missing vars" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("20 - firstof missing vars\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% firstof %}
;
const expected =
\\
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - firstof missing vars with fallback" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("21 - firstof missing vars with fallback\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% firstof "nothing here" %}
;
const expected =
\\nothing here
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
// std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings(expected, buf.items);
}
test "renderer - lorem" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("22 - lorem\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, buf.items, "Lorem ipsum") != null);
}
test "renderer - lorem with count and method words" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("23 - lorem with count and method words\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem 3 w %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expectEqualStrings("lorem ipsum dolor", buf.items);
}
test "renderer - lorem with count and method paragraphs" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("24 - lorem with count and method paragraphs\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem 5 p %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
const qty = std.mem.count(u8, buf.items, "<p>");
try testing.expect(std.mem.indexOf(u8, buf.items, "Lorem ipsum dolor") != null);
try testing.expect(qty == 5);
}
test "renderer - lorem only random" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("25 - lorem only random\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem true %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(buf.items.len > 0);
}
test "renderer - lorem words random" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("26 - lorem words random\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem 6 w true %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
const spaces = std.mem.count(u8, buf.items, " ");
try testing.expect(spaces == 5);
}
test "renderer - lorem paragraphs random" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("26 - lorem paragraphs random\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% lorem 3 p true %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
const spaces = std.mem.count(u8, buf.items, "<p>");
try testing.expect(spaces == 3);
}
test "renderer - svg" {
std.debug.print("____________________________________________________\n", .{});
std.debug.print("27 - svg\n", .{});
const alloc = testing.allocator;
var ctx = Context.init(alloc);
defer ctx.deinit();
var cache = TemplateCache.init(alloc);
try cache.initIcons();
defer cache.deinit();
const renderer = Renderer.init(&ctx, &cache);
const template =
\\{% svg material kangaroo %}
;
var buf = std.ArrayList(u8){};
defer buf.deinit(alloc);
try renderer.renderString(template, buf.writer(alloc));
std.debug.print("OUTPUT:\n\n{s}\n", .{buf.items});
try testing.expect(std.mem.indexOf(u8, buf.items, "<div class=\"svg-container\">") != null);
// const spaces = std.mem.count(u8, buf.items, "<p>");
// try testing.expect(spaces == 3);
}