* wip
This commit is contained in:
parent
4d8a7a9bc1
commit
698f4ba648
|
|
@ -2,6 +2,24 @@ $ = jQuery
|
|||
context = window
|
||||
context.JK ||= {};
|
||||
|
||||
# This is the sequence of how this widget works:
|
||||
# checkState() is the heart of the state machine; it is called to get things going, and is called whenevr a state ends
|
||||
# checkState() checks first against what the client thinks about the state of the JamTrack;
|
||||
# if it on the disk then the state machine may enter one of:
|
||||
# * synchronized
|
||||
# * keying
|
||||
#
|
||||
# if it's still on the server, then the state machine may be:
|
||||
# * packaging
|
||||
# * downloading
|
||||
#
|
||||
# errored state can be entered from @jamTrackRightId
|
||||
#
|
||||
# other state; you augment the error to the user by suppling @errorMessage before transitioning
|
||||
#
|
||||
# no-client is the way the widget behaves when you are in a normal browser (i.e., nothing happens other than tell the user to use the client)
|
||||
#
|
||||
# Discussion of the different states:
|
||||
# There are different states that a JamTrack can be in.
|
||||
# The final success state is that the JamTrack is on disk and loadable. (show synchronized state)
|
||||
# But there are others until you get there:
|
||||
|
|
@ -18,21 +36,25 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
@jamTrackId = jamTrackId
|
||||
@jamTrackRightId = jamTrackRightId
|
||||
@attemptedEnqueue = false
|
||||
@errorReason = null
|
||||
@errorMessage = null
|
||||
@transitionTimer = null
|
||||
@downloadTimer = null
|
||||
@trackDetail = null
|
||||
@stateHolder = null
|
||||
@active = false
|
||||
@startTime = null
|
||||
@path = []
|
||||
@errorSupportMsg = "Press RETRY, or if you have already retried, please contact support@jamkazam.com."
|
||||
@states = {
|
||||
no_client: { name: 'no-client', show: @showNoClient },
|
||||
synchronized: { name: 'synchronized', show: @showSynchronized },
|
||||
no_client: { name: 'no-client', show: @showNoClient, leaf: true },
|
||||
synchronized: { name: 'synchronized', show: @showSynchronized, leaf: true},
|
||||
packaging: { name: 'packaging', show: @showPackaging },
|
||||
downloading: { name: 'downloading', show: @showDownloading },
|
||||
keying: { name: 'keying', show: @showKeying },
|
||||
keying: { name: 'keying', show: @showKeying, max_time: 10000 },
|
||||
initial: { name: 'initial', show: @showInitial },
|
||||
errored: { name: 'errored', show: @showError }
|
||||
errored: { name: 'errored', show: @showError, leaf: true}
|
||||
}
|
||||
@state = @states.initial
|
||||
|
||||
context.JK.DownloadJamTracks[@jamTrackId] = this
|
||||
|
||||
|
|
@ -40,7 +62,14 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
# after you've created the DownloadJamTrack widget, call synchronize which will begin ensuring that the jamtrack
|
||||
# is downloaded and ready to open
|
||||
init: () =>
|
||||
@root = $($('#template-download-jamtrack').html())
|
||||
@active = true
|
||||
this.reset()
|
||||
|
||||
downloadJamTrackTemplate = $('#template-download-jamtrack')
|
||||
throw "no download jamtrack template" if not downloadJamTrackTemplate.exists()
|
||||
|
||||
@root = $(downloadJamTrackTemplate.html())
|
||||
@stateHolder = @root.find('.state')
|
||||
|
||||
# populate in template and visual transition functions
|
||||
for state, data of @states
|
||||
|
|
@ -48,55 +77,104 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
|
||||
# check if we are in a browser or client
|
||||
if !gon.isNativeClient
|
||||
@states.no_client.show()
|
||||
this.transition(@states.no_client)
|
||||
else
|
||||
@states.initial.show()
|
||||
this.synchronize()
|
||||
@attemptedEnqueue = false
|
||||
this.checkState()
|
||||
|
||||
# when done with the widget, call destroy; this ensures it's not still active
|
||||
destroy: () =>
|
||||
@active = false
|
||||
this.reset()
|
||||
|
||||
reset: () =>
|
||||
@path = []
|
||||
@startTime = new Date()
|
||||
@state = @states.initial
|
||||
# reset attemptedEnqueue to false, to allow one attempt to enqueue
|
||||
@attemptedEnqueue = false
|
||||
this.clearDownloadTimer()
|
||||
this.clearTransitionTimer()
|
||||
for state, data of @states
|
||||
if data.timer?
|
||||
clearInterval(data.timer)
|
||||
data.timer = null
|
||||
|
||||
|
||||
showPackaging: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
@logger.debug("showing #{@state.name}")
|
||||
this.expectTransition()
|
||||
|
||||
showDownloading: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
@logger.debug("showing #{@state.name}")
|
||||
# while downloading, we don't run the transition timer, because the download API is guaranteed to call success, or failure, eventually
|
||||
this.clearTransitionTimer()
|
||||
context.jamClient.StartFileDownload(context.JK.makeAbsolute('/api/jamtracks/download/' + @jamTrackId), this.makeDownloadProgressCallback(), this.makeDownloadSuccessCallback(), this.makeDownloadFailureCallback(), true)
|
||||
|
||||
showKeying: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
this.clearTransitionTimer()
|
||||
@logger.debug("showing #{@state.name}")
|
||||
context.jamClient.requestJamTrackKeys()
|
||||
this.expectKeyed()
|
||||
this.waitForState()
|
||||
|
||||
showInitial: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
@logger.debug("showing #{@state.name}")
|
||||
this.expectTransition()
|
||||
context.JK.SubscriptionUtils.subscribe('jam_track_right', @jamTrackRightId).on(context.JK.EVENTS.SUBSCRIBE_NOTIFICATION, this.onJamTrackRightEvent)
|
||||
this.checkState()
|
||||
|
||||
showError: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
clearTransitionTimer()
|
||||
@logger.debug("showing #{@state.name}")
|
||||
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrackRightId)
|
||||
@stateHolder.find('.msg').text(@errorMessage)
|
||||
@stateHolder.find('.retry-button').click(this.retry)
|
||||
|
||||
showSynchronized: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
clearTransitionTimer()
|
||||
@logger.debug("showing #{@state.name}")
|
||||
context.JK.SubscriptionUtils.unsubscribe('jam_track_right', @jamTrackRightId)
|
||||
|
||||
showNoClient: () =>
|
||||
@logger.debug("showing #{@states.name}")
|
||||
@logger.debug("showing #{@state.name}")
|
||||
|
||||
downloadCheck: () =>
|
||||
@logger.debug "downloadcheck"
|
||||
@logger.debug "downloadCheck"
|
||||
|
||||
# sets an interval timer for every 3 seconds, waiting for the status to change
|
||||
expectKeyed: () =>
|
||||
retry: () =>
|
||||
# just switch to the initial state again, causing the loop to start again
|
||||
this.transition(@states.initial)
|
||||
return false
|
||||
|
||||
clearStateTimer: () =>
|
||||
if @state.timer?
|
||||
clearInterval(@state.timer)
|
||||
@state.timer = null
|
||||
|
||||
stateIntervalCheck: () =>
|
||||
this.checkState()
|
||||
|
||||
# if the timer is null now, then it must have been whacked due to a state change
|
||||
# if not, then let's see if we have timed out
|
||||
if @state.timer?
|
||||
if (new Date()).getTime() - @state.stateStartTime.getTime() > @state.max_time
|
||||
@logger.debug("The current step (#{@state.name}) took too long")
|
||||
|
||||
if @state == @states.keying
|
||||
# specific message
|
||||
this.transitionError("#{@state.name}-timeout", "It took too long for the JamTrack to be keyed.")
|
||||
else
|
||||
# generic message
|
||||
this.transitionError("#{@state.name}-timeout", "The current step (#{@state.name}) took too long")
|
||||
|
||||
|
||||
# sets an interval timer for every second, waiting for the status to change
|
||||
waitForState: () =>
|
||||
unless @active
|
||||
@logger.error("DownloadJamTrack: ignoring waitForState because we are not active")
|
||||
|
||||
@state.timer = setInterval(this.stateIntervalCheck, 1000)
|
||||
|
||||
|
||||
# unused atm; the backend is good about always signalling. we still should though
|
||||
expectDownload: () =>
|
||||
unless @downloadTimer?
|
||||
return
|
||||
unless @active
|
||||
@logger.error("DownloadJamTrack: ignoring expectDownload because we are not active")
|
||||
|
||||
# every 10 seconds, wake up and check the server and see if we missed a state transition
|
||||
this.clearDownloadTimer()
|
||||
|
|
@ -107,6 +185,10 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
clearTimeout(@downloadTimer)
|
||||
@downloadTimer = null
|
||||
|
||||
transitionError: (reasonCode, errorMessage) =>
|
||||
@errorReason = reasonCode
|
||||
@errorMessage = errorMessage
|
||||
this.transition(@states.errored)
|
||||
|
||||
transitionCheck: () =>
|
||||
this.checkState()
|
||||
|
|
@ -117,8 +199,8 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
# we don't get an event, so that's why, after 12 seconds, we'll still go to the server and check.
|
||||
# exception: this should not be runngi
|
||||
expectTransition: () =>
|
||||
unless @transitionTimer?
|
||||
return
|
||||
unless @active
|
||||
@logger.error("DownloadJamTrack: ignoring expectTransition because we are not active")
|
||||
|
||||
# every 12 seconds, wake up and check the server and see if we missed a state transition
|
||||
this.clearTransitionTimer()
|
||||
|
|
@ -130,23 +212,54 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
@transitionTimer = null
|
||||
|
||||
transition: (newState) =>
|
||||
unless @active
|
||||
@logger.error("DownloadJamTrack: ignoring state change because we are not active")
|
||||
|
||||
if newState == @state
|
||||
@logger.debug("DownloadJamTrack: ignoring state change #{@state}")
|
||||
@logger.debug("DownloadJamTrack: ignoring state change #{@state.name}")
|
||||
return
|
||||
|
||||
@logger.debug("DownloadJamTrack: state change: #{@state} => #{newState}")
|
||||
@logger.debug("DownloadJamTrack: state change: #{@state.name} => #{newState.name}")
|
||||
|
||||
# make sure there is no timer running on the old state
|
||||
this.clearTransitionTimer()
|
||||
this.clearStateTimer()
|
||||
|
||||
@state = newState
|
||||
|
||||
@states[newState].show()
|
||||
# track which states were taken
|
||||
@path.push(@state.name)
|
||||
|
||||
if @state.leaf
|
||||
# report a stat now that we've reached the end of this widget's journey
|
||||
flattened_path = @path.join('-')
|
||||
data = {value: 1, path: flattened_path, duration: (new Date().getTime() - @startTime.getTime()) / 1000}
|
||||
if @state == @states.errored
|
||||
data.result = 'error'
|
||||
data.detail = @errorDetail
|
||||
else
|
||||
data.result = 'success'
|
||||
|
||||
context.JK.stats.write('web.jamtrack.downloader', data)
|
||||
|
||||
@state.stateStartTime = new Date();
|
||||
|
||||
@stateHolder.children().remove()
|
||||
@stateHolder.append(@state.template.html())
|
||||
|
||||
@state.show()
|
||||
|
||||
checkState: () =>
|
||||
# check for the success state against the local state of the client... if it's playable, then we should be OK
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail(@jamTrackId)
|
||||
@trackDetail = context.jamClient.JamTrackGetTrackDetail (@jamTrackId)
|
||||
|
||||
@logger.debug("DownloadJamTrack: JamTrackGetTrackDetail.key_state: " + @trackDetail.key_state)
|
||||
|
||||
switch @trackDetail.key_state
|
||||
when 'pending'
|
||||
this.transition(@states.keying)
|
||||
when 'not authorized'
|
||||
# TODO: if not authorized, do we need to re-initiate a keying attempt?
|
||||
this.transition(@states.keying)
|
||||
when 'ready'
|
||||
this.transition(@states.synchronized)
|
||||
|
|
@ -157,57 +270,54 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
|
||||
|
||||
processSigningState: (signingState) =>
|
||||
@logger.debug("DownloadJamTrack: processSigningState: " + signingState)
|
||||
|
||||
switch signingState
|
||||
when 'QUIET'
|
||||
if @attemptedEnqueue
|
||||
# this means we've already tried to poke the server. something is wrong
|
||||
@errorMessage = "The server has not begun building your JamTrack. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("enqueue-timeout", "The server has not begun building your JamTrack.")
|
||||
else
|
||||
|
||||
this.expectTransition()
|
||||
|
||||
@attemptedEnqueue = true
|
||||
@rest.enqueueJamTrack({id: @jamTrackId})
|
||||
.done(this.processEnqueueJamTrack)
|
||||
.fail(this.processEnqueueJamTrackFail)
|
||||
when 'QUEUED'
|
||||
# when it's queued, there is nothing to do except wait.
|
||||
this.expectTransition()
|
||||
this.transition(@states.packaging)
|
||||
when 'QUEUED_TIMEOUT'
|
||||
@errorMessage = "The server took too long to begin processing your JamTrack. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("queued-timeout", "The server took too long to begin processing your JamTrack.")
|
||||
when 'SIGNING'
|
||||
this.expectTransition()
|
||||
this.transition(@states.packaging)
|
||||
when 'SIGNING_TIMEOUT'
|
||||
@errorMessage = "The server took too long to create your JamTrack. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("signing-timeout", "The server took too long to create your JamTrack.")
|
||||
when 'SIGNED'
|
||||
this.transition(@states.downloading)
|
||||
when 'ERROR'
|
||||
if @attemptedEnqueue
|
||||
# this means we've already tried to poke the server. something is wrong
|
||||
@errorMessage = "The server failed to create your package. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("package-error", "The server failed to create your package.")
|
||||
else
|
||||
this.expectTransition()
|
||||
|
||||
@attemptedEnqueue = true
|
||||
@rest.enqueueJamTrack({id: @jamTrackId})
|
||||
.done(this.processEnqueueJamTrack)
|
||||
.fail(this.processEnqueueJamTrackFail)
|
||||
|
||||
|
||||
else
|
||||
@logger.error("unknown state: " + signingState)
|
||||
this.transitionError("unknown-state-#{signingState}", "The server sent an unknown state message: " + signingState)
|
||||
|
||||
processJamTrackRightFail: () =>
|
||||
@errorMessage = "Unable to check with the server on the status of your JamTrack. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("status-check-error", "Unable to check with the server on the status of your JamTrack.")
|
||||
|
||||
processEnqueueJamTrack: (enqueueResponse) =>
|
||||
this.expectTransition() # the act of enqueuing should send down events to the client. we wait...
|
||||
|
||||
processEnqueueJamTrackFail: () =>
|
||||
@errorMessage = "Unable to ask the server to build your JamTrack. #{@errorSupportMsg}"
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("enqueue-error", "Unable to ask the server to build your JamTrack.")
|
||||
|
||||
processJamTrackRight: (myJamTrack) =>
|
||||
this.processSigningState(myJamTrack.signing_state)
|
||||
|
|
@ -230,8 +340,7 @@ context.JK.DownloadJamTrack = class DownloadJamTrack
|
|||
this.transition(@states.keying)
|
||||
|
||||
downloadFailureCallback: (errorMsg) =>
|
||||
@errorMessage = errorMessage
|
||||
this.transition(@states.errored)
|
||||
this.transitionError("download-error", errorMsg)
|
||||
|
||||
# makes a function name for the backend
|
||||
makeDownloadProgressCallback: () =>
|
||||
|
|
|
|||
|
|
@ -682,6 +682,9 @@
|
|||
function JamTrackIsPlayable() {
|
||||
return true;
|
||||
}
|
||||
function JamTrackGetTrackDetail() {
|
||||
return {key_state: 'ready'}
|
||||
}
|
||||
// Method which sets volume
|
||||
function UpdateMixer(mixerId) {}
|
||||
|
||||
|
|
@ -977,6 +980,7 @@
|
|||
this.TrackSetChatUsesMusic = TrackSetChatUsesMusic;
|
||||
|
||||
this.JamTrackIsPlayable = JamTrackIsPlayable;
|
||||
this.JamTrackGetTrackDetail = JamTrackGetTrackDetail;
|
||||
|
||||
// Scoring Knobs
|
||||
this.GetScoreWorkTimingInterval = GetScoreWorkTimingInterval;
|
||||
|
|
|
|||
|
|
@ -1606,6 +1606,7 @@
|
|||
this.getJamtracks = getJamtracks;
|
||||
this.getPurchasedJamTracks = getPurchasedJamTracks;
|
||||
this.getJamTrackRight = getJamTrackRight;
|
||||
this.enqueueJamTrack = enqueueJamTrack;
|
||||
this.addJamtrackToShoppingCart = addJamtrackToShoppingCart;
|
||||
this.getShoppingCarts = getShoppingCarts;
|
||||
this.removeShoppingCart = removeShoppingCart;
|
||||
|
|
|
|||
|
|
@ -39,4 +39,16 @@ class SpikesController < ApplicationController
|
|||
Notification.send_subscription_message('test', '2', '{"msg": "oh hai 2"}')
|
||||
render text: 'oh hai'
|
||||
end
|
||||
|
||||
def download_jam_track
|
||||
|
||||
jamTrack = JamTrack.find(params[:jam_track_id])
|
||||
jamTrackRight = jamTrack.right_for_user(current_user)
|
||||
|
||||
gon.jamTrackId = jamTrack.id
|
||||
gon.jamTrackRightId = jamTrackRight.id
|
||||
gon.switchState = params[:state]
|
||||
|
||||
render :layout => 'web'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,30 +1,41 @@
|
|||
script type="text/template" id='template-download-jamtrack'
|
||||
.download-jamtrack
|
||||
|
||||
.state
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-no-client"
|
||||
.state-no-client
|
||||
| To download this JamTrack, launch the JamKazam application and open it while in a session.
|
||||
| To play this JamTrack, launch the JamKazam application and open it while in a session.
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-synchronized"
|
||||
.state-success
|
||||
.state-synchronized
|
||||
| This JamTrack is on your system and ready to play.
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-packaging"
|
||||
.state-packaging
|
||||
| Your JamTrack is currently being created on the JamKazam server.
|
||||
.msg
|
||||
| Your JamTrack is currently being created on the JamKazam server.
|
||||
.spinner-small
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-downloading"
|
||||
.state-downloading
|
||||
| Your JamTrack is currently being downloaded.
|
||||
.msg
|
||||
| Your JamTrack is currently being downloaded.
|
||||
.spinner-small
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-keying"
|
||||
.state-keying
|
||||
| Your JamTrack is being authenticated.
|
||||
.msg
|
||||
| Your JamTrack is being authenticated.
|
||||
.spinner-small
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-initial"
|
||||
.state-initial
|
||||
| Initializing...
|
||||
.msg
|
||||
| Initializing...
|
||||
|
||||
script type="text/template" id="template-download-jamtrack-state-errored"
|
||||
.state-errored
|
||||
.msg
|
||||
.msg
|
||||
.retry
|
||||
| Press RETRY, or if you have already retried, please contact support@jamkazam.com.
|
||||
.a.button-orange.retry-button RETRY
|
||||
|
|
@ -64,6 +64,7 @@
|
|||
<%= render "overlay_small" %>
|
||||
<%= render "listenBroadcast" %>
|
||||
<%= render "sync_viewer_templates" %>
|
||||
<%= render "download_jamtrack_templates" %>
|
||||
<%= render "help" %>
|
||||
<%= render 'dialogs/dialogs' %>
|
||||
<div id="fb-root"></div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
= javascript_include_tag "download_jamtrack"
|
||||
= render "clients/download_jamtrack_templates"
|
||||
|
||||
- provide(:title, 'Download Jam Track Widget')
|
||||
|
||||
.content-wrapper
|
||||
h2 Jam Track State Widget
|
||||
ul
|
||||
li synchronized
|
||||
li no_client
|
||||
li packaging
|
||||
li downloading
|
||||
li keying
|
||||
li initial
|
||||
li errored
|
||||
#widget
|
||||
|
||||
javascript:
|
||||
$(document).on('JAMKAZAM_READY', function() {
|
||||
window.downloadJamTrack = new JK.DownloadJamTrack(gon.jamTrackId, gon.jamTrackRightId)
|
||||
downloadJamTrack.init()
|
||||
$('#widget').append(window.downloadJamTrack.root)
|
||||
|
||||
console.log("gon.switchstate", gon.switchState)
|
||||
if(gon.switchState) {
|
||||
downloadJamTrack.transition(downloadJamTrack.states[gon.switchState]);
|
||||
}
|
||||
})
|
||||
|
|
@ -92,6 +92,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/launch_app', to: 'spikes#launch_app'
|
||||
match '/websocket', to: 'spikes#websocket'
|
||||
match '/test_subscription', to: 'spikes#subscription'
|
||||
match '/widgets/download_jam_track', to: 'spikes#download_jam_track'
|
||||
|
||||
# junk pages
|
||||
match '/help', to: 'static_pages#help'
|
||||
|
|
|
|||
|
|
@ -1,15 +1,289 @@
|
|||
describe "DownloadJamTrack", ->
|
||||
|
||||
beforeEach ->
|
||||
this.fixtures = fixture.load("downoadJamTrack.html"); # append these fixtures which were already cached
|
||||
this.fixtures = fixture.load("downloadJamTrack.html"); # append these fixtures which were already cached
|
||||
this.server = sinon.fakeServer.create();
|
||||
window.jamClient = sinon.stub()
|
||||
this.downloadJamTrack = new JK.DownloadJamTrack()
|
||||
this.downloadJamTrack.init()
|
||||
$('body').append(this.downloadJamTrack.root)
|
||||
this.app = sinon.stub()
|
||||
this.jamTrackId = '1'
|
||||
window.gon = {}
|
||||
window.JK.JamServer = {}
|
||||
window.JK.stats = {}
|
||||
@statsSpy = window.JK.stats.write = sinon.spy()
|
||||
window.JK.JamServer.send = sinon.stub(); # attempts to subscribe to the socket will need this
|
||||
|
||||
afterEach ->
|
||||
this.server.restore();
|
||||
window.JK.stats.write.reset()
|
||||
|
||||
describe "normal browser", ->
|
||||
|
||||
beforeEach ->
|
||||
window.gon.isNativeClient = false
|
||||
@showNoClientSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showNoClient')
|
||||
this.downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
|
||||
$('body').append(this.downloadJamTrack.root)
|
||||
|
||||
afterEach ->
|
||||
@showNoClientSpy.restore()
|
||||
|
||||
it "switches to 'no client' correctly", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
#window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'ready'})
|
||||
|
||||
@downloadJamTrack.init();
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(0)
|
||||
expect(@showNoClientSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-no-client')).toHaveLength(1)
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
describe "client", ->
|
||||
|
||||
beforeEach ->
|
||||
window.gon.isNativeClient = true
|
||||
|
||||
describe "already synchronized", ->
|
||||
beforeEach ->
|
||||
@showSynchronizedSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showSynchronized')
|
||||
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
|
||||
$('body').append(@downloadJamTrack.root)
|
||||
|
||||
afterEach ->
|
||||
@showSynchronizedSpy.restore()
|
||||
@downloadJamTrack.destroy()
|
||||
|
||||
it "shows synchronized state", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'ready'})
|
||||
|
||||
@downloadJamTrack.init();
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(1)
|
||||
expect(@showSynchronizedSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.transitionTimer).toBe(null)
|
||||
expect(@downloadJamTrack.downloadTimer).toBe(null)
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-synchronized')).toHaveLength(1)
|
||||
|
||||
describe "pending", ->
|
||||
beforeEach ->
|
||||
window.jamClient.requestJamTrackKeys = sinon.stub()
|
||||
@showSynchronizedSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showSynchronized')
|
||||
@showErrorSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showError')
|
||||
@showKeyingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showKeying')
|
||||
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
|
||||
@downloadJamTrack.states.keying.max_time = -1 # hurry up the test, instead of waiting 10 seconds
|
||||
$('body').append(@downloadJamTrack.root)
|
||||
|
||||
afterEach ->
|
||||
@showSynchronizedSpy.restore()
|
||||
@showErrorSpy.restore()
|
||||
@showKeyingSpy.restore()
|
||||
@downloadJamTrack.destroy()
|
||||
|
||||
it "shows errored state due to timeout", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'pending'})
|
||||
|
||||
@downloadJamTrack.init();
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(1)
|
||||
expect(@showKeyingSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.states.keying.timer).toNotBe(null)
|
||||
|
||||
@downloadJamTrack.stateIntervalCheck()
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(2)
|
||||
|
||||
expect(@showErrorSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.states.keying.timer).toBe(null)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-errored')).toHaveLength(1)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-errored .msg')).toContainText('It took too long for the JamTrack to be keyed.')
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
it "shows synchronized", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'pending'})
|
||||
|
||||
@downloadJamTrack.init()
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(1)
|
||||
expect(@showKeyingSpy.calledOnce).toBe(true)
|
||||
|
||||
# keying timer should be firing
|
||||
expect(@downloadJamTrack.states.keying.timer).toNotBe(null)
|
||||
|
||||
# say the keys have been fetched
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'ready'})
|
||||
|
||||
# then do a check
|
||||
@downloadJamTrack.stateIntervalCheck()
|
||||
|
||||
expect(@showSynchronizedSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.states.keying.timer).toBe(null)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-synchronized')).toHaveLength(1)
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
|
||||
|
||||
describe "JamTrack needs downloading", ->
|
||||
beforeEach ->
|
||||
window.jamClient.requestJamTrackKeys = sinon.stub()
|
||||
@showSynchronizedSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showSynchronized')
|
||||
@showErrorSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showError')
|
||||
@showKeyingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showKeying')
|
||||
@showDownloadingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showDownloading')
|
||||
@showPackagingSpy = sinon.spy(JK.DownloadJamTrack.prototype, 'showPackaging')
|
||||
@downloadJamTrack = new JK.DownloadJamTrack(@app, @jamTrackId, '1')
|
||||
@downloadJamTrack.states.keying.max_time = -1 # hurry up the test, instead of waiting 10 seconds
|
||||
$('body').append(@downloadJamTrack.root)
|
||||
|
||||
afterEach ->
|
||||
@showSynchronizedSpy.restore()
|
||||
@showErrorSpy.restore()
|
||||
@showKeyingSpy.restore()
|
||||
@showDownloadingSpy.restore()
|
||||
@showPackagingSpy.restore()
|
||||
@downloadJamTrack.destroy()
|
||||
|
||||
it "shows downloading for signed package", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'unknown'})
|
||||
|
||||
spyOn(@downloadJamTrack.rest, 'getJamTrackRight').andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({signing_state: 'SIGNED'});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
window.jamClient.StartFileDownload = sinon.stub()
|
||||
|
||||
@downloadJamTrack.init()
|
||||
|
||||
expect(window.jamClient.JamTrackGetTrackDetail.callCount).toBe(1)
|
||||
expect(window.jamClient.StartFileDownload.callCount).toBe(1)
|
||||
expect(@showDownloadingSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-downloading')).toHaveLength(1)
|
||||
|
||||
eval(@downloadJamTrack.makeDownloadSuccessCallback() + '()')
|
||||
|
||||
expect(@showKeyingSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-keying')).toHaveLength(1)
|
||||
|
||||
# keying timer should be firing
|
||||
expect(@downloadJamTrack.states.keying.timer).toNotBe(null)
|
||||
|
||||
# say the keys have been fetched
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'ready'})
|
||||
|
||||
# check state again
|
||||
@downloadJamTrack.stateIntervalCheck()
|
||||
|
||||
# we should now be synchronized
|
||||
expect(@showSynchronizedSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.states.keying.timer).toBe(null)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-synchronized')).toHaveLength(1)
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
it "is not yet packaged", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'unknown'})
|
||||
|
||||
spyOn(@downloadJamTrack.rest, 'getJamTrackRight').andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({signing_state: 'QUIET'});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
spyOn(@downloadJamTrack.rest, 'enqueueJamTrack').andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
window.jamClient.StartFileDownload = sinon.stub()
|
||||
|
||||
@downloadJamTrack.init()
|
||||
|
||||
expect(@downloadJamTrack.attemptedEnqueue).toBe(true)
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(true)
|
||||
|
||||
# simulate poke from server saying the track has been queued
|
||||
@downloadJamTrack.onJamTrackRightEvent(null, {body: {signing_state: 'QUEUED'}})
|
||||
|
||||
# the frontend should be saying that it's packaging now
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(true)
|
||||
expect(@showPackagingSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-packaging')).toHaveLength(1)
|
||||
|
||||
# simulate poke from server saying the track is currently signing
|
||||
@downloadJamTrack.onJamTrackRightEvent(null, {body: {signing_state: 'SIGNING'}})
|
||||
|
||||
# the frontend still be saying it's packaging
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(true)
|
||||
expect(@showPackagingSpy.calledOnce).toBe(true)
|
||||
|
||||
# simulate poke from server saying the track is signed
|
||||
@downloadJamTrack.onJamTrackRightEvent(null, {body: {signing_state: 'SIGNED'}})
|
||||
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(false)
|
||||
|
||||
# downloading has started; other test covers this, so we stop testing
|
||||
expect(@showDownloadingSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-downloading')).toHaveLength(1)
|
||||
|
||||
# since we haven't yet made it to a leave node, make sure we haven't reported a stat
|
||||
expect(@statsSpy.callCount).toBe(0)
|
||||
|
||||
it "queue time out when packaging", ->
|
||||
window.jamClient.JamTrackGetTrackDetail = sinon.stub()
|
||||
window.jamClient.JamTrackGetTrackDetail.returns({'key_state' : 'unknown'})
|
||||
|
||||
getJamTrackRightSpy = spyOn(@downloadJamTrack.rest, 'getJamTrackRight')
|
||||
getJamTrackRightSpy.andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({signing_state: 'QUIET'});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
spyOn(@downloadJamTrack.rest, 'enqueueJamTrack').andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
window.jamClient.StartFileDownload = sinon.stub()
|
||||
|
||||
@downloadJamTrack.init()
|
||||
|
||||
expect(@downloadJamTrack.attemptedEnqueue).toBe(true)
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(true)
|
||||
|
||||
getJamTrackRightSpy.reset()
|
||||
|
||||
# simulate timer running out, and server check resulting in QUEUED_TIMEOUT
|
||||
getJamTrackRightSpy.andCallFake((data) =>
|
||||
d = $.Deferred();
|
||||
d.resolve({signing_state: 'QUEUED_TIMEOUT'});
|
||||
d.promise();
|
||||
)
|
||||
|
||||
@downloadJamTrack.transitionCheck()
|
||||
|
||||
# the frontend should be saying that it's packaging now
|
||||
expect(@downloadJamTrack.transitionTimer?).toBe(false)
|
||||
expect(@showErrorSpy.calledOnce).toBe(true)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-errored')).toHaveLength(1)
|
||||
expect(@downloadJamTrack.stateHolder.find('.state-errored .msg')).toContainText('The server took too long to begin processing your JamTrack.')
|
||||
|
||||
expect(@statsSpy.calledOnce).toBe(true)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
it "display state correctly", ->
|
||||
//$track = this.downloadJamTrack.createTrack()
|
||||
|
|
|
|||
Loading…
Reference in New Issue