Подтвердить что ты не робот

Макет глобального объекта window в require.js

  • У меня есть веб-приложение, которое использует window.applicationCache для автономный доступ.
  • Весь мой код, управляющий appCache (например, проверка/обновление/замена кэша) инкапсулируется в объект "cache-controller".
  • У меня есть модульные тесты для тестирования моего функции "кеш-контроллер". Для тестирования я временно замените собственный объект window.applicationCache своим собственным макетом (так как я хочу только проверить свой код, а не браузеры реализация appCache), например.

    window.applicationCache = { /* my appCache mock */ };
    // unit tests run here. Code under test references window.applicationCache.
    

Некоторое время назад (около Chrome 16) этот подход работал отлично. Затем Chrome 17, как на платформах Mac, так и на Windows, удалил возможность исправления поверх свойства окна window.applicationCache по умолчанию. Любопытно, что он все еще отлично работает в Chrome для Linux для всех версий вплоть до Chrome 26 и включая Chrome 26. В то время я регистрировал ошибку Chromium; но, к сожалению, этот отчет об ошибках по-прежнему отображается как "неподтвержденный".

В любом случае, я просто портировал свое приложение из традиционных "глобалов браузера" (т.е. загружал файлы *.js с помощью тегов script, все объекты JS являются глобальными) для модулей в стиле AMD, используя require.js в качестве загрузчика модуля.

Одним из преимуществ AMD (или CommonJS) является инъекция зависимостей, где ваш код получает локальную ссылку для любых зависимых объектов, вместо того, чтобы полагаться на глобальную ссылку, например.

require(['foo'], function(Foo) {
  var bar = new Foo();
});

..., что позволяет легко делать объект издевательства, поскольку вы можете настроить загрузчик модуля для передачи макета для "foo" в тестовом режиме.

Я надеялся, что, перейдя к инъекции зависимостей, я мог бы обойти проблему моего приложения (поскольку ссылка "окна", переданная в мои модули, может быть либо глобальным объектом окна, либо макетным объектом).

Однако я не уверен, как нужно require.js ввести "окно" в качестве зависимости от моих модулей?

Возможно ли это (возможно, используя shim config?), чтобы определить модуль 'window'; который затем может быть передан любому коду, который работает с глобальным "окном"? Чтобы я мог сделать что-то вроде этого:

require(['???'], function(window) {
  // 'window' here is the real window object, or for testing it a mock window object
  window.applicationCache.update();
});

... где '???' это имя модуля, которое относится к объекту window.

Или мне нужно будет определить мой собственный модуль, который экспортирует "окно", которое может отображаться по-разному для модульного тестирования, например.

// window.js
define(function() {
  return window;  // real global window object
});

// window-mock.js
define(function() {
  return {
    applicationCache: { /* mock version of appCache */ }
  }
});

// for unit testing, remap 'window' to the mock version
require.config({
  map: {
    "cache-controller": {
      "window": "window-mock"
    }
  }
});

// cache-controller.js
require(['window'], function(window) {
  window.applicationCache.update();
});
4b9b3361

Ответ 1

Я ответил на свой вопрос. Я решил создать модули window.js и window-mock.js, как описано выше, что позволило мне передать макетную версию при выполнении модульных тестов и использовать "реальный" объект окна при нормальной работе.