Anyway to debug react-select dropdown from the browser devtools? - reactjs

I'm mostly interested in seeing the class names used so I can override them. Problem is, as soon as I click anywhere, even on the dev tools, the drop-down gets removed from the DOM, so there's no way to inspect it.
thanks

You can get all the classNames straight off the source:
Main element:
let className = classNames('Select', this.props.className, {
'has-value': valueArray.length,
'is-clearable': this.props.clearable,
'is-disabled': this.props.disabled,
'is-focused': this.state.isFocused,
'is-loading': this.props.isLoading,
'is-open': isOpen,
'is-pseudo-focused': this.state.isPseudoFocused,
'is-searchable': this.props.searchable,
'Select--multi': this.props.multi,
'Select--rtl': this.props.rtl,
'Select--single': !this.props.multi,
});
You can get the menu classnames from there as well.

Related

How to test react components on a site in Cypress E2E?

I have a project in which some components, such as dropdowns, are written in React.
In this case, I can't select an item from the dropdown because the DOM doesn't show what's in that dropdown.
<div class="Select__control css-1s2u09g-control"><div class="Select__value-container css-1d8n9bt"><div class="Select__placeholder css-14el2xx-placeholder" id="react-select-6-placeholder">Select...</div><input id="react-select-6-input" tabindex="0" inputmode="none" aria-autocomplete="list" aria-expanded="false" aria-haspopup="true" role="combobox" aria-readonly="true" aria-describedby="react-select-6-placeholder" class="css-1hac4vs-dummyInput" value=""></div><div class="Select__indicators css-1wy0on6"><div class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer" aria-hidden="true"><span></span></div></div></div>
How to conduct E2E tests in this case? Can someone explain or share their experience? I did not find information on the Internet. thank you
I looked for this component in the source code, but there are no files with react in the project code, these components are in node_modules, and it is not clear how to access this dropdown
This looks like the react-select control (judging by the classes).
This "hair-trigger" behavior makes it hard to find the options, the list disappears upon any mouse action.
The way I do it is
open the devtools
right-click the select, click inspect to find it in devtools
click the select on the page to open it, repeat a few times to open and close, watch the devtools
an element in devtools appears and disappears when menu is opened and closed. The element has format like this: <div id="react-select-6-listbox">, but the number in the id varies depending on how many selects are used on the page.
We now know the id of the options wrapper, so this is the test code:
cy.get('.Select__control')
.parent() // the top-level of react-select
.click() // open the list
cy.get('[id^="react-select"][id$="listbox"]') // the injected options wrapper
.within(() => {
cy.contains('5 - May').click() // select an option
})
cy.get('.Select__control')
.find('.Select__placeholder')
.should('contain', '5 - May') // verify selected text
If the 5 - May text is unique on the page you can just select it after opening the dropdown, but using .within() on the wrapper is safer.

how to set a text for a group in vis.js using groupTemplate

I have an application and using vis.js to build timeline events.
I'm using React.
I want to add an icon near each event, so I using groupTemplate and I want to render there a component with group text and icon.
in the options I add:
groupTemplate: (item, element) => {
if (!item) return;
ReactDOM.render(<TimelineGroupComp item={item}/>, element);
}
TimelineGroupComp component render function:
return (
<div className="primary-wrapper" key={this.props.item.content}>
<div style="background-image:url(../images/myIcon.svg);"/>
</div>
);
I get the correct Icon but the text is the item.id instead item.content.
I try to add a span with the correct text in the TimelineGroupComp but it renders also the item.id, not only the correct text.
Also I have another problem: when I collapse/expaned the group, I have an error in the console:
Warning: render(...): It looks like the React-rendered content of this
container was removed without using React. This is not supported and will
cause errors. Instead, call ReactDOM.unmountComponentAtNode to empty a
container.
and the group is render normal, ignored my component.
I know this post is almost a year old, but I thought I'd post the answer to this question anyways for anyone who gets the same issue in the future. I've had the same issue and this is how I fixed it.
Starting with React 16, if you want to use React templates in Vis Timeline you'll have to use React.createPortal in the groupTemplate option, see https://jsfiddle.net/api/post/library/pure/.
For the code above, the correct groupTemplate would be:
groupTemplate: (item, element) => {
if (!item) return;
ReactDOM.createPortal(
ReactDOM.render(<TimelineGroupComp item={item}/>, element),
element
)
}

Test : Click (fireEvent.click) on Link in react-router-dom with react-testing-library doesn't trigger

I am testing Link from 'react-router-dom' with react-testing-library.
Normaly clicking on this link, should appears linkId on the page.
But fireEvent.click on my tests, does not trigger the action. Therefore I have not my content.
<ul>
<li>
<Link data-testid="item" to={generatePath(LINK_TEST, { linkId: 'Link_test1' })}>Link Test 1</Link>
</li>
... test :
const linkButton = getByText(/Link Test 1/)
fireEvent.click(linkButton)
const content = queryAllByText(/Page : Link_test1/)
await waitForElement(() => content)
expect(content).toHaveLength(1)
If it's not too late to give my input:
You are initiating a click, but are not specifying with which button you are clicking. Your line of code should look like that:
fireEvent.click(linkButton, { button: 0});
As button: 0 means 'left-click'. Hope this helps.
Edit: Additionally, I don't think await is needed in this case. If this is some piece of the whole code, you may indeed need it, but in a similar case I just fire the click event and then check if what I'm expecting to be in the document IS in the document, like:
expect(getByText('Page : Link_test1')).toBeInTheDocument();
Or something like that, as I'm not exactly sure what are you expecting after the link click. Note that .toBeInTheDocument() is a method from '#testing-library/jest-dom' and is imported as
'#testing-library/jest-dom/extend-expect'
I have been hitting this issue with ALL links (I'm not using react-router-dom). But one way I got around it was to actually set the URL with window.location.href = linkHref.
When I did that, then it triggered the event handlers I have setup.
Not sure if this helps in the slightest, but wanted to mention it as a possible work-around. Your linkButton will have an href property you can snag.

Why does React functionality not working on Chrome and Opera?

I made a Single Page Application with React and everything was fine until I tested it on all the major browsers.
I used Mozilla during the development but then I tried it on other browsers and it worked on Edge, Explorer and Mozilla but it didn't on Chrome and Opera. All of the UI stuff works fine, and everything design related behaves well except the functionality that I made with React. So clicking on the Meal Types on the options dropdown, another list is supposed to appear on the page replacing the initial one with those 3 sections(Blog, Recipe, Tips). The application is supposed to expand further again by clicking on the Cookie section and again by clicking on the Horse section. As I said, all of this works fine except in Chrome and Opera. I want to make React behave as I described in Chrome and Opera too.
This is a link to the files
https://github.com/cristiAndreiTarasi/React_App
I expect that on clicking on the Meal Type option the app make those additional sections appear below - as it does in other browsers - in Chrome and Opera browsers and find what the problem is.
In your Header.jsx and Footer.jsx files you use class instead of className a few times, so you should correct that: https://reactjs.org/docs/faq-styling.html
Your problem is that you are registering an onClick on the <option> element, when you should be using the onChange prop on the <select> element itself, not the <option> element.
<select onChange={this.handleChange} className="custom-select mb-3">
<option selected>All</option>
<option value="mealType">Meal Type</option>
<option>Ingredients</option>
<option>World Cuisine</option>
<option>Cooking Style</option>
</select>
Your event handler looking like this:
handleChange = (event) => {
this.setState({
[event.target.value]: true,
});
}
Your state shouldn't be holding entire React components like it currently is, instead try something like this:
state = {
mealType: false,
}
With your render looking like this:
{this.state.mealType && <MealType click={this.handleClickTwo}/>}
As a general rule: state should contain data that a component's event handlers may change to trigger a UI update. this.state should only contain the minimal amount of data needed to represent your UI's state. See here for more details: http://web.archive.org/web/20150419023006/http://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html

click method is not working properly in selenium webdriver

i am trying to Automate flipkart website in which i am trying to change address but "add new adress" is not getting clicked i have attached the snapshot
my code is like driver.findElement(By.xpath("//*[#id='ng-app']/div/div[2]/ul/li[2]/div/div[2]/div[2]/div[2]/a/span")).click();
please give the appropriate help
I doesn't look that you are clicking active element, the xpath is //*[#id='ng-app']/div/div[2]/ul/li[2]/div/div[2]/div[2]/div[2]/a/span not correct it clicks on some span.
Use Firepath https://addons.mozilla.org/en-US/firefox/addon/firepath/ to get the xpath.
To ensure that button is clickable Use isDisplayed() and isEnabled() method before clicking on "Add New Address" button, this method return boolean value.
driver.findElement(By.xpath("//*[#id='ng-app']/div/div[2]/ul/li[2]/div/div[2]/div[2]/div[2]/a/span")).isDisplayed();
driver.findElement(By.xpath("//*[#id='ng-app']/div/div[2]/ul/li[2]/div/div[2]/div[2]/div[2]/a/span")).isEnabled();
Also you can verify that element is exist on page or not using below code
if(driver.findElements(byVal).size()!=0){
// Element is present.
}
hope it may helpful to identify cause of issue, why its not clickable.
First and foremost, Use a customized Xpath instead of the one you are using which is extracted directly from the browser. If no customized Xpath can be constructed then try a customized Css or any other locator if possible.
Try to go through the following attempts in order (I hope you can grasp why this is):
1- If .click() still doesn’t work, then keep on changing the values of the attributes you are using to construct your customized xpath, cssSelector, or locator.
2- Use the Actions class.
3- Use JavaScript executioner
4- instead of click(), try using any of: .sendKeys(“\n”). Or .sendKeys(keys.ENTER) or .sendKeys(keys.RETURN)

Resources