How to change the Menu dropdown element from Select in MaterialUI? - reactjs

What I need to do is actually change the HTML from the select dropdown when the property multiple is true, to be something like this:
Don't need to be exactly like that, the main thing that I want to do is add the checkbox before the option label. I can't see a way of doing this because the select component only accepts a MenuProps prop instead accepting a MenuComponent as well..
The select component docs:
https://material-ui.com/pt/components/selects

I don't think you can do that with the Select component without having to modify it a lot, but you can use Autocomplete which has pretty much the same functionality and you can add checkboxes to it.

Related

Custom Select with radio buttons as options

I need to do this in a React component:
I tried to hide/show a div, but the problem is to set a click listener on the whole page to hide the div, and it seems to be wrong.
I'm also using Formik, but I can't find the way to customize the select Field to have this kind of look.
How is the best way to approach this?
You can use an onBlur event to hide this div, instead of setting an event listener for the whole page.

How can I find and click a button that has no text using React Testing Library?

Many React Testing Library examples show how to find and click a button using the getByText query, as in:
fireEvent.click(getByText("Create"))
OR
userEvent.click(getByText("Create"))
However, it's common to have buttons with no text and only SVG icons, like Material UI's icon buttons or floating action buttons. Is there a recommended way to query for and click buttons like these? For context, I'm using the higher-level events provided by the companion user-event library.
For icon buttons, add an aria-label attribute like below:
<button aria-label='edit'>
<edit-icon />
</button>
Then in your test, pass the accessible name when calling getByRole()
screen.getByRole('button', {
name: /edit/i
})
From the docs:
The accessible name is for simple cases equal to e.g. the label of a
form element, or the text content of a button, or the value of the
aria-label attribute.
There are several ways to query an element, without seeing your hierarchy of elements, it's hard to say. But, there are several ways to query an element, an alternative to using getByText() could be getByRole('button'). If you want to add a data-testid to the element you could use getByTestId(). There are some more available queries found here: https://testing-library.com/docs/dom-testing-library/api-queries
There are a bunch of different ways to do it, including everyone's favorite fallback, data-tested. But if you're using Material UI, you might be looking for the most "MUI" way to do this. Two ideas:
The MUI documentation shows all its buttons wrapped with a label element with an htmlFor property. You could do this and then use getByLabelText()
Your icon buttons probably have (and should!) a tooltip, and the tooltip text is probably coming from a title property. Then you can get the button with getByTitle().
For me non of above answers works, what is worked for me is:
screen.getByRole('button', { name: /<icon-file-name>/i });
In my case the button with only svg file.
The best possible way of finding an element is to simulate the most User oriented approach. So probably User expects the role button and then searches for an icon in your case. That's where semantic HTML plays a role for elements structure inside your component.
MUI buttons also implement a name attribute for some icon buttons used inside another component e.g. Select and I strongly recommend using this attribute for testing purpose.
Please remember that, your tests should be unaware of implementation, so identification should rely on name, role, label and other "natural" attributes. But if that is not possible using data-testid should be your last resort.
A very good overall approach (not only for icon buttons) is to specify a name property alongside role in getByRole query:
const listOpenButton = screen.getByRole("button", { name: /open/i });
Also a data-testid approach:
const listOpenButton = screen.getByTestId("myButtonId");

Set defaultSelectedKeys with a button click in antd Tree to change Selected Node

I would like to change the selected node in antd Tree by using defaultSelectedKeys property, doesn't work. I also tried changing other property like showLine which seem to work but not defaultSelectedKeys.
Here is the link to code: link
Also, suggest if a better way to achieve the same.
TIA
defaultSelectedKeys used only on mount, therefore changing the state without unmounting the component will not affect the defaultSelectedKeys.
If you want to control the select values, use selectedKeys:
selectedKeys (Controlled) Specifies the keys of the selected treeNodes | string[]

Handling focus with react-select

I'm trying to figure out how to work around what appears to be greedy-focus issues with react-select.
I'm using custom components in my MenuList component that need the focus to work (rc-slider). Basically, I'd like the select to support an additional value for each option and I'm using a Slider to do that.
The issue with the sliders is that I can click on them to change the value, but can't drag the handles, as the Select seems to take back the focus (and even close the drop-down if menuIsOpen is not controlled).
The select does need to re-render when the values change, but I can't figure out why the focus has to change.
https://codesandbox.io/s/epic-moon-cv33b

How to refer to conditional elements when unit testing React components using jest and enzyme

I'm trying to test a component which should show a login and subscribe button when a user is not authenticated, but should show a logout button when a user is authenticated.
How should I refer to these buttons when making the test?
All examples I found is people doing things like:
expect(wrapper.find(Button).lenght).toBe(1); // or whatever
But this obviously doesn't fit my case, since I always have at least one button and they are all the same, except for its text and action.
So I think I need some way to refer to these buttons, so I could pass an authenticated prop and check if exactly the logout button is rendered.
What would be the best approach on doing that?
The options for selecting elements can be seen in the documentation for Selector.
In this case, you'd probably want to add css classes and use the class syntax, or perhaps the attribute syntax if your buttons use input elements where the text is set as an attribute.
You need to determine what differentiates each button. First, find the button:
const button = wrapper.find(Button)
Then expect() on some characteristic of the button. For example,
expect(button.props().children).toEqual('Subscribe')
or
expect(button.props().children).toEqual('Logout')
Just use filter:
wrraper.find(Button).filter({className:'any'})
wrraper.find(Button).filter({label:'any'})
...etc

Resources