
* Rename MattermostTeam -> UniqueServer, MattermostTab -> UniqueView * Rename 'team' to 'server' * Some further cleanup * Rename weirdly named function * Rename 'tab' to 'view' in most instances * Fix i18n * PR feedback
183 lines
7.4 KiB
JavaScript
183 lines
7.4 KiB
JavaScript
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import {app, dialog} from 'electron';
|
|
|
|
import CertificateStore from 'main/certificateStore';
|
|
import MainWindow from 'main/windows/mainWindow';
|
|
import ViewManager from 'main/views/viewManager';
|
|
|
|
import {handleAppWillFinishLaunching, handleAppCertificateError, certificateErrorCallbacks} from 'main/app/app';
|
|
import {getDeeplinkingURL, openDeepLink} from 'main/app/utils';
|
|
|
|
jest.mock('electron', () => ({
|
|
app: {
|
|
on: jest.fn(),
|
|
once: jest.fn(),
|
|
isReady: jest.fn(),
|
|
},
|
|
dialog: {
|
|
showMessageBox: jest.fn(),
|
|
},
|
|
}));
|
|
|
|
jest.mock('main/app/utils', () => ({
|
|
getDeeplinkingURL: jest.fn(),
|
|
openDeepLink: jest.fn(),
|
|
}));
|
|
jest.mock('main/autoUpdater', () => ({}));
|
|
|
|
jest.mock('main/certificateStore', () => ({
|
|
isExplicitlyUntrusted: jest.fn(),
|
|
isTrusted: jest.fn(),
|
|
isExisting: jest.fn(),
|
|
add: jest.fn(),
|
|
save: jest.fn(),
|
|
}));
|
|
jest.mock('main/i18nManager', () => ({
|
|
localizeMessage: jest.fn(),
|
|
}));
|
|
jest.mock('main/tray/tray', () => ({}));
|
|
jest.mock('main/windows/mainWindow', () => ({
|
|
get: jest.fn(),
|
|
show: jest.fn(),
|
|
}));
|
|
jest.mock('main/views/viewManager', () => ({
|
|
getView: jest.fn(),
|
|
getViewByWebContentsId: jest.fn(),
|
|
}));
|
|
|
|
describe('main/app/app', () => {
|
|
describe('handleAppWillFinishLaunching', () => {
|
|
const deepLinkURL = 'mattermost://server-1.com';
|
|
const testURL = 'http://server-1.com';
|
|
|
|
beforeEach(() => {
|
|
app.on.mockImplementation((event, cb) => {
|
|
if (event === 'open-url') {
|
|
cb({preventDefault: jest.fn()}, deepLinkURL);
|
|
}
|
|
});
|
|
getDeeplinkingURL.mockReturnValue(testURL);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.resetAllMocks();
|
|
});
|
|
|
|
it('should open deep link if app is ready', () => {
|
|
app.isReady.mockReturnValue(true);
|
|
handleAppWillFinishLaunching();
|
|
expect(openDeepLink).toHaveBeenCalledWith(testURL);
|
|
});
|
|
|
|
it('should wait until app is ready to open deep link', () => {
|
|
let callback;
|
|
app.once.mockImplementation((event, cb) => {
|
|
if (event === 'ready') {
|
|
callback = cb;
|
|
}
|
|
});
|
|
app.isReady.mockReturnValue(false);
|
|
handleAppWillFinishLaunching();
|
|
expect(openDeepLink).not.toHaveBeenCalled();
|
|
callback({preventDefault: jest.fn()}, deepLinkURL);
|
|
expect(openDeepLink).toHaveBeenCalledWith(testURL);
|
|
});
|
|
});
|
|
|
|
describe('handleAppCertificateError', () => {
|
|
const testURL = 'http://server-1.com';
|
|
const callback = jest.fn();
|
|
const event = {preventDefault: jest.fn()};
|
|
const webContents = {loadURL: jest.fn()};
|
|
const mainWindow = {};
|
|
const promise = Promise.resolve({});
|
|
const certificate = {};
|
|
const view = {
|
|
view: {
|
|
server: {
|
|
name: 'test-server',
|
|
url: new URL(testURL),
|
|
},
|
|
},
|
|
load: jest.fn(),
|
|
};
|
|
|
|
beforeEach(() => {
|
|
MainWindow.get.mockReturnValue(mainWindow);
|
|
ViewManager.getViewByWebContentsId.mockReturnValue(view);
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.resetAllMocks();
|
|
certificateErrorCallbacks.clear();
|
|
dialog.showMessageBox.mockReturnValue(promise);
|
|
});
|
|
|
|
it('should not trust if explicitly untrusted by CertificateStore', () => {
|
|
CertificateStore.isExplicitlyUntrusted.mockReturnValue(true);
|
|
handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(event.preventDefault).toHaveBeenCalled();
|
|
expect(callback).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it('should trust if trusted by CertificateStore', () => {
|
|
CertificateStore.isExplicitlyUntrusted.mockReturnValue(false);
|
|
CertificateStore.isTrusted.mockReturnValue(true);
|
|
handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(event.preventDefault).toHaveBeenCalled();
|
|
expect(callback).toHaveBeenCalledWith(true);
|
|
});
|
|
|
|
it('should ignore and untrust when the origin of the certificate does not match the server URL', () => {
|
|
handleAppCertificateError(event, webContents, 'http://a-different-url.com', 'error-1', certificate, callback);
|
|
expect(callback).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
it('should not show additional dialogs if certificate error has already been logged', () => {
|
|
certificateErrorCallbacks.set('http://server-1.com:error-1', callback);
|
|
handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(dialog.showMessageBox).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should set callback if one is not already set', () => {
|
|
handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(certificateErrorCallbacks.has('http://server-1.com:error-1')).toBe(true);
|
|
});
|
|
|
|
it('should remove callback and not add certificate if user selects Cancel', async () => {
|
|
dialog.showMessageBox.mockResolvedValue({response: 1});
|
|
await handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(callback).toHaveBeenCalledWith(false);
|
|
expect(certificateErrorCallbacks.has('http://server-1.com:error-1')).toBe(false);
|
|
expect(CertificateStore.add).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should remove callback and add certificate if user selects More Details and Trust', async () => {
|
|
dialog.showMessageBox.mockResolvedValue({response: 0});
|
|
await handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(callback).toHaveBeenCalledWith(true);
|
|
expect(certificateErrorCallbacks.has('http://server-1.com:error-1')).toBe(false);
|
|
expect(CertificateStore.add).toHaveBeenCalledWith(new URL('http://server-1.com'), certificate);
|
|
expect(CertificateStore.save).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should load URL using MattermostBrowserView when trusting certificate', async () => {
|
|
dialog.showMessageBox.mockResolvedValue({response: 0});
|
|
await handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(callback).toHaveBeenCalledWith(true);
|
|
expect(view.load).toHaveBeenCalledWith(testURL);
|
|
});
|
|
|
|
it('should explicitly untrust if user selects More Details and then cancel with the checkbox checked', async () => {
|
|
dialog.showMessageBox.mockResolvedValueOnce({response: 0}).mockResolvedValueOnce({response: 1, checkboxChecked: true});
|
|
await handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
|
|
expect(callback).toHaveBeenCalledWith(false);
|
|
expect(certificateErrorCallbacks.has('http://server-1.com:error-1')).toBe(false);
|
|
expect(CertificateStore.add).toHaveBeenCalledWith(new URL('http://server-1.com'), certificate, true);
|
|
expect(CertificateStore.save).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|