mirror of
https://github.com/element-hq/element-web
synced 2024-11-22 17:25:50 +03:00
Device manager - device tile main click target (#9409)
* change device tile click to toggle details instead of selection * lint * test current device section click * stuck cypress
This commit is contained in:
parent
77543b32d4
commit
17fce6ccb2
14 changed files with 69 additions and 22 deletions
|
@ -74,8 +74,8 @@ describe("Device manager", () => {
|
||||||
cy.get('.mx_FilteredDeviceList_list').find('.mx_FilteredDeviceList_listItem').should('have.length', 3);
|
cy.get('.mx_FilteredDeviceList_list').find('.mx_FilteredDeviceList_listItem').should('have.length', 3);
|
||||||
|
|
||||||
// select two sessions
|
// select two sessions
|
||||||
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem').first().click();
|
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem .mx_Checkbox').first().click();
|
||||||
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem').last().click();
|
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem .mx_Checkbox').last().click();
|
||||||
// sign out from list selection action buttons
|
// sign out from list selection action buttons
|
||||||
cy.get('[data-testid="sign-out-selection-cta"]').click();
|
cy.get('[data-testid="sign-out-selection-cta"]').click();
|
||||||
// list updated after sign out
|
// list updated after sign out
|
||||||
|
@ -84,7 +84,7 @@ describe("Device manager", () => {
|
||||||
cy.get('[data-testid="unverified-devices-cta"]').should('have.text', 'View all (1)');
|
cy.get('[data-testid="unverified-devices-cta"]').should('have.text', 'View all (1)');
|
||||||
|
|
||||||
const sessionName = `Alice's device`;
|
const sessionName = `Alice's device`;
|
||||||
// select the first session
|
// open the first session
|
||||||
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem').first().within(() => {
|
cy.get('.mx_FilteredDeviceList_list .mx_FilteredDeviceList_listItem').first().within(() => {
|
||||||
cy.get('[aria-label="Toggle device details"]').click();
|
cy.get('[aria-label="Toggle device details"]').click();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@ limitations under the License.
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_DeviceTile_interactive {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.mx_DeviceTile_info {
|
.mx_DeviceTile_info {
|
||||||
flex: 1 1 0;
|
flex: 1 1 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ limitations under the License.
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_SelectableDeviceTile_checkbox {
|
.mx_SelectableDeviceTile_checkbox {
|
||||||
|
|
|
@ -173,7 +173,7 @@ export default class DevicesPanelEntry extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_DevicesPanel_device">
|
<div className="mx_DevicesPanel_device">
|
||||||
<SelectableDeviceTile device={extendedDevice} onClick={this.onDeviceToggled} isSelected={this.props.selected}>
|
<SelectableDeviceTile device={extendedDevice} onSelect={this.onDeviceToggled} isSelected={this.props.selected}>
|
||||||
{ buttons }
|
{ buttons }
|
||||||
</SelectableDeviceTile>
|
</SelectableDeviceTile>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -105,6 +105,7 @@ const CurrentDeviceSection: React.FC<Props> = ({
|
||||||
{ !!device && <>
|
{ !!device && <>
|
||||||
<DeviceTile
|
<DeviceTile
|
||||||
device={device}
|
device={device}
|
||||||
|
onClick={() => setIsExpanded(!isExpanded)}
|
||||||
>
|
>
|
||||||
<DeviceExpandDetailsButton
|
<DeviceExpandDetailsButton
|
||||||
data-testid='current-session-toggle-details'
|
data-testid='current-session-toggle-details'
|
||||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { Fragment } from "react";
|
import React, { Fragment } from "react";
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { Icon as InactiveIcon } from '../../../../../res/img/element-icons/settings/inactive.svg';
|
import { Icon as InactiveIcon } from '../../../../../res/img/element-icons/settings/inactive.svg';
|
||||||
import { _t } from "../../../../languageHandler";
|
import { _t } from "../../../../languageHandler";
|
||||||
|
@ -23,6 +24,7 @@ import Heading from "../../typography/Heading";
|
||||||
import { INACTIVE_DEVICE_AGE_DAYS, isDeviceInactive } from "./filter";
|
import { INACTIVE_DEVICE_AGE_DAYS, isDeviceInactive } from "./filter";
|
||||||
import { ExtendedDevice } from "./types";
|
import { ExtendedDevice } from "./types";
|
||||||
import { DeviceTypeIcon } from "./DeviceTypeIcon";
|
import { DeviceTypeIcon } from "./DeviceTypeIcon";
|
||||||
|
import { preventDefaultWrapper } from "../../../../utils/NativeEventUtils";
|
||||||
export interface DeviceTileProps {
|
export interface DeviceTileProps {
|
||||||
device: ExtendedDevice;
|
device: ExtendedDevice;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
|
@ -88,13 +90,20 @@ const DeviceTile: React.FC<DeviceTileProps> = ({
|
||||||
{ id: 'deviceId', value: device.device_id },
|
{ id: 'deviceId', value: device.device_id },
|
||||||
];
|
];
|
||||||
|
|
||||||
return <div className="mx_DeviceTile" data-testid={`device-tile-${device.device_id}`}>
|
return <div
|
||||||
|
className={classNames(
|
||||||
|
"mx_DeviceTile",
|
||||||
|
{ "mx_DeviceTile_interactive": !!onClick },
|
||||||
|
)}
|
||||||
|
data-testid={`device-tile-${device.device_id}`}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
<DeviceTypeIcon
|
<DeviceTypeIcon
|
||||||
isVerified={device.isVerified}
|
isVerified={device.isVerified}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
deviceType={device.deviceType}
|
deviceType={device.deviceType}
|
||||||
/>
|
/>
|
||||||
<div className="mx_DeviceTile_info" onClick={onClick}>
|
<div className="mx_DeviceTile_info">
|
||||||
<DeviceTileName device={device} />
|
<DeviceTileName device={device} />
|
||||||
<div className="mx_DeviceTile_metadata">
|
<div className="mx_DeviceTile_metadata">
|
||||||
{ metadata.map(({ id, value }, index) =>
|
{ metadata.map(({ id, value }, index) =>
|
||||||
|
@ -107,7 +116,7 @@ const DeviceTile: React.FC<DeviceTileProps> = ({
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mx_DeviceTile_actions">
|
<div className="mx_DeviceTile_actions" onClick={preventDefaultWrapper(() => {})}>
|
||||||
{ children }
|
{ children }
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -179,7 +179,8 @@ const DeviceListItem: React.FC<{
|
||||||
}) => <li className='mx_FilteredDeviceList_listItem'>
|
}) => <li className='mx_FilteredDeviceList_listItem'>
|
||||||
<SelectableDeviceTile
|
<SelectableDeviceTile
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
onClick={toggleSelected}
|
onSelect={toggleSelected}
|
||||||
|
onClick={onDeviceExpandToggle}
|
||||||
device={device}
|
device={device}
|
||||||
>
|
>
|
||||||
<DeviceExpandDetailsButton
|
<DeviceExpandDetailsButton
|
||||||
|
|
|
@ -21,15 +21,22 @@ import DeviceTile, { DeviceTileProps } from './DeviceTile';
|
||||||
|
|
||||||
interface Props extends DeviceTileProps {
|
interface Props extends DeviceTileProps {
|
||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
onClick: () => void;
|
onSelect: () => void;
|
||||||
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectableDeviceTile: React.FC<Props> = ({ children, device, isSelected, onClick }) => {
|
const SelectableDeviceTile: React.FC<Props> = ({
|
||||||
|
children,
|
||||||
|
device,
|
||||||
|
isSelected,
|
||||||
|
onSelect,
|
||||||
|
onClick,
|
||||||
|
}) => {
|
||||||
return <div className='mx_SelectableDeviceTile'>
|
return <div className='mx_SelectableDeviceTile'>
|
||||||
<StyledCheckbox
|
<StyledCheckbox
|
||||||
kind={CheckboxStyle.Solid}
|
kind={CheckboxStyle.Solid}
|
||||||
checked={isSelected}
|
checked={isSelected}
|
||||||
onChange={onClick}
|
onChange={onSelect}
|
||||||
className='mx_SelectableDeviceTile_checkbox'
|
className='mx_SelectableDeviceTile_checkbox'
|
||||||
id={`device-tile-checkbox-${device.device_id}`}
|
id={`device-tile-checkbox-${device.device_id}`}
|
||||||
data-testid={`device-tile-checkbox-${device.device_id}`}
|
data-testid={`device-tile-checkbox-${device.device_id}`}
|
||||||
|
|
|
@ -67,6 +67,23 @@ describe('<CurrentDeviceSection />', () => {
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('displays device details on main tile click', () => {
|
||||||
|
const { getByTestId, container } = render(getComponent({ device: alicesUnverifiedDevice }));
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(getByTestId(`device-tile-${alicesUnverifiedDevice.device_id}`));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(container.getElementsByClassName('mx_DeviceDetails').length).toBeTruthy();
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
fireEvent.click(getByTestId(`device-tile-${alicesUnverifiedDevice.device_id}`));
|
||||||
|
});
|
||||||
|
|
||||||
|
// device details are hidden
|
||||||
|
expect(container.getElementsByClassName('mx_DeviceDetails').length).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
it('displays device details on toggle click', () => {
|
it('displays device details on toggle click', () => {
|
||||||
const { container, getByTestId } = render(getComponent({ device: alicesUnverifiedDevice }));
|
const { container, getByTestId } = render(getComponent({ device: alicesUnverifiedDevice }));
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,14 @@ describe('<DeviceTile />', () => {
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('applies interactive class when tile has click handler', () => {
|
||||||
|
const onClick = jest.fn();
|
||||||
|
const { getByTestId } = render(getComponent({ onClick }));
|
||||||
|
expect(
|
||||||
|
getByTestId('device-tile-123').className.includes('mx_DeviceTile_interactive'),
|
||||||
|
).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders a verified device with no metadata', () => {
|
it('renders a verified device with no metadata', () => {
|
||||||
const { container } = render(getComponent());
|
const { container } = render(getComponent());
|
||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
|
|
|
@ -30,6 +30,7 @@ describe('<SelectableDeviceTile />', () => {
|
||||||
deviceType: DeviceType.Unknown,
|
deviceType: DeviceType.Unknown,
|
||||||
};
|
};
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
|
onSelect: jest.fn(),
|
||||||
onClick: jest.fn(),
|
onClick: jest.fn(),
|
||||||
device,
|
device,
|
||||||
children: <div>test</div>,
|
children: <div>test</div>,
|
||||||
|
@ -48,15 +49,15 @@ describe('<SelectableDeviceTile />', () => {
|
||||||
expect(container.querySelector(`#device-tile-checkbox-${device.device_id}`)).toMatchSnapshot();
|
expect(container.querySelector(`#device-tile-checkbox-${device.device_id}`)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls onClick on checkbox click', () => {
|
it('calls onSelect on checkbox click', () => {
|
||||||
const onClick = jest.fn();
|
const onSelect = jest.fn();
|
||||||
const { container } = render(getComponent({ onClick }));
|
const { container } = render(getComponent({ onSelect }));
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
fireEvent.click(container.querySelector(`#device-tile-checkbox-${device.device_id}`));
|
fireEvent.click(container.querySelector(`#device-tile-checkbox-${device.device_id}`));
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(onClick).toHaveBeenCalled();
|
expect(onSelect).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls onClick on device tile info click', () => {
|
it('calls onClick on device tile info click', () => {
|
||||||
|
|
|
@ -181,7 +181,7 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
||||||
class="mx_SettingsSubsection_content"
|
class="mx_SettingsSubsection_content"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-alices_device"
|
data-testid="device-tile-alices_device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -317,7 +317,7 @@ exports[`<CurrentDeviceSection /> renders device and correct security card when
|
||||||
class="mx_SettingsSubsection_content"
|
class="mx_SettingsSubsection_content"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-alices_device"
|
data-testid="device-tile-alices_device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -35,7 +35,7 @@ exports[`<SelectableDeviceTile /> renders unselected device tile with checkbox 1
|
||||||
</label>
|
</label>
|
||||||
</span>
|
</span>
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-my-device"
|
data-testid="device-tile-my-device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -45,7 +45,7 @@ exports[`<SessionManagerTab /> current session section renders current session s
|
||||||
class="mx_SettingsSubsection_content"
|
class="mx_SettingsSubsection_content"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-alices_device"
|
data-testid="device-tile-alices_device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -167,7 +167,7 @@ exports[`<SessionManagerTab /> current session section renders current session s
|
||||||
class="mx_SettingsSubsection_content"
|
class="mx_SettingsSubsection_content"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-alices_device"
|
data-testid="device-tile-alices_device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -334,7 +334,7 @@ exports[`<SessionManagerTab /> goes to filtered list from security recommendatio
|
||||||
|
|
||||||
exports[`<SessionManagerTab /> sets device verification status correctly 1`] = `
|
exports[`<SessionManagerTab /> sets device verification status correctly 1`] = `
|
||||||
<div
|
<div
|
||||||
class="mx_DeviceTile"
|
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||||
data-testid="device-tile-alices_device"
|
data-testid="device-tile-alices_device"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
Loading…
Reference in a new issue