UNPKG

pusher-js

Version:

Pusher Channels JavaScript library for browsers, React Native, NodeJS and web workers

359 lines (294 loc) 12.5 kB
var Mocks = require("mocks"); var Runtime = require('runtime').default; var CachedStrategy = require('core/strategies/cached_strategy').default; var Util = require('core/util').default; describe("CachedStrategy", function() { beforeEach(function() { jasmine.clock().uninstall(); jasmine.clock().install(); }); afterEach(function() { jasmine.clock().uninstall(); }); describe("after calling isSupported", function() { it("should return true when the substrategy is supported", function() { var substrategy = Mocks.getStrategy(true); var strategy = new CachedStrategy(substrategy, {}, {}); expect(strategy.isSupported()).toBe(true); }); it("should return false when the substrategy is not supported", function() { var substrategy = Mocks.getStrategy(false); var strategy = new CachedStrategy(substrategy, {}, {}); expect(strategy.isSupported()).toBe(false); }); }); describe("on browsers not supporting localStorage", function() { beforeEach(function() { spyOn(Runtime, "getLocalStorage").and.returnValue(undefined); }); it("should try the substrategy immediately", function() { var substrategy = Mocks.getStrategy(false); var strategy = new CachedStrategy(substrategy, {}, {}); var callback = jasmine.createSpy("callback"); strategy.connect(0, callback); expect(substrategy.connect).toHaveBeenCalled(); }); }); describe("on browsers supporting localStorage", function() { var localStorage; beforeEach(function() { localStorage = {}; spyOn(Runtime, "getLocalStorage").and.returnValue(localStorage); }); function buildCachedTransportTests(useTLS) { var TLS_KEY = "pusherTransportTLS"; var NON_TLS_KEY = "pusherTransportNonTLS"; var usedKey = useTLS ? TLS_KEY : NON_TLS_KEY; var unusedKey = useTLS ? NON_TLS_KEY : TLS_KEY; var substrategy, transports, timeline; var strategy; var callback; beforeEach(function() { substrategy = Mocks.getStrategy(true); transports = { test: Mocks.getStrategy(true) }; timeline = Mocks.getTimeline(); strategy = new CachedStrategy(substrategy, transports, { useTLS: useTLS, timeline: timeline }); callback = jasmine.createSpy("callback"); }); describe("without cached transport, useTLS=" + useTLS, function() { beforeEach(function() { delete localStorage[usedKey]; localStorage[unusedKey] = "mock"; }); it("should not report anything to timeline", function() { strategy.connect(0, callback); expect(timeline.info).not.toHaveBeenCalled(); }); it("should try the substrategy immediately when cache is empty", function() { strategy.connect(0, callback); expect(substrategy.connect).toHaveBeenCalled(); }); it("should try the substrategy immediately when cache is stale", function() { localStorage[usedKey] = JSON.stringify({ timestamp: Util.now() - 1801*1000 // default ttl is 1800s }); strategy.connect(0, callback); expect(substrategy.connect).toHaveBeenCalled(); }); it("should abort the substrategy when requested", function() { var runner = strategy.connect(0, callback); runner.abort(); expect(substrategy._abort).toHaveBeenCalled(); }); describe("on forceMinPriority", function() { it("should force the new priority on the substrategy", function() { var runner = strategy.connect(0, callback); runner.forceMinPriority(10); expect(substrategy._forceMinPriority).toHaveBeenCalledWith(10); }); }); describe("after connecting successfully", function() { var transport; var startTimestamp; beforeEach(function() { startTimestamp = Util.now(); spyOn(Util, "now").and.returnValue(startTimestamp); strategy.connect(0, callback); Util.now.and.returnValue(startTimestamp + 1000); transport = Mocks.getTransport(true); transport.name = "test"; substrategy._callback(null, { transport: transport }); }); it("should call back with the transport", function() { expect(callback).toHaveBeenCalledWith(null, { transport: transport }); }); it("should cache the connected transport", function() { expect(JSON.parse(localStorage[usedKey])).toEqual({ timestamp: Util.now(), transport: "test", latency: 1000 }); expect(localStorage[unusedKey]).toEqual("mock"); }); }); describe("after receiving an error", function() { beforeEach(function() { // set a very low timestamp to have something unused in the cache localStorage[usedKey] = JSON.stringify({ timestamp: 0 }); strategy.connect(0, callback); substrategy._callback(1); }); it("should call back after receiving an error from the substrategy", function() { expect(callback).toHaveBeenCalledWith(1); }); it("should flush the appropriate transport cache", function() { expect(localStorage.pusherTransport).toBe(undefined); expect(localStorage[unusedKey]).toEqual("mock"); }); }); }); describe("with cached transport, useTLS=" + useTLS, function() { var t0 = Util.now(); beforeEach(function() { cachedStrategy = Mocks.getStrategy(true); localStorage[usedKey] = JSON.stringify({ timestamp: t0, transport: "test", latency: 1000 }); localStorage[unusedKey] = "mock"; }); it("should try the cached strategy first", function() { strategy.connect(0, callback); expect(transports.test.connect).toHaveBeenCalled(); }); it("should report to timeline when using cached strategy", function() { strategy.connect(0, callback); expect(timeline.info).toHaveBeenCalledWith({ cached: true, transport: "test", latency: 1000 }); }); it("should abort the cached transport and not call the substrategy", function() { var runner = strategy.connect(0, callback); runner.abort(); expect(transports.test._abort).toHaveBeenCalled(); expect(substrategy.connect).not.toHaveBeenCalled(); }); describe("on forceMinPriority", function() { it("should force the new priority on the cached strategy", function() { var runner = strategy.connect(0, callback); runner.forceMinPriority(1000); expect(transports.test._forceMinPriority).toHaveBeenCalledWith(1000); }); }); describe("after connecting successfully with the cached transport", function() { var transport; beforeEach(function() { startTimestamp = Util.now(); spyOn(Util, "now").and.returnValue(startTimestamp); strategy.connect(0, callback); Util.now.and.returnValue(startTimestamp + 2000); transport = Mocks.getTransport(true); transport.name = "test"; transport.options = { useTLS: false }; transports.test._callback(null, { transport: transport }); }); it("should call back with the transport", function() { expect(callback).toHaveBeenCalledWith(null, { transport: transport }); }); it("should not try the substrategy", function() { expect(substrategy.connect).not.toHaveBeenCalled(); }); it("should cache the connected transport", function() { expect(JSON.parse(localStorage[usedKey])).toEqual({ timestamp: Util.now(), transport: "test", latency: 2000 }); expect(localStorage[unusedKey]).toEqual("mock"); }); }); describe("after double the cached latency + 1s", function() { beforeEach(function() { startTimestamp = Util.now(); spyOn(Util, "now").and.returnValue(startTimestamp); strategy.connect(0, callback); Util.now.and.returnValue(startTimestamp + 3000); jasmine.clock().tick(3000); }); it("should abort the cached strategy", function() { expect(transports.test._abort).toHaveBeenCalled(); }); it("should fall back to the substrategy", function() { expect(substrategy.connect).toHaveBeenCalled(); }); it("should flush the appropriate transport cache", function() { expect(localStorage[usedKey]).toBe(undefined); expect(localStorage[unusedKey]).toEqual("mock"); }); }); describe("after failing to connect with the cached transport", function() { var runner; beforeEach(function() { startTimestamp = Util.now(); spyOn(Util, "now").and.returnValue(startTimestamp); runner = strategy.connect(0, callback); runner.forceMinPriority(666); Util.now.and.returnValue(startTimestamp + 2000); transports.test._callback("error"); Util.now.and.returnValue(startTimestamp + 2500); }); it("should fall back to the substrategy", function() { expect(substrategy.connect).toHaveBeenCalled(); }); it("should flush the appropriate transport cache", function() { expect(localStorage[usedKey]).toBe(undefined); expect(localStorage[unusedKey]).toEqual("mock"); }); it("should abort the substrategy when requested", function() { runner.abort(); expect(cachedStrategy._abort).not.toHaveBeenCalled(); expect(substrategy._abort).toHaveBeenCalled(); }); describe("on forceMinPriority", function() { it("should force the previously set priority on the substrategy", function() { // priority is forced in beforeEach expect(substrategy.connect) .toHaveBeenCalledWith(666, jasmine.any(Function)); }); it("should force the new priority on the substrategy", function() { runner.forceMinPriority(3); expect(substrategy._forceMinPriority).toHaveBeenCalledWith(3); }); }); describe("and connecting successfully using the substrategy", function() { var transport; beforeEach(function() { transport = Mocks.getTransport(true); transport.name = "test"; substrategy._callback(null, { transport: transport }); }); it("should call back with the connection", function() { expect(callback).toHaveBeenCalledWith(null, { transport: transport }); }); it("should cache the connected transport", function() { expect(JSON.parse(localStorage[usedKey])).toEqual({ timestamp: Util.now(), transport: "test", latency: 500 }); expect(localStorage[unusedKey]).toEqual("mock"); }); }); describe("and failing to connect using the substrategy", function() { beforeEach(function() { substrategy._callback("error again"); }); it("should call back with the error", function() { expect(callback).toHaveBeenCalledWith("error again"); }); it("should flush the appropriate transport cache", function() { expect(localStorage[usedKey]).toBe(undefined); expect(localStorage[unusedKey]).toEqual("mock"); }); }); }); }); } buildCachedTransportTests(false); buildCachedTransportTests(true); }); });