Repository: manusa/electronim
Pull request #271 (2023-01-21 07:30:37)

✨ cache storage cleared upon app quit
Relates to #266 

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=manusa_electronim&pullRequest=271)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=manusa_electronim&pullRequest=271&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=manusa_electronim&pullRequest=271&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=manusa_electronim&pullRequest=271&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=manusa_electronim&pullRequest=271&resolved=false&types=CODE_SMELL)

[![80.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/60-16px.png '80.0%')](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=271&metric=new_coverage&view=list) [80.0% Coverage](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=271&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=271&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=manusa_electronim&pullRequest=271&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/src/index.js b/src/index.js
index 20fe442..1e412ae 100644
--- a/src/index.js
+++ b/src/index.js
@@ -15,9 +15,10 @@
  */
 const {app} = require('electron');
 const {registerAppShortcuts} = require('./browser-window');
-const main = require('./main');
+const {init, quit} = require('./main');
 
 app.name = 'ElectronIM';
 
-app.on('ready', main.init);
+app.on('ready', init);
+app.on('quit', quit);
 app.on('web-contents-created', registerAppShortcuts);
diff --git a/src/main/index.js b/src/main/index.js
index 8798265..af076de 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -280,5 +280,5 @@ const init = () => {
 };
 
 module.exports = {
-  init
+  init, ...require('./quit')
 };
diff --git a/src/main/quit.js b/src/main/quit.js
new file mode 100644
index 0000000..247e923
--- /dev/null
+++ b/src/main/quit.js
@@ -0,0 +1,34 @@
+/*
+   Copyright 2023 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 {session} = require('electron');
+const {loadSettings} = require('../settings');
+
+const clearCache = s => Promise.all([
+  s.clearCache(),
+  s.clearCodeCaches({}),
+  s.clearHostResolverCache(),
+  s.clearStorageData({storages: ['serviceworkers', 'cachestorage']})
+]);
+
+const quit = () => {
+  const persistentSessions = loadSettings().tabs
+    .filter(({sandboxed = false}) => sandboxed)
+    .map(({id}) => session.fromPartition(`persist:${id}`));
+  // eslint-disable-next-line no-console
+  [...persistentSessions, session.defaultSession].forEach(s => clearCache(s).catch(console.error));
+};
+
+module.exports = {quit};


Test patch:
diff --git a/src/__tests__/electron.js b/src/__tests__/electron.js
index 88dcdf4..d4a2c91 100644
--- a/src/__tests__/electron.js
+++ b/src/__tests__/electron.js
@@ -62,6 +62,13 @@ const mockBrowserWindowInstance = () => {
 const mockElectronInstance = ({...overriddenProps} = {}) => {
   const browserViewInstance = mockBrowserWindowInstance();
   const browserWindowInstance = mockBrowserWindowInstance();
+  const sessionInstance = {
+    clearCache: jest.fn(),
+    clearCodeCaches: jest.fn(),
+    clearHostResolverCache: jest.fn(),
+    clearStorageData: jest.fn(),
+    userAgentInterceptor: true
+  };
   const trayInstance = {
     destroy: jest.fn(),
     on: jest.fn()
@@ -122,10 +129,8 @@ const mockElectronInstance = ({...overriddenProps} = {}) => {
     },
     nativeTheme: {},
     session: {
-      fromPartition: jest.fn(() => ({
-        userAgentInterceptor: true
-      })),
-      defaultSession: {userAgentInterceptor: true}
+      fromPartition: jest.fn(() => sessionInstance),
+      defaultSession: sessionInstance
     },
     shell: {
       openExternal: jest.fn()
diff --git a/src/__tests__/index.test.js b/src/__tests__/index.test.js
index fbfd78a..6f27f00 100644
--- a/src/__tests__/index.test.js
+++ b/src/__tests__/index.test.js
@@ -25,22 +25,14 @@ describe('Entrypoint test suite', () => {
     app = require('electron').app;
     main = require('../main');
   });
-  test('App initialization', () => {
-    // Given
-    // When
-    require('../index');
-    // Then
-    expect(app.name).toBe('ElectronIM');
-    expect(app.on).toHaveBeenCalledTimes(2);
-    expect(app.on). toHaveBeenCalledWith('ready', main.init);
-  });
-  test('Adds event listener to register app keyboard shortcuts on every webContents', () => {
-    // Given
-    // When
-    require('../index');
-    // Then
-    expect(app.on).toHaveBeenCalledTimes(2);
-    expect(app.on)
-      .toHaveBeenCalledWith('web-contents-created', require('../browser-window').registerAppShortcuts);
+  describe('App initialization', () => {
+    beforeEach(() => require('../'));
+    test('Sets app name', () => expect(app.name).toBe('ElectronIM'));
+    test('Adds ready event listener', () => expect(app.on).toHaveBeenCalledWith('ready', main.init));
+    test('Adds quit event listener', () => expect(app.on).toHaveBeenCalledWith('quit', main.quit));
+    test('Registers app keyboard shortcuts on every webContents created (web-contents-created)', () => {
+      expect(app.on)
+        .toHaveBeenCalledWith('web-contents-created', require('../browser-window').registerAppShortcuts);
+    });
   });
 });
diff --git a/src/main/__tests__/quit.test.js b/src/main/__tests__/quit.test.js
new file mode 100644
index 0000000..441dc38
--- /dev/null
+++ b/src/main/__tests__/quit.test.js
@@ -0,0 +1,43 @@
+/*
+   Copyright 2023 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 :: Quit test suite', () => {
+  let electron;
+  let quit;
+  beforeEach(() => {
+    jest.resetModules();
+    jest.mock('electron', () => require('../../__tests__').mockElectronInstance());
+    electron = require('electron');
+    quit = require('../').quit;
+  });
+  describe('quit()', () => {
+    beforeEach(() => {
+      quit();
+    });
+    test('Clears cache', () => {
+      expect(electron.session.defaultSession.clearCache).toHaveBeenCalled();
+    });
+    test('Clears code caches', () => {
+      expect(electron.session.defaultSession.clearCodeCaches).toHaveBeenCalled();
+    });
+    test('Clears host resolver cache', () => {
+      expect(electron.session.defaultSession.clearHostResolverCache).toHaveBeenCalled();
+    });
+    test('Clears storage data for service workers and cache storage', () => {
+      expect(electron.session.defaultSession.clearStorageData)
+        .toHaveBeenCalledWith({storages: ['serviceworkers', 'cachestorage']});
+    });
+  });
+});