diff --git a/db/manifest b/db/manifest index 2a8b874f0..899773187 100755 --- a/db/manifest +++ b/db/manifest @@ -154,4 +154,5 @@ fix_connection_fields.sql session_ratings.sql scheduled_sessions.sql add_last_jam_user_fields.sql -periodic_emails.sql +remove_lat_lng_user_fields.sql +update_get_work_for_larger_radius.sql diff --git a/db/up/remove_lat_lng_user_fields.sql b/db/up/remove_lat_lng_user_fields.sql new file mode 100644 index 000000000..c15026ee3 --- /dev/null +++ b/db/up/remove_lat_lng_user_fields.sql @@ -0,0 +1,2 @@ +alter table users drop column lat; +alter table users drop column lng; diff --git a/db/up/update_get_work_for_larger_radius.sql b/db/up/update_get_work_for_larger_radius.sql new file mode 100644 index 000000000..f2edb5123 --- /dev/null +++ b/db/up/update_get_work_for_larger_radius.sql @@ -0,0 +1,16 @@ +DROP FUNCTION get_work (mylocidispid BIGINT); +CREATE FUNCTION get_work (mylocidispid BIGINT, myaddr BIGINT) RETURNS TABLE (client_id VARCHAR(64)) ROWS 5 VOLATILE AS $$ +BEGIN + CREATE TEMPORARY TABLE foo (locidispid BIGINT, locid INT); + INSERT INTO foo SELECT DISTINCT locidispid, locidispid/1000000 FROM connections WHERE client_type = 'client'; + DELETE FROM foo WHERE locidispid IN (SELECT DISTINCT blocidispid FROM current_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < INTERVAL '24 hours'); + DELETE FROM foo WHERE locid NOT IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog FROM geoiplocations WHERE locid = mylocidispid/1000000), 4023360)); + CREATE TEMPORARY TABLE bar (client_id VARCHAR(64), locidispid BIGINT, r DOUBLE PRECISION); + INSERT INTO bar SELECT l.client_id, l.locidispid, random() FROM connections l, foo f WHERE l.locidispid = f.locidispid AND l.client_type = 'client' AND addr != myaddr; + DROP TABLE foo; + DELETE FROM bar b WHERE r != (SELECT MAX(r) FROM bar b0 WHERE b0.locidispid = b.locidispid); + RETURN QUERY SELECT b.client_id FROM bar b ORDER BY r LIMIT 5; + DROP TABLE bar; + RETURN; +END; +$$ LANGUAGE plpgsql; diff --git a/resetdb.sh b/resetdb.sh index 5a06c1ff0..10b0bee88 100755 --- a/resetdb.sh +++ b/resetdb.sh @@ -4,4 +4,4 @@ dropdb jam_db_build dropdb jam_ruby_test dropdb jam_web_test dropdb jam_websocket_test -createdb -Upostgres jam +sudo su postgres -c "createdb jam" diff --git a/ruby/lib/jam_ruby/models/connection.rb b/ruby/lib/jam_ruby/models/connection.rb index d706542db..82236b295 100644 --- a/ruby/lib/jam_ruby/models/connection.rb +++ b/ruby/lib/jam_ruby/models/connection.rb @@ -134,7 +134,7 @@ module JamRuby end def did_create - self.user.update_lat_lng(self.ip_address) if self.user && self.ip_address + # self.user.update_lat_lng(self.ip_address) if self.user && self.ip_address end def report_add_participant diff --git a/ruby/lib/jam_ruby/models/get_work.rb b/ruby/lib/jam_ruby/models/get_work.rb index f82ca00f4..2d52615c8 100644 --- a/ruby/lib/jam_ruby/models/get_work.rb +++ b/ruby/lib/jam_ruby/models/get_work.rb @@ -3,15 +3,15 @@ module JamRuby self.table_name = "connections" - def self.get_work(mylocidispid) - list = self.get_work_list(mylocidispid) + def self.get_work(mylocidispid, myaddr) + list = self.get_work_list(mylocidispid, myaddr) return nil if list.nil? return nil if list.length == 0 return list[0] end - def self.get_work_list(mylocidispid) - r = GetWork.select(:client_id).find_by_sql("select get_work(#{mylocidispid}) as client_id") + def self.get_work_list(mylocidispid, myaddr) + r = GetWork.select(:client_id).find_by_sql("select get_work(#{mylocidispid}, #{myaddr}) as client_id") #puts("r = #{r}") a = r.map {|i| i.client_id} #puts("a = #{a}") diff --git a/ruby/lib/jam_ruby/models/max_mind_geo.rb b/ruby/lib/jam_ruby/models/max_mind_geo.rb index f11e3ddf2..53a9c9716 100644 --- a/ruby/lib/jam_ruby/models/max_mind_geo.rb +++ b/ruby/lib/jam_ruby/models/max_mind_geo.rb @@ -88,35 +88,42 @@ module JamRuby end end end - User.find_each { |usr| usr.update_lat_lng } + # User.find_each { |usr| usr.update_lat_lng } Band.find_each { |bnd| bnd.update_lat_lng } end def self.where_latlng(relation, params, current_user=nil) - if 0 < (distance = params[:distance].to_i) - latlng = [] - if location_city = params[:city] - if geo = self.where(:city => params[:city]).limit(1).first + # this is only valid to call when relation is about bands + distance = params[:distance].to_i + if distance > 0 + latlng = nil + location_city = params[:city] + location_state = params[:state] + location_country = params[:country] + remote_ip = params[:remote_ip] + + if location_city and location_state and location_country + geo = self.where(city: location_city, region: location_state, country: location_country).limit(1).first + if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0) + # it isn't reasonable for both to be 0... latlng = [geo.lat, geo.lng] end - elsif current_user - if current_user.lat.nil? || current_user.lng.nil? - if params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip])) - geo.lat = nil if geo.lat = 0 - geo.lng = nil if geo.lng = 0 - latlng = [geo.lat, geo.lng] if geo.lat && geo.lng - end - else - latlng = [current_user.lat, current_user.lng] + elsif current_user and current_user.locidispid and current_user.locidispid != 0 + location = GeoIpLocations.lookup(current_user.locidispid/1000000) + if location and location.latitude and location.longitude and (location.latitude != 0 or location.longitude != 0) + # it isn't reasonable for both to be 0... + latlng = [location.latitude, location.longitude] + end + elsif remote_ip + geo = self.ip_lookup(remote_ip) + if geo and geo.lat and geo.lng and (geo.lat != 0 or geo.lng != 0) + # it isn't reasonable for both to be 0... + latlng = [geo.lat, geo.lng] end - elsif params[:remote_ip] && (geo = self.ip_lookup(params[:remote_ip])) - geo.lat = nil if geo.lat = 0 - geo.lng = nil if geo.lng = 0 - latlng = [geo.lat, geo.lng] if geo.lat && geo.lng end - if latlng.present? - relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL']) - .within(distance, :origin => latlng) + + if latlng + relation = relation.where(['lat IS NOT NULL AND lng IS NOT NULL']).within(distance, origin: latlng) end end relation diff --git a/ruby/lib/jam_ruby/models/score.rb b/ruby/lib/jam_ruby/models/score.rb index 570d409f4..962acd7c1 100644 --- a/ruby/lib/jam_ruby/models/score.rb +++ b/ruby/lib/jam_ruby/models/score.rb @@ -9,8 +9,10 @@ module JamRuby default_scope order('score_dt desc') - def self.createx(alocidispid, anodeid, aaddr, blocidispid, bnodeid, baddr, score, score_dt) + def self.createx(alocidispid, anodeid, aaddr, blocidispid, bnodeid, baddr, score, score_dt=nil) score_dt = Time.new.utc if score_dt.nil? + score = score.ceil + raise "score must be positive" if score <= 0 Score.create(alocidispid: alocidispid, anodeid: anodeid, aaddr: aaddr, blocidispid: blocidispid, bnodeid: bnodeid, baddr: baddr, score: score, scorer: 0, score_dt: score_dt) Score.create(alocidispid: blocidispid, anodeid: bnodeid, aaddr: baddr, blocidispid: alocidispid, bnodeid: anodeid, baddr: aaddr, score: score, scorer: 1, score_dt: score_dt) if alocidispid != blocidispid end @@ -25,5 +27,9 @@ module JamRuby return -1 if s.nil? return s.score end + + def self.score_conns(c1, c2, score) + self.createx(c1.locidispid, c1.client_id, c1.addr, c2.locidispid, c2.client_id, c2.addr, score) + end end end diff --git a/ruby/lib/jam_ruby/models/search.rb b/ruby/lib/jam_ruby/models/search.rb index 77509d8ad..2274e1fd0 100644 --- a/ruby/lib/jam_ruby/models/search.rb +++ b/ruby/lib/jam_ruby/models/search.rb @@ -120,14 +120,32 @@ module JamRuby ordering.blank? ? keys[0] : keys.detect { |oo| oo.to_s == ordering } end - def self.musician_filter(params={}, current_user=nil) + # produce a list of musicians (users where musician is true) + # params: + # instrument - instrument to search for or blank + # handled by relation_pagination: + # page - page number to fetch (origin 1) + # per_page - number of entries per page + # handled by order_param: + # orderby - ??? (followed, plays, playing) + # handled by where_latlng: + # distance - defunct + # city - defunct + # remote_ip - defunct + def self.musician_filter(params={}, user=nil, conn=nil) rel = User.musicians unless (instrument = params[:instrument]).blank? rel = rel.joins("RIGHT JOIN musicians_instruments AS minst ON minst.user_id = users.id") .where(['minst.instrument_id = ? AND users.id IS NOT NULL', instrument]) end - rel = MaxMindGeo.where_latlng(rel, params, current_user) + locidispid = (conn ? conn.locidispid : (user ? user.last_jam_locidispid : 0)) + + # to find appropriate musicians we need to join users with connections to get to their locidispid, + # then join scores with alocidispid found above with the musicians' locidispid to weed out users + # with no scores or bad scores + + # todo scott - rel = MaxMindGeo.where_latlng(rel, params, user) sel_str = 'users.*' case ordering = self.order_param(params) @@ -157,7 +175,7 @@ module JamRuby srch = Search.new srch.search_type = :musicians_filter srch.page_num, srch.page_count = page, objs.total_pages - srch.musician_results_for_user(objs, current_user) + srch.musician_results_for_user(objs, user) end def self.relation_pagination(rel, params) @@ -274,9 +292,9 @@ module JamRuby end def self.new_musicians(usr, since_date=Time.now - 1.week, max_count=50, radius=M_MILES_DEFAULT) + # todo scott turn this into score .within(radius, :origin => [usr.lat, usr.lng]) rel = User.musicians .where(['created_at >= ? AND users.id != ?', since_date, usr.id]) - .within(radius, :origin => [usr.lat, usr.lng]) .order('created_at DESC') .limit(max_count) objs = rel.all.to_a diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 419acbf7b..408719774 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -12,9 +12,9 @@ module JamRuby include Geokit::ActsAsMappable::Glue unless defined?(acts_as_mappable) acts_as_mappable - after_save :check_lat_lng + # after_save :check_lat_lng - attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection, :lat, :lng + attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection # updating_password corresponds to a lost_password attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json @@ -140,8 +140,8 @@ module JamRuby scope :musicians, where(:musician => true) scope :fans, where(:musician => false) - scope :geocoded_users, where(['lat IS NOT NULL AND lng IS NOT NULL']) - scope :musicians_geocoded, musicians.geocoded_users + # todo scott someone with locidispid - scope :geocoded_users, where(['lat IS NOT NULL AND lng IS NOT NULL']) + # todo scott geocoded_users that are musicians - scope :musicians_geocoded, musicians.geocoded_users scope :email_opt_in, where(:subscribe_email => true) def user_progression_fields @@ -1103,55 +1103,56 @@ module JamRuby !self.city.blank? && (!self.state.blank? || !self.country.blank?) end - def check_lat_lng - if (city_changed? || state_changed? || country_changed?) && !lat_changed? && !lng_changed? - update_lat_lng - end - end + # def check_lat_lng + # if (city_changed? || state_changed? || country_changed?) && !lat_changed? && !lng_changed? + # update_lat_lng + # end + # end - def update_lat_lng(ip_addy=nil) - if provides_location? # ip_addy argument ignored in this case - return false unless ip_addy.nil? # do nothing if attempting to set latlng from an ip address - query = { :city => self.city } - query[:region] = self.state unless self.state.blank? - query[:country] = self.country unless self.country.blank? - if geo = MaxMindGeo.where(query).limit(1).first - geo.lat = nil if geo.lat = 0 - geo.lng = nil if geo.lng = 0 - if geo.lat && geo.lng && (self.lat != geo.lat || self.lng != geo.lng) - self.update_attributes({ :lat => geo.lat, :lng => geo.lng }) - return true - end - end - elsif ip_addy - if geo = MaxMindGeo.ip_lookup(ip_addy) - geo.lat = nil if geo.lat = 0 - geo.lng = nil if geo.lng = 0 - if self.lat != geo.lat || self.lng != geo.lng - self.update_attributes({ :lat => geo.lat, :lng => geo.lng }) - return true - end - end - else - if self.lat || self.lng - self.update_attributes({ :lat => nil, :lng => nil }) - return true - end - end - false - end + # def update_lat_lng(ip_addy=nil) + # if provides_location? # ip_addy argument ignored in this case + # return false unless ip_addy.nil? # do nothing if attempting to set latlng from an ip address + # query = { :city => self.city } + # query[:region] = self.state unless self.state.blank? + # query[:country] = self.country unless self.country.blank? + # if geo = MaxMindGeo.where(query).limit(1).first + # geo.lat = nil if geo.lat = 0 + # geo.lng = nil if geo.lng = 0 + # if geo.lat && geo.lng && (self.lat != geo.lat || self.lng != geo.lng) + # self.update_attributes({ :lat => geo.lat, :lng => geo.lng }) + # return true + # end + # end + # elsif ip_addy + # if geo = MaxMindGeo.ip_lookup(ip_addy) + # geo.lat = nil if geo.lat = 0 + # geo.lng = nil if geo.lng = 0 + # if self.lat != geo.lat || self.lng != geo.lng + # self.update_attributes({ :lat => geo.lat, :lng => geo.lng }) + # return true + # end + # end + # else + # if self.lat || self.lng + # self.update_attributes({ :lat => nil, :lng => nil }) + # return true + # end + # end + # false + # end def current_city(ip_addy=nil) - unless self.city - if self.lat && self.lng - # todo this is really dumb, you can't compare lat lng for equality - return MaxMindGeo.where(['lat = ? AND lng = ?',self.lat,self.lng]).limit(1).first.try(:city) - elsif ip_addy - return MaxMindGeo.ip_lookup(ip_addy).try(:city) - end - else - return self.city - end + # unless self.city + # if self.lat && self.lng + # # todo this is really dumb, you can't compare lat lng for equality + # return MaxMindGeo.where(['lat = ? AND lng = ?',self.lat,self.lng]).limit(1).first.try(:city) + # elsif ip_addy + # return MaxMindGeo.ip_lookup(ip_addy).try(:city) + # end + # else + # return self.city + # end + self.city end def update_addr_loc(connection, reason) @@ -1176,11 +1177,12 @@ module JamRuby def self.deliver_new_musician_notifications(since_date=nil) since_date ||= Time.now-1.week - self.geocoded_users.find_each do |usr| - Search.new_musicians(usr, since_date) do |new_nearby| - UserMailer.new_musicians(usr, new_nearby).deliver - end - end + # todo scott return musicians with locidispid not null + # self.geocoded_users.find_each do |usr| + # Search.new_musicians(usr, since_date) do |new_nearby| + # UserMailer.new_musicians(usr, new_nearby).deliver + # end + # end end def facebook_invite! diff --git a/ruby/spec/jam_ruby/models/get_work_spec.rb b/ruby/spec/jam_ruby/models/get_work_spec.rb index 9f8349b33..4e12d2ab0 100644 --- a/ruby/spec/jam_ruby/models/get_work_spec.rb +++ b/ruby/spec/jam_ruby/models/get_work_spec.rb @@ -7,13 +7,13 @@ describe GetWork do end it "get_work_1" do - x = GetWork.get_work(1) + x = GetWork.get_work(1, 0) #puts x.inspect x.should be_nil end it "get_work_list_1" do - x = GetWork.get_work_list(1) + x = GetWork.get_work_list(1, 0) #puts x.inspect x.should eql([]) end diff --git a/ruby/spec/jam_ruby/models/musician_search_spec.rb b/ruby/spec/jam_ruby/models/musician_search_spec.rb index ab322f0d8..2a3ca0ced 100644 --- a/ruby/spec/jam_ruby/models/musician_search_spec.rb +++ b/ruby/spec/jam_ruby/models/musician_search_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe 'Musician search' do before(:each) do - @geocode1 = FactoryGirl.create(:geocoder) - @geocode2 = FactoryGirl.create(:geocoder) + # @geocode1 = FactoryGirl.create(:geocoder) + # @geocode2 = FactoryGirl.create(:geocoder) @users = [] @users << @user1 = FactoryGirl.create(:user) @users << @user2 = FactoryGirl.create(:user) @@ -276,6 +276,7 @@ describe 'Musician search' do context 'new users' do it "find nearby" do + pending 'todo scott fix this test so it does something' # create new user outside 500 from Apex to ensure its excluded from results FactoryGirl.create(:user, {city: "Austin", state: "TX", country: "US"}) User.geocoded_users.find_each do |usr| @@ -288,6 +289,7 @@ describe 'Musician search' do end it "sends new musician email" do + pending 'todo scott fix this test so it does something' # create new user outside 500 from Apex to ensure its excluded from results FactoryGirl.create(:user, {city: "Austin", state: "TX", country: "US"}) User.geocoded_users.find_each do |usr| diff --git a/ruby/spec/jam_ruby/models/score_spec.rb b/ruby/spec/jam_ruby/models/score_spec.rb index 84efb6127..604622b9e 100644 --- a/ruby/spec/jam_ruby/models/score_spec.rb +++ b/ruby/spec/jam_ruby/models/score_spec.rb @@ -92,4 +92,31 @@ describe Score do Score.findx(3456, 3456).should == -1 end + it "test shortcut for making scores from connections" do + user1 = FactoryGirl.create(:user) + conn1 = FactoryGirl.create(:connection, user: user1, addr: 0x01020304, locidispid: 5) + user2 = FactoryGirl.create(:user) + conn2 = FactoryGirl.create(:connection, user: user2, addr: 0x11121314, locidispid: 6) + user3 = FactoryGirl.create(:user) + conn3 = FactoryGirl.create(:connection, user: user3, addr: 0x21222324, locidispid: 7) + + Score.findx(5, 6).should == -1 + Score.findx(6, 5).should == -1 + Score.findx(5, 7).should == -1 + Score.findx(7, 5).should == -1 + Score.findx(6, 7).should == -1 + Score.findx(7, 6).should == -1 + + Score.score_conns(conn1, conn2, 12) + Score.score_conns(conn1, conn3, 13) + Score.score_conns(conn2, conn3, 23) + + Score.findx(5, 6).should == 12 + Score.findx(6, 5).should == 12 + Score.findx(5, 7).should == 13 + Score.findx(7, 5).should == 13 + Score.findx(6, 7).should == 23 + Score.findx(7, 6).should == 23 + end + end diff --git a/web/app/assets/javascripts/JamServer.js b/web/app/assets/javascripts/JamServer.js index 8f3a6c2ef..44321fd23 100644 --- a/web/app/assets/javascripts/JamServer.js +++ b/web/app/assets/javascripts/JamServer.js @@ -9,10 +9,12 @@ var logger = context.JK.logger; var msg_factory = context.JK.MessageFactory; + var rest = context.JK.Rest(); + // Let socket.io know where WebSocketMain.swf is context.WEB_SOCKET_SWF_LOCATION = "assets/flash/WebSocketMain.swf"; - context.JK.JamServer = function (app) { + context.JK.JamServer = function (app, activeElementEvent) { // uniquely identify the websocket connection var channelId = null; @@ -50,6 +52,8 @@ var $templateDisconnected = null; var $currentDisplay = null; + var $self = $(this); + var server = {}; server.socket = {}; server.signedIn = false; @@ -59,7 +63,6 @@ server.socketClosedListeners = []; server.connected = false; - function heartbeatStateReset() { lastHeartbeatSentTime = null; lastHeartbeatAckTime = null; @@ -72,10 +75,6 @@ freezeInteraction = activeElementVotes && ((activeElementVotes.dialog && activeElementVotes.dialog.freezeInteraction === true) || (activeElementVotes.screen && activeElementVotes.screen.freezeInteraction === true)); - if (!initialConnect) { - context.JK.CurrentSessionModel.onWebsocketDisconnected(in_error); - } - if (in_error) { reconnectAttempt = 0; $currentDisplay = renderDisconnected(); @@ -108,11 +107,11 @@ server.reconnecting = true; - var result = app.activeElementEvent('beforeDisconnect'); + var result = activeElementEvent('beforeDisconnect'); initiateReconnect(result, in_error); - app.activeElementEvent('afterDisconnect'); + activeElementEvent('afterDisconnect'); // notify anyone listening that the socket closed var len = server.socketClosedListeners.length; @@ -193,14 +192,12 @@ heartbeatAckCheckInterval = context.setInterval(_heartbeatAckCheck, 1000); lastHeartbeatAckTime = new Date(new Date().getTime() + heartbeatMS); // add a little forgiveness to server for initial heartbeat connectDeferred.resolve(); - app.activeElementEvent('afterConnect', payload); + activeElementEvent('afterConnect', payload); } function heartbeatAck(header, payload) { lastHeartbeatAckTime = new Date(); - - context.JK.CurrentSessionModel.trackChanges(header, payload); } function registerLoginAck() { @@ -272,11 +269,7 @@ // TODO: tell certain elements that we've reconnected } else { - // this path is the 'in session' path, where we actually reload the page - context.JK.CurrentSessionModel.leaveCurrentSession() - .always(function () { - window.location.reload(); - }); + window.location.reload(); } server.reconnecting = false; }); @@ -455,10 +448,10 @@ } connectDeferred = new $.Deferred(); channelId = context.JK.generateUUID(); // create a new channel ID for every websocket connection - logger.log("connecting websocket, channel_id: " + channelId); - var uri = context.JK.websocket_gateway_uri + '?channel_id=' + channelId; // Set in index.html.erb. - //var uri = context.gon.websocket_gateway_uri; // Leaving here for now, as we're looking for a better solution. + var uri = context.gon.websocket_gateway_uri + '?channel_id=' + channelId; // Set in index.html.erb. + + logger.debug("connecting websocket: " + uri); server.socket = new context.WebSocket(uri); server.socket.onopen = server.onOpen; diff --git a/web/app/assets/javascripts/application.js b/web/app/assets/javascripts/application.js index ec1dee5c6..f9d230ae6 100644 --- a/web/app/assets/javascripts/application.js +++ b/web/app/assets/javascripts/application.js @@ -34,6 +34,7 @@ //= require AAA_Log //= require globals //= require AAB_message_factory +//= require jam_rest //= require AAC_underscore //= require utils //= require custom_controls diff --git a/web/app/assets/javascripts/fakeJamClientRecordings.js b/web/app/assets/javascripts/fakeJamClientRecordings.js index b48ad335b..9fee4360f 100644 --- a/web/app/assets/javascripts/fakeJamClientRecordings.js +++ b/web/app/assets/javascripts/fakeJamClientRecordings.js @@ -34,8 +34,8 @@ function StartRecording(recordingId, clients) { startingSessionState = {}; - // we expect all clients to respond within 3 seconds to mimic the reliable UDP layer - startingSessionState.aggegratingStartResultsTimer = setTimeout(timeoutStartRecordingTimer, 3000); + // we expect all clients to respond within 1 seconds to mimic the reliable UDP layer + startingSessionState.aggegratingStartResultsTimer = setTimeout(timeoutStartRecordingTimer, 1000); startingSessionState.recordingId = recordingId; startingSessionState.groupedClientTracks = copyClientIds(clients, app.clientId); // we will manipulate this new one @@ -70,8 +70,8 @@ stoppingSessionState = {}; - // we expect all clients to respond within 3 seconds to mimic the reliable UDP layer - stoppingSessionState.aggegratingStopResultsTimer = setTimeout(timeoutStopRecordingTimer, 3000); + // we expect all clients to respond within 1 seconds to mimic the reliable UDP layer + stoppingSessionState.aggegratingStopResultsTimer = setTimeout(timeoutStopRecordingTimer, 1000); stoppingSessionState.recordingId = recordingId; stoppingSessionState.groupedClientTracks = copyClientIds(clients, app.clientId); @@ -137,14 +137,16 @@ } function onStopRecording(from, payload) { - logger.debug("received stop recording request from " + from); + logger.debug("received stop recording request from " + from); - // TODO check recordingId, and if currently recording - // we should return success if we are currently recording, or if we were already asked to stop for this recordingId - // this means we should keep a list of the last N recordings that we've seen, rather than just keeping the current - context.JK.JamServer.sendP2PMessage(from, JSON.stringify(p2pMessageFactory.stopRecordingAck(payload.recordingId, true))); + // TODO check recordingId, and if currently recording + // we should return success if we are currently recording, or if we were already asked to stop for this recordingId + // this means we should keep a list of the last N recordings that we've seen, rather than just keeping the current + context.JK.JamServer.sendP2PMessage(from, JSON.stringify(p2pMessageFactory.stopRecordingAck(payload.recordingId, true))); + if(stopRecordingResultCallbackName) { eval(stopRecordingResultCallbackName).call(this, payload.recordingId, {success:payload.success, reason:payload.reason, detail:from}); + } } function onStopRecordingAck(from, payload) { diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index 8f9da6756..2fc9e00b1 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -385,6 +385,7 @@ }) .on('stoppedRecording', function(e, data) { if(data.reason) { + logger.warn("Recording Discarded: ", data); var reason = data.reason; var detail = data.detail; diff --git a/web/app/assets/javascripts/sessionList.js b/web/app/assets/javascripts/sessionList.js index 368b56ffe..6563f8544 100644 --- a/web/app/assets/javascripts/sessionList.js +++ b/web/app/assets/javascripts/sessionList.js @@ -90,8 +90,7 @@ // loop through the tracks to get the instruments for (j=0; j < participant.tracks.length; j++) { var track = participant.tracks[j]; - logger.debug("Find:Finding instruments. Participant tracks:"); - logger.debug(participant.tracks); + logger.debug("Find:Finding instruments. Participant tracks:", participant.tracks); var inst = '../assets/content/icon_instrument_default24.png'; if (track.instrument_id in instrument_logo_map) { inst = instrument_logo_map[track.instrument_id]; diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index 791503e06..06cf02d0f 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -23,7 +23,9 @@ var participantsEverSeen = {}; var $self = $(this); - function id() { + server.registerOnSocketClosed(onWebsocketDisconnected); + + function id() { return currentSession ? currentSession.id : null; } @@ -91,6 +93,8 @@ server.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, trackChanges); server.registerMessageCallback(context.JK.MessageType.SESSION_DEPART, trackChanges); server.registerMessageCallback(context.JK.MessageType.TRACKS_CHANGED, trackChanges); + server.registerMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, trackChanges); + $(document).trigger('jamkazam.session_started', {session: {id: sessionId}}); }) .fail(function() { @@ -107,12 +111,14 @@ server.unregisterMessageCallback(context.JK.MessageType.SESSION_JOIN, trackChanges); server.unregisterMessageCallback(context.JK.MessageType.SESSION_DEPART, trackChanges); server.unregisterMessageCallback(context.JK.MessageType.TRACKS_CHANGED, trackChanges); + server.unregisterMessageCallback(context.JK.MessageType.HEARTBEAT_ACK, trackChanges); //server.unregisterMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_DEPART, refreshCurrentSession); // leave the session right away without waiting on REST. Why? If you can't contact the server, or if it takes a long // time, for that entire duration you'll still be sending voice data to the other users. // this may be bad if someone decides to badmouth others in the left-session during this time - logger.debug("calling jamClient.LeaveSession for clientId=" + clientId); + console.trace(); + logger.debug("performLeaveSession: calling jamClient.LeaveSession for clientId=" + clientId); client.LeaveSession({ sessionID: currentSessionId }); leaveSessionRest(currentSessionId) .done(function() { @@ -377,10 +383,11 @@ } function onWebsocketDisconnected(in_error) { - - // kill the streaming of the session immediately - logger.debug("calling jamClient.LeaveSession for clientId=" + clientId); + // kill the streaming of the session immediately + if(currentSessionId) { + logger.debug("onWebsocketDisconnect: calling jamClient.LeaveSession for clientId=" + clientId); client.LeaveSession({ sessionID: currentSessionId }); + } } // returns a deferred object @@ -423,7 +430,6 @@ this.getCurrentOrLastSession = function() { return currentOrLastSession; }; - this.trackChanges = trackChanges; this.getParticipant = function(clientId) { return participantsEverSeen[clientId] }; diff --git a/web/app/assets/javascripts/utils.js b/web/app/assets/javascripts/utils.js index 9ba52282f..a56a382f0 100644 --- a/web/app/assets/javascripts/utils.js +++ b/web/app/assets/javascripts/utils.js @@ -607,6 +607,49 @@ doneYet(); }; + context.JK.initJamClient = function() { + // If no jamClient (when not running in native client) + // create a fake one. + if (!(window.jamClient)) { + var p2pMessageFactory = new JK.FakeJamClientMessages(); + window.jamClient = new JK.FakeJamClient(JK.app, p2pMessageFactory); + window.jamClient.SetFakeRecordingImpl(new JK.FakeJamClientRecordings(JK.app, jamClient, p2pMessageFactory)); + } + else if(false) { // set to true to time long running bridge calls + var originalJamClient = window.jamClient; + var interceptedJamClient = {}; + $.each(Object.keys(originalJamClient), function(i, key) { + if(key.indexOf('(') > -1) { + // this is a method. time it + var jsKey = key.substring(0, key.indexOf('(')) + console.log("replacing " + jsKey) + interceptedJamClient[jsKey] = function() { + var original = originalJamClient[key] + var start = new Date(); + if(key == "FTUEGetDevices()") { + var returnVal = eval('originalJamClient.FTUEGetDevices(' + arguments[0] + ')'); + } + else { + var returnVal = original.apply(originalJamClient, arguments); + } + var time = new Date().getTime() - start.getTime(); + if(time >= 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold + console.error(time + "ms jamClient." + jsKey + ' returns=', returnVal); + } + + return returnVal; + } + } + else { + // we need to intercept properties... but how? + } + }); + + + window.jamClient = interceptedJamClient; + } + + } context.JK.clientType = function () { if (context.jamClient) { return context.jamClient.IsNativeClient() ? 'client' : 'browser'; diff --git a/web/app/assets/javascripts/web/web.js b/web/app/assets/javascripts/web/web.js index ffcbebaa6..347cb1382 100644 --- a/web/app/assets/javascripts/web/web.js +++ b/web/app/assets/javascripts/web/web.js @@ -52,3 +52,8 @@ //= require web/sessions //= require web/recordings //= require web/welcome +//= require banner +//= require fakeJamClient +//= require fakeJamClientMessages +//= require fakeJamClientRecordings +//= require JamServer diff --git a/web/app/assets/stylesheets/web/web.css b/web/app/assets/stylesheets/web/web.css index d060ec21b..f4533d6ff 100644 --- a/web/app/assets/stylesheets/web/web.css +++ b/web/app/assets/stylesheets/web/web.css @@ -1,4 +1,6 @@ /** +*= require client/banner +*= require client/jamServer *= require client/ie *= require client/jamkazam *= require easydropdown diff --git a/web/app/controllers/api_scoring_controller.rb b/web/app/controllers/api_scoring_controller.rb index 5ba61122d..fa9f042b1 100644 --- a/web/app/controllers/api_scoring_controller.rb +++ b/web/app/controllers/api_scoring_controller.rb @@ -7,13 +7,12 @@ class ApiScoringController < ApiController clientid = params[:clientid] if clientid.nil? then render :json => {message: 'clientid not specified'}, :status => 400; return end - conn = Connection.where(client_id: clientid).first + conn = Connection.where(client_id: clientid, user_id: current_user.id).first if conn.nil? then render :json => {message: 'session not found'}, :status => 404; return end - if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end + # if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end - # todo this method is a stub #puts "ApiScoringController#work(#{clientid}) => locidispid #{c.locidispid}" - result_client_id = JamRuby::GetWork.get_work(conn.locidispid) + result_client_id = JamRuby::GetWork.get_work(conn.locidispid, conn.addr) #result_client_id = clientid+'peer' render :json => {:clientid => result_client_id}, :status => 200 @@ -23,12 +22,11 @@ class ApiScoringController < ApiController clientid = params[:clientid] if clientid.nil? then render :json => {message: 'clientid not specified'}, :status => 400; return end - conn = Connection.where(client_id: clientid).first + conn = Connection.where(client_id: clientid, user_id: current_user.id).first if conn.nil? then render :json => {message: 'session not found'}, :status => 404; return end - if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end + # if !current_user.id.eql?(conn.user.id) then render :json => {message: 'session not owned by user'}, :status => 403; return end - # todo this method is a stub - result_client_ids = JamRuby::GetWork.get_work_list(conn.locidispid) + result_client_ids = JamRuby::GetWork.get_work_list(conn.locidispid, conn.addr) #result_client_ids = [clientid+'peer1', clientid+'peer2'] render :json => {:clientids => result_client_ids}, :status => 200 @@ -61,10 +59,10 @@ class ApiScoringController < ApiController if !score.is_a? Numeric then render :json => {message: 'score not valid numeric'}, :status => 400; return end - aconn = Connection.where(client_id: aclientid).first + aconn = Connection.where(client_id: aclientid, user_id: current_user.id).first if aconn.nil? then render :json => {message: 'a\'s session not found'}, :status => 404; return end if aAddr != aconn.addr then render :json => {message: 'a\'s session addr does not match aAddr'}, :status => 403; return end - if !current_user.id.eql?(aconn.user.id) then render :json => {message: 'a\'s session not owned by user'}, :status => 403; return end + # if !current_user.id.eql?(aconn.user.id) then render :json => {message: 'a\'s session not found'}, :status => 403; return end bconn = Connection.where(client_id: bclientid).first if bconn.nil? then render :json => {message: 'b\'s session not found'}, :status => 404; return end diff --git a/web/app/controllers/api_search_controller.rb b/web/app/controllers/api_search_controller.rb index 81baf7b6c..0ed3f9fd0 100644 --- a/web/app/controllers/api_search_controller.rb +++ b/web/app/controllers/api_search_controller.rb @@ -9,13 +9,14 @@ class ApiSearchController < ApiController if 1 == params[Search::PARAM_MUSICIAN].to_i || 1 == params[Search::PARAM_BAND].to_i query = params.clone query[:remote_ip] = request.remote_ip - if 1 == params[Search::PARAM_MUSICIAN].to_i - @search = Search.musician_filter(query, current_user) + if 1 == query[Search::PARAM_MUSICIAN].to_i + clientid = params[:clientid] + conn = (clientid ? Connection.where(client_id: clientid, user_id: current_user.id).first : nil) + @search = Search.musician_filter(query, current_user, conn) else @search = Search.band_filter(query, current_user) end respond_with @search, responder: ApiResponder, :status => 200 - elsif 1 == params[Search::PARAM_SESSION_INVITE].to_i @search = Search.session_invite_search(params[:query], current_user) else diff --git a/web/app/controllers/application_controller.rb b/web/app/controllers/application_controller.rb index 3954175af..29e294ac5 100644 --- a/web/app/controllers/application_controller.rb +++ b/web/app/controllers/application_controller.rb @@ -3,10 +3,15 @@ class ApplicationController < ActionController::Base protect_from_forgery include ApplicationHelper include SessionsHelper + include ClientHelper # inject username/email into bugsnag data before_bugsnag_notify :add_user_info_to_bugsnag + before_filter do + gon_setup + end + before_filter do if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? if cookies[AffiliatePartner::PARAM_COOKIE].blank? diff --git a/web/app/controllers/clients_controller.rb b/web/app/controllers/clients_controller.rb index 0f89b42de..637688b11 100644 --- a/web/app/controllers/clients_controller.rb +++ b/web/app/controllers/clients_controller.rb @@ -12,22 +12,6 @@ class ClientsController < ApplicationController return end - # use gon to pass variables into javascript - gon.websocket_gateway_uri = Rails.application.config.websocket_gateway_uri - gon.check_for_client_updates = Rails.application.config.check_for_client_updates - gon.fp_apikey = Rails.application.config.filepicker_rails.api_key - gon.fp_upload_dir = Rails.application.config.filepicker_upload_dir - gon.allow_force_native_client = Rails.application.config.allow_force_native_client - - # is this the native client or browser? - @nativeClient = is_native_client? - - # let javascript have access to the server's opinion if this is a native client - gon.isNativeClient = @nativeClient - - gon.use_cached_session_scores = Rails.application.config.use_cached_session_scores - gon.allow_both_find_algos = Rails.application.config.allow_both_find_algos - render :layout => 'client' end diff --git a/web/app/controllers/spikes_controller.rb b/web/app/controllers/spikes_controller.rb index 75cde8a49..ff31a9511 100644 --- a/web/app/controllers/spikes_controller.rb +++ b/web/app/controllers/spikes_controller.rb @@ -5,6 +5,8 @@ class SpikesController < ApplicationController + include ClientHelper + def facebook_invite end @@ -24,4 +26,8 @@ class SpikesController < ApplicationController def launch_app render :layout => 'web' end + + def websocket + render :layout => false + end end diff --git a/web/app/helpers/client_helper.rb b/web/app/helpers/client_helper.rb index 319b1456b..045b50636 100644 --- a/web/app/helpers/client_helper.rb +++ b/web/app/helpers/client_helper.rb @@ -15,4 +15,32 @@ module ClientHelper is_native_client end + + def gon_setup + + gon.root_url = root_url + # use gon to pass variables into javascript + if Rails.env == "development" + # if in development mode, we assume you are running websocket-gateway + # on the same host as you hit your server. + gon.websocket_gateway_uri = "ws://" + request.host + ":6767/websocket"; + else + # but in any other mode, just use config + gon.websocket_gateway_uri = Rails.application.config.websocket_gateway_uri + end + + gon.check_for_client_updates = Rails.application.config.check_for_client_updates + gon.fp_apikey = Rails.application.config.filepicker_rails.api_key + gon.fp_upload_dir = Rails.application.config.filepicker_upload_dir + gon.allow_force_native_client = Rails.application.config.allow_force_native_client + + # is this the native client or browser? + @nativeClient = is_native_client? + + # let javascript have access to the server's opinion if this is a native client + gon.isNativeClient = @nativeClient + + gon.use_cached_session_scores = Rails.application.config.use_cached_session_scores + gon.allow_both_find_algos = Rails.application.config.allow_both_find_algos + end end \ No newline at end of file diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 28836cda8..9b1b8cbfc 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -73,18 +73,7 @@ JK = JK || {}; - JK.root_url = "<%= root_url %>" - - <% if Rails.env == "development" %> - // if in development mode, we assume you are running websocket-gateway - // on the same host as you hit your server. - JK.websocket_gateway_uri = "ws://" + location.hostname + ":6767/websocket"; - <% else %> - // but in any other mode, just trust the config coming through gon - JK.websocket_gateway_uri = gon.websocket_gateway_uri - <% end %> - if (console) { console.log("websocket_gateway_uri:" + JK.websocket_gateway_uri); } - + JK.root_url = gon.root_url // If no trackVolumeObject (when not running in native client) // create a fake one. @@ -263,49 +252,10 @@ } JK.app = JK.JamKazam(); - var jamServer = new JK.JamServer(JK.app); + var jamServer = new JK.JamServer(JK.app, function(event_type) {JK.app.activeElementEvent(event_type)}); jamServer.initialize(); - // If no jamClient (when not running in native client) - // create a fake one. - if (!(window.jamClient)) { - var p2pMessageFactory = new JK.FakeJamClientMessages(); - window.jamClient = new JK.FakeJamClient(JK.app, p2pMessageFactory); - window.jamClient.SetFakeRecordingImpl(new JK.FakeJamClientRecordings(JK.app, jamClient, p2pMessageFactory)); - } - else if(false) { // set to true to time long running bridge calls - var originalJamClient = window.jamClient; - var interceptedJamClient = {}; - $.each(Object.keys(originalJamClient), function(i, key) { - if(key.indexOf('(') > -1) { - // this is a method. time it - var jsKey = key.substring(0, key.indexOf('(')) - console.log("replacing " + jsKey) - interceptedJamClient[jsKey] = function() { - var original = originalJamClient[key] - var start = new Date(); - if(key == "FTUEGetDevices()") { - var returnVal = eval('originalJamClient.FTUEGetDevices(' + arguments[0] + ')'); - } - else { - var returnVal = original.apply(originalJamClient, arguments); - } - var time = new Date().getTime() - start.getTime(); - if(time >= 0) { // if 0, you'll see ALL bridge calls. If you set it to a higher value, you'll only see calls that are beyond that threshold - console.error(time + "ms jamClient." + jsKey + ' returns=', returnVal); - } - - return returnVal; - } - } - else { - // we need to intercept properties... but how? - } - }); - - - window.jamClient = interceptedJamClient; - } + JK.initJamClient(); // Let's get things rolling... if (JK.currentUserId) { diff --git a/web/app/views/layouts/web.html.erb b/web/app/views/layouts/web.html.erb index 2515ae9da..60b500f40 100644 --- a/web/app/views/layouts/web.html.erb +++ b/web/app/views/layouts/web.html.erb @@ -70,6 +70,9 @@ <%= render "clients/footer" %> + <%= render "clients/banner" %> + <%= render "clients/banners/disconnected" %> + <%= render "clients/jamServer" %> <%= render "clients/invitationDialog" %> <%= render "users/signupDialog" %> <%= render "users/signinDialog" %> @@ -103,6 +106,12 @@ <% end %> JK.app = JK.JamKazam(); + var jamServer = new JK.JamServer(JK.app, $.noop); + jamServer.initialize(); + + // JamServer.connect needs the jamClient to be initialized + JK.initJamClient(); + JK.app.initialize({inClient: false, layoutOpts: {layoutFooter: false, sizeOverlayToContent: true}}); var facebookHelper = new JK.FacebookHelper(JK.app); @@ -125,6 +134,15 @@ videoDialog.initialize(); JK.bindHoverEvents(); + + + JK.JamServer.connect() // singleton here defined in JamServer.js + .done(function() { + console.log("websocket connected") + }) + .fail(function() { + console.log("websocket failed to connect") + }); }) diff --git a/web/app/views/spikes/websocket.html.erb b/web/app/views/spikes/websocket.html.erb new file mode 100644 index 000000000..e75e00919 --- /dev/null +++ b/web/app/views/spikes/websocket.html.erb @@ -0,0 +1,57 @@ + +<%= javascript_include_tag "jamServer" %> + +<%= include_gon %> + +<%= render "clients/banner" %> +<%= render "clients/banners/disconnected" %> +<%= render "clients/jamServer" %> + + +<%= stylesheet_link_tag "client/banner", media: "all" %> +<%= stylesheet_link_tag "client/jamServer", media: "all" %> + + \ No newline at end of file diff --git a/web/config/routes.rb b/web/config/routes.rb index a597d0bec..39482be79 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -79,7 +79,7 @@ SampleApp::Application.routes.draw do # route to spike controller (proof-of-concepts) match '/facebook_invite', to: 'spikes#facebook_invite' match '/launch_app', to: 'spikes#launch_app' - + match '/websocket', to: 'spikes#websocket' # junk pages match '/help', to: 'static_pages#help' diff --git a/web/spec/controllers/api_scoring_controller_spec.rb b/web/spec/controllers/api_scoring_controller_spec.rb index 7a3b71911..eae99ebd9 100644 --- a/web/spec/controllers/api_scoring_controller_spec.rb +++ b/web/spec/controllers/api_scoring_controller_spec.rb @@ -9,15 +9,15 @@ describe ApiScoringController do MARY_IP_ADDRESS = '75.92.54.210' # 1264334546, 4B.5C.36.D2 MARY_ADDR = 1264334546 - MARY_LOCIDISPID = 17192008423 + MARY_LOCIDISPID = 1807000004 MIKE_IP_ADDRESS = '173.172.108.1' # 2913758209, AD.AC.6C.01 MIKE_ADDR = 2913758209 - MIKE_LOCIDISPID = 17192043640 + MIKE_LOCIDISPID = 1539000002 JOHN_IP_ADDRESS = '255.255.1.2' # 4294902018, FF.FF.01.02 JOHN_ADDR = 4294902018 - JOHN_LOCIDISPID = 0 + JOHN_LOCIDISPID = 98765432 before do @mary = FactoryGirl.create(:user, first_name: 'mary') @@ -83,8 +83,9 @@ describe ApiScoringController do response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:clientid].should_not be_nil - [@mary_client_id, @mike_client_id].should include(json[:clientid]) + clientid = json[:clientid] + clientid.should_not be_nil + [@mike_client_id].should include(clientid) end it 'try work with mike login and mike' do @@ -93,8 +94,9 @@ describe ApiScoringController do response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:clientid].should_not be_nil - [@mary_client_id, @mike_client_id].should include(json[:clientid]) + clientid = json[:clientid] + clientid.should_not be_nil + [@mary_client_id].should include(clientid) end it 'try work with mary login and mike' do @@ -103,7 +105,7 @@ describe ApiScoringController do response.should_not be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:message].should eql('session not owned by user') + json[:message].should eql('session not found') end it 'try work with mike login and mary' do @@ -112,7 +114,7 @@ describe ApiScoringController do response.should_not be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:message].should eql('session not owned by user') + json[:message].should eql('session not found') end end @@ -152,13 +154,11 @@ describe ApiScoringController do response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:clientids].should_not be_nil - json[:clientids].should_receive :length - json[:clientids].length == 2 - [@mary_client_id, @mike_client_id].should include(json[:clientids][0]) - [@mary_client_id, @mike_client_id].should include(json[:clientids][1]) - json[:clientids][0].should_not eql(json[:clientids][1]) - + clientids = json[:clientids] + clientids.should_not be_nil + clientids.should respond_to :length + clientids.length.should == 1 + [@mike_client_id].should include(clientids[0]) end it 'try worklist with mike login and mike' do @@ -167,12 +167,11 @@ describe ApiScoringController do response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:clientids].should_not be_nil - json[:clientids].should_receive :length - json[:clientids].length == 2 - [@mary_client_id, @mike_client_id].should include(json[:clientids][0]) - [@mary_client_id, @mike_client_id].should include(json[:clientids][1]) - json[:clientids][0].should_not eql(json[:clientids][1]) + clientids = json[:clientids] + clientids.should_not be_nil + clientids.should respond_to :length + clientids.length.should == 1 + [@mary_client_id].should include(clientids[0]) end it 'try worklist with mary login and mike' do @@ -181,7 +180,7 @@ describe ApiScoringController do response.should_not be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:message].should eql('session not owned by user') + json[:message].should eql('session not found') end end @@ -302,7 +301,7 @@ describe ApiScoringController do response.should_not be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 1 - json[:message].should eql('a\'s session not owned by user') + json[:message].should eql('a\'s session not found') end it 'record with mary login, mary, mary_addr, mary, mary_addr, score' do @@ -359,12 +358,15 @@ describe ApiScoringController do json[:message].should eql('b\'s location or isp not found') end - it 'record with mary login, mary, mary_addr, mike, mike_addr, score' do + it 'record with mary login, mary, mary_addr, mike, mike_addr, score (integer)' do controller.current_user = @mary post :record, {:format => 'json', :aclientid => @mary_client_id, :aAddr => MARY_IP_ADDRESS, :bclientid => @mike_client_id, :bAddr => MIKE_IP_ADDRESS, :score => 20} response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 0 + score = Score.findx(MARY_LOCIDISPID, MIKE_LOCIDISPID) + score.should_not be_nil + score.should eq(20) end it 'record with mary login, mary, mary_addr, mike, mike_addr, score (floating pt)' do @@ -373,6 +375,9 @@ describe ApiScoringController do response.should be_success json = JSON.parse(response.body, :symbolize_names => true) json.length.should == 0 + score = Score.findx(MARY_LOCIDISPID, MIKE_LOCIDISPID) + score.should_not be_nil + score.should eq(22) end end diff --git a/web/spec/features/landing_spec.rb b/web/spec/features/landing_spec.rb index 0d42a2680..ff192b975 100644 --- a/web/spec/features/landing_spec.rb +++ b/web/spec/features/landing_spec.rb @@ -23,8 +23,10 @@ describe "Landing", :js => true, :type => :feature, :capybara_feature => true do end it "footer links work" do - first('#footer-links a').trigger(:click) - should have_selector('h1', text: 'About Us') + first('#footer-links a', text: 'about').trigger(:click) + page.within_window page.driver.window_handles.last do + should have_selector('h1', text: 'About Us') + end end end diff --git a/web/spec/features/production_spec.rb b/web/spec/features/production_spec.rb deleted file mode 100644 index 152bb94bc..000000000 --- a/web/spec/features/production_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'spec_helper' - -# these tests MUST be idempotent and DO use actual production user accounts on www -www = 'http://www.jamkazam.com' - -describe "Production site at #{www}", :test_www => true, :js => true, :type => :feature, :capybara_feature => true do - - subject { page } - - before(:all) do - Capybara.javascript_driver = :poltergeist - Capybara.current_driver = Capybara.javascript_driver - Capybara.app_host = www - Capybara.run_server = false - Capybara.default_wait_time = 10 - end - - TestUser = Class.new do - attr_accessor :email, :password, :first_name, :last_name, :id - - def initialize(h) - h.each {|k,v| send("#{k}=",v)} - end - - alias :to_s :first_name - - def name - first_name + ' ' + last_name - end - end - - user1 = TestUser.new({ email: 'anthony+jim@jamkazam.com', password: 'j4m!t3st3r', first_name: 'Jim', last_name: 'Smith', id: '68e8eea2-140d-44c1-b711-10d07ce70f96' }) - user2 = TestUser.new({ email: 'anthony+john@jamkazam.com', password: 'j4m!t3st3r', first_name: 'John', last_name: 'Jones', id: '5bbcf689-2f73-452d-815a-c4f44e9e7f3e' }) - -# before(:each) do -# emulate_client -# end - - it "is possible for #{user1} to sign in and not get disconnected within 30 seconds" do - in_client(user1) do - sign_in_poltergeist user1 - repeat_for(30.seconds) do - expect(page).to_not have_selector('.no-websocket-connection') #looks for reconnect dialog every 1 second - end - end - end - - it "is possible for #{user1} and #{user2} to see each other online, and to send messages" do - # this example heavily based on text_message_spec.rb - - in_client(user1) do - sign_in_poltergeist(user1) - end - - test_message = "#{SecureRandom.uuid} - Hey #{user1}!" - test_response = "#{SecureRandom.uuid} - Hey yourself, #{user2}!" - test_goodbye = "#{SecureRandom.uuid} - OK bye!" - - in_client(user2) do - sign_in_poltergeist(user2) - expect(page).to have_xpath( - "//div[@class='friend-name' and @user-id='#{user1.id}']/span[@class='friend-status']", - :text => "Available" ) - - site_search(user1.name, expand: true) - find("#search-results a[user-id=\"#{user1.id}\"][hoveraction=\"musician\"]", text: user1.name).hover_intent - find('#musician-hover #btnMessage').trigger(:click) - find('h1', text: 'conversation with ' + user1.name) - send_text_message(test_message) - end - - in_client(user1) do - expect(page).to have_xpath( - "//div[@class='friend-name' and @user-id='#{user2.id}']/span[@class='friend-status']", - :text => "Available" ) - find('#notification #ok-button').trigger(:click) - find('h1', text: 'conversation with ' + user2.name) - find('.previous-message-text', text: test_message) - send_text_message(test_response, close_on_send: true) - end - - in_client(user2) do - find('.previous-message-text', text: test_response) - send_text_message(test_goodbye, close_on_send: true) - end - - in_client(user1) { sign_out_poltergeist } - in_client(user2) { sign_out_poltergeist } - end - -end - diff --git a/web/spec/features/reconnect_spec.rb b/web/spec/features/reconnect_spec.rb index ce822ba51..0ff6752fe 100644 --- a/web/spec/features/reconnect_spec.rb +++ b/web/spec/features/reconnect_spec.rb @@ -117,7 +117,7 @@ describe "Reconnect", :js => true, :type => :feature, :capybara_feature => true # but.. after a few seconds, it should reconnect on it's own page.should_not have_selector('h2', text: 'Disconnected from Server') - find('h1', text:'session') + find('div[layout-id="session"] h1', text:'session') end end end diff --git a/web/spec/features/recordings_spec.rb b/web/spec/features/recordings_spec.rb index 5b005acfa..11518092a 100644 --- a/web/spec/features/recordings_spec.rb +++ b/web/spec/features/recordings_spec.rb @@ -50,7 +50,7 @@ describe "Session Recordings", :js => true, :type => :feature, :capybara_feature start_recording_with(creator, [joiner1]) in_client(creator) do - visit "/downloads" # kills websocket, looking like an abrupt leave + visit "/request_reset_password" # kills websocket, looking like an abrupt leave end in_client(joiner1) do @@ -83,7 +83,7 @@ describe "Session Recordings", :js => true, :type => :feature, :capybara_feature start_recording_with(creator, [joiner1, joiner2]) in_client(creator) do - visit "/downloads" # kills websocket, looking like an abrupt leave + visit "/request_reset_password" # kills websocket, looking like an abrupt leave end in_client(joiner1) do diff --git a/web/spec/requests/musician_search_api_spec.rb b/web/spec/requests/musician_search_api_spec.rb index a6c7a3381..a0dcb66fe 100644 --- a/web/spec/requests/musician_search_api_spec.rb +++ b/web/spec/requests/musician_search_api_spec.rb @@ -35,6 +35,7 @@ describe "Musician Search API", :type => :api do context 'location filtering' do it "gets no musicians for out of range locations" do + pending 'todo scott this needs to be rewritten using scores' get_query({:city => 'San Francisco', :distance => 100}) good_response expect((json['musicians'] || []).count).to be 0 diff --git a/web/spec/support/utilities.rb b/web/spec/support/utilities.rb index 62aa1c5d4..998b75962 100644 --- a/web/spec/support/utilities.rb +++ b/web/spec/support/utilities.rb @@ -479,4 +479,4 @@ def garbage length output = '' length.times { output << special_characters.sample } output.slice(0, length) -end \ No newline at end of file +end