Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Files upload testing in Enzyme

I have a FileInput in my render function

      <FileInput
      accept= "image/jpeg,image/png,audio/mp3"
      onChange= {this.fileInputOnChange}
      children= {<i className="fa fa-paperclip"/>}
      className= 'fileInput'
      />

I need to write a test for file upload, when I simulate the change function it call the function fileInputOnChange

fileInputOnChange: function(evt){
var file = evt.target.files[0];
var fileReader = new FileReader();

fileReader.onload = function(readFile){
  // Check the file type.
  var fileType = file.type.toLowerCase();

  if(fileType.lastIndexOf('image') === 0 && (fileType.lastIndexOf('png') >= 0 || fileType.lastIndexOf('jpeg'))){
    var image = new Image();

    image.onload = function(){
      var attachedFile = {
        attached: file,
        mediaSource: readFile.target.result,
        type: 'image'
      } 
        this.props.onChange(attachedFile);
    }.bind(this);

    image.onerror = function(){
      this.props.onError("INVALID_TYPE");
    }.bind(this);

    image.src = readFile.target.result;
  }else if(fileType.lastIndexOf('audio') === 0 && fileType.lastIndexOf('mp3') >= 0){
    //@todo: manage audio upload here
    var audio = new Audio();

    audio.oncanplaythrough = function(){
      var attachedFile = {
        attached: file,
        mediaSource: readFile.target.result,
        type: 'audio'
      } 
        this.props.onChange(attachedFile);
    }.bind(this);

    audio.onerror = function(e){
      this.props.onError("INVALID_TYPE");
    }.bind(this)

    audio.src = readFile.target.result;

  }else if (fileType.lastIndexOf('video') === 0 && fileType.lastIndexOf('mp4') >= 0){        
    var video = document.createElement('video');

    video.oncanplaythrough = function(){
      var attachedFile = {
        attached: file,
        mediaSource: readFile.target.result,
        type: 'video'
      } 
        this.props.onChange(attachedFile);
    }.bind(this);

    video.onerror = function(){
      this.props.onError("INVALID_TYPE");
    }.bind(this)

    video.src = readFile.target.result;
  }
}.bind(this);

fileReader.onerror = function(){
  this.props.onError("READING_ERROR");
}.bind(this)

fileReader.readAsDataURL(file); }

I could not add any files while simulating the upload button, I am confused of how to write the test for this scenario. Anyone ever came across this kinda scenarios? I would be greatful for all sorta helps.

it('testing attachfile change function...',()=>{
 const wrapper=shallow(<AttachFile />);
 wrapper.find('FileInput').simulate('change');
 console.log(wrapper.debug());
 });

When I tried the above test I got the following error

TypeError: Cannot read property 'target' of undefined
  at [object Object].fileInputOnChange (js/components/home/chats/AttachFile.react.js:11:16)
  at node_modules/enzyme/build/ShallowWrapper.js:768:23
  at ReactDefaultBatchingStrategyTransaction.Mixin.perform (node_modules/react/lib/Transaction.js:138:20)
  at Object.ReactDefaultBatchingStrategy.batchedUpdates (node_modules/react/lib/ReactDefaultBatchingStrategy.js:63:19)
  at batchedUpdates (node_modules/react/lib/ReactUpdates.js:98:20)
  at node_modules/enzyme/build/ShallowWrapper.js:767:45
  at withSetStateAllowed (node_modules/enzyme/build/Utils.js:196:3)
  at ShallowWrapper.simulate    (node_modules/enzyme/build/ShallowWrapper.js:764:42)
  at Context.<anonymous> (test/sample.js:40:27)
like image 545
Thomas John Avatar asked Sep 26 '16 12:09

Thomas John


People also ask

What is Enzyme in testing?

Enzyme is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse your React Components' output.

Why do we use Enzyme and jest?

Many people choose to use Jest and Enzyme together to test their React web applications. They use Jest as a test runner and assertion library, then use Enzyme to build the tests for their UI. This results in slimmer, cleaner testing code that's also easier to debug when a test breaks.


1 Answers

You'll need to provide a mocked event object, something like:

wrapper.find('FileInput').simulate('change', {
  target: {
     files: [
       'dummyValue.something'
     ]   
  }
});

Your component its making a lot of work inside, its like a huge side effect (it defines two callbacks with logic nailed). It's going to be difficult, but I suppose you'll need to mock FileReader as well using two spies, one reacting to the readAsDataURL calling the onload and another one calling the onerror.

Then you can check if your callbacks are doing what is supposed to.

Hope it helps!

like image 118
sminutoli Avatar answered Oct 08 '22 01:10

sminutoli