Merge "Initial test suite for plugins"
diff --git a/dev/js/runner/plugin.html b/dev/js/runner/plugin.html
new file mode 100644
index 0000000..94f3142
--- /dev/null
+++ b/dev/js/runner/plugin.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Spec Runner for Plugins</title>
+    <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
+    <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+    <script src="../lib/require.js"></script>
+    <script src="../lib/jasmine-2.1.1/jasmine.js"></script>
+    <script src="../lib/jasmine-2.1.1/jasmine-html.js"></script>
+    <script src="../lib/jasmine-2.1.1/boot.js"></script>
+    <script>
+    require.config({
+      baseUrl: "../src",
+      paths: {
+        "lib" : "../lib",
+        "spec" : "../spec"
+      }
+    });
+    require([
+      'lib/domReady!',
+      'spec/pluginSpec'
+    ],
+    function () {
+      if (jsApiReporter.finished === true)
+        jasmine.getEnv().execute();
+    });
+    </script>
+  </head>
+  <body>
+  </body>
+</html>
diff --git a/dev/js/spec/pluginSpec.js b/dev/js/spec/pluginSpec.js
new file mode 100644
index 0000000..fa74486
--- /dev/null
+++ b/dev/js/spec/pluginSpec.js
@@ -0,0 +1,28 @@
+define(['plugin/server','plugin/widget'], function (pluginServerClass, widgetClass) {
+
+  describe('KorAP.Plugin.Server', function () {
+
+    it('should be initializable', function () {
+      var manager = pluginServerClass.create();
+      expect(manager).toBeTruthy();
+      manager.destroy();
+    });
+
+    it('should add a widget', function () {
+      var manager = pluginServerClass.create();
+      var div = document.createElement("div");
+      var id = manager.addWidget(div, 'about:blank');
+      expect(id).toMatch(/^id-/);
+      expect(div.firstChild.tagName).toEqual("IFRAME");
+      manager.destroy();
+    });
+  });
+
+  describe('KorAP.Plugin.Widget', function () {
+    it('should be initializable', function () {
+      var widget = widgetClass.create();
+      expect(widget).toBeTruthy();
+    });
+  });
+
+});
diff --git a/dev/js/src/plugin/client.js b/dev/js/src/plugin/client.js
index 64f0bc4..4e7e337 100644
--- a/dev/js/src/plugin/client.js
+++ b/dev/js/src/plugin/client.js
@@ -50,8 +50,6 @@
     // Send a message
     _sendMsg : function (data) {
       data["originID"] = this.widgetID;
-
-      // TODO: This should send a correct origin
       window.parent.postMessage(data, this.server);
     },
 
diff --git a/dev/js/src/plugin/server.js b/dev/js/src/plugin/server.js
index 7dd0fce..82a4193 100644
--- a/dev/js/src/plugin/server.js
+++ b/dev/js/src/plugin/server.js
@@ -48,9 +48,8 @@
       //   only in case there is a widget
 
       var that = this;
-      window.addEventListener("message", function (e) {
-        that._receiveMsg(e);
-      });
+      this._listener = this._receiveMsg.bind(that);
+      window.addEventListener("message", this._listener);
 
       // Every second increase the limits of all registered widgets
       var myTimer = setInterval(function () {
@@ -82,6 +81,8 @@
       element.appendChild(
         widget.element()
       );
+
+      return id;
     },
 
     // Receive a call from an embedded iframe.
@@ -140,6 +141,13 @@
     // Get a random identifier
     _randomID : function () {
       return randomID(20);
+    },
+
+    // Destructor, just for testing scenarios
+    destroy : function () {
+      limits = {};
+      widgets = {};
+      window.removeEventListener("message", this._listener);
     }
   }
 });