我想知道如何测试基于 HTML5 DOM 方法的功能。例如,新的对话框 API。
考虑以下函数;
function show(dialog)
{
if(typeof(dialog.showModal) !== "function")
throw new Error("Update your browser");
dialog.showModal();
}
我想确认一下
- 当方法不可用时会抛出错误
- 如果可用,则调用dialog.showModal
我目前正在使用 Firefox 和 Chrome 启动器运行 karma + jasmine,但它们似乎都不支持对话框 API。
我可以通过某种方式对此进行填充吗?我可以在所有对话框 DOM 节点上创建函数吗?
我可以执行以下操作
var modal = document.createElement("dialog");
Object.defineProperty(modal, "showModal", {
value: function()
{
console.log("hello world!");
}
});
但是,这不会转移到对话框的其他实例。
这是我想要实现的目标的一个非常简单的示例。
最佳答案
这就是polyfills:尝试将对新规范的支持填充到不支持它们的浏览器中。你所说的本质上是为<dialog>
创建一个polyfill。元素。
一些旧的 ECMAScript 6 规范指定了一个函数来测试某些东西是否存在并且是一个函数,但这似乎在最近的规范中已被废弃。这是一个“polyfill”(以任何方式该术语可以应用于废弃的规范),既作为polyfill的示例,又作为我们用来进一步探索这个概念的工具:
(function () {
"use strict";
var ops = Object.prototype.toString;
Function.isFunction = function(o) {
return ops.call(o) === "[object Function]";
};
}());
请注意,我们必须缓存原始的 Object.prototype.toString:大多数 JavaScript 运行时都会在 Function.prototype.toString 中覆盖它,并且我们确实需要调用原始的。这应该会让您了解多重填充是多么繁琐和容易出错:即使在这样的情况下,代码简短而简单,细微差别如使用 Object.prototype.toString.call(o)
而不是o.toString()
仍然至关重要。
无论如何,一旦你有了这个函数,测试模态支持之类的事情就变得容易多了:
(function () {
"use strict";
var test = document.createElement("dialog");
if (!Function.isFunction(test.showModal)) {
throw new Error("HTMLDialogElement.showModal() is not supported");
};
}());
要修改所有对话框元素实例,您需要扩展与该对象最直接相关的原型(prototype)。对于 HTML 对话框规范来说,就是 HTMLDialogElement。你可以这样做:
(function () {
"use strict";
var HTMLDialogElement = HTMLDialogElement; //undefined if unsupported
if (!Function.isFunction(HTMLDialogElement)) {
// No native dialog support
throw new Error("No support for <dialog> elements");
}
if (!Function.isFunction(HTMLDialogElement.prototype.showModal)) {
// The interface exists, but showModal isn't supported
HTMLDialogElement.prototype.showModal = function () {
console.log("Hello world!");
};
}
}());
如果也不支持原型(prototype),那么事情就会变得更加棘手。未知的元素不会有独特的原型(prototype);它只是一个 HTMLElement(最终像所有其他元素一样)。因此,要使函数适用于 <dialog>
如果在不受支持的环境中使用元素,则必须将其添加到所有元素中。尽管如此,你还是可以让它发挥作用:
(function () {
"use strict";
HTMLElement.prototype.showModal = function () {
if (this.tagName !== "DIALOG") {
throw new TypeError("showModal() called on non-dialog");
}
console.log("Hello world!");
};
}());
大多数 Polyfill 的工作都是基于这样的妥协:它们并不完全支持规范,但足以支持常见用例。
请注意:填充扩展了 native 对象,这通常被认为是不好的做法。大多数认为这是不好做法的人都会对 Polyfill 进行异常(exception)处理,但尽管 Polyfill 非常有用,但这条规则仍然被认为是好的。这应该让您了解该任务有多复杂和容易出错。这是黑魔法:不是一项可以轻易完成的任务。
关于javascript - 基于 HTML5 DOM 方法的测试功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30529008/