* adding jam-web support for client update. fixing capybara 2.1.0 breaking changes

This commit is contained in:
Seth Call 2013-04-10 17:14:19 -05:00
parent e43f7effae
commit 315f5077b9
14 changed files with 247 additions and 29 deletions

View File

@ -1,6 +1,8 @@
source 'https://rubygems.org'
source 'https://jamjam:blueberryjam@www.jamkazam.com/gems/'
unless ENV["LOCAL_DEV"] == "1"
source 'https://jamjam:blueberryjam@www.jamkazam.com/gems/'
end
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
workspace = ENV["WORKSPACE"] || "~/workspace"

View File

@ -0,0 +1,134 @@
(function(context,$) {
"use strict";
context.JK = context.JK || {};
context.JK.ClientUpdate = function() {
var self = this;
var logger = context.JK.logger;
// updated once a download is started
var updateSize = 0;
/***************************************/
/******** CALLBACKS FROM BACKEND *******/
/***************************************/
function clientUpdateDownloadProgress(bytesReceived, bytesTotal, downloadSpeedMegSec, timeRemaining) {
//logger.debug("bytesReceived: " + bytesReceived, ", bytesTotal: " + bytesTotal, ", downloadSpeed: " + downloadSpeedMegSec, ", timeRemaining: " + timeRemaining );
// bytesTotal from Qt is not trust worthy; trust server's answer instead
$('#downloadprogressbar div').width( ((bytesReceived/updateSize) * 100).toString() + "%" )
$("#progres sbar_detail").text(parseInt(bytesReceived) + "/" + parseInt(updateSize))
}
function clientUpdateDownloadSuccess(updateLocation) {
logger.debug("client update downloaded successfully to: " + updateLocation);
startUpdate(updateLocation);
}
function clientUpdateDownloadFailure(errorMsg) {
logger.error("client update download error: " + errorMsg)
alert("Unable to download client update due to reason:" + errorMsg);
}
function clientUpdateLaunchSuccess(updateLocation) {
logger.debug("client update launched successfully to: " + updateLocation);
alert("Client updating momentarily...");
}
function clientUpdateLaunchFailure(errorMsg) {
logger.error("client update launch error: " + errorMsg)
alert("Unable to launch client updater due to reason: " + errorMsg)
}
/********************************************/
/******** END: CALLBACKS FROM BACKEND *******/
/********************************************/
function shouldUpdate(currentVersion, version) {
return true;
}
// check if updated is needed
function check() {
var product = "JamClient"
var os = context.jamClient.GetOSAsString()
var currentVersion = context.jamClient.ClientUpdateVersion();
if(currentVersion == null || currentVersion.indexOf("Compiled") > -1) {
// this is a developer build; it doesn't make much sense to do an packaged update, so skip
logger.debug("skipping client update check because this is a development build")
return;
}
$.ajax({
type: "GET",
url: "/api/versioncheck?product=" + product + "&os=" + os,
success: function(response) {
var version = response.version;
logger.debug("our client version: " + currentVersion + ", server client version: " + version);
// test url in lieu of having a configured server with a client-update available
//response.url = "http://localhost:8000/winimager/QtGui4.dll"
if(shouldUpdate(currentVersion, version)) {
updateSize = response.size;
// test metadata in lieu of having a configured server with a client-update available
// updateSize = 10000;
// version = "1.2.3"
if (confirm("The client will update to version " + version + " momentarily."))
{
startDownload(response.url)
}
}
},
error: function(jqXHR, textStatus, errorThrown) {
logger.error("Unable to do a client update check against /api/versioncheck");
}
});
}
function startDownload(url) {
logger.debug("starting client updater download from: " + url);
// initialize div in page so that we have something to update. temporary until real styles come
$('body').append($("<div id='downloadprogressbar_container'><span id='progressbar_info'>Downloading Client Update...<span id='progressbar_detail'></span></span><div id='downloadprogressbar'><div></div></div></div>"))
context.jamClient.ClientUpdateStartDownload(url,
"JK.ClientUpdate.DownloadProgressCallback",
"JK.ClientUpdate.DownloadSuccessCallback",
"JK.ClientUpdate.DownloadFailureCallback");
}
function startUpdate(updaterFilePath) {
logger.debug("starting client update from: " + updaterFilePath)
context.jamClient.ClientUpdateStartUpdate(updaterFilePath,
"JK.ClientUpdate.LaunchUpdateSuccessCallback",
"JK.ClientUpdate.LaunchUpdateFailureCallback");
}
function initialize() {
context.JK.ClientUpdate.DownloadProgressCallback = clientUpdateDownloadProgress;
context.JK.ClientUpdate.DownloadSuccessCallback = clientUpdateDownloadSuccess;
context.JK.ClientUpdate.DownloadFailureCallback = clientUpdateDownloadFailure;
context.JK.ClientUpdate.LaunchUpdateSuccessCallback = clientUpdateLaunchSuccess;
context.JK.ClientUpdate.LaunchUpdateFailureCallback = clientUpdateLaunchFailure;
return self;
}
// Expose publics
this.initialize = initialize;
this.check = check;
}
})(window,jQuery);

View File

@ -25,6 +25,7 @@
function GetFTUE() { return ftue; }
function SetFTUE(b) { ftue = b; }
function GetOS() { return 100000000; }
function GetOSAsString() { return "Win32"; }
function LatencyUpdated(map) { dbg('LatencyUpdated:' + JSON.stringify(map)); }
function LeaveSession(map) { dbg('LeaveSession:' + JSON.stringify(map)); }
@ -245,12 +246,38 @@
// Method which sets volume
function UpdateMixer(mixerId) {}
// Client Update Functions
function ClientUpdateVersion() { return "Compiled 1.2.3"; }
function ClientUpdateStartDownload(url, progressCallback, successCallback, failureCallback) {
// simulate a bunch of download callbacks
var count = 0;
var max = 100;
var bytesReceived = 0;
var bytesTotal = 10000;
function fire() {
count++;
setTimeout(function() {
bytesReceived = ( count / max ) * bytesTotal;
JK.ClientUpdate.DownloadProgressCallback(bytesReceived, bytesTotal, 0, 0)
if(count < max) {
fire()
}
}, 50)
}
fire()
}
function ClientUpdateStartUpdate(path, successCallback, failureCallback) {}
// Javascript Bridge seems to camel-case
// Set the instance functions:
this.GetASIODevices = GetASIODevices;
this.GetFTUE = GetFTUE;
this.GetOS = GetOS;
this.GetOSAsString = GetOSAsString;
this.JoinSession = JoinSession;
this.LatencyUpdated = LatencyUpdated;
this.LeaveSession = LeaveSession;
@ -299,6 +326,10 @@
this.TrackSetInstrument = TrackSetInstrument;
this.TrackGetInstrument = TrackGetInstrument;
// Client Update
this.ClientUpdateVersion = ClientUpdateVersion;
this.ClientUpdateStartDownload = ClientUpdateStartDownload;
this.ClientUpdateStartUpdate = ClientUpdateStartUpdate;
};
})(window,jQuery);

View File

@ -0,0 +1,36 @@
#downloadprogressbar_container {
position:fixed;
width: 400px;
top:0;
bottom: 0;
left: 0;
right: 0;
height:42px;
margin: auto;
background-color: black;
border:2px solid #ddd;
padding:5px;
}
#downloadprogressbar_container span#progressbar_info {
height:20px;
}
#downloadprogressbar_container span#progressbar_detail {
}
#downloadprogressbar {
height:22px;
border-radius: 13px;
padding: 3px;
}
#downloadprogressbar div {
background-color: orange;
width: 0;
height: 20px;
border-radius: 10px;
}

View File

@ -29,7 +29,7 @@ class ArtifactsController < ApiController
if @artifact.nil?
render :json => {}, :status => :ok
else
render :json => { "version" => @artifact.version, "uri" => @artifact.uri.path }, :status => :ok
render :json => { "version" => @artifact.version, "uri" => @artifact.uri.path, "sha1" => @artifact.sha1, "size" => @artifact.size }, :status => :ok
end
end

View File

@ -69,6 +69,11 @@
JK.currentUserId = null;
<% end %>
// do a client update check upon initialization
var clientUpdate = new JK.ClientUpdate()
clientUpdate.initialize().check()
// Some things can't be initialized until we're connected. Put them here.
function _initAfterConnect() {
@ -130,6 +135,7 @@
testConnected();
}
})
</script>

View File

@ -24,6 +24,7 @@
<%= stylesheet_link_tag "client/genreSelector", media: "all" %>
<%= stylesheet_link_tag "client/sessionList", media: "all" %>
<%= stylesheet_link_tag "client/searchResults", media: "all" %>
<%= stylesheet_link_tag "unstyled/progressbar", media: "all" %>
<%= include_gon %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>

View File

@ -13,19 +13,19 @@ require "sprockets/railtie"
ActiveRecord::Base.establish_connection(YAML::load(File.open('config/database.yml'))[Rails.env])
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
include JamRuby
include JamRuby
# require "rails/test_unit/railtie"
module SampleApp
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
module SampleApp
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.

View File

@ -1,11 +1,11 @@
ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp
ActionMailer::Base.smtp_settings = {
:address => "smtp.sendgrid.net",
:port => 587,
:domain => "www.jamkazam.com",
:authentication => :plain,
:user_name => "jamkazam",
:password => "jamjamblueberryjam",
:enable_starttls_auto => true
:address => "smtp.sendgrid.net",
:port => 587,
:domain => "www.jamkazam.com",
:authentication => :plain,
:user_name => "jamkazam",
:password => "jamjamblueberryjam",
:enable_starttls_auto => true
}

View File

@ -11,7 +11,7 @@ describe SessionsController do
it "should have the right title" do
get :new
response.body.should have_selector('title', :text => "Jamkazam | Sign in")
response.body.should have_title("Jamkazam | Sign in")
end
end

View File

@ -99,6 +99,7 @@ FactoryGirl.define do
product { "JamClient/Win32" }
environment { "public" }
sha1 { "blurp" }
size { 20 }
end
factory :musician_instrument, :class=> JamRuby::MusicianInstrument do

View File

@ -8,7 +8,7 @@ describe "Authentication" do
before { visit signin_path }
it { should have_selector('h1', text: 'sign in or register') }
it { expect(first('title').native.text).to eq "Jamkazam | Sign in" }
it { page.should have_title("Jamkazam | Sign in") }
end
describe "signin" do
@ -17,7 +17,7 @@ describe "Authentication" do
describe "with invalid information" do
before { click_button "SIGN IN" }
it { expect(first('title').native.text).to eq "Jamkazam | Sign in" }
it { page.should have_title("Jamkazam | Sign in") }
it { should have_selector('div.alert.alert-error', text: 'Invalid') }
#describe "after visiting another page" do
@ -35,7 +35,7 @@ describe "Authentication" do
end
# Successful sign-in goes to the client
it { expect(first('title').native.text).to eq "Jamkazam" }
it { page.should have_title("Jamkazam") }
it { should have_selector('h1', text: "Audio Gear Setup") }
end
end
@ -56,7 +56,7 @@ describe "Authentication" do
describe "after signing in" do
it "should render the desired protected page" do
expect(first('title').native.text).to eq "Jamkazam | Edit user"
page.should have_title("Jamkazam | Edit user")
end
describe "when signing in again" do
@ -69,7 +69,7 @@ describe "Authentication" do
it "should render the signed-in client page" do
# it now goes to /music_sessions
expect(first('title').native.text).to eq "Jamkazam"
page.should have_title("Jamkazam")
page.should have_selector('h1', text: "Audio Gear Setup")
end
end
@ -80,12 +80,12 @@ describe "Authentication" do
describe "visiting the edit page" do
before { visit edit_user_path(user) }
it { expect(first('title').native.text).to eq "Jamkazam | Sign in" }
it { page.should have_title("Jamkazam | Sign in") }
end
describe "visiting user index" do
before { visit users_path }
it { expect(first('title').native.text).to eq "Jamkazam | Sign in" }
it { page.should have_title("Jamkazam | Sign in") }
end
end
end
@ -99,7 +99,7 @@ describe "Authentication" do
before { visit edit_user_path(wrong_user) }
it {
pending "this should work, but right now you get redirected to ftue"
expect(first('title').native.text).to eq'Action Controller: Exception caught'
page.should have_title('Action Controller: Exception caught')
}
end
end

View File

@ -14,7 +14,7 @@ describe "Artifact API ", :type => :api do
it "matches an artifact" do
get '/api/versioncheck.json', { :os=>'Win32', :product=>'JamClient'}
last_response.status.should eql(200)
JSON.parse(last_response.body).should eql({ "version" => @artifact.version, "uri" => @artifact.uri.path})
JSON.parse(last_response.body).should eql({ "version" => @artifact.version, "uri" => @artifact.uri.path, "size" => @artifact.size, "sha1" => @artifact.sha1})
end
it "matches no artifact" do

View File

@ -25,6 +25,7 @@ include JamRuby
# put ActionMailer into test mode
ActionMailer::Base.delivery_method = :test
Spork.prefork do
# Loading more in this block will cause your tests to run faster. However,
# if you change any configuration or code from libraries loaded here, you'll
@ -45,6 +46,12 @@ Spork.prefork do
end
Capybara.javascript_driver = :poltergeist
end
Capybara.configure do |config|
config.match = :one
config.exact_options = true
config.ignore_hidden_elements = true
config.visible_text_only = true
end
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.