Repository: mui/material-ui (TypeScript) — Feature

Issue:
[Select] Should have role='listbox' or 'combobox' instead of 'button'
<!--- Provide a general summary of the feature in the Title above -->

<!--
    Thank you very much for contributing to Material-UI by creating an issue! ❤️
    To avoid duplicate issues we ask you to check off the following list.
-->

<!-- Checked checkbox should look like this: [x] -->
- [x] This is not a v0.x issue. <!-- (v0.x is no longer maintained) -->
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Expected Behavior 🤔

Select should behave like native selects & screen readers recognize them as either 'listbox' or 'combobox' instead of button.
And there should be a way to associate label of the select to the label of that div having the tabindex='0'. Can be done by adding a aria-label to the div equal to the label prop.

## Current Behavior 😯

Select element is a div with role button & screen reader announces as 'Popup Button not pressed' with no label.

## Context 🔦

Better accessibility of the Selects.



Discussion:
> screen reader announces as 'Popup Button not pressed' 

Which screen readers?
Could this problem share the same root cause with #11833? 
Different screen readers announcing it little differently for example Voice over says its a 'toggle button' & chromevox extension saying as 'popup button not pressed' none of them indicate it as combobox or listbox instead of a button.
And also the label is associated with the hidden input field instead of the div with role button.
So the label is also not announced.
And this is not same as the issue #11833 as I am able to interact with the select properly with keyboard just the announcement is not proper.
No issue with keyboard navigation.
The role issue should be solved with #16739.

I think the issue was the presence of `aria-pressed` and a generic `aria-haspopup`. It now has `aria-haspopup="listbox"` following WAI-ARIA.

Labeling will be addressed in a followup PR.
@eps1lon Thanks for the update.
I think this should fix the screen reader announcement.
Still not confirmed if the labeling works correctly. Will be closed once labeling following wai-aria dropdown is implemented.

Resolving patch:
diff --git a/docs/pages/api/select.md b/docs/pages/api/select.md
--- a/docs/pages/api/select.md
+++ b/docs/pages/api/select.md
@@ -31,6 +31,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
 | <span class="prop-name">IconComponent</span> | <span class="prop-type">elementType</span> | <span class="prop-default">ArrowDropDownIcon</span> | The icon that displays the arrow. |
 | <span class="prop-name">input</span> | <span class="prop-type">element</span> |  | An `Input` element; does not have to be a material-ui specific `Input`. |
 | <span class="prop-name">inputProps</span> | <span class="prop-type">object</span> |  | [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Attributes) applied to the `input` element. When `native` is `true`, the attributes are applied on the `select` element. |
+| <span class="prop-name">labelId</span> | <span class="prop-type">string</span> |  | The idea of an element that acts as an additional label. The Select will be labelled by the additional label and the selected value. |
 | <span class="prop-name">labelWidth</span> | <span class="prop-type">number</span> | <span class="prop-default">0</span> | The label width to be used on OutlinedInput. This prop is required when the `variant` prop is `outlined`. |
 | <span class="prop-name">MenuProps</span> | <span class="prop-type">object</span> |  | Props applied to the [`Menu`](/api/menu/) element. |
 | <span class="prop-name">multiple</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If true, `value` must be an array and the menu will support multiple selections. |
diff --git a/docs/src/pages/components/selects/ControlledOpenSelect.js b/docs/src/pages/components/selects/ControlledOpenSelect.js
--- a/docs/src/pages/components/selects/ControlledOpenSelect.js
+++ b/docs/src/pages/components/selects/ControlledOpenSelect.js
@@ -40,17 +40,15 @@ export default function ControlledOpenSelect() {
         Open the select
       </Button>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="demo-controlled-open-select">Age</InputLabel>
+        <InputLabel id="demo-controlled-open-select-label">Age</InputLabel>
         <Select
+          labelId="demo-controlled-open-select-label"
+          id="demo-controlled-open-select"
           open={open}
           onClose={handleClose}
           onOpen={handleOpen}
           value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'demo-controlled-open-select',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
diff --git a/docs/src/pages/components/selects/ControlledOpenSelect.tsx b/docs/src/pages/components/selects/ControlledOpenSelect.tsx
--- a/docs/src/pages/components/selects/ControlledOpenSelect.tsx
+++ b/docs/src/pages/components/selects/ControlledOpenSelect.tsx
@@ -42,17 +42,15 @@ export default function ControlledOpenSelect() {
         Open the select
       </Button>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="demo-controlled-open-select">Age</InputLabel>
+        <InputLabel id="demo-controlled-open-select-label">Age</InputLabel>
         <Select
+          labelId="demo-controlled-open-select-label"
+          id="demo-controlled-open-select"
           open={open}
           onClose={handleClose}
           onOpen={handleOpen}
           value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'demo-controlled-open-select',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
diff --git a/docs/src/pages/components/selects/CustomizedSelects.js b/docs/src/pages/components/selects/CustomizedSelects.js
--- a/docs/src/pages/components/selects/CustomizedSelects.js
+++ b/docs/src/pages/components/selects/CustomizedSelects.js
@@ -61,15 +61,17 @@ export default function CustomizedSelects() {
   return (
     <form className={classes.root} autoComplete="off">
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-input">Age</InputLabel>
-        <BootstrapInput id="age-customized-input" />
+        <InputLabel htmlFor="demo-customized-textbox">Age</InputLabel>
+        <BootstrapInput id="demo-customized-textbox" />
       </FormControl>
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-select">Age</InputLabel>
+        <InputLabel id="demo-customized-select-label">Age</InputLabel>
         <Select
+          labelId="demo-customized-select-label"
+          id="demo-customized-select"
           value={age}
           onChange={handleChange}
-          input={<BootstrapInput name="age" id="age-customized-select" />}
+          input={<BootstrapInput />}
         >
           <MenuItem value="">
             <em>None</em>
@@ -80,11 +82,12 @@ export default function CustomizedSelects() {
         </Select>
       </FormControl>
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-native-simple">Age</InputLabel>
+        <InputLabel htmlFor="demo-customized-select-native">Age</InputLabel>
         <NativeSelect
+          id="demo-customized-select-native"
           value={age}
           onChange={handleChange}
-          input={<BootstrapInput name="age" id="age-customized-native-simple" />}
+          input={<BootstrapInput />}
         >
           <option value="" />
           <option value={10}>Ten</option>
diff --git a/docs/src/pages/components/selects/CustomizedSelects.tsx b/docs/src/pages/components/selects/CustomizedSelects.tsx
--- a/docs/src/pages/components/selects/CustomizedSelects.tsx
+++ b/docs/src/pages/components/selects/CustomizedSelects.tsx
@@ -65,15 +65,17 @@ export default function CustomizedSelects() {
   return (
     <form className={classes.root} autoComplete="off">
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-input">Age</InputLabel>
-        <BootstrapInput id="age-customized-input" />
+        <InputLabel htmlFor="demo-customized-textbox">Age</InputLabel>
+        <BootstrapInput id="demo-customized-textbox" />
       </FormControl>
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-select">Age</InputLabel>
+        <InputLabel id="demo-customized-select-label">Age</InputLabel>
         <Select
+          labelId="demo-customized-select-label"
+          id="demo-customized-select"
           value={age}
           onChange={handleChange}
-          input={<BootstrapInput name="age" id="age-customized-select" />}
+          input={<BootstrapInput />}
         >
           <MenuItem value="">
             <em>None</em>
@@ -84,11 +86,12 @@ export default function CustomizedSelects() {
         </Select>
       </FormControl>
       <FormControl className={classes.margin}>
-        <InputLabel htmlFor="age-customized-native-simple">Age</InputLabel>
+        <InputLabel htmlFor="demo-customized-select-native">Age</InputLabel>
         <NativeSelect
+          id="demo-customized-select-native"
           value={age}
           onChange={handleChange}
-          input={<BootstrapInput name="age" id="age-customized-native-simple" />}
+          input={<BootstrapInput />}
         >
           <option value="" />
           <option value={10}>Ten</option>
diff --git a/docs/src/pages/components/selects/DialogSelect.js b/docs/src/pages/components/selects/DialogSelect.js
--- a/docs/src/pages/components/selects/DialogSelect.js
+++ b/docs/src/pages/components/selects/DialogSelect.js
@@ -24,37 +24,35 @@ const useStyles = makeStyles(theme => ({
 
 export default function DialogSelect() {
   const classes = useStyles();
-  const [state, setState] = React.useState({
-    open: false,
-    age: '',
-  });
+  const [open, setOpen] = React.useState(false);
+  const [age, setAge] = React.useState('');
 
-  const handleChange = name => event => {
-    setState({ ...state, [name]: Number(event.target.value) || '' });
+  const handleChange = event => {
+    setAge(Number(event.target.value) || '');
   };
 
   const handleClickOpen = () => {
-    setState({ ...state, open: true });
+    setOpen(true);
   };
 
   const handleClose = () => {
-    setState({ ...state, open: false });
+    setOpen(false);
   };
 
   return (
     <div>
       <Button onClick={handleClickOpen}>Open select dialog</Button>
-      <Dialog disableBackdropClick disableEscapeKeyDown open={state.open} onClose={handleClose}>
+      <Dialog disableBackdropClick disableEscapeKeyDown open={open} onClose={handleClose}>
         <DialogTitle>Fill the form</DialogTitle>
         <DialogContent>
           <form className={classes.container}>
             <FormControl className={classes.formControl}>
-              <InputLabel htmlFor="age-native-simple">Age</InputLabel>
+              <InputLabel htmlFor="demo-dialog-native">Age</InputLabel>
               <Select
                 native
-                value={state.age}
-                onChange={handleChange('age')}
-                input={<Input id="age-native-simple" />}
+                value={age}
+                onChange={handleChange}
+                input={<Input id="demo-dialog-native" />}
               >
                 <option value="" />
                 <option value={10}>Ten</option>
@@ -63,11 +61,13 @@ export default function DialogSelect() {
               </Select>
             </FormControl>
             <FormControl className={classes.formControl}>
-              <InputLabel htmlFor="age-simple">Age</InputLabel>
+              <InputLabel id="demo-dialog-select-label">Age</InputLabel>
               <Select
-                value={state.age}
-                onChange={handleChange('age')}
-                input={<Input id="age-simple" />}
+                labelId="demo-dialog-select-label"
+                id="demo-dialog-select"
+                value={age}
+                onChange={handleChange}
+                input={<Input />}
               >
                 <MenuItem value="">
                   <em>None</em>
diff --git a/docs/src/pages/components/selects/DialogSelect.tsx b/docs/src/pages/components/selects/DialogSelect.tsx
--- a/docs/src/pages/components/selects/DialogSelect.tsx
+++ b/docs/src/pages/components/selects/DialogSelect.tsx
@@ -26,39 +26,35 @@ const useStyles = makeStyles((theme: Theme) =>
 
 export default function DialogSelect() {
   const classes = useStyles();
-  const [state, setState] = React.useState({
-    open: false,
-    age: '',
-  });
+  const [open, setOpen] = React.useState(false);
+  const [age, setAge] = React.useState<number | string>('');
 
-  const handleChange = (name: keyof typeof state) => (
-    event: React.ChangeEvent<{ value: unknown }>,
-  ) => {
-    setState({ ...state, [name]: Number(event.target.value) || '' });
+  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
+    setAge(Number(event.target.value) || '');
   };
 
   const handleClickOpen = () => {
-    setState({ ...state, open: true });
+    setOpen(true);
   };
 
   const handleClose = () => {
-    setState({ ...state, open: false });
+    setOpen(false);
   };
 
   return (
     <div>
       <Button onClick={handleClickOpen}>Open select dialog</Button>
-      <Dialog disableBackdropClick disableEscapeKeyDown open={state.open} onClose={handleClose}>
+      <Dialog disableBackdropClick disableEscapeKeyDown open={open} onClose={handleClose}>
         <DialogTitle>Fill the form</DialogTitle>
         <DialogContent>
           <form className={classes.container}>
             <FormControl className={classes.formControl}>
-              <InputLabel htmlFor="age-native-simple">Age</InputLabel>
+              <InputLabel htmlFor="demo-dialog-native">Age</InputLabel>
               <Select
                 native
-                value={state.age}
-                onChange={handleChange('age')}
-                input={<Input id="age-native-simple" />}
+                value={age}
+                onChange={handleChange}
+                input={<Input id="demo-dialog-native" />}
               >
                 <option value="" />
                 <option value={10}>Ten</option>
@@ -67,11 +63,13 @@ export default function DialogSelect() {
               </Select>
             </FormControl>
             <FormControl className={classes.formControl}>
-              <InputLabel htmlFor="age-simple">Age</InputLabel>
+              <InputLabel id="demo-dialog-select-label">Age</InputLabel>
               <Select
-                value={state.age}
-                onChange={handleChange('age')}
-                input={<Input id="age-simple" />}
+                labelId="demo-dialog-select-label"
+                id="demo-dialog-select"
+                value={age}
+                onChange={handleChange}
+                input={<Input />}
               >
                 <MenuItem value="">
                   <em>None</em>
diff --git a/docs/src/pages/components/selects/MultipleSelect.js b/docs/src/pages/components/selects/MultipleSelect.js
--- a/docs/src/pages/components/selects/MultipleSelect.js
+++ b/docs/src/pages/components/selects/MultipleSelect.js
@@ -88,12 +88,14 @@ export default function MultipleSelect() {
   return (
     <div className={classes.root}>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple">Name</InputLabel>
+        <InputLabel id="demo-mutiple-name-label">Name</InputLabel>
         <Select
+          labelId="demo-mutiple-name-label"
+          id="demo-mutiple-name"
           multiple
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple" />}
+          input={<Input />}
           MenuProps={MenuProps}
         >
           {names.map(name => (
@@ -104,12 +106,14 @@ export default function MultipleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple-checkbox">Tag</InputLabel>
+        <InputLabel id="demo-mutiple-checkbox-label">Tag</InputLabel>
         <Select
+          labelId="demo-mutiple-checkbox-label"
+          id="demo-mutiple-checkbox"
           multiple
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple-checkbox" />}
+          input={<Input />}
           renderValue={selected => selected.join(', ')}
           MenuProps={MenuProps}
         >
@@ -122,8 +126,10 @@ export default function MultipleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple-chip">Chip</InputLabel>
+        <InputLabel id="demo-mutiple-chip-label">Chip</InputLabel>
         <Select
+          labelId="demo-mutiple-chip-label"
+          id="demo-mutiple-chip"
           multiple
           value={personName}
           onChange={handleChange}
@@ -150,7 +156,7 @@ export default function MultipleSelect() {
           displayEmpty
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple-placeholder" />}
+          input={<Input />}
           renderValue={selected => {
             if (selected.length === 0) {
               return <em>Placeholder</em>;
diff --git a/docs/src/pages/components/selects/MultipleSelect.tsx b/docs/src/pages/components/selects/MultipleSelect.tsx
--- a/docs/src/pages/components/selects/MultipleSelect.tsx
+++ b/docs/src/pages/components/selects/MultipleSelect.tsx
@@ -90,12 +90,14 @@ export default function MultipleSelect() {
   return (
     <div className={classes.root}>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple">Name</InputLabel>
+        <InputLabel id="demo-mutiple-name-label">Name</InputLabel>
         <Select
+          labelId="demo-mutiple-name-label"
+          id="demo-mutiple-name"
           multiple
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple" />}
+          input={<Input />}
           MenuProps={MenuProps}
         >
           {names.map(name => (
@@ -106,12 +108,14 @@ export default function MultipleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple-checkbox">Tag</InputLabel>
+        <InputLabel id="demo-mutiple-checkbox-label">Tag</InputLabel>
         <Select
+          labelId="demo-mutiple-checkbox-label"
+          id="demo-mutiple-checkbox"
           multiple
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple-checkbox" />}
+          input={<Input />}
           renderValue={selected => (selected as string[]).join(', ')}
           MenuProps={MenuProps}
         >
@@ -124,8 +128,10 @@ export default function MultipleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="select-multiple-chip">Chip</InputLabel>
+        <InputLabel id="demo-mutiple-chip-label">Chip</InputLabel>
         <Select
+          labelId="demo-mutiple-chip-label"
+          id="demo-mutiple-chip"
           multiple
           value={personName}
           onChange={handleChange}
@@ -152,7 +158,7 @@ export default function MultipleSelect() {
           displayEmpty
           value={personName}
           onChange={handleChange}
-          input={<Input id="select-multiple-placeholder" />}
+          input={<Input />}
           renderValue={selected => {
             if ((selected as string[]).length === 0) {
               return <em>Placeholder</em>;
diff --git a/docs/src/pages/components/selects/SimpleSelect.js b/docs/src/pages/components/selects/SimpleSelect.js
--- a/docs/src/pages/components/selects/SimpleSelect.js
+++ b/docs/src/pages/components/selects/SimpleSelect.js
@@ -22,10 +22,7 @@ const useStyles = makeStyles(theme => ({
 
 export default function SimpleSelect() {
   const classes = useStyles();
-  const [values, setValues] = React.useState({
-    age: '',
-    name: 'hai',
-  });
+  const [age, setAge] = React.useState('');
 
   const inputLabel = React.useRef(null);
   const [labelWidth, setLabelWidth] = React.useState(0);
@@ -34,23 +31,18 @@ export default function SimpleSelect() {
   }, []);
 
   const handleChange = event => {
-    setValues(oldValues => ({
-      ...oldValues,
-      [event.target.name]: event.target.value,
-    }));
+    setAge(event.target.value);
   };
 
   return (
     <form className={classes.root} autoComplete="off">
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-simple">Age</InputLabel>
+        <InputLabel id="demo-simple-select-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-label"
+          id="demo-simple-select"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-simple',
-          }}
         >
           <MenuItem value={10}>Ten</MenuItem>
           <MenuItem value={20}>Twenty</MenuItem>
@@ -58,14 +50,12 @@ export default function SimpleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-helper">Age</InputLabel>
+        <InputLabel id="demo-simple-select-helper-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-helper-label"
+          id="demo-simple-select-helper"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-helper',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
@@ -77,13 +67,7 @@ export default function SimpleSelect() {
         <FormHelperText>Some important helper text</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <Select
-          value={values.age}
-          onChange={handleChange}
-          displayEmpty
-          name="age"
-          className={classes.selectEmpty}
-        >
+        <Select value={age} onChange={handleChange} displayEmpty className={classes.selectEmpty}>
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
@@ -94,18 +78,15 @@ export default function SimpleSelect() {
         <FormHelperText>Without label</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel shrink htmlFor="age-label-placeholder">
+        <InputLabel shrink id="demo-simple-select-placeholder-label-label">
           Age
         </InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-placeholder-label-label"
+          id="demo-simple-select-placeholder-label"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-label-placeholder',
-          }}
           displayEmpty
-          name="age"
           className={classes.selectEmpty}
         >
           <MenuItem value="">
@@ -118,73 +99,65 @@ export default function SimpleSelect() {
         <FormHelperText>Label + placeholder</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl} disabled>
-        <InputLabel htmlFor="name-disabled">Name</InputLabel>
+        <InputLabel id="demo-simple-select-disabled-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-disabled-label"
+          id="demo-simple-select-disabled"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'name',
-            id: 'name-disabled',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Disabled</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl} error>
-        <InputLabel htmlFor="name-error">Name</InputLabel>
+        <InputLabel id="demo-simple-select-error-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-error-label"
+          id="demo-simple-select-error"
+          value={age}
           onChange={handleChange}
-          name="name"
           renderValue={value => `⚠️  - ${value}`}
-          inputProps={{
-            id: 'name-error',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Error</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="name-readonly">Name</InputLabel>
+        <InputLabel id="demo-simple-select-readonly-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-readonly-label"
+          id="demo-simple-select-readonly"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'name',
-            id: 'name-readonly',
-            readOnly: true,
-          }}
+          inputProps={{ readOnly: true }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Read only</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-auto-width">Age</InputLabel>
+        <InputLabel id="demo-simple-select-autowidth-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-autowidth-label"
+          id="demo-simple-select-autowidth"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-auto-width',
-          }}
           autoWidth
         >
           <MenuItem value="">
@@ -197,13 +170,7 @@ export default function SimpleSelect() {
         <FormHelperText>Auto width</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <Select
-          value={values.age}
-          onChange={handleChange}
-          name="age"
-          displayEmpty
-          className={classes.selectEmpty}
-        >
+        <Select value={age} onChange={handleChange} displayEmpty className={classes.selectEmpty}>
           <MenuItem value="" disabled>
             Placeholder
           </MenuItem>
@@ -214,14 +181,12 @@ export default function SimpleSelect() {
         <FormHelperText>Placeholder</FormHelperText>
       </FormControl>
       <FormControl required className={classes.formControl}>
-        <InputLabel htmlFor="age-required">Age</InputLabel>
+        <InputLabel id="demo-simple-select-required-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-required-label"
+          id="demo-simple-select-required"
+          value={age}
           onChange={handleChange}
-          name="age"
-          inputProps={{
-            id: 'age-required',
-          }}
           className={classes.selectEmpty}
         >
           <MenuItem value="">
@@ -234,17 +199,15 @@ export default function SimpleSelect() {
         <FormHelperText>Required</FormHelperText>
       </FormControl>
       <FormControl variant="outlined" className={classes.formControl}>
-        <InputLabel ref={inputLabel} htmlFor="outlined-age-simple">
+        <InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
           Age
         </InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-outlined-label"
+          id="demo-simple-select-outlined"
+          value={age}
           onChange={handleChange}
           labelWidth={labelWidth}
-          inputProps={{
-            name: 'age',
-            id: 'outlined-age-simple',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
@@ -255,14 +218,12 @@ export default function SimpleSelect() {
         </Select>
       </FormControl>
       <FormControl variant="filled" className={classes.formControl}>
-        <InputLabel htmlFor="filled-age-simple">Age</InputLabel>
+        <InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-filled-label"
+          id="demo-simple-select-filled"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'filled-age-simple',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
diff --git a/docs/src/pages/components/selects/SimpleSelect.tsx b/docs/src/pages/components/selects/SimpleSelect.tsx
--- a/docs/src/pages/components/selects/SimpleSelect.tsx
+++ b/docs/src/pages/components/selects/SimpleSelect.tsx
@@ -24,10 +24,7 @@ const useStyles = makeStyles((theme: Theme) =>
 
 export default function SimpleSelect() {
   const classes = useStyles();
-  const [values, setValues] = React.useState({
-    age: '',
-    name: 'hai',
-  });
+  const [age, setAge] = React.useState('');
 
   const inputLabel = React.useRef<HTMLLabelElement>(null);
   const [labelWidth, setLabelWidth] = React.useState(0);
@@ -35,24 +32,19 @@ export default function SimpleSelect() {
     setLabelWidth(inputLabel.current!.offsetWidth);
   }, []);
 
-  const handleChange = (event: React.ChangeEvent<{ name?: string; value: unknown }>) => {
-    setValues(oldValues => ({
-      ...oldValues,
-      [event.target.name as string]: event.target.value,
-    }));
+  const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
+    setAge(event.target.value as string);
   };
 
   return (
     <form className={classes.root} autoComplete="off">
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-simple">Age</InputLabel>
+        <InputLabel id="demo-simple-select-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-label"
+          id="demo-simple-select"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-simple',
-          }}
         >
           <MenuItem value={10}>Ten</MenuItem>
           <MenuItem value={20}>Twenty</MenuItem>
@@ -60,14 +52,12 @@ export default function SimpleSelect() {
         </Select>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-helper">Age</InputLabel>
+        <InputLabel id="demo-simple-select-helper-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-helper-label"
+          id="demo-simple-select-helper"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-helper',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
@@ -79,13 +69,7 @@ export default function SimpleSelect() {
         <FormHelperText>Some important helper text</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <Select
-          value={values.age}
-          onChange={handleChange}
-          displayEmpty
-          name="age"
-          className={classes.selectEmpty}
-        >
+        <Select value={age} onChange={handleChange} displayEmpty className={classes.selectEmpty}>
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
@@ -96,18 +80,15 @@ export default function SimpleSelect() {
         <FormHelperText>Without label</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel shrink htmlFor="age-label-placeholder">
+        <InputLabel shrink id="demo-simple-select-placeholder-label-label">
           Age
         </InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-placeholder-label-label"
+          id="demo-simple-select-placeholder-label"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-label-placeholder',
-          }}
           displayEmpty
-          name="age"
           className={classes.selectEmpty}
         >
           <MenuItem value="">
@@ -120,73 +101,65 @@ export default function SimpleSelect() {
         <FormHelperText>Label + placeholder</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl} disabled>
-        <InputLabel htmlFor="name-disabled">Name</InputLabel>
+        <InputLabel id="demo-simple-select-disabled-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-disabled-label"
+          id="demo-simple-select-disabled"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'name',
-            id: 'name-disabled',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Disabled</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl} error>
-        <InputLabel htmlFor="name-error">Name</InputLabel>
+        <InputLabel id="demo-simple-select-error-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-error-label"
+          id="demo-simple-select-error"
+          value={age}
           onChange={handleChange}
-          name="name"
           renderValue={value => `⚠️  - ${value}`}
-          inputProps={{
-            id: 'name-error',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Error</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="name-readonly">Name</InputLabel>
+        <InputLabel id="demo-simple-select-readonly-label">Name</InputLabel>
         <Select
-          value={values.name}
+          labelId="demo-simple-select-readonly-label"
+          id="demo-simple-select-readonly"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'name',
-            id: 'name-readonly',
-            readOnly: true,
-          }}
+          inputProps={{ readOnly: true }}
         >
           <MenuItem value="">
             <em>None</em>
           </MenuItem>
-          <MenuItem value="hai">Hai</MenuItem>
-          <MenuItem value="olivier">Olivier</MenuItem>
-          <MenuItem value="kevin">Kevin</MenuItem>
+          <MenuItem value={10}>Ten</MenuItem>
+          <MenuItem value={20}>Twenty</MenuItem>
+          <MenuItem value={30}>Thirty</MenuItem>
         </Select>
         <FormHelperText>Read only</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <InputLabel htmlFor="age-auto-width">Age</InputLabel>
+        <InputLabel id="demo-simple-select-autowidth-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-autowidth-label"
+          id="demo-simple-select-autowidth"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'age-auto-width',
-          }}
           autoWidth
         >
           <MenuItem value="">
@@ -199,13 +172,7 @@ export default function SimpleSelect() {
         <FormHelperText>Auto width</FormHelperText>
       </FormControl>
       <FormControl className={classes.formControl}>
-        <Select
-          value={values.age}
-          onChange={handleChange}
-          name="age"
-          displayEmpty
-          className={classes.selectEmpty}
-        >
+        <Select value={age} onChange={handleChange} displayEmpty className={classes.selectEmpty}>
           <MenuItem value="" disabled>
             Placeholder
           </MenuItem>
@@ -216,14 +183,12 @@ export default function SimpleSelect() {
         <FormHelperText>Placeholder</FormHelperText>
       </FormControl>
       <FormControl required className={classes.formControl}>
-        <InputLabel htmlFor="age-required">Age</InputLabel>
+        <InputLabel id="demo-simple-select-required-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-required-label"
+          id="demo-simple-select-required"
+          value={age}
           onChange={handleChange}
-          name="age"
-          inputProps={{
-            id: 'age-required',
-          }}
           className={classes.selectEmpty}
         >
           <MenuItem value="">
@@ -236,17 +201,15 @@ export default function SimpleSelect() {
         <FormHelperText>Required</FormHelperText>
       </FormControl>
       <FormControl variant="outlined" className={classes.formControl}>
-        <InputLabel ref={inputLabel} htmlFor="outlined-age-simple">
+        <InputLabel ref={inputLabel} id="demo-simple-select-outlined-label">
           Age
         </InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-outlined-label"
+          id="demo-simple-select-outlined"
+          value={age}
           onChange={handleChange}
           labelWidth={labelWidth}
-          inputProps={{
-            name: 'age',
-            id: 'outlined-age-simple',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
@@ -257,14 +220,12 @@ export default function SimpleSelect() {
         </Select>
       </FormControl>
       <FormControl variant="filled" className={classes.formControl}>
-        <InputLabel htmlFor="filled-age-simple">Age</InputLabel>
+        <InputLabel id="demo-simple-select-filled-label">Age</InputLabel>
         <Select
-          value={values.age}
+          labelId="demo-simple-select-filled-label"
+          id="demo-simple-select-filled"
+          value={age}
           onChange={handleChange}
-          inputProps={{
-            name: 'age',
-            id: 'filled-age-simple',
-          }}
         >
           <MenuItem value="">
             <em>None</em>
diff --git a/docs/src/pages/components/selects/selects.md b/docs/src/pages/components/selects/selects.md
--- a/docs/src/pages/components/selects/selects.md
+++ b/docs/src/pages/components/selects/selects.md
@@ -52,3 +52,26 @@ While it's discouraged by the Material Design specification, you can use a selec
 ## Text Fields
 
 The `TextField` wrapper component is a complete form control including a label, input and help text. You can find an example with the select mode [in this section](/components/text-fields/#textfield).
+
+## Accessibility
+
+To properly label your `Select` input you need an extra element with an `id` that contains a label.
+That `id` needs to match the `labelId` of the `Select` e.g.
+
+```jsx
+<InputLabel id="label">Age</InputLabel>
+<Select labelId="label" id="select" value="20">
+  <MenuItem value="10">Twenty</MenuItem>
+  <MenuItem value="20">Twenty</MenuItem>
+</Select>
+```
+
+Alternatively a `TextField` with an `id` and `label` creates the proper markup and
+ids for you:
+
+```jsx
+<TextField id="select" label="Age" value="20">
+  <MenuItem value="10">Twenty</MenuItem>
+  <MenuItem value="20">Twenty</MenuItem>
+</TextField>
+```
diff --git a/packages/material-ui/src/Select/Select.d.ts b/packages/material-ui/src/Select/Select.d.ts
--- a/packages/material-ui/src/Select/Select.d.ts
+++ b/packages/material-ui/src/Select/Select.d.ts
@@ -11,6 +11,7 @@ export interface SelectProps
   displayEmpty?: boolean;
   IconComponent?: React.ElementType;
   input?: React.ReactNode;
+  labelId?: string;
   labelWidth?: number;
   MenuProps?: Partial<MenuProps>;
   multiple?: boolean;
diff --git a/packages/material-ui/src/Select/Select.js b/packages/material-ui/src/Select/Select.js
--- a/packages/material-ui/src/Select/Select.js
+++ b/packages/material-ui/src/Select/Select.js
@@ -21,8 +21,10 @@ const Select = React.forwardRef(function Select(props, ref) {
     classes,
     displayEmpty = false,
     IconComponent = ArrowDropDownIcon,
+    id,
     input,
     inputProps,
+    labelId,
     MenuProps,
     multiple = false,
     native = false,
@@ -71,12 +73,13 @@ const Select = React.forwardRef(function Select(props, ref) {
         : {
             autoWidth,
             displayEmpty,
+            labelId,
             MenuProps,
             onClose,
             onOpen,
             open,
             renderValue,
-            SelectDisplayProps,
+            SelectDisplayProps: { id, ...SelectDisplayProps },
           }),
       ...inputProps,
       classes: inputProps
@@ -122,6 +125,10 @@ Select.propTypes = {
    * The icon that displays the arrow.
    */
   IconComponent: PropTypes.elementType,
+  /**
+   * @ignore
+   */
+  id: PropTypes.string,
   /**
    * An `Input` element; does not have to be a material-ui specific `Input`.
    */
@@ -131,6 +138,11 @@ Select.propTypes = {
    * When `native` is `true`, the attributes are applied on the `select` element.
    */
   inputProps: PropTypes.object,
+  /**
+   * The idea of an element that acts as an additional label. The Select will
+   * be labelled by the additional label and the selected value.
+   */
+  labelId: PropTypes.string,
   /**
    * The label width to be used on OutlinedInput.
    * This prop is required when the `variant` prop is `outlined`.
diff --git a/packages/material-ui/src/Select/SelectInput.js b/packages/material-ui/src/Select/SelectInput.js
--- a/packages/material-ui/src/Select/SelectInput.js
+++ b/packages/material-ui/src/Select/SelectInput.js
@@ -31,6 +31,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
     className,
     disabled,
     displayEmpty,
+    labelId,
     IconComponent,
     inputRef: inputRefProp,
     MenuProps = {},
@@ -45,7 +46,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
     readOnly,
     renderValue,
     required,
-    SelectDisplayProps,
+    SelectDisplayProps = {},
     tabIndex: tabIndexProp,
     // catching `type` from Input which makes no sense for SelectInput
     type,
@@ -264,6 +265,8 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
     tabIndex = disabled ? null : 0;
   }
 
+  const buttonId = SelectDisplayProps.id || (name ? `mui-component-select-${name}` : undefined);
+
   return (
     <React.Fragment>
       <div
@@ -282,15 +285,15 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
         tabIndex={tabIndex}
         role="button"
         aria-expanded={open ? 'true' : undefined}
+        aria-labelledby={`${labelId || ''} ${buttonId || ''}`}
         aria-haspopup="listbox"
-        aria-owns={open ? `menu-${name || ''}` : undefined}
         onKeyDown={handleKeyDown}
         onClick={disabled || readOnly ? null : handleClick}
         onBlur={handleBlur}
         onFocus={onFocus}
-        // The id can help with end-to-end testing automation.
-        id={name ? `select-${name}` : undefined}
         {...SelectDisplayProps}
+        // The id is required for proper a11y
+        id={buttonId}
       >
         {/* So the vertical align positioning algorithm kicks in. */}
         {isEmpty(display) ? (
@@ -316,6 +319,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
         onClose={handleClose}
         {...MenuProps}
         MenuListProps={{
+          'aria-labelledby': labelId,
           role: 'listbox',
           disableListWrap: true,
           ...MenuProps.MenuListProps,
@@ -375,6 +379,11 @@ SelectInput.propTypes = {
    * Equivalent to `ref`
    */
   inputRef: refType,
+  /**
+   * The idea of an element that acts as an additional label. The Select will
+   * be labelled by the additional label and the selected value.
+   */
+  labelId: PropTypes.string,
   /**
    * Props applied to the [`Menu`](/api/menu/) element.
    */
diff --git a/packages/material-ui/src/TextField/TextField.js b/packages/material-ui/src/TextField/TextField.js
--- a/packages/material-ui/src/TextField/TextField.js
+++ b/packages/material-ui/src/TextField/TextField.js
@@ -118,8 +118,14 @@ const TextField = React.forwardRef(function TextField(props, ref) {
 
     InputMore.labelWidth = labelWidth;
   }
+  if (select) {
+    // unset defaults from textbox inputs
+    InputMore.id = undefined;
+    InputMore['aria-describedby'] = undefined;
+  }
 
   const helperTextId = helperText && id ? `${id}-helper-text` : undefined;
+  const inputLabelId = label && id ? `${id}-label` : undefined;
   const InputComponent = variantComponent[variant];
   const InputElement = (
     <InputComponent
@@ -158,12 +164,19 @@ const TextField = React.forwardRef(function TextField(props, ref) {
       {...other}
     >
       {label && (
-        <InputLabel htmlFor={id} ref={labelRef} {...InputLabelProps}>
+        <InputLabel htmlFor={id} ref={labelRef} id={inputLabelId} {...InputLabelProps}>
           {label}
         </InputLabel>
       )}
       {select ? (
-        <Select aria-describedby={helperTextId} value={value} input={InputElement} {...SelectProps}>
+        <Select
+          aria-describedby={helperTextId}
+          id={id}
+          labelId={inputLabelId}
+          value={value}
+          input={InputElement}
+          {...SelectProps}
+        >
           {children}
         </Select>
       ) : (


Test patch:
diff --git a/packages/material-ui/src/Select/Select.test.js b/packages/material-ui/src/Select/Select.test.js
--- a/packages/material-ui/src/Select/Select.test.js
+++ b/packages/material-ui/src/Select/Select.test.js
@@ -402,6 +402,74 @@ describe('<Select />', () => {
 
       expect(getAllByRole('option')[1]).to.have.attribute('aria-selected', 'true');
     });
+
+    it('it will fallback to its content for the accessible name when it has no name', () => {
+      const { getByRole } = render(<Select value="" />);
+
+      expect(getByRole('button')).to.have.attribute('aria-labelledby', ' ');
+    });
+
+    it('is labelled by itself when it has a name', () => {
+      const { getByRole } = render(<Select name="select" value="" />);
+
+      expect(getByRole('button')).to.have.attribute(
+        'aria-labelledby',
+        ` ${getByRole('button').getAttribute('id')}`,
+      );
+    });
+
+    it('is labelled by itself when it has an id which is preferred over name', () => {
+      const { getAllByRole } = render(
+        <React.Fragment>
+          <span id="select-1-label">Chose first option:</span>
+          <Select id="select-1" labelId="select-1-label" name="select" value="" />
+          <span id="select-2-label">Chose second option:</span>
+          <Select id="select-2" labelId="select-2-label" name="select" value="" />
+        </React.Fragment>,
+      );
+
+      const triggers = getAllByRole('button');
+
+      expect(triggers[0]).to.have.attribute(
+        'aria-labelledby',
+        `select-1-label ${triggers[0].getAttribute('id')}`,
+      );
+      expect(triggers[1]).to.have.attribute(
+        'aria-labelledby',
+        `select-2-label ${triggers[1].getAttribute('id')}`,
+      );
+    });
+
+    it('can be labelled by an additional element if its id is provided in `labelId`', () => {
+      const { getByRole } = render(
+        <React.Fragment>
+          <span id="select-label">Choose one:</span>
+          <Select labelId="select-label" name="select" value="" />
+        </React.Fragment>,
+      );
+
+      expect(getByRole('button')).to.have.attribute(
+        'aria-labelledby',
+        `select-label ${getByRole('button').getAttribute('id')}`,
+      );
+    });
+
+    specify('the list of options is not labelled by default', () => {
+      const { getByRole } = render(<Select open value="" />);
+
+      expect(getByRole('listbox')).not.to.have.attribute('aria-labelledby');
+    });
+
+    specify('the list of options can be labelled by providing `labelId`', () => {
+      const { getByRole } = render(
+        <React.Fragment>
+          <span id="select-label">Choose one:</span>
+          <Select labelId="select-label" open value="" />
+        </React.Fragment>,
+      );
+
+      expect(getByRole('listbox')).to.have.attribute('aria-labelledby', 'select-label');
+    });
   });
 
   describe('prop: readOnly', () => {
@@ -784,7 +852,7 @@ describe('<Select />', () => {
     it('should have select-`name` id when name is provided', () => {
       const { getByRole } = render(<Select name="foo" value="" />);
 
-      expect(getByRole('button')).to.have.attribute('id', 'select-foo');
+      expect(getByRole('button')).to.have.attribute('id', 'mui-component-select-foo');
     });
   });
 });
diff --git a/packages/material-ui/src/TextField/TextField.test.js b/packages/material-ui/src/TextField/TextField.test.js
--- a/packages/material-ui/src/TextField/TextField.test.js
+++ b/packages/material-ui/src/TextField/TextField.test.js
@@ -7,6 +7,7 @@ import FormControl from '../FormControl';
 import Input from '../Input';
 import OutlinedInput from '../OutlinedInput';
 import TextField from './TextField';
+import MenuItem from '../MenuItem';
 
 describe('<TextField />', () => {
   let classes;
@@ -134,5 +135,36 @@ describe('<TextField />', () => {
       expect(select).to.be.ok;
       expect(select.querySelectorAll('option')).to.have.lengthOf(2);
     });
+
+    it('renders a combobox with the appropriate accessible name', () => {
+      const { getByRole } = render(
+        <TextField select id="my-select" label="Release: " value="stable">
+          <MenuItem value="alpha">Alpha</MenuItem>
+          <MenuItem value="beta">Beta</MenuItem>
+          <MenuItem value="stable">Stable</MenuItem>
+        </TextField>,
+      );
+
+      const label = getByRole('button')
+        .getAttribute('aria-labelledby')
+        .split(' ')
+        .map(idref => document.getElementById(idref))
+        .reduce((partial, element) => `${partial} ${element.textContent}`, '');
+      // this whitespace is ok since actual AT will only use so called "flat strings"
+      // https://w3c.github.io/accname/#mapping_additional_nd_te
+      expect(label).to.equal(' Release:  Stable');
+    });
+
+    it('creates an input[hidden] that has no accessible properties', () => {
+      const { container } = render(
+        <TextField select id="my-select" label="Release: " value="stable">
+          <MenuItem value="stable">Stable</MenuItem>
+        </TextField>,
+      );
+
+      const input = container.querySelector('input[type="hidden"]');
+      expect(input).not.to.have.attribute('id');
+      expect(input).not.to.have.attribute('aria-describedby');
+    });
   });
 });