diff --git a/client/src/components/Navigation.jsx b/client/src/components/Navigation.jsx
index 4577781..048a2ed 100644
--- a/client/src/components/Navigation.jsx
+++ b/client/src/components/Navigation.jsx
@@ -4,13 +4,13 @@ import {
Switch, Route, Redirect, useLocation,
} from 'react-router-dom';
import { connect, useDispatch } from 'react-redux';
-import { push } from 'connected-react-router';
-// import Backdrop from '@material-ui/core/Backdrop';
-import CircularProgress from '@material-ui/core/CircularProgress';
-import Button from '@material-ui/core/Button';
-import Snackbar from '@material-ui/core/Snackbar';
-import Alert from '@material-ui/lab/Alert';
-import { makeStyles } from '@material-ui/core/styles';
+import history from '../lib/history';
+// import Backdrop from '@mui/material/Backdrop';
+import CircularProgress from '@mui/material/CircularProgress';
+import Button from '@mui/material/Button';
+import Snackbar from '@mui/material/Snackbar';
+import Alert from '@mui/material/Alert';
+import { makeStyles } from '@mui/styles';
import PrivateRoute from './common/PrivateRoute';
import Header from './Header';
import Footer from './Footer';
@@ -215,7 +215,7 @@ function Navigation({
atPendingRoom={atPendingRoom}
error={resultSubmission.error}
onDiscard={() => dispatch(discardPendingResult(pendingResult.submissionId))}
- onReturn={() => dispatch(push(pendingRoomPath))}
+ onReturn={() => history.push(pendingRoomPath)}
pendingResult={pendingResult}
privateRoom={!!room.private}
status={resultSubmission.status}
@@ -274,6 +274,7 @@ Navigation.propTypes = {
_id: PropTypes.string,
accessCode: PropTypes.string,
fetching: PropTypes.bool,
+ private: PropTypes.bool,
type: PropTypes.string,
resultSubmission: PropTypes.shape({
status: PropTypes.oneOf(['idle', 'pending', 'sending', 'failed']),
diff --git a/client/src/components/Navigation.test.jsx b/client/src/components/Navigation.test.jsx
index 984b4f0..78348b1 100644
--- a/client/src/components/Navigation.test.jsx
+++ b/client/src/components/Navigation.test.jsx
@@ -1,7 +1,5 @@
import React from 'react';
-import { shallow } from 'enzyme';
-import Alert from '@material-ui/lab/Alert';
-import Button from '@material-ui/core/Button';
+import { fireEvent, render, screen } from '@testing-library/react';
import {
GlobalPendingResultAlert,
shouldShowGlobalPendingResult,
@@ -39,7 +37,7 @@ describe('global pending result alert', () => {
it('keeps discard accessible when the pending room could not be joined', () => {
const onDiscard = jest.fn();
- const wrapper = shallow(
+ render(
{
userId={42}
/>,
);
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
- expect(wrapper.text()).toContain('Enter the room password below');
- expect(actions.find(Button)).toHaveLength(1);
- expect(actions.find(Button).text()).toBe('Discard saved result');
-
- actions.find(Button).simulate('click');
+ expect(screen.getByText(/Enter the room password below/)).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Discard saved result' })).toBeInTheDocument();
+ fireEvent.click(screen.getByRole('button', { name: 'Discard saved result' }));
expect(onDiscard).toHaveBeenCalledTimes(1);
});
it('offers a return action when the user is somewhere else', () => {
const onReturn = jest.fn();
- const wrapper = shallow(
+ render(
{
userId={42}
/>,
);
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
- expect(actions.find(Button).map((button) => button.text())).toEqual([
- 'Return to room',
- 'Discard saved result',
- ]);
- actions.find(Button).at(0).simulate('click');
+ fireEvent.click(screen.getByRole('button', { name: 'Return to room' }));
expect(onReturn).toHaveBeenCalledTimes(1);
+ expect(screen.getByRole('button', { name: 'Discard saved result' })).toBeInTheDocument();
});
it('does not offer discard after delivery has started', () => {
- const wrapper = shallow(
+ render(
{
userId={42}
/>,
);
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
- expect(actions.find(Button)).toHaveLength(1);
- expect(actions.find(Button).text()).toBe('Return to room');
- expect(wrapper.text()).toContain('finish submitting');
+ expect(screen.getByRole('button', { name: 'Return to room' })).toBeInTheDocument();
+ expect(screen.queryByRole('button', { name: 'Discard saved result' })).not.toBeInTheDocument();
+ expect(screen.getByText(/finish submitting/)).toBeInTheDocument();
});
});
diff --git a/client/src/components/Notifications/NotificationList.jsx b/client/src/components/Notifications/NotificationList.jsx
index 5700adf..aa78988 100644
--- a/client/src/components/Notifications/NotificationList.jsx
+++ b/client/src/components/Notifications/NotificationList.jsx
@@ -1,11 +1,11 @@
import React from 'react';
import PropTypes from 'prop-types';
-import Button from '@material-ui/core/Button';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemText from '@material-ui/core/ListItemText';
-import Typography from '@material-ui/core/Typography';
-import { makeStyles } from '@material-ui/core/styles';
+import Button from '@mui/material/Button';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
+import Typography from '@mui/material/Typography';
+import { makeStyles } from '@mui/styles';
import notificationPresentation from './registry';
const useStyles = makeStyles((theme) => ({
diff --git a/client/src/components/Notifications/NotificationPopover.jsx b/client/src/components/Notifications/NotificationPopover.jsx
index 7bd32e7..10af7cb 100644
--- a/client/src/components/Notifications/NotificationPopover.jsx
+++ b/client/src/components/Notifications/NotificationPopover.jsx
@@ -1,17 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
-import { makeStyles } from '@material-ui/core/styles';
-import Avatar from '@material-ui/core/Avatar';
-import Button from '@material-ui/core/Button';
-import Divider from '@material-ui/core/Divider';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemAvatar from '@material-ui/core/ListItemAvatar';
-import ListItemText from '@material-ui/core/ListItemText';
-import Popover from '@material-ui/core/Popover';
-import Typography from '@material-ui/core/Typography';
-import NotificationsNoneIcon from '@material-ui/icons/NotificationsNone';
+import { makeStyles } from '@mui/styles';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import Divider from '@mui/material/Divider';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import ListItemText from '@mui/material/ListItemText';
+import Popover from '@mui/material/Popover';
+import Typography from '@mui/material/Typography';
+import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone';
import notificationPresentation from './registry';
const useStyles = makeStyles((theme) => ({
diff --git a/client/src/components/Notifications/index.jsx b/client/src/components/Notifications/index.jsx
index 69fda0b..ede6833 100644
--- a/client/src/components/Notifications/index.jsx
+++ b/client/src/components/Notifications/index.jsx
@@ -1,11 +1,11 @@
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
-import Button from '@material-ui/core/Button';
-import CircularProgress from '@material-ui/core/CircularProgress';
-import Container from '@material-ui/core/Container';
-import Typography from '@material-ui/core/Typography';
-import { makeStyles } from '@material-ui/core/styles';
+import Button from '@mui/material/Button';
+import CircularProgress from '@mui/material/CircularProgress';
+import Container from '@mui/material/Container';
+import Typography from '@mui/material/Typography';
+import { makeStyles } from '@mui/styles';
import {
fetchNotifications,
markAllNotificationsRead,
diff --git a/client/src/components/PublicProfile.jsx b/client/src/components/PublicProfile.jsx
index 727d2fe..1d6fece 100644
--- a/client/src/components/PublicProfile.jsx
+++ b/client/src/components/PublicProfile.jsx
@@ -2,13 +2,13 @@ import React, {
useCallback, useEffect, useRef, useState,
} from 'react';
import { Link, useParams } from 'react-router-dom';
-import Avatar from '@material-ui/core/Avatar';
-import Button from '@material-ui/core/Button';
-import CircularProgress from '@material-ui/core/CircularProgress';
-import Container from '@material-ui/core/Container';
-import Paper from '@material-ui/core/Paper';
-import Typography from '@material-ui/core/Typography';
-import { makeStyles } from '@material-ui/core/styles';
+import Avatar from '@mui/material/Avatar';
+import Button from '@mui/material/Button';
+import CircularProgress from '@mui/material/CircularProgress';
+import Container from '@mui/material/Container';
+import Paper from '@mui/material/Paper';
+import Typography from '@mui/material/Typography';
+import { makeStyles } from '@mui/styles';
import { lcFetch } from '../lib/fetch';
import { isFeatureEnabled } from '../lib/features';
diff --git a/client/src/components/Room/Common/AdminToolbar.jsx b/client/src/components/Room/Common/AdminToolbar.jsx
index 200d3a5..e0eeda3 100644
--- a/client/src/components/Room/Common/AdminToolbar.jsx
+++ b/client/src/components/Room/Common/AdminToolbar.jsx
@@ -1,15 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect, useDispatch } from 'react-redux';
-import Toolbar from '@material-ui/core/Toolbar';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-import Button from '@material-ui/core/Button';
-import FormGroup from '@material-ui/core/FormGroup';
-import Select from '@material-ui/core/Select';
-import ListSubheader from '@material-ui/core/ListSubheader';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
+import Toolbar from '@mui/material/Toolbar';
+import Menu from '@mui/material/Menu';
+import MenuItem from '@mui/material/MenuItem';
+import Button from '@mui/material/Button';
+import FormGroup from '@mui/material/FormGroup';
+import Select from '@mui/material/Select';
+import ListSubheader from '@mui/material/ListSubheader';
+import MoreVertIcon from '@mui/icons-material/MoreVert';
import { useConfirm } from 'material-ui-confirm';
import {
deleteRoom,
diff --git a/client/src/components/Room/Common/EditDialog.jsx b/client/src/components/Room/Common/EditDialog.jsx
index 86c4bf8..fcc4756 100644
--- a/client/src/components/Room/Common/EditDialog.jsx
+++ b/client/src/components/Room/Common/EditDialog.jsx
@@ -1,13 +1,13 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import DialogContent from '@material-ui/core/DialogContent';
-import TextField from '@material-ui/core/TextField';
-import Button from '@material-ui/core/Button';
-import Checkbox from '@material-ui/core/Checkbox';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogTitle from '@mui/material/DialogTitle';
+import DialogContent from '@mui/material/DialogContent';
+import TextField from '@mui/material/TextField';
+import Button from '@mui/material/Button';
+import Checkbox from '@mui/material/Checkbox';
+import FormControlLabel from '@mui/material/FormControlLabel';
import { formatRawTime, parseTime } from '../../../lib/utils';
function EditDialog({
diff --git a/client/src/components/Room/Common/Login.jsx b/client/src/components/Room/Common/Login.jsx
index abc29d1..a460aa2 100644
--- a/client/src/components/Room/Common/Login.jsx
+++ b/client/src/components/Room/Common/Login.jsx
@@ -1,12 +1,12 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect } from 'react-redux';
-import Paper from '@material-ui/core/Paper';
-import TextField from '@material-ui/core/TextField';
-import Button from '@material-ui/core/Button';
-import IconButton from '@material-ui/core/IconButton';
-import ArrowBackIcon from '@material-ui/icons/ArrowBack';
+import Paper from '@mui/material/Paper';
+import TextField from '@mui/material/TextField';
+import Button from '@mui/material/Button';
+import IconButton from '@mui/material/IconButton';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { Link } from 'react-router-dom';
import {
joinRoom,
diff --git a/client/src/components/Room/Common/Main.jsx b/client/src/components/Room/Common/Main.jsx
index 44fd4bf..50885a7 100644
--- a/client/src/components/Room/Common/Main.jsx
+++ b/client/src/components/Room/Common/Main.jsx
@@ -1,16 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { withStyles } from '@material-ui/core/styles';
+import { withStyles } from '@mui/styles';
import { connect } from 'react-redux';
-import Grid from '@material-ui/core/Grid';
-import Paper from '@material-ui/core/Paper';
-import Divider from '@material-ui/core/Divider';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import ClickAwayListener from '@material-ui/core/ClickAwayListener';
-import Alert from '@material-ui/lab/Alert';
+import Grid from '@mui/material/Grid';
+import Paper from '@mui/material/Paper';
+import Divider from '@mui/material/Divider';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import Alert from '@mui/material/Alert';
import UIfx from 'uifx';
-import { push } from 'connected-react-router';
+import history from '../../../lib/history';
import notificationAsset from '../../../assets/notification.mp3';
import calcStats from '../../../lib/stats';
import {
@@ -34,7 +34,7 @@ import Scramble from '../../common/Scramble';
import ScramblePreview from '../../common/ScramblePreview';
import UserStats from './UserStats';
-const useStyles = withStyles((theme) => ({
+const withComponentStyles = withStyles((theme) => ({
root: {
display: 'flex',
flexGrow: 1,
@@ -185,7 +185,7 @@ export class Main extends React.Component {
@@ -374,4 +374,4 @@ const mapStateToProps = (state) => ({
user: state.user,
});
-export default connect(mapStateToProps)(useStyles(Main));
+export default connect(mapStateToProps)(withComponentStyles(Main));
diff --git a/client/src/components/Room/Common/Main.test.jsx b/client/src/components/Room/Common/Main.test.jsx
index cd61307..cb650fe 100644
--- a/client/src/components/Room/Common/Main.test.jsx
+++ b/client/src/components/Room/Common/Main.test.jsx
@@ -1,7 +1,6 @@
import React from 'react';
-import { shallow } from 'enzyme';
-import Alert from '@material-ui/lab/Alert';
-import Button from '@material-ui/core/Button';
+import Alert from '@mui/material/Alert';
+import Button from '@mui/material/Button';
import Timer from '../../Timer/index';
import ScramblePreview from '../../common/ScramblePreview';
import { Main } from './Main';
@@ -27,6 +26,13 @@ const pendingResult = createPendingResult({
now: () => 1000,
});
+const findElements = (node, type) => {
+ if (!React.isValidElement(node)) return [];
+ const children = React.Children.toArray(node.props.children)
+ .flatMap((child) => findElements(child, type));
+ return node.type === type ? [node, ...children] : children;
+};
+
const makeProps = (overrides = {}) => ({
classes: {
root: 'root',
@@ -60,14 +66,22 @@ const makeProps = (overrides = {}) => ({
...overrides,
});
+const createMain = (props) => {
+ const main = new Main(props);
+ main.setState = (update) => {
+ main.state = { ...main.state, ...update };
+ };
+ return main;
+};
+
describe('room pending result UX', () => {
it('shows scramble previews for non-3x3 events', () => {
const props = makeProps({
room: { ...makeProps().room, event: 'pyram' },
});
- const wrapper = shallow();
+ const previews = findElements(createMain(props).render(), ScramblePreview);
- expect(wrapper.find(ScramblePreview).props()).toMatchObject({
+ expect(previews[0].props).toMatchObject({
event: 'pyram',
scramble: 'R U',
});
@@ -87,18 +101,19 @@ describe('room pending result UX', () => {
},
},
});
- const wrapper = shallow();
- wrapper.instance().handlePriming();
- wrapper.setProps({
+ const main = createMain(props);
+ main.handlePriming();
+ main.props = {
+ ...props,
room: {
...props.room,
attempts: [{
_id: 'replacement-attempt', id: 0, scrambles: ['F R'], results: {},
}],
},
- });
+ };
- wrapper.instance().onSubmitTime({ time: 1234, penalties: {} });
+ main.onSubmitTime({ time: 1234, penalties: {} });
expect(props.dispatch).toHaveBeenCalledWith({
type: SUBMIT_RESULT,
@@ -122,25 +137,25 @@ describe('room pending result UX', () => {
},
},
});
- const wrapper = shallow();
+ const tree = createMain(props).render();
- expect(wrapper.find(Timer).prop('disabled')).toBe(false);
- expect(wrapper.find(Alert)).toHaveLength(0);
+ expect(findElements(tree, Timer)[0].props.disabled).toBe(false);
+ expect(findElements(tree, Alert)).toHaveLength(0);
});
it('blocks another solve and offers return/discard actions outside the original room', () => {
const props = makeProps();
- const wrapper = shallow();
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
+ const alert = findElements(createMain(props).render(), Alert)[0];
+ const buttons = findElements(alert.props.action, Button);
- expect(wrapper.find(Timer).prop('disabled')).toBe(true);
- expect(wrapper.find(Alert).text()).toContain('Your saved time belongs to room original-room.');
- expect(actions.find(Button).map((button) => button.text())).toEqual([
+ expect(findElements(createMain(props).render(), Timer)[0].props.disabled).toBe(true);
+ expect(alert.props.children).toContain('Your saved time belongs to room original-room.');
+ expect(buttons.map((button) => button.props.children)).toEqual([
'Return to room',
'Discard saved result',
]);
- actions.find(Button).at(1).simulate('click');
+ buttons[1].props.onClick();
expect(props.dispatch).toHaveBeenCalledWith({
type: DISCARD_PENDING_RESULT,
submissionId: 'submission-one',
@@ -148,10 +163,7 @@ describe('room pending result UX', () => {
});
it('also blocks a solve when the device outbox belongs to another account', () => {
- const anotherUsersResult = {
- ...pendingResult,
- userId: 99,
- };
+ const anotherUsersResult = { ...pendingResult, userId: 99 };
const props = makeProps({
room: {
...makeProps().room,
@@ -162,13 +174,12 @@ describe('room pending result UX', () => {
},
},
});
- const wrapper = shallow();
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
+ const alert = findElements(createMain(props).render(), Alert)[0];
- expect(wrapper.find(Timer).prop('disabled')).toBe(true);
- expect(wrapper.find(Alert).text()).toContain('another account');
- expect(actions.find(Button)).toHaveLength(1);
- expect(actions.find(Button).text()).toBe('Discard saved result');
+ expect(findElements(createMain(props).render(), Timer)[0].props.disabled).toBe(true);
+ expect(alert.props.children).toContain('another account');
+ expect(findElements(alert.props.action, Button)).toHaveLength(1);
+ expect(findElements(alert.props.action, Button)[0].props.children).toBe('Discard saved result');
});
it('keeps an attempted result without offering discard', () => {
@@ -182,11 +193,11 @@ describe('room pending result UX', () => {
},
},
});
- const wrapper = shallow();
- const actions = shallow({wrapper.find(Alert).prop('action')}
);
+ const alert = findElements(createMain(props).render(), Alert)[0];
+ const buttons = findElements(alert.props.action, Button);
- expect(actions.find(Button)).toHaveLength(1);
- expect(actions.find(Button).text()).toBe('Return to room');
- expect(wrapper.find(Alert).text()).toContain('finish submitting');
+ expect(buttons).toHaveLength(1);
+ expect(buttons[0].props.children).toBe('Return to room');
+ expect(alert.props.children).toContain('finish submitting');
});
});
diff --git a/client/src/components/Room/Common/ManageUsersDialog.jsx b/client/src/components/Room/Common/ManageUsersDialog.jsx
index 0434a32..994ef7b 100644
--- a/client/src/components/Room/Common/ManageUsersDialog.jsx
+++ b/client/src/components/Room/Common/ManageUsersDialog.jsx
@@ -2,20 +2,20 @@ import React from 'react';
import clsx from 'clsx';
import { connect, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Button from '@material-ui/core/Button';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
-import Checkbox from '@material-ui/core/Checkbox';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemText from '@material-ui/core/ListItemText';
-import ListSubheader from '@material-ui/core/ListSubheader';
-import ListItemAvatar from '@material-ui/core/ListItemAvatar';
-import Avatar from '@material-ui/core/Avatar';
+import { makeStyles } from '@mui/styles';
+import Button from '@mui/material/Button';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import Checkbox from '@mui/material/Checkbox';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
+import ListSubheader from '@mui/material/ListSubheader';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import Avatar from '@mui/material/Avatar';
import { kickUser, updateUser, updateBanned } from '../../../store/room/actions';
import {
getUsersInRoom,
diff --git a/client/src/components/Room/Common/Panel.jsx b/client/src/components/Room/Common/Panel.jsx
index 0043d9a..4953262 100644
--- a/client/src/components/Room/Common/Panel.jsx
+++ b/client/src/components/Room/Common/Panel.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import Paper from '@material-ui/core/Paper';
-import Toolbar from '@material-ui/core/Toolbar';
-import Divider from '@material-ui/core/Divider';
-import { makeStyles } from '@material-ui/core/styles';
+import Paper from '@mui/material/Paper';
+import Toolbar from '@mui/material/Toolbar';
+import Divider from '@mui/material/Divider';
+import { makeStyles } from '@mui/styles';
const useStyles = makeStyles(() => ({
root: {
diff --git a/client/src/components/Room/Common/StatsDialog.jsx b/client/src/components/Room/Common/StatsDialog.jsx
index 7ec72cc..204f4cb 100644
--- a/client/src/components/Room/Common/StatsDialog.jsx
+++ b/client/src/components/Room/Common/StatsDialog.jsx
@@ -1,13 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Button from '@material-ui/core/Button';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import Typography from '@material-ui/core/Typography';
-import Paper from '@material-ui/core/Paper';
+import { makeStyles } from '@mui/styles';
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+import Typography from '@mui/material/Typography';
+import Paper from '@mui/material/Paper';
import { formatTime } from '../../../lib/utils';
const useStyles = makeStyles(() => ({
diff --git a/client/src/components/Room/Common/TableStatusCell.jsx b/client/src/components/Room/Common/TableStatusCell.jsx
index 23bf4f4..c26c85f 100644
--- a/client/src/components/Room/Common/TableStatusCell.jsx
+++ b/client/src/components/Room/Common/TableStatusCell.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Typography from '@material-ui/core/Typography';
-import TableCell from '@material-ui/core/TableCell';
+import { makeStyles } from '@mui/styles';
+import Typography from '@mui/material/Typography';
+import TableCell from '@mui/material/TableCell';
const useStyles = makeStyles(() => ({
root: {
diff --git a/client/src/components/Room/Common/TableTimeCell.jsx b/client/src/components/Room/Common/TableTimeCell.jsx
index 03939f3..f9cdabb 100644
--- a/client/src/components/Room/Common/TableTimeCell.jsx
+++ b/client/src/components/Room/Common/TableTimeCell.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Button from '@material-ui/core/Button';
-import Typography from '@material-ui/core/Typography';
-import TableCell from '@material-ui/core/TableCell';
+import { makeStyles } from '@mui/styles';
+import Button from '@mui/material/Button';
+import Typography from '@mui/material/Typography';
+import TableCell from '@mui/material/TableCell';
import { formatTime } from '../../../lib/utils';
import { useEditDialog } from './EditDialogProvider';
diff --git a/client/src/components/Room/Common/TimesTable.jsx b/client/src/components/Room/Common/TimesTable.jsx
index 54d8cd2..e6e1451 100644
--- a/client/src/components/Room/Common/TimesTable.jsx
+++ b/client/src/components/Room/Common/TimesTable.jsx
@@ -1,14 +1,14 @@
import React, { createRef } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Typography from '@material-ui/core/Typography';
-import TableContainer from '@material-ui/core/TableContainer';
-import Table from '@material-ui/core/Table';
-import TableHead from '@material-ui/core/TableHead';
-import TableBody from '@material-ui/core/TableBody';
-import TableRow from '@material-ui/core/TableRow';
-import TableCell from '@material-ui/core/TableCell';
+import { makeStyles } from '@mui/styles';
+import Typography from '@mui/material/Typography';
+import TableContainer from '@mui/material/TableContainer';
+import Table from '@mui/material/Table';
+import TableHead from '@mui/material/TableHead';
+import TableBody from '@mui/material/TableBody';
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
import { useStatsDialog } from './StatsDialogProvider';
import TableCellButton from '../../common/TableCellButton';
import TableStatusCell from './TableStatusCell';
diff --git a/client/src/components/Room/Common/UserSelectorDialog.jsx b/client/src/components/Room/Common/UserSelectorDialog.jsx
index 4d15637..22eb97e 100644
--- a/client/src/components/Room/Common/UserSelectorDialog.jsx
+++ b/client/src/components/Room/Common/UserSelectorDialog.jsx
@@ -1,18 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Button from '@material-ui/core/Button';
-import Checkbox from '@material-ui/core/Checkbox';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemText from '@material-ui/core/ListItemText';
-import ListItemAvatar from '@material-ui/core/ListItemAvatar';
-import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
-import Avatar from '@material-ui/core/Avatar';
+import { makeStyles } from '@mui/styles';
+import Button from '@mui/material/Button';
+import Checkbox from '@mui/material/Checkbox';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
+import Avatar from '@mui/material/Avatar';
const useStyles = makeStyles(() => ({}));
diff --git a/client/src/components/Room/Common/UserStats.jsx b/client/src/components/Room/Common/UserStats.jsx
index 08e0c13..4d3379a 100644
--- a/client/src/components/Room/Common/UserStats.jsx
+++ b/client/src/components/Room/Common/UserStats.jsx
@@ -1,12 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Paper from '@material-ui/core/Paper';
-import Table from '@material-ui/core/Table';
-import TableHead from '@material-ui/core/TableHead';
-import TableBody from '@material-ui/core/TableBody';
-import TableRow from '@material-ui/core/TableRow';
-import TableCell from '@material-ui/core/TableCell';
+import { makeStyles } from '@mui/styles';
+import Paper from '@mui/material/Paper';
+import Table from '@mui/material/Table';
+import TableHead from '@mui/material/TableHead';
+import TableBody from '@mui/material/TableBody';
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
import { formatTime } from '../../../lib/utils';
const useStyles = makeStyles((theme) => ({
diff --git a/client/src/components/Room/Common/UserToolbar.jsx b/client/src/components/Room/Common/UserToolbar.jsx
index 1c34885..ffae149 100644
--- a/client/src/components/Room/Common/UserToolbar.jsx
+++ b/client/src/components/Room/Common/UserToolbar.jsx
@@ -1,21 +1,21 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect } from 'react-redux';
-import Toolbar from '@material-ui/core/Toolbar';
-import FormGroup from '@material-ui/core/FormGroup';
-import Button from '@material-ui/core/Button';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import SettingsIcon from '@material-ui/icons/Settings';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
-import FormControl from '@material-ui/core/FormControl';
-import InputLabel from '@material-ui/core/InputLabel';
-import Checkbox from '@material-ui/core/Checkbox';
-import Select from '@material-ui/core/Select';
-import MenuItem from '@material-ui/core/MenuItem';
+import Toolbar from '@mui/material/Toolbar';
+import FormGroup from '@mui/material/FormGroup';
+import Button from '@mui/material/Button';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+import SettingsIcon from '@mui/icons-material/Settings';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import FormControl from '@mui/material/FormControl';
+import InputLabel from '@mui/material/InputLabel';
+import Checkbox from '@mui/material/Checkbox';
+import Select from '@mui/material/Select';
+import MenuItem from '@mui/material/MenuItem';
import { lcFetch } from '../../../lib/fetch';
import { updateCompeting } from '../../../store/room/actions';
import { updateProfile } from '../../../store/user/actions';
diff --git a/client/src/components/Room/GrandPrix/GrandPrixMain.jsx b/client/src/components/Room/GrandPrix/GrandPrixMain.jsx
index d88567e..f80298d 100644
--- a/client/src/components/Room/GrandPrix/GrandPrixMain.jsx
+++ b/client/src/components/Room/GrandPrix/GrandPrixMain.jsx
@@ -1,14 +1,15 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
-import { withStyles, makeStyles, useTheme } from '@material-ui/core/styles';
+import { useTheme } from '@mui/material/styles';
+import { withStyles, makeStyles } from '@mui/styles';
import { connect, useDispatch } from 'react-redux';
-import Grid from '@material-ui/core/Grid';
-import Box from '@material-ui/core/Box';
-import Paper from '@material-ui/core/Paper';
-import Divider from '@material-ui/core/Divider';
-import Typography from '@material-ui/core/Typography';
-import ClickAwayListener from '@material-ui/core/ClickAwayListener';
-import Button from '@material-ui/core/Button';
+import Grid from '@mui/material/Grid';
+import Box from '@mui/material/Box';
+import Paper from '@mui/material/Paper';
+import Divider from '@mui/material/Divider';
+import Typography from '@mui/material/Typography';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
+import Button from '@mui/material/Button';
import { formatISO9075 } from 'date-fns';
import calcStats from '../../../lib/stats';
import {
diff --git a/client/src/components/Room/GrandPrix/Leaderboard.jsx b/client/src/components/Room/GrandPrix/Leaderboard.jsx
index 68afe90..42ecf00 100644
--- a/client/src/components/Room/GrandPrix/Leaderboard.jsx
+++ b/client/src/components/Room/GrandPrix/Leaderboard.jsx
@@ -1,16 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect, useDispatch } from 'react-redux';
-import { makeStyles } from '@material-ui/core/styles';
-import Toolbar from '@material-ui/core/Toolbar';
-import Typography from '@material-ui/core/Typography';
-import Paper from '@material-ui/core/Paper';
-import TableContainer from '@material-ui/core/TableContainer';
-import Table from '@material-ui/core/Table';
-import TableHead from '@material-ui/core/TableHead';
-import TableBody from '@material-ui/core/TableBody';
-import TableRow from '@material-ui/core/TableRow';
-import TableCell from '@material-ui/core/TableCell';
+import { makeStyles } from '@mui/styles';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import Paper from '@mui/material/Paper';
+import TableContainer from '@mui/material/TableContainer';
+import Table from '@mui/material/Table';
+import TableHead from '@mui/material/TableHead';
+import TableBody from '@mui/material/TableBody';
+import TableRow from '@mui/material/TableRow';
+import TableCell from '@mui/material/TableCell';
import TableStatusCell from '../Common/TableStatusCell';
import TableTimeCell from '../Common/TableTimeCell';
import { StatsDialogProvider } from '../Common/StatsDialogProvider';
diff --git a/client/src/components/Room/GrandPrix/RegisterPanel.jsx b/client/src/components/Room/GrandPrix/RegisterPanel.jsx
index f426b26..f94ec7e 100644
--- a/client/src/components/Room/GrandPrix/RegisterPanel.jsx
+++ b/client/src/components/Room/GrandPrix/RegisterPanel.jsx
@@ -2,10 +2,10 @@ import React, { useState } from 'react';
import { connect, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { formatDistanceToNow, formatRFC7231 } from 'date-fns';
-import { makeStyles } from '@material-ui/core/styles';
-import Box from '@material-ui/core/Box';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
+import { makeStyles } from '@mui/styles';
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
import { updateRegistration } from '../../../store/room/actions';
import { getRegisteredUsers } from '../../../store/room/selectors';
diff --git a/client/src/components/Room/GrandPrix/index.jsx b/client/src/components/Room/GrandPrix/index.jsx
index 7a1cf3e..cbf779c 100644
--- a/client/src/components/Room/GrandPrix/index.jsx
+++ b/client/src/components/Room/GrandPrix/index.jsx
@@ -1,21 +1,21 @@
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect } from 'react-redux';
-import Grid from '@material-ui/core/Grid';
-import AppBar from '@material-ui/core/AppBar';
-import Toolbar from '@material-ui/core/Toolbar';
-import Typography from '@material-ui/core/Typography';
-import Paper from '@material-ui/core/Paper';
-import BottomNavigation from '@material-ui/core/BottomNavigation';
-import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
-import Divider from '@material-ui/core/Divider';
-import IconButton from '@material-ui/core/IconButton';
-import ChatIcon from '@material-ui/icons/Chat';
-import TimerIcon from '@material-ui/icons/Timer';
-import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
-import ArrowBackIcon from '@material-ui/icons/ArrowBack';
+import Grid from '@mui/material/Grid';
+import AppBar from '@mui/material/AppBar';
+import Toolbar from '@mui/material/Toolbar';
+import Typography from '@mui/material/Typography';
+import Paper from '@mui/material/Paper';
+import BottomNavigation from '@mui/material/BottomNavigation';
+import BottomNavigationAction from '@mui/material/BottomNavigationAction';
+import Divider from '@mui/material/Divider';
+import IconButton from '@mui/material/IconButton';
+import ChatIcon from '@mui/icons-material/Chat';
+import TimerIcon from '@mui/icons-material/Timer';
+import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Main from './GrandPrixMain';
import AdminToolbar from '../Common/AdminToolbar';
import UserToolbar from '../Common/UserToolbar';
diff --git a/client/src/components/Room/Normal/index.jsx b/client/src/components/Room/Normal/index.jsx
index 1ab53d4..465bc61 100644
--- a/client/src/components/Room/Normal/index.jsx
+++ b/client/src/components/Room/Normal/index.jsx
@@ -1,15 +1,15 @@
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect } from 'react-redux';
-import Grid from '@material-ui/core/Grid';
-import Paper from '@material-ui/core/Paper';
-import BottomNavigation from '@material-ui/core/BottomNavigation';
-import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
-import Divider from '@material-ui/core/Divider';
-import ChatIcon from '@material-ui/icons/Chat';
-import TimerIcon from '@material-ui/icons/Timer';
+import Grid from '@mui/material/Grid';
+import Paper from '@mui/material/Paper';
+import BottomNavigation from '@mui/material/BottomNavigation';
+import BottomNavigationAction from '@mui/material/BottomNavigationAction';
+import Divider from '@mui/material/Divider';
+import ChatIcon from '@mui/icons-material/Chat';
+import TimerIcon from '@mui/icons-material/Timer';
import Main from '../Common/Main';
import Chat from '../Panels/Chat';
import AdminToolbar from '../Common/AdminToolbar';
diff --git a/client/src/components/Room/Panels/Chat.jsx b/client/src/components/Room/Panels/Chat.jsx
index b02a11a..d29e5a2 100644
--- a/client/src/components/Room/Panels/Chat.jsx
+++ b/client/src/components/Room/Panels/Chat.jsx
@@ -2,25 +2,25 @@ import React, { useState, useRef, useEffect } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { makeStyles } from '@material-ui/core/styles';
-import Paper from '@material-ui/core/Paper';
-import Toolbar from '@material-ui/core/Toolbar';
-import FormControl from '@material-ui/core/FormControl';
-import Input from '@material-ui/core/Input';
-import Alert from '@material-ui/lab/Alert';
-import List from '@material-ui/core/List';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemText from '@material-ui/core/ListItemText';
-import ListItemAvatar from '@material-ui/core/ListItemAvatar';
-import ListItemIcon from '@material-ui/core/ListItemIcon';
-import Avatar from '@material-ui/core/Avatar';
-import Typography from '@material-ui/core/Typography';
-import IconButton from '@material-ui/core/IconButton';
-import Icon from '@material-ui/core/Icon';
-import NotificationImportantIcon from '@material-ui/icons/NotificationImportant';
-import PersonIcon from '@material-ui/icons/Person';
-import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
-import ArrowBackIcon from '@material-ui/icons/ArrowBack';
+import { makeStyles } from '@mui/styles';
+import Paper from '@mui/material/Paper';
+import Toolbar from '@mui/material/Toolbar';
+import FormControl from '@mui/material/FormControl';
+import Input from '@mui/material/Input';
+import Alert from '@mui/material/Alert';
+import List from '@mui/material/List';
+import ListItem from '@mui/material/ListItem';
+import ListItemText from '@mui/material/ListItemText';
+import ListItemAvatar from '@mui/material/ListItemAvatar';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import Avatar from '@mui/material/Avatar';
+import Typography from '@mui/material/Typography';
+import IconButton from '@mui/material/IconButton';
+import Icon from '@mui/material/Icon';
+import NotificationImportantIcon from '@mui/icons-material/NotificationImportant';
+import PersonIcon from '@mui/icons-material/Person';
+import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
+import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { sendChat } from '../../../store/chat/actions';
import Panel from '../Common/Panel';
diff --git a/client/src/components/Room/index.jsx b/client/src/components/Room/index.jsx
index 8b449a4..d9910ae 100644
--- a/client/src/components/Room/index.jsx
+++ b/client/src/components/Room/index.jsx
@@ -1,11 +1,11 @@
import React, { useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
+import { makeStyles } from '@mui/styles';
import { connect, useDispatch } from 'react-redux';
-import Paper from '@material-ui/core/Paper';
-import Backdrop from '@material-ui/core/Backdrop';
-import CircularProgress from '@material-ui/core/CircularProgress';
+import Paper from '@mui/material/Paper';
+import Backdrop from '@mui/material/Backdrop';
+import CircularProgress from '@mui/material/CircularProgress';
import qs from 'qs';
import Login from './Common/Login';
import {
diff --git a/client/src/components/RoomConfigureDialog.jsx b/client/src/components/RoomConfigureDialog.jsx
index 379f7b4..0535d0a 100644
--- a/client/src/components/RoomConfigureDialog.jsx
+++ b/client/src/components/RoomConfigureDialog.jsx
@@ -2,26 +2,26 @@ import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { format } from 'date-fns';
-import { makeStyles } from '@material-ui/core/styles';
-import Divider from '@material-ui/core/Divider';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import TextField from '@material-ui/core/TextField';
-import Switch from '@material-ui/core/Switch';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
-import FormControl from '@material-ui/core/FormControl';
-import FormHelperText from '@material-ui/core/FormHelperText';
-import InputLabel from '@material-ui/core/InputLabel';
-import Select from '@material-ui/core/Select';
-import MenuItem from '@material-ui/core/MenuItem';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import Accordion from '@material-ui/core/Accordion';
-import AccordionDetails from '@material-ui/core/AccordionDetails';
-import AccordionSummary from '@material-ui/core/AccordionSummary';
-import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import { makeStyles } from '@mui/styles';
+import Divider from '@mui/material/Divider';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import TextField from '@mui/material/TextField';
+import Switch from '@mui/material/Switch';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import FormControl from '@mui/material/FormControl';
+import FormHelperText from '@mui/material/FormHelperText';
+import InputLabel from '@mui/material/InputLabel';
+import Select from '@mui/material/Select';
+import MenuItem from '@mui/material/MenuItem';
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import DialogContent from '@mui/material/DialogContent';
+import DialogTitle from '@mui/material/DialogTitle';
+import Accordion from '@mui/material/Accordion';
+import AccordionDetails from '@mui/material/AccordionDetails';
+import AccordionSummary from '@mui/material/AccordionSummary';
+import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
const useStyles = makeStyles((theme) => ({
fab: {
@@ -117,6 +117,7 @@ function RoomConfigureDialog({
autoComplete="off"
autoFocus
fullWidth
+ margin="dense"
/>
render(
+
+
+ ,
+);
+
describe('RoomConfigureDialog passwords', () => {
it('allows an existing private room to be edited without replacing its password', () => {
const onSave = jest.fn();
- const wrapper = shallow(
- ,
- );
+ renderDialog({
+ room: privateRoom,
+ open: true,
+ onSave,
+ onCancel: jest.fn(),
+ });
- const save = wrapper.find(Button).filterWhere((button) => button.text() === 'Save');
- expect(save.prop('disabled')).toBe(false);
- save.simulate('click');
+ fireEvent.click(screen.getByRole('button', { name: 'Save' }));
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({
private: true,
@@ -39,18 +39,15 @@ describe('RoomConfigureDialog passwords', () => {
it('sends an explicitly changed password', () => {
const onSave = jest.fn();
- const wrapper = shallow(
- ,
- );
+ renderDialog({
+ room: privateRoom,
+ open: true,
+ onSave,
+ onCancel: jest.fn(),
+ });
- wrapper.find(TextField).findWhere((field) => field.prop('id') === 'password')
- .simulate('change', { target: { value: 'new-password' } });
- wrapper.find(Button).filterWhere((button) => button.text() === 'Save').simulate('click');
+ fireEvent.change(screen.getByLabelText('New Password'), { target: { value: 'new-password' } });
+ fireEvent.click(screen.getByRole('button', { name: 'Save' }));
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({
private: true,
@@ -59,35 +56,27 @@ describe('RoomConfigureDialog passwords', () => {
});
it('requires a password when making an existing public room private', () => {
- const wrapper = shallow(
- ,
- );
+ renderDialog({
+ room: { ...privateRoom, private: false },
+ open: true,
+ onSave: jest.fn(),
+ onCancel: jest.fn(),
+ });
- wrapper.find(FormControlLabel).first().prop('control').props.onChange();
- wrapper.update();
+ fireEvent.click(screen.getByRole('checkbox', { name: 'Private Room?' }));
- const save = wrapper.find(Button).filterWhere((button) => button.text() === 'Save');
- expect(save.prop('disabled')).toBe(true);
+ expect(screen.getByRole('button', { name: 'Save' })).toBeDisabled();
});
it('requires a password when creating a private room', () => {
- const wrapper = shallow(
- ,
- );
+ renderDialog({
+ open: true,
+ onSave: jest.fn(),
+ onCancel: jest.fn(),
+ });
- wrapper.find(FormControlLabel).first().prop('control').props.onChange();
- wrapper.update();
+ fireEvent.click(screen.getByRole('checkbox', { name: 'Private Room?' }));
- const create = wrapper.find(Button).filterWhere((button) => button.text() === 'Create');
- expect(create.prop('disabled')).toBe(true);
+ expect(screen.getByRole('button', { name: 'Create' })).toBeDisabled();
});
});
diff --git a/client/src/components/RoomListItem.jsx b/client/src/components/RoomListItem.jsx
index 0dfcbf8..eeddca6 100644
--- a/client/src/components/RoomListItem.jsx
+++ b/client/src/components/RoomListItem.jsx
@@ -3,18 +3,18 @@ import { useHistory } from 'react-router-dom';
import { connect, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { formatDistanceToNow } from 'date-fns';
-import Tooltip from '@material-ui/core/Tooltip';
-import ListItem from '@material-ui/core/ListItem';
-import ListItemIcon from '@material-ui/core/ListItemIcon';
-import ListItemText from '@material-ui/core/ListItemText';
-import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
-import Typography from '@material-ui/core/Typography';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-import IconButton from '@material-ui/core/IconButton';
-import PublicIcon from '@material-ui/icons/Public';
-import PrivateIcon from '@material-ui/icons/Lock';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
+import Tooltip from '@mui/material/Tooltip';
+import ListItem from '@mui/material/ListItem';
+import ListItemIcon from '@mui/material/ListItemIcon';
+import ListItemText from '@mui/material/ListItemText';
+import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
+import Typography from '@mui/material/Typography';
+import Menu from '@mui/material/Menu';
+import MenuItem from '@mui/material/MenuItem';
+import IconButton from '@mui/material/IconButton';
+import PublicIcon from '@mui/icons-material/Public';
+import PrivateIcon from '@mui/icons-material/Lock';
+import MoreVertIcon from '@mui/icons-material/MoreVert';
import { useConfirm } from 'material-ui-confirm';
import { lcFetch } from '../lib/fetch';
// import ListItem from './ListItemLink';
diff --git a/client/src/components/Timer/ManualTimer.jsx b/client/src/components/Timer/ManualTimer.jsx
index 4b69a6d..087a650 100644
--- a/client/src/components/Timer/ManualTimer.jsx
+++ b/client/src/components/Timer/ManualTimer.jsx
@@ -1,19 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
-import { withStyles } from '@material-ui/core/styles';
-import Box from '@material-ui/core/Box';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import Input from '@material-ui/core/Input';
-import Checkbox from '@material-ui/core/Checkbox';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
+import { withStyles } from '@mui/styles';
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import Input from '@mui/material/Input';
+import Checkbox from '@mui/material/Checkbox';
+import FormControlLabel from '@mui/material/FormControlLabel';
import {
formatTime, parseTime, setInterval, clearInterval, now,
} from '../../lib/utils';
import initialStyles from './styles';
-const useStyles = withStyles((theme) => ({
+const withComponentStyles = withStyles((theme) => ({
...initialStyles(theme),
input: {
maxWidth: '300px',
@@ -559,4 +559,4 @@ ManualTimer.defaultProps = {
onPriming: () => {},
};
-export default useStyles(ManualTimer);
+export default withComponentStyles(ManualTimer);
diff --git a/client/src/components/Timer/ManualTimer.test.jsx b/client/src/components/Timer/ManualTimer.test.jsx
index a149cb2..11a0b68 100644
--- a/client/src/components/Timer/ManualTimer.test.jsx
+++ b/client/src/components/Timer/ManualTimer.test.jsx
@@ -1,5 +1,3 @@
-import React from 'react';
-import { shallow } from 'enzyme';
import { ManualTimer } from './ManualTimer';
const makeProps = () => ({
@@ -15,24 +13,32 @@ const makeProps = () => ({
useInspection: false,
});
+const createTimer = (props) => {
+ const timer = new ManualTimer(props);
+ timer.setState = (update) => {
+ timer.state = { ...timer.state, ...update };
+ };
+ return timer;
+};
+
describe('manual timer submission', () => {
it.each(['', 'not-a-time'])('keeps invalid input for correction: %p', (timeInput) => {
const props = makeProps();
- const wrapper = shallow();
- wrapper.setState({ timeInput });
+ const timer = createTimer(props);
+ timer.state.timeInput = timeInput;
- wrapper.instance().submitTime({ preventDefault: jest.fn() });
+ timer.submitTime({ preventDefault: jest.fn() });
expect(props.onSubmitTime).not.toHaveBeenCalled();
- expect(wrapper.state('timeInput')).toBe(timeInput);
+ expect(timer.state.timeInput).toBe(timeInput);
});
it('submits and resets a valid time', () => {
const props = makeProps();
- const wrapper = shallow();
- wrapper.setState({ timeInput: '5.00' });
+ const timer = createTimer(props);
+ timer.state.timeInput = '5.00';
- wrapper.instance().submitTime({ preventDefault: jest.fn() });
+ timer.submitTime({ preventDefault: jest.fn() });
expect(props.onSubmitTime).toHaveBeenCalledWith({
time: 5000,
@@ -42,6 +48,6 @@ describe('manual timer submission', () => {
inspection: false,
},
});
- expect(wrapper.state('timeInput')).toBe('');
+ expect(timer.state.timeInput).toBe('');
});
});
diff --git a/client/src/components/Timer/SpacebarTimer.jsx b/client/src/components/Timer/SpacebarTimer.jsx
index d291dec..cf6f2ed 100644
--- a/client/src/components/Timer/SpacebarTimer.jsx
+++ b/client/src/components/Timer/SpacebarTimer.jsx
@@ -1,19 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
-import { withStyles } from '@material-ui/core/styles';
-import Box from '@material-ui/core/Box';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import Checkbox from '@material-ui/core/Checkbox';
-import FormGroup from '@material-ui/core/FormGroup';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
+import { withStyles } from '@mui/styles';
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import Checkbox from '@mui/material/Checkbox';
+import FormGroup from '@mui/material/FormGroup';
+import FormControlLabel from '@mui/material/FormControlLabel';
import {
formatTime, setInterval, clearInterval, now,
} from '../../lib/utils';
import styles from './styles';
-const useStyles = withStyles(styles);
+const withComponentStyles = withStyles(styles);
/*
Complicated beast.
@@ -475,4 +475,4 @@ Timer.defaultProps = {
onPriming: () => {},
};
-export default useStyles(Timer);
+export default withComponentStyles(Timer);
diff --git a/client/src/components/Timer/StackmatTimer.jsx b/client/src/components/Timer/StackmatTimer.jsx
index e1b2045..a68e5cd 100644
--- a/client/src/components/Timer/StackmatTimer.jsx
+++ b/client/src/components/Timer/StackmatTimer.jsx
@@ -3,19 +3,19 @@ import StackmatSignalProcessor from 'stackmat-signal-processor';
import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
-import { withStyles } from '@material-ui/core/styles';
-import Box from '@material-ui/core/Box';
-import Typography from '@material-ui/core/Typography';
-import Button from '@material-ui/core/Button';
-import Checkbox from '@material-ui/core/Checkbox';
-import FormGroup from '@material-ui/core/FormGroup';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
+import { withStyles } from '@mui/styles';
+import Box from '@mui/material/Box';
+import Typography from '@mui/material/Typography';
+import Button from '@mui/material/Button';
+import Checkbox from '@mui/material/Checkbox';
+import FormGroup from '@mui/material/FormGroup';
+import FormControlLabel from '@mui/material/FormControlLabel';
import {
formatTime, setInterval, clearInterval, now,
} from '../../lib/utils';
import styles from './styles';
-const useStyles = withStyles(styles);
+const withComponentStyles = withStyles(styles);
const STATUS = {
RESTING: 'RESTING',
@@ -431,4 +431,4 @@ Timer.defaultProps = {
onPriming: () => {},
};
-export default useStyles(Timer);
+export default withComponentStyles(Timer);
diff --git a/client/src/components/Timer/index.jsx b/client/src/components/Timer/index.jsx
index d796505..a0be36e 100644
--- a/client/src/components/Timer/index.jsx
+++ b/client/src/components/Timer/index.jsx
@@ -1,4 +1,4 @@
-/* eslint-disable react/jsx-props-no-spreading */
+
import React from 'react';
import PropTypes from 'prop-types';
import SpacebarTimer from './SpacebarTimer';
diff --git a/client/src/components/User.jsx b/client/src/components/User.jsx
index 847ce45..5e07e90 100644
--- a/client/src/components/User.jsx
+++ b/client/src/components/User.jsx
@@ -1,9 +1,9 @@
import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Popover from '@material-ui/core/Popover';
-import Typography from '@material-ui/core/Typography';
+import { makeStyles } from '@mui/styles';
+import Popover from '@mui/material/Popover';
+import Typography from '@mui/material/Typography';
import { Link } from 'react-router-dom';
const useStyles = makeStyles((theme) => ({
diff --git a/client/src/components/User.test.jsx b/client/src/components/User.test.jsx
index 84217a1..cb99e4e 100644
--- a/client/src/components/User.test.jsx
+++ b/client/src/components/User.test.jsx
@@ -1,23 +1,31 @@
import React from 'react';
-import { shallow } from 'enzyme';
-import Typography from '@material-ui/core/Typography';
+import { render, screen } from '@testing-library/react';
+import { MemoryRouter } from 'react-router-dom';
+import { ThemeProvider } from '../theme';
import User from './User';
describe('User', () => {
const baseUser = { displayName: 'Cuber', id: 42 };
+ const renderUser = (user) => render(
+
+
+
+
+ ,
+ );
+
it('does not turn an internal user ID into a public profile link', () => {
- const wrapper = shallow();
- const name = wrapper.find(Typography).first();
+ renderUser(baseUser);
+ const name = screen.getByText('Cuber');
- expect(name.prop('component')).toBe('span');
- expect(name.prop('to')).toBeUndefined();
+ expect(name.tagName).toBe('SPAN');
+ expect(name).not.toHaveAttribute('href');
});
it('links only through a server-provided public profile key', () => {
- const wrapper = shallow();
- const name = wrapper.find(Typography).first();
+ renderUser({ ...baseUser, profileKey: 'cuber' });
- expect(name.prop('to')).toBe('/users/cuber');
+ expect(screen.getByText('Cuber')).toHaveAttribute('href', '/users/cuber');
});
});
diff --git a/client/src/components/WCARedirect.jsx b/client/src/components/WCARedirect.jsx
index 52a3f06..17cad31 100644
--- a/client/src/components/WCARedirect.jsx
+++ b/client/src/components/WCARedirect.jsx
@@ -3,13 +3,13 @@ import PropTypes from 'prop-types';
import { connect, useDispatch } from 'react-redux';
import qs from 'qs';
import { Redirect, useLocation } from 'react-router-dom';
-import { makeStyles } from '@material-ui/core/styles';
-import Box from '@material-ui/core/Box';
-import Paper from '@material-ui/core/Paper';
-import Typography from '@material-ui/core/Typography';
-import LinearProgress from '@material-ui/core/LinearProgress';
-import Alert from '@material-ui/lab/Alert';
-import AlertTitle from '@material-ui/lab/AlertTitle';
+import { makeStyles } from '@mui/styles';
+import Box from '@mui/material/Box';
+import Paper from '@mui/material/Paper';
+import Typography from '@mui/material/Typography';
+import LinearProgress from '@mui/material/LinearProgress';
+import Alert from '@mui/material/Alert';
+import AlertTitle from '@mui/material/AlertTitle';
import { lcFetch } from '../lib/fetch';
import { userChanged } from '../store/user/actions';
diff --git a/client/src/components/common/EditableTextField.jsx b/client/src/components/common/EditableTextField.jsx
index 8302b26..93a83e8 100644
--- a/client/src/components/common/EditableTextField.jsx
+++ b/client/src/components/common/EditableTextField.jsx
@@ -1,14 +1,14 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Paper from '@material-ui/core/Paper';
-import Input from '@material-ui/core/Input';
-import InputLabel from '@material-ui/core/InputLabel';
-import Button from '@material-ui/core/Button';
-import ButtonGroup from '@material-ui/core/ButtonGroup';
-import FormControl from '@material-ui/core/FormControl';
-import FormHelperText from '@material-ui/core/FormHelperText';
-import ClickAwayListener from '@material-ui/core/ClickAwayListener';
+import { makeStyles } from '@mui/styles';
+import Paper from '@mui/material/Paper';
+import Input from '@mui/material/Input';
+import InputLabel from '@mui/material/InputLabel';
+import Button from '@mui/material/Button';
+import ButtonGroup from '@mui/material/ButtonGroup';
+import FormControl from '@mui/material/FormControl';
+import FormHelperText from '@mui/material/FormHelperText';
+import ClickAwayListener from '@mui/material/ClickAwayListener';
const useStyles = makeStyles((theme) => ({
root: {
diff --git a/client/src/components/common/EventListItem.jsx b/client/src/components/common/EventListItem.jsx
index b953217..c990023 100644
--- a/client/src/components/common/EventListItem.jsx
+++ b/client/src/components/common/EventListItem.jsx
@@ -3,23 +3,24 @@ import { useHistory } from 'react-router-dom';
import { connect, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { formatDistanceToNow } from 'date-fns';
-import Tooltip from '@material-ui/core/Tooltip';
-import { makeStyles, useTheme } from '@material-ui/core/styles';
-import Card from '@material-ui/core/Card';
-import CardHeader from '@material-ui/core/CardHeader';
-import CardContent from '@material-ui/core/CardContent';
-import CardActions from '@material-ui/core/CardActions';
-import CardMedia from '@material-ui/core/CardMedia';
-import Alert from '@material-ui/lab/Alert';
-import Typography from '@material-ui/core/Typography';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
-import IconButton from '@material-ui/core/IconButton';
-import Button from '@material-ui/core/Button';
-import PublicIcon from '@material-ui/icons/Public';
-import PrivateIcon from '@material-ui/icons/Lock';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
-import ShareIcon from '@material-ui/icons/Share';
+import Tooltip from '@mui/material/Tooltip';
+import { useTheme } from '@mui/material/styles';
+import { makeStyles } from '@mui/styles';
+import Card from '@mui/material/Card';
+import CardHeader from '@mui/material/CardHeader';
+import CardContent from '@mui/material/CardContent';
+import CardActions from '@mui/material/CardActions';
+import CardMedia from '@mui/material/CardMedia';
+import Alert from '@mui/material/Alert';
+import Typography from '@mui/material/Typography';
+import Menu from '@mui/material/Menu';
+import MenuItem from '@mui/material/MenuItem';
+import IconButton from '@mui/material/IconButton';
+import Button from '@mui/material/Button';
+import PublicIcon from '@mui/icons-material/Public';
+import PrivateIcon from '@mui/icons-material/Lock';
+import MoreVertIcon from '@mui/icons-material/MoreVert';
+import ShareIcon from '@mui/icons-material/Share';
import { useConfirm } from 'material-ui-confirm';
import { TwitchEmbed } from 'react-twitch-embed';
import { lcFetch } from '../../lib/fetch';
@@ -167,7 +168,7 @@ function RoomListItem({
id={`channel-${room.twitchChannel}-${room._id}`}
muted
withChat={false}
- theme={theme.palette.type}
+ theme={theme.palette.mode}
width="100%"
/>
diff --git a/client/src/components/common/HelpPopover.jsx b/client/src/components/common/HelpPopover.jsx
index ba58ece..b0cd17f 100644
--- a/client/src/components/common/HelpPopover.jsx
+++ b/client/src/components/common/HelpPopover.jsx
@@ -1,10 +1,10 @@
import React, { useState } from 'react';
-import Popover from '@material-ui/core/Popover';
-import Typography from '@material-ui/core/Typography';
-import IconButton from '@material-ui/core/IconButton';
-import HelpIcon from '@material-ui/icons/Help';
+import Popover from '@mui/material/Popover';
+import Typography from '@mui/material/Typography';
+import IconButton from '@mui/material/IconButton';
+import HelpIcon from '@mui/icons-material/Help';
-export default () => {
+const HelpPopover = () => {
const [helpAnchor, setHelpAnchor] = useState(null);
return (
@@ -39,3 +39,5 @@ export default () => {
);
};
+
+export default HelpPopover;
diff --git a/client/src/components/common/ListItemLink.jsx b/client/src/components/common/ListItemLink.jsx
index 26318db..74e3db7 100644
--- a/client/src/components/common/ListItemLink.jsx
+++ b/client/src/components/common/ListItemLink.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
-import ListItem from '@material-ui/core/ListItem';
+import ListItem from '@mui/material/ListItem';
function ListItemLink({ children, to, disabled }) {
return (
diff --git a/client/src/components/common/PrivateRoute.jsx b/client/src/components/common/PrivateRoute.jsx
index d1564e2..e91d6b8 100644
--- a/client/src/components/common/PrivateRoute.jsx
+++ b/client/src/components/common/PrivateRoute.jsx
@@ -4,7 +4,7 @@ import { Route, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
const PrivateRoute = ({
- user, children, isAdminRoute, ...rest
+ user, isAdminRoute, ...rest
}) => {
const { fetching, id } = user;
const loggedIn = !fetching && id;
@@ -24,16 +24,11 @@ const PrivateRoute = ({
};
PrivateRoute.propTypes = {
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node,
- ]),
isAdminRoute: PropTypes.bool,
user: PropTypes.shape(),
};
PrivateRoute.defaultProps = {
- children: [],
isAdminRoute: false,
user: {
},
diff --git a/client/src/components/common/Profile.jsx b/client/src/components/common/Profile.jsx
index dd4aa38..b389300 100644
--- a/client/src/components/common/Profile.jsx
+++ b/client/src/components/common/Profile.jsx
@@ -1,15 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import { makeStyles } from '@material-ui/core/styles';
-import Paper from '@material-ui/core/Paper';
-import Grid from '@material-ui/core/Grid';
-import Avatar from '@material-ui/core/Avatar';
-import Typography from '@material-ui/core/Typography';
-import FormControlLabel from '@material-ui/core/FormControlLabel';
-import Checkbox from '@material-ui/core/Checkbox';
-import Divider from '@material-ui/core/Divider';
-import Alert from '@material-ui/lab/Alert';
+import { makeStyles } from '@mui/styles';
+import Paper from '@mui/material/Paper';
+import Grid from '@mui/material/Grid';
+import Avatar from '@mui/material/Avatar';
+import Typography from '@mui/material/Typography';
+import FormControlLabel from '@mui/material/FormControlLabel';
+import Checkbox from '@mui/material/Checkbox';
+import Divider from '@mui/material/Divider';
+import Alert from '@mui/material/Alert';
import EditableTextField from './EditableTextField';
import { lcFetch } from '../../lib/fetch';
import { updateProfile } from '../../store/user/actions';
diff --git a/client/src/components/common/Scramble.jsx b/client/src/components/common/Scramble.jsx
index 5629e7e..6556cba 100644
--- a/client/src/components/common/Scramble.jsx
+++ b/client/src/components/common/Scramble.jsx
@@ -1,8 +1,8 @@
import React from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
-import { makeStyles } from '@material-ui/core/styles';
-import Typography from '@material-ui/core/Typography';
+import { makeStyles } from '@mui/styles';
+import Typography from '@mui/material/Typography';
const useStyles = makeStyles((theme) => ({
root: {
@@ -18,7 +18,7 @@ const useStyles = makeStyles((theme) => ({
disabled: {
color: theme.palette.text.disabled,
},
- // eslint-disable-next-line quote-props
+
minx: {
lineHeight: '.90rem',
fontSize: '.75rem',
diff --git a/client/src/components/common/Scramble.test.jsx b/client/src/components/common/Scramble.test.jsx
index 1fbad03..76e2ba2 100644
--- a/client/src/components/common/Scramble.test.jsx
+++ b/client/src/components/common/Scramble.test.jsx
@@ -1,15 +1,25 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import { render, screen } from '@testing-library/react';
+import { createTheme, ThemeProvider } from '@mui/material/styles';
import Scramble from './Scramble';
const scramble = 'test';
+const theme = createTheme();
+
+const renderScramble = (props) => render(
+