2016-05-13 3 views
26

Ich bin verwirrt darüber, wie auf <input> Wert zugreifen, wenn Sie mount verwenden. Hier ist, was ich als meine Test bekam:Enzym - Wie Zugriff und Einstellung Wert?

it('cancels changes when user presses esc', done => { 
    const wrapper = mount(<EditableText defaultValue="Hello" />); 
    const input = wrapper.find('input'); 

    console.log(input.render().attr('value')); 
    input.simulate('focus'); 
    done(); 
    }); 

Die Konsole druckt undefined. Aber wenn ich etwas ändern Sie den Code, es funktioniert:

it('cancels changes when user presses esc', done => { 
    const wrapper = render(<EditableText defaultValue="Hello" />); 
    const input = wrapper.find('input'); 

    console.log(input.val()); 
    input.simulate('focus'); 
    done(); 
    }); 

Außer natürlich, die input.simulate Linie versagt, da ich render bin jetzt mit. Ich muss beide richtig arbeiten. Wie behebe ich das?

EDIT:

Ich sollte erwähnen, <EditableText /> ist nicht eine kontrollierte Komponente. Aber wenn ich defaultValue in <input /> passiere, scheint es, den Wert einzustellen. Der zweite Codeblock oben druckt den Wert aus, und wenn ich das Eingabeelement in Chrome inspiziere und in der Konsole $0.value gebe, zeigt es den erwarteten Wert an.

Antwort

15

Verstanden. (Aktualisiert/verbesserte Version)

it('cancels changes when user presses esc', done => { 
    const wrapper = mount(<EditableText defaultValue="Hello" />); 
    const input = wrapper.find('input'); 

    input.simulate('focus'); 
    input.simulate('change', { target: { value: 'Changed' } }); 
    input.simulate('keyDown', { 
     which: 27, 
     target: { 
     blur() { 
      // Needed since <EditableText /> calls target.blur() 
      input.simulate('blur'); 
     }, 
     }, 
    }); 
    expect(input.get(0).value).to.equal('Hello'); 

    done(); 
    }); 
+0

Neugierig, wie dies für Sie arbeitet. Wir verwenden PhantomJS und 'mount()' fügt keine Komponenten in das DOM ein. Sie können also nicht fokussiert werden. Wir müssen ein DOM-Element hinzufügen und die Option 'context' für' mount() 'verwenden. – Pre101

+0

@ Pre101 Ich habe tatsächlich angefangen, Jest anstelle von Enzyme zu verwenden. Sehr empfehlenswert! – ffxsam

+0

@ffxsam: input.get (0) .value zeigt immer "undefined" –

24

Ich denke, was Sie wollen, ist:

input.simulate('change', { target: { value: 'Hello' } }) 

Here's my source.

Sie sollten render() nirgends verwenden, um den Wert festzulegen. Und nur zur Info, Sie verwenden zwei verschiedene render(). Die in Ihrem ersten Codeblock ist von Enzyme, und ist eine Methode auf dem Wrapper-Objekt mount und find geben Sie. Der zweite, obwohl es nicht 100% klar ist, ist wahrscheinlich der von react-dom. Wenn Sie Enzyme verwenden, verwenden Sie einfach shallow oder mount und render von react-dom.

+0

Die 'input.render()' ist nicht 'reaktiv-dom' render. Es ist dies: http://airbnb.io/enzym/docs/api/ShallowWrapper/render.html – ffxsam

+1

Auch 'shallow()' funktioniert nicht aus irgendeinem Grund .. das 'Fokus' Ereignis löst eine Methode aus, die versucht Referenz 'this.refs.input', was fehlschlägt. Aber wenn ich 'shallow' für' mount' austausche, funktioniert es wie erwartet. Meistens .. (ein weiteres Problem mit der Simulation der ESC-Taste) – ffxsam

+0

Ich hätte klarer sein sollen. Ich meinte den Render, der wie folgt aussieht: render () '. Ich denke, Ihr Anwendungsfall ist spezialisierter als ich dachte; Ich sehe, es behandelt nur die Einstellung des Eingabewertes, aber mit Fokus und "Abbrechen von Änderungen". Es wäre großartig, wenn Sie einen [Plunker] erstellen könnten (http://plnr.co/). –

0

In meinem Fall i ref Rückrufe wurde mit,

<input id="usuario" className="form-control" placeholder="Usuario" 
                 name="usuario" type="usuario" 
                 onKeyUp={this._validateMail.bind(this)} 
                 onChange={()=> this._validateMail()} 
                 ref={(val) =>{ this._username = val}} 
                > 

den Wert zu erhalten. Also Enzym wird den Wert von this._username nicht ändern.

Also musste ich:

login.node._username.value = "[email protected]"; 
    user.simulate('change'); 
    expect(login.state('mailValid')).toBe(true); 

Lage sein, den Wert setzen dann ändern aufrufen. Und dann behaupten.

1

Dies funktioniert für mich Enzym 2.4.1:

const wrapper = mount(<EditableText defaultValue="Hello" />); 
const input = wrapper.find('input'); 

console.log(input.node.value); 
+3

Als ich anfing, Jest/Enzym zu benutzen, habe ich oft ein Objekt "console.log" und durch (Sub-) Eigenschaften gegraben, um zu bekommen, was ich brauchte. Dabei habe ich oft '.node' in irgendeiner Form benutzt, so wie du es getan hast. Ich erinnere mich jedoch nicht daran, dass '.node' in der offiziellen Dokumentation erwähnt wurde, was darauf hindeutet, dass es zwischen Releases wechseln könnte, da es nicht offiziell Teil der öffentlich angekündigten API ist. Außerdem scheint es oft Alternativen zu geben. z.B. 'input.node.value' ===' input.get (0) .value'. Also, '.node' könnte funktionieren, und ich vermute, dass es manchmal einen guten Hack liefert, aber mit Vorsicht verwenden. –

3

Das ist für mich gearbeitet. Ich benutze create-react-app, das standardmäßig mit jest und Enzym 2.7.0 geliefert wird.

`

const wrapper = mount(<EditableText defaultValue="Hello" />); 
const input = wrapper.find('input')[index]; // where index is the position of the input field of interest 
input.node.value = 'Change'; 
input.simulate('change', input); 
done() 

`

8

Mit Enzym 3, wenn Sie benötigen einen Eingangswert zu ändern, aber nicht die onChange Funktion schießen müssen Sie ihn nur tun können (node Eigenschaft has been removed):

wrapper.find('input').instance().value = "foo";

Sie können wrapper.find('input').simulate("change", { target: { value: "foo" }}) verwenden, um onChange aufzurufen, wenn Sie eine Stütze dafür haben (dh für kontrollierte Komponenten).

+4

'HINWEIS: kann nur für eine Wrapper-Instanz aufgerufen werden, die auch die Root-Instanz ist.-aus den Dokumenten unter http://airbnb.io/enzyme/docs/api/ShallowWrapper/instance.html – davidjb

0

So viele verschiedene Meinungen hier. Das einzige, was für mich funktionierte, war keines der oben genannten, es war input.props().value. Ich hoffe das hilft.

1

Keiner der oben genannten funktionierte für mich. Dies ist, was für mich am Enzym gearbeitet^3.1.1:

input.instance().props.onChange(({ target: { value: '19:00' } })); 

Hier ist der Rest des Codes für Kontext ist:

const fakeHandleChangeValues = jest.fn(); 
    const fakeErrors = { 
    errors: [{ 
     timePeriod: opHoursData[0].timePeriod, 
     values: [{ 
     errorIndex: 2, 
     errorTime: '19:00', 
     }], 
    }], 
    state: true, 
    }; 
const wrapper = mount(<AccessibleUI 
    handleChangeValues={fakeHandleChangeValues} 
    opHoursData={opHoursData} 
    translations={translationsForRendering} 
    />); 
const input = wrapper.find('#input-2').at(0); 
input.instance().props.onChange(({ target: { value: '19:00' } })); 
expect(wrapper.state().error).toEqual(fakeErrors);