mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
111 lines
3.3 KiB
JavaScript
111 lines
3.3 KiB
JavaScript
import { Tinytest } from "meteor/tinytest";
|
|
import { WebAppInternals } from "meteor/webapp";
|
|
import { onPageLoad } from "meteor/server-render";
|
|
import { parse } from "parse5";
|
|
import streamToString from "stream-to-string";
|
|
|
|
const skeleton = `
|
|
<h1>Look, Ma... static HTML!</h1>
|
|
<div id="container-2"></div>
|
|
<p>
|
|
<div id="container-1">
|
|
</div>
|
|
</p>`;
|
|
|
|
Tinytest.addAsync(
|
|
'server-render - boilerplate',
|
|
async function (test) {
|
|
// This test is not a very good demonstration of the server-render
|
|
// abstraction. In normal usage, you would call renderIntoElementById
|
|
// and not think about the rest of this stuff. The extra complexity owes
|
|
// to the trickiness of testing this package without using a real
|
|
// browser to parse the resulting HTTP response.
|
|
|
|
const realCallback =
|
|
// Use the underlying abstraction to set the static HTML skeleton.
|
|
WebAppInternals.registerBoilerplateDataCallback(
|
|
"meteor/server-render",
|
|
(request, data, arch) => {
|
|
if (request.isServerRenderTest) {
|
|
test.equal(arch, "web.browser");
|
|
test.equal(request.url, "/server-render/test");
|
|
data.body = skeleton;
|
|
}
|
|
return realCallback.call(this, request, data, arch);
|
|
}
|
|
);
|
|
|
|
const callback1 = onPageLoad(sink => {
|
|
sink.renderIntoElementById("container-1", "<oyez/>");
|
|
});
|
|
|
|
// This callback is async, and that's fine because
|
|
// WebAppInternals.getBoilerplate is able to yield. Internally the
|
|
// webapp package uses a function called getBoilerplateAsync, so the
|
|
// Fiber power-tools need not be involved in typical requests.
|
|
const callback2 = onPageLoad(async sink => {
|
|
sink.renderIntoElementById(
|
|
"container-2",
|
|
(await "oy") + (await "ez")
|
|
);
|
|
});
|
|
|
|
try {
|
|
const { stream } = WebAppInternals.getBoilerplate({
|
|
isServerRenderTest: true,
|
|
browser: { name: "fake" },
|
|
url: "/server-render/test",
|
|
}, "web.browser");
|
|
|
|
const boilerplate = await streamToString(stream);
|
|
|
|
const ids = [];
|
|
const seen = new Set;
|
|
|
|
function walk(node) {
|
|
if (node && ! seen.has(node)) {
|
|
seen.add(node);
|
|
|
|
if (node.nodeName === "div" && node.attrs) {
|
|
node.attrs.some(attr => {
|
|
if (attr.name === "id") {
|
|
const id = attr.value;
|
|
|
|
if (id === "container-1") {
|
|
test.equal(node.childNodes[0].nodeName, "oyez");
|
|
ids.push(id);
|
|
} else if (id === "container-2") {
|
|
const child = node.childNodes[0];
|
|
test.equal(child.nodeName, "#text");
|
|
test.equal(child.value.trim(), "oyez");
|
|
ids.push(id);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (node.childNodes) {
|
|
node.childNodes.forEach(walk)
|
|
}
|
|
}
|
|
}
|
|
|
|
walk(parse(boilerplate));
|
|
|
|
test.equal(ids, ["container-2", "container-1"]);
|
|
|
|
} finally {
|
|
// Cleanup to minimize interference with other tests:
|
|
WebAppInternals.registerBoilerplateDataCallback(
|
|
"meteor/server-render",
|
|
realCallback
|
|
);
|
|
|
|
onPageLoad.remove(callback1);
|
|
onPageLoad.remove(callback2);
|
|
}
|
|
}
|
|
);
|