// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import path from 'path'; import {app, session} from 'electron'; import Config from 'common/config'; import parseArgs from 'main/ParseArgs'; import ViewManager from 'main/views/viewManager'; import {initialize} from './initialize'; import {clearAppCache, getDeeplinkingURL, wasUpdated} from './utils'; jest.mock('fs', () => ({ accessSync: jest.fn(), existsSync: jest.fn().mockReturnValue(false), mkdirSync: jest.fn(), readFile: jest.fn(), readFileSync: jest.fn().mockImplementation((text) => text), unlinkSync: jest.fn(), writeFile: jest.fn(), writeFileSync: jest.fn(), })); jest.mock('path', () => { const original = jest.requireActual('path'); return { ...original, dirname: jest.fn().mockImplementation((p) => p), resolve: jest.fn(), }; }); jest.mock('electron', () => ({ app: { on: jest.fn(), handle: jest.fn(), exit: jest.fn(), getPath: jest.fn(), setPath: jest.fn(), disableHardwareAcceleration: jest.fn(), enableSandbox: jest.fn(), requestSingleInstanceLock: jest.fn(), setAsDefaultProtocolClient: jest.fn(), setAppUserModelId: jest.fn(), getVersion: jest.fn(), whenReady: jest.fn(), getLocale: jest.fn(), getLocaleCountryCode: jest.fn(), }, ipcMain: { on: jest.fn(), handle: jest.fn(), emit: jest.fn(), removeHandler: jest.fn(), removeListener: jest.fn(), }, nativeTheme: { on: jest.fn(), }, screen: { on: jest.fn(), }, session: { defaultSession: { webRequest: { onHeadersReceived: jest.fn(), }, setSpellCheckerDictionaryDownloadURL: jest.fn(), setPermissionRequestHandler: jest.fn(), on: jest.fn(), }, }, protocol: { registerSchemesAsPrivileged: jest.fn(), handle: jest.fn(), }, })); jest.mock('main/i18nManager', () => ({ localizeMessage: jest.fn(), setLocale: jest.fn(), })); jest.mock('electron-extension-installer', () => { return () => ({ REACT_DEVELOPER_TOOLS: 'react-developer-tools', }); }); const isDev = false; jest.mock('electron-is-dev', () => isDev); jest.mock('../../../electron-builder.json', () => ([ { name: 'Mattermost', schemes: [ 'mattermost', ], }, ])); jest.mock('app/serverViewState', () => ({ init: jest.fn(), })); jest.mock('common/config', () => ({ once: jest.fn(), on: jest.fn(), init: jest.fn(), initRegistry: jest.fn(), })); jest.mock('main/allowProtocolDialog', () => ({ init: jest.fn(), })); jest.mock('main/app/app', () => ({})); jest.mock('main/app/config', () => ({ handleConfigUpdate: jest.fn(), handleUpdateTheme: jest.fn(), })); jest.mock('main/app/intercom', () => ({ handleMainWindowIsShown: jest.fn(), })); jest.mock('main/app/utils', () => ({ clearAppCache: jest.fn(), getDeeplinkingURL: jest.fn(), handleUpdateMenuEvent: jest.fn(), shouldShowTrayIcon: jest.fn(), updateSpellCheckerLocales: jest.fn(), wasUpdated: jest.fn(), initCookieManager: jest.fn(), updateServerInfos: jest.fn(), })); jest.mock('common/appState', () => ({ on: jest.fn(), })); jest.mock('main/AppVersionManager', () => ({})); jest.mock('main/authManager', () => ({})); jest.mock('main/AutoLauncher', () => ({ upgradeAutoLaunch: jest.fn(), })); jest.mock('main/autoUpdater', () => ({})); jest.mock('main/badge', () => ({ setupBadge: jest.fn(), })); jest.mock('main/certificateManager', () => ({})); jest.mock('main/CriticalErrorHandler', () => ({ init: jest.fn(), })); jest.mock('main/notifications', () => ({ displayDownloadCompleted: jest.fn(), getDoNotDisturb: jest.fn(), })); jest.mock('main/ParseArgs', () => jest.fn()); jest.mock('common/servers/serverManager', () => ({ reloadFromConfig: jest.fn(), getAllServers: jest.fn(), on: jest.fn(), })); jest.mock('main/tray/tray', () => ({ refreshImages: jest.fn(), setup: jest.fn(), })); jest.mock('main/trustedOrigins', () => ({ load: jest.fn(), })); jest.mock('main/UserActivityMonitor', () => ({ on: jest.fn(), startMonitoring: jest.fn(), })); jest.mock('main/windows/callsWidgetWindow', () => ({})); jest.mock('main/views/viewManager', () => ({ getViewByWebContentsId: jest.fn(), handleDeepLink: jest.fn(), })); jest.mock('main/windows/mainWindow', () => ({ get: jest.fn(), show: jest.fn(), sendToRenderer: jest.fn(), })); const originalProcess = process; describe('main/app/initialize', () => { beforeAll(() => { global.process = { ...originalProcess, on: jest.fn(), chdir: jest.fn(), cwd: jest.fn().mockImplementation((text) => text), }; }); beforeEach(() => { parseArgs.mockReturnValue({}); Config.once.mockImplementation((event, cb) => { if (event === 'update') { cb(); } }); Config.data = {}; app.whenReady.mockResolvedValue(); app.requestSingleInstanceLock.mockReturnValue(true); app.getPath.mockImplementation((p) => `/basedir/${p}`); }); afterEach(() => { jest.resetAllMocks(); delete Config.data; }); afterAll(() => { global.process = originalProcess; }); it('should initialize without errors', async () => { await initialize(); }); describe('initializeArgs', () => { it('should set datadir when specified', async () => { path.resolve.mockImplementation((p) => `/basedir${p}`); parseArgs.mockReturnValue({ dataDir: '/some/dir', }); await initialize(); expect(app.setPath).toHaveBeenCalledWith('userData', '/basedir/some/dir'); }); }); describe('initializeConfig', () => { it('should disable hardware acceleration when specified', async () => { Config.enableHardwareAcceleration = false; await initialize(); expect(app.disableHardwareAcceleration).toHaveBeenCalled(); }); }); describe('initializeBeforeAppReady', () => { it('should exit the app when single instance lock fails', () => { app.requestSingleInstanceLock.mockReturnValue(false); }); }); describe('initializeAfterAppReady', () => { if (process.platform !== 'darwin') { it('should set spell checker URL if applicable', async () => { Config.spellCheckerURL = 'http://server-1.com'; await initialize(); expect(session.defaultSession.setSpellCheckerDictionaryDownloadURL).toHaveBeenCalledWith('http://server-1.com/'); }); } it('should clear app cache if last version opened was older', async () => { wasUpdated.mockReturnValue(true); await initialize(); expect(clearAppCache).toHaveBeenCalled(); }); it('should perform deeplink on win32', async () => { getDeeplinkingURL.mockReturnValue('mattermost://server-1.com'); const originalPlatform = process.platform; Object.defineProperty(process, 'argv', { value: ['mattermost', 'mattermost://server-1.com'], }); Object.defineProperty(process, 'platform', { value: 'win32', }); await initialize(); Object.defineProperty(process, 'platform', { value: originalPlatform, }); expect(ViewManager.handleDeepLink).toHaveBeenCalledWith('mattermost://server-1.com'); }); }); });