Repository: manusa/electronim
Pull request #454 (2024-12-04 05:56:27)

🐛 Fix WhatsApp Favicon Not Displaying Due to net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin ErrorFix/whatsapp icon
_Originally authored by @lukasborges_ in #430

> This pull request fixes the issue where the WhatsApp favicon was not displaying due to a net::ERR_BLOCKED_BY_RESPONSE.NotSameOrigin error. Previously, the favicon was applied as a background image within a div, which caused cross-origin restrictions to block it.
> 
> The solution involves:
> 
> - Replacing the background image in the div with an <img> tag that includes the crossorigin="anonymous" attribute to handle cross-origin restrictions.
> - Updating the CSS to explicitly set the size of the favicon by applying width: 16px and height: 16px to the image inside the tab container.

sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=manusa_electronim&pullRequest=454) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=454&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=454&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=manusa_electronim&pullRequest=454&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=454&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=454&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=manusa_electronim&pullRequest=454)



Patch:
diff --git a/package-lock.json b/package-lock.json
index 7f90c81..d4e9335 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -50,8 +50,8 @@
         "jest-environment-jsdom": "29.7.0",
         "jest-environment-node": "29.7.0",
         "jest-extended": "4.0.2",
-        "sass": "1.81.1",
-        "sass-loader": "16.0.3",
+        "sass": "1.82.0",
+        "sass-loader": "16.0.4",
         "style-loader": "4.0.0",
         "val-loader": "6.0.0",
         "webpack": "5.96.1"
@@ -9267,9 +9267,9 @@
       }
     },
     "node_modules/sass": {
-      "version": "1.81.1",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.1.tgz",
-      "integrity": "sha512-VNLgf4FC5yFyKwAumAAwwNh8X4SevlVREq3Y8aDZIkm0lI/zO1feycMXQ4hn+eB6FVhRbleSQ1Yb/q8juSldTA==",
+      "version": "1.82.0",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz",
+      "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==",
       "dev": true,
       "dependencies": {
         "chokidar": "^4.0.0",
@@ -9287,9 +9287,9 @@
       }
     },
     "node_modules/sass-loader": {
-      "version": "16.0.3",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz",
-      "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==",
+      "version": "16.0.4",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
+      "integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==",
       "dev": true,
       "dependencies": {
         "neo-async": "^2.6.2"
@@ -17534,9 +17534,9 @@
       }
     },
     "sass": {
-      "version": "1.81.1",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.1.tgz",
-      "integrity": "sha512-VNLgf4FC5yFyKwAumAAwwNh8X4SevlVREq3Y8aDZIkm0lI/zO1feycMXQ4hn+eB6FVhRbleSQ1Yb/q8juSldTA==",
+      "version": "1.82.0",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz",
+      "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==",
       "dev": true,
       "requires": {
         "@parcel/watcher": "^2.4.1",
@@ -17546,9 +17546,9 @@
       }
     },
     "sass-loader": {
-      "version": "16.0.3",
-      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz",
-      "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==",
+      "version": "16.0.4",
+      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
+      "integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==",
       "dev": true,
       "requires": {
         "neo-async": "^2.6.2"
diff --git a/package.json b/package.json
index 74151d4..e6c66d8 100644
--- a/package.json
+++ b/package.json
@@ -195,8 +195,8 @@
     "jest-environment-jsdom": "29.7.0",
     "jest-environment-node": "29.7.0",
     "jest-extended": "4.0.2",
-    "sass": "1.81.1",
-    "sass-loader": "16.0.3",
+    "sass": "1.82.0",
+    "sass-loader": "16.0.4",
     "style-loader": "4.0.0",
     "val-loader": "6.0.0",
     "webpack": "5.96.1"
diff --git a/src/chrome-tabs/chrome-tabs.browser.css b/src/chrome-tabs/chrome-tabs.browser.css
index 35f0f09..7c62577 100644
--- a/src/chrome-tabs/chrome-tabs.browser.css
+++ b/src/chrome-tabs/chrome-tabs.browser.css
@@ -52,6 +52,13 @@ body {
   /* https://github.com/vaadin/web-components/issues/4183 */
   /* Prevents https://bugs.chromium.org/p/chromium/issues/detail?id=1399431 */
   -webkit-mask-image: none;
+  display: flex;
+  align-items: center;
+}
+
+.tab-container .chrome-tabs .chrome-tab .chrome-tab-content .chrome-tab-favicon-icon {
+  width: var(--chrome-tab-favicon-size);
+  height: var(--chrome-tab-favicon-size);
 }
 
 .tab-container .chrome-tabs .chrome-tab .chrome-tab-content::after {
diff --git a/src/chrome-tabs/chrome-tabs.browser.mjs b/src/chrome-tabs/chrome-tabs.browser.mjs
index b2d7604..a9c37ee 100644
--- a/src/chrome-tabs/chrome-tabs.browser.mjs
+++ b/src/chrome-tabs/chrome-tabs.browser.mjs
@@ -61,12 +61,16 @@ const isInVisibleArea = event =>
   event.clientX <= window.innerWidth && event.clientY <= window.innerHeight;
 
 const Favicon = ({favicon = ''}) => {
-  const faviconProps = {hidden: true};
+  let img = html``;
   if (favicon) {
-    faviconProps.style = `background-image: url("${favicon}");`;
-    delete faviconProps.hidden;
+    img = html`
+      <img class="chrome-tab-favicon-icon" crossorigin="anonymous" src="${favicon}" alt="" role="presentation"/>
+    `;
   }
-  return html`<div class="chrome-tab-favicon" ...${faviconProps}></div>`;
+  return html`
+      <div class="chrome-tab-favicon">
+          ${img}
+      </div>`;
 };
 
 const NotificationIcon = ({disableNotifications = false}) => disableNotifications && html`
@@ -192,8 +196,8 @@ const TabContainer = () => {
     sendTabsReady();
   }, []);
   return html`
-    <${ChromeTabs} state=${state} dispatch=${dispatch}/>
-    <${Menu} state=${state}/>
+      <${ChromeTabs} state=${state} dispatch=${dispatch}/>
+          <${Menu} state=${state}/>
   `;
 };
 
diff --git a/src/constants/index.js b/src/constants/index.js
index 06a498c..03745e7 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -39,6 +39,7 @@ const APP_EVENTS = {
   dictionaryGetEnabled: 'dictionaryGetEnabled',
   dictionaryGetMisspelled: 'dictionaryGetMisspelled',
   electronimNewVersionAvailable: 'electronimNewVersionAvailable',
+  findInPageOpenWindow: 'findInPageOpenWindow',
   fullscreenToggle: 'fullscreenToggle',
   helpOpenDialog: 'helpOpenDialog',
   notificationClick: 'notificationClick',
diff --git a/src/main/index.js b/src/main/index.js
index bd8ac5d..27689ef 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -165,6 +165,9 @@ const initTabListener = () => {
   });
   eventBus.on(APP_EVENTS.reload, handleTabReload);
   eventBus.on(APP_EVENTS.tabReorder, handleTabReorder);
+  // findInPageOpenWindow is just a loopback from preload.keyboard-shortcuts to preload.find-in-page
+  eventBus.on(APP_EVENTS.findInPageOpenWindow,
+    event => event.sender.send(APP_EVENTS.findInPageOpenWindow));
   eventBus.on(APP_EVENTS.zoomIn, handleZoomIn);
   eventBus.on(APP_EVENTS.zoomOut, handleZoomOut);
   eventBus.on(APP_EVENTS.zoomReset, handleZoomReset);
diff --git a/src/styles/base/variables.css b/src/styles/base/variables.css
index 5f8970a..3bdc1dc 100644
--- a/src/styles/base/variables.css
+++ b/src/styles/base/variables.css
@@ -16,6 +16,7 @@
 :root {
   --default-spacing: 6px;
   --tab-container-height: 46px;
+  --chrome-tab-favicon-size: 16px;
   /*--material3-field-height: 56px;*/
   /* Material 3 default height is too big for us, reduce it to something more appealing */
   --material3-field-height: 40px;
diff --git a/src/tab-manager/context-menu.js b/src/tab-manager/context-menu.js
index 1131141..966d4b4 100644
--- a/src/tab-manager/context-menu.js
+++ b/src/tab-manager/context-menu.js
@@ -89,7 +89,7 @@ const handleContextMenu = viewOrWindow => async (_event, params) => {
     menu = regularContextMenu({webContents, params});
   }
   const {x, y} = params;
-  menu.popup({x, y});
+  menu.popup({x: x + 1, y: y + 1});
 };
 
 module.exports = {handleContextMenu};
diff --git a/src/tab-manager/preload.find-in-page.js b/src/tab-manager/preload.find-in-page.js
new file mode 100644
index 0000000..9dbb78a
--- /dev/null
+++ b/src/tab-manager/preload.find-in-page.js
@@ -0,0 +1,27 @@
+/*
+   Copyright 2024 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.
+ */
+/* eslint-disable no-undef */
+const {ipcRenderer} = require('electron');
+
+
+const openFindWindow = () => {
+};
+
+const initFindInPage = () => {
+  ipcRenderer.on(APP_EVENTS.findInPageOpenWindow, openFindWindow);
+};
+
+module.exports = {initFindInPage};
diff --git a/src/tab-manager/preload.js b/src/tab-manager/preload.js
index b69f408..3a60cdc 100644
--- a/src/tab-manager/preload.js
+++ b/src/tab-manager/preload.js
@@ -14,6 +14,7 @@
    limitations under the License.
  */
 require('./preload.notification-shim');
+require('./preload.find-in-page').initFindInPage();
 require('./preload.mediadevices-shim');
 require('./preload.keyboard-shortcuts').initKeyboardShortcuts();
 require('./preload.spell-check').initSpellChecker()
diff --git a/src/tab-manager/preload.keyboard-shortcuts.js b/src/tab-manager/preload.keyboard-shortcuts.js
index f9dc4d7..bc8b575 100644
--- a/src/tab-manager/preload.keyboard-shortcuts.js
+++ b/src/tab-manager/preload.keyboard-shortcuts.js
@@ -26,6 +26,10 @@ EVENTS.set(eventKey({key: 'R', ctrlKey: true}), () => ipcRenderer.send(APP_EVENT
 EVENTS.set(eventKey({key: 'r', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.reload));
 EVENTS.set(eventKey({key: 'R', metaKey: true}), () => ipcRenderer.send(APP_EVENTS.reload));
 EVENTS.set(eventKey({key: 'r', metaKey: true}), () => ipcRenderer.send(APP_EVENTS.reload));
+EVENTS.set(eventKey({key: 'f', metaKey: true}), () => ipcRenderer.send(APP_EVENTS.findInPageOpenWindow));
+EVENTS.set(eventKey({key: 'F', metaKey: true}), () => ipcRenderer.send(APP_EVENTS.findInPageOpenWindow));
+EVENTS.set(eventKey({key: 'f', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.findInPageOpenWindow));
+EVENTS.set(eventKey({key: 'F', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.findInPageOpenWindow));
 EVENTS.set(eventKey({key: '+', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.zoomIn));
 EVENTS.set(eventKey({key: '-', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.zoomOut));
 EVENTS.set(eventKey({key: '0', ctrlKey: true}), () => ipcRenderer.send(APP_EVENTS.zoomReset));
diff --git a/utils/common.js b/utils/common.js
index e6a7992..30947f8 100644
--- a/utils/common.js
+++ b/utils/common.js
@@ -1,3 +1,18 @@
+/*
+   Copyright 2020 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.
+ */
 const refPrefix = 'refs/tags/v';
 
 const extractVersionFromTag = () => {
diff --git a/utils/error-handler.js b/utils/error-handler.js
index 6d1ed65..53d3243 100644
--- a/utils/error-handler.js
+++ b/utils/error-handler.js
@@ -1,3 +1,18 @@
+/*
+   Copyright 2020 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.
+ */
 /* eslint-disable no-console */
 
 const errorHandler = error => {
diff --git a/utils/prepare-chocolatey.js b/utils/prepare-chocolatey.js
index f6e21ba..a8b1aa5 100644
--- a/utils/prepare-chocolatey.js
+++ b/utils/prepare-chocolatey.js
@@ -1,4 +1,19 @@
 #!/usr/bin/env node
+/*
+   Copyright 2024 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.
+ */
 /* eslint-disable no-console */
 const crypto = require('crypto');
 const fs = require('fs');
diff --git a/utils/prepare-electron-builder.js b/utils/prepare-electron-builder.js
index df599ca..ce5c0e1 100755
--- a/utils/prepare-electron-builder.js
+++ b/utils/prepare-electron-builder.js
@@ -1,4 +1,19 @@
 #!/usr/bin/env node
+/*
+   Copyright 2020 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.
+ */
 /* eslint-disable no-console */
 const fs = require('fs');
 const path = require('path');
diff --git a/utils/upload-artifact.js b/utils/upload-artifact.js
index 5711370..8b0b3f7 100755
--- a/utils/upload-artifact.js
+++ b/utils/upload-artifact.js
@@ -1,4 +1,19 @@
 #!/usr/bin/env node
+/*
+   Copyright 2020 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.
+ */
 /* eslint-disable no-console,no-useless-escape */
 const axios = require('axios');
 const fs = require('fs');
diff --git a/utils/version-from-tag.js b/utils/version-from-tag.js
index c6d0290..93813ed 100755
--- a/utils/version-from-tag.js
+++ b/utils/version-from-tag.js
@@ -1,4 +1,19 @@
 #!/usr/bin/env node
+/*
+   Copyright 2020 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.
+ */
 /* eslint-disable no-console */
 
 const childProcess = require('child_process');


Test patch:
diff --git a/src/__tests__/electron.js b/src/__tests__/electron.js
index 8feede3..9e85be3 100644
--- a/src/__tests__/electron.js
+++ b/src/__tests__/electron.js
@@ -142,6 +142,7 @@ const mockElectronInstance = ({...overriddenProps} = {}) => {
       })
     },
     ipcRenderer: {
+      on: jest.fn(),
       send: jest.fn()
     },
     nativeTheme: {},
diff --git a/src/chrome-tabs/__tests__/chrome-tabs.browser.test.mjs b/src/chrome-tabs/__tests__/chrome-tabs.browser.test.mjs
index 96faffa..3c5f4d8 100644
--- a/src/chrome-tabs/__tests__/chrome-tabs.browser.test.mjs
+++ b/src/chrome-tabs/__tests__/chrome-tabs.browser.test.mjs
@@ -60,8 +60,8 @@ describe('ChromeTabs in Browser test suite', () => {
       expect($addedTabs[1].querySelector('.chrome-tab-title').innerHTML)
         .toBe('313373');
       expect($addedTabs[1].hasAttribute('active')).toBe(false);
-      expect($addedTabs[2].querySelector('.chrome-tab-favicon').style.backgroundImage)
-        .toBe('url(https://13373.png)');
+      expect($addedTabs[2].querySelector('.chrome-tab-favicon-icon').getAttribute('src'))
+        .toBe('https://13373.png');
       expect(mockIpcRenderer.send).toHaveBeenCalledWith('activateTab', {id: 1337, restoreWindow: false});
     });
     test('activateTabInContainer, should change active tab', async () => {
@@ -95,11 +95,11 @@ describe('ChromeTabs in Browser test suite', () => {
       mockIpcRenderer.events.setTabFavicon({}, {id: 313373, favicon: 'https://f/replaced.png'});
       // Then
       await waitFor(() => expect(
-        $chromeTabs.querySelector('.chrome-tab[data-tab-id="313373"] .chrome-tab-favicon').style.backgroundImage)
-        .toBe('url(https://f/replaced.png)'));
+        $chromeTabs.querySelector('.chrome-tab[data-tab-id="313373"] .chrome-tab-favicon-icon').getAttribute('src'))
+        .toBe('https://f/replaced.png'));
       expect(
-        $chromeTabs.querySelector('.chrome-tab[data-tab-id="13373"] .chrome-tab-favicon').style.backgroundImage)
-        .toBe('url(https://13373.png)');
+        $chromeTabs.querySelector('.chrome-tab[data-tab-id="13373"] .chrome-tab-favicon-icon').getAttribute('src'))
+        .toBe('https://13373.png');
     });
     test('setTabTitle, should change title of specified tab', async () => {
       // Given
diff --git a/src/main/__tests__/index.test.js b/src/main/__tests__/index.test.js
index 1e91af4..3019876 100644
--- a/src/main/__tests__/index.test.js
+++ b/src/main/__tests__/index.test.js
@@ -19,7 +19,6 @@
 describe('Main module test suite', () => {
   let mockNotification;
   let electron;
-  let mockView;
   let mockBaseWindow;
   let mockDesktopCapturer;
   let mockIpc;
@@ -27,7 +26,6 @@ describe('Main module test suite', () => {
   let mockSettings;
   let appMenuModule;
   let settingsModule;
-  let tabManagerModule;
   let main;
   beforeEach(() => {
     jest.resetModules();
@@ -42,7 +40,6 @@ describe('Main module test suite', () => {
       nativeTheme: mockNativeTheme
     }));
     electron = require('electron');
-    mockView = electron.webContentsViewInstance;
     mockBaseWindow = electron.baseWindowInstance;
     mockIpc = electron.ipcMain;
     appMenuModule = require('../../app-menu');
@@ -51,7 +48,6 @@ describe('Main module test suite', () => {
     jest.spyOn(settingsModule, 'getPlatform').mockImplementation(() => 'linux');
     jest.spyOn(settingsModule, 'loadSettings').mockImplementation(() => mockSettings);
     jest.spyOn(settingsModule, 'updateSettings').mockImplementation();
-    tabManagerModule = require('../../tab-manager');
     jest.spyOn(require('../../user-agent'), 'initBrowserVersions').mockImplementation(() => ({
       then: func => {
         func.call();
@@ -286,209 +282,4 @@ describe('Main module test suite', () => {
       });
     });
   });
-  describe('initTabListener ipc events', () => {
-    describe('tabsReady', () => {
-      let addTabsNested;
-      beforeEach(() => {
-        addTabsNested = jest.fn();
-        jest.spyOn(tabManagerModule, 'addTabs')
-          .mockImplementation(() => addTabsNested);
-      });
-      test('No tabs in settings, should open settings dialog', () => {
-        // Given
-        settingsModule.loadSettings.mockImplementation(() => ({tabs: []}));
-        main.init();
-        // When
-        mockIpc.listeners.tabsReady({});
-        // Then
-        expect(tabManagerModule.addTabs).not.toHaveBeenCalled();
-        expect(addTabsNested).not.toHaveBeenCalled();
-        expect(mockView.webContents.loadURL)
-          .toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
-      });
-      test('Previous saved tabs in loaded settings, should add tabs to manager and activate them as they are added', () => {
-        // Given
-        const event = {sender: {send: jest.fn()}};
-        settingsModule.loadSettings.mockImplementation(() => ({tabs: [
-          {id: '1337', otherInfo: 'A Tab'},
-          {id: 'disabled-1337', disabled: true, otherInfo: 'I should be ignored'}
-        ]}));
-        main.init();
-        // When
-        mockIpc.listeners.tabsReady(event);
-        // Then
-        expect(tabManagerModule.addTabs).toHaveBeenCalledWith(event.sender);
-        expect(addTabsNested).toHaveBeenCalledTimes(1);
-        expect(addTabsNested).toHaveBeenCalledWith([{id: '1337', otherInfo: 'A Tab', active: false}]);
-        expect(mockView.webContents.loadURL)
-          .not.toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
-      });
-    });
-    describe('activateTab', () => {
-      let activeTab;
-      beforeEach(() => {
-        activeTab = {
-          setBounds: jest.fn(),
-          webContents: {focus: jest.fn()}
-        };
-        mockBaseWindow.getBrowserViews = jest.fn(() => ([]));
-        mockBaseWindow.setBrowserView = jest.fn();
-        mockBaseWindow.addBrowserView = jest.fn();
-        tabManagerModule.getTab = jest.fn(id => (id === 'validId' ? activeTab : null));
-      });
-      test('no active tab, should do nothing', () => {
-        // Given
-        main.init();
-        // When
-        mockIpc.listeners.activateTab({}, {id: 'not here'});
-        // Then
-        expect(mockBaseWindow.setBrowserView).not.toHaveBeenCalled();
-        expect(mockBaseWindow.addBrowserView).not.toHaveBeenCalled();
-      });
-      test('active tab, should resize tab and set it as the main window browser view', () => {
-        // Given
-        mockBaseWindow.getContentBounds = jest.fn(() => ({width: 13, height: 83}));
-        main.init();
-        // When
-        mockIpc.listeners.activateTab({}, {id: 'validId'});
-        // Then
-        expect(activeTab.setBounds).toHaveBeenCalledWith({x: 0, y: 46, width: 13, height: 37});
-        expect(mockBaseWindow.contentView.addChildView)
-          .toHaveBeenCalledWith(expect.objectContaining({isTabContainer: true}));
-        expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledWith(activeTab);
-        expect(activeTab.webContents.focus).toHaveBeenCalledTimes(1);
-      });
-      test('#23, setBounds should be called AFTER adding view to BaseWindow', () => {
-        // Given
-        mockBaseWindow.getContentBounds = jest.fn(() => ({width: 13, height: 83}));
-        main.init();
-        // When
-        mockIpc.listeners.activateTab({}, {id: 'validId'});
-        // Then
-        expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(mockView.setBounds);
-        expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(mockView.setBounds);
-        expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(activeTab.setBounds);
-        expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(activeTab.setBounds);
-      });
-    });
-    test('canNotify, should call to the canNotify method of the tabManager', () => {
-      // Given
-      const mockIpcMainEvent = {returnValue: null};
-      tabManagerModule.canNotify = jest.fn(() => 'yepe');
-      main.init();
-      // When
-      mockIpc.listeners.canNotify(mockIpcMainEvent, 'validId');
-      // Then
-      expect(tabManagerModule.canNotify).toHaveBeenCalledWith('validId');
-      expect(mockIpcMainEvent.returnValue).toBe('yepe');
-    });
-    test('notificationClick, should restore window and activate tab', () => {
-      // Given
-      mockSettings.startMinimized = true;
-      mockBaseWindow.restore = jest.fn();
-      mockBaseWindow.show = jest.fn();
-      jest.spyOn(tabManagerModule, 'getTab').mockImplementation();
-      main.init();
-      // When
-      mockIpc.listeners.notificationClick({}, {tabId: 'validId'});
-      // Then
-      expect(mockView.webContents.send).toHaveBeenCalledWith('activateTabInContainer', {tabId: 'validId'});
-      expect(mockBaseWindow.restore).toHaveBeenCalledTimes(1);
-      expect(mockBaseWindow.show).toHaveBeenCalledTimes(1);
-      expect(mockBaseWindow.show).toHaveBeenCalledAfter(mockBaseWindow.restore);
-      expect(tabManagerModule.getTab).toHaveBeenCalledWith('validId');
-    });
-    test('handleReload', () => {
-      const event = {sender: {reloadIgnoringCache: jest.fn()}};
-      main.init();
-      // When
-      mockIpc.listeners.reload(event);
-      // Then
-      expect(event.sender.reloadIgnoringCache).toHaveBeenCalledTimes(1);
-    });
-    test('handleZoomIn', () => {
-      const event = {sender: {
-        getZoomFactor: jest.fn(() => 0),
-        setZoomFactor: jest.fn()
-      }};
-      main.init();
-      // When
-      mockIpc.listeners.zoomIn(event);
-      // Then
-      expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
-      expect(event.sender.setZoomFactor).toHaveBeenCalledWith(0.1);
-    });
-    describe('handleZoomOut', () => {
-      test('with valid initial zoom factor, should zoom out', () => {
-        const event = {sender: {
-          getZoomFactor: jest.fn(() => 0.200001),
-          setZoomFactor: jest.fn()
-        }};
-        main.init();
-        // When
-        mockIpc.listeners.zoomOut(event);
-        // Then
-        expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
-        expect(event.sender.setZoomFactor).toHaveBeenCalledWith(0.100001);
-      });
-      test('with invalid initial zoom factor, should do nothing', () => {
-        const event = {sender: {
-          getZoomFactor: jest.fn(() => 0.199999999999999),
-          setZoomFactor: jest.fn()
-        }};
-        main.init();
-        // When
-        mockIpc.listeners.zoomOut(event);
-        // Then
-        expect(event.sender.setZoomFactor).not.toHaveBeenCalled();
-      });
-    });
-    test('handleZoomReset', () => {
-      const event = {sender: {setZoomFactor: jest.fn()}};
-      main.init();
-      // When
-      mockIpc.listeners.zoomReset(event);
-      // Then
-      expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
-      expect(event.sender.setZoomFactor).toHaveBeenCalledWith(1);
-    });
-    describe('handleTabReorder', () => {
-      test('Several tabs, order changed, should update settings', () => {
-        // Given
-        mockSettings = {
-          tabs: [{id: '1337'}, {id: '313373'}]
-        };
-        main.init();
-        // When
-        mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
-        // Then
-        expect(settingsModule.updateSettings).toHaveBeenCalledWith({tabs: [{id: '313373'}, {id: '1337'}]});
-      });
-      test('Several tabs, order changed, should update tabManager order', () => {
-        // Given
-        mockSettings = {
-          tabs: [{id: '1337'}, {id: '313373'}]
-        };
-        jest.spyOn(tabManagerModule, 'sortTabs').mockImplementation();
-        main.init();
-        // When
-        mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
-        // Then
-        expect(tabManagerModule.sortTabs).toHaveBeenCalledWith(['313373', '1337']);
-      });
-      test('Several tabs with hidden, order changed, should update settings keeping hidden tags', () => {
-        // Given
-        mockSettings = {
-          tabs: [{id: '1337'}, {id: 'hidden'}, {id: '313373'}, {id: 'hidden-too'}]
-        };
-        main.init();
-        // When
-        mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
-        // Then
-        expect(settingsModule.updateSettings).toHaveBeenCalledWith({tabs: [
-          {id: '313373'}, {id: '1337'}, {id: 'hidden'}, {id: 'hidden-too'}
-        ]});
-      });
-    });
-  });
 });
diff --git a/src/main/__tests__/tab-listeners.test.js b/src/main/__tests__/tab-listeners.test.js
new file mode 100644
index 0000000..97d8bd3
--- /dev/null
+++ b/src/main/__tests__/tab-listeners.test.js
@@ -0,0 +1,264 @@
+/**
+ * @jest-environment node
+ */
+/*
+   Copyright 2024 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 :: Tab listeners test suite', () => {
+  let electron;
+  let settingsModule;
+  let mockSettings;
+  let mockBaseWindow;
+  let main;
+  let mockIpc;
+  let mockView;
+  let tabManagerModule;
+  beforeEach(() => {
+    jest.resetModules();
+    mockSettings = {};
+    // Always mock settings unless we want to overwrite the real settings file !
+    jest.mock('../../settings');
+    settingsModule = require('../../settings');
+    settingsModule.loadSettings.mockImplementation(() => mockSettings);
+    settingsModule.openSettingsDialog = jest.requireActual('../../settings').openSettingsDialog;
+    jest.mock('electron', () => require('../../__tests__').mockElectronInstance({
+      // Notification: jest.fn(() => mockNotification),
+    }));
+    electron = require('electron');
+    mockBaseWindow = electron.baseWindowInstance;
+    mockIpc = electron.ipcMain;
+    mockView = electron.webContentsViewInstance;
+    tabManagerModule = require('../../tab-manager');
+    jest.spyOn(require('../../user-agent'), 'initBrowserVersions').mockImplementation(() => ({
+      then: func => {
+        func.call();
+        return {catch: () => {}};
+      }
+    }));
+    main = require('../');
+  });
+  describe('tabsReady', () => {
+    let addTabsNested;
+    beforeEach(() => {
+      addTabsNested = jest.fn();
+      jest.spyOn(tabManagerModule, 'addTabs')
+        .mockImplementation(() => addTabsNested);
+    });
+    test('No tabs in settings, should open settings dialog', () => {
+      // Given
+      settingsModule.loadSettings.mockImplementation(() => ({tabs: []}));
+      main.init();
+      // When
+      mockIpc.listeners.tabsReady({});
+      // Then
+      expect(tabManagerModule.addTabs).not.toHaveBeenCalled();
+      expect(addTabsNested).not.toHaveBeenCalled();
+      expect(mockView.webContents.loadURL)
+        .toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
+    });
+    test('Previous saved tabs in loaded settings, should add tabs to manager and activate them as they are added', () => {
+      // Given
+      const event = {sender: {send: jest.fn()}};
+      settingsModule.loadSettings.mockImplementation(() => ({tabs: [
+        {id: '1337', otherInfo: 'A Tab'},
+        {id: 'disabled-1337', disabled: true, otherInfo: 'I should be ignored'}
+      ]}));
+      main.init();
+      // When
+      mockIpc.listeners.tabsReady(event);
+      // Then
+      expect(tabManagerModule.addTabs).toHaveBeenCalledWith(event.sender);
+      expect(addTabsNested).toHaveBeenCalledTimes(1);
+      expect(addTabsNested).toHaveBeenCalledWith([{id: '1337', otherInfo: 'A Tab', active: false}]);
+      expect(mockView.webContents.loadURL)
+        .not.toHaveBeenCalledWith(expect.stringMatching(/settings\/index.html$/));
+    });
+  });
+  describe('activateTab', () => {
+    let activeTab;
+    beforeEach(() => {
+      activeTab = {
+        setBounds: jest.fn(),
+        webContents: {focus: jest.fn()}
+      };
+      mockBaseWindow.getBrowserViews = jest.fn(() => ([]));
+      mockBaseWindow.setBrowserView = jest.fn();
+      mockBaseWindow.addBrowserView = jest.fn();
+      tabManagerModule.getTab = jest.fn(id => (id === 'validId' ? activeTab : null));
+    });
+    test('no active tab, should do nothing', () => {
+      // Given
+      main.init();
+      // When
+      mockIpc.listeners.activateTab({}, {id: 'not here'});
+      // Then
+      expect(mockBaseWindow.setBrowserView).not.toHaveBeenCalled();
+      expect(mockBaseWindow.addBrowserView).not.toHaveBeenCalled();
+    });
+    test('active tab, should resize tab and set it as the main window browser view', () => {
+      // Given
+      mockBaseWindow.getContentBounds = jest.fn(() => ({width: 13, height: 83}));
+      main.init();
+      // When
+      mockIpc.listeners.activateTab({}, {id: 'validId'});
+      // Then
+      expect(activeTab.setBounds).toHaveBeenCalledWith({x: 0, y: 46, width: 13, height: 37});
+      expect(mockBaseWindow.contentView.addChildView)
+        .toHaveBeenCalledWith(expect.objectContaining({isTabContainer: true}));
+      expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledWith(activeTab);
+      expect(activeTab.webContents.focus).toHaveBeenCalledTimes(1);
+    });
+    test('#23, setBounds should be called AFTER adding view to BaseWindow', () => {
+      // Given
+      mockBaseWindow.getContentBounds = jest.fn(() => ({width: 13, height: 83}));
+      main.init();
+      // When
+      mockIpc.listeners.activateTab({}, {id: 'validId'});
+      // Then
+      expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(mockView.setBounds);
+      expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(mockView.setBounds);
+      expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(activeTab.setBounds);
+      expect(mockBaseWindow.contentView.addChildView).toHaveBeenCalledBefore(activeTab.setBounds);
+    });
+  });
+  test('canNotify, should call to the canNotify method of the tabManager', () => {
+    // Given
+    const mockIpcMainEvent = {returnValue: null};
+    tabManagerModule.canNotify = jest.fn(() => 'yepe');
+    main.init();
+    // When
+    mockIpc.listeners.canNotify(mockIpcMainEvent, 'validId');
+    // Then
+    expect(tabManagerModule.canNotify).toHaveBeenCalledWith('validId');
+    expect(mockIpcMainEvent.returnValue).toBe('yepe');
+  });
+  test('notificationClick, should restore window and activate tab', () => {
+    // Given
+    mockSettings.startMinimized = true;
+    mockBaseWindow.restore = jest.fn();
+    mockBaseWindow.show = jest.fn();
+    jest.spyOn(tabManagerModule, 'getTab').mockImplementation();
+    main.init();
+    // When
+    mockIpc.listeners.notificationClick({}, {tabId: 'validId'});
+    // Then
+    expect(mockView.webContents.send).toHaveBeenCalledWith('activateTabInContainer', {tabId: 'validId'});
+    expect(mockBaseWindow.restore).toHaveBeenCalledTimes(1);
+    expect(mockBaseWindow.show).toHaveBeenCalledTimes(1);
+    expect(mockBaseWindow.show).toHaveBeenCalledAfter(mockBaseWindow.restore);
+    expect(tabManagerModule.getTab).toHaveBeenCalledWith('validId');
+  });
+  test('findInPageOpenWindow, should loopback to the view', () => {
+    // Given
+    const event = {sender: {send: jest.fn()}};
+    main.init();
+    // When
+    mockIpc.listeners.findInPageOpenWindow(event);
+    // Then
+    expect(event.sender.send).toHaveBeenCalledWith('findInPageOpenWindow');
+  });
+  test('handleReload', () => {
+    const event = {sender: {reloadIgnoringCache: jest.fn()}};
+    main.init();
+    // When
+    mockIpc.listeners.reload(event);
+    // Then
+    expect(event.sender.reloadIgnoringCache).toHaveBeenCalledTimes(1);
+  });
+  test('handleZoomIn', () => {
+    const event = {sender: {
+      getZoomFactor: jest.fn(() => 0),
+      setZoomFactor: jest.fn()
+    }};
+    main.init();
+    // When
+    mockIpc.listeners.zoomIn(event);
+    // Then
+    expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
+    expect(event.sender.setZoomFactor).toHaveBeenCalledWith(0.1);
+  });
+  describe('handleZoomOut', () => {
+    test('with valid initial zoom factor, should zoom out', () => {
+      const event = {sender: {
+        getZoomFactor: jest.fn(() => 0.200001),
+        setZoomFactor: jest.fn()
+      }};
+      main.init();
+      // When
+      mockIpc.listeners.zoomOut(event);
+      // Then
+      expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
+      expect(event.sender.setZoomFactor).toHaveBeenCalledWith(0.100001);
+    });
+    test('with invalid initial zoom factor, should do nothing', () => {
+      const event = {sender: {
+        getZoomFactor: jest.fn(() => 0.199999999999999),
+        setZoomFactor: jest.fn()
+      }};
+      main.init();
+      // When
+      mockIpc.listeners.zoomOut(event);
+      // Then
+      expect(event.sender.setZoomFactor).not.toHaveBeenCalled();
+    });
+  });
+  test('handleZoomReset', () => {
+    const event = {sender: {setZoomFactor: jest.fn()}};
+    main.init();
+    // When
+    mockIpc.listeners.zoomReset(event);
+    // Then
+    expect(event.sender.setZoomFactor).toHaveBeenCalledTimes(1);
+    expect(event.sender.setZoomFactor).toHaveBeenCalledWith(1);
+  });
+  describe('handleTabReorder', () => {
+    test('Several tabs, order changed, should update settings', () => {
+      // Given
+      mockSettings = {
+        tabs: [{id: '1337'}, {id: '313373'}]
+      };
+      main.init();
+      // When
+      mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
+      // Then
+      expect(settingsModule.updateSettings).toHaveBeenCalledWith({tabs: [{id: '313373'}, {id: '1337'}]});
+    });
+    test('Several tabs, order changed, should update tabManager order', () => {
+      // Given
+      mockSettings = {
+        tabs: [{id: '1337'}, {id: '313373'}]
+      };
+      jest.spyOn(tabManagerModule, 'sortTabs').mockImplementation();
+      main.init();
+      // When
+      mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
+      // Then
+      expect(tabManagerModule.sortTabs).toHaveBeenCalledWith(['313373', '1337']);
+    });
+    test('Several tabs with hidden, order changed, should update settings keeping hidden tags', () => {
+      // Given
+      mockSettings = {
+        tabs: [{id: '1337'}, {id: 'hidden'}, {id: '313373'}, {id: 'hidden-too'}]
+      };
+      main.init();
+      // When
+      mockIpc.listeners.tabReorder({}, {tabIds: ['313373', '1337']});
+      // Then
+      expect(settingsModule.updateSettings).toHaveBeenCalledWith({tabs: [
+        {id: '313373'}, {id: '1337'}, {id: 'hidden'}, {id: 'hidden-too'}
+      ]});
+    });
+  });
+});
diff --git a/src/tab-manager/__tests__/context-menu.test.js b/src/tab-manager/__tests__/context-menu.test.js
index c64e6eb..7f1c3dc 100644
--- a/src/tab-manager/__tests__/context-menu.test.js
+++ b/src/tab-manager/__tests__/context-menu.test.js
@@ -58,7 +58,7 @@ describe('Tab Manager context-menu test suite', () => {
       await listeners['context-menu'](event, params);
       // Then
       expect(electron.Menu).toHaveBeenCalledTimes(1);
-      expect(mockMenu.popup).toHaveBeenCalledWith({x: 13, y: 37});
+      expect(mockMenu.popup).toHaveBeenCalledWith({x: 14, y: 38});
     });
     describe('with native spellcheck', () => {
       beforeEach(() => {
@@ -97,9 +97,9 @@ describe('Tab Manager context-menu test suite', () => {
       params.editFlags = {};
       await listeners['context-menu'](event, params);
     });
-    test('should popup a menu at the specified location', async () => {
+    test('should popup a menu at the specified location (x+1, y+1)', async () => {
       expect(electron.Menu).toHaveBeenCalledTimes(1);
-      expect(mockMenu.popup).toHaveBeenCalledWith({x: 13, y: 37});
+      expect(mockMenu.popup).toHaveBeenCalledWith({x: 14, y: 38});
     });
     test.each(['Back', 'Reload', 'Cut', 'Copy', 'Copy image', 'Paste', 'DevTools'])(
       'adds MenuItem with label %s', async label => {
diff --git a/src/tab-manager/__tests__/preload.test.js b/src/tab-manager/__tests__/preload.test.js
index 04d96b6..cdf559d 100644
--- a/src/tab-manager/__tests__/preload.test.js
+++ b/src/tab-manager/__tests__/preload.test.js
@@ -19,12 +19,12 @@ const {waitFor} = require('@testing-library/dom');
 describe('Tab Manager Module preload test suite', () => {
   let mockElectron;
   beforeEach(() => {
-    mockElectron = {
-      webFrame: {setSpellCheckProvider: jest.fn()},
-      ipcRenderer: {invoke: async () => ({useNativeSpellChecker: false})}
-    };
     jest.resetModules();
-    jest.mock('electron', () => mockElectron);
+    jest.mock('electron', () => require('../../__tests__').mockElectronInstance());
+    mockElectron = require('electron');
+    // noinspection JSConstantReassignment,JSValidateTypes
+    mockElectron.webFrame = {setSpellCheckProvider: jest.fn()};
+    mockElectron.ipcRenderer.invoke = async () => ({useNativeSpellChecker: false});
     window.APP_EVENTS = require('../../constants').APP_EVENTS;
     window.ELECTRONIM_VERSION = '1.33.7';
     window.Notification = 'NOT A FUNCTION';
@@ -32,6 +32,7 @@ describe('Tab Manager Module preload test suite', () => {
   });
   describe('preload', () => {
     beforeEach(() => {
+      jest.spyOn(require('../preload.find-in-page'), 'initFindInPage');
       jest.spyOn(require('../preload.keyboard-shortcuts'), 'initKeyboardShortcuts');
       jest.spyOn(require('../preload.spell-check'), 'initSpellChecker');
     });
@@ -41,6 +42,7 @@ describe('Tab Manager Module preload test suite', () => {
       // Then
       expect(window.Notification).toEqual(expect.any(Function));
       expect(window.navigator.mediaDevices.getDisplayMedia).toEqual(expect.any(Function));
+      expect(require('../preload.find-in-page').initFindInPage).toHaveBeenCalledTimes(1);
       expect(require('../preload.keyboard-shortcuts').initKeyboardShortcuts).toHaveBeenCalledTimes(1);
       await waitFor(() => expect(mockElectron.webFrame.setSpellCheckProvider).toHaveBeenCalledTimes(1));
       expect(require('../preload.spell-check').initSpellChecker).toHaveBeenCalledTimes(1);