使用 JSDOM 模拟 online/offline

Simulating going online/offline with JSDOM

我们正在编写离线第一个应用程序的基础教程,并使用 JSDOM 和 Tape 来测试我们的代码。 在我们的代码中,我们更新 DOM 以便文本节点从说 "online" 变为 "offline",反之亦然,方法是将事件侦听器附加到 window 并侦听 "online"/"offline" 事件,navigator.onLine 将文本初始化为 online/offline。像这样:

// get the online status element from the DOM
var onlineStatusDom = document.querySelector('.online-status');
// navigator.onLine will be true when online and false when offline. We update the text in the online status element in the dom to reflect the online status from navigator.onLine
if (navigator.onLine) {
  onlineStatusDom.innerText = 'online';
} else {
  onlineStatusDom.innerText = 'offline';
}

// we use the 'online' and 'offline' events to update the online/offline notification to the user
// in IE8 the offline/online events exist on document.body rather than window, so make sure to reflect that in your code!
window.addEventListener('offline', function(e) {
  onlineStatusDom.innerText = 'offline';
});

window.addEventListener('online', function(e) {
  onlineStatusDom.innerText = 'online';
});

我们想使用 JSDOM 来测试当离线时触发离线事件并且我们的文本节点更新为 "offline".

JSDOM 有一个 window.navigator.onLine 属性、but it is read only, and we can't find a way to change it (always true). It seems that it has the online/offline events as well,但我看不出如何让它们启动。

我们如何在使用 node 进行测试时模拟 online/offline?

JSDOM 11.0.0(这是我撰写此答案时的当前版本)中没有更改 navigator.onLine 或生成 onlineoffline 事件的规定。

但是,可以接管 navigator.onLine 来控制它并自己生成事件。这是一个概念证明:

const { JSDOM } = require("jsdom");
const { window } = new JSDOM();

class OnlineController {
    constructor(win) {
        this.win = win;
        this.onLine = win.navigator.onLine;

        // Replace the default onLine implementation with our own.
        Object.defineProperty(win.navigator.constructor.prototype,
                              "onLine",
                              {
                                  get: () => {
                                      return this.onLine;
                                  },
                              });
    }

    goOnline() {
        const was = this.onLine;
        this.onLine = true;

        // Fire only on transitions.
        if (!was) {
            this.fire("online");
        }
    }

    goOffline() {
        const was = this.onLine;
        this.onLine = false;

        // Fire only on transitions.
        if (was) {
            this.fire("offline");
        }
    }

    fire(event) {
        this.win.dispatchEvent(new this.win.Event(event));
    }
}

window.addEventListener("offline", function () {
    console.log("gone offline");
});

window.addEventListener("online", function () {
    console.log("gone online");
});

const cont = new OnlineController(window);
console.log("online?", window.navigator.onLine);
cont.goOffline();
console.log("online?", window.navigator.onLine);
cont.goOnline();
console.log("online?", window.navigator.onLine);

如果你运行这个文件,你应该得到:

online? true
gone offline
online? false
gone online
online? true