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 = "" }); 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: <script>alert()</script> \\Safe: \\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 = "
conteúdo
" }); 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: <div>conteúdo</div> | Safe:
conteúdo
", 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 = \\ \\{% block title %}Título Padrão{% endblock %} \\ \\{% block content %}Conteúdo padrão{% endblock %} \\ \\ ; const child = \\{% extends "base.html" %} \\{% block title %}Meu Título{% endblock %} \\{% block content %} \\Olá {{ nome }}! \\{% endblock %} ; const expected = \\ \\Meu Título \\ \\ \\Olá Lucas! \\ \\ \\ ; // 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, "") != 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 = \\ \\{% block title %}Título Padrão{% endblock %} \\ \\{% block content %}Conteúdo padrão{% endblock %} \\ \\ ; const child = \\{% extends "base.html" %} \\{% block title %}Meu Título{% endblock %} \\{% block content %} \\{{ block.super }} \\Olá {{ nome }}! \\{% endblock %} ; const expected = \\ \\Meu Título \\ \\ \\Conteúdo padrão \\Olá Lucas! \\ \\ \\ ; // 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, "") != 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 = \\
\\

Bem-vindo

\\
; const main = \\{% include "header.html" %} \\
\\

Conteúdo principal

\\ Olá {{ nome }}! \\
; const expected = \\
\\

Bem-vindo

\\
\\
\\

Conteúdo principal

\\ Olá Lucas! \\
; 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, "

Bem-vindo

") != 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 = "
Bem-vindo
"; const base = \\{% include "header.html" %} \\
\\ {% block content %} \\ Conteúdo padrão \\ {% endblock %} \\
; 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, "
Bem-vindo
") != null); try testing.expect(std.mem.indexOf(u8, output, "
") != 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 = \\
\\ {% block content %} \\ Conteúdo padrão \\ {% endblock %} \\
; 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 = \\
\\ {% block content %} \\ Conteúdo padrão \\ {% endblock %} \\
; const child = \\{% extends "base.html" %} \\{% block content %} \\ Conteúdo do filho \\Bar \\ {{ 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 = \\ ; 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, "

"); 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, "

"); 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, "

") != null); // const spaces = std.mem.count(u8, buf.items, "

"); // try testing.expect(spaces == 3); }