From cdc9d121cbbca3a542465dc4fe0de800b8adb577 Mon Sep 17 00:00:00 2001 From: Bert Owen Date: Mon, 19 May 2014 23:35:38 +0800 Subject: [PATCH] VRFS-1674 Create Session API --- db/manifest | 3 +- db/up/add_timezone_music_session.sql | 1 + ruby/lib/jam_ruby/models/music_session.rb | 67 +- ruby/spec/factories.rb | 1 + .../models/active_music_session_spec.rb | 467 +++++++++++ .../models/music_session_history_spec.rb | 114 --- .../jam_ruby/models/music_session_spec.rb | 481 +----------- .../api_music_sessions_controller.rb | 17 + web/app/views/api_music_sessions/create.rabl | 4 +- web/config/routes.rb | 1 + .../active_music_sessions_api_spec.rb | 730 ++++++++++++++++++ web/spec/requests/music_sessions_api_spec.rb | 715 +---------------- 12 files changed, 1321 insertions(+), 1280 deletions(-) create mode 100644 db/up/add_timezone_music_session.sql create mode 100644 ruby/spec/jam_ruby/models/active_music_session_spec.rb delete mode 100644 ruby/spec/jam_ruby/models/music_session_history_spec.rb create mode 100755 web/spec/requests/active_music_sessions_api_spec.rb mode change 100755 => 100644 web/spec/requests/music_sessions_api_spec.rb diff --git a/db/manifest b/db/manifest index f41f30931..6e91f40a1 100755 --- a/db/manifest +++ b/db/manifest @@ -155,4 +155,5 @@ session_ratings.sql scheduled_sessions.sql notification_scheduled_session.sql music_notation.sql -music_session_recurring_mode.sql \ No newline at end of file +music_session_recurring_mode.sql +add_timezone_music_session.sql \ No newline at end of file diff --git a/db/up/add_timezone_music_session.sql b/db/up/add_timezone_music_session.sql new file mode 100644 index 000000000..973c2cac8 --- /dev/null +++ b/db/up/add_timezone_music_session.sql @@ -0,0 +1 @@ +ALTER TABLE music_sessions ADD COLUMN timezone VARCHAR(255); \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index b25053f2a..b9d6ea35c 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -30,6 +30,8 @@ module JamRuby has_many :invited_musicians, :through => :invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver has_many :fan_invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::FanInvitation", :foreign_key => "music_session_id" has_many :invited_fans, :through => :fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver + has_many :rsvp_slots, :class_name => "JamRuby::RsvpSlot", :foreign_key => "music_session_id", :dependent => :destroy + has_many :music_notations, :class_name => "JamRuby::MusicNotations", :foreign_key => "music_session_id" validates :genre, :presence => true validates :description, :presence => true, :no_profanity => true @@ -39,7 +41,6 @@ module JamRuby validates :musician_access, :inclusion => {:in => [true, false]} validates :legal_terms, :inclusion => {:in => [true]}, :on => :create validates :creator, :presence => true - # validates :recurring_mode, :inclusion => {:in => RECURRING_MODES}, :on => :create validate :creator_is_musician before_create :generate_share_token @@ -106,24 +107,66 @@ module JamRuby return query end - def self.create user, params - band = Band.find(params[:band]) unless params[:band].nil? + def self.create user, options + band = Band.find(options[:band]) unless options[:band].nil? ms = MusicSession.new - ms.name = params[:description][0..40] - ms.description = params[:description] - ms.musician_access = params[:musician_access] - ms.approval_required = params[:approval_required] - ms.fan_access = params[:fan_access] - ms.fan_chat = params[:fan_chat] + ms.name = options[:name] + ms.description = options[:description] + ms.genre_id = (options[:genres].length > 0 ? options[:genres][0] : nil) if options[:genres] + ms.musician_access = options[:musician_access] + ms.approval_required = options[:approval_required] + ms.fan_access = options[:fan_access] + ms.fan_chat = options[:fan_chat] ms.band = band - ms.legal_policy = params[:legal_policy] - ms.language = params[:language] - ms.genre_id = (params[:genres].length > 0 ? params[:genres][0] : nil) if params[:genres] + ms.legal_policy = options[:legal_policy] + ms.language = options[:language] + ms.scheduled_start = options[:start] if options[:start] + ms.timezone = options[:timezone] + ms.recurring_mode = options[:recurring_mode] if options[:recurring_mode] ms.legal_terms = true ms.creator = user ms.save + + unless ms.errors.any? + ms.reload + + options[:rsvp_slots].each do |rs| + rsvp = RsvpSlot.new + rsvp.instrument = Instrument.find(rs[:instrument_id]) + rsvp.proficiency_level = rs[:proficiency_level] + rsvp.music_session = ms + rsvp.save + + ms.rsvp_slots << rsvp + end if options[:rsvp_slots] + + options[:invitations].each do |invite_id| + invitation = Invitation.new + receiver = User.find(invite_id) + invitation.sender = user + invitation.receiver = receiver + invitation.music_session = ms + invitation.save + + ms.invitations << invitation + + Notification.send_session_invitation(receiver, user, ms.id) + end if options[:invitations] + + options[:music_notations].each do |notation_id| + notation = MusicNotation.find(notation_id) + notation.music_session = ms + notation.save + + ms.music_notations << notation + end if options[:music_notations] + + ms.save + end + + ms end def unique_users diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index d8c5c4b5e..8798e0694 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -88,6 +88,7 @@ FactoryGirl.define do musician_access true legal_terms true language 'english' + timezone 'utc' legal_policy 'standard' recurring_mode 'once' genre JamRuby::Genre.first diff --git a/ruby/spec/jam_ruby/models/active_music_session_spec.rb b/ruby/spec/jam_ruby/models/active_music_session_spec.rb new file mode 100644 index 000000000..74be88bf1 --- /dev/null +++ b/ruby/spec/jam_ruby/models/active_music_session_spec.rb @@ -0,0 +1,467 @@ +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 + + + 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) + 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_false + 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 +end + diff --git a/ruby/spec/jam_ruby/models/music_session_history_spec.rb b/ruby/spec/jam_ruby/models/music_session_history_spec.rb deleted file mode 100644 index ba36c9a30..000000000 --- a/ruby/spec/jam_ruby/models/music_session_history_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -require 'spec_helper' - -describe MusicSession do - - - let(:creator) {FactoryGirl.create(:user)} - let(:some_user) { FactoryGirl.create(:user) } - let(:music_session) { FactoryGirl.create(:active_music_session_no_user_history) } - let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) } - let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) } - let(:user_history3) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) } - let(:user_history4) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) } - - 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 - - it "unique users" do - user_history1.should_not be_nil - user_history2.should_not be_nil - users = music_session.music_session.unique_users - - users.length.should eql(2) - - users.include?(some_user).should be_true - users.include?(music_session.creator).should be_true - - user_history3.should_not be_nil - user_history4.should_not be_nil - users = music_session.music_session.unique_users - - users.length.should eql(2) - users.include?(some_user).should be_true - users.include?(music_session.creator).should be_true - end - - it "unique_user_histories" do - - created_at = 4.days.ago - session_removed_at = created_at + 1.days - user_history1.created_at = created_at - user_history1.session_removed_at = session_removed_at - user_history1.save! - user_history2.created_at = created_at - user_history2.session_removed_at = session_removed_at - user_history2.save! - - histories = music_session.music_session.unique_user_histories - histories.length.should eql(2) - histories[0].first_name.should_not be_nil - histories[0].last_name.should_not be_nil - histories[0].photo_url.should be_nil - histories[0].total_duration.to_i.should == 1.day.to_i - histories[0].total_instruments.should == 'guitar' - histories[1].total_duration.to_i.should == 1.day.to_i - histories[1].total_instruments.should == 'guitar' - - - user_history3.created_at = created_at - user_history3.session_removed_at = session_removed_at - user_history3.save! - user_history4.created_at = created_at - user_history4.session_removed_at = session_removed_at - user_history4.save! - - histories = music_session.music_session.unique_user_histories - histories.length.should eql(2) - histories[0].total_duration.to_i.should == 2.day.to_i - histories[0].total_instruments.should == 'guitar|guitar' - histories[1].total_duration.to_i.should == 2.day.to_i - histories[1].total_instruments.should == 'guitar|guitar' - - - users = histories.map {|i| i.user} - users.include?(some_user).should be_true - users.include?(music_session.creator).should be_true - end - -end - - diff --git a/ruby/spec/jam_ruby/models/music_session_spec.rb b/ruby/spec/jam_ruby/models/music_session_spec.rb index 74be88bf1..a52688b26 100644 --- a/ruby/spec/jam_ruby/models/music_session_spec.rb +++ b/ruby/spec/jam_ruby/models/music_session_spec.rb @@ -1,467 +1,52 @@ 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) +describe MusicSession do - music_session.access?(user1).should == true - music_session.access?(user2).should == true - music_session.access?(user3).should == false - end + let(:creator) {FactoryGirl.create(:user)} + 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) } - 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 + 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 "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) + it "updates the fields of a music session properly" do 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 + genre3 = FactoryGirl.create(:genre) + genre4 = FactoryGirl.create(:genre) 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 + 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 "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 + 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 "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 - + 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 "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) - 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_false - 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 end + diff --git a/web/app/controllers/api_music_sessions_controller.rb b/web/app/controllers/api_music_sessions_controller.rb index 1f5929394..3ad4329df 100644 --- a/web/app/controllers/api_music_sessions_controller.rb +++ b/web/app/controllers/api_music_sessions_controller.rb @@ -60,6 +60,23 @@ class ApiMusicSessionsController < ApiController limit: params[:limit]) end + def create + client_id = params[:client_id] + + if client_id.nil? + raise JamArgumentError, 'client_id must be specified' + end + + @music_session = MusicSession.create(current_user, params) + + if @music_session.errors.any? + response.status = :unprocessable_entity + respond_with @music_session + else + respond_with @music_session, responder: ApiResponder + end + end + def create_legacy client_id = params[:client_id] diff --git a/web/app/views/api_music_sessions/create.rabl b/web/app/views/api_music_sessions/create.rabl index e34b6943d..c1fb2890c 100644 --- a/web/app/views/api_music_sessions/create.rabl +++ b/web/app/views/api_music_sessions/create.rabl @@ -1,3 +1 @@ -object @music_session - -extends "api_music_sessions/show" \ No newline at end of file +object @music_session \ No newline at end of file diff --git a/web/config/routes.rb b/web/config/routes.rb index 8842a6303..8be884f76 100644 --- a/web/config/routes.rb +++ b/web/config/routes.rb @@ -150,6 +150,7 @@ SampleApp::Application.routes.draw do match '/sessions/:id' => 'api_music_sessions#show', :via => :get, :as => 'api_session_detail' match '/sessions/:id' => 'api_music_sessions#update', :via => :put match '/sessions' => 'api_music_sessions#index', :via => :get + match '/sessions' => 'api_music_sessions#create', :via => :post match '/sessions/nindex/:client_id' => 'api_music_sessions#nindex', :via => :get match '/sessions/legacy' => 'api_music_sessions#create_legacy', :via => :post # can be removed when new Create Session comes in match '/sessions/:id/perf' => 'api_music_sessions#perf_upload', :via => :put diff --git a/web/spec/requests/active_music_sessions_api_spec.rb b/web/spec/requests/active_music_sessions_api_spec.rb new file mode 100755 index 000000000..f775b5051 --- /dev/null +++ b/web/spec/requests/active_music_sessions_api_spec.rb @@ -0,0 +1,730 @@ +require 'spec_helper' + +describe "Music Session API ", :type => :api do + + include Rack::Test::Methods + + subject { page } + + before(:each) do + ActiveMusicSession.delete_all + end + + def login(user) + post '/sessions', "session[email]" => user.email, "session[password]" => user.password + rack_mock_session.cookie_jar["remember_token"].should == user.remember_token + end + + def make_friends(user1, user2) + Friendship.save(user1, user2) + end + + describe "profile page" do + let(:user) { FactoryGirl.create(:user) } + + # defopts are used to setup default options for the session + let(:defopts) { { :description => "a session", :fan_chat => true, :fan_access => true, :approval_required => false, :genres => ["classical"], :musician_access => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}], :legal_terms => true, :intellectual_property => true} } + before do + #sign_in user + ActiveMusicSession.delete_all + + login(user) + end + + it "should list no sessions" do + get '/api/sessions.json' + last_response.body.should eql('[]') + end + + it "should create session" do + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # now fetch it's data + location_header = last_response.headers["Location"] + get location_header + music_session = JSON.parse(last_response.body) + + get '/api/sessions.json' + music_sessions = JSON.parse(last_response.body) + music_session = music_sessions[0] + music_session["id"].should == music_sessions[0]["id"] + music_session["musician_access"].should be_true + music_session["invitations"].should == [] + music_session["join_requests"].should == [] + music_session["approval_required"].should be_false + music_session["fan_chat"].should be_true + music_session["fan_access"].should be_true + music_session["participants"].length.should == 1 + participant = music_session["participants"][0] + participant["ip_address"].should == client.ip_address + participant["client_id"].should == client.client_id + participant["tracks"].length.should == 1 + track = participant["tracks"][0] + track["instrument_id"].should == "electric guitar" + track["sound"].should == "mono" + + # test session settings + get '/api/users/' + user.id + '/session_settings.json' + session_settings = JSON.parse(last_response.body) + session_settings["musician_access"].should be_true + session_settings["approval_required"].should be_false + session_settings["fan_chat"].should be_true + session_settings["fan_access"].should be_true + + # test session history + get '/api/users/' + user.id + '/session_history.json' + last_response.status.should == 200 + session_history = JSON.parse(last_response.body) + session_history[0]["user_id"].to_s.should == user.id + session_history[0]["band_id"].should == music_session["band_id"] + session_history[0]["description"].should == music_session["description"] + + get '/api/users/' + user.id + '/session_history/' + music_session["id"] + '/users.json' + + # test Track-specific APIs + get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + tracks = JSON.parse(last_response.body) + tracks.size.should == 1 + tracks[0]["instrument_id"].should == "electric guitar" + tracks[0]["sound"].should == "mono" + + # change instrument + post "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", { :instrument_id => "drums" }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + + # get individual track + get "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + updated_track = JSON.parse(last_response.body) + updated_track["instrument_id"].should == "drums" + updated_track["sound"].should == "mono" + + # change sound + post "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", { :sound => "stereo" }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + + # get individual track + get "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + updated_track = JSON.parse(last_response.body) + updated_track["instrument_id"].should == "drums" + updated_track["sound"].should == "stereo" + + # create a 2nd track for this session + conn_id = updated_track["connection_id"] + post "/api/sessions/#{music_session["id"]}/tracks.json", { :connection_id => "#{conn_id}", :instrument_id => "electric guitar", :sound => "mono", :client_track_id => "client_track_guid" }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should == 201 + + get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + tracks = JSON.parse(last_response.body) + tracks.size.should == 2 + + # invalid track ID + get "/api/sessions/#{music_session["id"]}/tracks/1234.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 404 + + # delete track + delete "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json" + last_response.status.should == 204 + + # get tracks again + get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + tracks = JSON.parse(last_response.body) + tracks.size.should == 1 + end + + + describe "update music session properties" do + + let(:user) { FactoryGirl.create(:user) } + let(:music_session) { music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") } + let(:client) { FactoryGirl.create(:connection, :user => user) } + + it "successful" do + put "/api/sessions/#{music_session.id}.json", {:description => "you!", :musician_access => false, :fan_chat => false, :fan_access => false, :approval_required => true}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' + updated_session = JSON.parse(last_response.body) + updated_session["description"].should == "you!" + updated_session["musician_access"].should be_false + updated_session["fan_chat"].should be_false + updated_session["fan_access"].should be_false + updated_session["approval_required"].should be_true + end + + it "string boolean value" do + put "/api/sessions/#{music_session.id}.json", {:musician_access => "false"}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' + updated_session = JSON.parse(last_response.body) + updated_session["musician_access"].should be_false + end + + + it "empty description not allowed" do + put "/api/sessions/#{music_session.id}.json", {:description => ""}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + end + + it "updated genres" do + put "/api/sessions/#{music_session.id}.json", {:genres => ["jazz"]}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' + updated_session = JSON.parse(last_response.body) + updated_session["genres"].should == ["Jazz"] + end + end + + + it "should add/remove member from session" do + # create the session + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # now fetch it's data + location_header = last_response.headers["Location"] + get location_header + ".json", "CONTENT_TYPE" => 'application/json' + + music_session = JSON.parse(last_response.body) + + # and the creator should be in the session + music_session["participants"].length.should == 1 + musician = music_session["participants"][0] + + # and that musician should have the same IP address + musician["ip_address"].should == client.ip_address + + # and that musician should have the correct IP address + musician["client_id"].should == client.client_id + + # now delete that musician + delete "/api/participants/#{musician["client_id"]}.json", '', "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + + # re-fetch the session now that there is not a musician; + # we auto-delete sessions when the last person leaves + get "/api/sessions/#{music_session["id"]}.json" + last_response.status.should eql(404) + end + + + it "should add a second member to the session" do + + user2 = FactoryGirl.create(:user) + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # now fetch it's data + music_session_uri = last_response.headers["Location"] + get music_session_uri + ".json", "CONTENT_TYPE" => 'application/json' + + music_session = JSON.parse(last_response.body) + + # and the creator should be in the session + music_session["participants"].length.should == 1 + musician = music_session["participants"][0] + # and should have tracks + musician["tracks"].length.should == 1 + musician["tracks"][0]["instrument_id"].should == 'electric guitar' + musician["tracks"][0]["sound"].should == 'mono' + musician["ip_address"].should == client.ip_address + musician["client_id"].should == client.client_id + + login(user2) + post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' + + last_response.status.should eql(201) + + # now fetch it's data + location_header = last_response.headers["Location"] + login(user2) + get location_header + ".json", "CONTENT_TYPE" => 'application/json' + + participant = JSON.parse(last_response.body) + + # and the creator should be in the session + # and should have tracks + participant["tracks"].length.should == 1 + participant["tracks"][0]["instrument_id"].should == 'bass guitar' + participant["tracks"][0]["sound"].should == 'mono' + participant["ip_address"].should == client2.ip_address + participant["client_id"].should == client2.client_id + + # refetch the session and make sure both participnats are accounted for + login(user2) + get music_session_uri + ".json", "CONTENT_TYPE" => 'application/json' + + music_session = JSON.parse(last_response.body) + # and the creator should be in the session + music_session["participants"].length.should == 2 + + login(user) + delete "/api/participants/#{client.client_id}.json", '', "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + login(user2) + delete "/api/participants/#{client2.client_id}.json", '', "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(204) + + # re-fetch the session now that there is not a musician; + # we auto-delete sessions when the last person leaves + login(user2) + get "/api/sessions/#{music_session["id"]}.json" + last_response.status.should eql(404) + end + + it "should error with no genre specified" do + # create the session + original_count = ActiveMusicSession.all().length + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :genres => nil}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + ActiveMusicSession.all().length.should == original_count + end + + it "should error with invalid genre specified" do + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({ :client_id => client.client_id, :genres => ["Junk"]}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + JSON.parse(last_response.body)["errors"]["genre"].should == ["can't be blank"] + end + + it "should error with no track specified" do + original_count = ActiveMusicSession.all().length + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => nil}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + JSON.parse(last_response.body)["errors"]["tracks"].should == [ValidationMessages::SELECT_AT_LEAST_ONE] + + # check that the transaction was rolled back + ActiveMusicSession.all().length.should == original_count + end + + it "should error with invalid track specified" do + original_count = ActiveMusicSession.all().length + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => [{"instrument_id" => "mom", "sound" => "mono", "client_track_id" => "client_track_guid"}]}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(404) + + # check that the transaction was rolled back + ActiveMusicSession.all().length.should == original_count + end + + it "should error with invalid sound specified" do + original_count = ActiveMusicSession.all().length + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mom", "client_track_id" => "client_track_guid"}]}).to_json, "CONTENT_TYPE" => 'application/json' + + last_response.status.should eql(422) + JSON.parse(last_response.body)["errors"]["tracks"][0].should == "is invalid" + + # check that the transaction was rolled back + ActiveMusicSession.all().length.should == original_count + end + + it "can see user_id of friend in session" do + pending + + # create the session + user2 = FactoryGirl.create(:user) # in the music session + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + session = JSON.parse(last_response.body) + + FactoryGirl.create(:friendship, :user => user, :friend => user2) + FactoryGirl.create(:friendship, :user => user2, :friend => user) + + login(user2) + get '/api/sessions.json' + last_response.status.should eql(200) + music_sessions = JSON.parse(last_response.body) + music_session = music_sessions[0] + + music_session["id"].should == session["id"] + music_session["musician_access"].should == false + music_session["invitations"].should == [] + music_session["participants"].length.should == 1 + participant = music_session["participants"][0] + participant["ip_address"].should == client.ip_address + participant["client_id"].should == client.client_id + participant["user"]["id"].should == user.id + end + + it "can see invitation_id associatied with hidden session" do + # create the session + user2 = FactoryGirl.create(:user) # in the music session + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + session = JSON.parse(last_response.body) + + FactoryGirl.create(:friendship, :user => user, :friend => user2) + FactoryGirl.create(:friendship, :user => user2, :friend => user) + invitation_model = FactoryGirl.create(:invitation, :sender => user, :receiver => user2, :music_session_id => session["id"] ) + + login(user2) + get '/api/sessions.json' + last_response.status.should eql(200) + music_sessions = JSON.parse(last_response.body) + music_session = music_sessions[0] + music_session["id"].should == session["id"] + music_session["musician_access"].should == false + + # we should be able to see the invitation + music_session["invitations"].length.should == 1 + invitation = music_session["invitations"][0] + invitation["id"].should == invitation_model.id + + music_session["participants"].length.should == 1 + participant = music_session["participants"][0] + participant["client_id"].should == client.client_id + + # and see the user_id because they are friends + participant["user"]["id"].should == user.id + end + + it "can't join closed music session with no invitation" do + # create the session + user2 = FactoryGirl.create(:user) # in the music session + + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "3") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + session = JSON.parse(last_response.body) + + client2 = FactoryGirl.create(:connection, :user => user2) + + FactoryGirl.create(:friendship, :user => user, :friend => user2) + FactoryGirl.create(:friendship, :user => user2, :friend => user) + + # users are friends, but no invitation... so we shouldn't be able to join as user 2 + login(user2) + post "/api/sessions/#{session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}] }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + join_response = JSON.parse(last_response.body) + join_response["errors"]["musician_access"].should == [ValidationMessages::INVITE_REQUIRED] + + # but let's make sure if we then invite, that we can then join' + login(user) + post '/api/invitations.json', { :music_session => session["id"], :receiver => user2.id }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + login(user2) + post "/api/sessions/#{session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}] }.to_json, "CONTENT_TYPE" => 'application/json' + + last_response.status.should eql(201) + end + + it "join_requests don't show up in session listing" do + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + location_header = last_response.headers["Location"] + get location_header + music_session = JSON.parse(last_response.body) + + get '/api/sessions.json' + music_sessions = JSON.parse(last_response.body) + + music_session = music_sessions[0] + music_session["id"].should == music_session["id"] + music_session["join_requests"].should == [] + + user2 = FactoryGirl.create(:user) # in the music session + + login(user2) + + # create join request + post '/api/join_requests.json', { :music_session => music_session["id"], :text => "lemme in" }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should == 201 + + location_header = last_response.headers["Location"] + login(user2) + get location_header + ".json", "CONTENT_TYPE" => 'application/json' + join_request = JSON.parse(last_response.body) + + # now join_requests should still be empty, because we don't share join_requests to people outside the session + login(user2) + get '/api/sessions.json' + music_sessions = JSON.parse(last_response.body) + + music_session = music_sessions[0] + music_session["id"].should == music_session["id"] + music_session["join_requests"].should be_nil + + login(user) + + # but for people in the session, they can see the join_requests! + get '/api/sessions.json' + music_sessions = JSON.parse(last_response.body) + + music_session = music_sessions[0] + music_session["id"].should == music_session["id"] + music_session["join_requests"].length.should == 1 + music_session["join_requests"][0]["id"].should == join_request["id"] + end + + it "should now allow join of approval_required=true session" do + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :approval_required => true}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # now fetch it's data + location_header = last_response.headers["Location"] + get location_header + music_session = JSON.parse(last_response.body) + + # try to add 2nd user to session - should fail because approval is required + user2 = FactoryGirl.create(:user) + client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2") + + login(user2) + post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + rejected_join_attempt = JSON.parse(last_response.body) + rejected_join_attempt["errors"]["approval_required"] = [ValidationMessages::INVITE_REQUIRED] + + # now send up a join_request to try and get in + login(user2) + post '/api/join_requests.json', { :music_session => music_session["id"], :text => "lemme in" }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should == 201 + + location_header = last_response.headers["Location"] + login(user2) + get location_header + ".json", "CONTENT_TYPE" => 'application/json' + join_request = JSON.parse(last_response.body) + + # pop back to user1 and allow user2 to get in + login(user) + post '/api/invitations.json', {:music_session => music_session["id"], :receiver => user2.id, :join_request => join_request["id"]}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # finally, go back to user2 and attempt to join again + login(user2) + post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + end + + + + it "should allow create session and join session for creator" do + # this test was created to stop duplication of tracks + # but ultimately it should be fine to create a session, and then 'join' it with no ill effects + # https://jamkazam.atlassian.net/browse/VRFS-254 + user.admin = true + client = FactoryGirl.create(:connection, :user => user) + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # now fetch it's data + location_header = last_response.headers["Location"] + get location_header + music_session = JSON.parse(last_response.body) + + get "/api/sessions/#{music_session["id"]}.json" + last_response.status.should eql(200) + music_session["participants"].length.should == 1 + participant = music_session["participants"][0] + participant["client_id"].should == client.client_id + participant["tracks"].length.should == 1 + track = participant["tracks"][0] + track["instrument_id"].should == "electric guitar" + track["sound"].should == "mono" + + post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client.client_id, :as_musician => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' + + last_response.status.should eql(201) + + get "/api/sessions/#{music_session["id"]}.json" + music_session = JSON.parse(last_response.body) + music_session["participants"].length.should == 1 + participant = music_session["participants"][0] + participant["client_id"].should == client.client_id + participant["tracks"].length.should == 1 # there should only be one track, still + track = participant["tracks"][0] + track["instrument_id"].should == "electric guitar" + track["sound"].should == "mono" + end + + it "can't join session that's recording" do + user = FactoryGirl.create(:user) + user2 = FactoryGirl.create(:user) + client = FactoryGirl.create(:connection, :user => user) + client2 = FactoryGirl.create(:connection, :user => user2) + instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') + track = FactoryGirl.create(:track, :connection => client, :instrument => instrument) + track2 = FactoryGirl.create(:track, :connection => client2, :instrument => instrument) + + # 1st user joins + login(user) + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' + location_header = last_response.headers["Location"] + get location_header + music_session = JSON.parse(last_response.body) + + # start a recording + post "/api/recordings/start", {:format => :json, :music_session_id => music_session['id'] }.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + + # user 2 should not be able to join + login(user2) + post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(422) + JSON.parse(last_response.body)["errors"]["music_session"][0].should == ValidationMessages::CANT_JOIN_RECORDING_SESSION + end + + it "shows mount info based on fan_access" do + # create the session + server = FactoryGirl.create(:icecast_server_minimal) + user2 = FactoryGirl.create(:user) # in the music session + client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.10", :client_id => "mount_info") + post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :fan_access => true}).to_json, "CONTENT_TYPE" => 'application/json' + last_response.status.should eql(201) + session = JSON.parse(last_response.body) + music_session = ActiveMusicSession.find(session["id"]) + session["mount"].should_not be_nil + session["mount"]["name"].should == music_session.mount.name + session["mount"]["listeners"].should == music_session.mount.listeners + session["mount"]["sourced"].should == music_session.mount.sourced + + # set gfan_access to false, which should cause the mount info to hide + music_session.music_session.fan_access = false + music_session.music_session.save! + + get "/api/sessions/#{session["id"]}.json" + last_response.status.should eql(200) + session = JSON.parse(last_response.body) + session["mount"].should be_nil + + end + + end + + it "Finds a single open session" do + creator = FactoryGirl.create(:user) + session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "My Session") + client = FactoryGirl.create(:connection, :user => creator, :music_session => session) + + user = FactoryGirl.create(:user) + login(user) + + get '/api/sessions', "CONTENT_TYPE" => "application/json" + last_response.status.should == 200 + sessions = JSON.parse(last_response.body) + sessions.length.should == 1 + sessions.first["description"].should == "My Session" + end + + it "prepare for perf data upload" do + user = FactoryGirl.create(:user) + client = FactoryGirl.create(:connection, :user => user) + music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") + msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id) + + put "/api/sessions/#{music_session.id}/perf.json?client_id=#{client.client_id}", "CONTENT_TYPE" => "application/json" + + last_response.status.should == 302 + redirect = last_response.headers["Location"] + + put redirect + '.json', "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + body = JSON.parse(last_response.body) + perf_data_id = body["id"] + + music_session_perf_data = MusicSessionPerfData.find(perf_data_id) + music_session_perf_data.should_not be_nil + music_session_perf_data.music_session_user_history.should == MusicSessionUserHistory.find_by_client_id(client.client_id) + end + + it "rating" do + user = FactoryGirl.create(:user) + client = FactoryGirl.create(:connection, :user => user) + music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") + msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id) + msuh.rating.should be_nil + login(user) + post "/api/participant_histories/#{msuh.client_id}/rating.json", { :rating => 1 }.to_json, "CONTENT_TYPE" => "application/json" + last_response.status.should == 200 + msuh.reload + msuh.rating.to_i.should == 1 + end + + it "track sync" do + pending "recording_session_landing broken tests" + user = FactoryGirl.create(:single_user_session) + instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') + music_session = FactoryGirl.create(:active_music_session, :creator => user) + client = FactoryGirl.create(:connection, :user => user, :music_session => music_session) + track = FactoryGirl.create(:track, :connection => client, :instrument => instrument) + + existing_track = {:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id } + new_track = {:client_track_id => "client_track_id1", :instrument_id => instrument.id, :sound => 'stereo'} + # let's add a new track, and leave the existing one alone + tracks = [existing_track, new_track] + login(user) + + put "/api/sessions/#{music_session.id}/tracks.json", { :client_id => client.client_id, :tracks => tracks }.to_json, "CONTENT_TYPE" => "application/json" + last_response.status.should == 204 + + get "/api/sessions/#{music_session.id}/tracks.json", "CONTENT_TYPE" => 'application/json' + last_response.status.should == 200 + tracks = JSON.parse(last_response.body) + tracks.size.should == 2 + tracks[0]["id"].should == track.id + tracks[0]["instrument_id"].should == instrument.id + tracks[0]["sound"].should == "mono" + tracks[0]["client_track_id"].should == track.client_track_id + tracks[1]["instrument_id"].should == instrument.id + tracks[1]["sound"].should == "stereo" + tracks[1]["client_track_id"].should == "client_track_id1" + end + + it "allows start/stop recording playback of a claimed recording" do + + user = FactoryGirl.create(:user) + connection = FactoryGirl.create(:connection, :user => user) + track = FactoryGirl.create(:track, :connection => connection, :instrument => Instrument.first) + music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true) + # music_session.connections << connection + music_session.save + connection.join_the_session(music_session, true, nil) + recording = Recording.start(music_session, user) + recording.stop + recording.reload + claimed_recording = recording.claim(user, "name", "description", Genre.first, true) + recording.reload + + login(user) + post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/start.json", {}.to_json, "CONTENT_TYPE" => "application/json" + + last_response.status.should == 201 + music_session.reload + music_session.claimed_recording.should == claimed_recording + music_session.claimed_recording_initiator.should == user + + post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/stop.json", {}.to_json, "CONTENT_TYPE" => "application/json" + + last_response.status.should == 201 + music_session.reload + music_session.claimed_recording.should be_nil + music_session.claimed_recording_initiator.should be_nil + end +end + + + + diff --git a/web/spec/requests/music_sessions_api_spec.rb b/web/spec/requests/music_sessions_api_spec.rb old mode 100755 new mode 100644 index f775b5051..d1475cf09 --- a/web/spec/requests/music_sessions_api_spec.rb +++ b/web/spec/requests/music_sessions_api_spec.rb @@ -1,730 +1,41 @@ require 'spec_helper' -describe "Music Session API ", :type => :api do +describe "Scheduled Music Session API ", :type => :api do include Rack::Test::Methods subject { page } before(:each) do - ActiveMusicSession.delete_all + MusicSession.delete_all end def login(user) - post '/sessions', "session[email]" => user.email, "session[password]" => user.password - rack_mock_session.cookie_jar["remember_token"].should == user.remember_token - end - - def make_friends(user1, user2) - Friendship.save(user1, user2) + post '/sessions', "session[email]" => user.email, "session[password]" => user.password + rack_mock_session.cookie_jar["remember_token"].should == user.remember_token end describe "profile page" do let(:user) { FactoryGirl.create(:user) } # defopts are used to setup default options for the session - let(:defopts) { { :description => "a session", :fan_chat => true, :fan_access => true, :approval_required => false, :genres => ["classical"], :musician_access => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}], :legal_terms => true, :intellectual_property => true} } + let(:defopts) { { :name => "session name", :description => "session description", + :genres => ["classical"], :musician_access => true, :approval_required => false, + :fan_chat => true, :fan_access => true, + :legal_policy => true, :language => 'english', + :timezone => "utc"} } + before do #sign_in user - ActiveMusicSession.delete_all + MusicSession.delete_all login(user) end - it "should list no sessions" do - get '/api/sessions.json' - last_response.body.should eql('[]') - end - it "should create session" do client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # now fetch it's data - location_header = last_response.headers["Location"] - get location_header - music_session = JSON.parse(last_response.body) - - get '/api/sessions.json' - music_sessions = JSON.parse(last_response.body) - music_session = music_sessions[0] - music_session["id"].should == music_sessions[0]["id"] - music_session["musician_access"].should be_true - music_session["invitations"].should == [] - music_session["join_requests"].should == [] - music_session["approval_required"].should be_false - music_session["fan_chat"].should be_true - music_session["fan_access"].should be_true - music_session["participants"].length.should == 1 - participant = music_session["participants"][0] - participant["ip_address"].should == client.ip_address - participant["client_id"].should == client.client_id - participant["tracks"].length.should == 1 - track = participant["tracks"][0] - track["instrument_id"].should == "electric guitar" - track["sound"].should == "mono" - - # test session settings - get '/api/users/' + user.id + '/session_settings.json' - session_settings = JSON.parse(last_response.body) - session_settings["musician_access"].should be_true - session_settings["approval_required"].should be_false - session_settings["fan_chat"].should be_true - session_settings["fan_access"].should be_true - - # test session history - get '/api/users/' + user.id + '/session_history.json' - last_response.status.should == 200 - session_history = JSON.parse(last_response.body) - session_history[0]["user_id"].to_s.should == user.id - session_history[0]["band_id"].should == music_session["band_id"] - session_history[0]["description"].should == music_session["description"] - - get '/api/users/' + user.id + '/session_history/' + music_session["id"] + '/users.json' - - # test Track-specific APIs - get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - tracks = JSON.parse(last_response.body) - tracks.size.should == 1 - tracks[0]["instrument_id"].should == "electric guitar" - tracks[0]["sound"].should == "mono" - - # change instrument - post "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", { :instrument_id => "drums" }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - - # get individual track - get "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - updated_track = JSON.parse(last_response.body) - updated_track["instrument_id"].should == "drums" - updated_track["sound"].should == "mono" - - # change sound - post "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", { :sound => "stereo" }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - - # get individual track - get "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - updated_track = JSON.parse(last_response.body) - updated_track["instrument_id"].should == "drums" - updated_track["sound"].should == "stereo" - - # create a 2nd track for this session - conn_id = updated_track["connection_id"] - post "/api/sessions/#{music_session["id"]}/tracks.json", { :connection_id => "#{conn_id}", :instrument_id => "electric guitar", :sound => "mono", :client_track_id => "client_track_guid" }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should == 201 - - get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - tracks = JSON.parse(last_response.body) - tracks.size.should == 2 - - # invalid track ID - get "/api/sessions/#{music_session["id"]}/tracks/1234.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 404 - - # delete track - delete "/api/sessions/#{music_session["id"]}/tracks/#{tracks[0]["id"]}.json" - last_response.status.should == 204 - - # get tracks again - get "/api/sessions/#{music_session["id"]}/tracks.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - tracks = JSON.parse(last_response.body) - tracks.size.should == 1 - end - - - describe "update music session properties" do - - let(:user) { FactoryGirl.create(:user) } - let(:music_session) { music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") } - let(:client) { FactoryGirl.create(:connection, :user => user) } - - it "successful" do - put "/api/sessions/#{music_session.id}.json", {:description => "you!", :musician_access => false, :fan_chat => false, :fan_access => false, :approval_required => true}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' - updated_session = JSON.parse(last_response.body) - updated_session["description"].should == "you!" - updated_session["musician_access"].should be_false - updated_session["fan_chat"].should be_false - updated_session["fan_access"].should be_false - updated_session["approval_required"].should be_true - end - - it "string boolean value" do - put "/api/sessions/#{music_session.id}.json", {:musician_access => "false"}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' - updated_session = JSON.parse(last_response.body) - updated_session["musician_access"].should be_false - end - - - it "empty description not allowed" do - put "/api/sessions/#{music_session.id}.json", {:description => ""}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - end - - it "updated genres" do - put "/api/sessions/#{music_session.id}.json", {:genres => ["jazz"]}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - get "/api/sessions/#{music_session.id}.json", "CONTENT_TYPE" => 'application/json' - updated_session = JSON.parse(last_response.body) - updated_session["genres"].should == ["Jazz"] - end - end - - - it "should add/remove member from session" do - # create the session - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # now fetch it's data - location_header = last_response.headers["Location"] - get location_header + ".json", "CONTENT_TYPE" => 'application/json' - - music_session = JSON.parse(last_response.body) - - # and the creator should be in the session - music_session["participants"].length.should == 1 - musician = music_session["participants"][0] - - # and that musician should have the same IP address - musician["ip_address"].should == client.ip_address - - # and that musician should have the correct IP address - musician["client_id"].should == client.client_id - - # now delete that musician - delete "/api/participants/#{musician["client_id"]}.json", '', "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - - # re-fetch the session now that there is not a musician; - # we auto-delete sessions when the last person leaves - get "/api/sessions/#{music_session["id"]}.json" - last_response.status.should eql(404) - end - - - it "should add a second member to the session" do - - user2 = FactoryGirl.create(:user) - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # now fetch it's data - music_session_uri = last_response.headers["Location"] - get music_session_uri + ".json", "CONTENT_TYPE" => 'application/json' - - music_session = JSON.parse(last_response.body) - - # and the creator should be in the session - music_session["participants"].length.should == 1 - musician = music_session["participants"][0] - # and should have tracks - musician["tracks"].length.should == 1 - musician["tracks"][0]["instrument_id"].should == 'electric guitar' - musician["tracks"][0]["sound"].should == 'mono' - musician["ip_address"].should == client.ip_address - musician["client_id"].should == client.client_id - - login(user2) - post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' - - last_response.status.should eql(201) - - # now fetch it's data - location_header = last_response.headers["Location"] - login(user2) - get location_header + ".json", "CONTENT_TYPE" => 'application/json' - - participant = JSON.parse(last_response.body) - - # and the creator should be in the session - # and should have tracks - participant["tracks"].length.should == 1 - participant["tracks"][0]["instrument_id"].should == 'bass guitar' - participant["tracks"][0]["sound"].should == 'mono' - participant["ip_address"].should == client2.ip_address - participant["client_id"].should == client2.client_id - - # refetch the session and make sure both participnats are accounted for - login(user2) - get music_session_uri + ".json", "CONTENT_TYPE" => 'application/json' - - music_session = JSON.parse(last_response.body) - # and the creator should be in the session - music_session["participants"].length.should == 2 - - login(user) - delete "/api/participants/#{client.client_id}.json", '', "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - login(user2) - delete "/api/participants/#{client2.client_id}.json", '', "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(204) - - # re-fetch the session now that there is not a musician; - # we auto-delete sessions when the last person leaves - login(user2) - get "/api/sessions/#{music_session["id"]}.json" - last_response.status.should eql(404) - end - - it "should error with no genre specified" do - # create the session - original_count = ActiveMusicSession.all().length - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :genres => nil}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - ActiveMusicSession.all().length.should == original_count - end - - it "should error with invalid genre specified" do - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({ :client_id => client.client_id, :genres => ["Junk"]}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - JSON.parse(last_response.body)["errors"]["genre"].should == ["can't be blank"] - end - - it "should error with no track specified" do - original_count = ActiveMusicSession.all().length - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => nil}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - JSON.parse(last_response.body)["errors"]["tracks"].should == [ValidationMessages::SELECT_AT_LEAST_ONE] - - # check that the transaction was rolled back - ActiveMusicSession.all().length.should == original_count - end - - it "should error with invalid track specified" do - original_count = ActiveMusicSession.all().length - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => [{"instrument_id" => "mom", "sound" => "mono", "client_track_id" => "client_track_guid"}]}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(404) - - # check that the transaction was rolled back - ActiveMusicSession.all().length.should == original_count - end - - it "should error with invalid sound specified" do - original_count = ActiveMusicSession.all().length - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mom", "client_track_id" => "client_track_guid"}]}).to_json, "CONTENT_TYPE" => 'application/json' - - last_response.status.should eql(422) - JSON.parse(last_response.body)["errors"]["tracks"][0].should == "is invalid" - - # check that the transaction was rolled back - ActiveMusicSession.all().length.should == original_count - end - - it "can see user_id of friend in session" do - pending - - # create the session - user2 = FactoryGirl.create(:user) # in the music session - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - session = JSON.parse(last_response.body) - - FactoryGirl.create(:friendship, :user => user, :friend => user2) - FactoryGirl.create(:friendship, :user => user2, :friend => user) - - login(user2) - get '/api/sessions.json' - last_response.status.should eql(200) - music_sessions = JSON.parse(last_response.body) - music_session = music_sessions[0] - - music_session["id"].should == session["id"] - music_session["musician_access"].should == false - music_session["invitations"].should == [] - music_session["participants"].length.should == 1 - participant = music_session["participants"][0] - participant["ip_address"].should == client.ip_address - participant["client_id"].should == client.client_id - participant["user"]["id"].should == user.id - end - - it "can see invitation_id associatied with hidden session" do - # create the session - user2 = FactoryGirl.create(:user) # in the music session - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - session = JSON.parse(last_response.body) - - FactoryGirl.create(:friendship, :user => user, :friend => user2) - FactoryGirl.create(:friendship, :user => user2, :friend => user) - invitation_model = FactoryGirl.create(:invitation, :sender => user, :receiver => user2, :music_session_id => session["id"] ) - - login(user2) - get '/api/sessions.json' - last_response.status.should eql(200) - music_sessions = JSON.parse(last_response.body) - music_session = music_sessions[0] - music_session["id"].should == session["id"] - music_session["musician_access"].should == false - - # we should be able to see the invitation - music_session["invitations"].length.should == 1 - invitation = music_session["invitations"][0] - invitation["id"].should == invitation_model.id - - music_session["participants"].length.should == 1 - participant = music_session["participants"][0] - participant["client_id"].should == client.client_id - - # and see the user_id because they are friends - participant["user"]["id"].should == user.id - end - - it "can't join closed music session with no invitation" do - # create the session - user2 = FactoryGirl.create(:user) # in the music session - - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "3") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :musician_access => false}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - session = JSON.parse(last_response.body) - - client2 = FactoryGirl.create(:connection, :user => user2) - - FactoryGirl.create(:friendship, :user => user, :friend => user2) - FactoryGirl.create(:friendship, :user => user2, :friend => user) - - # users are friends, but no invitation... so we shouldn't be able to join as user 2 - login(user2) - post "/api/sessions/#{session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}] }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - join_response = JSON.parse(last_response.body) - join_response["errors"]["musician_access"].should == [ValidationMessages::INVITE_REQUIRED] - - # but let's make sure if we then invite, that we can then join' - login(user) - post '/api/invitations.json', { :music_session => session["id"], :receiver => user2.id }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - login(user2) - post "/api/sessions/#{session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}] }.to_json, "CONTENT_TYPE" => 'application/json' - + post '/api/sessions.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' last_response.status.should eql(201) end - - it "join_requests don't show up in session listing" do - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - location_header = last_response.headers["Location"] - get location_header - music_session = JSON.parse(last_response.body) - - get '/api/sessions.json' - music_sessions = JSON.parse(last_response.body) - - music_session = music_sessions[0] - music_session["id"].should == music_session["id"] - music_session["join_requests"].should == [] - - user2 = FactoryGirl.create(:user) # in the music session - - login(user2) - - # create join request - post '/api/join_requests.json', { :music_session => music_session["id"], :text => "lemme in" }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should == 201 - - location_header = last_response.headers["Location"] - login(user2) - get location_header + ".json", "CONTENT_TYPE" => 'application/json' - join_request = JSON.parse(last_response.body) - - # now join_requests should still be empty, because we don't share join_requests to people outside the session - login(user2) - get '/api/sessions.json' - music_sessions = JSON.parse(last_response.body) - - music_session = music_sessions[0] - music_session["id"].should == music_session["id"] - music_session["join_requests"].should be_nil - - login(user) - - # but for people in the session, they can see the join_requests! - get '/api/sessions.json' - music_sessions = JSON.parse(last_response.body) - - music_session = music_sessions[0] - music_session["id"].should == music_session["id"] - music_session["join_requests"].length.should == 1 - music_session["join_requests"][0]["id"].should == join_request["id"] - end - - it "should now allow join of approval_required=true session" do - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :approval_required => true}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # now fetch it's data - location_header = last_response.headers["Location"] - get location_header - music_session = JSON.parse(last_response.body) - - # try to add 2nd user to session - should fail because approval is required - user2 = FactoryGirl.create(:user) - client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2") - - login(user2) - post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - rejected_join_attempt = JSON.parse(last_response.body) - rejected_join_attempt["errors"]["approval_required"] = [ValidationMessages::INVITE_REQUIRED] - - # now send up a join_request to try and get in - login(user2) - post '/api/join_requests.json', { :music_session => music_session["id"], :text => "lemme in" }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should == 201 - - location_header = last_response.headers["Location"] - login(user2) - get location_header + ".json", "CONTENT_TYPE" => 'application/json' - join_request = JSON.parse(last_response.body) - - # pop back to user1 and allow user2 to get in - login(user) - post '/api/invitations.json', {:music_session => music_session["id"], :receiver => user2.id, :join_request => join_request["id"]}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # finally, go back to user2 and attempt to join again - login(user2) - post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - end - - - - it "should allow create session and join session for creator" do - # this test was created to stop duplication of tracks - # but ultimately it should be fine to create a session, and then 'join' it with no ill effects - # https://jamkazam.atlassian.net/browse/VRFS-254 - user.admin = true - client = FactoryGirl.create(:connection, :user => user) - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # now fetch it's data - location_header = last_response.headers["Location"] - get location_header - music_session = JSON.parse(last_response.body) - - get "/api/sessions/#{music_session["id"]}.json" - last_response.status.should eql(200) - music_session["participants"].length.should == 1 - participant = music_session["participants"][0] - participant["client_id"].should == client.client_id - participant["tracks"].length.should == 1 - track = participant["tracks"][0] - track["instrument_id"].should == "electric guitar" - track["sound"].should == "mono" - - post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client.client_id, :as_musician => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' - - last_response.status.should eql(201) - - get "/api/sessions/#{music_session["id"]}.json" - music_session = JSON.parse(last_response.body) - music_session["participants"].length.should == 1 - participant = music_session["participants"][0] - participant["client_id"].should == client.client_id - participant["tracks"].length.should == 1 # there should only be one track, still - track = participant["tracks"][0] - track["instrument_id"].should == "electric guitar" - track["sound"].should == "mono" - end - - it "can't join session that's recording" do - user = FactoryGirl.create(:user) - user2 = FactoryGirl.create(:user) - client = FactoryGirl.create(:connection, :user => user) - client2 = FactoryGirl.create(:connection, :user => user2) - instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') - track = FactoryGirl.create(:track, :connection => client, :instrument => instrument) - track2 = FactoryGirl.create(:track, :connection => client2, :instrument => instrument) - - # 1st user joins - login(user) - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json' - location_header = last_response.headers["Location"] - get location_header - music_session = JSON.parse(last_response.body) - - # start a recording - post "/api/recordings/start", {:format => :json, :music_session_id => music_session['id'] }.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - - # user 2 should not be able to join - login(user2) - post "/api/sessions/#{music_session["id"]}/participants/legacy.json", { :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(422) - JSON.parse(last_response.body)["errors"]["music_session"][0].should == ValidationMessages::CANT_JOIN_RECORDING_SESSION - end - - it "shows mount info based on fan_access" do - # create the session - server = FactoryGirl.create(:icecast_server_minimal) - user2 = FactoryGirl.create(:user) # in the music session - client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.10", :client_id => "mount_info") - post '/api/sessions/legacy.json', defopts.merge({:client_id => client.client_id, :fan_access => true}).to_json, "CONTENT_TYPE" => 'application/json' - last_response.status.should eql(201) - session = JSON.parse(last_response.body) - music_session = ActiveMusicSession.find(session["id"]) - session["mount"].should_not be_nil - session["mount"]["name"].should == music_session.mount.name - session["mount"]["listeners"].should == music_session.mount.listeners - session["mount"]["sourced"].should == music_session.mount.sourced - - # set gfan_access to false, which should cause the mount info to hide - music_session.music_session.fan_access = false - music_session.music_session.save! - - get "/api/sessions/#{session["id"]}.json" - last_response.status.should eql(200) - session = JSON.parse(last_response.body) - session["mount"].should be_nil - - end - end - - it "Finds a single open session" do - creator = FactoryGirl.create(:user) - session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "My Session") - client = FactoryGirl.create(:connection, :user => creator, :music_session => session) - - user = FactoryGirl.create(:user) - login(user) - - get '/api/sessions', "CONTENT_TYPE" => "application/json" - last_response.status.should == 200 - sessions = JSON.parse(last_response.body) - sessions.length.should == 1 - sessions.first["description"].should == "My Session" - end - - it "prepare for perf data upload" do - user = FactoryGirl.create(:user) - client = FactoryGirl.create(:connection, :user => user) - music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") - msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id) - - put "/api/sessions/#{music_session.id}/perf.json?client_id=#{client.client_id}", "CONTENT_TYPE" => "application/json" - - last_response.status.should == 302 - redirect = last_response.headers["Location"] - - put redirect + '.json', "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - body = JSON.parse(last_response.body) - perf_data_id = body["id"] - - music_session_perf_data = MusicSessionPerfData.find(perf_data_id) - music_session_perf_data.should_not be_nil - music_session_perf_data.music_session_user_history.should == MusicSessionUserHistory.find_by_client_id(client.client_id) - end - - it "rating" do - user = FactoryGirl.create(:user) - client = FactoryGirl.create(:connection, :user => user) - music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session") - msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id) - msuh.rating.should be_nil - login(user) - post "/api/participant_histories/#{msuh.client_id}/rating.json", { :rating => 1 }.to_json, "CONTENT_TYPE" => "application/json" - last_response.status.should == 200 - msuh.reload - msuh.rating.to_i.should == 1 - end - - it "track sync" do - pending "recording_session_landing broken tests" - user = FactoryGirl.create(:single_user_session) - instrument = FactoryGirl.create(:instrument, :description => 'a great instrument') - music_session = FactoryGirl.create(:active_music_session, :creator => user) - client = FactoryGirl.create(:connection, :user => user, :music_session => music_session) - track = FactoryGirl.create(:track, :connection => client, :instrument => instrument) - - existing_track = {:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id } - new_track = {:client_track_id => "client_track_id1", :instrument_id => instrument.id, :sound => 'stereo'} - # let's add a new track, and leave the existing one alone - tracks = [existing_track, new_track] - login(user) - - put "/api/sessions/#{music_session.id}/tracks.json", { :client_id => client.client_id, :tracks => tracks }.to_json, "CONTENT_TYPE" => "application/json" - last_response.status.should == 204 - - get "/api/sessions/#{music_session.id}/tracks.json", "CONTENT_TYPE" => 'application/json' - last_response.status.should == 200 - tracks = JSON.parse(last_response.body) - tracks.size.should == 2 - tracks[0]["id"].should == track.id - tracks[0]["instrument_id"].should == instrument.id - tracks[0]["sound"].should == "mono" - tracks[0]["client_track_id"].should == track.client_track_id - tracks[1]["instrument_id"].should == instrument.id - tracks[1]["sound"].should == "stereo" - tracks[1]["client_track_id"].should == "client_track_id1" - end - - it "allows start/stop recording playback of a claimed recording" do - - user = FactoryGirl.create(:user) - connection = FactoryGirl.create(:connection, :user => user) - track = FactoryGirl.create(:track, :connection => connection, :instrument => Instrument.first) - music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true) - # music_session.connections << connection - music_session.save - connection.join_the_session(music_session, true, nil) - recording = Recording.start(music_session, user) - recording.stop - recording.reload - claimed_recording = recording.claim(user, "name", "description", Genre.first, true) - recording.reload - - login(user) - post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/start.json", {}.to_json, "CONTENT_TYPE" => "application/json" - - last_response.status.should == 201 - music_session.reload - music_session.claimed_recording.should == claimed_recording - music_session.claimed_recording_initiator.should == user - - post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/stop.json", {}.to_json, "CONTENT_TYPE" => "application/json" - - last_response.status.should == 201 - music_session.reload - music_session.claimed_recording.should be_nil - music_session.claimed_recording_initiator.should be_nil - end -end - - - - +end \ No newline at end of file