From 7c892c8d765a805ad7b71b2fe140cba995828a10 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Mon, 6 Nov 2017 16:41:28 +0100
Subject: [PATCH] when plugin is unregistered check about removing listeners is
 added and all listeners are removed by force if necessary

---
 .../src/main/js/plugin/MinervaPluginProxy.js  | 10 +++++
 frontend-js/src/main/js/plugin/Plugin.js      |  4 ++
 .../test/js/plugin/MinervaPluginProxy-test.js | 37 +++++++++++++++++++
 frontend-js/src/test/js/plugin/Plugin-test.js | 18 +++++++++
 .../plugin-invalid/unclean-unregister.js      | 23 ++++++++++++
 5 files changed, 92 insertions(+)
 create mode 100644 frontend-js/testFiles/plugin-invalid/unclean-unregister.js

diff --git a/frontend-js/src/main/js/plugin/MinervaPluginProxy.js b/frontend-js/src/main/js/plugin/MinervaPluginProxy.js
index ea16e1ff7f..59e9adb587 100644
--- a/frontend-js/src/main/js/plugin/MinervaPluginProxy.js
+++ b/frontend-js/src/main/js/plugin/MinervaPluginProxy.js
@@ -267,6 +267,16 @@ function createProjectMap(options) {
 
       listenersData.splice(indexToBeRemoved, 1);
     },
+    removeAllListeners: function () {
+      var removedListeners = [];
+      for (var i = 0; i < listenersData.length; i++) {
+        var listenerData = listenersData[i];
+        var listenerWrapper = listenersData[i].wrapper;
+        listenerData.object.removeListener(listenerData.type, listenerWrapper);
+        removedListeners.push(listenerData.listener);
+      }
+      return removedListeners;
+    },
     getHighlightedBioEntities: function (dbOverlayName) {
       if (dbOverlayName === undefined) {
         dbOverlayName = pluginId;
diff --git a/frontend-js/src/main/js/plugin/Plugin.js b/frontend-js/src/main/js/plugin/Plugin.js
index 3080f52465..14157eb0f9 100644
--- a/frontend-js/src/main/js/plugin/Plugin.js
+++ b/frontend-js/src/main/js/plugin/Plugin.js
@@ -94,6 +94,10 @@ Plugin.prototype.unload = function () {
   return Promise.resolve().then(function () {
     return self.getLoadedPluginData().unregister();
   }).then(function () {
+    var removedListeners = self.getMinervaPluginProxy().project.map.removeAllListeners();
+    if (removedListeners.length > 0) {
+      logger.warn("'"+self.getLoadedPluginData().getName() + "' plugin didn't remove all registered listeners");
+    }
     return self.destroy();
   });
 };
diff --git a/frontend-js/src/test/js/plugin/MinervaPluginProxy-test.js b/frontend-js/src/test/js/plugin/MinervaPluginProxy-test.js
index 71339d6b56..14143e1fab 100644
--- a/frontend-js/src/test/js/plugin/MinervaPluginProxy-test.js
+++ b/frontend-js/src/test/js/plugin/MinervaPluginProxy-test.js
@@ -125,6 +125,43 @@ describe('MinervaPluginProxy', function () {
       });
     });
   });
+  describe('removeAllListeners', function () {
+    it('valid listener', function () {
+      var callbackOk = false;
+      var map, options;
+      return ServerConnector.getProject().then(function (project) {
+        map = helper.createCustomMap(project);
+        helper.createSearchDbOverlay(map);
+        var proxy = createProxy(map);
+
+        options = {
+          dbOverlayName: "search",
+          type: "onSearch",
+          callback: function (elements) {
+            assert.ok(elements.length > 0);
+            assert.ok(elements[0].length !== undefined, "Array of arrays expected as onSearch result");
+            callbackOk = true;
+          }
+        };
+        proxy.project.map.addListener(options);
+        var removedListeners = proxy.project.map.removeAllListeners();
+        assert.equal(1, removedListeners.length);
+        return map.destroy();
+      });
+    });
+    it('no listeners', function () {
+      var callbackOk = false;
+      var map, options;
+      return ServerConnector.getProject().then(function (project) {
+        map = helper.createCustomMap(project);
+        helper.createSearchDbOverlay(map);
+        var proxy = createProxy(map);
+        var removedListeners = proxy.project.map.removeAllListeners();
+        assert.equal(0, removedListeners.length);
+        return map.destroy();
+      });
+    });
+  });
 
   describe("getBioEntityById", function () {
     it("for alias", function () {
diff --git a/frontend-js/src/test/js/plugin/Plugin-test.js b/frontend-js/src/test/js/plugin/Plugin-test.js
index 601df1310b..cac782f04f 100644
--- a/frontend-js/src/test/js/plugin/Plugin-test.js
+++ b/frontend-js/src/test/js/plugin/Plugin-test.js
@@ -81,4 +81,22 @@ describe('Plugin', function () {
       });
     });
   });
+  describe('unload', function () {
+    it('warning about cleaning', function () {
+      var map = helper.createCustomMap();
+      helper.createSearchDbOverlay(map);
+
+      var plugin = new Plugin({
+        url: "./testFiles/plugin-invalid/unclean-unregister.js",
+        map: map,
+        configuration: helper.getConfiguration()
+      });
+      return plugin.load().then(function () {
+        assert.equal(0, logger.getWarnings().length);
+        return plugin.unload();
+      }).then(function () {
+        assert.equal(1, logger.getWarnings().length);
+      });
+    });
+  });
 });
diff --git a/frontend-js/testFiles/plugin-invalid/unclean-unregister.js b/frontend-js/testFiles/plugin-invalid/unclean-unregister.js
new file mode 100644
index 0000000000..a309c06a47
--- /dev/null
+++ b/frontend-js/testFiles/plugin-invalid/unclean-unregister.js
@@ -0,0 +1,23 @@
+define(function () {
+  return {
+    register: function (minervaObject) {
+      options = {
+        dbOverlayName: "search",
+        type: "onSearch",
+        callback: function (elements) {
+          console.log("hi there");
+        }
+      };
+      minervaObject.project.map.addListener(options);
+    },
+    unregister: function () {
+      console.log("unregistering test plugin");
+    },
+    getName: function () {
+      return "high test";
+    },
+    getVersion: function () {
+      return "0.0.1";
+    }
+  };
+});
\ No newline at end of file
-- 
GitLab