Device manager - device security recommendation card (PSG-637) (#9158)
* add security card and style * deprecate warning and verified svgs that use hard coded color * style icons, test * i18n * stylelint * redo lost lint fixes * fix svg ref * actually fix svg * fix stupid copy pasting * use rgba for e2e light variations * add security card and style * deprecate warning and verified svgs that use hard coded color * style icons, test * i18n * stylelint * fix svg ref * actually fix svg * fix stupid copy pasting * use rgba for e2e light variations * use device security card in current session section * lint * update snapshot test after dev merge
|
@ -28,6 +28,7 @@
|
|||
@import "./components/views/messages/_MBeaconBody.pcss";
|
||||
@import "./components/views/messages/shared/_MediaProcessingError.pcss";
|
||||
@import "./components/views/settings/devices/_DeviceDetails.pcss";
|
||||
@import "./components/views/settings/devices/_DeviceSecurityCard.pcss";
|
||||
@import "./components/views/settings/devices/_DeviceTile.pcss";
|
||||
@import "./components/views/settings/devices/_FilteredDeviceList.pcss";
|
||||
@import "./components/views/settings/devices/_SelectableDeviceTile.pcss";
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.mx_DeviceSecurityCard {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
|
||||
padding: $spacing-16;
|
||||
|
||||
border: 1px solid $quinary-content;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.mx_DeviceSecurityCard_icon {
|
||||
flex: 0 0 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: $spacing-16;
|
||||
border-radius: 8px;
|
||||
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
|
||||
color: var(--icon-color);
|
||||
background-color: var(--background-color);
|
||||
|
||||
&.Verified {
|
||||
--icon-color: $e2e-verified-color;
|
||||
--background-color: $e2e-verified-color-light;
|
||||
}
|
||||
|
||||
&.Unverified {
|
||||
--icon-color: $e2e-warning-color;
|
||||
--background-color: $e2e-warning-color-light;
|
||||
}
|
||||
|
||||
&.Inactive {
|
||||
--icon-color: $secondary-content;
|
||||
--background-color: $system;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_DeviceSecurityCard_content {
|
||||
flex: 1 1;
|
||||
}
|
||||
.mx_DeviceSecurityCard_heading {
|
||||
margin: 0 0 $spacing-4 0;
|
||||
}
|
||||
.mx_DeviceSecurityCard_description {
|
||||
margin: 0 0 $spacing-8 0;
|
||||
font-size: $font-12px;
|
||||
color: $secondary-content;
|
||||
}
|
3
res/img/e2e/verified-deprecated.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 3.05V9.27C2 15.63 9 17 9 17C9 17 16 15.63 16 9.27V3.05L9 1L2 3.05ZM11.9405 5.5196C12.1305 5.3396 12.4305 5.3496 12.6105 5.5396C12.7705 5.7196 12.7705 5.9896 12.6305 6.1696L8.41047 11.2796L8.38047 11.3196C8.10047 11.6596 7.59047 11.7096 7.25047 11.4296C7.22027 11.4145 7.19577 11.388 7.17266 11.363C7.16517 11.3549 7.15782 11.347 7.15047 11.3396L5.34047 9.2596C5.14047 9.0196 5.16047 8.6596 5.40047 8.4596C5.60047 8.2796 5.89047 8.2796 6.10047 8.4196L7.67047 9.5196L11.9405 5.5196Z" fill="#010101"/>
|
||||
</svg>
|
After Width: | Height: | Size: 658 B |
|
@ -1,3 +1,3 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 3.05V9.27C2 15.63 9 17 9 17C9 17 16 15.63 16 9.27V3.05L9 1L2 3.05ZM11.9405 5.5196C12.1305 5.3396 12.4305 5.3496 12.6105 5.5396C12.7705 5.7196 12.7705 5.9896 12.6305 6.1696L8.41047 11.2796L8.38047 11.3196C8.10047 11.6596 7.59047 11.7096 7.25047 11.4296C7.22027 11.4145 7.19577 11.388 7.17266 11.363C7.16517 11.3549 7.15782 11.347 7.15047 11.3396L5.34047 9.2596C5.14047 9.0196 5.16047 8.6596 5.40047 8.4596C5.60047 8.2796 5.89047 8.2796 6.10047 8.4196L7.67047 9.5196L11.9405 5.5196Z" fill="#010101"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 3.05V9.27C2 15.63 9 17 9 17C9 17 16 15.63 16 9.27V3.05L9 1L2 3.05ZM11.9405 5.5196C12.1305 5.3396 12.4305 5.3496 12.6105 5.5396C12.7705 5.7196 12.7705 5.9896 12.6305 6.1696L8.41047 11.2796L8.38047 11.3196C8.10047 11.6596 7.59047 11.7096 7.25047 11.4296C7.22027 11.4145 7.19577 11.388 7.17266 11.363C7.16517 11.3549 7.15782 11.347 7.15047 11.3396L5.34047 9.2596C5.14047 9.0196 5.16047 8.6596 5.40047 8.4596C5.60047 8.2796 5.89047 8.2796 6.10047 8.4196L7.67047 9.5196L11.9405 5.5196Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 663 B |
3
res/img/e2e/warning-deprecated.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9.27V3.05L9 1L16 3.05V9.27C16 15.63 9 17 9 17C9 17 2 15.63 2 9.27ZM8.92011 4.39997C8.35011 4.43997 7.93011 4.93997 7.98011 5.50997L8.30011 9.50997C8.33011 9.85997 8.60011 10.13 8.95011 10.16H9.01011C9.38011 10.16 9.69011 9.87997 9.72011 9.50997L10.0401 5.50997V5.34997C9.98011 4.77997 9.48011 4.35997 8.92011 4.39997ZM9.88012 12.12C9.88012 12.606 9.48613 13 9.00012 13C8.51411 13 8.12012 12.606 8.12012 12.12C8.12012 11.634 8.51411 11.24 9.00012 11.24C9.48613 11.24 9.88012 11.634 9.88012 12.12Z" fill="#020202"/>
|
||||
</svg>
|
After Width: | Height: | Size: 673 B |
|
@ -1,3 +1,3 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9.27V3.05L9 1L16 3.05V9.27C16 15.63 9 17 9 17C9 17 2 15.63 2 9.27ZM8.92011 4.39997C8.35011 4.43997 7.93011 4.93997 7.98011 5.50997L8.30011 9.50997C8.33011 9.85997 8.60011 10.13 8.95011 10.16H9.01011C9.38011 10.16 9.69011 9.87997 9.72011 9.50997L10.0401 5.50997V5.34997C9.98011 4.77997 9.48011 4.35997 8.92011 4.39997ZM9.88012 12.12C9.88012 12.606 9.48613 13 9.00012 13C8.51411 13 8.12012 12.606 8.12012 12.12C8.12012 11.634 8.51411 11.24 9.00012 11.24C9.48613 11.24 9.88012 11.634 9.88012 12.12Z" fill="#020202"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9.27V3.05L9 1L16 3.05V9.27C16 15.63 9 17 9 17C9 17 2 15.63 2 9.27ZM8.92011 4.39997C8.35011 4.43997 7.93011 4.93997 7.98011 5.50997L8.30011 9.50997C8.33011 9.85997 8.60011 10.13 8.95011 10.16H9.01011C9.38011 10.16 9.69011 9.87997 9.72011 9.50997L10.0401 5.50997V5.34997C9.98011 4.77997 9.48011 4.35997 8.92011 4.39997ZM9.88012 12.12C9.88012 12.606 9.48613 13 9.00012 13C8.51411 13 8.12012 12.606 8.12012 12.12C8.12012 11.634 8.51411 11.24 9.00012 11.24C9.48613 11.24 9.88012 11.634 9.88012 12.12Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 678 B |
3
res/img/element-icons/settings/inactive.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="8" height="14" viewBox="0 0 8 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.33333 0.333008C0.6 0.333008 0 0.933008 0 1.66634L0.00666682 3.78634C0.00666682 4.13967 0.146667 4.47301 0.393333 4.72634L2.66667 6.99967L0.393333 9.28634C0.146667 9.53301 0.00666682 9.87301 0.00666682 10.2263L0 12.333C0 13.0663 0.6 13.6663 1.33333 13.6663H6.66667C7.4 13.6663 8 13.0663 8 12.333V10.2263C8 9.87301 7.86 9.53301 7.61333 9.28634L5.33333 6.99967L7.60667 4.73301C7.86 4.47967 8 4.13967 8 3.78634V1.66634C8 0.933008 7.4 0.333008 6.66667 0.333008H1.33333ZM6.66667 10.273V11.6663C6.66667 12.033 6.36667 12.333 6 12.333H2C1.63333 12.333 1.33333 12.033 1.33333 11.6663V10.273C1.33333 10.093 1.40667 9.92634 1.52667 9.79967L4 7.33301L6.47333 9.80634C6.59333 9.92634 6.66667 10.0997 6.66667 10.273Z" fill="currentColor"/>
|
||||
</svg>
|
After Width: | Height: | Size: 839 B |
|
@ -217,6 +217,8 @@ $e2e-verified-color: #76cfa5; /* N.B. *NOT* the same as $accent */
|
|||
$e2e-unknown-color: #e8bf37;
|
||||
$e2e-unverified-color: #e8bf37;
|
||||
$e2e-warning-color: #ba6363;
|
||||
$e2e-verified-color-light: rgba($e2e-verified-color, 0.06);
|
||||
$e2e-warning-color-light: rgba($e2e-warning-color, 0.06);
|
||||
|
||||
/*** ImageView ***/
|
||||
$lightbox-bg-color: #454545;
|
||||
|
|
|
@ -201,6 +201,8 @@ $e2e-verified-color: #76cfa5; /* N.B. *NOT* the same as $accent */
|
|||
$e2e-unknown-color: #e8bf37;
|
||||
$e2e-unverified-color: #e8bf37;
|
||||
$e2e-warning-color: #ba6363;
|
||||
$e2e-verified-color-light: rgba($e2e-verified-color, 0.06);
|
||||
$e2e-warning-color-light: rgba($e2e-warning-color, 0.06);
|
||||
/* ******************** */
|
||||
|
||||
/* Tabbed views */
|
||||
|
|
|
@ -24,9 +24,9 @@ import { IDialogProps } from "../IDialogProps";
|
|||
|
||||
function iconFromPhase(phase: Phase) {
|
||||
if (phase === Phase.Done) {
|
||||
return require("../../../../../res/img/e2e/verified.svg").default;
|
||||
return require("../../../../../res/img/e2e/verified-deprecated.svg").default;
|
||||
} else {
|
||||
return require("../../../../../res/img/e2e/warning.svg").default;
|
||||
return require("../../../../../res/img/e2e/warning-deprecated.svg").default;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ const EncryptionPanel: React.FC<IProps> = (props: IProps) => {
|
|||
// handle transitions -> cancelled for mismatches which fire a modal instead of showing a card
|
||||
if (request && request.cancelled && MISMATCHES.includes(request.cancellationCode)) {
|
||||
Modal.createDialog(ErrorDialog, {
|
||||
headerImage: require("../../../../res/img/e2e/warning.svg").default,
|
||||
headerImage: require("../../../../res/img/e2e/warning-deprecated.svg").default,
|
||||
title: _t("Your messages are not secure"),
|
||||
description: <div>
|
||||
{ _t("One of the following may be compromised:") }
|
||||
|
|
60
src/components/views/settings/devices/DeviceSecurityCard.tsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
import { Icon as VerifiedIcon } from '../../../../../res/img/e2e/verified.svg';
|
||||
import { Icon as UnverifiedIcon } from '../../../../../res/img/e2e/warning.svg';
|
||||
import { Icon as InactiveIcon } from '../../../../../res/img/element-icons/settings/inactive.svg';
|
||||
|
||||
export enum DeviceSecurityVariation {
|
||||
Verified = 'Verified',
|
||||
Unverified = 'Unverified',
|
||||
Inactive = 'Inactive',
|
||||
}
|
||||
interface Props {
|
||||
variation: DeviceSecurityVariation;
|
||||
heading: string;
|
||||
description: string | React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const VariationIcon: Record<DeviceSecurityVariation, React.FC<React.SVGProps<SVGSVGElement>>> = {
|
||||
[DeviceSecurityVariation.Inactive]: InactiveIcon,
|
||||
[DeviceSecurityVariation.Verified]: VerifiedIcon,
|
||||
[DeviceSecurityVariation.Unverified]: UnverifiedIcon,
|
||||
};
|
||||
|
||||
const DeviceSecurityIcon: React.FC<{ variation: DeviceSecurityVariation }> = ({ variation }) => {
|
||||
const Icon = VariationIcon[variation];
|
||||
return <div className={classNames('mx_DeviceSecurityCard_icon', variation)}>
|
||||
<Icon height={16} width={16} />
|
||||
</div>;
|
||||
};
|
||||
|
||||
const DeviceSecurityCard: React.FC<Props> = ({ variation, heading, description, children }) => {
|
||||
return <div className='mx_DeviceSecurityCard'>
|
||||
<DeviceSecurityIcon variation={variation} />
|
||||
<div className='mx_DeviceSecurityCard_content'>
|
||||
<p className='mx_DeviceSecurityCard_heading'>{ heading }</p>
|
||||
<p className='mx_DeviceSecurityCard_description'>{ description }</p>
|
||||
{ children }
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
|
||||
export default DeviceSecurityCard;
|
|
@ -20,6 +20,7 @@ import { _t } from "../../../../../languageHandler";
|
|||
import Spinner from '../../../elements/Spinner';
|
||||
import { useOwnDevices } from '../../devices/useOwnDevices';
|
||||
import DeviceTile from '../../devices/DeviceTile';
|
||||
import DeviceSecurityCard, { DeviceSecurityVariation } from '../../devices/DeviceSecurityCard';
|
||||
import SettingsSubsection from '../../shared/SettingsSubsection';
|
||||
import SettingsTab from '../SettingsTab';
|
||||
import FilteredDeviceList from '../../devices/FilteredDeviceList';
|
||||
|
@ -30,15 +31,32 @@ const SessionManagerTab: React.FC = () => {
|
|||
const { [currentDeviceId]: currentDevice, ...otherDevices } = devices;
|
||||
const shouldShowOtherSessions = Object.keys(otherDevices).length > 0;
|
||||
|
||||
const securityCardProps = currentDevice?.isVerified ? {
|
||||
variation: DeviceSecurityVariation.Verified,
|
||||
heading: _t('Verified session'),
|
||||
description: _t('This session is ready for secure messaging.'),
|
||||
} : {
|
||||
variation: DeviceSecurityVariation.Unverified,
|
||||
heading: _t('Unverified session'),
|
||||
description: _t('Verify or sign out from this session for best security and reliability.'),
|
||||
};
|
||||
|
||||
return <SettingsTab heading={_t('Sessions')}>
|
||||
<SettingsSubsection
|
||||
heading={_t('Current session')}
|
||||
data-testid='current-session-section'
|
||||
>
|
||||
{ isLoading && <Spinner /> }
|
||||
{ !!currentDevice && <DeviceTile
|
||||
device={currentDevice}
|
||||
/> }
|
||||
{ !!currentDevice && <>
|
||||
<DeviceTile
|
||||
device={currentDevice}
|
||||
/>
|
||||
<br />
|
||||
<DeviceSecurityCard
|
||||
{...securityCardProps}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
</SettingsSubsection>
|
||||
{
|
||||
shouldShowOtherSessions &&
|
||||
|
|
|
@ -1553,6 +1553,10 @@
|
|||
"Share anonymous data to help us identify issues. Nothing personal. No third parties.": "Share anonymous data to help us identify issues. Nothing personal. No third parties.",
|
||||
"Where you're signed in": "Where you're signed in",
|
||||
"Manage your signed-in devices below. A device's name is visible to people you communicate with.": "Manage your signed-in devices below. A device's name is visible to people you communicate with.",
|
||||
"Verified session": "Verified session",
|
||||
"This session is ready for secure messaging.": "This session is ready for secure messaging.",
|
||||
"Unverified session": "Unverified session",
|
||||
"Verify or sign out from this session for best security and reliability.": "Verify or sign out from this session for best security and reliability.",
|
||||
"Sessions": "Sessions",
|
||||
"Current session": "Current session",
|
||||
"Other sessions": "Other sessions",
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
|
||||
import DeviceSecurityCard, {
|
||||
DeviceSecurityVariation,
|
||||
} from '../../../../../src/components/views/settings/devices/DeviceSecurityCard';
|
||||
|
||||
describe('<DeviceSecurityCard />', () => {
|
||||
const defaultProps = {
|
||||
variation: DeviceSecurityVariation.Verified,
|
||||
heading: 'Verified session',
|
||||
description: 'nice',
|
||||
};
|
||||
const getComponent = (props = {}): React.ReactElement =>
|
||||
<DeviceSecurityCard {...defaultProps} {...props} />;
|
||||
|
||||
it('renders basic card', () => {
|
||||
const { container } = render(getComponent());
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders with children', () => {
|
||||
const { container } = render(getComponent({
|
||||
children: <div>hey</div>,
|
||||
variation: DeviceSecurityVariation.Unverified,
|
||||
}));
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,66 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<DeviceSecurityCard /> renders basic card 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Verified"
|
||||
>
|
||||
<div
|
||||
height="16"
|
||||
width="16"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Verified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
nice
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<DeviceSecurityCard /> renders with children 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Unverified"
|
||||
>
|
||||
<div
|
||||
height="16"
|
||||
width="16"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Verified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
nice
|
||||
</p>
|
||||
<div>
|
||||
hey
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -143,7 +143,7 @@ describe('<SessionManagerTab />', () => {
|
|||
expect(getByTestId(`device-tile-${alicesDevice.device_id}`)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders current session section', async () => {
|
||||
it('renders current session section with an unverified session', async () => {
|
||||
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
|
||||
const { getByTestId } = render(getComponent());
|
||||
|
||||
|
@ -154,6 +154,21 @@ describe('<SessionManagerTab />', () => {
|
|||
expect(getByTestId('current-session-section')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders current session section with a verified session', async () => {
|
||||
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice, alicesMobileDevice] });
|
||||
mockClient.getStoredDevice.mockImplementation(() => new DeviceInfo(alicesDevice.device_id));
|
||||
mockCrossSigningInfo.checkDeviceTrust
|
||||
.mockReturnValue(new DeviceTrustLevel(true, true, false, false));
|
||||
|
||||
const { getByTestId } = render(getComponent());
|
||||
|
||||
await act(async () => {
|
||||
await flushPromisesWithFakeTimers();
|
||||
});
|
||||
|
||||
expect(getByTestId('current-session-section')).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('does not render other sessions section when user has only one device', async () => {
|
||||
mockClient.getDevices.mockResolvedValue({ devices: [alicesDevice] });
|
||||
const { queryByTestId } = render(getComponent());
|
||||
|
@ -165,7 +180,7 @@ describe('<SessionManagerTab />', () => {
|
|||
expect(queryByTestId('other-sessions-section')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('renders other sessions section', async () => {
|
||||
it('renders other sessions section when user has more than one device', async () => {
|
||||
mockClient.getDevices.mockResolvedValue({
|
||||
devices: [alicesDevice, alicesOlderMobileDevice, alicesMobileDevice],
|
||||
});
|
||||
|
|
|
@ -1,6 +1,78 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<SessionManagerTab /> renders current session section 1`] = `
|
||||
exports[`<SessionManagerTab /> renders current session section with a verified session 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="current-session-section"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3 mx_SettingsSubsection_heading"
|
||||
>
|
||||
Current session
|
||||
</h3>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTile"
|
||||
data-testid="device-tile-alices_device"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTile_info"
|
||||
>
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
alices_device
|
||||
</h4>
|
||||
<div
|
||||
class="mx_DeviceTile_metadata"
|
||||
>
|
||||
<span
|
||||
data-testid="device-metadata-isVerified"
|
||||
>
|
||||
Verified
|
||||
</span>
|
||||
·
|
||||
·
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceTile_actions"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Verified"
|
||||
>
|
||||
<div
|
||||
height="16"
|
||||
width="16"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Verified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
This session is ready for secure messaging.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> renders current session section with an unverified session 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="current-session-section"
|
||||
|
@ -41,6 +113,33 @@ exports[`<SessionManagerTab /> renders current session section 1`] = `
|
|||
class="mx_DeviceTile_actions"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Unverified"
|
||||
>
|
||||
<div
|
||||
height="16"
|
||||
width="16"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Unverified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Verify or sign out from this session for best security and reliability.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|