* Fix flaky biometric authentication test Eliminates timing race conditions in SecurityManager test by using fixed timestamps instead of real Date.now() values. The test was failing inconsistently due to timing variations between test runs. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * use fake timers * revert changes --------- Co-authored-by: Claude <noreply@anthropic.com>
547 lines
27 KiB
TypeScript
547 lines
27 KiB
TypeScript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import Emm from '@mattermost/react-native-emm';
|
|
import {isRootedExperimentalAsync} from 'expo-device';
|
|
import {Alert, type AppStateStatus} from 'react-native';
|
|
|
|
import {switchToServer} from '@actions/app/server';
|
|
import {logout} from '@actions/remote/session';
|
|
import {Screens} from '@constants';
|
|
import {DEFAULT_LOCALE, getTranslations, t} from '@i18n';
|
|
import {getServerCredentials} from '@init/credentials';
|
|
import TestHelper from '@test/test_helper';
|
|
import {toMilliseconds} from '@utils/datetime';
|
|
import {logError} from '@utils/log';
|
|
|
|
import SecurityManager from '.';
|
|
|
|
jest.mock('@mattermost/react-native-emm', () => ({
|
|
isDeviceSecured: jest.fn(),
|
|
authenticate: jest.fn(),
|
|
openSecuritySettings: jest.fn(),
|
|
exitApp: jest.fn(),
|
|
enableBlurScreen: jest.fn(),
|
|
}));
|
|
|
|
jest.mock('expo-device', () => ({
|
|
isRootedExperimentalAsync: jest.fn(),
|
|
}));
|
|
jest.mock('@actions/app/server', () => ({switchToServer: jest.fn()}));
|
|
jest.mock('@actions/remote/session', () => ({logout: jest.fn()}));
|
|
jest.mock('@utils/datetime', () => ({toMilliseconds: jest.fn(() => 25000)}));
|
|
jest.mock('@utils/helpers', () => ({
|
|
isMainActivity: jest.fn(() => true),
|
|
isTablet: jest.fn(() => false),
|
|
}));
|
|
jest.mock('@utils/log', () => ({logError: jest.fn()}));
|
|
jest.mock('@init/managed_app', () => ({enabled: true, inAppPinCode: false}));
|
|
jest.mock('@init/credentials', () => ({getServerCredentials: jest.fn().mockResolvedValue({token: 'token'})}));
|
|
|
|
describe('SecurityManager', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
SecurityManager.initialized = false;
|
|
SecurityManager.serverConfig = {};
|
|
SecurityManager.activeServer = undefined;
|
|
});
|
|
|
|
describe('init', () => {
|
|
test('should initialize with servers', () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
};
|
|
SecurityManager.init(servers, 'server-1');
|
|
expect(SecurityManager.serverConfig['server-1']).toBeDefined();
|
|
expect(SecurityManager.activeServer).toBe('server-1');
|
|
});
|
|
|
|
test('should initialize with servers and set active server', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
'server-2': {SiteName: 'Server Two', MobileEnableBiometrics: 'false'},
|
|
};
|
|
await SecurityManager.init(servers, 'server-1');
|
|
expect(SecurityManager.serverConfig['server-1']).toBeDefined();
|
|
expect(SecurityManager.serverConfig['server-2']).toBeDefined();
|
|
expect(SecurityManager.activeServer).toBe('server-1');
|
|
});
|
|
|
|
test('should not reinitialize if already initialized', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
};
|
|
SecurityManager.initialized = true;
|
|
await SecurityManager.init(servers, 'server-1');
|
|
expect(SecurityManager.serverConfig['server-1']).toBeUndefined();
|
|
});
|
|
|
|
test('should set active server and authenticate if not jailbroken', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
};
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(isRootedExperimentalAsync).mockResolvedValue(false);
|
|
|
|
const isDeviceJailbrokenSpy = jest.spyOn(SecurityManager, 'isDeviceJailbroken');
|
|
const authenticateWithBiometricsIfNeededSpy = jest.spyOn(SecurityManager, 'authenticateWithBiometricsIfNeeded');
|
|
|
|
await SecurityManager.init(servers, 'server-1');
|
|
expect(SecurityManager.activeServer).toBe('server-1');
|
|
expect(isDeviceJailbrokenSpy).toHaveBeenCalledWith('server-1');
|
|
expect(authenticateWithBiometricsIfNeededSpy).toHaveBeenCalledWith('server-1');
|
|
});
|
|
|
|
test('should not authenticate if device is jailbroken', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true', MobileJailbreakProtection: 'true'},
|
|
};
|
|
jest.mocked(isRootedExperimentalAsync).mockResolvedValue(true);
|
|
await SecurityManager.init(servers, 'server-1');
|
|
expect(SecurityManager.activeServer).toBe('server-1');
|
|
expect(SecurityManager.isDeviceJailbroken).toHaveBeenCalledWith('server-1');
|
|
expect(SecurityManager.authenticateWithBiometricsIfNeeded).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('should not set active server if not provided', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
};
|
|
await SecurityManager.init(servers);
|
|
expect(SecurityManager.activeServer).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('addServer', () => {
|
|
test('should add server config with biometrics enabled', () => {
|
|
SecurityManager.addServer('server-1', {SiteName: 'Server One', MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
expect(SecurityManager.serverConfig['server-1']).toEqual({
|
|
siteName: 'Server One',
|
|
Biometrics: true,
|
|
JailbreakProtection: false,
|
|
PreventScreenCapture: false,
|
|
authenticated: false,
|
|
});
|
|
});
|
|
|
|
test('should add server config with jailbreak protection enabled', () => {
|
|
SecurityManager.addServer('server-2', {SiteName: 'Server Two', MobileJailbreakProtection: 'true'} as ClientConfig);
|
|
expect(SecurityManager.serverConfig['server-2']).toEqual({
|
|
siteName: 'Server Two',
|
|
Biometrics: false,
|
|
JailbreakProtection: true,
|
|
PreventScreenCapture: false,
|
|
authenticated: false,
|
|
});
|
|
});
|
|
|
|
test('should add server config with screen capture prevention enabled', () => {
|
|
SecurityManager.addServer('server-3', {SiteName: 'Server Three', MobilePreventScreenCapture: 'true'} as ClientConfig);
|
|
expect(SecurityManager.serverConfig['server-3']).toEqual({
|
|
siteName: 'Server Three',
|
|
Biometrics: false,
|
|
JailbreakProtection: false,
|
|
PreventScreenCapture: true,
|
|
authenticated: false,
|
|
});
|
|
});
|
|
|
|
test('should add server config with all features enabled', () => {
|
|
SecurityManager.addServer('server-4', {
|
|
SiteName: 'Server Four',
|
|
MobileEnableBiometrics: 'true',
|
|
MobileJailbreakProtection: 'true',
|
|
MobilePreventScreenCapture: 'true',
|
|
} as ClientConfig);
|
|
expect(SecurityManager.serverConfig['server-4']).toEqual({
|
|
siteName: 'Server Four',
|
|
Biometrics: true,
|
|
JailbreakProtection: true,
|
|
PreventScreenCapture: true,
|
|
authenticated: false,
|
|
});
|
|
});
|
|
|
|
test('should add server config with authenticated set to true', () => {
|
|
SecurityManager.addServer('server-5', {SiteName: 'Server Five'} as ClientConfig, true);
|
|
expect(SecurityManager.serverConfig['server-5']).toEqual({
|
|
siteName: 'Server Five',
|
|
Biometrics: false,
|
|
JailbreakProtection: false,
|
|
PreventScreenCapture: false,
|
|
authenticated: true,
|
|
});
|
|
});
|
|
|
|
test('should add server config without config', () => {
|
|
SecurityManager.addServer('server-6');
|
|
expect(SecurityManager.serverConfig['server-6']).toEqual({
|
|
siteName: undefined,
|
|
Biometrics: false,
|
|
JailbreakProtection: false,
|
|
PreventScreenCapture: false,
|
|
authenticated: false,
|
|
});
|
|
});
|
|
|
|
test('should update a server config previously added', () => {
|
|
SecurityManager.addServer('server-3', {SiteName: 'Server Three', MobilePreventScreenCapture: 'true'} as ClientConfig, true);
|
|
expect(SecurityManager.serverConfig['server-3']).toEqual({
|
|
siteName: 'Server Three',
|
|
Biometrics: false,
|
|
JailbreakProtection: false,
|
|
PreventScreenCapture: true,
|
|
authenticated: true,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('removeServer', () => {
|
|
test('should remove server config and active server', async () => {
|
|
const servers: Record<string, any> = {
|
|
'server-1': {SiteName: 'Server One', MobileEnableBiometrics: 'true'},
|
|
'server-2': {SiteName: 'Server Two', MobileEnableBiometrics: 'false'},
|
|
};
|
|
await SecurityManager.init(servers, 'server-1');
|
|
SecurityManager.removeServer('server-1');
|
|
expect(SecurityManager.serverConfig['server-1']).toBeUndefined();
|
|
expect(SecurityManager.activeServer).toBeUndefined();
|
|
expect(SecurityManager.initialized).toBe(false);
|
|
});
|
|
|
|
test('should remove server config', () => {
|
|
SecurityManager.addServer('server-3');
|
|
SecurityManager.removeServer('server-3');
|
|
expect(SecurityManager.serverConfig['server-3']).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('getServerConfig', () => {
|
|
test('should return server config', () => {
|
|
SecurityManager.addServer('server-4', {SiteName: 'Server Four'} as ClientConfig);
|
|
expect(SecurityManager.getServerConfig('server-4')?.siteName).toBe('Server Four');
|
|
});
|
|
|
|
test('should return undefined if server config does not exist', () => {
|
|
expect(SecurityManager.getServerConfig('server-5')).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('setActiveServer', () => {
|
|
test('should set active server and update lastAccessed', () => {
|
|
SecurityManager.addServer('server-5');
|
|
const before = Date.now();
|
|
SecurityManager.setActiveServer('server-5');
|
|
const after = Date.now();
|
|
expect(SecurityManager.activeServer).toBe('server-5');
|
|
expect(SecurityManager.serverConfig['server-5'].lastAccessed).toBeGreaterThanOrEqual(before);
|
|
expect(SecurityManager.serverConfig['server-5'].lastAccessed).toBeLessThanOrEqual(after);
|
|
});
|
|
|
|
test('should not set active server if server does not exist', () => {
|
|
SecurityManager.setActiveServer('server-6');
|
|
expect(SecurityManager.activeServer).toBeUndefined();
|
|
});
|
|
|
|
test('should update active server and lastAccessed if a different server is set', () => {
|
|
SecurityManager.addServer('server-7');
|
|
SecurityManager.addServer('server-8');
|
|
SecurityManager.setActiveServer('server-7');
|
|
const before = Date.now();
|
|
SecurityManager.setActiveServer('server-8');
|
|
const after = Date.now();
|
|
expect(SecurityManager.activeServer).toBe('server-8');
|
|
expect(SecurityManager.serverConfig['server-8'].lastAccessed).toBeGreaterThanOrEqual(before);
|
|
expect(SecurityManager.serverConfig['server-8'].lastAccessed).toBeLessThanOrEqual(after);
|
|
});
|
|
|
|
test('should not change active server or lastAccessed if the same server is set', async () => {
|
|
SecurityManager.addServer('server-9');
|
|
SecurityManager.setActiveServer('server-9');
|
|
const lastAccessed = SecurityManager.serverConfig['server-9'].lastAccessed;
|
|
SecurityManager.setActiveServer('server-9');
|
|
expect(SecurityManager.activeServer).toBe('server-9');
|
|
expect(SecurityManager.serverConfig['server-9'].lastAccessed).toBe(lastAccessed);
|
|
});
|
|
});
|
|
|
|
describe('isScreenCapturePrevented', () => {
|
|
test('should return true if screen capture prevention is enabled', () => {
|
|
SecurityManager.addServer('server-1', {SiteName: 'Server One', MobilePreventScreenCapture: 'true'} as ClientConfig);
|
|
expect(SecurityManager.isScreenCapturePrevented('server-1')).toBe(true);
|
|
});
|
|
|
|
test('should return false if screen capture prevention is disabled', () => {
|
|
SecurityManager.addServer('server-2', {SiteName: 'Server Two', MobilePreventScreenCapture: 'false'} as ClientConfig);
|
|
expect(SecurityManager.isScreenCapturePrevented('server-2')).toBe(false);
|
|
});
|
|
|
|
test('should return false if server configuration does not exist', () => {
|
|
expect(SecurityManager.isScreenCapturePrevented('server-3')).toBe(false);
|
|
});
|
|
|
|
test('should return false if PreventScreenCapture property is not set', () => {
|
|
SecurityManager.addServer('server-4', {SiteName: 'Server Four'} as ClientConfig);
|
|
expect(SecurityManager.isScreenCapturePrevented('server-4')).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('authenticateWithBiometricsIfNeeded', () => {
|
|
test('should handle biometric authentication if biometrics enabled and device secured', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(Emm.authenticate).mockResolvedValue(true);
|
|
SecurityManager.addServer('server-6', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-6')).resolves.toBe(true);
|
|
expect(Emm.isDeviceSecured).toHaveBeenCalled();
|
|
expect(Emm.authenticate).toHaveBeenCalled();
|
|
});
|
|
|
|
test('should not prompt for biometric authentication if biometrics enabled but device is not secured', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(false);
|
|
const showNotSecuredAlertSpy = jest.spyOn(SecurityManager, 'showNotSecuredAlert');
|
|
SecurityManager.addServer('server-6', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-6')).resolves.toBe(false);
|
|
expect(showNotSecuredAlertSpy).toHaveBeenCalled();
|
|
expect(Emm.isDeviceSecured).toHaveBeenCalled();
|
|
expect(Emm.authenticate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('should not attempt biometric authentication if biometrics not enabled', async () => {
|
|
SecurityManager.addServer('server-8', {MobileEnableBiometrics: 'false'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-8')).resolves.toBe(true);
|
|
expect(Emm.isDeviceSecured).not.toHaveBeenCalled();
|
|
expect(Emm.authenticate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('should resolve with true if biometric authentication succeeds', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(Emm.authenticate).mockResolvedValue(true);
|
|
SecurityManager.addServer('server-9', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-9')).resolves.toBe(true);
|
|
expect(Emm.isDeviceSecured).toHaveBeenCalled();
|
|
expect(Emm.authenticate).toHaveBeenCalled();
|
|
});
|
|
|
|
test('should log error and resolve with false if biometric authentication fails', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(Emm.authenticate).mockResolvedValue(false);
|
|
SecurityManager.addServer('server-10', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-10')).resolves.toBe(false);
|
|
expect(Emm.isDeviceSecured).toHaveBeenCalled();
|
|
expect(Emm.authenticate).toHaveBeenCalled();
|
|
expect(SecurityManager.getServerConfig('server-10')?.authenticated).toBe(false);
|
|
expect(logError).toHaveBeenCalled();
|
|
});
|
|
|
|
test('should log error and resolve with false if biometric authentication throws an error', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(Emm.authenticate).mockRejectedValue(new Error('Authorization cancelled'));
|
|
SecurityManager.addServer('server-11', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-11')).resolves.toBe(false);
|
|
expect(Emm.isDeviceSecured).toHaveBeenCalled();
|
|
expect(Emm.authenticate).toHaveBeenCalled();
|
|
expect(logError).toHaveBeenCalled();
|
|
});
|
|
|
|
test('should not attempt biometric authentication if server was previously authenticated within 5 mins', async () => {
|
|
// Mock toMilliseconds locally to return correct value for this test
|
|
const originalToMilliseconds = jest.requireActual('@utils/datetime').toMilliseconds;
|
|
jest.mocked(require('@utils/datetime').toMilliseconds).mockImplementation(originalToMilliseconds);
|
|
|
|
// Use a fixed timestamp instead of Date.now() to eliminate timing races
|
|
const fixedTime = 1672574400000; // Fixed timestamp: Jan 1, 2023 12:00:00 GMT
|
|
const oneMinuteAgo = fixedTime - (60 * 1000);
|
|
|
|
// Mock Date.now to return our fixed time
|
|
const originalDateNow = Date.now;
|
|
Date.now = jest.fn(() => fixedTime);
|
|
|
|
try {
|
|
SecurityManager.addServer('server-12', {MobileEnableBiometrics: 'true'} as ClientConfig, true);
|
|
SecurityManager.serverConfig['server-12'].lastAccessed = oneMinuteAgo;
|
|
await expect(SecurityManager.authenticateWithBiometricsIfNeeded('server-12')).resolves.toBe(true);
|
|
expect(Emm.isDeviceSecured).not.toHaveBeenCalled();
|
|
expect(Emm.authenticate).not.toHaveBeenCalled();
|
|
} finally {
|
|
// Restore original implementations
|
|
Date.now = originalDateNow;
|
|
jest.mocked(require('@utils/datetime').toMilliseconds).mockReturnValue(25000);
|
|
}
|
|
});
|
|
|
|
test('should not attempt biometric authentication if server was previously failed authentication even though lastAccess is less than 5 mins', async () => {
|
|
SecurityManager.addServer('server-13', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.serverConfig['server-13'].authenticated = false;
|
|
SecurityManager.serverConfig['server-13'].lastAccessed = Date.now() - toMilliseconds({minutes: 1});
|
|
await SecurityManager.authenticateWithBiometricsIfNeeded('server-13');
|
|
expect(SecurityManager.serverConfig['server-13'].authenticated).toBe(false);
|
|
await expect(Emm.authenticate).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('onAppStateChange', () => {
|
|
test('should handle app state changes', async () => {
|
|
SecurityManager.addServer('server-8', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.setActiveServer('server-8');
|
|
await SecurityManager.onAppStateChange('background' as AppStateStatus);
|
|
expect(SecurityManager.backgroundSince).toBeGreaterThan(0);
|
|
await SecurityManager.onAppStateChange('active' as AppStateStatus);
|
|
expect(SecurityManager.backgroundSince).toBe(0);
|
|
});
|
|
|
|
test('should call biometric authentication app state changes', async () => {
|
|
const authenticateWithBiometrics = jest.spyOn(SecurityManager, 'authenticateWithBiometrics');
|
|
jest.mocked(isRootedExperimentalAsync).mockResolvedValue(false);
|
|
SecurityManager.addServer('server-8', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.setActiveServer('server-8');
|
|
SecurityManager.onAppStateChange('background' as AppStateStatus);
|
|
SecurityManager.backgroundSince = Date.now() - toMilliseconds({minutes: 5, seconds: 1});
|
|
SecurityManager.onAppStateChange('active' as AppStateStatus);
|
|
await TestHelper.wait(300);
|
|
expect(authenticateWithBiometrics).toHaveBeenCalledWith('server-8');
|
|
});
|
|
});
|
|
|
|
describe('showNotSecuredAlert', () => {
|
|
test('should show not secured alert', async () => {
|
|
SecurityManager.addServer('server-9');
|
|
SecurityManager.showNotSecuredAlert('server-9', 'Test Site', getTranslations(DEFAULT_LOCALE));
|
|
await TestHelper.wait(300);
|
|
expect(Alert.alert).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('goToPreviousServer', () => {
|
|
afterAll(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
test('should switch to previous server', async () => {
|
|
jest.mocked(Emm.isDeviceSecured).mockResolvedValue(true);
|
|
jest.mocked(Emm.authenticate).mockResolvedValue(true);
|
|
jest.mocked(switchToServer).mockImplementation((serverUrl: string) => {
|
|
SecurityManager.setActiveServer(serverUrl);
|
|
return Promise.resolve();
|
|
});
|
|
SecurityManager.activeServer = undefined;
|
|
SecurityManager.addServer('server-10', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.setActiveServer('server-10');
|
|
SecurityManager.addServer('server-11', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.setActiveServer('server-11');
|
|
await SecurityManager.goToPreviousServer(['server-10', 'server-11']);
|
|
expect(switchToServer).toHaveBeenCalledWith('server-10', expect.anything(), expect.anything());
|
|
expect(SecurityManager.activeServer).toBe('server-10');
|
|
});
|
|
});
|
|
|
|
describe('buildAlertOptions', () => {
|
|
test('should build alert options with logout', async () => {
|
|
jest.mocked(getServerCredentials).mockResolvedValue({token: 'some-token', serverUrl: 'server-12', userId: 'me'});
|
|
SecurityManager.addServer('server-12', {MobileEnableBiometrics: 'true'} as ClientConfig);
|
|
SecurityManager.setActiveServer('server-12');
|
|
const translations = getTranslations(DEFAULT_LOCALE);
|
|
const buttons = await SecurityManager.buildAlertOptions('server-12', translations);
|
|
expect(buttons.length).toBeGreaterThan(0);
|
|
const logoutButton = buttons.find((button) => button.text === translations[t('mobile.managed.logout')]);
|
|
expect(logoutButton).toBeDefined();
|
|
logoutButton?.onPress?.();
|
|
expect(logout).toHaveBeenCalledWith('server-12', undefined);
|
|
});
|
|
});
|
|
|
|
describe('showDeviceNotTrustedAlert', () => {
|
|
test('should show device not trusted alert', async () => {
|
|
const server = 'server-13';
|
|
const siteName = 'Site Name';
|
|
const translations = getTranslations(DEFAULT_LOCALE);
|
|
|
|
await SecurityManager.showDeviceNotTrustedAlert(server, siteName, translations);
|
|
|
|
expect(Alert.alert).toHaveBeenCalledWith(
|
|
translations[t('mobile.managed.blocked_by')].replace('{vendor}', siteName),
|
|
translations[t('mobile.managed.jailbreak')].replace('{vendor}', siteName),
|
|
expect.any(Array),
|
|
{cancelable: false},
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('showBiometricFailureAlert', () => {
|
|
test('should show biometric failure alert', async () => {
|
|
const server = 'server-14';
|
|
const siteName = 'Site Name';
|
|
const translations = getTranslations(DEFAULT_LOCALE);
|
|
|
|
await SecurityManager.showBiometricFailureAlert(server, false, siteName, translations);
|
|
|
|
expect(Alert.alert).toHaveBeenCalledWith(
|
|
translations[t('mobile.managed.blocked_by')].replace('{vendor}', siteName),
|
|
translations[t('mobile.managed.biometric_failed')],
|
|
expect.any(Array),
|
|
{cancelable: false},
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('isDeviceJailbroken', () => {
|
|
test('should check if device is jailbroken', async () => {
|
|
const server = 'server-15';
|
|
const siteName = 'Site Name';
|
|
SecurityManager.addServer(server, {MobileJailbreakProtection: 'true'} as ClientConfig);
|
|
jest.mocked(isRootedExperimentalAsync).mockResolvedValue(true);
|
|
const translations = getTranslations(DEFAULT_LOCALE);
|
|
|
|
const result = await SecurityManager.isDeviceJailbroken(server, siteName);
|
|
expect(result).toBe(true);
|
|
await TestHelper.wait(300);
|
|
expect(Alert.alert).toHaveBeenCalledWith(
|
|
translations[t('mobile.managed.blocked_by')].replace('{vendor}', siteName),
|
|
translations[t('mobile.managed.jailbreak')].replace('{vendor}', siteName),
|
|
expect.any(Array),
|
|
{cancelable: false},
|
|
);
|
|
});
|
|
|
|
test('should return false if device is not jailbroken', async () => {
|
|
const server = 'server-16';
|
|
const siteName = 'Site Name';
|
|
SecurityManager.addServer(server, {MobileJailbreakProtection: 'true'} as ClientConfig);
|
|
jest.mocked(isRootedExperimentalAsync).mockResolvedValue(false);
|
|
|
|
const result = await SecurityManager.isDeviceJailbroken(server, siteName);
|
|
|
|
expect(result).toBe(false);
|
|
expect(Alert.alert).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('getShieldScreenId', () => {
|
|
test('should return the name of the screen shielded if prevent screen capture is enabled', () => {
|
|
SecurityManager.addServer('server-2', {MobilePreventScreenCapture: 'true'} as ClientConfig);
|
|
SecurityManager.activeServer = 'server-2';
|
|
expect(SecurityManager.getShieldScreenId(Screens.CHANNEL)).toBe(`${Screens.CHANNEL}.screen.shielded`);
|
|
});
|
|
|
|
test('should return the name of the screen without shielded if active server is different', () => {
|
|
SecurityManager.addServer('server-2', {MobilePreventScreenCapture: 'true'} as ClientConfig);
|
|
SecurityManager.activeServer = 'server-1';
|
|
expect(SecurityManager.getShieldScreenId(Screens.CHANNEL)).toBe(`${Screens.CHANNEL}.screen`);
|
|
});
|
|
|
|
test('should return the name of the screen shielded if prevent screen capture is disabled', () => {
|
|
SecurityManager.addServer('server-2', {MobilePreventScreenCapture: 'false'} as ClientConfig);
|
|
expect(SecurityManager.getShieldScreenId(Screens.CHANNEL)).toBe(`${Screens.CHANNEL}.screen`);
|
|
});
|
|
|
|
test('should return the name of the screen shielded if prevent screen capture is disabled but forced', () => {
|
|
SecurityManager.addServer('server-2', {MobilePreventScreenCapture: 'false'} as ClientConfig);
|
|
expect(SecurityManager.getShieldScreenId(Screens.CHANNEL, true)).toBe(`${Screens.CHANNEL}.screen.shielded`);
|
|
});
|
|
|
|
test('should return the name of the screen as shielded but skip', () => {
|
|
SecurityManager.addServer('server-2', {MobilePreventScreenCapture: 'true'} as ClientConfig);
|
|
SecurityManager.activeServer = 'server-2';
|
|
expect(SecurityManager.getShieldScreenId(Screens.CHANNEL, false, true)).toBe(`${Screens.CHANNEL}.screen.skip.shielded`);
|
|
});
|
|
});
|
|
});
|