ngneat / spectator

🦊 🚀 A Powerful Tool to Simplify Your Angular Tests

Home Page:https://ngneat.github.io/spectator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`change` event is never fired when faking a file drop on custom input

ThomasFerro opened this issue · comments

Is this a regression?

No

Description

Hello!

We are working on a custom file input component, which mostly rely on native elements with a more refined UI. Unfortunately, we are unable to test the "drag and drop" feature of this component using spectator the way we imagined it.

We managed to reproduce the issue in the following minimalist implementation:

<!-- my-file-input template -->
<input type="file" multiple (drop)="onFilesDrop($event)">
// my-file-input component
import { Component } from '@angular/core';

@Component({
  selector: 'app-my-file-input',
  templateUrl: './my-file-input.component.html',
  styleUrls: ['./my-file-input.component.css'],
  standalone: true
})
export class MyFileInputComponent {
  onFilesDrop(e: Event) {
    console.log('onFilesDrop', e)
  }
}
<!-- app template -->
<app-my-file-input (change)="onFileChanged($event)"></app-my-file-input>
// app component
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  onFileChanged(e: Event) {
    console.log('onFileChanged', e)
  }
}

In a browser, it all seems to work just fine:

  1. When dropping a file in the custom component, we have both the inner input's drop and the wrapper's change events are triggered:
    image
  2. When selecting a file via the file chooser, the wrapper's change event is also triggered:
    image

However, in the test context, when faking a file drop, only the inner input's drop event is trigger, not the wrapper's change event:

LOG: 'onFilesDrop', Object{dataTransfer: Object{files: Object{length: ..., item: ...}}}

Here is how we fake the file drop (complete reproduction repo is also linked):

it('should emit files when the user drops files', fakeAsync(() => {
    const emittedFiles: FileList = {
      length: 1,
      item(): File | null {
        return new File([], 'newFile.pdf');
      },
    };

    let changeEventEmitted = false;
    spectator.element.addEventListener('change', (event) => {
      const element = event.target as HTMLInputElement;
      expect(element.files!.length).toEqual(1);
      expect(element.files!.item(0)).toEqual(emittedFiles[0]);
      changeEventEmitted = true;
    });

    const dragEvent: DragEvent = {
      // @ts-ignore
      dataTransfer: {
        files: emittedFiles,
      },
    };
    spectator.triggerEventHandler('input', 'drop', dragEvent);
    tick(50);
    expect(changeEventEmitted).toBeTruthy();
  }));

Is it related to the way we implemented the test? A limitation in the library?

Thanks for the whole project and in advance for this specific issue, have a nice day :D

Please provide a link to a minimal reproduction of the bug

https://gitlab.com/thomas.ferro/spectator-fake-file-drop-event

Please provide the exception or error you saw

We expect the test to succeed, but the `change` event is never fired, thus making the assertion fail.

Please provide the environment you discovered this bug in

Local.

Anything else?

I will be glad to help resolving this issue if indeed it is due to a bug in the library :)

Do you want to create a pull request?

Yes