为 ClipboardEvent 创建自定义 clipboardData 属性

art*_*its 6 javascript google-chrome karma-jasmine

在我的 Karma-Jasmine 测试中,我必须测试我的onPaste方法。

onPaste 方法:

onPaste(event: any): void {
  const pastedText = event.clipboardData.getData('text/plain');
  // some stuff
}
Run Code Online (Sandbox Code Playgroud)

我的单元测试:

it('should do something', () => {
  const queryField = fixture.debugElement.query(By.css('input[type="search"]')).nativeElement;
  queryField.dispatchEvent(new ClipboardEvent('paste', {
    dataType: 'text/plain',
    data: '325435956\r325435956',
  }));
  // some stuff
})
Run Code Online (Sandbox Code Playgroud)

我使用 Chrome 运行测试,但new ClipboardEvent()在 Chrome 中创建ClipboardEvent对象 where clipboardDataisnullevent.clipboardData.getData('text/plain')引发错误:

Uncaught TypeError: Cannot read property 'getData' of null
Run Code Online (Sandbox Code Playgroud)

它不会在 Firefox 中发生,所以如果我使用karma-firefox-launcher它可以正常工作,但我必须使用 Chrome。所以,我有一些想法如何解决它。

第一个想法是创建ClipboardEvent对象并覆盖 clipboardData 属性:

const pasteEvent = new ClipboardEvent('paste', {
  dataType: 'text/plain',
  data: '325435956\r325435956',
});

pasteEvent.clipboardData = {
  getData() {
    return this.data;
  }
};
Run Code Online (Sandbox Code Playgroud)

但我不能这样做,因为它clipboardData是只读属性。

第二个想法是创建假ClipboardEvent对象:

function FakePasteEvent(options) {
  this.clipboardData = {
    dataType: options.dataType,
    data: options.data,
    getData() {
      return this.data;
    }
  };
}
const pasteEvent = new FakePasteEvent({
  dataType: 'text/plain',
  data: '325435956\r325435956',
});

console.log(pasteEvent.clipboardData.getData()) // returns what I need
Run Code Online (Sandbox Code Playgroud)

但我不能将它传递给,dispatchEvent因为类型pasteEvent不是事件。然后我想我可以为我的指定原型对象FakePasteEvent

Object.setPrototypeOf(pasteEvent, ClipboardEvent);
Run Code Online (Sandbox Code Playgroud)

但无论如何我有一个错误:

TypeError: Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'

你能帮我解决这个问题吗?;)

这里的代码示例http://jsbin.com/puqilivalo/1/edit?html,js,console,output

Kai*_*ido 9

非常有趣的是,我目前正在为 chrome 和 Firefox 之间谁是对的而苦苦挣扎,我仍然无法弄清楚规范在说什么时说的

dictionary ClipboardEventInit : EventInit {
 DataTransfer? clipboardData = null;
};
Run Code Online (Sandbox Code Playgroud)

[Constructor (DOMString type, optional ClipboardEventInit eventInitDict), Exposed=Window]
 interface ClipboardEvent : Event {
 readonly attribute DataTransfer? clipboardData;
};
Run Code Online (Sandbox Code Playgroud)

我倾向于说 Chrome 在为clipboardData属性返回 null 时是正确的,但是接下来的示例使 FF 行为正确:

示例 3
var pasteEvent = new ClipboardEvent('paste');
pasteEvent.clipboardData.items.add('My string', 'text/plain'); document.dispatchEvent(pasteEvent);



但无论如何,Chrome 确实支持(部分)DataTransfer构造函数,而 FF 仍然不支持。然后,您也可以在 chrome 中使用此 DataTransfer 对象构建您的事件:

dictionary ClipboardEventInit : EventInit {
 DataTransfer? clipboardData = null;
};
Run Code Online (Sandbox Code Playgroud)