mirror of
https://github.com/zulip/zulip.git
synced 2025-11-15 19:31:58 +00:00
We want to undo overrides in reverse order, which is important if you override the same name more than once in the same function. Until today the code basically prevented us from ever using the original implementation of a name we stubbed, and most of them start as undefined due to their parent modules starting with `set_global`. But I do want this proper, and I introduced a tiny pitfall today.
114 lines
3.0 KiB
JavaScript
114 lines
3.0 KiB
JavaScript
const requires = [];
|
|
const new_globals = new Set();
|
|
let old_globals = {};
|
|
|
|
exports.set_global = function (name, val) {
|
|
if (!(name in old_globals)) {
|
|
if (!(name in global)) {
|
|
new_globals.add(name);
|
|
}
|
|
old_globals[name] = global[name];
|
|
}
|
|
global[name] = val;
|
|
return val;
|
|
};
|
|
|
|
exports.zrequire = function (name, fn) {
|
|
if (fn === undefined) {
|
|
fn = "../../static/js/" + name;
|
|
} else if (/^generated\/|^js\/|^shared\/|^third\//.test(fn)) {
|
|
// FIXME: Stealing part of the NPM namespace is confusing.
|
|
fn = "../../static/" + fn;
|
|
}
|
|
delete require.cache[require.resolve(fn)];
|
|
requires.push(fn);
|
|
return require(fn);
|
|
};
|
|
|
|
exports.clear_zulip_refs = function () {
|
|
/*
|
|
This is a big hammer to make sure
|
|
we are not "borrowing" a transitively
|
|
required module from a previous test.
|
|
This kind of leak can make it seems
|
|
like we've written the second test
|
|
correctly, but it will fail if we
|
|
run it standalone.
|
|
*/
|
|
_.each(require.cache, (_, fn) => {
|
|
if (fn.indexOf("static/") >= 0) {
|
|
if (fn.indexOf("static/templates") < 0) {
|
|
delete require.cache[fn];
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
exports.restore = function () {
|
|
requires.forEach((fn) => {
|
|
delete require.cache[require.resolve(fn)];
|
|
});
|
|
Object.assign(global, old_globals);
|
|
old_globals = {};
|
|
for (const name of new_globals) {
|
|
delete global[name];
|
|
}
|
|
new_globals.clear();
|
|
};
|
|
|
|
exports.stub_out_jquery = function () {
|
|
set_global("$", () => ({
|
|
on() {},
|
|
trigger() {},
|
|
hide() {},
|
|
removeClass() {},
|
|
}));
|
|
$.fn = {};
|
|
$.now = function () {};
|
|
};
|
|
|
|
exports.with_overrides = function (test_function) {
|
|
// This function calls test_function() and passes in
|
|
// a way to override the namespace temporarily.
|
|
|
|
const restore_callbacks = [];
|
|
const unused_funcs = new Map();
|
|
|
|
const override = function (name, f) {
|
|
if (typeof f !== "function") {
|
|
throw new Error("You can only override with a function.");
|
|
}
|
|
|
|
unused_funcs.set(name, true);
|
|
|
|
const parts = name.split(".");
|
|
const module = parts[0];
|
|
const func_name = parts[1];
|
|
|
|
if (!Object.prototype.hasOwnProperty.call(global, module)) {
|
|
throw new Error("you must first use set_global/zrequire for " + module);
|
|
}
|
|
|
|
const old_f = global[module][func_name];
|
|
global[module][func_name] = function (...args) {
|
|
unused_funcs.delete(name);
|
|
return f.apply(this, args);
|
|
};
|
|
|
|
restore_callbacks.push(() => {
|
|
global[module][func_name] = old_f;
|
|
});
|
|
};
|
|
|
|
test_function(override);
|
|
|
|
restore_callbacks.reverse();
|
|
for (const restore_callback of restore_callbacks) {
|
|
restore_callback();
|
|
}
|
|
|
|
for (const unused_name of unused_funcs.keys()) {
|
|
throw new Error(unused_name + " never got invoked!");
|
|
}
|
|
};
|