2016-12-23 3 views
1

Ich habe Schwierigkeiten, eine Komponente mit Spaß und Enzym zu testen. Was ich tun möchte, ist das Senden des Formulars ohne Wert im Namensfeld zu testen. Dadurch wird sichergestellt, dass die Komponente einen Fehler anzeigt. Allerdings, wenn ich den Rest betreibe ich einen Fehler in meiner Konsole bin immer:Enzym simulieren Formular einreichen, Eigenschaft 'Wert' von undefiniert nicht lesen

TypeError: Cannot read property 'value' of undefined

Ich bin ziemlich neu in Front-End-Tests und Tests im Allgemeinen. Also bin ich mir nicht ganz sicher, ob ich das Enzym für diese Art von Test richtig verwende. Ich weiß nicht, ob meine Tests falsch sind oder ob ich gerade eine Komponente geschrieben habe, die nicht leicht zu testen ist. Ich bin offen für das Ändern meiner Komponente, wenn das den Test einfacher macht?

Komponente

class InputForm extends Component { 
    constructor(props) { 
    super(props); 
    this.onFormSubmit = this.onFormSubmit.bind(this); 
    } 

    onFormSubmit(e) { 
    e.preventDefault(); 
    // this is where the error comes from 
    const name = this.name.value; 
    this.props.submitForm(name); 
    } 

    render() { 
    let errorMsg = (this.props.validationError ? 'Please enter your name.' : null); 
    return (
     <form onSubmit={(e) => this.onFormSubmit(e)}> 
     <input 
      type="text" 
      placeholder="Name" 
      ref={ref => { 
       this.name = ref 
       }} 
     /> 
     <p className="error"> 
      {errorMsg} 
     </p> 
     <input 
      type="submit" 
      className="btn" 
      value="Submit" 
     /> 
     </form> 
    ); 
    } 
} 
InputForm.propTypes = { 
    submitForm: React.PropTypes.func.isRequired, 
}; 

-Test

// all other code omitted 
    // bear in mind I am shallow rendering the component 

    describe('the user does not populate the input field',() => { 

    it('should display an error',() => { 
     const form = wrapper.find('form').first(); 
     form.simulate('submit', { 
     preventDefault:() => { 
     }, 
     // below I am trying to set the value of the name field 
     target: [ 
      { 
      value: '', 
      } 
     ], 
     }); 
     expect(
     wrapper.text() 
    ).toBe('Please enter your name.'); 
    }); 

    }); 

Antwort

1

Als Faustregel sollten Sie möglichst keine Refs verwenden, warum? here

In Ihrem Fall schlage ich eine der besseren Ansätze sein könnte:

class InputForm extends Component { 
     constructor(props) { 
     super(props); 
     this.state = { 
      name : '' 
     } 
     this.onFormSubmit = this.onFormSubmit.bind(this); 
     this.handleNameChange = this.handleNameChange.bind(this); 
     } 


     handleNameChange(e){ 
     this.setState({name:e.target.value}) 
     } 

     onFormSubmit(e) { 
     e.preventDefault(); 
     this.props.submitForm(this.state.name); 
     } 

     render() { 
     let errorMsg = (this.props.validationError ? 'Please enter your name.' : null); 
     return (
      <form onSubmit={(e) => this.onFormSubmit(e)}> 
      <input 
       type="text" 
       placeholder="Name" 
       onChange={this.handleNameChange} 
      /> 
      <p className="error"> 
       {errorMsg} 
      </p> 
      <input 
       type="submit" 
       className="btn" 
       value="Submit" 
      /> 
      </form> 
     ); 
     } 
    } 

Ich denke, das Ihr Problem lösen. Damit sollte Ihr Test gut laufen.

+0

Ich weiß Ihren Kommentar zu schätzen, aber ich möchte den Status nicht in zwei separaten Komponenten verwalten. Die Klasse '' 'inputForm''' ist eine Kindkomponente einer viel größeren Anwendung. Die gesamte Verwaltung wird von der übergeordneten Komponente übernommen und bei Bedarf als Requisite übergeben. Mit der Zeit werde ich die Anwendung aktualisieren, um Redux für bessere Zustandsverwaltung zu verwenden. –

1

Das Problem wurde in this thread bereits diskutiert.
Und diese Lösung funktioniert für mich.

import { mount, shallow } from 'enzyme'; 
    import InputForm from '../InputForm': 
    import React from 'react'; 
    import { spy } from 'sinon'; 

    describe('Form',() => { 
    it('submit event when click submit',() => { 
     const callback = spy(); 
     const wrapper = mount(<InputForm />); 
     wrapper.find('[type="submit"]').get(0).click(); 
     expect(callback).to.have.been.called(); 
    }); 
    }); 

Seine Verwendung von Mokka + Chai anstelle von Scherz. Aber Sie können eine Vorstellung davon bekommen, wie es geht.

+0

das ist hilfreich, aber ich denke, Sie haben die Frage missverstanden. Ja, ich möchte das Senden des Formulars testen, aber ich möchte es mit einem Wert und erneut ohne einen Wert testen. –

2

Ich denke, dass Sie Ereignisobjekt nicht übergeben müssen, um das Senden-Ereignis zu simulieren. Das sollte funktionieren.

describe('the user does not populate the input field',() => { 

    it('should display an error',() => { 
     const form = wrapper.find('form').first(); 
     form.simulate('submit'); 
     expect(
     wrapper.find('p.error').first().text() 
    ).toBe('Please enter your name.'); 
    }); 

    }); 
+1

Ich glaube, ich muss das Event-Objekt übergeben, sonst bekomme ich einen Fehler '' 'TypeError: Kann die Eigenschaft 'preventDefault' von undefined''' nicht lesen. http://airbnb.io/enzyme/docs/api/ShallowWrapper/simulate.html wenn Enzym-Simulate die Form vorgibt, ruft es die Methode '' onFormSubmit'' auf, die wiederum die Ereignisobjekte '' preventDefault''' aufruft Methode. Ohne eine leere '' 'preventDefault''' Methode zu übergeben, wird der Test einen Fehler auslösen. Untersuchen Sie die Klasse '' '' inputForm''', um sie besser zu verstehen. –

Verwandte Themen