more jasmine specs for proxypair, ui, and snowflake coffee files

This commit is contained in:
Serene Han 2016-02-07 08:32:41 -08:00
parent e0081ea954
commit 547cb9690a
9 changed files with 159 additions and 56 deletions

View file

@ -13,7 +13,9 @@ FILES = [
] ]
FILES_SPEC = [ FILES_SPEC = [
'spec/util.spec.coffee' 'spec/util.spec.coffee'
'spec/ui.spec.coffee'
'spec/proxypair.spec.coffee' 'spec/proxypair.spec.coffee'
'spec/snowflake.spec.coffee'
] ]
FILES_ALL = FILES.concat FILES_SPEC FILES_ALL = FILES.concat FILES_SPEC
OUTFILE = 'build/snowflake.coffee' OUTFILE = 'build/snowflake.coffee'

View file

@ -24,7 +24,6 @@ class Broker
constructor: (@url) -> constructor: (@url) ->
@clients = 0 @clients = 0
@id = genSnowflakeID() @id = genSnowflakeID()
dbg 'Contacting Broker at ' + @url + '\nSnowflake ID: ' + @id
# Ensure url has the right protocol + trailing slash. # Ensure url has the right protocol + trailing slash.
@url = 'https://' + @url if 0 != @url.indexOf('https://', 0) @url = 'https://' + @url if 0 != @url.indexOf('https://', 0)
@url += '/' if '/' != @url.substr -1 @url += '/' if '/' != @url.substr -1

View file

@ -5,7 +5,6 @@ Represents a single:
### ###
class ProxyPair class ProxyPair
MAX_BUFFER: 10 * 1024 * 1024 MAX_BUFFER: 10 * 1024 * 1024
@ -58,15 +57,15 @@ class ProxyPair
channel.onopen = => channel.onopen = =>
log 'WebRTC DataChannel opened!' log 'WebRTC DataChannel opened!'
snowflake.state = MODE.WEBRTC_READY snowflake.state = MODE.WEBRTC_READY
ui.setActive true snowflake.ui.setActive true
# This is the point when the WebRTC datachannel is done, so the next step # This is the point when the WebRTC datachannel is done, so the next step
# is to establish websocket to the server. # is to establish websocket to the server.
@connectRelay() @connectRelay()
channel.onclose = -> channel.onclose = ->
log 'WebRTC DataChannel closed.' log 'WebRTC DataChannel closed.'
ui.setStatus 'disconnected.' snowflake.ui.setStatus 'disconnected.'
snowflake.ui.setActive false
snowflake.state = MODE.INIT snowflake.state = MODE.INIT
ui.setActive false
# Change this for multiplexing. # Change this for multiplexing.
snowflake.reset() snowflake.reset()
channel.onerror = -> log 'Data channel error!' channel.onerror = -> log 'Data channel error!'
@ -79,7 +78,7 @@ class ProxyPair
@relay.label = 'websocket-relay' @relay.label = 'websocket-relay'
@relay.onopen = => @relay.onopen = =>
log @relay.label + ' connected!' log @relay.label + ' connected!'
ui.setStatus 'connected' snowflake.ui.setStatus 'connected'
@relay.onclose = @onClose @relay.onclose = @onClose
@relay.onerror = @onError @relay.onerror = @onError
@relay.onmessage = @onRelayToClientMessage @relay.onmessage = @onRelayToClientMessage

View file

@ -21,8 +21,6 @@ if 'undefined' != typeof window && window.location
COPY_PASTE_ENABLED = Params.getBool(query, 'manual', false) COPY_PASTE_ENABLED = Params.getBool(query, 'manual', false)
else else
window = {} window = {}
# HEADLESS is true if we are running not in a browser with a DOM.
HEADLESS = 'undefined' == typeof(document)
# Bytes per second. Set to undefined to disable limit. # Bytes per second. Set to undefined to disable limit.
DEFAULT_RATE_LIMIT = DEFAULT_RATE_LIMIT || undefined DEFAULT_RATE_LIMIT = DEFAULT_RATE_LIMIT || undefined
@ -59,7 +57,7 @@ class Snowflake
state: MODE.INIT state: MODE.INIT
retries: 0 retries: 0
constructor: (@broker) -> constructor: (@broker, @ui) ->
rateLimitBytes = undefined rateLimitBytes = undefined
if 'off' != query['ratelimit'] if 'off' != query['ratelimit']
rateLimitBytes = Params.getByteCount(query, 'ratelimit', rateLimitBytes = Params.getByteCount(query, 'ratelimit',
@ -89,8 +87,8 @@ class Snowflake
return if COPY_PASTE_ENABLED return if COPY_PASTE_ENABLED
timer = null timer = null
# Temporary countdown. # Temporary countdown.
countdown = (msg, sec) -> countdown = (msg, sec) =>
ui.setStatus msg + ' (Retrying in ' + sec + ' seconds...)' @ui.setStatus msg + ' (Retrying in ' + sec + ' seconds...)'
sec-- sec--
if sec >= 0 if sec >= 0
setTimeout((-> countdown(msg, sec)), 1000) setTimeout((-> countdown(msg, sec)), 1000)
@ -101,8 +99,8 @@ class Snowflake
clearTimeout timer clearTimeout timer
msg = 'polling for client... ' msg = 'polling for client... '
msg += '[retries: ' + @retries + ']' if @retries > 0 msg += '[retries: ' + @retries + ']' if @retries > 0
ui.setStatus msg @ui.setStatus msg
recv = broker.getClientOffer() recv = @broker.getClientOffer()
@retries++ @retries++
recv.then (desc) => recv.then (desc) =>
offer = JSON.parse desc offer = JSON.parse desc
@ -132,14 +130,12 @@ class Snowflake
pair.onCleanup = (event) => pair.onCleanup = (event) =>
# Delete from the list of active proxy pairs. # Delete from the list of active proxy pairs.
@proxyPairs.splice(@proxyPairs.indexOf(pair), 1) @proxyPairs.splice(@proxyPairs.indexOf(pair), 1)
# @badge.endProxy() if @badge
try try
pair.begin() pair.begin()
catch err catch err
log 'ERROR: ProxyPair exception while connecting.' log 'ERROR: ProxyPair exception while connecting.'
log err log err
return return
# @badge.beginProxy if @badge
cease: -> cease: ->
while @proxyPairs.length > 0 while @proxyPairs.length > 0
@ -148,12 +144,10 @@ class Snowflake
disable: -> disable: ->
log 'Disabling Snowflake.' log 'Disabling Snowflake.'
@cease() @cease()
# @badge.disable() if @badge
die: -> die: ->
log 'Snowflake died.' log 'Snowflake died.'
@cease() @cease()
# @badge.die() if @badge
# Close all existing ProxyPairs and begin finding new clients from scratch. # Close all existing ProxyPairs and begin finding new clients from scratch.
reset: -> reset: ->
@ -163,8 +157,6 @@ class Snowflake
@beginWebRTC() @beginWebRTC()
snowflake = null snowflake = null
broker = null
ui = null
# Signalling channel - just tells user to copy paste to the peer. # Signalling channel - just tells user to copy paste to the peer.
# Eventually this should go over the broker. # Eventually this should go over the broker.
@ -190,19 +182,19 @@ Signalling =
# Log to both console and UI if applicable. # Log to both console and UI if applicable.
log = (msg) -> log = (msg) ->
console.log 'Snowflake: ' + msg console.log 'Snowflake: ' + msg
ui.log msg snowflake.ui.log msg
dbg = (msg) -> log msg if true == ui.debug dbg = (msg) -> log msg if true == snowflake.ui.debug
init = -> init = ->
ui = new UI() ui = new UI()
log '== snowflake proxy =='
log 'Copy-Paste mode detected.' if COPY_PASTE_ENABLED
brokerUrl = Params.getString(query, 'broker', DEFAULT_BROKER) brokerUrl = Params.getString(query, 'broker', DEFAULT_BROKER)
broker = new Broker brokerUrl broker = new Broker brokerUrl
snowflake = new Snowflake(broker) snowflake = new Snowflake broker, ui
# window.snowflake = snowflake
# window.ui = ui dbg 'Contacting Broker at ' + broker.url + '\nSnowflake ID: ' + broker.id
log '== snowflake proxy =='
log 'Copy-Paste mode detected.' if COPY_PASTE_ENABLED
relayAddr = Params.getAddress(query, 'relay', DEFAULT_RELAY) relayAddr = Params.getAddress(query, 'relay', DEFAULT_RELAY)
snowflake.setRelayAddr relayAddr snowflake.setRelayAddr relayAddr

View file

@ -1,27 +1,13 @@
### ###
jasmine tests for Snowflake jasmine tests for Snowflake proxypair
### ###
# Stubs to fake browser functionality.
class PeerConnection
class WebSocket
OPEN: 1
CLOSED: 0
ui =
log: ->
setActive: ->
log = ->
describe 'ProxyPair', -> describe 'ProxyPair', ->
fakeRelay = Parse.address '0.0.0.0:12345' fakeRelay = Parse.address '0.0.0.0:12345'
rateLimit = new DummyRateLimit() rateLimit = new DummyRateLimit()
destination = [] destination = []
fakeClient = send: (d) -> destination.push d fakeClient = send: (d) -> destination.push d
# Fake snowflake to interact with
snowflake = {
broker:
sendAnswer: ->
}
pp = new ProxyPair(fakeClient, fakeRelay, rateLimit) pp = new ProxyPair(fakeClient, fakeRelay, rateLimit)
it 'begins webrtc connection', -> it 'begins webrtc connection', ->

View file

@ -0,0 +1,60 @@
###
jasmine tests for Snowflake
###
query = {}
# Fake browser functionality:
class PeerConnection
class RTCSessionDescription
type: 'offer'
class WebSocket
OPEN: 1
CLOSED: 0
log = ->
class FakeUI
log: ->
setActive: ->
setStatus: ->
fakeUI = new FakeUI()
class FakeBroker
getClientOffer: -> new Promise((F,R) -> {})
# Fake snowflake to interact with
snowflake =
ui: fakeUI
broker:
sendAnswer: ->
describe 'Snowflake', ->
it 'constructs correctly', ->
s = new Snowflake({ fake: 'broker' }, fakeUI)
query['ratelimit'] = 'off'
expect(s.rateLimit).not.toBeNull()
expect(s.broker).toEqual { fake: 'broker' }
expect(s.ui).not.toBeNull()
expect(s.retries).toBe 0
it 'sets relay address correctly', ->
s = new Snowflake(null, fakeUI)
s.setRelayAddr 'foo'
expect(s.relayAddr).toEqual 'foo'
it 'initalizes WebRTC connection', ->
s = new Snowflake(new FakeBroker(), fakeUI)
spyOn(s.broker, 'getClientOffer').and.callThrough()
s.beginWebRTC()
expect(s.retries).toBe 1
expect(s.broker.getClientOffer).toHaveBeenCalled()
it 'receives SDP offer', ->
s = new Snowflake(new FakeBroker(), fakeUI)
s.proxyPair = { receiveWebRTCOffer: -> }
spyOn(s.proxyPair, 'receiveWebRTCOffer').and.returnValue true
spyOn(s, 'sendAnswer')
s.receiveOffer 'foo'
expect(s.sendAnswer).toHaveBeenCalled()
it 'can make a proxypair', ->
s = new Snowflake(new FakeBroker(), fakeUI)
s.makeProxyPair()
expect(s.proxyPairs.length).toBe 2

75
proxy/spec/ui.spec.coffee Normal file
View file

@ -0,0 +1,75 @@
###
jasmine tests for Snowflake UI
###
document =
getElementById: (id) ->
describe 'UI', ->
it 'activates debug mode when badge does not exist', ->
spyOn(document, 'getElementById').and.callFake (id) ->
return null if 'badge' == id
return {
focus: ->
}
u = new UI()
expect(u.debug).toBe true
expect(document.getElementById.calls.count()).toEqual 5
expect(u.$status).not.toBeNull()
expect(u.$msglog).not.toBeNull()
expect(u.$send).not.toBeNull()
expect(u.$input).not.toBeNull()
it 'is not debug mode when badge exists', ->
spyOn(document, 'getElementById').and.callFake (id) ->
return {} if 'badge' == id
return null
u = new UI()
expect(u.debug).toBe false
expect(document.getElementById).toHaveBeenCalled()
expect(document.getElementById.calls.count()).toEqual 1
expect(u.$status).toBeNull()
expect(u.$msglog).toBeNull()
expect(u.$send).toBeNull()
expect(u.$input).toBeNull()
it 'sets status message only when in debug mode', ->
u = new UI()
u.$status = { innerHTML: '' }
u.debug = false
u.setStatus('test')
expect(u.$status.innerHTML).toEqual ''
u.debug = true
u.setStatus('test')
expect(u.$status.innerHTML).toEqual 'Status: test'
it 'sets message log css correctly for debug mode', ->
u = new UI()
u.debug = true
u.$msglog = {}
u.setActive true
expect(u.$msglog.className).toEqual 'active'
u.setActive false
expect(u.$msglog.className).toEqual ''
it 'sets badge css correctly for non-debug mode', ->
u = new UI()
u.debug = false
u.$badge = {}
u.setActive true
expect(u.$badge.className).toEqual 'active'
u.setActive false
expect(u.$badge.className).toEqual ''
it 'logs to the textarea correctly, only when debug mode', ->
u = new UI()
u.$msglog = { value: '', scrollTop: 0, scrollHeight: 1337 }
u.debug = false
u.log 'test'
expect(u.$msglog.value).toEqual ''
expect(u.$msglog.scrollTop).toEqual 0
u.debug = true
u.log 'test'
expect(u.$msglog.value).toEqual 'test\n'
expect(u.$msglog.scrollTop).toEqual 1337

View file

@ -1,17 +1,7 @@
### ###
jasmine tests for Snowflake jasmine tests for Snowflake utils
### ###
# Stubs to fake browser functionality.
class PeerConnection
class WebSocket
OPEN: 1
CLOSED: 0
ui =
log: ->
setActive: ->
log = ->
describe 'BuildUrl', -> describe 'BuildUrl', ->
it 'should parse just protocol and host', -> it 'should parse just protocol and host', ->
expect(buildUrl('http', 'example.com')).toBe 'http://example.com' expect(buildUrl('http', 'example.com')).toBe 'http://example.com'

View file

@ -6,10 +6,10 @@ class UI
debug = false # True when there's no badge debug = false # True when there's no badge
# DOM elements references. # DOM elements references.
$msglog = null $msglog: null
$send = null $send: null
$input = null $input: null
$status = null $status: null
constructor: -> constructor: ->
@$badge = document.getElementById('badge') @$badge = document.getElementById('badge')