require 'spec_helper' describe MusicSession do let(:creator) {FactoryGirl.create(:user, last_jam_locidispid: 1)} let(:some_user) { FactoryGirl.create(:user) } let(:music_session1) { FactoryGirl.create(:music_session) } let(:music_session2) { FactoryGirl.create(:music_session) } let(:music_session3) { FactoryGirl.create(:music_session) } let(:music_session4) { FactoryGirl.create(:music_session) } describe "validations" do it "genre must be set" do music_session = FactoryGirl.build(:music_session) music_session.genre = nil music_session.save.should be_false music_session.errors[:genre].should == ["can't be blank"] end it "updates the fields of a music session properly" do genre1 = FactoryGirl.create(:genre) genre2 = FactoryGirl.create(:genre) genre3 = FactoryGirl.create(:genre) genre4 = FactoryGirl.create(:genre) creator = FactoryGirl.create(:user) session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :genre => genre3) session.update_attributes({:description => "Session2", :genre => genre1}) session.reload session.description.should == "Session2" session.genre.should == genre1 end it "must have legal_terms accepted" do user1 = FactoryGirl.create(:user) music_session = FactoryGirl.build(:music_session, :creator => user1, legal_terms: false) music_session.save music_session.valid?.should be_false music_session.errors["legal_terms"].should == ["is not included in the list"] end it "cannot have profanity in the description" do user1 = FactoryGirl.create(:user) music_session = FactoryGirl.build(:music_session, :creator => user1, legal_terms: false, :description => "fuck you") music_session.save music_session.valid?.should be_false end end describe "create" do let(:open_params) { { name: "session 1", description: "my session", genres: ['ambient'], musician_access: true, fan_access: true, approval_required: true, fan_chat: true, legal_policy: 'Standard', language: 'eng', start: "Thu Jul 10 2014 10:00 PM", duration: 30, timezone: "Central Time (US & Canada),America/Chicago", open_rsvps: true, legal_terms: true, recurring_mode: 'once', isUnstructuredRsvp: true, rsvp_slots: [{ instrument_id: "other", proficiency_level: 1, approve: true}] } } it "wide open scheduled session" do session = MusicSession.create(creator, open_params) session.valid?.should be_true # verify that scheduled_start is now 5 hours ahead of what was specified (CST during summer is -5 offset) session.scheduled_start.utc.should == DateTime.new(2014,07,11,3,00,0) # verify that the update_scheduled_start does not disturb scheduled_start session.save! session.scheduled_start.utc.should == DateTime.new(2014,07,11,3,00,0) end it "works with UTC timezone" do open_params[:timezone] = 'UTC,Etc/UTC' session = MusicSession.create(creator, open_params) session.valid?.should be_true # verify that scheduled_start is now 5 hours ahead of what was specified (CST during summer is -5 offset) session.scheduled_start.should == DateTime.new(2014,07,10,22,00,0) end it "no scheduled_start" do open_params[:timezone] = nil open_params[:scheduled_start] = nil open_params[:scheduled_duration] = nil session = MusicSession.create(creator, open_params) session.valid?.should be_true session.scheduled_start.should be_nil end end describe "pretty_scheduled_start" do it "displays central time correctly" do time = MusicSession.parse_scheduled_start("Thu Jul 10 2014 10:00 PM", "Central Time (US & Canada),America/Chicago") music_session = FactoryGirl.create(:music_session, scheduled_start: time, timezone: "Central Time (US & Canada),America/Chicago") music_session.pretty_scheduled_start(true).should == 'Thursday, July 10, 10:00-11:00 PM Central Time (US & Canada)' music_session.pretty_scheduled_start(false).should == 'Thursday, July 10 - 10:00pm' end it "displays default correctly" do music_session = FactoryGirl.create(:music_session, scheduled_start: nil) music_session.pretty_scheduled_start(true).should == 'Date and time TBD' music_session.pretty_scheduled_start(false).should == 'Date and time TBD' end end describe "nindex" do it "nindex orders two sessions by created_at starting with most recent" do creator = FactoryGirl.create(:user) creator2 = FactoryGirl.create(:user) earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session") c1 = FactoryGirl.create(:connection, user: creator, music_session: earlier_session, addr: 0x01020304, locidispid: 1) later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session") c2 = FactoryGirl.create(:connection, user: creator2, music_session: later_session, addr: 0x21020304, locidispid: 2) user = FactoryGirl.create(:user) c3 = FactoryGirl.create(:connection, user: user, locidispid: 3) Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil); Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil); # scores! #ActiveRecord::Base.logger = Logger.new(STDOUT) music_sessions = ActiveMusicSession.nindex(user, client_id: c3.client_id).take(100) #music_sessions = MusicSession.index(user).take(100) #ActiveRecord::Base.logger = nil music_sessions.length.should == 2 music_sessions[0].id.should == later_session.id music_sessions[1].id.should == earlier_session.id end end it 'uninvited users cant join approval-required sessions without invitation' do user1 = FactoryGirl.create(:user) # in the jam session user2 = FactoryGirl.create(:user) # in the jam session music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true, :approval_required => true) connection1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session) expect { FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :joining_session => true) }.to raise_error(ActiveRecord::RecordInvalid) end it "is_recording? returns false if not recording" do user1 = FactoryGirl.create(:user) music_session = FactoryGirl.build(:active_music_session, :creator => user1) music_session.is_recording?.should be_false end describe "recordings" do before(:each) do @user1 = FactoryGirl.create(:user) @connection = FactoryGirl.create(:connection, :user => @user1) @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument) @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true) # @music_session.connections << @connection @music_session.save! @connection.join_the_session(@music_session, true, nil, @user1, 10) end describe "not recording" do it "stop_recording should return nil if not recording" do @music_session.stop_recording.should be_nil end end describe "currently recording" do before(:each) do @recording = FactoryGirl.create(:recording, :music_session => @music_session, :owner => @user1) end it "is_recording? returns true if recording" do @music_session.is_recording?.should be_true end it "stop_recording should return recording object if recording" do @music_session.stop_recording.should == @recording end end describe "claim a recording" do before(:each) do @recording = Recording.start(@music_session, @user1) @recording.errors.any?.should be_false @recording.stop @recording.reload @claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true) @claimed_recording.errors.any?.should be_false end it "allow a claimed recording to be associated" do @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false @music_session.reload @music_session.claimed_recording.should == @claimed_recording @music_session.claimed_recording_initiator.should == @user1 end it "allow a claimed recording to be removed" do @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false @music_session.claimed_recording_stop @music_session.errors.any?.should be_false @music_session.reload @music_session.claimed_recording.should be_nil @music_session.claimed_recording_initiator.should be_nil end it "disallow a claimed recording to be started when already started by someone else" do @user2 = FactoryGirl.create(:user) @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false @music_session.claimed_recording_start(@user2, @claimed_recording) @music_session.errors.any?.should be_true @music_session.errors[:claimed_recording] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS] end it "allow a claimed recording to be started when already started by self" do @user2 = FactoryGirl.create(:user) @claimed_recording2 = @recording.claim(@user1, "name", "description", Genre.first, true) @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false @music_session.claimed_recording_start(@user1, @claimed_recording2) @music_session.errors.any?.should be_true end end end describe "get_connection_ids" do before(:each) do @user1 = FactoryGirl.create(:user) @user2 = FactoryGirl.create(:user) @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true) @connection1 = FactoryGirl.create(:connection, :user => @user1, :music_session => @music_session, :as_musician => true) @connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session, :as_musician => false) end it "get all connections" do @music_session.get_connection_ids().should == [@connection1.client_id, @connection2.client_id] end it "exclude non-musicians" do @music_session.get_connection_ids(as_musician: true).should == [@connection1.client_id] end it "exclude musicians" do @music_session.get_connection_ids(as_musician: false).should == [@connection2.client_id] end it "exclude particular client" do @music_session.get_connection_ids(exclude_client_id: @connection1.client_id).should == [@connection2.client_id] end it "exclude particular client and exclude non-musicians" do @music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id] end end describe "approved_rsvps" do it "aggregrates instrument info" do creators_slot = music_session1.rsvp_slots[0] music_session1.approved_rsvps.length.should == 1 approved_user = music_session1.approved_rsvps[0] JSON.parse(approved_user[:instrument_ids])[0].should == creators_slot.instrument.id JSON.parse(approved_user[:instrument_descriptions])[0].should == creators_slot.instrument.description JSON.parse(approved_user[:instrument_proficiencies])[0].should == creators_slot.proficiency_level JSON.parse(approved_user[:rsvp_request_ids])[0].should == creators_slot.rsvp_requests[0].id end it "unstructured rsvps should still be returned" do music_session1.rsvp_slots.length.should == 1 creators_slot = music_session1.rsvp_slots[0] # now take out the instrument and proficiency of the rsvp_slot (make it unstructured) creators_slot.is_unstructured_rsvp = true creators_slot.instrument = nil creators_slot.proficiency_level = nil creators_slot.save! music_session = MusicSession.find(music_session1.id) approved_rsvps = music_session.approved_rsvps approved_rsvps.length.should == 1 approved_user = approved_rsvps[0] JSON.parse(approved_user[:instrument_ids])[0].should == nil JSON.parse(approved_user[:instrument_descriptions])[0].should == nil JSON.parse(approved_user[:instrument_proficiencies])[0].should == nil JSON.parse(approved_user[:rsvp_request_ids])[0].should == creators_slot.rsvp_requests[0].id end it "handles 2 instruments for a single request correctly" do rsvp_request = FactoryGirl.create(:rsvp_request_for_multiple_slots, user: some_user, music_session: music_session1, number: 2, chosen:true) approved_rsvps = music_session1.approved_rsvps approved_rsvps.length.should == 2 # find the user who made the request for 2 rsvp slots in the approved_users array approved_some_user = approved_rsvps.find {|s| s.id == some_user.id} instrument_ids = JSON.parse(approved_some_user[:instrument_ids]) instrument_ids.should =~ rsvp_request.rsvp_slots.map {|slot| slot.instrument_id } instrument_descriptions = JSON.parse(approved_some_user[:instrument_descriptions]) instrument_descriptions.should =~ rsvp_request.rsvp_slots.map {|slot| slot.instrument.description } instrument_proficiencies = JSON.parse(approved_some_user[:instrument_proficiencies]) instrument_proficiencies.should =~ rsvp_request.rsvp_slots.map {|slot| slot.proficiency_level } JSON.parse(approved_some_user[:rsvp_request_ids])[0].should == rsvp_request.id end end describe "parse_scheduled_start" do it "converts central time correctly" do # CST has -5 offset in summery time = DateTime.new(2004,10,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S') converted = MusicSession.parse_scheduled_start(time, 'Central Time (US & Canada),America/Chicago') converted.should == DateTime.new(2004,10,15,6,30,0, '+0') # CST has -6 offset in winter time = DateTime.new(2004,11,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S') converted = MusicSession.parse_scheduled_start(time, 'Central Time (US & Canada),America/Chicago') converted.should == DateTime.new(2004,11,15,7,30,0, '+0') end it "converts UTC correctly" do # should not shift time = DateTime.new(2004,10,15,1,30,0, '+0').strftime('%Y-%m-%d %H:%M:%S') converted = MusicSession.parse_scheduled_start(time, 'UTC,Etc/UTC') converted.should == DateTime.new(2004,10,15,1,30,0, '+0') # should not shift time = DateTime.new(2004,11,15,1,30,0).strftime('%Y-%m-%d %H:%M:%S') converted = MusicSession.parse_scheduled_start(time, 'UTC,Etc/UTC') converted.should == DateTime.new(2004,11,15,1,30,0, '+0') end end describe "scheduled" do it "excludes based on time-range" do session = FactoryGirl.create(:music_session, scheduled_start: Time.now) sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 session.scheduled_start = 11.hours.ago session.save! sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 session.scheduled_start = 13.hours.ago session.save! sessions = MusicSession.scheduled(session.creator) sessions.length.should == 0 session.scheduled_start = 13.hours.from_now session.save! sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 session.scheduled_start = 300.days.from_now session.save! sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 session.scheduled_start = nil session.save! sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 end it "excludes canceled" do session = FactoryGirl.create(:music_session, scheduled_start: Time.now) sessions = MusicSession.scheduled(session.creator) sessions.length.should == 1 session.canceled = true session.save! MusicSession.scheduled(session.creator).length.should == 0 end end def sms(user, params) ActiveRecord::Base.transaction do return MusicSession.sms_index(user, params) end end def session_with_scores(user, music_session_id) ActiveRecord::Base.transaction do return MusicSession.session_with_scores(user, music_session_id) end end describe "session_with_scores", no_transaction: true do let(:conn) { FactoryGirl.create(:connection, user: creator, locidispid: creator.last_jam_locidispid) } let(:searcher) { FactoryGirl.create(:user, last_jam_locidispid: 2) } let(:searcher_conn) { FactoryGirl.create(:connection, user: searcher, ip_address: '2.2.2.2', locidispid: searcher.last_jam_locidispid) } let(:default_opts) { {client_id: searcher_conn.client_id} } let(:network_score) { 20 } before(:each) do Score.createx(conn.locidispid, conn.client_id, conn.addr, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: creator.id, buserid: searcher.id}) end it "invalid session ID" do expect {session_with_scores(searcher, 'blah')}.to raise_error(ActiveRecord::RecordNotFound) end it "one session with scores" do session = FactoryGirl.create(:music_session, creator: creator) music_session, user_scores = session_with_scores(searcher, session.id) music_session.latency.should be_nil # we don't return music_session.latency with session_with_scores, because it's used for sorting among many sessions user_scores.length.should == 1 user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) end end describe "sms_index", no_transaction: true do describe "simple" do let(:conn) { FactoryGirl.create(:connection, user: creator, locidispid: creator.last_jam_locidispid) } let(:searcher) { FactoryGirl.create(:user, last_jam_locidispid: 2) } let(:searcher_conn) { FactoryGirl.create(:connection, user: searcher, ip_address: '2.2.2.2', locidispid: searcher.last_jam_locidispid) } let(:default_opts) { {client_id: searcher_conn.client_id} } let(:network_score) { 20 } before(:each) do Score.createx(conn.locidispid, conn.client_id, conn.addr, searcher_conn.locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: creator.id, buserid: searcher.id}) end it "no results" do music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 user_scores.length.should == 0 end it "one session shows/hides based on open_rsvps" do creator.last_jam_locidispid = conn.locidispid creator.save! music_session = FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 music_session.open_rsvps = false music_session.save! music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 end it "one session with no scheduled_start time" do creator.last_jam_locidispid = conn.locidispid creator.save! music_session = FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 end it "one session, one RSVP (creator)" do creator.last_jam_locidispid = conn.locidispid creator.save! music_session = FactoryGirl.create(:music_session, creator: creator) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 music_sessions[0].tag.should == 3 # open session sort music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) user_scores.length.should == 1 user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) end it "skip session with past due scheduled_start time" do interval = MusicSession::UNSTARTED_INTERVAL_DAYS_SKIP dd = Time.now - (interval.to_i + 1).days Timecop.travel(dd) msess1 = FactoryGirl.create(:music_session, creator: creator, scheduled_start: dd) Timecop.return msess2 = FactoryGirl.create(:music_session, creator: creator) music_sessions, user_scores = sms(searcher, default_opts) expect(music_sessions.length).to be(1) expect(music_sessions[0].id).to eq(msess2.id) end it "filters sessions in the past" do music_session = FactoryGirl.create(:music_session, creator: creator) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 # 15 minutes is the edge of forgiveness music_session.scheduled_start = 16.minutes.ago music_session.save! music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 # this should still fall in time music_session.scheduled_start = 14.minutes.ago music_session.save! music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 end it "one session, one RSVP (creator), one invitation" do # create an invitee, and friend them with the creator (you have to be friends to send an invite) invitee = FactoryGirl.create(:user, last_jam_audio_latency: 30, last_jam_locidispid: 3) FactoryGirl.create(:friendship, user: creator, friend: invitee) FactoryGirl.create(:friendship, user: invitee, friend: creator) music_session = FactoryGirl.create(:music_session, creator: creator) FactoryGirl.create(:invitation, receiver:invitee, sender:creator, music_session: music_session) # create a score between creator, searcher Score.createx(creator.last_jam_locidispid, conn.client_id, conn.addr, searcher.last_jam_locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: creator.id, buserid: searcher.id}) # create a score between invitee, and searcher Score.createx(invitee.last_jam_locidispid, 'immaterial', 1, searcher.last_jam_locidispid, searcher_conn.client_id, searcher_conn.addr, network_score, nil, nil, {auserid: invitee.id, buserid: searcher.id}) # create a score between invitee, and creator Score.createx(invitee.last_jam_locidispid, 'immaterial', 1, creator.last_jam_locidispid, conn.client_id, conn.addr, network_score, nil, nil) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 music_sessions[0].tag.should == 3 # open session sort music_sessions[0].latency.should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) user_scores.length.should == 1 # the creator (invitees are not included) user_scores[creator.id][:full_score].should == (network_score + searcher.last_jam_audio_latency + creator.last_jam_audio_latency ) #search with the invitee this time. invitee_conn = FactoryGirl.create(:connection, user: invitee, ip_address: '3.3.3.3', locidispid: invitee.last_jam_locidispid) music_sessions, user_scores = sms(invitee, {client_id: invitee_conn.client_id}) music_sessions.length.should == 1 music_sessions[0].tag.should == 2 # invited sort music_sessions[0].latency.should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency )).ceil user_scores.length.should == 1 # the creator, and the invitee user_scores[creator.id][:full_score].should == ((network_score + invitee.last_jam_audio_latency + creator.last_jam_audio_latency )).ceil end it "does not show when it goes active" do # we create a scheduled session--it should return music_session = FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 # but then make an active session for this scheduled session ams = FactoryGirl.create(:active_music_session, music_session: music_session, creator: creator, musician_access: true) music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 # finally, delete the active session, and see results go back to one ams.delete music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 end it "should allow a null locidispid to search" do searcher_conn.locidispid = nil searcher_conn.save! music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 end describe "keywords" do before(:each) do creator.last_jam_locidispid = conn.locidispid creator.save! FactoryGirl.create(:music_session, creator: creator, scheduled_start: nil, description: 'chunky icecream for the fools') end it "handles single keyword" do default_opts[:keyword] = 'chunky' music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 user_scores.length.should == 1 end it "handles two keyword" do default_opts[:keyword] = 'chunky for' music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 user_scores.length.should == 1 end it "handles single quote" do default_opts[:keyword] = "chun'ky fo'r" music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 0 user_scores.length.should == 1 default_opts[:keyword] = "chunky for'" music_sessions, user_scores = sms(searcher, default_opts) music_sessions.length.should == 1 user_scores.length.should == 1 end end end describe "sorting" do let!(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) } let!(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr:4) } let!(:creator_2) { FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 10) } let!(:creator_conn_2) { FactoryGirl.create(:connection, user: creator_2, ip_address: '4.4.4.4', locidispid: 1, addr:1) } let!(:creator_3) { FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 12) } let!(:creator_conn_3) { FactoryGirl.create(:connection, user: creator_3, ip_address: '5.5.5.5', locidispid: 2, addr:2) } let!(:searcher_1) { FactoryGirl.create(:user, last_jam_locidispid: 5, last_jam_audio_latency: 6) } let!(:searcher_conn_1) { FactoryGirl.create(:connection, user: searcher_1, ip_address: '8.8.8.8', locidispid: 5, addr:5) } let!(:searcher_2) { FactoryGirl.create(:user, last_jam_locidispid: 3, last_jam_audio_latency: 14) } let!(:searcher_conn_2) { FactoryGirl.create(:connection, user: searcher_2, ip_address: '9.9.9.9', locidispid: 3, addr:3) } let!(:music_session_1) { FactoryGirl.create(:music_session, creator: creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps") } let!(:music_session_2) { FactoryGirl.create(:music_session, creator: creator_2, genre: Genre.find('ambient'), language: 'spa', description: "Play with us as we jam to beatles and bunnies") } let!(:music_session_3) { FactoryGirl.create(:music_session, creator: creator_3) } let(:good_network_score) { 20 } let(:fair_network_score) { 30 } let(:bad_network_score) { 40 } before(:each) do # add an RSVP for searcher_1 to music_session_1 searcher_rsvp_slot = FactoryGirl.create(:rsvp_slot, music_session: music_session_1, instrument: Instrument.find('piano')) searcher_rsvp_request = FactoryGirl.create(:rsvp_request, user: searcher_1) searcher_rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:true, rsvp_request: searcher_rsvp_request, rsvp_slot: searcher_rsvp_slot) # add an invitation to searcher_1 to music_session_2 FactoryGirl.create(:friendship, user: creator_2, friend: searcher_1) FactoryGirl.create(:friendship, user: searcher_1, friend: creator_2) FactoryGirl.create(:invitation, receiver:searcher_1, sender:creator_2, music_session: music_session_2) end it "searcher_1" do # create a bad score between searcher_1 and creator_1 (but we should still see it sort 1st because it's got an RSVP to the searcher) Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_1.locidispid, creator_conn_1.client_id, creator_conn_1.addr, bad_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_1.id}) # create a fair score between searcher_1 and creator_2 (but we should still see it sort 2st because it's got an invitation to the searcher) Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_2.locidispid, creator_conn_2.client_id, creator_conn_2.addr, fair_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_2.id}) # create a good score between searcher_1 and creator_3 (but we should still see it sort last because it's an open session; no affiliation with the searcher) Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_3.locidispid, creator_conn_3.client_id, creator_conn_3.addr, good_network_score, nil, nil, {auserid: searcher_1.id, buserid: creator_3.id}) music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 3 music_session = music_sessions[0] music_session.should == music_session_1 music_session.tag.should == 1 # RSVP music_session.latency.should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) music_session = music_sessions[1] music_session.should == music_session_2 music_session.tag.should == 2 # INVITE music_session.latency.should == (fair_network_score + searcher_1.last_jam_audio_latency + creator_2.last_jam_audio_latency ) music_session = music_sessions[2] music_session.should == music_session_3 music_session.tag.should == 3 # OPEN music_session.latency.should == (good_network_score + searcher_1.last_jam_audio_latency + creator_3.last_jam_audio_latency ) user_scores.length.should == 3 # the creator, and the invitee user_scores[creator_1.id][:full_score].should == (bad_network_score + searcher_1.last_jam_audio_latency + creator_1.last_jam_audio_latency ) # let's make music_session_3 invisible, and verify the count goes to 2 music_session_3.open_rsvps = false music_session_3.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 # let's make music_session_2 invisible, but still the count should be the same (because searcher_1 have an invite) music_session_2.open_rsvps = false music_session_2.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 # and lastly with music_session_1, make it invisible, and still it should be visible to the searcher (because searcher_1 has an invite) music_session_1.open_rsvps = false music_session_1.save! music_sessions, user_scores = sms(searcher_1, {client_id: searcher_conn_1.client_id}) music_sessions.length.should == 2 end end describe "parameters" do let(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) } let(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr:4) } let(:creator_2) { FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 10) } let(:creator_conn_2) { FactoryGirl.create(:connection, user: creator_2, ip_address: '4.4.4.4', locidispid: 1, addr:1) } let(:creator_3) { FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 12) } let(:creator_conn_3) { FactoryGirl.create(:connection, user: creator_3, ip_address: '5.5.5.5', locidispid: 2, addr:2) } let(:searcher_1) { FactoryGirl.create(:user, last_jam_locidispid: 5, last_jam_audio_latency: 6) } let(:searcher_conn_1) { FactoryGirl.create(:connection, user: searcher_1, ip_address: '8.8.8.8', locidispid: 5, addr:5) } let(:searcher_2) { FactoryGirl.create(:user, last_jam_locidispid: 3, last_jam_audio_latency: 14) } let(:searcher_conn_2) { FactoryGirl.create(:connection, user: searcher_2, ip_address: '9.9.9.9', locidispid: 3, addr:3) } let!(:music_session_1) { FactoryGirl.create(:music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps" ) } let!(:music_session_2) { FactoryGirl.create(:music_session, :creator => creator_2, genre: Genre.find('ambient'), language: 'spa', description: "Play with us as we jam to beatles and bunnies") } let(:good_network_score) { 20 } let(:fair_network_score) { 30 } it "offset/limit" do # set up some scores to control sorting Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_1.locidispid, creator_conn_1.client_id, creator_conn_1.addr, good_network_score, nil) Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_2.locidispid, creator_conn_2.client_id, creator_conn_2.addr, fair_network_score, nil) # verify we can get all 2 sessions music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 music_sessions[0].should == music_session_1 # grab just the 1st music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, offset:0, limit:1) music_sessions.length.should == 1 music_sessions[0].should == music_session_1 # then the second music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, offset:1, limit:2) music_sessions.length.should == 1 music_sessions[0].should == music_session_2 end it "genre" do # verify we can get all 2 sessions music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 # get only african music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, genre: 'african') music_sessions.length.should == 1 music_sessions[0].genre.should == Genre.find('african') # get only ambient music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, genre: 'ambient') music_sessions.length.should == 1 music_sessions[0].genre.should == Genre.find('ambient') end it "language" do # verify we can get all 2 sessions music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 # get only english music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, lang: 'eng') music_sessions.length.should == 1 music_sessions[0].language.should == 'eng' # get only ambient music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, lang: 'spa') music_sessions.length.should == 1 music_sessions[0].language.should == 'spa' end it "keyword" do music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Jump') music_sessions.length.should == 1 music_sessions[0].should == music_session_1 music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Bunny') music_sessions.length.should == 2 music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'play') music_sessions.length.should == 1 music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'bun') music_sessions.length.should == 2 end it "date" do music_session_1.scheduled_start = 1.days.ago music_session_1.save! # if no day/timezone_offset specified, then the 15 minute slush rule will still kick in, nixing music_session_1 music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 1 music_sessions[0].should == music_session_2 # find today's session music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, day: Date.today.to_s, timezone_offset: DateTime.now.offset.numerator) music_sessions.length.should == 1 music_sessions[0].should == music_session_2 # find yesterday's session... oh wait, you can't find a session for yesterday, because the 15 minute slush rule will still kick in. music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, day: (Date.today - 1).to_s, timezone_offset: DateTime.now.offset.numerator) music_sessions.length.should == 0 # but let's make it tomorrow, so we can test in that direction music_session_1.scheduled_start = 1.day.from_now music_session_1.save! music_sessions, user_search = sms(searcher_1, client_id: searcher_conn_1.client_id, day: (Date.today + 1).to_s, timezone_offset: DateTime.now.offset.numerator) music_sessions.length.should == 1 music_sessions[0].should == music_session_1 end end describe "scheduled_rsvp" do let(:creator_1) { FactoryGirl.create(:user) } let!(:music_session_1) { FactoryGirl.create(:music_session, :creator => creator_1, description: "Bunny Jumps", :create_type => MusicSession::CREATE_TYPE_IMMEDIATE ) } it "lists one" do MusicSession.scheduled_rsvp(creator_1).should == [music_session_1] end it "does not list canceled" do music_session_1.canceled = true music_session_1.save! MusicSession.scheduled_rsvp(creator_1).should == [] end it "does not list old" do music_session_1.scheduled_start = 5.hours.ago music_session_1.save! MusicSession.scheduled_rsvp(creator_1).should == [] end it "only show approved sessions" do MusicSession.scheduled_rsvp(creator_1, true).should == [music_session_1] end it "does not show unchosen" do music_session_1.rsvp_slots[0].rsvp_requests_rsvp_slots[0].chosen = false music_session_1.rsvp_slots[0].rsvp_requests_rsvp_slots[0].save! MusicSession.scheduled_rsvp(creator_1, true).should == [] end it "create_type = nil will still return RSVPs" do music_session_1.create_type = nil music_session_1.save! MusicSession.scheduled_rsvp(creator_1, true).should == [music_session_1] end end end describe "scheduled session rescheduled logic" do it "detect change to scheduling info" do music_session1.description = "Hey!" music_session1.save! music_session1.scheduling_info_changed.should be_false music_session1.scheduled_start = Time.now - 1.days music_session1.save! music_session1.scheduling_info_changed.should be_true end end describe "html_sanitize" do it "sanitizes" do music_session1.name = 'dog' music_session1.description = 'cat' music_session1.save! music_session1.name.should == 'dog' music_session1.description.should == 'cat' end end describe "purgeable sessions " do it 'selects unscheduled sessions past due date' do interval = MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE dd = Time.now - (interval.to_i + 1).days Timecop.travel(dd) msess1 = FactoryGirl.create(:music_session) Timecop.return msess2 = FactoryGirl.create(:music_session) purging = MusicSession.purgeable_sessions expect(purging.size).to be(1) expect(purging[0].id).to eq(msess1.id) end it 'selects recurring and non-recurring sessions past due date' do [MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE, MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE_RECUR].each do |interval| dd = Time.now - (interval.to_i + 1).days Timecop.travel(dd) msess1 = FactoryGirl.create(:music_session, scheduled_start: Time.now) Timecop.return msess2 = FactoryGirl.create(:music_session, scheduled_start: Time.now) purging = MusicSession.purgeable_sessions expect(purging.size).to be(1) expect(purging[0].id).to eq(msess1.id) MusicSession.delete_all end end end end