/* * Wire * Copyright (C) 2019 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import {act, render} from '@testing-library/react'; import {FeatureStatus} from '@wireapp/api-client/lib/team/feature/'; import {amplify} from 'amplify'; import ko from 'knockout'; import {WebAppEvents} from '@wireapp/webapp-events'; import {createUuid} from 'Util/uuid'; import {AppLock, APPLOCK_STATE} from './AppLock'; import type {ClientRepository} from '../../client'; import {TeamState} from '../../team/TeamState'; import {AppLockRepository} from '../../user/AppLockRepository'; import {AppLockState} from '../../user/AppLockState'; import {UserState} from '../../user/UserState'; // https://github.com/jedisct1/libsodium.js/issues/235 jest.mock('libsodium-wrappers', () => ({ crypto_pwhash_str: (value: string) => value, crypto_pwhash_str_verify: (value1: string, value2: string) => value1 === value2, ready: Promise.resolve, })); const clientRepository = {} as unknown as ClientRepository; const createTeamState = ({ status = 'enabled', enforceAppLock = false, inactivityTimeoutSecs = 10, }: { enforceAppLock?: boolean; inactivityTimeoutSecs?: number; status?: string; } = {}) => { const teamState = new TeamState(); jest.spyOn(teamState, 'isTeam').mockImplementation(ko.pureComputed(() => true)); const teamFeatures = { applock: { config: { enforceAppLock, inactivityTimeoutSecs, }, status, }, }; jest.spyOn(teamState, 'teamFeatures').mockImplementation(ko.observable(teamFeatures)); return teamState; }; const createAppLockState = (teamState?: TeamState) => { teamState = teamState ?? createTeamState(); const appLockState = new AppLockState(teamState); return appLockState; }; const createAppLockRepository = (appLockState?: AppLockState) => { const userState = new UserState(); appLockState = appLockState ?? createAppLockState(); jest.spyOn(userState, 'self').mockImplementation(ko.observable({id: createUuid()})); const appLockRepository = new AppLockRepository(userState, appLockState); return appLockRepository; }; describe('AppLock', () => { describe('disabled feature', () => { it('does not shows up if applock is disabled', () => { const appLockState = createAppLockState(createTeamState({status: FeatureStatus.DISABLED})); const appLockRepository = createAppLockRepository(appLockState); const props = { appLockRepository, appLockState, clientRepository, }; const {queryByTestId} = render(); const appLockModal = queryByTestId('applock-modal'); expect(appLockModal).toBe(null); }); }); describe('modal state', () => { it('shows locked state when it the passphrase is set and app lock is enabled', () => { const appLockState = createAppLockState(); const appLockRepository = createAppLockRepository(appLockState); appLockState.hasPassphrase(true); appLockState.isActivatedInPreferences(true); jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('div')); const props = { appLockRepository, appLockState, clientRepository, }; const {getByTestId} = render(); const appLockModalBody = getByTestId('applock-modal-body'); expect(appLockModalBody.getAttribute('data-uie-value')).toEqual(APPLOCK_STATE.LOCKED); }); it('shows setup state when there is no passphrase is set and app lock is enabled', () => { const appLockState = createAppLockState(); const appLockRepository = createAppLockRepository(appLockState); appLockState.hasPassphrase(false); appLockState.isActivatedInPreferences(true); jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('div')); const props = { appLockRepository, appLockState, clientRepository, }; const {getByTestId} = render(); act(() => { amplify.publish(WebAppEvents.PREFERENCES.CHANGE_APP_LOCK_PASSPHRASE); }); const appLockModalBody = getByTestId('applock-modal-body'); expect(appLockModalBody.getAttribute('data-uie-value')).toEqual(APPLOCK_STATE.SETUP); }); it('shows setup state when there is no passphrase is set and enforced is enabled', () => { const appLockState = createAppLockState(createTeamState({enforceAppLock: true, status: 'enabled'})); const appLockRepository = createAppLockRepository(appLockState); appLockState.hasPassphrase(false); jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('div')); const props = { appLockRepository, appLockState, clientRepository, }; const {getByTestId} = render(); act(() => { amplify.publish(WebAppEvents.PREFERENCES.CHANGE_APP_LOCK_PASSPHRASE); }); const appLockModalBody = getByTestId('applock-modal-body'); expect(appLockModalBody.getAttribute('data-uie-value')).toEqual(APPLOCK_STATE.SETUP); }); }); it('shows the locked modal on start if timeout is set as flag and a code is stored', async () => { const appLockState = createAppLockState(); const appLockRepository = createAppLockRepository(appLockState); appLockState.hasPassphrase(true); appLockState.isActivatedInPreferences(true); jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('div')); const props = { appLockRepository, appLockState, clientRepository, }; const {getByTestId} = render(); const appLockModal = getByTestId('applock-modal'); expect(window.getComputedStyle(appLockModal).getPropertyValue('display')).toBe('flex'); }); });