/*
* 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');
});
});