Global Metrics

path: .metrics.halstead.N2
old: 651.0
new: 652.0

path: .metrics.halstead.effort
old: 406517.00263080874
new: 407353.7266703157

path: .metrics.halstead.purity_ratio
old: 0.5723775296831682
new: 0.5720792610382057

path: .metrics.halstead.difficulty
old: 28.982876712328768
new: 29.027397260273972

path: .metrics.halstead.level
old: 0.03450313127732482
new: 0.034450212364322795

path: .metrics.halstead.time
old: 22584.27792393382
new: 22630.76259279532

path: .metrics.halstead.length
old: 1918.0
new: 1919.0

path: .metrics.halstead.bugs
old: 1.829214162095996
new: 1.8317233197852971

path: .metrics.halstead.volume
old: 14026.109508235397
new: 14033.42239119068

path: .metrics.mi.mi_original
old: -0.7469138010056895
new: -0.7496242519401335

path: .metrics.mi.mi_sei
old: -63.976982217573266
new: -63.98089257169495

Spaces Data

Minimal test - lines (20, 43)

path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 10.5
new: 10.75

path: .spaces[0].spaces[0].metrics.halstead.volume
old: 580.0962752639431
new: 584.8511627661065

path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.11117445162443187
new: 0.11354847170170154

path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.09523809523809525
new: 0.09302325581395347

path: .spaces[0].spaces[0].metrics.halstead.time
old: 338.3894939039668
new: 349.28611109642475

path: .spaces[0].spaces[0].metrics.halstead.effort
old: 6091.010890271403
new: 6287.149999735645

path: .spaces[0].spaces[0].metrics.halstead.length
old: 122.0
new: 123.0

path: .spaces[0].spaces[0].metrics.halstead.N2
old: 42.0
new: 43.0

path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 0.8490817626142821
new: 0.8421786588531904

path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 85.7369187240447
new: 85.69446950872106

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 48.29683505048003
new: 48.23559377804298

path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 50.13854896142965
new: 50.1137248589012

Code

  beforeEach(() => {
    RPmessagePorts = [];
    function RP(url, isFromAboutNewTab = false) {
      this.url = url;
      this.messagePorts = RPmessagePorts;
      this.addMessageListener = globals.sandbox.spy();
      this.removeMessageListener = globals.sandbox.spy();
      this.sendAsyncMessage = globals.sandbox.spy();
      this.destroy = globals.sandbox.spy();
      this.isFromAboutNewTab = isFromAboutNewTab;
    }
    globals = new GlobalOverrider();
    const overridePageListener = globals.sandbox.stub();
    overridePageListener.withArgs(true).returns(new RP("about:newtab", true));
    overridePageListener.withArgs(false).returns(null);
    globals.set("AboutNewTab", {
      overridePageListener,
      reset: globals.sandbox.spy(),
    });
    globals.set("RemotePages", RP);
    globals.set("AboutHomeStartupCache", { onPreloadedNewTabMessage() {} });
    dispatch = globals.sandbox.spy();
    mm = new ActivityStreamMessageChannel({ dispatch });
  });

Minimal test - lines (22, 30)

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 108.5151046457366
new: 108.40562691790788

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 63.45912552382257
new: 63.39510346076484

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 80.95517120134282
new: 80.79722822631653

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 56.83303646976594
new: 61.45650001236268

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 6.071428571428571
new: 6.428571428571429

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.03384238709965076
new: 0.03565378414594695

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 17.0
new: 18.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 1022.994656455787
new: 1106.2170002225282

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 47.0
new: 48.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 0.6651303176348945
new: 0.6512734360175009

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 168.49323753389433
new: 172.0782000346155

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.16470588235294115
new: 0.15555555555555556

Code

    function RP(url, isFromAboutNewTab = false) {
      this.url = url;
      this.messagePorts = RPmessagePorts;
      this.addMessageListener = globals.sandbox.spy();
      this.removeMessageListener = globals.sandbox.spy();
      this.sendAsyncMessage = globals.sandbox.spy();
      this.destroy = globals.sandbox.spy();
      this.isFromAboutNewTab = isFromAboutNewTab;
    }

Minimal test - lines (15, 508)

path: .spaces[0].metrics.mi.mi_visual_studio
old: 0.08951468840349394
new: 0.08788982292400717

path: .spaces[0].metrics.mi.mi_original
old: 0.15307011716997465
new: 0.15029159720005225

path: .spaces[0].metrics.mi.mi_sei
old: -62.73215734828261
new: -62.73616590526424

path: .spaces[0].metrics.halstead.difficulty
old: 23.198529411764707
new: 23.235294117647054

path: .spaces[0].metrics.halstead.purity_ratio
old: 0.5329311744302083
new: 0.5326464889737819

path: .spaces[0].metrics.halstead.bugs
old: 1.5336058947987912
new: 1.5357727349376322

path: .spaces[0].metrics.halstead.length
old: 1871.0
new: 1872.0

path: .spaces[0].metrics.halstead.effort
old: 312070.3700014084
new: 312731.9924598964

path: .spaces[0].metrics.halstead.time
old: 17337.242777856023
new: 17373.999581105356

path: .spaces[0].metrics.halstead.volume
old: 13452.161749664512
new: 13459.351574223392

path: .spaces[0].metrics.halstead.N2
old: 631.0
new: 632.0

path: .spaces[0].metrics.halstead.level
old: 0.043106180665610144
new: 0.043037974683544304

Code

describe("ActivityStreamMessageChannel", () => {
  let globals;
  let dispatch;
  let mm;
  let RPmessagePorts;
  beforeEach(() => {
    RPmessagePorts = [];
    function RP(url, isFromAboutNewTab = false) {
      this.url = url;
      this.messagePorts = RPmessagePorts;
      this.addMessageListener = globals.sandbox.spy();
      this.removeMessageListener = globals.sandbox.spy();
      this.sendAsyncMessage = globals.sandbox.spy();
      this.destroy = globals.sandbox.spy();
      this.isFromAboutNewTab = isFromAboutNewTab;
    }
    globals = new GlobalOverrider();
    const overridePageListener = globals.sandbox.stub();
    overridePageListener.withArgs(true).returns(new RP("about:newtab", true));
    overridePageListener.withArgs(false).returns(null);
    globals.set("AboutNewTab", {
      overridePageListener,
      reset: globals.sandbox.spy(),
    });
    globals.set("RemotePages", RP);
    globals.set("AboutHomeStartupCache", { onPreloadedNewTabMessage() {} });
    dispatch = globals.sandbox.spy();
    mm = new ActivityStreamMessageChannel({ dispatch });
  });

  afterEach(() => globals.restore());

  describe("portID validation", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.createSandbox();
      sandbox.spy(global.Cu, "reportError");
    });
    afterEach(() => {
      sandbox.restore();
    });
    it("should log errors for an invalid portID", () => {
      mm.validatePortID({});
      mm.validatePortID({});
      mm.validatePortID({});

      assert.equal(global.Cu.reportError.callCount, 3);
    });
  });

  it("should exist", () => {
    assert.ok(ActivityStreamMessageChannel);
  });
  it("should apply default options", () => {
    mm = new ActivityStreamMessageChannel();
    OPTIONS.forEach(o => assert.equal(mm[o], DEFAULT_OPTIONS[o], o));
  });
  it("should add options", () => {
    const options = {
      dispatch: () => {},
      pageURL: "FOO.html",
      outgoingMessageName: "OUT",
      incomingMessageName: "IN",
    };
    mm = new ActivityStreamMessageChannel(options);
    OPTIONS.forEach(o => assert.equal(mm[o], options[o], o));
  });
  it("should throw an error if no dispatcher was provided", () => {
    mm = new ActivityStreamMessageChannel();
    assert.throws(() => mm.dispatch({ type: "FOO" }));
  });
  describe("Creating/destroying the channel", () => {
    describe("#createChannel", () => {
      it("should create .channel with the correct URL", () => {
        mm.createChannel();
        assert.ok(mm.channel);
        assert.equal(mm.channel.url, mm.pageURL);
      });
      it("should add 4 message listeners", () => {
        mm.createChannel();
        assert.callCount(mm.channel.addMessageListener, 4);
      });
      it("should add the custom message listener to the channel", () => {
        mm.createChannel();
        assert.calledWith(
          mm.channel.addMessageListener,
          mm.incomingMessageName,
          mm.onMessage
        );
      });
      it("should override AboutNewTab", () => {
        mm.createChannel();
        assert.calledOnce(global.AboutNewTab.overridePageListener);
      });
      it("should use the channel passed by AboutNewTab on override", () => {
        mm.createChannel();
        assert.ok(mm.channel.isFromAboutNewTab);
      });
      it("should not override AboutNewTab if the pageURL is not about:newtab", () => {
        mm = new ActivityStreamMessageChannel({ pageURL: "foo.html" });
        mm.createChannel();
        assert.notCalled(global.AboutNewTab.overridePageListener);
      });
    });
    describe("#simulateMessagesForExistingTabs", () => {
      beforeEach(() => {
        sinon.stub(mm, "onActionFromContent");
        mm.createChannel();
      });
      it("should simulate init for existing ports", () => {
        RPmessagePorts.push({
          url: "about:monkeys",
          loaded: false,
          portID: "inited",
          simulated: true,
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        });
        RPmessagePorts.push({
          url: "about:sheep",
          loaded: true,
          portID: "loaded",
          simulated: true,
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        });

        mm.simulateMessagesForExistingTabs();

        assert.calledWith(mm.onActionFromContent.firstCall, {
          type: at.NEW_TAB_INIT,
          data: RPmessagePorts[0],
        });
        assert.calledWith(mm.onActionFromContent.secondCall, {
          type: at.NEW_TAB_INIT,
          data: RPmessagePorts[1],
        });
      });
      it("should simulate load for loaded ports", () => {
        RPmessagePorts.push({
          loaded: true,
          portID: "foo",
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        });

        mm.simulateMessagesForExistingTabs();

        assert.calledWith(
          mm.onActionFromContent,
          { type: at.NEW_TAB_LOAD },
          "foo"
        );
      });
      it("should set renderLayers on preloaded browsers after load", () => {
        RPmessagePorts.push({
          loaded: true,
          portID: "foo",
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {
              STATE_MAXIMIZED: 1,
              STATE_MINIMIZED: 2,
              STATE_NORMAL: 3,
              STATE_FULLSCREEN: 4,
              windowState: 3,
              isFullyOccluded: false,
            },
          },
        });
        mm.simulateMessagesForExistingTabs();
        assert.equal(RPmessagePorts[0].browser.renderLayers, true);
      });
    });
    describe("#destroyChannel", () => {
      let channel;
      beforeEach(() => {
        mm.createChannel();
        channel = mm.channel;
      });
      it("should set .channel to null", () => {
        mm.destroyChannel();
        assert.isNull(mm.channel);
      });
      it("should reset AboutNewTab, and pass back its channel", () => {
        mm.destroyChannel();
        assert.calledOnce(global.AboutNewTab.reset);
        assert.calledWith(global.AboutNewTab.reset, channel);
      });
      it("should not reset AboutNewTab if the pageURL is not about:newtab", () => {
        mm = new ActivityStreamMessageChannel({ pageURL: "foo.html" });
        mm.createChannel();
        mm.destroyChannel();
        assert.notCalled(global.AboutNewTab.reset);
      });
      it("should call channel.destroy() if pageURL is not about:newtab", () => {
        mm = new ActivityStreamMessageChannel({ pageURL: "foo.html" });
        mm.createChannel();
        channel = mm.channel;
        mm.destroyChannel();
        assert.calledOnce(channel.destroy);
      });
    });
  });
  describe("Message handling", () => {
    describe("#getTargetById", () => {
      it("should get an id if it exists", () => {
        const t = { portID: "foo:1" };
        mm.createChannel();
        mm.channel.messagePorts.push(t);
        assert.equal(mm.getTargetById("foo:1"), t);
      });
      it("should return null if the target doesn't exist", () => {
        const t = { portID: "foo:2" };
        mm.createChannel();
        mm.channel.messagePorts.push(t);
        assert.equal(mm.getTargetById("bar:3"), null);
      });
    });
    describe("#getPreloadedBrowser", () => {
      it("should get a preloaded browser if it exists", () => {
        const port = {
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        assert.equal(mm.getPreloadedBrowser()[0], port);
      });
      it("should get all the preloaded browsers across windows if they exist", () => {
        const port = {
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        mm.channel.messagePorts.push(port);
        assert.equal(mm.getPreloadedBrowser().length, 2);
      });
      it("should return null if there is no preloaded browser", () => {
        const port = {
          browser: {
            getAttribute: () => "consumed",
            ownerGlobal: {},
          },
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        assert.equal(mm.getPreloadedBrowser(), null);
      });
    });
    describe("#onNewTabInit", () => {
      it("should dispatch a NEW_TAB_INIT action", () => {
        const t = { portID: "foo", url: "about:monkeys" };
        sinon.stub(mm, "onActionFromContent");

        mm.onNewTabInit({ target: t });

        assert.calledWith(mm.onActionFromContent, {
          type: at.NEW_TAB_INIT,
          data: t,
        });
      });
    });
    describe("#onNewTabLoad", () => {
      it("should dispatch a NEW_TAB_LOAD action", () => {
        const t = {
          portID: "foo",
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
        };
        sinon.stub(mm, "onActionFromContent");
        mm.onNewTabLoad({ target: t });
        assert.calledWith(
          mm.onActionFromContent,
          { type: at.NEW_TAB_LOAD },
          "foo"
        );
      });
    });
    describe("#onNewTabUnload", () => {
      it("should dispatch a NEW_TAB_UNLOAD action", () => {
        const t = { portID: "foo" };
        sinon.stub(mm, "onActionFromContent");
        mm.onNewTabUnload({ target: t });
        assert.calledWith(
          mm.onActionFromContent,
          { type: at.NEW_TAB_UNLOAD },
          "foo"
        );
      });
    });
    describe("#onMessage", () => {
      let sandbox;
      beforeEach(() => {
        sandbox = sinon.createSandbox();
        sandbox.spy(global.Cu, "reportError");
      });
      afterEach(() => sandbox.restore());
      it("should report an error if the msg.data is missing", () => {
        mm.onMessage({ target: { portID: "foo" } });
        assert.calledOnce(global.Cu.reportError);
      });
      it("should report an error if the msg.data.type is missing", () => {
        mm.onMessage({ target: { portID: "foo" }, data: "foo" });
        assert.calledOnce(global.Cu.reportError);
      });
      it("should call onActionFromContent", () => {
        sinon.stub(mm, "onActionFromContent");
        const action = {
          data: { data: {}, type: "FOO" },
          target: { portID: "foo" },
        };
        const expectedAction = {
          type: action.data.type,
          data: action.data.data,
          _target: { portID: "foo" },
        };
        mm.onMessage(action);
        assert.calledWith(mm.onActionFromContent, expectedAction, "foo");
      });
    });
  });
  describe("Sending and broadcasting", () => {
    describe("#send", () => {
      it("should send a message on the right port", () => {
        const t = { portID: "foo:3", sendAsyncMessage: sinon.spy() };
        mm.createChannel();
        mm.channel.messagePorts = [t];
        const action = ac.AlsoToOneContent({ type: "HELLO" }, "foo:3");
        mm.send(action);
        assert.calledWith(
          t.sendAsyncMessage,
          DEFAULT_OPTIONS.outgoingMessageName,
          action
        );
      });
      it("should not throw if the target isn't around", () => {
        mm.createChannel();
        // port is not added to the channel
        const action = ac.AlsoToOneContent({ type: "HELLO" }, "foo:4");

        assert.doesNotThrow(() => mm.send(action));
      });
    });
    describe("#broadcast", () => {
      it("should send a message on the channel", () => {
        mm.createChannel();
        const action = ac.BroadcastToContent({ type: "HELLO" });
        mm.broadcast(action);
        assert.calledWith(
          mm.channel.sendAsyncMessage,
          DEFAULT_OPTIONS.outgoingMessageName,
          action
        );
      });
    });
    describe("#preloaded browser", () => {
      it("should send the message to the preloaded browser if there's data and a preloaded browser exists", () => {
        const port = {
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
          sendAsyncMessage: sinon.spy(),
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        const action = ac.AlsoToPreloaded({ type: "HELLO", data: 10 });
        mm.sendToPreloaded(action);
        assert.calledWith(
          port.sendAsyncMessage,
          DEFAULT_OPTIONS.outgoingMessageName,
          action
        );
      });
      it("should send the message to all the preloaded browsers if there's data and they exist", () => {
        const port = {
          browser: {
            getAttribute: () => "preloaded",
            ownerGlobal: {},
          },
          sendAsyncMessage: sinon.spy(),
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        mm.channel.messagePorts.push(port);
        mm.sendToPreloaded(ac.AlsoToPreloaded({ type: "HELLO", data: 10 }));
        assert.calledTwice(port.sendAsyncMessage);
      });
      it("should not send the message to the preloaded browser if there's no data and a preloaded browser does not exists", () => {
        const port = {
          browser: {
            getAttribute: () => "consumed",
            ownerGlobal: {},
          },
          sendAsyncMessage: sinon.spy(),
        };
        mm.createChannel();
        mm.channel.messagePorts.push(port);
        const action = ac.AlsoToPreloaded({ type: "HELLO" });
        mm.sendToPreloaded(action);
        assert.notCalled(port.sendAsyncMessage);
      });
    });
  });
  describe("Handling actions", () => {
    describe("#onActionFromContent", () => {
      beforeEach(() => mm.onActionFromContent({ type: "FOO" }, "foo:5"));
      it("should dispatch a AlsoToMain action", () => {
        assert.calledOnce(dispatch);
        const [action] = dispatch.firstCall.args;
        assert.equal(action.type, "FOO", "action.type");
      });
      it("should have the right fromTarget", () => {
        const [action] = dispatch.firstCall.args;
        assert.equal(action.meta.fromTarget, "foo:5", "meta.fromTarget");
      });
    });
    describe("#middleware", () => {
      let store;
      beforeEach(() => {
        store = createStore(addNumberReducer, applyMiddleware(mm.middleware));
      });
      it("should just call next if no channel is found", () => {
        store.dispatch({ type: "ADD", data: 10 });
        assert.equal(store.getState(), 10);
      });
      it("should call .send but not affect the main store if an OnlyToOneContent action is dispatched", () => {
        sinon.stub(mm, "send");
        const action = ac.OnlyToOneContent({ type: "ADD", data: 10 }, "foo");
        mm.createChannel();

        store.dispatch(action);

        assert.calledWith(mm.send, action);
        assert.equal(store.getState(), 0);
      });
      it("should call .send and update the main store if an AlsoToOneContent action is dispatched", () => {
        sinon.stub(mm, "send");
        const action = ac.AlsoToOneContent({ type: "ADD", data: 10 }, "foo");
        mm.createChannel();

        store.dispatch(action);

        assert.calledWith(mm.send, action);
        assert.equal(store.getState(), 10);
      });
      it("should call .broadcast if the action is BroadcastToContent", () => {
        sinon.stub(mm, "broadcast");
        const action = ac.BroadcastToContent({ type: "FOO" });

        mm.createChannel();
        store.dispatch(action);

        assert.calledWith(mm.broadcast, action);
      });
      it("should call .sendToPreloaded if the action is AlsoToPreloaded", () => {
        sinon.stub(mm, "sendToPreloaded");
        const action = ac.AlsoToPreloaded({ type: "FOO" });

        mm.createChannel();
        store.dispatch(action);

        assert.calledWith(mm.sendToPreloaded, action);
      });
      it("should dispatch other actions normally", () => {
        sinon.stub(mm, "send");
        sinon.stub(mm, "broadcast");
        sinon.stub(mm, "sendToPreloaded");

        mm.createChannel();
        store.dispatch({ type: "ADD", data: 1 });

        assert.equal(store.getState(), 1);
        assert.notCalled(mm.send);
        assert.notCalled(mm.broadcast);
        assert.notCalled(mm.sendToPreloaded);
      });
    });
  });
});