require 'spec_helper' describe ActiveMusicSession do before(:each) do ActiveMusicSession.delete_all IcecastServer.delete_all IcecastMount.delete_all end it 'can grant access to valid user' do user1 = FactoryGirl.create(:user) # in the jam session user2 = FactoryGirl.create(:user) # in the jam session user3 = FactoryGirl.create(:user) # not in the jam session music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false) FactoryGirl.create(:connection, :user => user1, :music_session => music_session) FactoryGirl.create(:connection, :user => user2, :music_session => music_session) music_session.access?(user1).should == true music_session.access?(user2).should == true music_session.access?(user3).should == false end it 'anyone can join a open music session' do user1 = FactoryGirl.create(:user) # in the jam session user2 = FactoryGirl.create(:user) # in the jam session user3 = FactoryGirl.create(:user) # not in the jam session music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true) music_session.can_join?(user1, true).should == true music_session.can_join?(user2, true).should == true music_session.can_join?(user3, true).should == true end it 'no one but invited people can join closed music session' do user1 = FactoryGirl.create(:user) # in the jam session user2 = FactoryGirl.create(:user) # in the jam session user3 = FactoryGirl.create(:user) # not in the jam session music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false) FactoryGirl.create(:connection, :user => user1, :music_session => music_session) music_session.can_join?(user1, true).should == true music_session.can_join?(user2, true).should == false music_session.can_join?(user3, true).should == false # invite user 2 FactoryGirl.create(:friendship, :user => user1, :friend => user2) FactoryGirl.create(:friendship, :user => user2, :friend => user1) FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session) music_session.can_join?(user1, true).should == true music_session.can_join?(user2, true).should == true music_session.can_join?(user3, true).should == false end it 'no one but invited people can see closed music session' do user1 = FactoryGirl.create(:user) # in the jam session user2 = FactoryGirl.create(:user) # in the jam session user3 = FactoryGirl.create(:user) # not in the jam session music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false, :fan_access => false) FactoryGirl.create(:connection, :user => user1, :music_session => music_session) music_session.can_see?(user1).should == true music_session.can_see?(user2).should == false music_session.can_see?(user3).should == false # invite user 2 FactoryGirl.create(:friendship, :user => user1, :friend => user2) FactoryGirl.create(:friendship, :user => user2, :friend => user1) FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session) music_session.can_see?(user1).should == true music_session.can_see?(user2).should == true music_session.can_see?(user3).should == false end describe "index" do it "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") FactoryGirl.create(:connection, :user => creator, :music_session => earlier_session) later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session") FactoryGirl.create(:connection, :user => creator2, :music_session => later_session) user = FactoryGirl.create(:user) #ActiveRecord::Base.logger = Logger.new(STDOUT) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 2 music_sessions.first.id.should == later_session.id end it "orders sessions with inviteds first, even if created first" do creator1 = FactoryGirl.create(:user) creator2 = FactoryGirl.create(:user) earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session") FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session) later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session") FactoryGirl.create(:connection, :user => creator2, :music_session => later_session) user = FactoryGirl.create(:user) FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session) FactoryGirl.create(:friendship, :user => creator1, :friend => user) FactoryGirl.create(:friendship, :user => user, :friend => creator1) FactoryGirl.create(:invitation, :sender => creator1, :receiver => user, :music_session => earlier_session.music_session) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 2 music_sessions.first.id.should == earlier_session.id end it "orders sessions with friends in the session first, even if created first" do creator1 = FactoryGirl.create(:user) creator2 = FactoryGirl.create(:user) earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session") FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session) later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session") FactoryGirl.create(:connection, :user => creator2, :music_session => later_session) user = FactoryGirl.create(:user) FactoryGirl.create(:friendship, :user => creator1, :friend => user) FactoryGirl.create(:friendship, :user => user, :friend => creator1) FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session) FactoryGirl.create(:connection, :user => creator2, :music_session => earlier_session) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 2 music_sessions.first.id.should == earlier_session.id end it "doesn't list a session if musician_access is set to false" do creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false) user = FactoryGirl.create(:user) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 0 end it "does list a session if musician_access is set to false but user was invited" do creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false) user = FactoryGirl.create(:user) FactoryGirl.create(:connection, :user => creator, :music_session => session) FactoryGirl.create(:friendship, :user => creator, :friend => user) FactoryGirl.create(:friendship, :user => user, :friend => creator) FactoryGirl.create(:invitation, :sender => creator, :receiver => user, :music_session => session.music_session) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 1 end it "lists a session if the genre matches" do creator = FactoryGirl.create(:user) genre = FactoryGirl.create(:genre) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre) FactoryGirl.create(:connection, :user => creator, :music_session => session) user = FactoryGirl.create(:user) music_sessions = ActiveMusicSession.index(user, genres: [genre.id]) music_sessions.length.should == 1 end it "does not list a session if the genre fails to match" do creator = FactoryGirl.create(:user) genre1 = FactoryGirl.create(:genre) genre2 = FactoryGirl.create(:genre) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre1) user = FactoryGirl.create(:user) music_sessions = ActiveMusicSession.index(user, genres: [genre2.id]) music_sessions.length.should == 0 end it "does not list a session if friends_only is set and no friends are in it" do creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session") user = FactoryGirl.create(:user) music_sessions = ActiveMusicSession.index(user, friends_only: true) music_sessions.length.should == 0 end it "lists a session properly if a friend is in it" do creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session") user = FactoryGirl.create(:user) FactoryGirl.create(:friendship, :user => creator, :friend => user) FactoryGirl.create(:friendship, :user => user, :friend => creator) FactoryGirl.create(:connection, :user => creator, :music_session => session) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 1 music_sessions = ActiveMusicSession.index(user, friends_only: true) music_sessions.length.should == 1 music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true) music_sessions.length.should == 0 music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true) music_sessions.length.should == 1 end it "does not list a session if it has no participants" do # it's a design goal that there should be no sessions with 0 connections; # however, this bug continually crops up so the .index method will protect against this common bug creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session") session.connections.delete_all # should leave a bogus, 0 participant session around music_sessions = ActiveMusicSession.index(creator) music_sessions.length.should == 0 end it "does not list a session if my_bands_only is set and it's not my band" do creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session") user = FactoryGirl.create(:user) music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true) music_sessions.length.should == 0 end it "lists a session properly if it's my band's session" do band = FactoryGirl.create(:band) creator = FactoryGirl.create(:user) session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :band => band) FactoryGirl.create(:connection, :user => creator, :music_session => session) user = FactoryGirl.create(:user) FactoryGirl.create(:band_musician, :band => band, :user => creator) FactoryGirl.create(:band_musician, :band => band, :user => user) music_sessions = ActiveMusicSession.index(user) music_sessions.length.should == 1 music_sessions = ActiveMusicSession.index(user, friends_only: true) music_sessions.length.should == 0 music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true) music_sessions.length.should == 1 music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true) music_sessions.length.should == 1 end describe "index(as_musician: false)" do let(:fan_access) { true } let(:creator) { FactoryGirl.create(:user) } let(:session) { FactoryGirl.create(:active_music_session, creator: creator, fan_access: fan_access ) } let(:connection) { FactoryGirl.create(:connection, user: creator, :music_session => session) } let(:user) {FactoryGirl.create(:user) } describe "no mount" do before(:each) do session.mount.should be_nil end it "no session listed if mount is nil" do connection.touch sessions = ActiveMusicSession.index(user, as_musician: false) sessions.length.should == 0 end end describe "with mount" do let(:session_with_mount) { FactoryGirl.create(:active_music_session_with_mount) } let(:connection_with_mount) { FactoryGirl.create(:connection, user: creator, :music_session => session_with_mount) } before(:each) { session_with_mount.mount.should_not be_nil } it "no session listed if icecast_server config hasn't been updated" do connection_with_mount.touch sessions = ActiveMusicSession.index(user, as_musician: false) sessions.length.should == 0 end it "session listed if icecast_server config has been updated" do connection_with_mount.touch session_with_mount.created_at = 2.minutes.ago session_with_mount.save!(:validate => false) session_with_mount.mount.server.config_updated_at = 1.minute.ago session_with_mount.mount.server.save!(:validate => false) sessions = ActiveMusicSession.index(user, as_musician: false) sessions.length.should == 1 end end 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 def ams(user, params) ActiveRecord::Base.transaction do return ActiveMusicSession.ams_index(user, params) end end describe "ams_index", no_transaction: true do it "does not crash" do creator = FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 5) creator2 = FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 10) earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session") c1 = FactoryGirl.create(:connection, user: creator, music_session: earlier_session, locidispid: 1, last_jam_audio_latency: 5) later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session") c2 = FactoryGirl.create(:connection, user: creator2, music_session: later_session, locidispid: 2, last_jam_audio_latency: 10) user = FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 5) c3 = FactoryGirl.create(:connection, user: user, locidispid: 1, last_jam_audio_latency: 5) Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil, nil, {auserid: creator.id, buserid: user.id}) Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil, nil, {auserid: creator2.id, buserid: user.id}) # make a transaction ActiveRecord::Base.transaction do ActiveMusicSession.ams_init(user, client_id: c3.client_id) music_sessions = ActiveMusicSession.ams_query(user, client_id: c3.client_id).take(100) music_sessions.should_not be_nil music_sessions.length.should == 2 music_sessions[0].tag.should_not be_nil music_sessions[0].latency.should_not be_nil music_sessions[1].tag.should_not be_nil music_sessions[1].latency.should_not be_nil users = ActiveMusicSession.ams_users.take(100) users.should_not be_nil users.length.should == 2 if users[0].music_session_id == earlier_session.id users[0].id.should == creator.id users[0].full_score.should == 30 # (5 + 20 + 5) users[0].audio_latency = 5 users[0].internet_score = 20 users[1].music_session_id == later_session.id users[1].id.should == creator2.id users[1].full_score.should == 45 # (5 + 30 + 10) users[1].audio_latency.should == 10 users[1].internet_score.should == 30 else users[0].music_session_id.should == later_session.id users[0].id.should == creator2.id users[0].full_score.should == 45 # (5 + 30 + 10) users[0].audio_latency.should == 10 users[0].internet_score.should == 30 users[1].music_session_id == earlier_session.id users[1].id.should == creator.id users[1].full_score.should == 30 # (5 + 20 + 5) users[1].audio_latency.should == 5 users[1].internet_score.should == 20 end 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(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps" ) } let!(:music_session_2) { FactoryGirl.create(:active_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 } let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] } it "offset/limit" do # put creators in the session creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10) creator_conn_1.errors.any?.should be_false creator_conn_2.join_the_session(music_session_2.music_session, true, tracks, creator_2, 10) creator_conn_2.errors.any?.should be_false # 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 = ams(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 music_sessions[0].should == music_session_1.music_session # grab just the 1st music_sessions, user_search = ams(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.music_session # then the second music_sessions, user_search = ams(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.music_session end it "genre" do # verify we can get all 2 sessions music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 # get only african music_sessions, user_search = ams(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 = ams(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 = ams(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 # get only english music_sessions, user_search = ams(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 = ams(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 = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Jump') music_sessions.length.should == 1 music_sessions[0].should == music_session_1.music_session music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Bunny') music_sessions.length.should == 2 music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'play') music_sessions.length.should == 1 music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'bun') music_sessions.length.should == 2 music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'bunny play') music_sessions.length.should == 1 end it "date" do music_session_1.music_session.scheduled_start = 1.days.ago music_session_1.music_session.save! # if no day/timezone_offset specified, both should be returned music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 # find today's session music_sessions, user_search = ams(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.music_session # find yesterday's session music_sessions, user_search = ams(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.music_session end it "should allow a null locidispid to search" do searcher_conn_1.locidispid = nil searcher_conn_1.save! music_sessions, user_scores = ams(searcher_1, client_id: searcher_conn_1.client_id) music_sessions.length.should == 2 end end # todo we need more tests: # # the easiest collection of tests, not involving filtering, just tagging and latency, still result in many cases # (given a creator, member, and observer): # # {not_rsvp, rsvp_not_chosen, rsvp_chosen} x # {not_invited, invited} x # {no_musicians, musicians_on_approval, musicians_freely_join} x # {creator_not_member, creator_is_member} x # {observer_not_member, observer_is_member} x # {observer_member_not_scored, observer_member_scored} # # eh, that's 144 cases all told, and that doesn't cover the cases with multiple members... # # member is the user in the session # creator is the user that created the session # observer is the user making the call to ams_index # # the first two categories (rsvp and invited) are about the observer. # # i see this being written like this: # # test_ams([:not_rsvp, :not_invited, :no_musicians, :creator_not_member, :observer_not_member, :observer_member_not_scored], # member_latency, observer_member_score, observer_latency, expected_count, expected_tag, expected_latency) # # ... repeat as above with all the various combinations by choosing one from each category and appropriate other # values and then expected results ... # # expected_count is 0 for the above written case, and would be 1 in the cases where any of rsvp_chosen, invited, # musicians_on_approval, or musicians_freely_join are specified. test_ams would know which session and user should # appear in the results of ams_index and ams_users. # # there should be an additional active music session created and joined by a distinct user, other. it should never # appear in results. 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 "open_jam_track" 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) @jam_track = FactoryGirl.create(:jam_track) @jam_track_right = FactoryGirl.create(:jam_track_right, jam_track: @jam_track, user: @user1) end it "allow a jam track to be associated" do # simple success case; just open the jam track and observe the state of the session is correct @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_false @music_session.reload @music_session.jam_track.should == @jam_track @music_session.jam_track_initiator.should == @user1 end it "allow a jam track to be closed" do # simple success case; close an opened jam track and observe the state of the session is correct @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_false @music_session.close_jam_track @music_session.errors.any?.should be_false @music_session.reload @music_session.jam_track.should be_nil @music_session.jam_track_initiator.should be_nil end it "disallow a jam track to be opened when another is already opened" do pending "needs fixing" # if a jam track is open, don't allow another to be opened @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_false @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_true @music_session.errors[:jam_track] == [ValidationMessages::JAM_TRACK_ALREADY_OPEN] end it "disallow a jam track to be opened when recording is ongoing" do @recording = Recording.start(@music_session, @user1) @music_session.errors.any?.should be_false @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_true @music_session.errors[:jam_track] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS] end it "disallow a jam track to be opened when recording is playing back" do # create a recording, and open it for play back @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 @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false # while it's open, try to open a jam track @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_true @music_session.errors[:jam_track] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS] end 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 "open 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 "disallow 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 it "disallow a claimed recording to be started when jam track is open" do # open the jam track @jam_track = FactoryGirl.create(:jam_track) @jam_track_right = FactoryGirl.create(:jam_track_right, jam_track: @jam_track, user: @user1) @music_session.open_jam_track(@user1, @jam_track) @music_session.errors.any?.should be_false # and try to open a recording for playback @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_true @music_session.errors[:claimed_recording] == [ValidationMessages::JAM_TRACK_ALREADY_OPEN] end it "disallow a claimed recording to be started when backing track is open" do # open the backing track @backing_track = "foo.mp3" @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_false # and try to open a recording for playback @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_true @music_session.errors[:claimed_recording] == [ValidationMessages::BACKING_TRACK_ALREADY_OPEN] end it "disallow a claimed recording to be started when metronome is open" do # open the metronome @music_session.open_metronome(@user1) @music_session.errors.any?.should be_false # and try to open a recording for playback @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_true @music_session.errors[:claimed_recording] == [ValidationMessages::METRONOME_ALREADY_OPEN] end end end describe "updates parent music_session" do it "updates needed fields" do music_session = FactoryGirl.create(:music_session, scheduled_start: nil) active_music_session = FactoryGirl.create(:active_music_session, music_session: music_session) music_session.reload active_music_session.reload music_session.scheduled_start.to_s.should == active_music_session.created_at.to_s music_session.active_music_session.should == active_music_session end it "ignore scheduled_start if already set" do yesterday = 1.days.ago music_session = FactoryGirl.create(:music_session, scheduled_start: yesterday) active_music_session = FactoryGirl.create(:active_music_session, music_session: music_session) music_session.reload music_session.scheduled_start.should == yesterday 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 "join_the_session" 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!(:music_session_1) { FactoryGirl.create(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps" ) } let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] } let(:videos) { [{'client_video_source_id' => 'abc'}] } it "joins the session with no video" do creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10) creator_conn_1.errors.any?.should be_false music_sessions = ActiveMusicSession.index(creator_1) music_sessions.should_not be_nil music_sessions.length.should == 1 music_sessions[0].connections.should have(1).items music_sessions[0].connections.should have(1).items music_sessions[0].connections[0].tracks.should have(1).items music_sessions[0].connections[0].video_sources.should have(0).items end it "joins the session with video" do creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10, videos) creator_conn_1.errors.any?.should be_false music_sessions = ActiveMusicSession.index(creator_1) music_sessions.should_not be_nil music_sessions.length.should == 1 creator_conn_1.video_sources.should have(1).items music_sessions[0].connections.should have(1).items music_sessions[0].connections[0].video_sources.should have(1).items music_sessions[0].connections[0].tracks.should have(1).items end end describe "open_backing_track" 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) @backing_track = "foo/bar.mp3" end it "allow a backing track to be associated" do # simple success case; just open the backing track and observe the state of the session is correct @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_false @music_session.reload @music_session.backing_track_path.should == @backing_track @music_session.backing_track_initiator.should == @user1 end it "allow a backing track to be closed" do # simple success case; close an opened backing track and observe the state of the session is correct @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_false @music_session.close_backing_track @music_session.errors.any?.should be_false @music_session.reload @music_session.backing_track_path.should be_nil @music_session.backing_track_initiator.should be_nil end it "disallow a backing track to be opened when another is already opened" do # if a backing track is open, don't allow another to be opened @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_false @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_true @music_session.errors[:backing_track] == [ValidationMessages::BACKING_TRACK_ALREADY_OPEN] end it "disallow a backing track to be opened when recording is ongoing" do @recording = Recording.start(@music_session, @user1) @music_session.errors.any?.should be_false @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_true @music_session.errors[:backing_track] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS] end it "disallow a backing track to be opened when recording is playing back" do # create a recording, and open it for play back @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 @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false # while it's open, try to open a jam track @music_session.open_backing_track(@user1, @backing_track) @music_session.errors.any?.should be_true @music_session.errors[:backing_track] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS] end end describe "open_metronome" 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 it "allow a metronome to be activated" do # simple success case; just open the metronome and observe the state of the session is correct @music_session.open_metronome(@user1) @music_session.errors.any?.should be_false @music_session.reload @music_session.metronome_active.should == true @music_session.metronome_initiator.should == @user1 end it "allow a metronome to be closed" do # simple success case; close an opened metronome and observe the state of the session is correct @music_session.open_metronome(@user1) @music_session.errors.any?.should be_false @music_session.close_metronome @music_session.errors.any?.should be_false @music_session.reload @music_session.metronome_active.should be_false @music_session.metronome_initiator.should be_nil end it "disallow a metronome to be opened when recording is ongoing" do @recording = Recording.start(@music_session, @user1) @music_session.errors.any?.should be_false @music_session.open_metronome(@user1) @music_session.errors.any?.should be_true @music_session.errors[:metronome] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS] end it "disallow a metronome to be opened when recording is playing back" do # create a recording, and open it for play back @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 @music_session.claimed_recording_start(@user1, @claimed_recording) @music_session.errors.any?.should be_false # while it's open, try to open a jam track @music_session.open_metronome(@user1) @music_session.errors.any?.should be_true @music_session.errors[:metronome] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS] end end describe "stats" do it "empty" do ActiveMusicSession.stats['count'].should eq(0) end it "one" do FactoryGirl.create(:active_music_session) ActiveMusicSession.stats.should eq('count' => 1, 'jam_track_count' => 0, 'backing_track_count' => 0, 'metronome_count' => 0, 'recording_count' => 0) end it "two" do ams1 = FactoryGirl.create(:active_music_session, jam_track_initiator_id: '1') ams2 = FactoryGirl.create(:active_music_session, jam_track_initiator_id: '2') user1 = FactoryGirl.create(:user) user2 = FactoryGirl.create(:user) ActiveMusicSession.stats.should eq('count' => 2, 'jam_track_count' => 2, 'backing_track_count' => 0, 'metronome_count' => 0, 'recording_count' => 0) ams1.backing_track_initiator = user1 ams2.backing_track_initiator = user2 ams1.save! ams2.save! ActiveMusicSession.stats.should eq('count' => 2, 'jam_track_count' => 2, 'backing_track_count' => 2, 'metronome_count' => 0, 'recording_count' => 0) ams1.metronome_initiator = user1 ams2.metronome_initiator = user2 ams1.save! ams2.save! ActiveMusicSession.stats.should eq('count' => 2, 'jam_track_count' => 2, 'backing_track_count' => 2, 'metronome_count' => 2, 'recording_count' => 0) ams1.claimed_recording_initiator = user1 ams2.claimed_recording_initiator = user2 ams1.save! ams2.save! ActiveMusicSession.stats.should eq('count' => 2, 'jam_track_count' => 2, 'backing_track_count' => 2, 'metronome_count' => 2, 'recording_count' => 2) end end end