Test display of qr code login section (#9456)

* Support for login + E2EE set up with QR

* Whitespace

* Padding

* Refactor of fetch

* Whitespace

* CSS whitespace

* Add link to MSC3906

* Handle incorrect typing in MatrixClientPeg.get()

* Use unstable class name

* fix: use unstable class name

* Use default fetch client instead

* Update to revised function name

* Refactor device manager panel and make it work with new sessions manager

* Lint fix

* Add missing interstitials and update wording

* Linting

* i18n

* Lint

* Use sensible sdk config name for fallback server

* Improve error handling for QR code generation

* Refactor feature availability logic

* Hide device manager panel if no options available

* Put sign in with QR behind lab setting

* Reduce scope of PR to just showing code on existing device

* i18n updates

* Handle null features

* Testing for LoginWithQRSection

* Refactor to handle UIA

* Imports

* Reduce diff complexity

* Remove unnecessary change

* Remove unused styles

* Support UIA

* Tidy up

* i18n

* Remove additional unused parts of flow

* Add extra instruction when showing QR code

* Add getVersions to server mocks

* Use proper colours for theme support

* Test cases

* Lint

* Remove obsolete snapshot

* Don't override error if already set

* Remove unused var

* Update src/components/views/settings/devices/LoginWithQRSection.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/auth/LoginWithQR.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/auth/LoginWithQR.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/auth/LoginWithQR.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/auth/LoginWithQR.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update src/components/views/auth/LoginWithQR.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Update res/css/views/auth/_LoginWithQR.pcss

Co-authored-by: Kerry <kerrya@element.io>

* Use spacing variables

* Remove debug

* Style + docs

* preventDefault

* Names of tests

* Fixes for js-sdk refactor

* Update snapshots to match test names

* Refactor labs config to make deployment simpler

* i18n

* Unused imports

* Typo

* Stateless component

* Whitespace

* Use context not MatrixClientPeg

* Add missing context

* Type updates to match js-sdk

* Wrap click handlers in useCallback

* Update src/components/views/settings/DevicesPanel.tsx

Co-authored-by: Travis Ralston <travisr@matrix.org>

* Wait for DOM update instead of timeout

* Add missing snapshot update from last commit

* Remove void keyword in favour of then() clauses

* test main paths in LoginWithQR

* test coverage for display of qr code section

* remove unused test props

Co-authored-by: Hugh Nimmo-Smith <hughns@matrix.org>
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: Travis Ralston <travisr@matrix.org>
pull/28788/head^2
Kerry 2022-10-19 17:11:42 +02:00 committed by GitHub
parent 8066b9ffbe
commit d5a4718d46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 2 deletions

View File

@ -370,7 +370,7 @@ export default class LoginWithQR extends React.Component<IProps, IState> {
} }
return ( return (
<div className="mx_LoginWithQR"> <div data-testid="login-with-qr" className="mx_LoginWithQR">
<div className={centreTitle ? "mx_LoginWithQR_centreTitle" : ""}> <div className={centreTitle ? "mx_LoginWithQR_centreTitle" : ""}>
{ backButton ? { backButton ?
<AccessibleButton <AccessibleButton

View File

@ -4,6 +4,7 @@ exports[`<LoginWithQR /> approves login and waits for new device 1`] = `
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="" class=""
@ -61,6 +62,7 @@ exports[`<LoginWithQR /> displays confirmation digits after connected to rendezv
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="" class=""
@ -122,6 +124,7 @@ exports[`<LoginWithQR /> displays error when approving login fails 1`] = `
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="mx_LoginWithQR_centreTitle" class="mx_LoginWithQR_centreTitle"
@ -168,6 +171,7 @@ exports[`<LoginWithQR /> displays qr code after it is created 1`] = `
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="" class=""
@ -232,6 +236,7 @@ exports[`<LoginWithQR /> displays unknown error if connection to rendezvous fail
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="mx_LoginWithQR_centreTitle" class="mx_LoginWithQR_centreTitle"
@ -278,6 +283,7 @@ exports[`<LoginWithQR /> no content in case of no support 1`] = `
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="mx_LoginWithQR_centreTitle" class="mx_LoginWithQR_centreTitle"
@ -324,6 +330,7 @@ exports[`<LoginWithQR /> renders spinner while generating code 1`] = `
<div> <div>
<div <div
class="mx_LoginWithQR" class="mx_LoginWithQR"
data-testid="login-with-qr"
> >
<div <div
class="" class=""

View File

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { render } from '@testing-library/react'; import { fireEvent, render } from '@testing-library/react';
import React from 'react'; import React from 'react';
import SecurityUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/SecurityUserSettingsTab"; import SecurityUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/SecurityUserSettingsTab";
@ -26,6 +26,7 @@ import {
mockClientMethodsCrypto, mockClientMethodsCrypto,
mockClientMethodsDevice, mockClientMethodsDevice,
mockPlatformPeg, mockPlatformPeg,
flushPromises,
} from '../../../../../test-utils'; } from '../../../../../test-utils';
describe('<SecurityUserSettingsTab />', () => { describe('<SecurityUserSettingsTab />', () => {
@ -42,6 +43,12 @@ describe('<SecurityUserSettingsTab />', () => {
...mockClientMethodsCrypto(), ...mockClientMethodsCrypto(),
getRooms: jest.fn().mockReturnValue([]), getRooms: jest.fn().mockReturnValue([]),
getIgnoredUsers: jest.fn(), getIgnoredUsers: jest.fn(),
getVersions: jest.fn().mockResolvedValue({
unstable_features: {
'org.matrix.msc3882': true,
'org.matrix.msc3886': true,
},
}),
}); });
const getComponent = () => const getComponent = () =>
@ -70,4 +77,34 @@ describe('<SecurityUserSettingsTab />', () => {
expect(queryByTestId('devices-section')).toBeFalsy(); expect(queryByTestId('devices-section')).toBeFalsy();
}); });
it('does not render qr code login section when disabled', () => {
settingsValueSpy.mockReturnValue(false);
const { queryByText } = render(getComponent());
expect(settingsValueSpy).toHaveBeenCalledWith('feature_qr_signin_reciprocate_show');
expect(queryByText('Sign in with QR code')).toBeFalsy();
});
it('renders qr code login section when enabled', async () => {
settingsValueSpy.mockImplementation(settingName => settingName === 'feature_qr_signin_reciprocate_show');
const { getByText } = render(getComponent());
// wait for versions call to settle
await flushPromises();
expect(getByText('Sign in with QR code')).toBeTruthy();
});
it('enters qr code login section when show QR code button clicked', async () => {
settingsValueSpy.mockImplementation(settingName => settingName === 'feature_qr_signin_reciprocate_show');
const { getByText, getByTestId } = render(getComponent());
// wait for versions call to settle
await flushPromises();
fireEvent.click(getByText('Show QR code'));
expect(getByTestId("login-with-qr")).toBeTruthy();
});
}); });

View File

@ -34,6 +34,7 @@ import {
import SessionManagerTab from '../../../../../../src/components/views/settings/tabs/user/SessionManagerTab'; import SessionManagerTab from '../../../../../../src/components/views/settings/tabs/user/SessionManagerTab';
import MatrixClientContext from '../../../../../../src/contexts/MatrixClientContext'; import MatrixClientContext from '../../../../../../src/contexts/MatrixClientContext';
import { import {
flushPromises,
flushPromisesWithFakeTimers, flushPromisesWithFakeTimers,
getMockClientWithEventEmitter, getMockClientWithEventEmitter,
mkPusher, mkPusher,
@ -47,6 +48,7 @@ import {
ExtendedDevice, ExtendedDevice,
} from '../../../../../../src/components/views/settings/devices/types'; } from '../../../../../../src/components/views/settings/devices/types';
import { INACTIVE_DEVICE_AGE_MS } from '../../../../../../src/components/views/settings/devices/filter'; import { INACTIVE_DEVICE_AGE_MS } from '../../../../../../src/components/views/settings/devices/filter';
import SettingsStore from '../../../../../../src/settings/SettingsStore';
mockPlatformPeg(); mockPlatformPeg();
@ -1142,4 +1144,50 @@ describe('<SessionManagerTab />', () => {
expect(checkbox.getAttribute('aria-checked')).toEqual("false"); expect(checkbox.getAttribute('aria-checked')).toEqual("false");
}); });
describe('QR code login', () => {
const settingsValueSpy = jest.spyOn(SettingsStore, 'getValue');
beforeEach(() => {
settingsValueSpy.mockClear().mockReturnValue(false);
// enable server support for qr login
mockClient.getVersions.mockResolvedValue({
versions: [],
unstable_features: {
'org.matrix.msc3882': true,
'org.matrix.msc3886': true,
},
});
});
it('does not render qr code login section when disabled', () => {
settingsValueSpy.mockReturnValue(false);
const { queryByText } = render(getComponent());
expect(settingsValueSpy).toHaveBeenCalledWith('feature_qr_signin_reciprocate_show');
expect(queryByText('Sign in with QR code')).toBeFalsy();
});
it('renders qr code login section when enabled', async () => {
settingsValueSpy.mockImplementation(settingName => settingName === 'feature_qr_signin_reciprocate_show');
const { getByText } = render(getComponent());
// wait for versions call to settle
await flushPromises();
expect(getByText('Sign in with QR code')).toBeTruthy();
});
it('enters qr code login section when show QR code button clicked', async () => {
settingsValueSpy.mockImplementation(settingName => settingName === 'feature_qr_signin_reciprocate_show');
const { getByText, getByTestId } = render(getComponent());
// wait for versions call to settle
await flushPromises();
fireEvent.click(getByText('Show QR code'));
expect(getByTestId("login-with-qr")).toBeTruthy();
});
});
}); });