【问题标题】:Test that event handler is called when file input receives data测试文件输入接收数据时是否调用事件处理程序
【发布时间】:2018-03-25 15:36:16
【问题描述】:

我有一个 Angular 4 组件,它的 <input> 类型为 file。我想创建一个 Jasmine 测试,验证输入字段接收到文件时是否调用了事件处理程序。

这是组件:

<div>
    <input type="file" (change)="fileChange($event)" placeholder="Upload file" accept=".xls, .xlsx" style="padding-left: 5px">
</div>

这是事件处理程序:

fileChange(event) {
    let fileList: FileList = event.target.files;
    if (fileList.length > 0) {
        // save the file to the backend - this behaviour is tested in a different test
    }
}

这是我到目前为止的测试用例,由 Stackoverflow 上的各种答案拼凑而成(例如 these answers 的一些答案),这些答案似乎在 Angular 2 中有效,但在 Angular 4 中无效:

beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
});

it('file change event should arrive in handler', () => {
    let input  = fixture.debugElement.query(By.css('input[type=file]')).nativeElement;
    input.value = {name: 'excel'};
    input.dispatchEvent(new Event('input'));

    // check that the event handler has been called
    spyOn(component, 'fileChange');

    expect(component.fileChange).toHaveBeenCalled();
});

问题在于,Karma 为行 input.value = {name: 'excel'}; 显示 SecurityError: The operation is insecure.。是否有另一种方法可以手动分配输入字段的值,或者至少让它发送由fileChange 处理的事件?

【问题讨论】:

  • 你有没有想过这个?我也一直在到处搜索,似乎找不到可靠的解决方案。
  • 不,我放弃了测试。我只是再次查看它(现在使用 Angular 5.0.1),现在我坚持将文件分配给输入,因为 Value being assigned to HTMLInputElement.files does not implement interface FileList.不过,没有时间进一步调试它。如果你愿意,我可以将我当前的代码添加到问题中。
  • 我的库 ngx-material-file-input 也有类似的问题,使用单元测试重现清除字段(使用角度 v7)时出现的错误。似乎测试引擎仍然有局限性,并且没有实际的解决方案(据我所知)来确保文件在本机文件输入中,作为FileList 对象(我哭了)。我尝试使用fakeAsync/tick 等待DOM 刷新,但没有运气。我还尝试多次添加fixture.detectChanges() 来运行另一个生命周期检查,但再次没有运气。所以我最终哈维

标签: angular unit-testing typescript jasmine


【解决方案1】:

是否有另一种方法可以手动分配输入字段的值

出于安全原因,您不能为 input[type="file"] 赋值。

或者至少让它发送一个由 fileChange 处理的事件

您可以在spyOn 之后触发change 事件:

spyOn(component, 'fileChange');
input.dispatchEvent(new Event('change'));
expect(component.fileChange).toHaveBeenCalled();

Plunker Example

【讨论】:

  • 我可以做这么多,但它没有解决如何测试 fileChange 函数内的所有逻辑,例如 const reader = new FileReader(); const target = &lt;HTMLInputElement&gt;evt.target; if (target.files &amp;&amp; target.files.length) {const file = target.files[0]; reader.readAsDataURL(file); reader.onload = () =&gt; { this.getUploadFormGroup(index, isReq).patchValue({...}); } fileChange 内的这些行是我发现最难测试的东西,监视fileChange 不允许我们在那里测试它们。如果你能展示如何测试这些,你就会得到赏金。
  • 我又看了一遍。因为您确实在技术上回答了 OP 的问题,所以我现在就给您赏金。但是有没有人可以回答我关于访问内部线路的问题?
  • 不幸的是,我无法再访问代码,因此无法测试您的答案。但它帮助了@JeremyMoritz 并且 Plunkr 有效,所以我还是会接受你的回答。
【解决方案2】:
describe("A suite is just a function", function() {
  var a;

  it("and so is a spec", function() {
    a = true;

    expect(a).toBe(true);
  });
});

【讨论】:

  • 嗨,欢迎来到 stackockflow,如需解答,请提供更多信息,例如您的解决方案为何有效以及做错了什么。这些答案可以在谷歌等网站上找到,每个人都应该清楚。感谢您的贡献,祝您好运!
  • 此答案仅显示如何使用 Jasmine 编写通用测试用例。您能否添加一些有关如何专门在输入元素上测试事件处理程序的详细信息?
  • 此回复与提出的问题无关。至少,请描述您要使用此代码示例演示的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-27
  • 2022-07-21
相关资源
最近更新 更多