From d5a4718d461b7c60b571914217d8a9425da3af1e Mon Sep 17 00:00:00 2001 From: Kerry <kerrya@element.io> Date: Wed, 19 Oct 2022 17:11:42 +0200 Subject: [PATCH] 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> --- src/components/views/auth/LoginWithQR.tsx | 2 +- .../__snapshots__/LoginWithQR-test.tsx.snap | 7 +++ .../user/SecurityUserSettingsTab-test.tsx | 39 ++++++++++++++- .../tabs/user/SessionManagerTab-test.tsx | 48 +++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/components/views/auth/LoginWithQR.tsx b/src/components/views/auth/LoginWithQR.tsx index f95e618cc5..3d3f76be95 100644 --- a/src/components/views/auth/LoginWithQR.tsx +++ b/src/components/views/auth/LoginWithQR.tsx @@ -370,7 +370,7 @@ export default class LoginWithQR extends React.Component<IProps, IState> { } return ( - <div className="mx_LoginWithQR"> + <div data-testid="login-with-qr" className="mx_LoginWithQR"> <div className={centreTitle ? "mx_LoginWithQR_centreTitle" : ""}> { backButton ? <AccessibleButton diff --git a/test/components/views/settings/devices/__snapshots__/LoginWithQR-test.tsx.snap b/test/components/views/settings/devices/__snapshots__/LoginWithQR-test.tsx.snap index 91fe73abf4..b851a2c686 100644 --- a/test/components/views/settings/devices/__snapshots__/LoginWithQR-test.tsx.snap +++ b/test/components/views/settings/devices/__snapshots__/LoginWithQR-test.tsx.snap @@ -4,6 +4,7 @@ exports[`<LoginWithQR /> approves login and waits for new device 1`] = ` <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="" @@ -61,6 +62,7 @@ exports[`<LoginWithQR /> displays confirmation digits after connected to rendezv <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="" @@ -122,6 +124,7 @@ exports[`<LoginWithQR /> displays error when approving login fails 1`] = ` <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="mx_LoginWithQR_centreTitle" @@ -168,6 +171,7 @@ exports[`<LoginWithQR /> displays qr code after it is created 1`] = ` <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="" @@ -232,6 +236,7 @@ exports[`<LoginWithQR /> displays unknown error if connection to rendezvous fail <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="mx_LoginWithQR_centreTitle" @@ -278,6 +283,7 @@ exports[`<LoginWithQR /> no content in case of no support 1`] = ` <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="mx_LoginWithQR_centreTitle" @@ -324,6 +330,7 @@ exports[`<LoginWithQR /> renders spinner while generating code 1`] = ` <div> <div class="mx_LoginWithQR" + data-testid="login-with-qr" > <div class="" diff --git a/test/components/views/settings/tabs/user/SecurityUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/SecurityUserSettingsTab-test.tsx index 3497f2f161..3fc250facc 100644 --- a/test/components/views/settings/tabs/user/SecurityUserSettingsTab-test.tsx +++ b/test/components/views/settings/tabs/user/SecurityUserSettingsTab-test.tsx @@ -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 limitations under the License. */ -import { render } from '@testing-library/react'; +import { fireEvent, render } from '@testing-library/react'; import React from 'react'; import SecurityUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/SecurityUserSettingsTab"; @@ -26,6 +26,7 @@ import { mockClientMethodsCrypto, mockClientMethodsDevice, mockPlatformPeg, + flushPromises, } from '../../../../../test-utils'; describe('<SecurityUserSettingsTab />', () => { @@ -42,6 +43,12 @@ describe('<SecurityUserSettingsTab />', () => { ...mockClientMethodsCrypto(), getRooms: jest.fn().mockReturnValue([]), getIgnoredUsers: jest.fn(), + getVersions: jest.fn().mockResolvedValue({ + unstable_features: { + 'org.matrix.msc3882': true, + 'org.matrix.msc3886': true, + }, + }), }); const getComponent = () => @@ -70,4 +77,34 @@ describe('<SecurityUserSettingsTab />', () => { 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(); + }); }); diff --git a/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx b/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx index 7826b3cc80..e9dd352903 100644 --- a/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx +++ b/test/components/views/settings/tabs/user/SessionManagerTab-test.tsx @@ -34,6 +34,7 @@ import { import SessionManagerTab from '../../../../../../src/components/views/settings/tabs/user/SessionManagerTab'; import MatrixClientContext from '../../../../../../src/contexts/MatrixClientContext'; import { + flushPromises, flushPromisesWithFakeTimers, getMockClientWithEventEmitter, mkPusher, @@ -47,6 +48,7 @@ import { ExtendedDevice, } from '../../../../../../src/components/views/settings/devices/types'; import { INACTIVE_DEVICE_AGE_MS } from '../../../../../../src/components/views/settings/devices/filter'; +import SettingsStore from '../../../../../../src/settings/SettingsStore'; mockPlatformPeg(); @@ -1142,4 +1144,50 @@ describe('<SessionManagerTab />', () => { 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(); + }); + }); });