adhearsion 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +3 -3
- data/CHANGELOG.md +29 -0
- data/Gemfile +0 -2
- data/Guardfile +2 -2
- data/README.markdown +3 -6
- data/Rakefile +1 -1
- data/adhearsion.gemspec +7 -2
- data/features/cli_create.feature +85 -7
- data/features/plugin_generator.feature +4 -0
- data/features/step_definitions/app_generator_steps.rb +8 -1
- data/lib/adhearsion.rb +6 -3
- data/lib/adhearsion/call.rb +101 -30
- data/lib/adhearsion/call_controller.rb +40 -12
- data/lib/adhearsion/call_controller/dial.rb +119 -36
- data/lib/adhearsion/call_controller/input.rb +11 -5
- data/lib/adhearsion/call_controller/output.rb +47 -33
- data/lib/adhearsion/call_controller/output/async_player.rb +3 -2
- data/lib/adhearsion/call_controller/output/formatter.rb +7 -2
- data/lib/adhearsion/call_controller/output/player.rb +2 -2
- data/lib/adhearsion/call_controller/record.rb +16 -13
- data/lib/adhearsion/call_controller/utility.rb +3 -3
- data/lib/adhearsion/calls.rb +21 -8
- data/lib/adhearsion/cli_commands/ahn_command.rb +1 -0
- data/lib/adhearsion/configuration.rb +2 -2
- data/lib/adhearsion/console.rb +3 -2
- data/lib/adhearsion/generators.rb +7 -9
- data/lib/adhearsion/generators/app/app_generator.rb +12 -2
- data/lib/adhearsion/generators/app/templates/Gemfile.erb +7 -9
- data/lib/adhearsion/generators/app/templates/README.md +0 -19
- data/lib/adhearsion/generators/app/templates/adhearsion.erb +37 -0
- data/lib/adhearsion/generators/app/templates/config/environment.rb +6 -1
- data/lib/adhearsion/generators/app/templates/events.erb +18 -0
- data/lib/adhearsion/generators/app/templates/routes.erb +19 -0
- data/lib/adhearsion/generators/app/templates/{lib/simon_game.rb → simon_game.rb} +0 -0
- data/lib/adhearsion/generators/app/templates/{spec/call_controllers/simon_game_spec.rb → simon_game_spec.rb} +0 -0
- data/lib/adhearsion/generators/controller/controller_generator.rb +2 -2
- data/lib/adhearsion/generators/controller/templates/lib/{controller.rb → controller.rb.erb} +0 -0
- data/lib/adhearsion/generators/controller/templates/spec/{controller_spec.rb → controller_spec.rb.erb} +0 -0
- data/lib/adhearsion/generators/plugin/plugin_generator.rb +16 -15
- data/lib/adhearsion/generators/plugin/templates/gitignore +17 -0
- data/lib/adhearsion/generators/plugin/templates/spec/plugin-template/controller_methods_spec.rb.tt +1 -1
- data/lib/adhearsion/initializer.rb +14 -2
- data/lib/adhearsion/logging.rb +1 -0
- data/lib/adhearsion/outbound_call.rb +3 -7
- data/lib/adhearsion/punchblock_plugin/initializer.rb +3 -2
- data/lib/adhearsion/router/openended_route.rb +1 -1
- data/lib/adhearsion/router/route.rb +4 -3
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/dial_spec.rb +811 -79
- data/spec/adhearsion/call_controller/output/formatter_spec.rb +13 -1
- data/spec/adhearsion/call_controller/output_spec.rb +35 -1
- data/spec/adhearsion/call_controller_spec.rb +174 -18
- data/spec/adhearsion/call_spec.rb +423 -39
- data/spec/adhearsion/calls_spec.rb +19 -3
- data/spec/adhearsion/outbound_call_spec.rb +88 -45
- data/spec/adhearsion/punchblock_plugin/initializer_spec.rb +3 -3
- data/spec/adhearsion/router/route_spec.rb +2 -2
- data/spec/spec_helper.rb +2 -0
- metadata +92 -77
- data/features/app_generator.feature +0 -49
- data/lib/adhearsion/generators/app/templates/config/adhearsion.rb +0 -71
- data/lib/adhearsion/generators/plugin/templates/.gitignore +0 -9
| @@ -24,15 +24,17 @@ module Adhearsion | |
| 24 24 | 
             
                    end
         | 
| 25 25 |  | 
| 26 26 | 
             
                    describe "#ssml_for_collection" do
         | 
| 27 | 
            -
                      let(:collection) { ["/foo/bar.wav", 1, Time.now] }
         | 
| 27 | 
            +
                      let(:collection) { ["/foo/bar.wav", 1, Time.now, '123*'] }
         | 
| 28 28 | 
             
                      let :ssml do
         | 
| 29 29 | 
             
                        file = collection[0]
         | 
| 30 30 | 
             
                        n = collection[1].to_s
         | 
| 31 31 | 
             
                        t = collection[2].to_s
         | 
| 32 | 
            +
                        c = collection[3].to_s
         | 
| 32 33 | 
             
                        RubySpeech::SSML.draw do
         | 
| 33 34 | 
             
                          audio :src => file
         | 
| 34 35 | 
             
                          say_as(:interpret_as => 'cardinal') { n }
         | 
| 35 36 | 
             
                          say_as(:interpret_as => 'time') { t }
         | 
| 37 | 
            +
                          say_as(:interpret_as => 'characters') { c }
         | 
| 36 38 | 
             
                        end
         | 
| 37 39 | 
             
                      end
         | 
| 38 40 |  | 
| @@ -78,6 +80,16 @@ module Adhearsion | |
| 78 80 | 
             
                        subject.detect_type(number).should be :numeric
         | 
| 79 81 | 
             
                      end
         | 
| 80 82 |  | 
| 83 | 
            +
                      it "detects a String of digits" do
         | 
| 84 | 
            +
                        number = '123'
         | 
| 85 | 
            +
                        subject.detect_type(number).should be :numeric
         | 
| 86 | 
            +
                      end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      it "detects a String of characters" do
         | 
| 89 | 
            +
                        number = '123#'
         | 
| 90 | 
            +
                        subject.detect_type(number).should be :characters
         | 
| 91 | 
            +
                      end
         | 
| 92 | 
            +
             | 
| 81 93 | 
             
                      ["Foo", "Foo bar", "The answer: foo", "The answer could be foo/bar"].each do |string|
         | 
| 82 94 | 
             
                        it "detects '#{string}' as text" do
         | 
| 83 95 | 
             
                          subject.detect_type(string).should be :text
         | 
| @@ -338,6 +338,13 @@ module Adhearsion | |
| 338 338 | 
             
                    let(:extra_options) do
         | 
| 339 339 | 
             
                      { renderer: :native }
         | 
| 340 340 | 
             
                    end
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                    describe "with a nil argument" do
         | 
| 343 | 
            +
                      it "is a noop" do
         | 
| 344 | 
            +
                        subject.play nil
         | 
| 345 | 
            +
                      end
         | 
| 346 | 
            +
                    end
         | 
| 347 | 
            +
             | 
| 341 348 | 
             
                    describe "with a single string" do
         | 
| 342 349 | 
             
                      let(:audio_file) { "/foo/bar.wav" }
         | 
| 343 350 | 
             
                      let :ssml do
         | 
| @@ -357,15 +364,17 @@ module Adhearsion | |
| 357 364 | 
             
                    end
         | 
| 358 365 |  | 
| 359 366 | 
             
                    describe "with multiple arguments" do
         | 
| 360 | 
            -
                      let(:args) { ["/foo/bar.wav", 1, Time.now] }
         | 
| 367 | 
            +
                      let(:args) { ["/foo/bar.wav", 1, Time.now, "123#"] }
         | 
| 361 368 | 
             
                      let :ssml do
         | 
| 362 369 | 
             
                        file = args[0]
         | 
| 363 370 | 
             
                        n = args[1].to_s
         | 
| 364 371 | 
             
                        t = args[2].to_s
         | 
| 372 | 
            +
                        c = args[3].to_s
         | 
| 365 373 | 
             
                        RubySpeech::SSML.draw do
         | 
| 366 374 | 
             
                          audio :src => file
         | 
| 367 375 | 
             
                          say_as(:interpret_as => 'cardinal') { n }
         | 
| 368 376 | 
             
                          say_as(:interpret_as => 'time') { t }
         | 
| 377 | 
            +
                          say_as(:interpret_as => 'characters') { c }
         | 
| 369 378 | 
             
                        end
         | 
| 370 379 | 
             
                      end
         | 
| 371 380 |  | 
| @@ -398,6 +407,12 @@ module Adhearsion | |
| 398 407 | 
             
                        expect_ssml_output ssml
         | 
| 399 408 | 
             
                        subject.play(args).should be true
         | 
| 400 409 | 
             
                      end
         | 
| 410 | 
            +
             | 
| 411 | 
            +
                      context "that is empty" do
         | 
| 412 | 
            +
                        it "is a noop" do
         | 
| 413 | 
            +
                          subject.play []
         | 
| 414 | 
            +
                        end
         | 
| 415 | 
            +
                      end
         | 
| 401 416 | 
             
                    end
         | 
| 402 417 |  | 
| 403 418 | 
             
                    describe "with a number" do
         | 
| @@ -496,6 +511,13 @@ module Adhearsion | |
| 496 511 | 
             
                    let(:extra_options) do
         | 
| 497 512 | 
             
                      { renderer: :native }
         | 
| 498 513 | 
             
                    end
         | 
| 514 | 
            +
             | 
| 515 | 
            +
                    describe "with a nil argument" do
         | 
| 516 | 
            +
                      it "is a noop" do
         | 
| 517 | 
            +
                        subject.play! nil
         | 
| 518 | 
            +
                      end
         | 
| 519 | 
            +
                    end
         | 
| 520 | 
            +
             | 
| 499 521 | 
             
                    describe "with a single string" do
         | 
| 500 522 | 
             
                      let(:audio_file) { "/foo/bar.wav" }
         | 
| 501 523 | 
             
                      let :ssml do
         | 
| @@ -731,6 +753,12 @@ module Adhearsion | |
| 731 753 | 
             
                  end
         | 
| 732 754 |  | 
| 733 755 | 
             
                  describe "#say" do
         | 
| 756 | 
            +
                    describe "with a nil argument" do
         | 
| 757 | 
            +
                      it "is a no-op" do
         | 
| 758 | 
            +
                        subject.say nil
         | 
| 759 | 
            +
                      end
         | 
| 760 | 
            +
                    end
         | 
| 761 | 
            +
             | 
| 734 762 | 
             
                    describe "with a RubySpeech document" do
         | 
| 735 763 | 
             
                      it 'plays the correct SSML' do
         | 
| 736 764 | 
             
                        ssml = RubySpeech::SSML.draw { string "Hello world" }
         | 
| @@ -829,6 +857,12 @@ module Adhearsion | |
| 829 857 | 
             
                  end
         | 
| 830 858 |  | 
| 831 859 | 
             
                  describe "#say!" do
         | 
| 860 | 
            +
                    describe "with a nil argument" do
         | 
| 861 | 
            +
                      it "is a noop" do
         | 
| 862 | 
            +
                        subject.say! nil
         | 
| 863 | 
            +
                      end
         | 
| 864 | 
            +
                    end
         | 
| 865 | 
            +
             | 
| 832 866 | 
             
                    describe "with a RubySpeech document" do
         | 
| 833 867 | 
             
                      it 'plays the correct SSML' do
         | 
| 834 868 | 
             
                        ssml = RubySpeech::SSML.draw { string "Hello world" }
         | 
| @@ -28,6 +28,13 @@ module Adhearsion | |
| 28 28 | 
             
                its(:logger)    { should be call.logger }
         | 
| 29 29 | 
             
                its(:variables) { should be call.variables }
         | 
| 30 30 |  | 
| 31 | 
            +
                describe "#send_message" do
         | 
| 32 | 
            +
                  it 'should send a message' do
         | 
| 33 | 
            +
                    call.should_receive(:send_message).with("Hello World!").once
         | 
| 34 | 
            +
                    subject.send_message "Hello World!"
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 31 38 | 
             
                context "when the call is dead" do
         | 
| 32 39 | 
             
                  before { call.terminate }
         | 
| 33 40 |  | 
| @@ -49,6 +56,17 @@ module Adhearsion | |
| 49 56 | 
             
                    subject.execute!
         | 
| 50 57 | 
             
                  end
         | 
| 51 58 |  | 
| 59 | 
            +
                  context "when trying to execute a command against a dead call" do
         | 
| 60 | 
            +
                    before do
         | 
| 61 | 
            +
                      subject.should_receive(:run).once.ordered.and_raise(Call::ExpiredError)
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    it "gracefully terminates " do
         | 
| 65 | 
            +
                      subject.logger.should_receive(:info).once.with(/Call was hung up/).ordered
         | 
| 66 | 
            +
                      subject.execute!
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 52 70 | 
             
                  it "catches standard errors, triggering an exception event" do
         | 
| 53 71 | 
             
                    subject.should_receive(:run).once.ordered.and_raise(StandardError)
         | 
| 54 72 | 
             
                    latch = CountDownLatch.new 1
         | 
| @@ -165,26 +183,28 @@ module Adhearsion | |
| 165 183 | 
             
                end
         | 
| 166 184 |  | 
| 167 185 | 
             
                describe "#pass" do
         | 
| 168 | 
            -
                   | 
| 169 | 
            -
                     | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
                       | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 186 | 
            +
                  let(:pass_controller) do
         | 
| 187 | 
            +
                    Class.new CallController do
         | 
| 188 | 
            +
                      after_call :foobar
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                      def run
         | 
| 191 | 
            +
                        before
         | 
| 192 | 
            +
                        pass SecondController, :foo => 'bar'
         | 
| 193 | 
            +
                        after
         | 
| 194 | 
            +
                      end
         | 
| 176 195 |  | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 196 | 
            +
                      def before
         | 
| 197 | 
            +
                      end
         | 
| 179 198 |  | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 199 | 
            +
                      def after
         | 
| 200 | 
            +
                      end
         | 
| 182 201 |  | 
| 183 | 
            -
             | 
| 202 | 
            +
                      def foobar
         | 
| 203 | 
            +
                      end
         | 
| 184 204 | 
             
                    end
         | 
| 185 205 | 
             
                  end
         | 
| 186 206 |  | 
| 187 | 
            -
                  subject {  | 
| 207 | 
            +
                  subject { pass_controller.new call }
         | 
| 188 208 |  | 
| 189 209 | 
             
                  before do
         | 
| 190 210 | 
             
                    call.wrapped_object.stub :write_and_await_response => nil
         | 
| @@ -211,6 +231,142 @@ module Adhearsion | |
| 211 231 | 
             
                  end
         | 
| 212 232 | 
             
                end
         | 
| 213 233 |  | 
| 234 | 
            +
                describe "#hard_pass" do
         | 
| 235 | 
            +
                  let(:pass_controller) do
         | 
| 236 | 
            +
                    Class.new CallController do
         | 
| 237 | 
            +
                      def run
         | 
| 238 | 
            +
                        hard_pass SecondController, foo: 'bar'
         | 
| 239 | 
            +
                      end
         | 
| 240 | 
            +
                    end
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                  subject { pass_controller.new call }
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                  before do
         | 
| 246 | 
            +
                    call.wrapped_object.stub(:write_and_await_response).and_return do |command|
         | 
| 247 | 
            +
                      command.request!
         | 
| 248 | 
            +
                      command.execute!
         | 
| 249 | 
            +
                    end
         | 
| 250 | 
            +
                    call.stub register_controller: nil
         | 
| 251 | 
            +
                    SecondController.any_instance.should_receive(:md_check).once.with :foo => 'bar'
         | 
| 252 | 
            +
                    Events.should_receive(:trigger).with(:exception, Exception).never
         | 
| 253 | 
            +
                  end
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                  it "should cease execution of the current controller, and instruct the call to execute another" do
         | 
| 256 | 
            +
                    call.should_receive(:answer).once.ordered
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                    subject.exec
         | 
| 259 | 
            +
                  end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                  context "when components have been executed on the controller" do
         | 
| 262 | 
            +
                    let(:pass_controller) do
         | 
| 263 | 
            +
                      Class.new CallController do
         | 
| 264 | 
            +
                        attr_accessor :output1, :output2
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                        def prep_output
         | 
| 267 | 
            +
                          @output1 = play! 'file://foo.wav'
         | 
| 268 | 
            +
                          @output2 = play! 'file://bar.wav'
         | 
| 269 | 
            +
                        end
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                        def run
         | 
| 272 | 
            +
                          hard_pass SecondController, foo: 'bar'
         | 
| 273 | 
            +
                        end
         | 
| 274 | 
            +
                      end
         | 
| 275 | 
            +
                    end
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                    before { subject.prep_output }
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    context "but not yet received a complete event" do
         | 
| 280 | 
            +
                      it "should terminate the components" do
         | 
| 281 | 
            +
                        subject.output1.should_receive(:stop!).once
         | 
| 282 | 
            +
                        subject.output2.should_receive(:stop!).once
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                        subject.exec
         | 
| 285 | 
            +
                      end
         | 
| 286 | 
            +
             | 
| 287 | 
            +
                      context "and some fail to terminate" do
         | 
| 288 | 
            +
                        before { subject.output1.should_receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
         | 
| 289 | 
            +
             | 
| 290 | 
            +
                        it "should terminate the others" do
         | 
| 291 | 
            +
                          subject.output2.should_receive(:stop!).once
         | 
| 292 | 
            +
                          subject.exec
         | 
| 293 | 
            +
                        end
         | 
| 294 | 
            +
                      end
         | 
| 295 | 
            +
                    end
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                    context "when some have completed" do
         | 
| 298 | 
            +
                      before { subject.output1.trigger_event_handler Punchblock::Event::Complete.new }
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                      it "should not terminate the completed components" do
         | 
| 301 | 
            +
                        subject.output1.should_receive(:stop!).never
         | 
| 302 | 
            +
                        subject.output2.should_receive(:stop!).once
         | 
| 303 | 
            +
             | 
| 304 | 
            +
                        subject.exec
         | 
| 305 | 
            +
                      end
         | 
| 306 | 
            +
                    end
         | 
| 307 | 
            +
                  end
         | 
| 308 | 
            +
                end
         | 
| 309 | 
            +
             | 
| 310 | 
            +
                describe '#stop_all_components' do
         | 
| 311 | 
            +
                  let(:stop_controller) do
         | 
| 312 | 
            +
                    Class.new CallController do
         | 
| 313 | 
            +
                      attr_accessor :output1, :output2
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                      def prep_output
         | 
| 316 | 
            +
                        @output1 = play! 'file://foo.wav'
         | 
| 317 | 
            +
                        @output2 = play! 'file://bar.wav'
         | 
| 318 | 
            +
                      end
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                      def run
         | 
| 321 | 
            +
                        stop_all_components
         | 
| 322 | 
            +
                      end
         | 
| 323 | 
            +
                    end
         | 
| 324 | 
            +
                  end
         | 
| 325 | 
            +
             | 
| 326 | 
            +
                  subject { stop_controller.new call }
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                  context "when components have been executed on the controller" do
         | 
| 329 | 
            +
                    before do
         | 
| 330 | 
            +
                      call.wrapped_object.stub(:write_and_await_response).and_return do |command|
         | 
| 331 | 
            +
                        command.request!
         | 
| 332 | 
            +
                        command.execute!
         | 
| 333 | 
            +
                      end
         | 
| 334 | 
            +
                      call.stub register_controller: nil
         | 
| 335 | 
            +
                      Events.should_receive(:trigger).with(:exception, Exception).never
         | 
| 336 | 
            +
                      subject.prep_output
         | 
| 337 | 
            +
                    end
         | 
| 338 | 
            +
             | 
| 339 | 
            +
                    context "when they have not yet received a complete event" do
         | 
| 340 | 
            +
                      it "should terminate the components" do
         | 
| 341 | 
            +
                        subject.output1.should_receive(:stop!).once
         | 
| 342 | 
            +
                        subject.output2.should_receive(:stop!).once
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                        subject.exec
         | 
| 345 | 
            +
                      end
         | 
| 346 | 
            +
             | 
| 347 | 
            +
                      context "and some fail to terminate" do
         | 
| 348 | 
            +
                        before { subject.output1.should_receive(:stop!).and_raise(Punchblock::Component::InvalidActionError) }
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                        it "should terminate the others" do
         | 
| 351 | 
            +
                          subject.output2.should_receive(:stop!).once
         | 
| 352 | 
            +
                          subject.exec
         | 
| 353 | 
            +
                        end
         | 
| 354 | 
            +
                      end
         | 
| 355 | 
            +
                    end
         | 
| 356 | 
            +
             | 
| 357 | 
            +
                    context "when some have completed" do
         | 
| 358 | 
            +
                      before { subject.output1.trigger_event_handler Punchblock::Event::Complete.new }
         | 
| 359 | 
            +
             | 
| 360 | 
            +
                      it "should not terminate the completed components" do
         | 
| 361 | 
            +
                        subject.output1.should_receive(:stop!).never
         | 
| 362 | 
            +
                        subject.output2.should_receive(:stop!).once
         | 
| 363 | 
            +
             | 
| 364 | 
            +
                        subject.exec
         | 
| 365 | 
            +
                      end
         | 
| 366 | 
            +
                    end
         | 
| 367 | 
            +
                  end
         | 
| 368 | 
            +
                end
         | 
| 369 | 
            +
             | 
| 214 370 | 
             
                describe "#write_and_await_response" do
         | 
| 215 371 | 
             
                  let(:message) { Punchblock::Command::Accept.new }
         | 
| 216 372 |  | 
| @@ -249,7 +405,7 @@ module Adhearsion | |
| 249 405 | 
             
                describe "#join" do
         | 
| 250 406 | 
             
                  it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
         | 
| 251 407 | 
             
                    subject.should_receive(:block_until_resumed).once.ordered
         | 
| 252 | 
            -
                     | 
| 408 | 
            +
                    call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
         | 
| 253 409 | 
             
                    latch = CountDownLatch.new 1
         | 
| 254 410 | 
             
                    Thread.new do
         | 
| 255 411 | 
             
                      subject.join 'call1', :foo => :bar
         | 
| @@ -265,7 +421,7 @@ module Adhearsion | |
| 265 421 | 
             
                  context "with a mixer" do
         | 
| 266 422 | 
             
                    it "delegates to the call, blocking first until it is allowed to execute, and unblocking when an unjoined event is received" do
         | 
| 267 423 | 
             
                      subject.should_receive(:block_until_resumed).once.ordered
         | 
| 268 | 
            -
                       | 
| 424 | 
            +
                      call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
         | 
| 269 425 | 
             
                      latch = CountDownLatch.new 1
         | 
| 270 426 | 
             
                      Thread.new do
         | 
| 271 427 | 
             
                        subject.join :mixer_name => 'foobar', :foo => :bar
         | 
| @@ -282,7 +438,7 @@ module Adhearsion | |
| 282 438 | 
             
                  context "with :async => true" do
         | 
| 283 439 | 
             
                    it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
         | 
| 284 440 | 
             
                      subject.should_receive(:block_until_resumed).once.ordered
         | 
| 285 | 
            -
                       | 
| 441 | 
            +
                      call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(call_uri: 'call1'))
         | 
| 286 442 | 
             
                      latch = CountDownLatch.new 1
         | 
| 287 443 | 
             
                      Thread.new do
         | 
| 288 444 | 
             
                        subject.join 'call1', :foo => :bar, :async => true
         | 
| @@ -296,7 +452,7 @@ module Adhearsion | |
| 296 452 | 
             
                    context "with a mixer" do
         | 
| 297 453 | 
             
                      it "delegates to the call, blocking first until it is allowed to execute, and unblocking when the joined event is received" do
         | 
| 298 454 | 
             
                        subject.should_receive(:block_until_resumed).once.ordered
         | 
| 299 | 
            -
                         | 
| 455 | 
            +
                        call.wrapped_object.should_receive(:write_and_await_response).once.ordered.with(Punchblock::Command::Join.new(mixer_name: 'foobar'))
         | 
| 300 456 | 
             
                        latch = CountDownLatch.new 1
         | 
| 301 457 | 
             
                        Thread.new do
         | 
| 302 458 | 
             
                          subject.join :mixer_name => 'foobar', :foo => :bar, :async => true
         | 
| @@ -37,6 +37,20 @@ module Adhearsion | |
| 37 37 | 
             
                  Adhearsion.active_calls.clear
         | 
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 | 
            +
                it "should do recursion detection on inspect" do
         | 
| 41 | 
            +
                  subject[:foo] = subject
         | 
| 42 | 
            +
                  Timeout.timeout(0.2) do
         | 
| 43 | 
            +
                    expect(subject.inspect).to match('...')
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                it "should allow timers to be registered from outside" do
         | 
| 48 | 
            +
                  foo = :bar
         | 
| 49 | 
            +
                  subject.after(1) { foo = :baz }
         | 
| 50 | 
            +
                  sleep 1.1
         | 
| 51 | 
            +
                  foo.should == :baz
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 40 54 | 
             
                it { should respond_to :<< }
         | 
| 41 55 |  | 
| 42 56 | 
             
                its(:end_reason) { should be == nil }
         | 
| @@ -50,6 +64,8 @@ module Adhearsion | |
| 50 64 | 
             
                its(:to)      { should be == to }
         | 
| 51 65 | 
             
                its(:from)    { should be == from }
         | 
| 52 66 |  | 
| 67 | 
            +
                its(:auto_hangup) { should be_true }
         | 
| 68 | 
            +
             | 
| 53 69 | 
             
                context "when the ID is nil" do
         | 
| 54 70 | 
             
                  let(:call_id) { nil }
         | 
| 55 71 |  | 
| @@ -141,28 +157,52 @@ module Adhearsion | |
| 141 157 | 
             
                  end
         | 
| 142 158 | 
             
                end
         | 
| 143 159 |  | 
| 144 | 
            -
                 | 
| 145 | 
            -
                  event  | 
| 146 | 
            -
                   | 
| 147 | 
            -
             | 
| 148 | 
            -
                   | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 160 | 
            +
                context 'registered event handlers' do
         | 
| 161 | 
            +
                  let(:event)     { double 'Event' }
         | 
| 162 | 
            +
                  let(:response)  { double 'Response' }
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  it 'are called when messages are delivered' do
         | 
| 165 | 
            +
                    event.should_receive(:foo?).and_return true
         | 
| 166 | 
            +
                    response.should_receive(:call).once
         | 
| 167 | 
            +
                    subject.register_event_handler(:foo?) { response.call }
         | 
| 168 | 
            +
                    subject << event
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  context 'when a handler raises' do
         | 
| 172 | 
            +
                    it 'does not cause the call actor to crash' do
         | 
| 173 | 
            +
                      subject.register_event_handler { raise 'Boom' }
         | 
| 174 | 
            +
                      subject << event
         | 
| 175 | 
            +
                      subject.should be_alive
         | 
| 176 | 
            +
                    end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                    it "triggers an exception event" do
         | 
| 179 | 
            +
                      e = StandardError.new('Boom')
         | 
| 180 | 
            +
                      Events.should_receive(:trigger).once.with(:exception, [e, subject.logger])
         | 
| 181 | 
            +
                      subject.register_event_handler { raise e }
         | 
| 182 | 
            +
                      subject << event
         | 
| 183 | 
            +
                    end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                    it 'executes all handlers for each event' do
         | 
| 186 | 
            +
                      response.should_receive(:call).once
         | 
| 187 | 
            +
                      subject.register_event_handler { raise 'Boom' }
         | 
| 188 | 
            +
                      subject.register_event_handler { response.call }
         | 
| 189 | 
            +
                      subject << event
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
                  end
         | 
| 151 192 | 
             
                end
         | 
| 152 193 |  | 
| 153 194 | 
             
                describe "event handlers" do
         | 
| 154 | 
            -
                  before { pending }
         | 
| 155 195 | 
             
                  let(:response) { double 'Response' }
         | 
| 156 196 |  | 
| 157 197 | 
             
                  describe "for joined events" do
         | 
| 158 198 | 
             
                    context "joined to another call" do
         | 
| 159 199 | 
             
                      let :event do
         | 
| 160 | 
            -
                        Punchblock::Event::Joined.new call_uri: ' | 
| 200 | 
            +
                        Punchblock::Event::Joined.new call_uri: 'footransport:foobar@rayo.net'
         | 
| 161 201 | 
             
                      end
         | 
| 162 202 |  | 
| 163 203 | 
             
                      it "should trigger any on_joined callbacks set for the matching call ID" do
         | 
| 164 204 | 
             
                        response.should_receive(:call).once.with(event)
         | 
| 165 | 
            -
                        subject.on_joined(:call_uri => ' | 
| 205 | 
            +
                        subject.on_joined(:call_uri => 'footransport:foobar@rayo.net') { |event| response.call event }
         | 
| 166 206 | 
             
                        subject << event
         | 
| 167 207 | 
             
                      end
         | 
| 168 208 |  | 
| @@ -175,14 +215,14 @@ module Adhearsion | |
| 175 215 | 
             
                      it "should trigger any on_joined callbacks set for the matching call" do
         | 
| 176 216 | 
             
                        response.should_receive(:call).once.with(event)
         | 
| 177 217 | 
             
                        call = Call.new
         | 
| 178 | 
            -
                        call.wrapped_object.stub id: 'foobar', domain: 'rayo.net'
         | 
| 218 | 
            +
                        call.wrapped_object.stub id: 'foobar', domain: 'rayo.net', transport: 'footransport'
         | 
| 179 219 | 
             
                        subject.on_joined(call) { |event| response.call event }
         | 
| 180 220 | 
             
                        subject << event
         | 
| 181 221 | 
             
                      end
         | 
| 182 222 |  | 
| 183 223 | 
             
                      it "should not trigger on_joined callbacks for other call IDs" do
         | 
| 184 224 | 
             
                        response.should_receive(:call).never
         | 
| 185 | 
            -
                        subject.on_joined(: | 
| 225 | 
            +
                        subject.on_joined(:call_uri => 'barfoo') { |event| response.call event }
         | 
| 186 226 | 
             
                        subject << event
         | 
| 187 227 | 
             
                      end
         | 
| 188 228 |  | 
| @@ -212,7 +252,7 @@ module Adhearsion | |
| 212 252 |  | 
| 213 253 | 
             
                      it "should not trigger any on_joined callbacks set for calls" do
         | 
| 214 254 | 
             
                        response.should_receive(:call).never
         | 
| 215 | 
            -
                        subject.on_joined(: | 
| 255 | 
            +
                        subject.on_joined(:call_uri => 'foobar') { |event| response.call event }
         | 
| 216 256 | 
             
                        subject << event
         | 
| 217 257 | 
             
                      end
         | 
| 218 258 |  | 
| @@ -225,7 +265,7 @@ module Adhearsion | |
| 225 265 | 
             
                      it "should not trigger any on_joined callbacks set for the matching call" do
         | 
| 226 266 | 
             
                        response.should_receive(:call).never
         | 
| 227 267 | 
             
                        call = Call.new
         | 
| 228 | 
            -
                        call.stub :id => 'foobar'
         | 
| 268 | 
            +
                        call.wrapped_object.stub :id => 'foobar'
         | 
| 229 269 | 
             
                        subject.on_joined(call) { |event| response.call event }
         | 
| 230 270 | 
             
                        subject << event
         | 
| 231 271 | 
             
                      end
         | 
| @@ -235,12 +275,12 @@ module Adhearsion | |
| 235 275 | 
             
                  describe "for unjoined events" do
         | 
| 236 276 | 
             
                    context "unjoined from another call" do
         | 
| 237 277 | 
             
                      let :event do
         | 
| 238 | 
            -
                        Punchblock::Event::Unjoined.new call_uri: ' | 
| 278 | 
            +
                        Punchblock::Event::Unjoined.new call_uri: 'footransport:foobar@rayo.net'
         | 
| 239 279 | 
             
                      end
         | 
| 240 280 |  | 
| 241 281 | 
             
                      it "should trigger any on_unjoined callbacks set for the matching call ID" do
         | 
| 242 282 | 
             
                        response.should_receive(:call).once.with(event)
         | 
| 243 | 
            -
                        subject.on_unjoined(:call_uri => ' | 
| 283 | 
            +
                        subject.on_unjoined(:call_uri => 'footransport:foobar@rayo.net') { |event| response.call event }
         | 
| 244 284 | 
             
                        subject << event
         | 
| 245 285 | 
             
                      end
         | 
| 246 286 |  | 
| @@ -253,14 +293,14 @@ module Adhearsion | |
| 253 293 | 
             
                      it "should trigger any on_unjoined callbacks set for the matching call" do
         | 
| 254 294 | 
             
                        response.should_receive(:call).once.with(event)
         | 
| 255 295 | 
             
                        call = Call.new
         | 
| 256 | 
            -
                        call.wrapped_object.stub id: 'foobar', domain: 'rayo.net'
         | 
| 296 | 
            +
                        call.wrapped_object.stub id: 'foobar', domain: 'rayo.net', transport: 'footransport'
         | 
| 257 297 | 
             
                        subject.on_unjoined(call) { |event| response.call event }
         | 
| 258 298 | 
             
                        subject << event
         | 
| 259 299 | 
             
                      end
         | 
| 260 300 |  | 
| 261 301 | 
             
                      it "should not trigger on_unjoined callbacks for other call IDs" do
         | 
| 262 302 | 
             
                        response.should_receive(:call).never
         | 
| 263 | 
            -
                        subject.on_unjoined(: | 
| 303 | 
            +
                        subject.on_unjoined(:call_uri => 'barfoo') { |event| response.call event }
         | 
| 264 304 | 
             
                        subject << event
         | 
| 265 305 | 
             
                      end
         | 
| 266 306 |  | 
| @@ -290,7 +330,7 @@ module Adhearsion | |
| 290 330 |  | 
| 291 331 | 
             
                      it "should not trigger any on_unjoined callbacks set for calls" do
         | 
| 292 332 | 
             
                        response.should_receive(:call).never
         | 
| 293 | 
            -
                        subject.on_unjoined(: | 
| 333 | 
            +
                        subject.on_unjoined(:call_uri => 'foobar') { |event| response.call event }
         | 
| 294 334 | 
             
                        subject << event
         | 
| 295 335 | 
             
                      end
         | 
| 296 336 |  | 
| @@ -303,7 +343,7 @@ module Adhearsion | |
| 303 343 | 
             
                      it "should not trigger any on_unjoined callbacks set for the matching call" do
         | 
| 304 344 | 
             
                        response.should_receive(:call).never
         | 
| 305 345 | 
             
                        call = Call.new
         | 
| 306 | 
            -
                        call.stub :id => 'foobar'
         | 
| 346 | 
            +
                        call.wrapped_object.stub :id => 'foobar'
         | 
| 307 347 | 
             
                        subject.on_unjoined(call) { |event| response.call event }
         | 
| 308 348 | 
             
                        subject << event
         | 
| 309 349 | 
             
                      end
         | 
| @@ -346,54 +386,121 @@ module Adhearsion | |
| 346 386 | 
             
                end
         | 
| 347 387 |  | 
| 348 388 | 
             
                context "peer registry" do
         | 
| 349 | 
            -
                  let(: | 
| 389 | 
            +
                  let(:other_call_uri) { 'xmpp:foobar@example.com' }
         | 
| 350 390 | 
             
                  let(:other_call) { Call.new }
         | 
| 351 391 |  | 
| 352 | 
            -
                  before { other_call.stub : | 
| 392 | 
            +
                  before { other_call.stub uri: other_call_uri }
         | 
| 353 393 |  | 
| 354 394 | 
             
                  let :joined_event do
         | 
| 355 | 
            -
                    Punchblock::Event::Joined.new call_uri:  | 
| 395 | 
            +
                    Punchblock::Event::Joined.new call_uri: other_call_uri
         | 
| 356 396 | 
             
                  end
         | 
| 357 397 |  | 
| 358 398 | 
             
                  let :unjoined_event do
         | 
| 359 | 
            -
                    Punchblock::Event::Unjoined.new call_uri:  | 
| 399 | 
            +
                    Punchblock::Event::Unjoined.new call_uri: other_call_uri
         | 
| 360 400 | 
             
                  end
         | 
| 361 401 |  | 
| 362 402 | 
             
                  context "when we know about the joined call" do
         | 
| 363 403 | 
             
                    before { Adhearsion.active_calls << other_call }
         | 
| 404 | 
            +
                    after { Adhearsion.active_calls.remove_inactive_call other_call }
         | 
| 364 405 |  | 
| 365 406 | 
             
                    it "should add the peer to its registry" do
         | 
| 366 407 | 
             
                      subject << joined_event
         | 
| 367 | 
            -
                      subject.peers.should == {'foobar' => other_call}
         | 
| 408 | 
            +
                      subject.peers.should == {'xmpp:foobar@example.com' => other_call}
         | 
| 409 | 
            +
                    end
         | 
| 410 | 
            +
             | 
| 411 | 
            +
                    context "in a handler for the joined event" do
         | 
| 412 | 
            +
                      it "should have already populated the registry" do
         | 
| 413 | 
            +
                        peer = nil
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                        subject.on_joined do |event|
         | 
| 416 | 
            +
                          peer = subject.peers.keys.first
         | 
| 417 | 
            +
                        end
         | 
| 418 | 
            +
             | 
| 419 | 
            +
                        subject << joined_event
         | 
| 420 | 
            +
             | 
| 421 | 
            +
                        peer.should == other_call_uri
         | 
| 422 | 
            +
                      end
         | 
| 423 | 
            +
                    end
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                    context "when being unjoined from a previously joined call" do
         | 
| 426 | 
            +
                      before { subject << joined_event }
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                      it "should remove the peer from its registry" do
         | 
| 429 | 
            +
                        subject.peers.should_not eql({})
         | 
| 430 | 
            +
                        subject << unjoined_event
         | 
| 431 | 
            +
                        subject.peers.should eql({})
         | 
| 432 | 
            +
                      end
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                      context "in a handler for the unjoined event" do
         | 
| 435 | 
            +
                        it "should have already been removed the registry" do
         | 
| 436 | 
            +
                          peer_count = nil
         | 
| 437 | 
            +
             | 
| 438 | 
            +
                          subject.on_unjoined do |event|
         | 
| 439 | 
            +
                            peer_count = subject.peers.size
         | 
| 440 | 
            +
                          end
         | 
| 441 | 
            +
             | 
| 442 | 
            +
                          subject << unjoined_event
         | 
| 443 | 
            +
             | 
| 444 | 
            +
                          peer_count.should == 0
         | 
| 445 | 
            +
                        end
         | 
| 446 | 
            +
                      end
         | 
| 368 447 | 
             
                    end
         | 
| 369 448 | 
             
                  end
         | 
| 370 449 |  | 
| 371 450 | 
             
                  context "when we don't know about the joined call" do
         | 
| 372 451 | 
             
                    it "should add a nil entry to its registry" do
         | 
| 373 452 | 
             
                      subject << joined_event
         | 
| 374 | 
            -
                      subject.peers.should == {'foobar' => nil}
         | 
| 453 | 
            +
                      subject.peers.should == {'xmpp:foobar@example.com' => nil}
         | 
| 375 454 | 
             
                    end
         | 
| 376 | 
            -
                  end
         | 
| 377 455 |  | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
             | 
| 456 | 
            +
                    context "in a handler for the joined event" do
         | 
| 457 | 
            +
                      it "should have already populated the registry" do
         | 
| 458 | 
            +
                        peer = nil
         | 
| 381 459 |  | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 460 | 
            +
                        subject.on_joined do |event|
         | 
| 461 | 
            +
                          peer = subject.peers.keys.first
         | 
| 462 | 
            +
                        end
         | 
| 463 | 
            +
             | 
| 464 | 
            +
                        subject << joined_event
         | 
| 384 465 |  | 
| 385 | 
            -
             | 
| 386 | 
            -
                       | 
| 387 | 
            -
                      subject << unjoined_event
         | 
| 388 | 
            -
                      subject.peers.should eql({})
         | 
| 466 | 
            +
                        peer.should == other_call_uri
         | 
| 467 | 
            +
                      end
         | 
| 389 468 | 
             
                    end
         | 
| 469 | 
            +
             | 
| 470 | 
            +
                    context "when being unjoined from a previously joined call" do
         | 
| 471 | 
            +
                      before { subject << joined_event }
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                      it "should remove the peer from its registry" do
         | 
| 474 | 
            +
                        subject.peers.should_not eql({})
         | 
| 475 | 
            +
                        subject << unjoined_event
         | 
| 476 | 
            +
                        subject.peers.should eql({})
         | 
| 477 | 
            +
                      end
         | 
| 478 | 
            +
             | 
| 479 | 
            +
                      context "in a handler for the unjoined event" do
         | 
| 480 | 
            +
                        it "should have already been removed the registry" do
         | 
| 481 | 
            +
                          peer_count = nil
         | 
| 482 | 
            +
             | 
| 483 | 
            +
                          subject.on_unjoined do |event|
         | 
| 484 | 
            +
                            peer_count = subject.peers.size
         | 
| 485 | 
            +
                          end
         | 
| 486 | 
            +
             | 
| 487 | 
            +
                          subject << unjoined_event
         | 
| 488 | 
            +
             | 
| 489 | 
            +
                          peer_count.should == 0
         | 
| 490 | 
            +
                        end
         | 
| 491 | 
            +
                      end
         | 
| 492 | 
            +
                    end
         | 
| 493 | 
            +
                  end
         | 
| 494 | 
            +
             | 
| 495 | 
            +
                  it "should not return the same registry every call" do
         | 
| 496 | 
            +
                    subject.peers.should_not be subject.peers
         | 
| 390 497 | 
             
                  end
         | 
| 391 498 | 
             
                end
         | 
| 392 499 |  | 
| 393 500 | 
             
                describe "#<<" do
         | 
| 394 501 | 
             
                  describe "with a Punchblock End" do
         | 
| 395 502 | 
             
                    let :end_event do
         | 
| 396 | 
            -
                      Punchblock::Event::End.new :reason => :hangup
         | 
| 503 | 
            +
                      Punchblock::Event::End.new :reason => :hangup, :platform_code => 'arbitrary_code'
         | 
| 397 504 | 
             
                    end
         | 
| 398 505 |  | 
| 399 506 | 
             
                    it "should mark the call as ended" do
         | 
| @@ -406,6 +513,11 @@ module Adhearsion | |
| 406 513 | 
             
                      subject.end_reason.should be == :hangup
         | 
| 407 514 | 
             
                    end
         | 
| 408 515 |  | 
| 516 | 
            +
                    it "should set the end code" do
         | 
| 517 | 
            +
                      subject << end_event
         | 
| 518 | 
            +
                      subject.end_code.should be == 'arbitrary_code'
         | 
| 519 | 
            +
                    end
         | 
| 520 | 
            +
             | 
| 409 521 | 
             
                    it "should set the end time" do
         | 
| 410 522 | 
             
                      finish_time = Time.local(2008, 9, 1, 12, 1, 3)
         | 
| 411 523 | 
             
                      Timecop.freeze finish_time
         | 
| @@ -654,6 +766,20 @@ module Adhearsion | |
| 654 766 | 
             
                  end
         | 
| 655 767 | 
             
                end
         | 
| 656 768 |  | 
| 769 | 
            +
                describe "#send_message" do
         | 
| 770 | 
            +
                  it "should send a message through the Punchblock connection using the call ID and domain" do
         | 
| 771 | 
            +
                    subject.wrapped_object.should_receive(:client).once.and_return mock_client
         | 
| 772 | 
            +
                    mock_client.should_receive(:send_message).once.with(subject.id, subject.domain, "Hello World!", {})
         | 
| 773 | 
            +
                    subject.send_message "Hello World!"
         | 
| 774 | 
            +
                  end
         | 
| 775 | 
            +
             | 
| 776 | 
            +
                  it "should send a message with the given subject" do
         | 
| 777 | 
            +
                    subject.wrapped_object.should_receive(:client).once.and_return mock_client
         | 
| 778 | 
            +
                    mock_client.should_receive(:send_message).once.with(subject.id, subject.domain, nil, :subject => "Important Message")
         | 
| 779 | 
            +
                    subject.send_message nil, :subject => "Important Message"
         | 
| 780 | 
            +
                  end
         | 
| 781 | 
            +
                end
         | 
| 782 | 
            +
             | 
| 657 783 | 
             
                describe "basic control commands" do
         | 
| 658 784 | 
             
                  def expect_message_waiting_for_response(message = nil, fail = false, &block)
         | 
| 659 785 | 
             
                    expectation = subject.wrapped_object.should_receive(:write_and_await_response, &block).once
         | 
| @@ -810,26 +936,156 @@ module Adhearsion | |
| 810 936 | 
             
                          subject.join target, :media => :bridge, :direction => :recv
         | 
| 811 937 | 
             
                        end
         | 
| 812 938 | 
             
                      end
         | 
| 939 | 
            +
             | 
| 940 | 
            +
                      it "should return the command" do
         | 
| 941 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 942 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 943 | 
            +
                        result[:command].should be_a Punchblock::Command::Join
         | 
| 944 | 
            +
                        result[:command].call_uri.should eql(uri)
         | 
| 945 | 
            +
                        result[:command].media.should eql(:bridge)
         | 
| 946 | 
            +
                        result[:command].direction.should eql(:recv)
         | 
| 947 | 
            +
                      end
         | 
| 948 | 
            +
             | 
| 949 | 
            +
                      it "should return something that can be blocked on until the join is complete" do
         | 
| 950 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 951 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 952 | 
            +
             | 
| 953 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 954 | 
            +
             | 
| 955 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 956 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 957 | 
            +
                      end
         | 
| 958 | 
            +
             | 
| 959 | 
            +
                      it "should return something that can be blocked on until the entities are unjoined" do
         | 
| 960 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 961 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 962 | 
            +
             | 
| 963 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 964 | 
            +
             | 
| 965 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 966 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 967 | 
            +
             | 
| 968 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 969 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 970 | 
            +
                      end
         | 
| 971 | 
            +
             | 
| 972 | 
            +
                      it "should unblock all conditions on call end if no joined/unjoined events are received" do
         | 
| 973 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 974 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 975 | 
            +
             | 
| 976 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 977 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 978 | 
            +
             | 
| 979 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 980 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 981 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 982 | 
            +
                      end
         | 
| 983 | 
            +
             | 
| 984 | 
            +
                      it "should not error on call end when joined/unjoined events are received correctly" do
         | 
| 985 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 986 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 987 | 
            +
             | 
| 988 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 989 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 990 | 
            +
             | 
| 991 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 992 | 
            +
                      end
         | 
| 993 | 
            +
             | 
| 994 | 
            +
                      it "should not error if multiple joined events are received for the same join" do
         | 
| 995 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 996 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 997 | 
            +
             | 
| 998 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 999 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1000 | 
            +
             | 
| 1001 | 
            +
                        subject.should be_alive
         | 
| 1002 | 
            +
                      end
         | 
| 813 1003 | 
             
                    end
         | 
| 814 1004 |  | 
| 815 1005 | 
             
                    context "with a call ID" do
         | 
| 816 1006 | 
             
                      let(:target) { rand.to_s }
         | 
| 1007 | 
            +
                      let(:uri) { "footransport:#{target}@#{subject.domain}" }
         | 
| 817 1008 |  | 
| 818 1009 | 
             
                      it "should send a join command joining to the provided call ID" do
         | 
| 819 | 
            -
                        expect_join_with_options call_uri:  | 
| 1010 | 
            +
                        expect_join_with_options call_uri: uri
         | 
| 820 1011 | 
             
                        subject.join target
         | 
| 821 1012 | 
             
                      end
         | 
| 822 1013 |  | 
| 823 1014 | 
             
                      context "and direction/media options" do
         | 
| 824 1015 | 
             
                        it "should send a join command with the correct options" do
         | 
| 825 | 
            -
                          expect_join_with_options :call_uri =>  | 
| 1016 | 
            +
                          expect_join_with_options :call_uri => uri, :media => :bridge, :direction => :recv
         | 
| 826 1017 | 
             
                          subject.join target, :media => :bridge, :direction => :recv
         | 
| 827 1018 | 
             
                        end
         | 
| 828 1019 | 
             
                      end
         | 
| 1020 | 
            +
             | 
| 1021 | 
            +
                      it "should return the command" do
         | 
| 1022 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1023 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1024 | 
            +
                        result[:command].should be_a Punchblock::Command::Join
         | 
| 1025 | 
            +
                        result[:command].call_uri.should eql(uri)
         | 
| 1026 | 
            +
                        result[:command].media.should eql(:bridge)
         | 
| 1027 | 
            +
                        result[:command].direction.should eql(:recv)
         | 
| 1028 | 
            +
                      end
         | 
| 1029 | 
            +
             | 
| 1030 | 
            +
                      it "should return something that can be blocked on until the join is complete" do
         | 
| 1031 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1032 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1033 | 
            +
             | 
| 1034 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1035 | 
            +
             | 
| 1036 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1037 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1038 | 
            +
                      end
         | 
| 1039 | 
            +
             | 
| 1040 | 
            +
                      it "should return something that can be blocked on until the entities are unjoined" do
         | 
| 1041 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1042 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1043 | 
            +
             | 
| 1044 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1045 | 
            +
             | 
| 1046 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1047 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1048 | 
            +
             | 
| 1049 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 1050 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1051 | 
            +
                      end
         | 
| 1052 | 
            +
             | 
| 1053 | 
            +
                      it "should unblock all conditions on call end if no joined/unjoined events are received" do
         | 
| 1054 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1055 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1056 | 
            +
             | 
| 1057 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1058 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1059 | 
            +
             | 
| 1060 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1061 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1062 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1063 | 
            +
                      end
         | 
| 1064 | 
            +
             | 
| 1065 | 
            +
                      it "should not error on call end when joined/unjoined events are received correctly" do
         | 
| 1066 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1067 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1068 | 
            +
             | 
| 1069 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1070 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 1071 | 
            +
             | 
| 1072 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1073 | 
            +
                      end
         | 
| 1074 | 
            +
             | 
| 1075 | 
            +
                      it "should not error if multiple joined events are received for the same join" do
         | 
| 1076 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1077 | 
            +
                        result = subject.join target, :media => :bridge, :direction => :recv
         | 
| 1078 | 
            +
             | 
| 1079 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1080 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1081 | 
            +
             | 
| 1082 | 
            +
                        subject.should be_alive
         | 
| 1083 | 
            +
                      end
         | 
| 829 1084 | 
             
                    end
         | 
| 830 1085 |  | 
| 831 1086 | 
             
                    context "with a call URI as a hash key" do
         | 
| 832 1087 | 
             
                      let(:call_id) { rand.to_s }
         | 
| 1088 | 
            +
                      let(:uri) { call_id }
         | 
| 833 1089 | 
             
                      let(:target)  { { :call_uri => call_id } }
         | 
| 834 1090 |  | 
| 835 1091 | 
             
                      it "should send a join command joining to the provided call ID" do
         | 
| @@ -843,6 +1099,70 @@ module Adhearsion | |
| 843 1099 | 
             
                          subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 844 1100 | 
             
                        end
         | 
| 845 1101 | 
             
                      end
         | 
| 1102 | 
            +
             | 
| 1103 | 
            +
                      it "should return the command" do
         | 
| 1104 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1105 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1106 | 
            +
                        result[:command].should be_a Punchblock::Command::Join
         | 
| 1107 | 
            +
                        result[:command].call_uri.should eql(uri)
         | 
| 1108 | 
            +
                        result[:command].media.should eql(:bridge)
         | 
| 1109 | 
            +
                        result[:command].direction.should eql(:recv)
         | 
| 1110 | 
            +
                      end
         | 
| 1111 | 
            +
             | 
| 1112 | 
            +
                      it "should return something that can be blocked on until the join is complete" do
         | 
| 1113 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1114 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1115 | 
            +
             | 
| 1116 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1117 | 
            +
             | 
| 1118 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1119 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1120 | 
            +
                      end
         | 
| 1121 | 
            +
             | 
| 1122 | 
            +
                      it "should return something that can be blocked on until the entities are unjoined" do
         | 
| 1123 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1124 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1125 | 
            +
             | 
| 1126 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1127 | 
            +
             | 
| 1128 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1129 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1130 | 
            +
             | 
| 1131 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 1132 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1133 | 
            +
                      end
         | 
| 1134 | 
            +
             | 
| 1135 | 
            +
                      it "should unblock all conditions on call end if no joined/unjoined events are received" do
         | 
| 1136 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1137 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1138 | 
            +
             | 
| 1139 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1140 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1141 | 
            +
             | 
| 1142 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1143 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1144 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1145 | 
            +
                      end
         | 
| 1146 | 
            +
             | 
| 1147 | 
            +
                      it "should not error on call end when joined/unjoined events are received correctly" do
         | 
| 1148 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1149 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1150 | 
            +
             | 
| 1151 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1152 | 
            +
                        subject << Punchblock::Event::Unjoined.new(call_uri: uri)
         | 
| 1153 | 
            +
             | 
| 1154 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1155 | 
            +
                      end
         | 
| 1156 | 
            +
             | 
| 1157 | 
            +
                      it "should not error if multiple joined events are received for the same join" do
         | 
| 1158 | 
            +
                        expect_join_with_options :call_id => uri, :media => :bridge, :direction => :recv
         | 
| 1159 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1160 | 
            +
             | 
| 1161 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1162 | 
            +
                        subject << Punchblock::Event::Joined.new(call_uri: uri)
         | 
| 1163 | 
            +
             | 
| 1164 | 
            +
                        subject.should be_alive
         | 
| 1165 | 
            +
                      end
         | 
| 846 1166 | 
             
                    end
         | 
| 847 1167 |  | 
| 848 1168 | 
             
                    context "with a mixer name as a hash key" do
         | 
| @@ -860,6 +1180,70 @@ module Adhearsion | |
| 860 1180 | 
             
                          subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 861 1181 | 
             
                        end
         | 
| 862 1182 | 
             
                      end
         | 
| 1183 | 
            +
             | 
| 1184 | 
            +
                      it "should return the command" do
         | 
| 1185 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1186 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1187 | 
            +
                        result[:command].should be_a Punchblock::Command::Join
         | 
| 1188 | 
            +
                        result[:command].mixer_name.should eql(mixer_name)
         | 
| 1189 | 
            +
                        result[:command].media.should eql(:bridge)
         | 
| 1190 | 
            +
                        result[:command].direction.should eql(:recv)
         | 
| 1191 | 
            +
                      end
         | 
| 1192 | 
            +
             | 
| 1193 | 
            +
                      it "should return something that can be blocked on until the join is complete" do
         | 
| 1194 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1195 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1196 | 
            +
             | 
| 1197 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1198 | 
            +
             | 
| 1199 | 
            +
                        subject << Punchblock::Event::Joined.new(mixer_name: mixer_name)
         | 
| 1200 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1201 | 
            +
                      end
         | 
| 1202 | 
            +
             | 
| 1203 | 
            +
                      it "should return something that can be blocked on until the entities are unjoined" do
         | 
| 1204 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1205 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1206 | 
            +
             | 
| 1207 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1208 | 
            +
             | 
| 1209 | 
            +
                        subject << Punchblock::Event::Joined.new(mixer_name: mixer_name)
         | 
| 1210 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1211 | 
            +
             | 
| 1212 | 
            +
                        subject << Punchblock::Event::Unjoined.new(mixer_name: mixer_name)
         | 
| 1213 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1214 | 
            +
                      end
         | 
| 1215 | 
            +
             | 
| 1216 | 
            +
                      it "should unblock all conditions on call end if no joined/unjoined events are received" do
         | 
| 1217 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1218 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1219 | 
            +
             | 
| 1220 | 
            +
                        result[:joined_condition].wait(0.5).should be_false
         | 
| 1221 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_false
         | 
| 1222 | 
            +
             | 
| 1223 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1224 | 
            +
                        result[:joined_condition].wait(0.5).should be_true
         | 
| 1225 | 
            +
                        result[:unjoined_condition].wait(0.5).should be_true
         | 
| 1226 | 
            +
                      end
         | 
| 1227 | 
            +
             | 
| 1228 | 
            +
                      it "should not error on call end when joined/unjoined events are received correctly" do
         | 
| 1229 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1230 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1231 | 
            +
             | 
| 1232 | 
            +
                        subject << Punchblock::Event::Joined.new(mixer_name: mixer_name)
         | 
| 1233 | 
            +
                        subject << Punchblock::Event::Unjoined.new(mixer_name: mixer_name)
         | 
| 1234 | 
            +
             | 
| 1235 | 
            +
                        subject << Punchblock::Event::End.new
         | 
| 1236 | 
            +
                      end
         | 
| 1237 | 
            +
             | 
| 1238 | 
            +
                      it "should not error if multiple joined events are received for the same join" do
         | 
| 1239 | 
            +
                        expect_join_with_options :mixer_name => mixer_name, :media => :bridge, :direction => :recv
         | 
| 1240 | 
            +
                        result = subject.join target.merge({:media => :bridge, :direction => :recv})
         | 
| 1241 | 
            +
             | 
| 1242 | 
            +
                        subject << Punchblock::Event::Joined.new(mixer_name: mixer_name)
         | 
| 1243 | 
            +
                        subject << Punchblock::Event::Joined.new(mixer_name: mixer_name)
         | 
| 1244 | 
            +
             | 
| 1245 | 
            +
                        subject.should be_alive
         | 
| 1246 | 
            +
                      end
         | 
| 863 1247 | 
             
                    end
         | 
| 864 1248 |  | 
| 865 1249 | 
             
                    context "with a call ID and a mixer name as hash keys" do
         |