2022-05-22 00:03:48 +03:00
|
|
|
import { assertEquals } from "testing/asserts.ts";
|
2022-05-22 22:47:17 +03:00
|
|
|
import { TextNode } from "../core/node.ts";
|
|
|
|
import { E, F } from "./node.ts";
|
2022-05-22 00:03:48 +03:00
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
import { HtmlStrRenderer } from "./html_str.ts";
|
2022-05-22 00:03:48 +03:00
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render text node",
|
|
|
|
fn: () => {
|
|
|
|
const tn = new TextNode("hello world");
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(tn);
|
|
|
|
|
|
|
|
assertEquals(res, "hello world");
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render element",
|
|
|
|
fn: () => {
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
|
2022-06-13 17:58:22 +03:00
|
|
|
assertEquals(ren.render(E("p", [])), "<p></p>");
|
|
|
|
assertEquals(ren.render(E("p", [], "hello world")), "<p>hello world</p>");
|
|
|
|
assertEquals(
|
|
|
|
ren.render(E("p", [], ["hello", "world"])),
|
|
|
|
"<p>hello world</p>",
|
|
|
|
);
|
|
|
|
assertEquals(
|
|
|
|
ren.render(E("p", [], [E("span", [], "hello"), E("span", [], "world")])),
|
|
|
|
"<p><span>hello</span><span>world</span></p>",
|
|
|
|
);
|
|
|
|
assertEquals(
|
|
|
|
ren.render(E("p", [], ["hello", E("span", [], "world")])),
|
|
|
|
"<p>hello <span>world</span></p>",
|
|
|
|
);
|
|
|
|
assertEquals(
|
|
|
|
ren.render(E("p", [], [E("span", [], "hello"), "world"])),
|
|
|
|
"<p><span>hello</span> world</p>",
|
|
|
|
);
|
2022-05-22 00:03:48 +03:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render empty fragment as empty string",
|
|
|
|
fn: () => {
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-06-13 17:58:22 +03:00
|
|
|
assertEquals(ren.render(F([])), "");
|
2022-05-22 00:03:48 +03:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render fragment",
|
|
|
|
fn: () => {
|
|
|
|
const frag = F([
|
|
|
|
"hello world",
|
|
|
|
E("div", { class: "hello" }),
|
|
|
|
E("p", [], "world"),
|
|
|
|
]);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(frag);
|
|
|
|
|
2022-06-13 17:58:22 +03:00
|
|
|
assertEquals(res, 'hello world <div class="hello"></div><p>world</p>');
|
2022-05-22 00:03:48 +03:00
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should recursive render elements",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("body", [], [
|
|
|
|
E("div", { id: "root" }, [
|
|
|
|
E("p", [], "hello world"),
|
|
|
|
]),
|
|
|
|
]);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(res, '<body><div id="root"><p>hello world</p></div></body>');
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render attributes",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("body", { class: "body-lock" }, [
|
|
|
|
E("div", { id: "root" }, [
|
|
|
|
E("p", { class: "first" }, "hello world"),
|
|
|
|
]),
|
|
|
|
]);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<body class="body-lock"><div id="root"><p class="first">hello world</p></div></body>',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render default doctype if root node is html",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("html", []);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(res, "<!doctype html><html></html>");
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render custom doctype if root node is html",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("html", []);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer({
|
2022-05-22 00:03:48 +03:00
|
|
|
doctype:
|
|
|
|
'html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"',
|
|
|
|
});
|
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<!doctype html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html></html>',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
2022-05-22 00:13:39 +03:00
|
|
|
name: "should force render doctype if root node is not html",
|
2022-05-22 00:03:48 +03:00
|
|
|
fn: () => {
|
|
|
|
const layout = E("body", [], []);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer({ forceRenderDoctype: true });
|
2022-05-22 00:03:48 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(res, "<!doctype html><body></body>");
|
|
|
|
},
|
|
|
|
});
|
2022-05-22 22:47:17 +03:00
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should wrap node",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("body", [], []);
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer({
|
|
|
|
wrapNode: (node) => E("html", [], [node]),
|
|
|
|
});
|
2022-05-22 22:47:17 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(res, "<!doctype html><html><body></body></html>");
|
|
|
|
},
|
|
|
|
});
|
2022-05-29 01:41:24 +03:00
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should change attr key",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("a", {
|
|
|
|
target: "_blank",
|
|
|
|
href: "/hello/world",
|
|
|
|
rel: "nofollow noopener",
|
|
|
|
}, "hello world");
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer({
|
2022-05-29 01:41:24 +03:00
|
|
|
onVisitAttr: ([key, val]) => [`data-${key}`, val],
|
|
|
|
});
|
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<a data-target="_blank" data-href="/hello/world" data-rel="nofollow noopener">hello world</a>',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should change attr value",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("a", {
|
|
|
|
href: "/hello/world",
|
|
|
|
}, "hello world");
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer({
|
2022-05-29 01:41:24 +03:00
|
|
|
onVisitAttr: ([key, val]) => [key, "/eng" + val],
|
|
|
|
});
|
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<a href="/eng/hello/world">hello world</a>',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
2022-05-29 02:02:55 +03:00
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should filter attr",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("input", { type: "number", disabled: false });
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-29 02:02:55 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<input type="number">',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
Deno.test({
|
|
|
|
name: "should render boolean attr",
|
|
|
|
fn: () => {
|
|
|
|
const layout = E("input", { type: "number", disabled: true });
|
|
|
|
|
2022-06-08 23:48:35 +03:00
|
|
|
const ren = new HtmlStrRenderer();
|
2022-05-29 02:02:55 +03:00
|
|
|
const res = ren.render(layout);
|
|
|
|
|
|
|
|
assertEquals(
|
|
|
|
res,
|
|
|
|
'<input type="number" disabled>',
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|