Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
930 views
in Technique[技术] by (71.8m points)

reactjs - jest + enzyme, using mount(), document.getElementById() returns null on component which appear after _method call

I faced a problem with my jest+enzyme mount() testing. I am testing a function, which switches displaying components.

Switch between components: when state.infoDisplayContent = 'mission' a missionControl component is mounted, when state.infoDisplayContent = 'profile' - other component steps in:

_modifyAgentStatus () {
    const { currentAgentProfile, agentsDatabase } = this.state;
    const agentToMod = currentAgentProfile;

    if (agentToMod.status === 'Free') {
        this.setState({
            infoDisplayContent: 'mission'
        });
        agentToMod.status = 'Waiting';
    } else if (agentToMod.status === 'Waiting') {
        const locationSelect = document.getElementById('missionLocationSelect');

        agentToMod.location = locationSelect[locationSelect.selectedIndex].innerText;
        agentToMod.status = 'On Mission';
        this.setState({
            infoDisplayContent: 'profile'
        });
    }
}

When I trigger this function everything looks Ok, this test runs well and test successfully pass with required component:

import React from 'react';
import { mount } from 'enzyme';
import App from '../containers/App';

const result = mount(
    <App />
)

test('change mission controls', () => {
    expect(result.state().currentAgentProfile.status).toBe('Free');
    result.find('#statusController').simulate('click');
    expect(result.find('#missionControls')).toHaveLength(1);
    expect(result.find('#missionLocationSelect')).toHaveLength(1);
    expect(result.state().currentAgentProfile.status).toBe('Waiting');
});

But when I simulate onClick two times: 

test('change mission controls', () => {
    expect(result.state().currentAgentProfile.status).toBe('Free');
    result.find('#statusController').simulate('click');
    expect(result.find('#missionControls')).toHaveLength(1);
    expect(result.find('#missionLocationSelect')).toHaveLength(1);
    expect(result.state().currentAgentProfile.status).toBe('Waiting');
    result.find('#statusController').simulate('click');
    expect(result.state().currentAgentProfile.status).toBe('On Mission');
});

I get this assert:

    TypeError: Cannot read property 'selectedIndex' of null

  at App._modifyAgentStatus (development/containers/App/index.js:251:68)
  at Object.invokeGuardedCallback [as invokeGuardedCallbackWithCatch] (node_modules/react-dom/lib/ReactErrorUtils.js:26:5)
  at executeDispatch (node_modules/react-dom/lib/EventPluginUtils.js:83:21)
  at Object.executeDispatchesInOrder (node_modules/react-dom/lib/EventPluginUtils.js:108:5)
  at executeDispatchesAndRelease (node_modules/react-dom/lib/EventPluginHub.js:43:22)
  at executeDispatchesAndReleaseSimulated (node_modules/react-dom/lib/EventPluginHub.js:51:10)
  at forEachAccumulated (node_modules/react-dom/lib/forEachAccumulated.js:26:8)
  at Object.processEventQueue (node_modules/react-dom/lib/EventPluginHub.js:255:7)
  at node_modules/react-dom/lib/ReactTestUtils.js:350:22
  at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-dom/lib/Transaction.js:140:20)
  at Object.batchedUpdates (node_modules/react-dom/lib/ReactDefaultBatchingStrategy.js:62:26)
  at Object.batchedUpdates (node_modules/react-dom/lib/ReactUpdates.js:97:27)
  at node_modules/react-dom/lib/ReactTestUtils.js:348:18
  at ReactWrapper.<anonymous> (node_modules/enzyme/build/ReactWrapper.js:776:11)
  at ReactWrapper.single (node_modules/enzyme/build/ReactWrapper.js:1421:25)
  at ReactWrapper.simulate (node_modules/enzyme/build/ReactWrapper.js:769:14)
  at Object.<anonymous> (development/tests/AgentProfile.test.js:26:38)
  at process._tickCallback (internal/process/next_tick.js:109:7)

It is obvious that:

document.getElementById('missionLocationSelect');

return null, but I can not get why. Element passes tests, as I mention.

expect(result.find('#missionLocationSelect')).toHaveLength(1);

But it could not be captured with document.getElementById().

Please, help me to fix this problem and run tests.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Found the solution thanks to https://stackoverflow.com/users/853560/lewis-chung and gods of Google:

  1. Attached my component to DOM via attachTo param:

    const result = mount(
        <App />, { attachTo: document.body }
    );
    
  2. Changed buggy string in my method to string which works with element Object

agentToMod.location = locationSelect.options[locationSelect.selectedIndex].text;` : 

_modifyAgentStatus () {

    const { currentAgentProfile, agentsDatabase } = this.state;
    const agentToMod = currentAgentProfile;

    if (agentToMod.status === 'Free') {
        this.setState({
            infoDisplayContent: 'mission'
        });
        agentToMod.status = 'Waiting';
    } else if (agentToMod.status === 'Waiting') {
        const locationSelect = document.getElementById('missionLocationSelect');

        agentToMod.location = agentToMod.location = locationSelect.options[locationSelect.selectedIndex].text;
        agentToMod.status = 'On Mission';
        this.setState({
            infoDisplayContent: 'profile'
            });
        }
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...