Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/__tests__/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const mockBrowserWindowInstance = () => {
addBrowserView: jest.fn(),
destroy: jest.fn(),
getContentBounds: jest.fn(() => ({})),
isFullScreen: jest.fn(() => false),
isFullScreen: jest.fn(),
loadURL: jest.fn(),
on: jest.fn((eventName, func) => {
instance.listeners[eventName] = func;
Expand All @@ -32,13 +32,16 @@ const mockBrowserWindowInstance = () => {
setBrowserView: jest.fn(),
setFullScreen: jest.fn(),
webContents: {
loadedUrl: '',
copy: jest.fn(),
copyImageAt: jest.fn(),
cut: jest.fn(),
destroy: jest.fn(),
executeJavaScript: jest.fn(async () => {}),
goBack: jest.fn(),
loadURL: jest.fn(),
loadURL: jest.fn(url => {
instance.webContents.loadedUrl = url;
}),
on: jest.fn((...args) => instance.on(...args)),
openDevTools: jest.fn(),
paste: jest.fn(),
Expand Down
184 changes: 184 additions & 0 deletions src/main/__tests__/global-listeners.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* @jest-environment node
*/
/*
Copyright 2022 Marc Nuri San Felix

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
describe('Main :: Global listeners module test suite', () => {
let electron;
let main;
let browserWindow;
let eventBus;
beforeEach(() => {
jest.resetModules();
// Always mock settings unless we want to overwrite the real settings file !
jest.mock('../../settings');
require('../../settings').loadSettings.mockImplementation(() => ({}));
require('../../settings').openSettingsDialog = jest.requireActual('../../settings').openSettingsDialog;
jest.mock('electron', () => require('../../__tests__').mockElectronInstance({
// Return a **different** instance for each view
BrowserView: jest.fn(() => require('../../__tests__').mockBrowserWindowInstance())
}));
electron = require('electron');
browserWindow = electron.browserWindowInstance;
eventBus = electron.ipcMain;
jest.spyOn(require('../../user-agent'), 'initBrowserVersions')
.mockImplementation(() => Promise.resolve({}));
main = require('../');
main.init();
});
test('appMenuOpen, should show and resize app-menu', () => {
// When
eventBus.listeners.appMenuOpen();
// Then
expect(browserWindow.addBrowserView).toHaveBeenCalledWith(
expect.objectContaining({isAppMenu: true})
);
expect(browserWindow.addBrowserView.mock.calls[0][0].setBounds).toHaveBeenCalledWith(expect.objectContaining({
x: 0, y: 0
}));
});
test('appMenuClose, should hide app-menu', () => {
// When
eventBus.listeners.appMenuClose();
// Then
expect(browserWindow.removeBrowserView).toHaveBeenCalledWith(
expect.objectContaining({isAppMenu: true})
);
});
describe('closeDialog', () => {
describe('with dialog visible (<= 1 view)', () => {
let dialog;
beforeEach(() => {
dialog = new electron.BrowserView();
browserWindow.getBrowserViews = jest.fn(() => [dialog]);
browserWindow.getBrowserView = jest.fn(() => (dialog));
});
test('should destroy dialog', () => {
// When
eventBus.listeners.closeDialog();
// Then
expect(dialog.webContents.destroy).toHaveBeenCalledTimes(1);
});
test('should activate current tab', () => {
// Given
const tabManagerModule = require('../../tab-manager');
jest.spyOn(tabManagerModule, 'getActiveTab').mockImplementation();
// When
eventBus.listeners.closeDialog();
// Then
expect(tabManagerModule.getActiveTab).toHaveBeenCalledTimes(1);
});
test('should not call update settings', () => {
// Given
const settingsModule = require('../../settings');
jest.spyOn(settingsModule, 'updateSettings').mockImplementation();
// When
eventBus.listeners.closeDialog();
// Then
expect(settingsModule.updateSettings).not.toHaveBeenCalled();
});
});
test('should return if no dialog is shown (>1 view)', () => {
// Given
const view = new electron.BrowserView();
browserWindow.getBrowserViews = jest.fn(() => [view, view]);
// When
eventBus.listeners.closeDialog();
// Then
expect(view.webContents.destroy).not.toHaveBeenCalled();
});
});
describe('fullscreenToggle', () => {
test('when not fullscreen, should enter fullscreen', () => {
// Given
browserWindow.isFullScreen.mockReturnValue(false);
// When
eventBus.listeners.fullscreenToggle();
// Then
expect(browserWindow.setFullScreen).toHaveBeenCalledWith(true);
});
test('when in fullscreen, should leave fullscreen', () => {
// Given
browserWindow.isFullScreen.mockReturnValue(true);
// When
eventBus.listeners.fullscreenToggle();
// Then
expect(browserWindow.setFullScreen).toHaveBeenCalledWith(false);
});
});
test('helpOpenDialog, should open help dialog', () => {
// When
eventBus.listeners.helpOpenDialog();
// Then
const browserView = electron.BrowserView.mock.results
.map(r => r.value).filter(bv => bv.webContents.loadedUrl.endsWith('/help/index.html'))[0];
expect(browserWindow.setBrowserView).toHaveBeenCalledWith(browserView);
expect(browserView.webContents.loadURL)
.toHaveBeenCalledWith(expect.stringMatching(/help\/index.html$/));
});
test('settingsOpenDialog, should open settings dialog', () => {
// When
eventBus.listeners.settingsOpenDialog();
// Then
const browserView = electron.BrowserView.mock.results
.map(r => r.value).filter(bv => bv.webContents.loadedUrl.endsWith('/settings/index.html'))[0];
expect(browserWindow.setBrowserView).toHaveBeenCalledWith(browserView);
expect(browserView.webContents.loadURL)
.toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
});
describe('settingsSave', () => {
let settings;
beforeEach(() => {
settings = new electron.BrowserView();
browserWindow.getBrowserViews = jest.fn(() => [settings]);
browserWindow.getBrowserView = jest.fn(() => (settings));
});
test('should reload settings', () => {
// Given
const settingsModule = require('../../settings');
// When
eventBus.listeners.settingsSave({}, {tabs: [{id: 1337}], enabledDictionaries: []});
// Then
expect(electron.browserWindowInstance.loadURL)
.toHaveBeenCalledWith(expect.stringMatching(/spell-check\/dictionary.renderer\/index.html$/));
expect(settingsModule.updateSettings).toHaveBeenCalledTimes(1);
});
test('should reset all views', () => {
// Given
const tabManagerModule = require('../../tab-manager');
jest.spyOn(tabManagerModule, 'removeAll').mockImplementation();
// When
eventBus.listeners.settingsSave({}, {tabs: [{id: 1337}], enabledDictionaries: []});
// Then
expect(browserWindow.removeBrowserView).toHaveBeenCalledTimes(1);
expect(browserWindow.removeBrowserView).toHaveBeenCalledWith(settings);
expect(tabManagerModule.removeAll).toHaveBeenCalledTimes(1);
expect(settings.webContents.destroy).toHaveBeenCalledTimes(1);
});
test('should set saved theme', () => {
// When
eventBus.listeners.settingsSave({}, {theme: 'light'});
// Then
expect(electron.nativeTheme.themeSource).toEqual('light');
});
test('should fallback theme to system', () => {
// When
eventBus.listeners.settingsSave({}, {});
// Then
expect(electron.nativeTheme.themeSource).toEqual('system');
});
});
});
127 changes: 0 additions & 127 deletions src/main/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ describe('Main module test suite', () => {
let mockSettings;
let appMenuModule;
let settingsModule;
let spellCheckModule;
let tabManagerModule;
let userAgentModule;
let main;
Expand All @@ -52,8 +51,6 @@ describe('Main module test suite', () => {
settingsModule = require('../../settings');
jest.spyOn(settingsModule, 'loadSettings').mockImplementation(() => mockSettings);
jest.spyOn(settingsModule, 'updateSettings').mockImplementation();
jest.mock('../../spell-check');
spellCheckModule = require('../../spell-check');
tabManagerModule = require('../../tab-manager');
jest.mock('../../user-agent');
userAgentModule = require('../../user-agent');
Expand Down Expand Up @@ -443,128 +440,4 @@ describe('Main module test suite', () => {
});
});
});
describe('initGlobalListeners ipc events', () => {
let settingsView;
beforeEach(() => {
settingsView = {webContents: {destroy: jest.fn()}};
mockBrowserWindow.getBrowserView = jest.fn(() => settingsView);
mockBrowserWindow.getBrowserViews = jest.fn(() => [settingsView]);
});
describe('saveSettings', () => {
beforeEach(() => {
mockBrowserWindow.removeBrowserView = jest.fn();
main.init();
});
test('should reload settings and reset all views', () => {
// Given
jest.spyOn(tabManagerModule, 'removeAll').mockImplementation();
// When
mockIpc.listeners.settingsSave({}, {tabs: [{id: 1337}], enabledDictionaries: []});
// Then
expect(spellCheckModule.loadDictionaries).toHaveBeenCalledTimes(2);
expect(settingsModule.updateSettings).toHaveBeenCalledTimes(1);
expect(mockBrowserWindow.removeBrowserView).toHaveBeenCalledTimes(1);
expect(mockBrowserWindow.removeBrowserView).toHaveBeenCalledWith(settingsView);
expect(tabManagerModule.removeAll).toHaveBeenCalledTimes(1);
expect(settingsView.webContents.destroy).toHaveBeenCalledTimes(1);
expect(mockBrowserView.webContents.destroy).toHaveBeenCalledTimes(1);
});
test('should set saved theme', () => {
// When
mockIpc.listeners.settingsSave({}, {theme: 'light'});
// Then
expect(mockNativeTheme.themeSource).toEqual('light');
});
test('should fallback theme to system', () => {
// When
mockIpc.listeners.settingsSave({}, {});
// Then
expect(mockNativeTheme.themeSource).toEqual('system');
});
});
describe('closeDialog', () => {
beforeEach(() => {
jest.spyOn(tabManagerModule, 'getActiveTab').mockImplementation();
main.init();
});
test('should destroy dialog view and activate current tab', () => {
// When
mockIpc.listeners.closeDialog();
// Then
expect(settingsModule.updateSettings).not.toHaveBeenCalled();
expect(tabManagerModule.getActiveTab).toHaveBeenCalledTimes(1);
expect(settingsView.webContents.destroy).toHaveBeenCalledTimes(1);
});
test('should return if no dialog is shown (>1 view)', () => {
// Given
mockBrowserWindow.getBrowserViews = jest.fn(() => [{}, {}]);
// When
mockIpc.listeners.closeDialog();
// Then
expect(settingsModule.updateSettings).not.toHaveBeenCalled();
expect(tabManagerModule.getActiveTab).not.toHaveBeenCalled();
});
});
test('appMenuOpen, should show and resize app-menu', () => {
// Given
const mockAppMenu = {setBounds: jest.fn()};
jest.spyOn(appMenuModule, 'newAppMenu').mockImplementation(() => mockAppMenu);
main.init();
// When
mockIpc.listeners.appMenuOpen();
// Then
expect(mockBrowserWindow.addBrowserView).toHaveBeenCalledTimes(1);
expect(mockBrowserWindow.addBrowserView).toHaveBeenCalledWith(mockAppMenu);
expect(mockAppMenu.setBounds).toHaveBeenCalledWith(expect.objectContaining({x: 0, y: 0}));
});
test('appMenuClose, should hide app-menu', () => {
// Given
const mockAppMenu = {isTheMockAppMenu: true};
jest.spyOn(appMenuModule, 'newAppMenu').mockImplementation(() => mockAppMenu);
main.init();
// When
mockIpc.listeners.appMenuClose();
// Then
expect(mockBrowserWindow.removeBrowserView).toHaveBeenCalledTimes(1);
expect(mockBrowserWindow.removeBrowserView).toHaveBeenCalledWith(mockAppMenu);
});
describe('fullscreenToggle', () => {
test('when not fullscreen, should enter fullscreen', () => {
// Given
mockBrowserWindow.isFullScreen.mockReturnValue(false);
main.init();
// When
mockIpc.listeners.fullscreenToggle();
// Then
expect(mockBrowserWindow.setFullScreen).toHaveBeenCalledWith(true);
});
test('when in fullscreen, should leave fullscreen', () => {
// Given
mockBrowserWindow.isFullScreen.mockReturnValue(true);
main.init();
// When
mockIpc.listeners.fullscreenToggle();
// Then
expect(mockBrowserWindow.setFullScreen).toHaveBeenCalledWith(false);
});
});
test('settingsOpenDialog, should open settings dialog', () => {
// Given
main.init();
// When
mockIpc.listeners.settingsOpenDialog();
// Then
expect(mockBrowserView.webContents.loadURL)
.toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
});
test('helpOpenDialog, should open help dialog', () => {
// Given
main.init();
// When
mockIpc.listeners.helpOpenDialog();
// Then
expect(mockBrowserView.webContents.loadURL)
.toHaveBeenCalledWith(expect.stringMatching(/help\/index.html$/));
});
});
});
2 changes: 1 addition & 1 deletion src/main/__tests__/keyboard-shortcuts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
describe('Global Keyboard Shortcuts module test suite', () => {
describe('Main :: Global Keyboard Shortcuts module test suite', () => {
let electron;
beforeEach(() => {
jest.resetModules();
Expand Down