Skip to content

Instantly share code, notes, and snippets.

@danott
Created December 21, 2023 23:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danott/d7743e012697fc85c8aacf150b8696a4 to your computer and use it in GitHub Desktop.
Save danott/d7743e012697fc85c8aacf150b8696a4 to your computer and use it in GitHub Desktop.
Embracing the grain of the web's <template> and <slot> tags for rendering declarative markup on the server.
class HtmlRenderingTest < Minitest::Test
CRUST = <<~HTML.strip
<!doctype html>
<html lang="en">
<head>
<title><server-side-slot name="title"><%= title %></server-side-slot></title>
<server-side-slot name="head"></server-side-slot>
<% meta.each do |name, content| %>
<meta name="<%= name %>" content="<%= content %>">
<% end %>
</head>
<time><%= date %></time>
<server-side-slot name="body">Fallback for body slot in crust.</server-side-slot>
</html>
HTML
MANTLE = <<~HTML.strip
<server-side-layout name="crust">
<server-side-template slot="head">
<server-side-slot name="head"></server-side-slot>
<link rel="mantle" href="https://www.example.com">
</server-side-template>
<server-side-slot name="body">Fallback for body slot in mantle.</server-side-slot>
<p>Here is another random number: <%= Random.rand %></p>
</server-side-layout>
HTML
CORE = <<~HTML.strip
<server-side-layout name="mantle">
<server-side-template slot="title">Inner Title</server-side-template>
<server-side-template slot="head">
<link rel="inner" href="https://www.example.com">
</server-side-template>
<h1>This is the title</h1>
<p>Here is a random number: <%= Random.rand %></p>
</server-side-layout>
HTML
DATA = {
"title" => "Default Title",
"date" => Date.new(2023, 1, 2),
"meta" => {
"hello" => "world",
"howdy" => "partner"
}
}
LAYOUTS = { "core" => CORE, "mantle" => MANTLE, "crust" => CRUST }
def test_rendering_three_layers_deep
rendered = HtmlRendering.new(DATA.merge("layout" => "core"), LAYOUTS).html
refute_includes rendered, "<title>Default Title</title>"
assert_includes rendered, "<title>Inner Title</title>"
assert_includes rendered, '<meta name="hello" content="world">'
assert_includes rendered, '<meta name="howdy" content="partner">'
assert_includes rendered, "Here is a random number:"
assert_includes rendered, "Here is another random number:"
refute_includes rendered, "Random.rand"
refute_includes rendered, "Fallback for body slot in mantle."
refute_includes rendered, "Fallback for body slot in crust."
end
def test_rendering_two_layers_deep
rendered = HtmlRendering.new(DATA.merge("layout" => "mantle"), LAYOUTS).html
assert_includes rendered, "<title>Default Title</title>"
assert_includes rendered, '<meta name="hello" content="world">'
assert_includes rendered, '<meta name="howdy" content="partner">'
refute_includes rendered, "Here is a random number:"
assert_includes rendered, "Here is another random number:"
refute_includes rendered, "Random.rand"
assert_includes rendered, "Fallback for body slot in mantle."
refute_includes rendered, "Fallback for body slot in crust."
end
def test_rendering_one_layer
rendered = HtmlRendering.new(DATA.merge("layout" => "crust"), LAYOUTS).html
assert_includes rendered, "<title>Default Title</title>"
assert_includes rendered, '<meta name="hello" content="world">'
assert_includes rendered, '<meta name="howdy" content="partner">'
refute_includes rendered, "Here is a random number:"
refute_includes rendered, "Here is another random number:"
refute_includes rendered, "Random.rand"
refute_includes rendered, "Fallback for body slot in mantle."
assert_includes rendered, "Fallback for body slot in crust."
end
def test_double_rendering_is_fine
instance = HtmlRendering.new(DATA.merge("layout" => "core"), LAYOUTS)
first_render = instance.html
second_render = instance.render.render.html
assert_equal first_render, second_render
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment