angular - 无法创建 KeyboardEvent 来测试 Internet Explorer 11 中的输入组件( Angular )

标签 angular karma-runner internet-explorer-11 typescript-typings karma-webpack

我们为我们的 Angular 应用程序提供了已启动并正在运行的 karma 测试套件。对于 chrome,所有测试都是绿色的。现在我必须修复 IE 11 失败的测试。我得到的异常如下:

TypeError: Object doesn't support this action
       at createEventWithKeycode (http://localhost:9876/_karma_webpack_/main.bundle.js:3574:5)
       at Anonymous function (http://localhost:9876/_karma_webpack_/main.bundle.js:3115:13)
       at Anonymous function (http://localhost:9876/_karma_webpack_/vendor.bundle.js:74994:17)
       at ZoneDelegate.prototype.invoke (http://localhost:9876/_karma_webpack_/polyfills.bundle.js:10531:13)
       at ProxyZoneSpec.prototype.onInvoke (http://localhost:9876/_karma_webpack_/vendor.bundle.js:26806:13)
       at ZoneDelegate.prototype.invoke (http://localhost:9876/_karma_webpack_/polyfills.bundle.js:10531:13)
       at Zone.prototype.run (http://localhost:9876/_karma_webpack_/polyfills.bundle.js:10283:17)
       at Anonymous function (http://localhost:9876/_karma_webpack_/vendor.bundle.js:26503:13)

我的理解是,测试用例正在创建一个 Angular 组件,以便在 Angulars TestBed 类的帮助下进行测试。通过一些神奇的代码,我们获取输入组件本身并在其上运行 keydown 事件:

inputComponent.onKeyDownInput(event);

但是当我在 IE 中运行代码时,当我尝试使用以下代码创建事件对象时,已经发生异常:

const event = new KeyboardEvent('keydown', {         //This triggers the exception
    bubbles: true,
    cancelable: true,
    shiftKey: true
  });

KeyboardEvent 对象在类型文件 lib.es6.d.ts 中定义:

declare var KeyboardEvent: {
    prototype: KeyboardEvent;
    new(typeArg: string, eventInitDict?: KeyboardEventInit): KeyboardEvent;
    readonly DOM_KEY_LOCATION_JOYSTICK: number;
    readonly DOM_KEY_LOCATION_LEFT: number;
    readonly DOM_KEY_LOCATION_MOBILE: number;
    readonly DOM_KEY_LOCATION_NUMPAD: number;
    readonly DOM_KEY_LOCATION_RIGHT: number;
    readonly DOM_KEY_LOCATION_STANDARD: number;
}

有人可以解释一下这个问题吗?请记住,一切都可以在 Chrome 上运行 - 只有 IE 不起作用!

最佳答案

如果有人遇到这个问题,我可以让下面的内容发挥作用

function createKeyEvent(
    key: Key|number = null, options: {type: 'keyup'|'keydown'|'input', bubbles?: boolean, cancelable?: boolean} = {
      type: 'keyup',
      bubbles: true,
      cancelable: true
    }): KeyboardEvent {
  let eventInitDict: any = {bubbles: options.bubbles, cancelable: options.cancelable};
  if (key) {
    eventInitDict.key = String.fromCharCode(key);
  }
  if (key === Key.Shift) {
    eventInitDict.shiftKey = true;
    key = null;
  }
  let event;
  if (isBrowser(['ie10', 'ie11'])) {
    event = document.createEvent('KeyboardEvent') as KeyboardEvent;
    event.initKeyboardEvent(options.type, options.cancelable, options.bubbles, window, key, 0, 0, 0, 0);
  } else {
    event = new KeyboardEvent(options.type, eventInitDict)
  }
  if (key) {
    Object.defineProperties(event, {which: {get: () => key}});
    Object.defineProperties(event, {keyCode: {get: () => key}});
  }

  return event;
}

编辑:添加有关 Key 对象的信息

export enum Key {
  Backspace = 8,
  Tab = 9,
  Enter = 13,
  Shift = 16,
  Escape = 27,
  Space = 32,
  End = 35,
  Home = 36,
  ArrowLeft = 37,
  ArrowUp = 38,
  ArrowRight = 39,
  ArrowDown = 40
}

编辑 #2:添加 isBrowser 函数

export type Browser = 'ie9'|'ie10'|'ie11'|'ie'|'edge'|'chrome'|'safari'|'firefox';

export function getBrowser(ua = window.navigator.userAgent) {
  let browser = 'unknown';

  // IE < 11
  const msie = ua.indexOf('MSIE ');
  if (msie > 0) {
    return 'ie' + parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
  }

  // IE 11
  if (ua.indexOf('Trident/') > 0) {
    let rv = ua.indexOf('rv:');
    return 'ie' + parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
  }

  // Edge
  if (ua.indexOf('Edge/') > 0) {
    return 'edge';
  }

  // Chrome
  if (ua.indexOf('Chrome/') > 0) {
    return 'chrome';
  }

  // Safari
  if (ua.indexOf('Safari/') > 0) {
    return 'safari';
  }

  // Firefox
  if (ua.indexOf('Firefox/') > 0) {
    return 'firefox';
  }

  if (browser === 'unknown') {
    throw new Error('Browser detection failed for: ' + ua);
  }
}

export function isBrowser(browsers: Browser|Browser[], ua = window.navigator.userAgent) {
  let browsersStr = Array.isArray(browsers) ? (browsers as Browser[]).map(x => x.toString()) : [browsers.toString()];
  let browser = getBrowser(ua);

  if (browsersStr.indexOf('ie') > -1 && browser.startsWith('ie')) {
    return true;
  } else {
    return browsersStr.indexOf(browser) > -1;
  }
}

关于angular - 无法创建 KeyboardEvent 来测试 Internet Explorer 11 中的输入组件( Angular ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45994059/

相关文章:

javascript - 类型错误 [ERR_INVALID_CALLBACK] : Callback must be a function

angular - 使用 Angular 6 中的订阅调用并等待间隔

unit-testing - 使用 Karma 在移动设备上测试 Javascript

javascript - 无法获取未定义或空引用的属性 'top' (IE 11)

html - 具有最大 body 高度和 flex 的 DIV 在 IE11 上无法正常工作

模板中的 Angular 方法调用

javascript - 在 JavaScript 中对时间戳数组进行排序

angular - 模块 'DecoratorFactory' 导入了意外值 'DynamicTestModule'。请添加@NgModule 注解

javascript - Karma 如何通过 id 加载模块?

IE11 上的 Angular 4 性能/CPU 使用率