Can't get TreeView Icons and IconButton for Tests - reactjs

I'm trying to test a component that has an endAdornment IconButton and other with a TreeView, but neither the IconButton and the ExpandIcon/CollapseIcon have good options to dispatch test events.
This is the TextField component that I'm using:
<TextField
fullWidth
label="Label"
onChange={handleChange}
type="text"
InputProps={{
endAdornment: (
<InputAdornment >
<IconButton onClick={openAssetHierarchy}>
<Folder />
</IconButton>
</InputAdornment>
),
}}
/>
This is the TreeView component:
<TreeView
defaultCollapseIcon={<ArrowDropDown />}
defaultExpandIcon={<ArrowRight />}
defaultEndIcon={<div style={{ width: 24 }} />}
onNodeToggle={handleToggle}
onNodeSelect={handleSelect}
>
[...]
</TreeView>
For the TextField icon button:
For TreeView when using Testing Playground to get the icon
There aren't good queries to get the icons for tests. How can I get these options?

For the IconButton you can add an aria-label attribute to the element, then use getByLabelText to access it in your test. This is also useful and recommended for accessibility purposes.
<IconButton aria-label="add a file" onClick={openAssetHierarchy}>
<Folder />
</IconButton>
screen.getByLabelText('add a file') // Gets you the `IconButton`
For the TreeView items, I assume you don't actually need to access the icon specifically but simply need to access the TreeItem for testing purposes. This can be done with getByRole and passing the tree item's name.
screen.getByRole('treeitem', { name: /Test1/ }) // Gets you the first `TreeItem`

Related

React: Show MUI Autocomplete freeSolo with drop-down arrow

I am new to MUI, so need a little help.
I want to use <Autocomplete freeSolo ...> that shows a dropdown arrow icon like it were a combo-box mode.
Looks like popupIcon and forcePopupIcon props are being ignored in freeSolo mode.
Thanks!
You can add your icon in renderInput prop of Autocomplete. Actually Autocomplete component is just a wrapper around Textfield component. In MUI V5, You can add any icon at the start or end of it by targeting Textfield inside it. For your case check the example below.
import Autocomplete from '#mui/material/Autocomplete'
import InputAdornment from '#mui/material/InputAdornment'
import TextField from '#mui/material/TextField'
import ArrowDropDownIcon from '#mui/icons-material/ArrowDropDown'
<Autocomplete
freeSolo
options={myOptions}
renderInput={(params) => (
<TextField
{...params}
label="My label"
InputProps={{ endAdornment: (
<InputAdornment position="end">
<ArrowDropDownIcon />
</InputAdornment>
),
}}
/>
)}
/>

Textfield's label gets clipped when inside a Dialog

When using a Textfield as the first child of DialogContent:
export default function App() {
return (
<Dialog open={true}>
<DialogTitle>Hey</DialogTitle>
<DialogContent>
<TextField
fullWidth
id='name'
label={'Foo'}
name='name'
required
type='text'
value={'Bar'}
/>
</DialogContent>
</Dialog>
);
}
its label (when using `variant="outlined") gets clipped. See codebox sample. Any way to fix this problem? e.g. by customizing the theme?
You can easily fix that issue by adding some margin to the TextField like the following.
sx={{ marginTop: 2 }}
Or you could wrap the TextField using Box inside the DialogContent like the following.
<Box p={1}>
<TextField
...
/>
</Box>

React Mui DateRangePicker include Calendar Icon

I want to implement a DateRangePicker from Material UI with a calendar icon, e.g. it should look like that:
According to the Api documentation it should work with
components={{
OpenPickerIcon: CalendarTodayIcon
}}
but it doesn't. See codesandbock.
I also tried it by adding an Icon manually to the TextField which shows an Icon but doesn't open the PopupMenu when clicking on the Icon.
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton>
<CalendarTodayIcon />
</IconButton>
</InputAdornment>
)
}}
Anyone an idea how to implement that? I am using mui 5.1.0 and mui/lab 5.0.0-alpha.50
I haven't used the Component from the library but you're right according to the documentation
components={{
OpenPickerIcon: CalendarTodayIcon
}}
Should work but it doesn't.
In your workaround, you're not supplying anything on the IconButton onClick event handler so naturally, the icon does nothing when clicked.
What you need to do is focus on the input whenever the Icon is clicked. You can achieve that by using the useRef hook in your input and then calling the current.focus() method inside the onClick handler of the IconButton.
const startInputRef = React.useRef();
<TextField
inputRef={startInputRef}
{...startProps}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => {
startInputRef.current.focus();
}}
>
<CalendarTodayIcon />
</IconButton>
</InputAdornment>
)
}}
/>
See codesandbox for a working example.
I still think this is a hacky workaround though so I'd suggest opening an issue on the library's github repo to get instructions.

How to make smaller radio buttons

I can't find a way to create a group of three small (19px high) labelled radio buttons in material-ui. I'm migrating a browser app from static HTML/JS into material-ui/react, and I need the group to stay the same size.
The button group I'm starting with has three small vertically aligned labelled radio buttons. Here's
a screenshot:
Here's the code for the best I've been able to do using the material-ui documentation:
<FormControl
margin="dense"
size="small"
>
<RadioGroup
size="small"
name="dataSource"
value={dataSource}
onChange={handleDataSourceChange}
>
<FormControlLabel
value="CaseCount"
control={
<Radio
className={classes.radio}
size="small"
/>
}
label="Cases"
/>
<FormControlLabel
value="DeathCount"
control={
<Radio
className={classes.radio}
size="small"
/>
}
label="Deaths"
/>
<FormControlLabel
value="HotSpots"
control={
<Radio
size="small"
/>
}
label="HotSpot warning"
/>
</RadioGroup>
</FormControl>
This results in an oversized group -- the button icons are too large, the text is too large, and each row is 38 pixels high (twice the 19 pixels of the original). Here's a screenshot of the material-ui counterpart:
I think I want the result to use a vanilla html input (with type of radio) instead of an svg icon, and a font with font-height of 13px. How do I do that in material-ui?
I know how to fix the padding-left so I'm not worried about that. How do I get rows that are 19px high instead of 38px?
Reason
If you inspect the Material radio button, we can see that the padding of the radio button is causing each row to have a height of 38px.
Code
Therefore, we can simply remove the vertical padding from all radio buttons with the following code (note that my code is slightly different than yours):
const useStyles = makeStyles({
// Applied to <Radio />
root: {
width: 19,
height: 19,
paddingTop: 0,
paddingBottom: 0,
},
// Applied to <FormControlLabel />
label: {
fontSize: 13
}
});
export default function RadioButtonsGroup() {
const [value, setValue] = React.useState("CaseCount");
const classes = useStyles();
const handleChange = (event) => {
setValue(event.target.value);
};
const customRadio = <Radio size="small" classes={{root: classes.root}} />;
return (
<FormControl component="fieldset">
<RadioGroup value={value} onChange={handleChange}>
<FormControlLabel classes={{label: classes.label}} control={customRadio} value="CaseCount" label="Cases" />
<FormControlLabel classes={{label: classes.label}} control={customRadio} value="DeathCount" label="Deaths" />
<FormControlLabel
classes={{label: classes.label}}
control={customRadio}
value="HotSpots"
label="Hotspot Warning"
/>
</RadioGroup>
</FormControl>
);
}
Explanation
According to the Radio API documentation, we can apply custom styling to root of the radio button by overriding styles with classes using the class name of root. Therefore, we first define a style object called root in the makeStyles() function. Next, we apply the styling to the Radio component by adding the prop of classes={{root: classes.root}}:
<Radio size="small" classes={{root: classes.root}} />
Similarly, according to the FormControlLabel API documentation, we can apply custom styling to the text label using the label class name. Therefore, we first define a style object of label in the makeStyles() function. Next, we apply the styling to the FormControlLabel component by adding the prop of classes={{label: classes.label}}:
<FormControlLabel classes={{label: classes.label}} /* ... */ />

How to use label in IconMenu

I am using IconMenu with IconButton and Icon.
I want to have a label just before 'NavigationExpandMoreIcon'.
Is it possible to achieve in this possible setup or do I need to change the components that I am using?
My Code looks like:
<IconMenu
iconButtonElement={
<IconButton touch>
<NavigationExpandMoreIcon />
</IconButton>
}
onItemClick={this.handleClick}
>
{options}
</IconMenu>
I am using material UI 0.20 and React 16
I also have material ui 3.7 (So I can upgrade the component, if needed)
I think you can customize using iconButtonElement options it is accept node..
<IconMenu
iconButtonElement={
<React.Fragment>
//Use styles based on your need for label component...
<label>Your Label here</label>
<IconButton touch>
<NavigationExpandMoreIcon />
</IconButton>
</React.Fragement>
}
onItemClick={this.handleClick}
>
{options}
</IconMenu>

Resources