diff --git a/app/assets/javascripts/ftue.js b/app/assets/javascripts/ftueAudioSelection.js similarity index 62% rename from app/assets/javascripts/ftue.js rename to app/assets/javascripts/ftueAudioSelection.js index 04b28b73e..011c97a8b 100644 --- a/app/assets/javascripts/ftue.js +++ b/app/assets/javascripts/ftueAudioSelection.js @@ -1,18 +1,17 @@ /** -* The First-Time User Experience (FTUE) Screen to be shown -* to users who have not set up their audio hardware yet. -* Corresponds to the route #/ftue3 +* FtueAudioSelectionScreen +* Javascript that goes with the screen where initial +* selection of the audio devices takes place. +* Corresponds to /#ftue2 */ (function(context,$) { "use strict"; context.JK = context.JK || {}; - context.JK.FTUEScreen = function(app) { + context.JK.FtueAudioSelectionScreen = function(app) { var logger = context.JK.logger; var jamClient = context.jamClient; - var playbackTestRunning = false; - var recordingTestRunning = false; function beforeShow(data) { loadDevices(); @@ -24,6 +23,7 @@ function loadDevices() { $('#choose-input-audio-device select').empty(); $('#choose-output-audio-device select').empty(); + $('#choose-input-voice-device select').empty(); var optionTemplate = $('#template_audio_device_item').html(); var devices = context.jamClient.GetASIODevices(); var inputOptions = []; @@ -60,6 +60,7 @@ } $('#choose-input-audio-device select').html(inputOptions.join('')); $('#choose-output-audio-device select').html(outputOptions.join('')); + $('#choose-input-voice-device select').html(inputOptions.join('')); } /** @@ -89,45 +90,6 @@ $('#latency-testing p').html("Done."); } - function playbackButtonHandler(evt) { - if (playbackTestRunning) { - $('#playback-testing p').html('Test stopped by user'); - $('#playbackTestingButton').html('Start Playback Test'); - playbackTestRunning = false; - context.jamClient.StopPlayTest(); - } else { - $('#playback-testing p').html('Playback test in progress... Click the button below when things start to sound crappy'); - $('#playbackTestingButton').html('Click when things sound bad...'); - playbackTestRunning = true; - context.jamClient.StartPlayTest('JK.playbackTestComplete'); - } - } - - function playbackTestComplete() { - logger.debug('playbackTestComplete. Arguments:'); - logger.debug(arguments); - $('#playback-testing p').html('Done'); - $('#playbackTestingButton').html('Start Playback Test'); - playbackTestRunning = false; - } - - function recordingButtonHandler(evt) { - if (recordingTestRunning) { - $('#recording-testing p').html('Recording complete.'); - $('#recordingTestingButton').html('Start Recording Test'); - recordingTestRunning = false; - context.jamClient.RecordTestEnd(); - } else { - $('#recording-testing p').html('Recording in progress... Click the button below to stop recording'); - $('#recordingTestingButton').html('Stop Recording'); - recordingTestRunning = true; - context.jamClient.RecordTestBegin(); - } - } - - function recordingPlaybackButtonHandler(evt) { - context.jamClient.RecordTestPlayback(); - } function events() { $('#enableDevices').click(function() { @@ -135,15 +97,12 @@ testLatency(); }); - $('#playbackTestingButton').click(playbackButtonHandler); - $('#recordingTestingButton').click(recordingButtonHandler); - $('#recordingTestPlaybackButton').click(recordingPlaybackButtonHandler); } function initialize() { events(); var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow }; - app.bindScreen('ftue3', screenBindings); + app.bindScreen('ftue2', screenBindings); } // Expose publics @@ -151,7 +110,6 @@ // Expose callbacks for the bridge on the global namespace context.JK.latencyTestingComplete = latencyTestingComplete; - context.JK.playbackTestComplete = playbackTestComplete; return this; }; diff --git a/app/assets/javascripts/ftueAudioTesting.js b/app/assets/javascripts/ftueAudioTesting.js new file mode 100644 index 000000000..cc5b5116f --- /dev/null +++ b/app/assets/javascripts/ftueAudioTesting.js @@ -0,0 +1,98 @@ +/** +* FtueAudioTestingScreen +* Javascript that goes with the screen where +* testing of selected audio devices happens. +* Corresponds to /#ftue3 +*/ +(function(context,$) { + "use strict"; + + context.JK = context.JK || {}; + context.JK.FtueAudioTestingScreen = function(app) { + var logger = context.JK.logger; + var jamClient = context.jamClient; + + var selectors = { + step1: 'div[layout-id="ftue3"] div[data-step="step1"]', + step2: 'div[layout-id="ftue3"] div[data-step="step2"]', + step3: 'div[layout-id="ftue3"] div[data-step="step3"]', + good: 'div[layout-id="ftue3"] div[data-step="good"]', + bad: 'div[layout-id="ftue3"] div[data-step="bad"]', + progress1: '#recordingTestProgress1', + progress1Int: '#___recordingTestProgress1___', + progress2: '#recordingTestProgress2', + progress2Int: '#___recordingTestProgress2___' + }; + + function beforeShow(data) { + $(selectors.step1).show(); + $(selectors.step2).hide(); + $(selectors.step3).hide(); + $(selectors.good).hide(); + $(selectors.bad).hide(); + } + + function afterShow(data) {} + + function runProgressBar(selector, seconds, doneFunction) { + var id = "___" + selector.substr(1) + "___"; + $(selector).html('
'); + $("#" + id).animate({ + width: "400px" + }, seconds * 1000, doneFunction); + } + + function startTestButtonHandler(evt) { + $(selectors.step1).hide(); + $(selectors.step3).hide(); + $(selectors.good).hide(); + $(selectors.bad).hide(); + $(selectors.step2).show(); + runProgressBar(selectors.progress1, 10, good); + context.jamClient.RecordTestBegin(); + } + + function poorAudioButtonHandler(evt) { + $(selectors.progress1Int).stop(); + $(selectors.step2).hide(); + $(selectors.step3).show(); + runProgressBar(selectors.progress2, 10, bad); + //context.jamClient.RecordTestBegin(); + } + + function goodAudioButtonHandler(evt) { + good(); + } + + function good() { + $(selectors.step2).hide(); + $(selectors.step3).hide(); + $(selectors.good).show(); + } + + function bad() { + $(selectors.step3).hide(); + $(selectors.bad).show(); + } + + function events() { + $('.startTestButton').click(startTestButtonHandler); + $('#poorAudioButton').click(poorAudioButtonHandler); + $('#goodAudioButton').click(goodAudioButtonHandler); + } + + function initialize() { + events(); + var screenBindings = { 'beforeShow': beforeShow, 'afterShow': afterShow }; + app.bindScreen('ftue3', screenBindings); + } + + // Expose publics + this.initialize = initialize; + + //context.JK.playbackTestComplete = playbackTestComplete; + + return this; + }; + + })(window,jQuery); \ No newline at end of file diff --git a/app/assets/stylesheets/client/ftue.css.scss b/app/assets/stylesheets/client/ftue.css.scss new file mode 100644 index 000000000..be15eba5e --- /dev/null +++ b/app/assets/stylesheets/client/ftue.css.scss @@ -0,0 +1,42 @@ +/* Custom Styles for the FTUE Screens */ + +@import "client/common.css.scss"; +@charset "UTF-8"; + +div[layout-id="ftue2"] { + .formrow { + position:relative; + clear:both; + border:none; + margin: 12px; + padding:4px; + } + label { + text-align:left; + } + select { + display:block; + position:absolute; + left: 140px; + top: 0px; + } +} + +div[layout-id="ftue3"] { + button { + margin: 0px 2em; + } + + .progressContainer { + margin: 2em; + border: 1px solid #fff; + width: 400px; + height: 10px; + } + + .progressFull { + height: 10px; + width: 2px; + background-color:#0f0; + } +} diff --git a/app/assets/stylesheets/client/jamkazam.css.scss b/app/assets/stylesheets/client/jamkazam.css.scss index 73993c0dd..ca9539b69 100644 --- a/app/assets/stylesheets/client/jamkazam.css.scss +++ b/app/assets/stylesheets/client/jamkazam.css.scss @@ -21,9 +21,12 @@ body { font-weight: 300; } +b { font-weight: bold; } + a { cursor:pointer; color: $ColorLink; + text-decoration: none; } a:hover { @@ -258,4 +261,4 @@ input[type="text"] { .right { float:right; -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/client/screen_common.css.scss b/app/assets/stylesheets/client/screen_common.css.scss index 45a30a05d..8908e4ad2 100644 --- a/app/assets/stylesheets/client/screen_common.css.scss +++ b/app/assets/stylesheets/client/screen_common.css.scss @@ -8,6 +8,7 @@ .screen.secondary { border: 1px solid $ColorScreenPrimary; background-color:$ColorScreenBackground; + .footer button { margin:1em 0em 1em 1em; } @@ -139,4 +140,4 @@ textarea { -webkit-box-shadow: inset 2px 2px 3px 0px #888; box-shadow: inset 2px 2px 3px 0px #888; color:#333; -} \ No newline at end of file +} diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e5ebc94f4..60d4be406 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -52,7 +52,7 @@ class UsersController < ApplicationController end def signup_confirm - @user = UserManager.new.signup_confirm(params[:signup_token]) + @user = UserManager.new.signup_confirm(params[:signup_token], request.remote_ip) unless @user.nil? || @user.errors.any? sign_in @user diff --git a/app/views/clients/_ftue1.html.erb b/app/views/clients/_ftue1.html.erb index 28280984a..abf69e557 100644 --- a/app/views/clients/_ftue1.html.erb +++ b/app/views/clients/_ftue1.html.erb @@ -1,10 +1,17 @@
-

Welcome to JamKazam!

+

Audio Gear Setup

<%= render "screen_navigation" %>
-

You'll need appropriate audio gear. Here are some links to where you can buy some.

-

Make sure your audio gear is plugged in, then CONTINUE.

+

If you already have audio gear to get your instrumental or vocal music into your computer, please set up your gear and instrument now. Then click the Next button below. For Windows this will be ASIO-compatible audio devices, and Mac gear will use Core Audio. We strongly recommend using headphones with your gear vs. speakers or powered monitors to avoid feedback problems. If you don't already have this gear handy or are not sure what will work, please use the help links below for some guidance:

+ +
+

+
diff --git a/app/views/clients/_ftue2.html.erb b/app/views/clients/_ftue2.html.erb index 20273c3ab..26fce3cdc 100644 --- a/app/views/clients/_ftue2.html.erb +++ b/app/views/clients/_ftue2.html.erb @@ -1,10 +1,42 @@
-

Welcome to JamKazam!

+

Audio Gear Settings

<%= render "screen_navigation" %>
-

Next we'll show you how to hook up a cable for a loopback test, so we can test your latency.

-

Once your cables are all connected, then CONTINUE.

+

Please choose the audio gear you want to use for audio input, chat input, and audio output below. Then play and either sing or speak to ensure that you can hear both your instrument and voice through your headphones. After verifying that you hear your music and voice properly, please click the Next button below. If you don't hear things correctly, please press the Help button below for troubleshooting guidance.

+ +
+
+ +
+
+ +
+
+ +
+
+ +
+

+ + + +

+
+ + diff --git a/app/views/clients/_ftue3.html.erb b/app/views/clients/_ftue3.html.erb index f921b9d3a..3345abcd4 100644 --- a/app/views/clients/_ftue3.html.erb +++ b/app/views/clients/_ftue3.html.erb @@ -1,45 +1,44 @@
-

Welcome to JamKazam!

+

Audio Gear Test

<%= render "screen_navigation" %>
-
-

Step 1: Choose Devices

- - - +
+

We will now test your audio gear to ensure it works and to find its ideal settings. When you are ready, please click the Start Test button below, and be ready to start playing your instrument or singing.

+
-
-

Latency Testing

-

+
+

Please play your instrument and/or sing, and listen to the audio. If the quality of the audio becomes poor, please click the Poor Audio button below. This test will last about 45 seconds.

+ +
-
-

Playback Testing

-

Click the button below to start a playback test. We'll start with safe settings, and then lower the values for better latency. When things begin to sound bad, click the button again.

- +
+

Please press the Good Audio button when the audio quality improves to an acceptable level.

+ +
-
-

Recording Testing

-

When ready, click the button below to enable recording of your audio input. When done, click the button again, and use the other button for playback to see how things sound.

- - + +
+

Congratulations! Your audio gear is now ready to use, and you may create or join sessions with other musicians in JamKazam.

+
-

If everything looks good, then WE'RE DONE.

+
+

We're sorry, but it appears you are not happy with the quality of your audio, so we cannot recommend that you use JamKazam with this audio gear.

+ + +
+
+

+ + +

+
- diff --git a/app/views/clients/index.html.erb b/app/views/clients/index.html.erb index 1f87d7d36..cbd8ccf80 100644 --- a/app/views/clients/index.html.erb +++ b/app/views/clients/index.html.erb @@ -72,13 +72,15 @@ var sessionScreen = new JK.SessionScreen(jk); sessionScreen.initialize(); - var ftueScreen = new JK.FTUEScreen(jk); - ftueScreen.initialize(); + var ftueAudioSelectionScreen = new JK.FtueAudioSelectionScreen(jk); + ftueAudioSelectionScreen.initialize(); + + var ftueAudioTestingScreen = new JK.FtueAudioTestingScreen(jk); + ftueAudioTestingScreen.initialize(); var testBridgeScreen = new JK.TestBridgeScreen(jk); testBridgeScreen.initialize(); - } else { var landing = new JK.LandingPage(jk); landing.initialize(); diff --git a/app/views/layouts/client.html.erb b/app/views/layouts/client.html.erb index f60e089b8..a59ba5314 100644 --- a/app/views/layouts/client.html.erb +++ b/app/views/layouts/client.html.erb @@ -18,6 +18,7 @@ <%= stylesheet_link_tag "client/findSession", media: "all" %> <%= stylesheet_link_tag "client/session", media: "all" %> <%= stylesheet_link_tag "client/search", media: "all" %> + <%= stylesheet_link_tag "client/ftue", media: "all" %> <%= stylesheet_link_tag "client/lato", media: "all" %> <%= stylesheet_link_tag "client/createSession", media: "all" %> <%= include_gon %> diff --git a/build b/build index 1d4bf9b13..2339eeda8 100755 --- a/build +++ b/build @@ -48,14 +48,16 @@ if [ -z $SKIP_TESTS ]; then exit 1 fi - echo "running cucumber tests" - DISPLAY=":99" bundle exec cucumber - if [ "$?" = "0" ]; then - echo "success: cucumber tests completed" - else - echo "running cucumber tests failed" - exit 1 - fi + if [ -z "$SKIP_CUCUMBER_TESTS" ]; then + echo "running cucumber tests" + DISPLAY=":99" bundle exec cucumber + if [ "$?" = "0" ]; then + echo "success: cucumber tests completed" + else + echo "running cucumber tests failed" + exit 1 + fi + fi fi if [ -n "$PACKAGE" ]; then diff --git a/config/initializers/dev_users.rb b/config/initializers/dev_users.rb index 024cd218e..f65daaae6 100644 --- a/config/initializers/dev_users.rb +++ b/config/initializers/dev_users.rb @@ -9,4 +9,5 @@ if Rails.env == "development" && Rails.application.config.bootstrap_dev_users User.create_dev_user("David", "Wilson", "david@jamkazam.com", "jam123", "Austin", "TX", "US", nil, nil) User.create_dev_user("Nat", "Meo", "nat@jamkazam.com", "jam123", "Raleigh", "Virginia", "US", nil, nil) User.create_dev_user("Jonathon", "Wilson", "jonathon@jamkazam.com", "jam123", "Denver", "Colorado", "US", nil, nil) -end \ No newline at end of file + User.create_dev_user("Jonathan", "Kolyer", "jonathan@jamkazam.com", "jam123", "San Francisco", "CA", "US", nil, nil) +end diff --git a/features/step_definitions/create_session_steps.rb b/features/step_definitions/create_session_steps.rb index 47208d853..f67986b9d 100644 --- a/features/step_definitions/create_session_steps.rb +++ b/features/step_definitions/create_session_steps.rb @@ -14,11 +14,11 @@ When /^I create a public music session$/ do sleep 1 page.find("a[href='#/ftue3']").click sleep 1 + page.find('div[data-step="step1"] button.startTestButton').click + page.find("#poorAudioButton").click + page.find("#goodAudioButton").click page.find("[cucumber-id='ftue-home-link']").click - sleep 1 - page.find("[layout-link='createSession']").click - sleep 1 # pick a genre, any genre page.find("input[value='african']").click @@ -45,6 +45,12 @@ Then /^I should be in a music session that another musician can find$/ do sleep 1 @second_session.find("a[href='#/ftue3']").click sleep 1 + @second_session.find('div[data-step="step1"] button.startTestButton').click + sleep 1 + @second_session.find("#poorAudioButton").click + sleep 1 + @second_session.find("#goodAudioButton").click + sleep 1 @second_session.find("[cucumber-id='ftue-home-link']").click sleep 1 diff --git a/features/support/before_cucumber.rb b/features/support/before_cucumber.rb index 1b98e3b3f..a2743f0fb 100644 --- a/features/support/before_cucumber.rb +++ b/features/support/before_cucumber.rb @@ -2,10 +2,12 @@ require 'active_record' require 'action_mailer' require 'jam_db' require 'jam_ruby' +require 'capybara' +require 'selenium/webdriver' + require File.expand_path('../../../spec/spec_db', __FILE__) include JamRuby - # put this in a class, so that multiple loads of this file # don't cause the database to be recreated multiple times class BeforeCucumber @@ -18,4 +20,33 @@ class BeforeCucumber ActionMailer::Base.delivery_method = :test end -end \ No newline at end of file +end + +if ENV['SHOW_JS_ERRORS'] == "1" + # we need a firefox extension to start intercepting javascript errors before the page + # scripts load + Capybara.register_driver :selenium do |app| + profile = Selenium::WebDriver::Firefox::Profile.new + # see https://github.com/mguillem/JSErrorCollector + profile.add_extension File.join(Rails.root, "features/support/extensions/JSErrorCollector.xpi") + Capybara::Selenium::Driver.new app, :profile => profile + end + + After do |scenario| + if page.driver.to_s.match("Selenium") + errors = page.execute_script("return window.JSErrorCollector_errors.pump()") + + if errors.any? + puts '-------------------------------------------------------------' + puts "Found #{errors.length} javascript errors" + puts '-------------------------------------------------------------' + errors.each do |error| + puts " #{error["errorMessage"]} (#{error["sourceName"]}:#{error["lineNumber"]})" + end + # raise "Javascript error detected, see above" + end + + end + end +end + diff --git a/features/support/extensions/JSErrorCollector.xpi b/features/support/extensions/JSErrorCollector.xpi new file mode 100644 index 000000000..3e8af6a84 Binary files /dev/null and b/features/support/extensions/JSErrorCollector.xpi differ diff --git a/features/support/login_helper.rb b/features/support/login_helper.rb index b5153b92b..e869e908c 100644 --- a/features/support/login_helper.rb +++ b/features/support/login_helper.rb @@ -2,6 +2,11 @@ module LoginHelper def login(user, context) context.visit root_path + + # When troubleshooting JS errors, sleeping when the UI first comes up is helpful. + # It allows you to bring up a JS console on the test browser and see what the problem is. + # sleep 60 + # verify that the root page is showing context.should have_content "Welcome to JamKazam" @@ -20,4 +25,4 @@ module LoginHelper end end -World(LoginHelper) \ No newline at end of file +World(LoginHelper) diff --git a/lib/managers/user_manager.rb b/lib/managers/user_manager.rb index 4c7f37d1f..e87548218 100644 --- a/lib/managers/user_manager.rb +++ b/lib/managers/user_manager.rb @@ -33,9 +33,10 @@ class UserManager < BaseManager #end end - def signup_confirm(signup_token) + def signup_confirm(signup_token, remote_ip=nil) begin @user = User.signup_confirm(signup_token) + @user.location = MaxMindManager.lookup(remote_ip) if remote_ip rescue ActiveRecord::RecordNotFound @user = nil end