mirror of
https://github.com/jiahaog/Nativefier
synced 2024-06-27 07:45:03 +02:00
72de7b3fca
* Catch promise errors better * Move subFunctions to bottom of createNewWindow * Use parents when creating child BrowserWindow instances * Some about:blank pages have an anchor (for some reason) * Inject browserWindowOptions better * Interim refactor to MainWindow object * Split up the window functions/helpers/events some * Further separate out window functions + tests * Add a mock for unit testing functions that access electron * Add unit tests for onWillPreventUnload * Improve windowEvents tests * Add the first test for windowHelpers * Move WebRequest event handling to node * insertCSS completely under test * clearAppData completely under test * Fix contextMenu require bug * More tests + fixes * Fix + add to createNewTab tests * Convert createMainWindow back to func + work out gremlins * Move setupWindow away from main since its shared * Make sure contextMenu is handling promises
358 lines
11 KiB
TypeScript
358 lines
11 KiB
TypeScript
jest.mock('./helpers');
|
|
jest.mock('./windowEvents');
|
|
jest.mock('./windowHelpers');
|
|
|
|
import { dialog, BrowserWindow, WebContents } from 'electron';
|
|
import { linkIsInternal, openExternal, nativeTabsSupported } from './helpers';
|
|
const { onNewWindowHelper, onWillNavigate, onWillPreventUnload } =
|
|
jest.requireActual('./windowEvents');
|
|
import {
|
|
blockExternalURL,
|
|
createAboutBlankWindow,
|
|
createNewTab,
|
|
} from './windowHelpers';
|
|
|
|
describe('onNewWindowHelper', () => {
|
|
const originalURL = 'https://medium.com/';
|
|
const internalURL = 'https://medium.com/topics/technology';
|
|
const externalURL = 'https://www.wikipedia.org/wiki/Electron';
|
|
const foregroundDisposition = 'foreground-tab';
|
|
const backgroundDisposition = 'background-tab';
|
|
|
|
const mockBlockExternalURL: jest.SpyInstance = blockExternalURL as jest.Mock;
|
|
const mockCreateAboutBlank: jest.SpyInstance =
|
|
createAboutBlankWindow as jest.Mock;
|
|
const mockCreateNewTab: jest.SpyInstance = createNewTab as jest.Mock;
|
|
const mockLinkIsInternal: jest.SpyInstance = (
|
|
linkIsInternal as jest.Mock
|
|
).mockImplementation(() => true);
|
|
const mockNativeTabsSupported: jest.SpyInstance =
|
|
nativeTabsSupported as jest.Mock;
|
|
const mockOpenExternal: jest.SpyInstance = openExternal as jest.Mock;
|
|
const preventDefault = jest.fn();
|
|
const setupWindow = jest.fn();
|
|
|
|
beforeEach(() => {
|
|
mockBlockExternalURL
|
|
.mockReset()
|
|
.mockReturnValue(Promise.resolve(undefined));
|
|
mockCreateAboutBlank.mockReset();
|
|
mockCreateNewTab.mockReset();
|
|
mockLinkIsInternal.mockReset().mockReturnValue(true);
|
|
mockNativeTabsSupported.mockReset().mockReturnValue(false);
|
|
mockOpenExternal.mockReset();
|
|
preventDefault.mockReset();
|
|
setupWindow.mockReset();
|
|
});
|
|
|
|
afterAll(() => {
|
|
mockBlockExternalURL.mockRestore();
|
|
mockCreateAboutBlank.mockRestore();
|
|
mockCreateNewTab.mockRestore();
|
|
mockLinkIsInternal.mockRestore();
|
|
mockNativeTabsSupported.mockRestore();
|
|
mockOpenExternal.mockRestore();
|
|
});
|
|
|
|
test('internal urls should not be handled', () => {
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
undefined,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('external urls should be opened externally', () => {
|
|
mockLinkIsInternal.mockReturnValue(false);
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
externalURL,
|
|
undefined,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).toHaveBeenCalledTimes(1);
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('external urls should be ignored if blockExternalUrls is true', () => {
|
|
mockLinkIsInternal.mockReturnValue(false);
|
|
const options = {
|
|
blockExternalUrls: true,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
externalURL,
|
|
undefined,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).toHaveBeenCalledTimes(1);
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('tab disposition should be ignored if tabs are not enabled', () => {
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
foregroundDisposition,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('tab disposition should be ignored if url is external', () => {
|
|
mockLinkIsInternal.mockReturnValue(false);
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
externalURL,
|
|
foregroundDisposition,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).toHaveBeenCalledTimes(1);
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('foreground tabs with internal urls should be opened in the foreground', () => {
|
|
mockNativeTabsSupported.mockReturnValue(true);
|
|
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
foregroundDisposition,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).toHaveBeenCalledTimes(1);
|
|
expect(mockCreateNewTab).toHaveBeenCalledWith(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
true,
|
|
undefined,
|
|
);
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('background tabs with internal urls should be opened in background tabs', () => {
|
|
mockNativeTabsSupported.mockReturnValue(true);
|
|
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
backgroundDisposition,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).not.toHaveBeenCalled();
|
|
expect(mockCreateNewTab).toHaveBeenCalledTimes(1);
|
|
expect(mockCreateNewTab).toHaveBeenCalledWith(
|
|
options,
|
|
setupWindow,
|
|
internalURL,
|
|
false,
|
|
undefined,
|
|
);
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('about:blank urls should be handled', () => {
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
onNewWindowHelper(
|
|
options,
|
|
setupWindow,
|
|
'about:blank',
|
|
undefined,
|
|
preventDefault,
|
|
);
|
|
|
|
expect(mockCreateAboutBlank).toHaveBeenCalledTimes(1);
|
|
expect(mockCreateNewTab).not.toHaveBeenCalled();
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('onWillNavigate', () => {
|
|
const originalURL = 'https://medium.com/';
|
|
const internalURL = 'https://medium.com/topics/technology';
|
|
const externalURL = 'https://www.wikipedia.org/wiki/Electron';
|
|
|
|
const mockBlockExternalURL: jest.SpyInstance = blockExternalURL as jest.Mock;
|
|
const mockLinkIsInternal: jest.SpyInstance = linkIsInternal as jest.Mock;
|
|
const mockOpenExternal: jest.SpyInstance = openExternal as jest.Mock;
|
|
const preventDefault = jest.fn();
|
|
|
|
beforeEach(() => {
|
|
mockBlockExternalURL
|
|
.mockReset()
|
|
.mockReturnValue(Promise.resolve(undefined));
|
|
mockLinkIsInternal.mockReset().mockReturnValue(false);
|
|
mockOpenExternal.mockReset();
|
|
preventDefault.mockReset();
|
|
});
|
|
|
|
afterAll(() => {
|
|
mockBlockExternalURL.mockRestore();
|
|
mockLinkIsInternal.mockRestore();
|
|
mockOpenExternal.mockRestore();
|
|
});
|
|
|
|
test('internal urls should not be handled', () => {
|
|
mockLinkIsInternal.mockReturnValue(true);
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
const event = { preventDefault };
|
|
onWillNavigate(options, event, internalURL);
|
|
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('external urls should be opened externally', () => {
|
|
const options = {
|
|
blockExternalUrls: false,
|
|
targetUrl: originalURL,
|
|
};
|
|
const event = { preventDefault };
|
|
onWillNavigate(options, event, externalURL);
|
|
|
|
expect(mockBlockExternalURL).not.toHaveBeenCalled();
|
|
expect(mockOpenExternal).toHaveBeenCalledTimes(1);
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('external urls should be ignored if blockExternalUrls is true', () => {
|
|
const options = {
|
|
blockExternalUrls: true,
|
|
targetUrl: originalURL,
|
|
};
|
|
const event = { preventDefault };
|
|
onWillNavigate(options, event, externalURL);
|
|
|
|
expect(mockBlockExternalURL).toHaveBeenCalledTimes(1);
|
|
expect(mockOpenExternal).not.toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('onWillPreventUnload', () => {
|
|
const mockFromWebContents: jest.SpyInstance = jest
|
|
.spyOn(BrowserWindow, 'fromWebContents')
|
|
.mockImplementation(() => new BrowserWindow());
|
|
const mockShowDialog: jest.SpyInstance = jest.spyOn(
|
|
dialog,
|
|
'showMessageBoxSync',
|
|
);
|
|
const preventDefault: jest.SpyInstance = jest.fn();
|
|
|
|
beforeEach(() => {
|
|
mockFromWebContents.mockReset();
|
|
mockShowDialog.mockReset().mockReturnValue(undefined);
|
|
preventDefault.mockReset();
|
|
});
|
|
|
|
afterAll(() => {
|
|
mockFromWebContents.mockRestore();
|
|
mockShowDialog.mockRestore();
|
|
});
|
|
|
|
test('with no sender', () => {
|
|
const event = {};
|
|
onWillPreventUnload(event);
|
|
|
|
expect(mockFromWebContents).not.toHaveBeenCalled();
|
|
expect(mockShowDialog).not.toHaveBeenCalled();
|
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
});
|
|
|
|
test('shows dialog and calls preventDefault on ok', () => {
|
|
mockShowDialog.mockReturnValue(0);
|
|
|
|
const event = { preventDefault, sender: new WebContents() };
|
|
onWillPreventUnload(event);
|
|
|
|
expect(mockFromWebContents).toHaveBeenCalledWith(event.sender);
|
|
expect(mockShowDialog).toHaveBeenCalled();
|
|
expect(preventDefault).toHaveBeenCalledWith();
|
|
});
|
|
|
|
test('shows dialog and does not call preventDefault on cancel', () => {
|
|
mockShowDialog.mockReturnValue(1);
|
|
|
|
const event = { preventDefault, sender: new WebContents() };
|
|
onWillPreventUnload(event);
|
|
|
|
expect(mockFromWebContents).toHaveBeenCalledWith(event.sender);
|
|
expect(mockShowDialog).toHaveBeenCalled();
|
|
expect(preventDefault).not.toHaveBeenCalled();
|
|
});
|
|
});
|