mirror of https://github.com/zulip/zulip.git
tests: Compile Handlebars templates with source maps.
This allows us to collect coverage for Handlebars templates, and also improves the readability of Handlebars-related stack traces. Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This commit is contained in:
parent
36a8e61e67
commit
4889a0486d
|
@ -1,52 +1,58 @@
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
const Handlebars = require("handlebars/dist/cjs/handlebars.js");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const { SourceMapConsumer, SourceNode } = require("source-map");
|
||||||
|
|
||||||
const templates_path = path.resolve(__dirname, "../../static/templates");
|
const templates_path = path.resolve(__dirname, "../../static/templates");
|
||||||
let render;
|
|
||||||
|
|
||||||
exports.make_handlebars = () => {
|
exports.make_handlebars = () => Handlebars.create();
|
||||||
// Create a new Handlebars instance.
|
|
||||||
const Handlebars = require("handlebars/dist/cjs/handlebars.js");
|
|
||||||
const hb = Handlebars.create();
|
|
||||||
|
|
||||||
const compiled = new Set();
|
|
||||||
const compileFile = filename => {
|
|
||||||
const name = "$" + path.relative(templates_path, filename);
|
|
||||||
if (!compiled.has(name)) {
|
|
||||||
compiled.add(name);
|
|
||||||
hb.registerPartial(
|
|
||||||
name,
|
|
||||||
hb.compile(fs.readFileSync(filename, "utf-8"), { preventIndent: true, zjsFilename: filename })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ZJavaScriptCompiler extends hb.JavaScriptCompiler {
|
|
||||||
nameLookup(parent, name, type) {
|
|
||||||
// Auto-register partials with relative paths, like handlebars-loader.
|
|
||||||
if (type === "partial" && name !== "@partial-block") {
|
|
||||||
name = compileFile(path.resolve(path.dirname(this.options.zjsFilename), name + ".hbs"));
|
|
||||||
}
|
|
||||||
return super.nameLookup(parent, name, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZJavaScriptCompiler.prototype.compiler = ZJavaScriptCompiler;
|
|
||||||
hb.JavaScriptCompiler = ZJavaScriptCompiler;
|
|
||||||
|
|
||||||
render = (filename, ...args) => hb.partials[compileFile(filename)](...args);
|
|
||||||
|
|
||||||
return hb;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.stub_templates = stub => {
|
exports.stub_templates = stub => {
|
||||||
render = (filename, ...args) => {
|
window.template_stub = stub;
|
||||||
const name = path.relative(templates_path, filename).slice(0, -".hbs".length);
|
|
||||||
return stub(name, ...args);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hb = Handlebars.create();
|
||||||
|
|
||||||
|
class ZJavaScriptCompiler extends hb.JavaScriptCompiler {
|
||||||
|
nameLookup(parent, name, type) {
|
||||||
|
// Auto-register partials with relative paths, like handlebars-loader.
|
||||||
|
if (type === "partial" && name !== "@partial-block") {
|
||||||
|
const filename = path.resolve(path.dirname(this.options.srcName), name + ".hbs");
|
||||||
|
return ["require(", JSON.stringify(filename), ")"];
|
||||||
|
}
|
||||||
|
return super.nameLookup(parent, name, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZJavaScriptCompiler.prototype.compiler = ZJavaScriptCompiler;
|
||||||
|
hb.JavaScriptCompiler = ZJavaScriptCompiler;
|
||||||
|
|
||||||
require.extensions[".hbs"] = (module, filename) => {
|
require.extensions[".hbs"] = (module, filename) => {
|
||||||
module.exports = (...args) => render(filename, ...args);
|
const code = fs.readFileSync(filename, "utf-8");
|
||||||
|
const name = path.relative(templates_path, filename).slice(0, -".hbs".length);
|
||||||
|
const pc = hb.precompile(code, { preventIndent: true, srcName: filename });
|
||||||
|
const node = new SourceNode();
|
||||||
|
node.add([
|
||||||
|
"let hb, template;\n",
|
||||||
|
"module.exports = (...args) => {\n",
|
||||||
|
" if (window.template_stub !== undefined) {\n",
|
||||||
|
" return window.template_stub(",
|
||||||
|
JSON.stringify(name),
|
||||||
|
", ...args);\n",
|
||||||
|
" }\n",
|
||||||
|
" if (hb !== Handlebars) {\n",
|
||||||
|
" template = (hb = Handlebars).template(",
|
||||||
|
SourceNode.fromStringWithSourceMap(pc.code, new SourceMapConsumer(pc.map)),
|
||||||
|
");\n",
|
||||||
|
" }\n",
|
||||||
|
" return template(...args);\n",
|
||||||
|
"};\n",
|
||||||
|
]);
|
||||||
|
const out = node.toStringWithSourceMap();
|
||||||
|
module._compile(
|
||||||
|
out.code +
|
||||||
|
"\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," +
|
||||||
|
Buffer.from(out.map.toString()).toString("base64"),
|
||||||
|
filename
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,7 +202,7 @@ def run_tests_via_node_js() -> int:
|
||||||
coverage_lcov_file = os.path.join(coverage_dir, 'lcov.info')
|
coverage_lcov_file = os.path.join(coverage_dir, 'lcov.info')
|
||||||
|
|
||||||
nyc = os.path.join(ROOT_DIR, 'node_modules/.bin/nyc')
|
nyc = os.path.join(ROOT_DIR, 'node_modules/.bin/nyc')
|
||||||
command = [nyc, '--extension', '.ts']
|
command = [nyc, '--extension', '.hbs', '--extension', '.ts']
|
||||||
command += ['--report-dir', coverage_dir]
|
command += ['--report-dir', coverage_dir]
|
||||||
command += ['--temp-directory', coverage_dir, '-r=text-summary']
|
command += ['--temp-directory', coverage_dir, '-r=text-summary']
|
||||||
command += node_tests_cmd
|
command += node_tests_cmd
|
||||||
|
|
Loading…
Reference in New Issue