var assert = require('assert');
var ift = require('../library/ift');
var Transport = require('../library/base/transport');
var util = require('./util');

describe('ift', function() {
  var createIframe = sinon.stub(), _createIframe;

  // Hook into ParentTransport#_createIframe to attach a `code` query param
  // containing a raw function to execute on the child page for a given test.
  _createIframe = ift.ParentTransport.prototype._createIframe;
  function stubChild(code) {
    createIframe = sinon.stub(ift.ParentTransport.prototype, '_createIframe', function(uri) {
      return _createIframe.call(this, uri + '?code=' + encodeURIComponent(code));
    });
  }

  function dispatchMessageEvent(data, origin) {
    util.dispatchEvent(window, 'message', {
      data: data,
      origin: origin
    }, 'MessageEvent', ['data', 'origin']);
  }

  describe('Transport', function() {
    it("ignores 'message' events from non-targeted origins", function() {
      var incoming = sinon.stub();
      var transport = new Transport(['http://origin1']);
      transport.on('incoming', incoming);
      dispatchMessageEvent('data', 'http://origin1');
      sinon.assert.calledOnce(incoming);
      dispatchMessageEvent('data', 'http://origin2');
      sinon.assert.calledOnce(incoming);
    });

    describe('#destroy', function() {
      it("stops listening for 'message'", function() {
        var transport = new Transport(['http://origin']);
        var incoming = sinon.stub();
        transport.on('incoming', incoming);
        dispatchMessageEvent('data', 'http://origin');
        sinon.assert.calledOnce(incoming);
        transport.destroy();
        dispatchMessageEvent('data', 'http://origin');
        sinon.assert.calledOnce(incoming);
      });

      it("clears out event listeners", function() {
        var transport = new Transport(['http://origin']);
        var incoming = sinon.stub();
        transport.on('incoming', incoming);
        transport.trigger('incoming');
        sinon.assert.calledOnce(incoming);
        transport.destroy();
        transport.trigger('incoming');
        sinon.assert.calledOnce(incoming);
      });
    });
  });

  describe('ParentTransport', function() {
    describe('#constructor', function() {
      it("creates an iframe from childOrigin and childPath", function() {
        var appendChild = sinon.stub(document.body, 'appendChild');
        var transport = new ift.ParentTransport('http://origin', '/path');
        assert.strictEqual(transport.iframe.src, 'http://origin/path');
        appendChild.restore();
      });
    });

    describe('#ready', function() {
      var appendChild, transport, onReady;

      beforeEach(function() {
        appendChild = sinon.stub(document.body, 'appendChild');
        transport = new ift.ParentTransport('http://origin', '/path');
        onReady = sinon.stub();
      });

      afterEach(function() {
        appendChild.restore();
      });

      it("invokes onReady once child sends 'ready' postMessage", function() {
        transport.ready(onReady);
        sinon.assert.notCalled(onReady);
        dispatchMessageEvent('ready', 'http://origin');
        sinon.assert.calledOnce(onReady);
        sinon.assert.calledWith(onReady, transport);
      });

      it("only invokes onReady once", function() {
        transport.ready(onReady);
        sinon.assert.notCalled(onReady);
        dispatchMessageEvent('ready', 'http://origin');
        sinon.assert.calledOnce(onReady);
        dispatchMessageEvent('ready', 'http://origin');
        sinon.assert.calledOnce(onReady);
        transport.trigger('ready');
        sinon.assert.calledOnce(onReady);
      });

      it("fires immediately if transport is already ready", function() {
        dispatchMessageEvent('ready', 'http://origin');
        transport.ready(onReady);
        sinon.assert.calledOnce(onReady);
      });
    });

    describe('#send', function() {
      it("calls postMessage on the iframe with message and childOrigin", function() {
        var transport = new ift.ParentTransport(CHILD_ORIGIN, CHILD_PATH);
        var postMessage = sinon.stub(transport.iframe.contentWindow, 'postMessage');
        transport.send('test');
        sinon.assert.calledOnce(postMessage);
        sinon.assert.calledWith(postMessage, 'test', CHILD_ORIGIN);
      });
    });

    describe('#destroy', function() {
      it("removes iframe from the dom", function() {
        var transport = new ift.ParentTransport(CHILD_ORIGIN, CHILD_PATH);
        assert(transport.iframe.parentNode);
        transport.destroy();
        assert.strictEqual(transport.iframe.parentNode, null);
      });
    });
  });
});

@@ -2210,52 +2210,8 @@
 ) %7B%0A
-    describe('#constructor', function() %7B%0A  
     
@@ -2280,26 +2280,24 @@
 n() %7B%0A      
- 
- 
 var appendCh
@@ -2340,26 +2340,24 @@
 endChild');%0A
-  
       var tr
@@ -2415,34 +2415,32 @@
 '/path');%0A      
-  
 assert.strictEqu
@@ -2489,26 +2489,24 @@
 th');%0A      
- 
- 
 appendChild.
@@ -2516,27 +2516,327 @@
 tore();%0A    
-  %7D
+%7D);%0A%0A    it(%22creates an iframe not visible on the page%22, function() %7B%0A      var transport = new ift.ParentTransport(CHILD_ORIGIN, CHILD_PATH);%0A      assert(transport.iframe.offsetTop %3C 100);%0A      assert.strictEqual(transport.iframe.border, 0);%0A      assert.strictEqual(transport.iframe.frameBorder, '0'
 );%0A    %7D);%0A%0A

Test hidden iframe