-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wrapper.find('#name') returning two elements but only one element is shown in wrapper.html() #836
Comments
Is the wrapper using mount or shallow? What is the |
Also what's the component code look like? It's possible cheerio is filtering out a duplicate ID. |
|
oops, sorry :-) |
@RyanAtViceSoftware the next step is, could you provide the actual React component code that generates this, as well as the code you're using in your tests to create the wrapper? |
@ljharb Here's the component and test Componentimport React, { Component } from 'react';
import '../../../../node_modules/deloitte-symphony-core-fe/dist/scss/components/form.scss';
import '../../../assets/sass/tabstyles.scss';
import '../../../assets/sass/sidePanelContainer.scss';
import * as icActions from '../../../state/actions/internalControl.action';
import { updateRightDrawerContent } from '../../../state/actions/drawer.action';
import { CANVAS_OBJECT_TYPES } from '../../../constants/canvasObjectTypes';
class OperationDetails extends Component {
constructor(props) {
super(props);
this.closePanel = this.closePanel.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
closePanel() {
// TODO: Ryan - We should be firing an action here and using redux state
var closeButton = document.getElementById("closeDrawer");
closeButton.click();
}
handleInputChange(event, field) {
let target = event.target;
let content = this.props.content;
if (target !== undefined) {
const value = target.type === 'checkbox' ? target.checked : target.value;
content.dto[field] = value;
this.props.content.dispatch(icActions.updateProcessDtos(content.dto, CANVAS_OBJECT_TYPES.Operation));
this.props.content.dispatch(updateRightDrawerContent(content));
}
}
// TODO: Ryan - We should use container\presentational pattern here
render() {
const { content } = this.props;
if (content) {
return (
<div className="sidePanelInnerContainer">
<div className="inputContainer">
<label htmlFor="name">Name</label>
<textarea id="name"
value={(content.dto) ? content.dto.text : ''}
onChange={(e) => {
this.handleInputChange(e, "text");
}}
></textarea>
<hr />
</div>
<div className="inputContainer">
<label htmlFor="description">Description</label>
<textarea id="description" name="description" defaultValue={content.dto && content.dto.description} onChange={(e) => {
this.handleInputChange(e, "description")
}}></textarea>
<hr />
</div>
</div>
);
}
else {
return <div/>;
}
}
}
export default OperationDetails; Testimport React from 'react';
import chai, { expect } from 'chai';
import { Provider } from 'react-redux';
import { mount, shallow } from 'enzyme';
import createRootReducer from '../../../src/state/reducers/createRootReducer';
import createStore from '../../../src/state/stores/main.store';
import '../../setupTests';
import App from '../../../src/containers/App/App';
import behaviors from '../behaviors';
import expected from './rightDrawerExpected';
import chaiProperties from 'chai-properties';
const go = (process.env.NODE_ENV === 'production') ? require('../../../GoJs/1.6.23-go-src') :
require('../../../GoJs/1.6.23-go-src-debug');
import * as chartUtils from '../../../src/common/util/chart/canvas.utils';
import ProcessCanvasComponent from '../../../src/components/canvas/processCanvas';
import {stubComponent} from '../../testUtils';
chai.use(chaiProperties);
chai.use(function(_chai, _) {
_chai.Assertion.addMethod('withMessage', function(msg) {
_.flag(this, 'message', msg);
});
});
function getTestingStore(initialState) {
const store = createStore(createRootReducer(initialState));
const dispatch = action => {
store.dispatch(action);
return {
andExpect: function(expected) {
expect(store.getState(),
"Store state was not what was expected after dispatching the following action: "
+ JSON.stringify(action))
.to.have.properties(expected);
}
}
};
return {
dispatch,
getState: store.getState,
subscribe: store.subscribe,
replacementReducer: store.replaceReducer
};
}
describe('Given I open a process and expand the details on an operation', () => {
it(
'when I update the title in the details pane then the operation on the canvas also shows the title',
() => {
const symphonyContext = {
engagementId: '897c6642-2244-4b7c-8311-198ed54602ce'
};
const store = getTestingStore();
const diagramMock = {
toolManager: {
linkingTool: { linkValidation: function() {} },
relinkingTool: { linkValidation: function() {} }
},
startTransaction: function() {}
};
chartUtils.AddNodeShapes = function() {
};
chartUtils.AddPalette = function() {
};
go.GraphObject = {
make: function() {
return diagramMock;
}
};
stubComponent(ProcessCanvasComponent);
const wrapper = mount(<Provider store={store}><App
symphonyContext={symphonyContext}/></Provider>);
store.dispatch(behaviors.setSymponyContext);
store.dispatch(behaviors.setConnectionRules);
store.dispatch(behaviors.loadProcesses);
store.dispatch(behaviors.setSymphonyEngagement);
store.dispatch(behaviors.setCurrentProcess);
store.dispatch(behaviors.navigateToProcessFlowDiagram);
store.dispatch(behaviors.openOperationInRightDrawer);
const nameTextAreaWrapper = wrapper.find('#name').first();
const nameTextAreaHtml = nameTextAreaWrapper.html();
const expectedNameTextAreaHtml = '<textarea id="name">Activate or redeem credit card</textarea>';
expect(nameTextAreaHtml).to.equal(expectedNameTextAreaHtml);
nameTextAreaWrapper.simulate('keydown', { which: 'c' })
const nameTextAreaHtmlAfter = wrapper.find('#name').first().html();
const expectedNameTextAreaHtmlAfter = '<textarea id="name">Activate or redeem credit card</textarea>';
expect(nameTextAreaHtmlAfter).to.equal(expectedNameTextAreaHtmlAfter);
});
}); |
@RyanAtViceSoftware Have you found a solution for this issue? Currently having a similar experience trying to locate text in a component. |
@frankmariette unfortunately no... |
Is this still an issue in v3? |
I have a same issue in v3. |
@CoderK can you file a new issue, just in case? |
@RyanAtViceSoftware |
@skrece22 there was not more than one component with name as id, that was the whole point of the issue and not I'm using |
@RyanAtBarefoot |
@RyanAtViceSoftware Whats the IDE you are using? |
@badaljain i was using web storm at that time |
I'm experiencing the same problem. Using Visual Studio Code and running code in console (npm test). |
Chiming in - I am having the same issue here and was able to get more information using Here's a simplified example:
You can see that enzyme included the react pseudo-element in its markup, so that if This was done with mount() |
This is indeed correct behavior. To filter out custom components, use |
|
I've also encountered this issue and don't really understand the reason why it works like this now? Why do I need to run some Mounting a single For example this:
Why would I expect to have 2 elements here? Could someone explain this behaviour to me? @ljharb? 😃 |
@sarneeh because in enzyme 3, the nodes you get are both React component instances, and DOM nodes. If you want to just have DOM nodes, you use |
@ljharb Alright, I understand that. But why it has been decided that this behaviour should be the default one? Couldn't it be reversed, so by default I'll get the behaviour from Enzyme v2, and in v3 have an additional method to get all of them? To be clear: I don't want to hate anyone nor anything, I just want to understand the decision behind it, because maybe I'm missing something, and maybe I could learn something too 😄 |
@sarneeh i believe this was chosen to match the way the react dev tools chrome extension works. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Got the same issue. For me worked adjusting a little bit the selector. Not sure why though. Also, |
@asumaran because of #836 (comment) |
In the following example, getting two results from function SomeWrapper({ as: AsComponent, id }) {
// Imagine that this does useful things :) There is a case for it.
return <AsComponent id={id} />;
}
mount(<SomeWrapper as="div" id="example-id" />)
.find('#example-id')
// This returns two items.
.getDOMNode(); |
@kumar303 |
Thanks, I did discover that from this thread (hooray). I was just providing a concrete example of how this is very surprising behavior. Maybe it could be aliased as |
Is "node" a DOM node, or a React tree node? Would a React Native user expect "node" to mean "DOM node", when a Host Node for RN is something like |
In the case of |
Your comment is that getting two dom nodes is surprising - are you getting a non-dom node from that method? |
Yes, the example in #836 (comment) gets a non-DOM node from |
Interesting. That does seem like a problem; |
Sure: #2244 Thanks for looking into it. |
Hi All
and my test was failing
When debugging
So Enzyme generates I haven't found a better solution than specifying Button |
@jasonsrogers you can add |
what is that "evaluate expression" debugger that you are using? it seems cool :D |
@lstickelhube It looks like WebStorm |
wrapper.find('#name') returning two elements but only one element is shown in wrapper.html().
expected outcome
only one element would be returned by
wrapper.find('#name')
and my eventual goal is to get the val of that textarea.wrapper.find('#name')
wrapper.html()
Note that there is only the one element with
id=name
below<textarea id="name">Activate or redeem credit card</textarea>
The text was updated successfully, but these errors were encountered: