fix tests

This commit is contained in:
James Baxley
2017-11-10 13:07:59 -05:00
committed by Ben Newman
parent 3a7f34d610
commit fb4e2b6f73
8 changed files with 382 additions and 271 deletions

View File

@@ -1,4 +1,4 @@
export function generateHTMLForArch(arch) {
export async function generateHTMLForArch(arch) {
// Use a dummy manifest. None of these paths will be read from the filesystem, but css / js should be handled differently
const manifest = [
{
@@ -50,5 +50,29 @@ export function generateHTMLForArch(arch) {
},
});
return boilerplate.toHTML();
const { start, stream, end } = boilerplate.toHTML();
const body = await toString(stream);
return start + body + end;
};
function toString(stream) {
return new Promise((success, fail) => {
var string = ''
stream.on('readable', function(buffer) {
var part = buffer.read().toString();
string += part;
});
stream.on('end', function() {
success(string)
});
stream.on('error', function(error) {
fail(error);
});
});
}

View File

@@ -2,62 +2,69 @@ import { parse, serialize } from 'parse5';
import { generateHTMLForArch } from './test-lib';
const html = generateHTMLForArch('web.browser');
const start = async () => {
const html = await generateHTMLForArch('web.browser');
Tinytest.add("boilerplate-generator-tests - web.browser - well-formed html", function (test) {
const formatted = serialize(parse(html));
test.isTrue(formatted.replace(/\s/g, '') === html.replace(/\s/g, ''));
});
Tinytest.add("boilerplate-generator-tests - web.browser - well-formed html", function (test) {
const formatted = serialize(parse(html));
test.isTrue(formatted.replace(/\s/g, '') === html.replace(/\s/g, ''));
});
Tinytest.add("boilerplate-generator-tests - web.browser - include htmlAttributes", function (test) {
test.matches(html, /foo="foobar"/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include htmlAttributes", function (test) {
test.matches(html, /foo="foobar"/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape htmlAttributes", function (test) {
test.matches(html, /gems="&""/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape htmlAttributes", function (test) {
test.matches(html, /gems="&""/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - escape css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - call rewriteHook", function (test) {
test.matches(html, /\+rewritten_url=true/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - call rewriteHook", function (test) {
test.matches(html, /\+rewritten_url=true/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include runtime config", function (test) {
test.matches(html, /<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/);
});
Tinytest.add("boilerplate-generator-tests - web.browser - include runtime config", function (test) {
test.matches(html, /<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/);
});
// https://github.com/meteor/meteor/issues/9149
Tinytest.add(
"boilerplate-generator-tests - web.browser - properly render boilerplate " +
"elements when _.template settings are overridden",
function (test) {
import { _ } from 'meteor/underscore';
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
const newHtml = generateHTMLForArch('web.browser');
test.matches(newHtml, /foo="foobar"/);
test.matches(newHtml, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
test.matches(newHtml, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
test.matches(newHtml, /<script>var a/);
test.matches(
newHtml,
/<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/
);
}
);
// https://github.com/meteor/meteor/issues/9149
Tinytest.addAsync(
"boilerplate-generator-tests - web.browser - properly render boilerplate " +
"elements when _.template settings are overridden",
function (test, onComplete) {
const run = async () => {
import { _ } from 'meteor/underscore';
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
const newHtml = await generateHTMLForArch('web.browser');
test.matches(newHtml, /foo="foobar"/);
test.matches(newHtml, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
test.matches(newHtml, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
test.matches(newHtml, /<script>var a/);
test.matches(
newHtml,
/<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/
);
}
run().then(onComplete);
}
);
};
start();

View File

@@ -2,53 +2,62 @@ import { parse, serialize } from 'parse5';
import { generateHTMLForArch } from './test-lib';
const html = generateHTMLForArch('web.cordova');
const start = async () => {
const html = await generateHTMLForArch('web.cordova');
Tinytest.add("boilerplate-generator-tests - web.cordova - well-formed html", function (test) {
const formatted = serialize(parse(html));
test.isTrue(formatted.replace(/\s/g, '') === html.replace(/\s/g, ''));
});
Tinytest.add("boilerplate-generator-tests - web.cordova - well-formed html", function (test) {
const formatted = serialize(parse(html));
test.isTrue(formatted.replace(/\s/g, '') === html.replace(/\s/g, ''));
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - escape js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - escape js", function (test) {
test.matches(html, /<script[^<>]*src="[^<>]*templating[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - escape css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - escape css", function (test) {
test.matches(html, /<link[^<>]*href="[^<>]*bootstrap[^<>]*&amp;v=&quot;1&quot;[^<>]*">/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - do not call rewriteHook", function (test) {
test.notMatches(html, /\+rewritten_url=true/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - do not call rewriteHook", function (test) {
test.notMatches(html, /\+rewritten_url=true/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include runtime config", function (test) {
test.matches(html, /<script[^<>]*>[^<>]*\n[^<>]*__meteor_runtime_config__ =[^<>]*decodeURIComponent\(config123\)\)/);
});
Tinytest.add("boilerplate-generator-tests - web.cordova - include runtime config", function (test) {
test.matches(html, /<script[^<>]*>[^<>]*\n[^<>]*__meteor_runtime_config__ =[^<>]*decodeURIComponent\(config123\)\)/);
});
// https://github.com/meteor/meteor/issues/9149
Tinytest.add(
"boilerplate-generator-tests - web.cordova - properly render boilerplate " +
"elements when _.template settings are overridden",
function (test) {
import { _ } from 'meteor/underscore';
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
const newHtml = generateHTMLForArch('web.cordova');
test.matches(newHtml, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
test.matches(newHtml, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
test.matches(newHtml, /<script>var a/);
test.matches(
newHtml,
/<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/
);
}
);
// https://github.com/meteor/meteor/issues/9149
Tinytest.addAsync(
"boilerplate-generator-tests - web.cordova - properly render boilerplate " +
"elements when _.template settings are overridden",
function (test, onComplete) {
const run = async () => {
import { _ } from 'meteor/underscore';
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
const newHtml = await generateHTMLForArch('web.cordova');
test.matches(newHtml, /<link[^<>]*href="[^<>]*bootstrap[^<>]*">/);
test.matches(newHtml, /<script[^<>]*src="[^<>]*templating[^<>]*">/);
test.matches(newHtml, /<script>var a/);
test.matches(
newHtml,
/<script[^<>]*>[^<>]*__meteor_runtime_config__ =.*decodeURIComponent\(config123\)/
);
}
run().then(onComplete)
}
);
};
start();

View File

@@ -45,18 +45,22 @@ WebAppInternals.registerBoilerplateDataCallback(
if (html) {
reallyMadeChanges = true;
const start = magic.slice(lastStart, loc.endOffset);
const end = magic.slice(loc.endOffset);
stream
.append(start)
.append(html)
.append(end)
.append(null);
lastStart = loc.endOffset;
}
return true;
}
});
});
parser.on("endTag", (name, location) => {
if (location.endOffset === html.length) {
// reached the end of the template
const end = magic.slice(lastStart);
stream.append(end).append(null);
}
})
data[property] = stream;
}

View File

@@ -3,6 +3,26 @@ import { WebAppInternals } from "meteor/webapp";
import { onPageLoad } from "meteor/server-render";
import { parse } from "parse5";
// convert a stream to a string via promise
function toString(stream) {
return new Promise((success, fail) => {
var string = ''
stream.on('data', function(data) {
string += data.toString();
});
stream.on('end', function() {
success(string)
});
stream.on('error', function(error) {
fail(error);
});
});
}
const skeleton = `
<h1>Look, Ma... static HTML!</h1>
<div id="container-2"></div>
@@ -11,94 +31,102 @@ const skeleton = `
</div>
</p>`;
Tinytest.add('server-render - boilerplate', 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.
Tinytest.addAsync('server-render - boilerplate', function (test, onComplete) {
const run = async () => {
// 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;
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);
}
return realCallback.call(this, request, data, arch);
}
);
);
const callback1 = onPageLoad(sink => {
sink.renderIntoElementById("container-1", "<oyez/>");
});
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")
);
});
// 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 boilerplate = WebAppInternals.getBoilerplate({
isServerRenderTest: true,
browser: { name: "fake" },
url: "/server-render/test"
}, "web.browser");
try {
const { start, stream, end } = WebAppInternals.getBoilerplate({
isServerRenderTest: true,
browser: { name: "fake" },
url: "/server-render/test"
}, "web.browser");
const ids = [];
const seen = new Set;
function walk(node) {
if (node && ! seen.has(node)) {
seen.add(node);
const body = await toString(stream);
const boilerplate = start + "\n" + body + "\n" + end;
if (node.nodeName === "div" && node.attrs) {
node.attrs.some(attr => {
if (attr.name === "id") {
const id = attr.value;
const ids = [];
const seen = new Set;
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);
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;
}
});
}
return true;
}
});
}
if (node.childNodes) {
node.childNodes.forEach(walk)
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);
}
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);
}
run().then(onComplete).catch(console.error);
});

View File

@@ -85,7 +85,6 @@ function appendContent(object, property, content) {
} else if ((content = content && content.toString("utf8"))) {
object[property] = (object[property] || "") + content;
madeChanges = true;
// should we join streams here?
}
return madeChanges;
}

View File

@@ -811,7 +811,6 @@ function runWebAppServer() {
headers = {...headers, ...newHeaders };
}
console.log("setting status code")
res.writeHead(statusCode, headers);
res.write(start);
stream.pipe(res, { end: false })

View File

@@ -8,6 +8,24 @@ var hash = crypto.createHash('sha1');
hash.update(additionalScript);
var additionalScriptPathname = hash.digest('hex') + ".js";
// convert a stream to a string via promise
function toString(stream) {
return new Promise((success, fail) => {
var string = ''
stream.on('data', function(data) {
string += data.toString();
});
stream.on('end', function() {
success(string)
});
stream.on('error', function(error) {
fail(error);
});
});
}
// Mock the 'res' object that gets passed to connect handlers. This mock
// just records any utf8 data written to the response and returns it
// when you call `mockResponse.getBody()`.
@@ -66,132 +84,155 @@ Tinytest.add("webapp - content-type header", function (test) {
"application/javascript; charset=utf-8");
});
Tinytest.add("webapp - additional static javascript", function (test) {
var origInlineScriptsAllowed = WebAppInternals.inlineScriptsAllowed();
Tinytest.addAsync("webapp - additional static javascript", function (test, onComplete) {
const run = async () => {
var origInlineScriptsAllowed = WebAppInternals.inlineScriptsAllowed();
var staticFilesOpts = {
staticFiles: {},
clientDir: "/"
};
var staticFilesOpts = {
staticFiles: {},
clientDir: "/"
};
// It's okay to set this global state because we're not going to yield
// before settng it back to what it was originally.
WebAppInternals.setInlineScriptsAllowed(true);
// It's okay to set this global state because we're not going to yield
// before settng it back to what it was originally.
WebAppInternals.setInlineScriptsAllowed(true);
(function () {
var boilerplate = WebAppInternals.getBoilerplate({
browser: "doesn't-matter",
url: "also-doesnt-matter"
}, "web.browser");
await (async function () {
const { start, stream, end } = WebAppInternals.getBoilerplate({
browser: "doesn't-matter",
url: "also-doesnt-matter"
}, "web.browser");
// When inline scripts are allowed, the script should be inlined.
test.isTrue(boilerplate.indexOf(additionalScript) !== -1);
const body = await toString(stream);
const boilerplate = start + body + end;
// And the script should not be served as its own separate resource,
// meaning that the static file handler should pass on this request.
var res = new MockResponse();
var req = new http.IncomingMessage();
req.headers = {};
req.method = "GET";
req.url = "/" + additionalScriptPathname;
var nextCalled = false;
WebAppInternals.staticFilesMiddleware(
staticFilesOpts, req, res, function () {
nextCalled = true;
});
test.isTrue(nextCalled);
})();
// When inline scripts are allowed, the script should be inlined.
test.isTrue(boilerplate.indexOf(additionalScript) !== -1);
// When inline scripts are disallowed, the script body should not be
// inlined, and the script should be included in a <script src="..">
// tag.
WebAppInternals.setInlineScriptsAllowed(false);
// And the script should not be served as its own separate resource,
// meaning that the static file handler should pass on this request.
var res = new MockResponse();
var req = new http.IncomingMessage();
req.headers = {};
req.method = "GET";
req.url = "/" + additionalScriptPathname;
var nextCalled = false;
WebAppInternals.staticFilesMiddleware(
staticFilesOpts, req, res, function () {
nextCalled = true;
});
test.isTrue(nextCalled);
(function () {
var boilerplate = WebAppInternals.getBoilerplate({
browser: "doesn't-matter",
url: "also-doesnt-matter"
}, "web.browser");
})();
// The script contents itself should not be present; the pathname
// where the script is served should be.
test.isTrue(boilerplate.indexOf(additionalScript) === -1);
test.isTrue(boilerplate.indexOf(additionalScriptPathname) !== -1);
// When inline scripts are disallowed, the script body should not be
// inlined, and the script should be included in a <script src="..">
// tag.
WebAppInternals.setInlineScriptsAllowed(false);
// And the static file handler should serve the script at that pathname.
var res = new MockResponse();
var req = new http.IncomingMessage();
req.headers = {};
req.method = "GET";
req.url = "/" + additionalScriptPathname;
WebAppInternals.staticFilesMiddleware(staticFilesOpts, req, res,
function () { });
var resBody = res.getBody();
test.isTrue(resBody.indexOf(additionalScript) !== -1);
test.equal(res.statusCode, 200);
})();
await (async function () {
const { start, stream, end } = WebAppInternals.getBoilerplate({
browser: "doesn't-matter",
browser: "doesn't-matter",
url: "also-doesnt-matter"
}, "web.browser");
WebAppInternals.setInlineScriptsAllowed(origInlineScriptsAllowed);
const body = await toString(stream);
const boilerplate = start + body + end;
// The script contents itself should not be present; the pathname
// where the script is served should be.
test.isTrue(boilerplate.indexOf(additionalScript) === -1);
test.isTrue(boilerplate.indexOf(additionalScriptPathname) !== -1);
// And the static file handler should serve the script at that pathname.
var res = new MockResponse();
var req = new http.IncomingMessage();
req.headers = {};
req.method = "GET";
req.url = "/" + additionalScriptPathname;
WebAppInternals.staticFilesMiddleware(staticFilesOpts, req, res,
function () { });
var resBody = res.getBody();
test.isTrue(resBody.indexOf(additionalScript) !== -1);
test.equal(res.statusCode, 200);
})();
WebAppInternals.setInlineScriptsAllowed(origInlineScriptsAllowed);
}
run().then(onComplete);
});
// Regression test: `generateBoilerplateInstance` should not change
// `__meteor_runtime_config__`.
Tinytest.add("webapp - generating boilerplate should not change runtime config", function (test) {
// Set a dummy key in the runtime config served in the
// boilerplate. Test that the dummy key appears in the boilerplate,
// but not in __meteor_runtime_config__ after generating the
// boilerplate.
Tinytest.addAsync("webapp - generating boilerplate should not change runtime config", function (test, onComplete) {
const run = async () => {
// Set a dummy key in the runtime config served in the
// boilerplate. Test that the dummy key appears in the boilerplate,
// but not in __meteor_runtime_config__ after generating the
// boilerplate.
test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);
test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);
var boilerplate = WebAppInternals.generateBoilerplateInstance(
"web.browser",
[], // empty manifest
{ runtimeConfigOverrides: { WEBAPP_TEST_KEY: true } }
);
var boilerplate = WebAppInternals.generateBoilerplateInstance(
"web.browser",
[], // empty manifest
{ runtimeConfigOverrides: { WEBAPP_TEST_KEY: true } }
);
var boilerplateHtml = boilerplate.toHTML();
test.isFalse(boilerplateHtml.indexOf("WEBAPP_TEST_KEY") === -1);
const { start, stream, end } = boilerplate.toHTML();
const body = await toString(stream);
const boilerplateHtml = start + stream + end;
test.isFalse(boilerplateHtml.indexOf("WEBAPP_TEST_KEY") === -1);
test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);
test.isFalse(__meteor_runtime_config__.WEBAPP_TEST_KEY);
};
run().then(onComplete);
});
Tinytest.add("webapp - WebAppInternals.registerBoilerplateDataCallback", function (test) {
const key = "from webapp_tests.js";
let callCount = 0;
Tinytest.addAsync("webapp - WebAppInternals.registerBoilerplateDataCallback", function (test, onComplete) {
const run = async () => {
const key = "from webapp_tests.js";
let callCount = 0;
function callback(request, data, arch) {
test.equal(arch, "web.browser");
test.equal(request.url, "http://example.com");
test.equal(data.dynamicHead.indexOf("so dynamic"), 0);
test.equal(data.body, "");
data.body = "<div>oyez</div>";
++callCount;
}
function callback(request, data, arch) {
test.equal(arch, "web.browser");
test.equal(request.url, "http://example.com");
test.equal(data.dynamicHead.indexOf("so dynamic"), 0);
test.equal(data.body, "");
data.body = "<div>oyez</div>";
++callCount;
}
WebAppInternals.registerBoilerplateDataCallback(key, callback);
WebAppInternals.registerBoilerplateDataCallback(key, callback);
test.equal(callCount, 0);
test.equal(callCount, 0);
const req = new http.IncomingMessage();
req.url = "http://example.com";
req.browser = { name: "headless" };
req.dynamicHead = "so dynamic";
const req = new http.IncomingMessage();
req.url = "http://example.com";
req.browser = { name: "headless" };
req.dynamicHead = "so dynamic";
const html = WebAppInternals.getBoilerplate(req, "web.browser");
const { start, stream, end } = WebAppInternals.getBoilerplate(req, "web.browser");
const body = await toString(stream);
test.equal(callCount, 1);
const html = start + "\n" + body + "\n" + end;
test.isTrue(html.indexOf([
"<body>",
"<div>oyez</div>"
].join("\n")) >= 0);
test.equal(callCount, 1);
test.equal(
// Make sure this callback doesn't get called again after this test.
WebAppInternals.registerBoilerplateDataCallback(key, null),
callback
);
test.isTrue(html.indexOf([
"<body>",
"<div>oyez</div>"
].join("\n")) >= 0);
test.equal(
// Make sure this callback doesn't get called again after this test.
WebAppInternals.registerBoilerplateDataCallback(key, null),
callback
);
};
run().then(onComplete);
});
// Support 'named pipes' (strings) as ports for support of Windows Server /