`);
// 脚本默认将不能执行:
dom.window.document.body.children.length === 1;

constdom=newJSDOM(`
`);
// 脚本默认将不能执行:
dom.window.document.body.children.length===1;
要在页面内启用脚本,可以使用runScripts:"dangerously"选项:
const dom = new JSDOM(`
`, { runScripts: "dangerously" });
// 脚本将执行并修改 DOM:
dom.window.document.body.children.length === 2;

constdom=newJSDOM(`
`,{runScripts:"dangerously"});
// 脚本将执行并修改 DOM:
dom.window.document.body.children.length===2;

我们再次强调只有在提供给jsdom的代码是你已知道是安全的代码时方可使用它。如果您运行了任意用户提供的或Internet上的不可信的Node.js代码,可能会危及您的计算机。

假如你想通过

请注意,除非runScripts设置为"dangerously",否则事件处理程序属性(如


如果您只是试图从“外部”执行脚本,而不是通过

const window = (new JSDOM(``, { runScripts: "outside-only" })).window;
window.eval(`document.body.innerHTML = "
Hello, world!
";`); 
 
window.document.body.children.length === 1;


constwindow=(newJSDOM(``,{runScripts:"outside-only"})).window;
window.eval(`document.body.innerHTML="
Hello, world!
";`); 
 
window.document.body.children.length===1;

由于性能原因,默认情况下会关闭此功能,但可以安全启用。

请注意,我们强烈建议不要试图通过将jsdom和Node全局环境混合在一起(例如,通过执行global.window = dom.window)来“执行脚本”,然后在Node全局环境中执行脚本或测试代码。相反,您应该像对待浏览器一样对待jsdom,并使用window.eval或runScripts: "dangerously"来运行需要访问jsdom环境内的DOM的所有脚本和测试。例如,这可能需要创建一个browserify包作为

最后,对于高级用例,您可以使用dom.runVMScript(脚本)方法,如下所述。

假装成一个视觉浏览器

jsdom没有渲染可视内容的能力,并且默认情况下会像无头浏览器一样工作。它通过API(如document.hidden)向网页提供提示,表明其内容不可见。

当pretendToBeVisual选项设置为true时,jsdom会假装它正在呈现并显示内容。它是这样做的:

更改document.hidden以返回false而不是true

更改document.visibilityState以返回“visible”而不是“prerender”

启用window.requestAnimationFrame() 和window.cancelAnimationFrame()方法,否则不存在

const window = (new JSDOM(``, { pretendToBeVisual: true })).window;
window.requestAnimationFrame(timestamp => {
console.log(timestamp > 0);
});


constwindow=(newJSDOM(``,{pretendToBeVisual:true})).window;
window.requestAnimationFrame(timestamp=>{
console.log(timestamp>0);
});

请注意,jsdom仍然不做任何布局或渲染,因此这实际上只是假装为可视化,而不是实现真正的可视化Web浏览器将实现的部分。

加载子资源

默认情况下,jsdom不会加载任何子资源,如脚本,样式表,图像或iframe。如果您希望jsdom加载这些资源,则可以传递resources: "usable"选项,该选项将加载所有可用资源。资源列表如下:

frame 和 iframe,通过 和 实现

样式,通过

脚本,通过

图片,通过,但是前提是canvas(或者 canvas-prebuilt) npm 包已安装

未来,我们计划通过此选项提供更多的资源加载定制,但现在只提供的两种模式:'default'和 'usable'。

虚拟控制台

像网页浏览器一样,jsdom也具有“控制台”的概念。通过在文档内执行的脚本以及来自jsdom本身实现的信息和记录会从页面直接发送过来。我们将用户可控制的控制台称为“虚拟控制台”,以便将其与Node.js console API和页面内部的window.console API区分开来。

默认情况下,JSDOM构造函数将返回一个具有虚拟控制台的实例,该虚拟控制台将其所有输出转发到Node.js控制台。为了创建自己的虚拟控制台并将其传递给jsdom,可以通过执行下面代码来覆盖此默认值

const virtualConsole = new jsdom.VirtualConsole();

const dom = new JSDOM(``, { virtualConsole });


constvirtualConsole=newjsdom.VirtualConsole();

constdom=newJSDOM(``,{virtualConsole});

这样的代码将创建一个没有任何行为的虚拟控制台。您可以为所有可能的控制台方法添加事件侦听器来为其提供行为:

virtualConsole.on("error", () => { ... });
virtualConsole.on("warn", () => { ... });
virtualConsole.on("info", () => { ... });
virtualConsole.on("dir", () => { ... });
// ... etc. See https://console.spec.whatwg.org/#logging


virtualConsole.on("error",()=>{...});
virtualConsole.on("warn",()=>{...});
virtualConsole.on("info",()=>{...});
virtualConsole.on("dir",()=>{...});
// ... etc. See https://console.spec.whatwg.org/#logging

(请注意,最好在调用 new JSDOM()之前设置这些事件侦听器,因为在解析期间可能会发生错误或控制台调用脚本错误。)

如果你只是想将虚拟控制台输出重定向到另一个控制台,比如默认的Node.js,你可以这样做

virtualConsole.sendTo(console);

0

virtualConsole.sendTo(console);

还有一个特殊的事件,"jsdomError",它的触发将通过错误对象来记录jsdom本身的错误。这与错误消息在Web浏览器控制台中的显示方式类似,即使它们不是由console.error输出的。到目前为止,错误会按照下面的方式输出:

加载或解析子资源时出错(脚本,样式表,frames和iframe)

不是由window onerror事件处理程序处理的脚本执行错误,它将会返回true或调用event.preventDefault()

由于调用jsdom没有实现的方法而导致的错误,例如window.alert,兼容性的 web 浏览器都实现了这些方法

如果您使用sendTo(c)将错误发送给c,则默认情况下,它将使用来自"jsdomError"事件的信息调用console.error。如果您希望保持事件与方法调用的严格的一对一映射,并且可能自己处理"jsdomError",那么您可以执行

virtualConsole.sendTo(c, { omitJSDOMErrors: true });

0

virtualConsole.sendTo(c,{omitJSDOMErrors:true});

Cookie jars(存储Cookie的容器)

像网页浏览器一样,jsdom也具有cookie jar的概念,存储HTTP cookie 。在文档的同一个域上一个URL,并且没有标记为HTTP only的cookies,可以通过document.cookie API来访问。此外,Cookie jar中的所有cookie都会影响子资源的http加载。

默认情况下,JSDOM构造函数将返回一个带有空cookie的实例。要创建自己的cookie jar并将其传递给jsdom,可以通过以下代码来覆盖默认值

const cookieJar = new jsdom.CookieJar(store, options);

const dom = new JSDOM(``, { cookieJar });

0

1

constcookieJar=newjsdom.CookieJar(store,options);

constdom=newJSDOM(``,{cookieJar});

如果您想要在多个jsdoms中共享同一个cookie jar,或者提前使用特定的值来填充cookie jar,这将非常有用。

Cookie jar包由tough-cookie包提供的。jsdom.CookieJar构造函数是tough-cookie cookie jar的子类,并且默认设置了looseMode:true选项,因为它更符合浏览器的行为方式。如果您想自己使用tough-cookie的方法和类,则可以使用jsdom.toughCookie模块导出来访问使用jsdom打包的tough-cookie模块实例。

在解析之前进行干预

jsdom允许您在很早的时候介入创建jsdom:创建Window和Document对象之后,但在解析任何HTML并使用节点填充文档之前:

const dom = new JSDOM(`
Hello
`, { 
 
beforeParse(window) {
window.document.childNodes.length === 0;
window.someCoolAPI = () => { /* ... */ };
}
});


constdom=newJSDOM(`
Hello
`,{ 
 
beforeParse(window){
window.document.childNodes.length===0;
window.someCoolAPI=()=>{/* ... */};
}
});

如果您希望以某种方式修改环境,这尤其有用,例如添加jsdom不支持的Web API的填充程序。

JSDOM object API

一旦你构建了一个JSDOM对象,它将具有以下有用的功能:

Properties

window属性: window对象的key 从Window 对象检索而来 virtualConsole和cookieJar:可以传入或者使用默认值

通过serialize()序列化document

const dom = new JSDOM(`hello`);
dom.serialize() === "
hello"; 
 
// Contrast with:
dom.window.document.documentElement.outerHTML === "
hello";



constdom=newJSDOM(`hello`);
dom.serialize()==="
hello"; 
 
// Contrast with:
dom.window.document.documentElement.outerHTML==="
hello