blob: ce7137e1c9e9e1d4fa6ba1391d9669d236ee1c67 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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("channel", function () {
var channel = require('cordova/channel'),
multiChannel,
stickyChannel;
function callCount(spy) {
return spy.argsForCall.length;
}
function expectCallCount(spy, count) {
expect(callCount(spy)).toEqual(count);
}
beforeEach(function() {
multiChannel = channel.create('multiChannel');
stickyChannel = channel.createSticky('stickyChannel');
});
describe("subscribe method", function() {
it("should throw an exception if no function is provided", function() {
expect(function() {
multiChannel.subscribe();
}).toThrow();
expect(function() {
multiChannel.subscribe(null);
}).toThrow();
expect(function() {
multiChannel.subscribe(undefined);
}).toThrow();
expect(function() {
multiChannel.subscribe({apply:function(){},call:function(){}});
}).toThrow();
});
it("should not change number of handlers if no function is provided", function() {
var initialLength = multiChannel.numHandlers;
try {
multiChannel.subscribe();
} catch(e) {}
expect(multiChannel.numHandlers).toEqual(initialLength);
try {
multiChannel.subscribe(null);
} catch(e) {}
expect(multiChannel.numHandlers).toEqual(initialLength);
});
it("should not change number of handlers when subscribing same function multiple times", function() {
var handler = function(){};
multiChannel.subscribe(handler);
multiChannel.subscribe(handler);
stickyChannel.subscribe(handler);
stickyChannel.subscribe(handler);
expect(multiChannel.numHandlers).toEqual(1);
expect(stickyChannel.numHandlers).toEqual(1);
});
});
describe("unsubscribe method", function() {
it("should throw an exception if passed in null or undefined", function() {
expect(function() {
multiChannel.unsubscribe();
}).toThrow();
expect(function() {
multiChannel.unsubscribe(null);
}).toThrow();
});
it("should not decrement numHandlers if unsubscribing something that does not exist", function() {
multiChannel.subscribe(function() {});
multiChannel.unsubscribe(function() {});
expect(multiChannel.numHandlers).toEqual(1);
});
it("should change the handlers length appropriately", function() {
var firstHandler = function() {};
var secondHandler = function() {};
var thirdHandler = function() {};
multiChannel.subscribe(firstHandler);
multiChannel.subscribe(secondHandler);
multiChannel.subscribe(thirdHandler);
expect(multiChannel.numHandlers).toEqual(3);
multiChannel.unsubscribe(thirdHandler);
expect(multiChannel.numHandlers).toEqual(2);
multiChannel.unsubscribe(firstHandler);
multiChannel.unsubscribe(secondHandler);
expect(multiChannel.numHandlers).toEqual(0);
});
it("should not decrement handlers length more than once if unsubscribing a single handler", function() {
var firstHandler = function(){};
multiChannel.subscribe(firstHandler);
expect(multiChannel.numHandlers).toEqual(1);
multiChannel.unsubscribe(firstHandler);
multiChannel.unsubscribe(firstHandler);
multiChannel.unsubscribe(firstHandler);
multiChannel.unsubscribe(firstHandler);
expect(multiChannel.numHandlers).toEqual(0);
});
it("should not unregister a function registered with a different handler", function() {
var cHandler = function(){};
var c2Handler = function(){};
var c2 = channel.create('jables');
multiChannel.subscribe(cHandler);
c2.subscribe(c2Handler);
expect(multiChannel.numHandlers).toEqual(1);
expect(c2.numHandlers).toEqual(1);
multiChannel.unsubscribe(c2Handler);
c2.unsubscribe(cHandler);
expect(multiChannel.numHandlers).toEqual(1);
expect(c2.numHandlers).toEqual(1);
});
});
function commonFireTests(multi) {
it("should fire all subscribed handlers", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy();
var anotherOne = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.subscribe(anotherOne);
testChannel.fire();
expectCallCount(handler, 1);
expectCallCount(anotherOne, 1);
});
it("should pass params to handlers", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.fire(1, 2, 3);
expect(handler.argsForCall[0]).toEqual({0:1, 1:2, 2:3});
});
it("should not fire a handler that was unsubscribed", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy();
var anotherOne = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.subscribe(anotherOne);
testChannel.unsubscribe(handler);
testChannel.fire();
expectCallCount(handler, 0);
expectCallCount(anotherOne, 1);
});
it("should not fire a handler more than once if it was subscribed more than once", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.subscribe(handler);
testChannel.subscribe(handler);
testChannel.fire();
expectCallCount(handler, 1);
});
it("handler should be called when subscribed, removed, and subscribed again", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.unsubscribe(handler);
testChannel.subscribe(handler);
testChannel.fire();
expectCallCount(handler, 1);
});
it("should not prevent a callback from firing when it is removed during firing.", function() {
var testChannel = multi ? multiChannel : stickyChannel;
var handler = jasmine.createSpy().andCallFake(function() { testChannel.unsubscribe(handler2); });
var handler2 = jasmine.createSpy();
testChannel.subscribe(handler);
testChannel.subscribe(handler2);
testChannel.fire();
expectCallCount(handler, 1);
expectCallCount(handler2, 1);
});
}
describe("fire method for sticky channels", function() {
commonFireTests(false);
it("should instantly trigger the callback if the event has already been fired", function () {
var before = jasmine.createSpy('before'),
after = jasmine.createSpy('after');
stickyChannel.subscribe(before);
stickyChannel.fire(1, 2, 3);
stickyChannel.subscribe(after);
expectCallCount(before, 1);
expectCallCount(after, 1);
expect(after.argsForCall[0]).toEqual({0:1, 1:2, 2:3});
});
it("should instantly trigger the callback if the event is currently being fired.", function () {
var handler1 = jasmine.createSpy().andCallFake(function() { stickyChannel.subscribe(handler2); }),
handler2 = jasmine.createSpy().andCallFake(function(arg1) { expect(arg1).toEqual('foo');});
stickyChannel.subscribe(handler1);
stickyChannel.fire('foo');
expectCallCount(handler2, 1);
});
it("should unregister all handlers after being fired.", function() {
var handler = jasmine.createSpy();
stickyChannel.subscribe(handler);
stickyChannel.fire();
stickyChannel.fire();
expectCallCount(handler, 1);
});
});
describe("fire method for multi channels", function() {
commonFireTests(true);
it("should not trigger the callback if the event has already been fired", function () {
var before = jasmine.createSpy('before'),
after = jasmine.createSpy('after');
multiChannel.subscribe(before);
multiChannel.fire();
multiChannel.subscribe(after);
expectCallCount(before, 1);
expectCallCount(after, 0);
});
it("should not trigger the callback if the event is currently being fired.", function () {
var handler1 = jasmine.createSpy().andCallFake(function() { multiChannel.subscribe(handler2); }),
handler2 = jasmine.createSpy();
multiChannel.subscribe(handler1);
multiChannel.fire();
multiChannel.fire();
expectCallCount(handler1, 2);
expectCallCount(handler2, 1);
});
it("should not unregister handlers after being fired.", function() {
var handler = jasmine.createSpy();
multiChannel.subscribe(handler);
multiChannel.fire();
multiChannel.fire();
expectCallCount(handler, 2);
});
});
describe("channel.join()", function() {
it("should be called when all functions start unfired", function() {
var handler = jasmine.createSpy(),
stickyChannel2 = channel.createSticky('stickyChannel');
channel.join(handler, [stickyChannel, stickyChannel2]);
expectCallCount(handler, 0);
stickyChannel.fire();
expectCallCount(handler, 0);
stickyChannel2.fire();
expectCallCount(handler, 1);
});
it("should be called when one functions start fired", function() {
var handler = jasmine.createSpy(),
stickyChannel2 = channel.createSticky('stickyChannel');
stickyChannel.fire();
channel.join(handler, [stickyChannel, stickyChannel2]);
expectCallCount(handler, 0);
stickyChannel2.fire();
expectCallCount(handler, 1);
});
it("should be called when all functions start fired", function() {
var handler = jasmine.createSpy(),
stickyChannel2 = channel.createSticky('stickyChannel');
stickyChannel.fire();
stickyChannel2.fire();
channel.join(handler, [stickyChannel, stickyChannel2]);
expectCallCount(handler, 1);
});
it("should throw if a channel is not sticky", function() {
expect(function() {
channel.join(function(){}, [stickyChannel, multiChannel]);
}).toThrow();
});
});
describe("onHasSubscribersChange", function() {
it("should be called only when the first subscriber is added and last subscriber is removed.", function() {
var handler = jasmine.createSpy().andCallFake(function() {
if (callCount(handler) == 1) {
expect(this.numHandlers).toEqual(1);
} else {
expect(this.numHandlers).toEqual(0);
}
});
multiChannel.onHasSubscribersChange = handler;
function foo1() {}
function foo2() {}
multiChannel.subscribe(foo1);
multiChannel.subscribe(foo2);
multiChannel.unsubscribe(foo1);
multiChannel.unsubscribe(foo2);
expectCallCount(handler, 2);
});
});
});