Моделирование онлайн/оффлайн с JSDOM

мы работаем над учебником по основам автономных первых приложений и используем JSDOM с лентой для тестирования нашего кода. В нашем коде мы обновляем DOM так, чтобы текстовый узел менялся с "онлайн" на "офлайн" и наоборот, прикрепляя прослушиватель событий к окну и прослушивая события "онлайн"/"офлайн" и 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 собственность но это только для чтения, и мы не можем найти способ изменить его (всегда верно). Кажется, что у него есть онлайн / оффлайн события, а также, но я не вижу, как заставить их стрелять.

как мы можем имитировать онлайн/оффлайн при тестировании с узлом?

1 ответов


в JSDOM 11.0.0 (который является текущей версией, поскольку я пишу этот ответ) нет положения для изменения navigator.onLine или для создания online и offline событий.

, можно взять за 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