spec/adhearsion/call_controller/dial_spec.rb in adhearsion-2.6.4 vs spec/adhearsion/call_controller/dial_spec.rb in adhearsion-3.0.0.beta1
- old
+ new
@@ -13,11 +13,11 @@
let(:second_to) { 'sip:baz@bar.com' }
let(:second_other_call_id) { new_uuid }
let(:second_other_mock_call) { OutboundCall.new }
- let(:mock_answered) { Punchblock::Event::Answered.new }
+ let(:mock_answered) { Adhearsion::Event::Answered.new }
let(:latch) { CountDownLatch.new 1 }
let(:join_options) { options[:join_options] || {} }
@@ -25,11 +25,11 @@
allow(other_mock_call.wrapped_object).to receive_messages id: other_call_id, write_command: true
allow(second_other_mock_call.wrapped_object).to receive_messages id: second_other_call_id, write_command: true
end
def mock_end(reason = :hangup_command)
- Punchblock::Event::End.new.tap { |event| allow(event).to receive_messages reason: reason }
+ Adhearsion::Event::End.new.tap { |event| allow(event).to receive_messages reason: reason }
end
describe "#dial" do
it "should dial the call to the correct endpoint and return a dial status object" do
expect(OutboundCall).to receive(:new).and_return other_mock_call
@@ -148,11 +148,11 @@
expect(latch.wait(2)).to be_truthy
end
end
context "with ringback specified" do
- let(:component) { Punchblock::Component::Output.new }
+ let(:component) { Adhearsion::Rayo::Component::Output.new }
let(:options) { { ringback: ['file://tt-monkeys'] } }
before do
component.request!
component.execute!
@@ -210,13 +210,13 @@
end
end
end
it "hangs up the new call when the root call ends" do
+ expect(other_mock_call).to receive(:hangup).once
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:join).once.with(call, {})
- expect(other_mock_call).to receive(:hangup).once
dial_in_thread
expect(latch.wait(2)).to be_falsey
@@ -264,12 +264,12 @@
context "when the call is answered and joined" do
it "has an overall dial status of :answer" do
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
end
t = dial_in_thread
sleep 0.5
@@ -288,12 +288,12 @@
end
it "records the duration of the join" do
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
end
allow(other_mock_call).to receive_messages hangup: true
t = dial_in_thread
@@ -304,11 +304,11 @@
other_mock_call << mock_answered
base_time = Time.local(2008, 9, 1, 12, 0, 37)
Timecop.freeze base_time
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
other_mock_call << mock_end
expect(latch.wait(2)).to be_truthy
t.join
@@ -321,20 +321,23 @@
context "when join options are specified" do
let(:options) { { join_options: {media: :direct} } }
it "joins the calls with those options" do
expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, media: :direct)
+ expect(other_mock_call).to receive(:join).once.with(call, media: :direct) do
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
+ end
allow(other_mock_call).to receive_messages hangup: true
t = dial_in_thread
sleep 0.5
other_mock_call << mock_answered
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
other_mock_call << mock_end
expect(latch.wait(2)).to be_truthy
t.join
@@ -346,23 +349,23 @@
let(:join_target) { call }
before do
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:join).once.with(join_target, join_options) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
end
allow(other_mock_call).to receive(:unjoin) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
end
it "should unjoin the calls" do
expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
dial = Dial::Dial.new to, options, call
dial.run subject
@@ -498,12 +501,12 @@
end
context "when rejoining" do
it "should rejoin the calls" do
expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
dial = Dial::Dial.new to, options, call
dial.run subject
@@ -516,11 +519,14 @@
other_mock_call << mock_answered
dial.split
- expect(other_mock_call).to receive(:join).once.ordered.with(call, {})
+ expect(other_mock_call).to receive(:join).once.ordered.with(call, {}) do
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
+ end
dial.rejoin
other_mock_call << mock_end
expect(latch.wait(2)).to be_truthy
@@ -540,11 +546,14 @@
other_mock_call << mock_answered
dial.split
- expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct)
+ expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct) do
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
+ end
dial.rejoin
end
end
context "when join options are passed to rejoin" do
@@ -556,11 +565,14 @@
other_mock_call << mock_answered
dial.split
- expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct)
+ expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct) do
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
+ end
dial.rejoin nil, media: :direct
end
end
context "when a join target was originally specified" do
@@ -569,12 +581,12 @@
it "joins the calls to the specified target on answer" do
expect(call).to receive(:join).once.with(join_target, {})
expect(other_mock_call).to receive(:unjoin).once.ordered.with(join_target)
expect(call).to receive(:unjoin).once.ordered.with(join_target) do
- call << Punchblock::Event::Unjoined.new(join_target)
- other_mock_call << Punchblock::Event::Unjoined.new(join_target)
+ call << Adhearsion::Event::Unjoined.new(join_target)
+ other_mock_call << Adhearsion::Event::Unjoined.new(join_target)
end
dial = Dial::Dial.new to, options, call
dial.run subject
@@ -605,12 +617,12 @@
context "to a specified mixer" do
let(:mixer) { SecureRandom.uuid }
it "should join all calls to the mixer" do
expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
dial = Dial::Dial.new to, options, call
dial.run subject
@@ -637,12 +649,12 @@
expect(dial.status.result).to eq(:answer)
end
it "#split should then unjoin calls from the mixer" do
expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
dial = Dial::Dial.new to, options, call
dial.run subject
@@ -660,20 +672,20 @@
expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
dial.rejoin mixer_name: mixer
expect(other_mock_call).to receive(:unjoin).once.ordered.with(mixer_name: mixer) do
- other_mock_call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
+ other_mock_call << Adhearsion::Event::Unjoined.new(mixer_name: mixer)
end
expect(call).to receive(:unjoin).once.ordered.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
+ call << Adhearsion::Event::Unjoined.new(mixer_name: mixer)
end
dial.split
other_mock_call << mock_end
- expect(latch.wait(10)).to be_truthy
+ expect(latch.wait(2)).to be_truthy
waiter_thread.join
expect(dial.status.result).to eq(:answer)
end
end
@@ -703,16 +715,16 @@
second_other_mock_call << mock_answered
end
it "should split calls, rejoin to a mixer, and rejoin other calls to mixer" do
expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ call << Adhearsion::Event::Unjoined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
end
expect(second_other_mock_call).to receive(:unjoin).once.ordered.with(second_root_call) do
- second_root_call << Punchblock::Event::Unjoined.new(call_uri: second_other_mock_call.id)
- second_other_mock_call << Punchblock::Event::Unjoined.new(call_uri: second_root_call.id)
+ second_root_call << Adhearsion::Event::Unjoined.new(call_uri: second_other_mock_call.id)
+ second_other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: second_root_call.id)
end
expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
@@ -842,19 +854,19 @@
other_mock_call << mock_end
expect(latch.wait(2)).to be_falsey
[call, second_root_call, second_other_mock_call].each do |call|
expect(call).to receive(:unjoin).once.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
+ call << Adhearsion::Event::Unjoined.new(mixer_name: mixer)
end
end
dial.split
- [call, second_root_call, second_other_mock_call].each do |call|
+ [call, other_mock_call, second_root_call, second_other_mock_call].each do |call|
expect(call).to receive(:join).once.with({mixer_name: mixer}, {}) do
- call << Punchblock::Event::Joined.new(mixer_name: mixer)
+ call << Adhearsion::Event::Joined.new(mixer_name: mixer)
end
end
dial.rejoin
end
@@ -950,11 +962,11 @@
sleep 0.5
[call, second_root_call, second_other_mock_call].each do |call|
expect(call).to receive(:unjoin).once.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
+ call << Adhearsion::Event::Unjoined.new(mixer_name: mixer)
end
end
expect(other_mock_call).to receive(:unjoin).and_raise Adhearsion::Call::Hangup
@@ -963,11 +975,11 @@
other_mock_call << mock_end
expect(latch.wait(2)).to be_falsey
[call, second_root_call, second_other_mock_call].each do |call|
expect(call).to receive(:join).once.with({mixer_name: mixer}, {}) do
- call << Punchblock::Event::Joined.new(mixer_name: mixer)
+ call << Adhearsion::Event::Joined.new(mixer_name: mixer)
end
end
expect(other_mock_call).to receive(:join).and_raise Adhearsion::Call::ExpiredError
@@ -975,12 +987,12 @@
end
end
context "if the calls were not joined" do
it "should still join to mixer" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call).and_raise Punchblock::ProtocolError.new.setup(:service_unavailable)
- expect(second_other_mock_call).to receive(:unjoin).once.ordered.with(second_root_call).and_raise Punchblock::ProtocolError.new.setup(:service_unavailable)
+ expect(other_mock_call).to receive(:unjoin).once.ordered.with(call).and_raise Adhearsion::ProtocolError.new.setup(:service_unavailable)
+ expect(second_other_mock_call).to receive(:unjoin).once.ordered.with(second_root_call).and_raise Adhearsion::ProtocolError.new.setup(:service_unavailable)
expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
expect(second_root_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
@@ -1018,11 +1030,11 @@
expect { subject.dial to, options }.to raise_error(Call::Hangup)
end
it "should not make any outbound calls" do
expect(OutboundCall).to receive(:new).never
- expect { subject.dial to, options }.to raise_error
+ expect { subject.dial to, options }.to raise_error(Call::Hangup)
end
end
describe "with multiple third parties specified" do
let(:options) { {} }
@@ -1080,11 +1092,11 @@
t = dial_in_thread
expect(latch.wait(2)).to be_falsey
other_mock_call << mock_answered
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
expect(latch.wait(2)).to be_truthy
t.join
status = t.value
@@ -1271,1363 +1283,10 @@
# Copy metadata onto call variables so we can assert it later. Ugly hack
metadata.each_pair do |key, value|
call[key] = value
end
@@confirmation_latch.countdown!
- call['confirm'] || hangup
- end
- end
- end
-
- let(:confirmation_latch) { CountDownLatch.new 1 }
-
- let(:options) { {:confirm => confirmation_controller} }
-
- context "with confirmation controller metadata specified" do
- let(:options) { {:confirm => confirmation_controller, :confirm_metadata => {:foo => 'bar'}} }
-
- before do
- expect(other_mock_call).to receive(:dial).once
- expect(OutboundCall).to receive(:new).and_return other_mock_call
- end
-
- it "should set the metadata on the controller" do
- expect(other_mock_call).to receive(:hangup).once do
- other_mock_call << mock_end
- end
- other_mock_call['confirm'] = false
-
- dial_in_thread
-
- expect(latch.wait(0.1)).to be_falsey
-
- other_mock_call << mock_answered
-
- expect(confirmation_latch.wait(2)).to be_truthy
- expect(latch.wait(2)).to be_truthy
-
- expect(other_mock_call[:foo]).to eq('bar')
- end
- end
-
- context "when an outbound call is answered" do
- before do
- expect(other_mock_call).to receive(:dial).once
- expect(OutboundCall).to receive(:new).and_return other_mock_call
- end
-
- it "should execute the specified confirmation controller" do
- expect(other_mock_call).to receive(:hangup).once do
- other_mock_call << mock_end
- end
- other_mock_call['confirm'] = false
-
- dial_in_thread
-
- expect(latch.wait(0.1)).to be_falsey
-
- other_mock_call << mock_answered
-
- expect(confirmation_latch.wait(2)).to be_truthy
- expect(latch.wait(2)).to be_truthy
- end
-
- it "should join the calls if the call is still active after execution of the call controller" do
- other_mock_call['confirm'] = true
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- expect(other_mock_call).to receive(:hangup).once do
- other_mock_call << mock_end
- end
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- base_time = Time.local(2008, 9, 1, 12, 0, 0)
- Timecop.freeze base_time
-
- other_mock_call << mock_answered
-
- base_time = Time.local(2008, 9, 1, 12, 0, 42)
- Timecop.freeze base_time
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
-
- expect(latch.wait(3)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:answer)
-
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(42.0)
- expect(joined_status.result).to eq(:joined)
- end
-
- it "should not join the calls if the call is not active after execution of the call controller" do
- expect(other_mock_call).to receive(:hangup).once do
- other_mock_call << mock_end
- end
- other_mock_call['confirm'] = false
- expect(call).to receive(:answer).never
- expect(other_mock_call).to receive(:join).never.with(call)
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:unconfirmed)
-
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(0.0)
- expect(joined_status.result).to eq(:unconfirmed)
- end
- end
-
- context "when multiple calls are made" do
- before do
- expect(OutboundCall).to receive(:new).and_return other_mock_call, second_other_mock_call
- end
-
- def dial_in_thread
- Thread.new do
- status = subject.dial [to, second_to], options
- latch.countdown!
- status
- end
- end
-
- context "when one answers" do
- it "should only execute the confirmation controller on the first call to answer, immediately hanging up all others" do
- other_mock_call['confirm'] = true
- expect(call).to receive(:answer).once
-
- expect(other_mock_call).to receive(:dial).once.with(to, from: nil)
- expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- expect(other_mock_call).to receive(:hangup).once do
- other_mock_call << mock_end
- end
-
- expect(second_other_mock_call).to receive(:dial).once.with(second_to, from: nil)
- expect(second_other_mock_call).to receive(:join).never
- expect(second_other_mock_call).to receive(:execute_controller).never
- expect(second_other_mock_call).to receive(:hangup).once do
- second_other_mock_call << mock_end(:foo)
- end
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- expect(confirmation_latch.wait(2)).to be_truthy
-
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status).to be_a Dial::DialStatus
- expect(status.calls.size).to eq(2)
- status.calls.each { |c| expect(c).to be_a OutboundCall }
- expect(status.result).to eq(:answer)
- end
- end
- end
- end
- end
-
- describe "#dial_and_confirm" do
- it "should dial the call to the correct endpoint and return a dial status object" do
- expect(OutboundCall).to receive(:new).and_return other_mock_call
- expect(other_mock_call).to receive(:dial).with(to, :from => 'foo').once
- dial_thread = Thread.new do
- status = subject.dial_and_confirm(to, :from => 'foo')
-
- expect(status).to be_a Dial::DialStatus
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(0.0)
- expect(joined_status.result).to eq(:no_answer)
- end
- sleep 0.1
- other_mock_call << mock_end
- expect(dial_thread.join).to be_truthy
- end
-
- it "should default the caller ID to that of the original call" do
- allow(call).to receive_messages :from => 'sip:foo@bar.com'
- expect(OutboundCall).to receive(:new).and_return other_mock_call
- expect(other_mock_call).to receive(:dial).with(to, :from => 'sip:foo@bar.com').once
- dial_thread = Thread.new do
- subject.dial_and_confirm to
- end
- sleep 0.1
- other_mock_call << mock_end
- expect(dial_thread.join).to be_truthy
- end
-
- let(:options) { { :foo => :bar } }
-
- def dial_in_thread
- Thread.new do
- status = subject.dial_and_confirm to, options
- latch.countdown!
- status
- end
- end
-
- describe "without a block" do
- before do
- expect(other_mock_call).to receive(:dial).once.with(to, options)
- expect(OutboundCall).to receive(:new).and_return other_mock_call
- end
-
- it "blocks the original controller until the new call ends" do
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
-
- it "unblocks the original controller if the original call ends" do
- expect(other_mock_call).to receive(:hangup).once
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
-
- it "joins the new call to the existing one on answer" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
-
- context "with a join target specified" do
- let(:options) { { join_target: {mixer_name: 'foobar'} } }
-
- it "joins the calls to the specified target on answer" do
- expect(call).to receive(:answer).once
- expect(call).to receive(:join).once.with({mixer_name: 'foobar'}, {})
- expect(other_mock_call).to receive(:join).once.with({mixer_name: 'foobar'}, {})
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
- end
-
- context "with a pre-join callback specified" do
- let(:foo) { double }
- let(:options) { { pre_join: ->(call) { foo.bar call } } }
-
- it "executes the callback prior to joining" do
- expect(foo).to receive(:bar).once.with(other_mock_call).ordered
- expect(call).to receive(:answer).once.ordered
- expect(other_mock_call).to receive(:join).once.with(call, {}).ordered
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
- end
-
- context "with ringback specified" do
- let(:component) { Punchblock::Component::Output.new }
- let(:options) { { ringback: ['file://tt-monkeys'] } }
-
- before do
- component.request!
- component.execute!
- end
-
- it "plays the ringback asynchronously, terminating prior to joining" do
- expect(subject).to receive(:play!).once.with(['file://tt-monkeys'], repeat_times: 0).and_return(component)
- expect(component).to receive(:stop!).twice
- expect(call).to receive(:answer).once.ordered
- expect(other_mock_call).to receive(:join).once.with(call, {}).ordered
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
-
- context "as a callback" do
- let(:foo) { double }
- let(:options) { { ringback: -> { foo.bar; component } } }
-
- it "calls the callback to start, and uses the return value of the callback to stop the ringback" do
- expect(foo).to receive(:bar).once.ordered
- expect(component).to receive(:stop!).twice
- expect(call).to receive(:answer).once.ordered
- expect(other_mock_call).to receive(:join).once.with(call, {}).ordered
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
- end
-
- context "when the call is rejected" do
- it "terminates the ringback before returning" do
- expect(subject).to receive(:play!).once.with(['file://tt-monkeys'], repeat_times: 0).and_return(component)
- expect(component).to receive(:stop!).once
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_end(:reject)
-
- expect(latch.wait(2)).to be_truthy
- end
- end
- end
-
- it "hangs up the new call when the root call ends" do
- expect(other_mock_call).to receive(:hangup).once
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
-
- dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- call << mock_end
-
- expect(latch.wait(2)).to be_truthy
- end
-
- context "when the call is rejected" do
- it "has an overall dial status of :no_answer" do
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_end(:reject)
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:no_answer)
- end
- end
-
- context "when the call ends with an error" do
- it "has an overall dial status of :error" do
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_end(:error)
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:error)
-
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(0.0)
- expect(joined_status.result).to eq(:error)
- end
- end
-
- context "when the call is answered and joined" do
- it "has an overall dial status of :answer" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
-
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:answer)
-
- joined_status = status.joins[status.calls.first]
- expect(joined_status.result).to eq(:joined)
- end
-
- it "records the duration of the join" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- allow(other_mock_call).to receive_messages hangup: true
-
- t = dial_in_thread
-
- sleep 0.5
-
- base_time = Time.local(2008, 9, 1, 12, 0, 0)
- Timecop.freeze base_time
-
- other_mock_call << mock_answered
-
- base_time = Time.local(2008, 9, 1, 12, 0, 37)
- Timecop.freeze base_time
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:answer)
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(37.0)
- end
-
- context "when join options are specified" do
- let(:options) { { join_options: {media: :direct} } }
-
- it "joins the calls with those options" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, media: :direct) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- allow(other_mock_call).to receive_messages hangup: true
-
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- end
- end
- end
-
- context "when a dial is split" do
- let(:join_target) { call }
-
- before do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(join_target, join_options) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- allow(other_mock_call).to receive(:unjoin) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
- end
-
- it "should unjoin the calls" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- it "should not unblock immediately" do
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- it "should set end time" do
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- base_time = Time.local(2008, 9, 1, 12, 0, 0)
- Timecop.freeze base_time
-
- other_mock_call << mock_answered
-
- base_time = Time.local(2008, 9, 1, 12, 0, 37)
- Timecop.freeze base_time
- dial.split
-
- base_time = Time.local(2008, 9, 1, 12, 0, 54)
- Timecop.freeze base_time
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- status = dial.status
- expect(status.result).to eq(:answer)
- joined_status = status.joins[status.calls.first]
- expect(joined_status.duration).to eq(37.0)
- end
-
- context "with new controllers specified" do
- let(:split_latch) { CountDownLatch.new 2 }
-
- let(:split_controller) do
- latch = split_latch
- Class.new(Adhearsion::CallController) do
- @@split_latch = latch
-
- def run
- call['hit_split_controller'] = self.class
- call['split_controller_metadata'] = metadata
- @@split_latch.countdown!
- end
- end
- end
-
- let(:main_split_controller) { Class.new(split_controller) }
- let(:others_split_controller) { Class.new(split_controller) }
-
- it "should execute the :main controller on the originating call and :others on the outbound calls" do
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- expect(self).to receive(:callback).once.with(call)
- expect(self).to receive(:callback).once.with(other_mock_call)
-
- dial.split main: main_split_controller, others: others_split_controller, main_callback: ->(call) { self.callback(call) }, others_callback: ->(call) { self.callback(call) }
-
- expect(latch.wait(2)).to be_falsey
- expect(split_latch.wait(2)).to be_truthy
-
- expect(call['hit_split_controller']).to eq(main_split_controller)
- expect(call['split_controller_metadata']['current_dial']).to be dial
-
- expect(other_mock_call['hit_split_controller']).to eq(others_split_controller)
- expect(other_mock_call['split_controller_metadata']['current_dial']).to be dial
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
- end
-
- context "when rejoining" do
- it "should rejoin the calls" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(other_mock_call).to receive(:join).once.ordered.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- dial.rejoin
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- context "when join options were set originally" do
- let(:options) { { join_options: {media: :direct} } }
-
- it "should rejoin with the same parameters" do
- allow(other_mock_call).to receive(:unjoin)
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- dial.rejoin
- end
- end
-
- context "when join options are passed to rejoin" do
- it "should rejoin with those parameters" do
- allow(other_mock_call).to receive(:unjoin)
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(other_mock_call).to receive(:join).once.ordered.with(call, media: :direct) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
- end
- dial.rejoin nil, media: :direct
- end
- end
-
- context "when a join target was originally specified" do
- let(:join_target) { {mixer_name: 'foobar'} }
- let(:options) { { join_target: join_target } }
-
- it "joins the calls to the specified target on answer" do
- expect(call).to receive(:join).once.with(join_target, {})
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(join_target)
- expect(call).to receive(:unjoin).once.ordered.with(join_target) do
- call << Punchblock::Event::Unjoined.new(join_target)
- other_mock_call << Punchblock::Event::Unjoined.new(join_target)
- end
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: 'foobar'}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: 'foobar'}, {})
- dial.rejoin
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
- end
-
- context "to a specified mixer" do
- let(:mixer) { SecureRandom.uuid }
-
- it "should join all calls to the mixer" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- dial.rejoin mixer_name: mixer
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- it "#split should then unjoin calls from the mixer" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
-
- dial = Dial::ParallelConfirmationDial.new to, options, call
- dial.run subject
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_answered
-
- dial.split
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- dial.rejoin mixer_name: mixer
-
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(mixer_name: mixer) do
- other_mock_call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
- end
- expect(call).to receive(:unjoin).once.ordered.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
- end
- dial.split
-
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
- end
- end
-
- context "when another dial is merged in" do
- let(:second_root_call_id) { new_uuid }
- let(:second_root_call) { Adhearsion::Call.new }
- let(:mixer) { SecureRandom.uuid }
-
- let(:dial) { Dial::ParallelConfirmationDial.new to, options, call }
- let(:other_dial) { Dial::ParallelConfirmationDial.new second_to, options, second_root_call }
-
- before do
- allow(second_root_call).to receive_messages write_command: true, id: second_root_call_id
- expect(OutboundCall).to receive(:new).and_return second_other_mock_call
- expect(second_other_mock_call).to receive(:join).once.with(second_root_call, {})
- expect(second_other_mock_call).to receive(:dial).once.with(second_to, options)
- expect(second_root_call).to receive(:answer).once
-
- allow(SecureRandom).to receive_messages uuid: mixer
-
- dial.run subject
- other_dial.run subject
-
- other_mock_call << mock_answered
- second_other_mock_call << mock_answered
- end
-
- it "should split calls, rejoin to a mixer, and rejoin other calls to mixer" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call) do
- call << Punchblock::Event::Unjoined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
- end
- expect(second_other_mock_call).to receive(:unjoin).once.ordered.with(second_root_call) do
- second_root_call << Punchblock::Event::Unjoined.new(call_uri: second_other_mock_call.id)
- second_other_mock_call << Punchblock::Event::Unjoined.new(call_uri: second_root_call.id)
- end
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- expect(second_root_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(second_other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call.async << mock_end
- second_root_call.async << mock_end
- second_other_mock_call.async << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- context "when join options were specified originally" do
- let(:options) { { join_options: {media: :direct} } }
-
- it "should rejoin with default options" do
- allow(other_mock_call).to receive(:unjoin)
- allow(second_other_mock_call).to receive(:unjoin)
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- expect(second_root_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(second_other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- dial.merge other_dial
- end
- end
-
- it "should add the merged calls to the returned status" do
- [call, other_mock_call, second_root_call, second_other_mock_call].each { |c| allow(c).to receive_messages join: true, unjoin: true }
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call.async << mock_end
- second_root_call.async << mock_end
- second_other_mock_call.async << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- expect(dial.status.calls).to include(second_root_call, second_other_mock_call)
- end
-
- it "should not unblock until all joined calls end" do
- [call, other_mock_call, second_root_call, second_other_mock_call].each { |c| allow(c).to receive_messages join: true, unjoin: true }
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_end
- expect(latch.wait(2)).to be_falsey
-
- second_other_mock_call << mock_end
- expect(latch.wait(2)).to be_falsey
-
- second_root_call << mock_end
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- it "should cleanup merged calls when the root call ends" do
- [call, other_mock_call, second_root_call, second_other_mock_call].each do |c|
- allow(c).to receive_messages join: true, unjoin: true
- end
- [other_mock_call, second_root_call, second_other_mock_call].each do |c|
- expect(c).to receive(:hangup).once
- end
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- dial.cleanup_calls
- latch.countdown!
- end
-
- sleep 0.5
-
- call << mock_end
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
-
- it "should subsequently rejoin to a mixer" do
- [call, other_mock_call, second_root_call, second_other_mock_call].each { |c| allow(c).to receive_messages join: true, unjoin: true }
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call << mock_end
- expect(latch.wait(2)).to be_falsey
-
- [call, second_root_call, second_other_mock_call].each do |call|
- expect(call).to receive(:unjoin).once.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
- end
- end
-
- dial.split
-
- [call, other_mock_call, second_root_call, second_other_mock_call].each do |call|
- expect(call).to receive(:join).once.with({mixer_name: mixer}, {}) do
- call << Punchblock::Event::Joined.new(mixer_name: mixer)
- end
- end
-
- dial.rejoin
- end
-
- context "if a call hangs up" do
- it "should still allow splitting and rejoining" do
- [call, other_mock_call, second_root_call, second_other_mock_call].each { |c| allow(c).to receive_messages join: true, unjoin: true }
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- [call, second_root_call, second_other_mock_call].each do |call|
- expect(call).to receive(:unjoin).once.with(mixer_name: mixer) do
- call << Punchblock::Event::Unjoined.new(mixer_name: mixer)
- end
- end
-
- expect(other_mock_call).to receive(:unjoin).and_raise Adhearsion::Call::Hangup
-
- dial.split
-
- other_mock_call << mock_end
- expect(latch.wait(2)).to be_falsey
-
- [call, second_root_call, second_other_mock_call].each do |call|
- expect(call).to receive(:join).once.with({mixer_name: mixer}, {}) do
- call << Punchblock::Event::Joined.new(mixer_name: mixer)
- end
- end
-
- expect(other_mock_call).to receive(:join).and_raise Adhearsion::Call::ExpiredError
-
- dial.rejoin
- end
- end
-
- context "if the calls were not joined" do
- it "should still join to mixer" do
- expect(other_mock_call).to receive(:unjoin).once.ordered.with(call).and_raise Punchblock::ProtocolError.new.setup(:service_unavailable)
- expect(second_other_mock_call).to receive(:unjoin).once.ordered.with(second_root_call).and_raise Punchblock::ProtocolError.new.setup(:service_unavailable)
-
- expect(call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- expect(second_root_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
- expect(second_other_mock_call).to receive(:join).once.ordered.with({mixer_name: mixer}, {})
-
- dial.merge other_dial
-
- waiter_thread = Thread.new do
- dial.await_completion
- latch.countdown!
- end
-
- sleep 0.5
-
- other_mock_call.async << mock_end
- second_root_call.async << mock_end
- second_other_mock_call.async << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- waiter_thread.join
- expect(dial.status.result).to eq(:answer)
- end
- end
- end
- end
- end
-
- describe "when the caller has already hung up" do
- before do
- call << mock_end
- end
-
- it "should raise Call::Hangup" do
- expect { subject.dial_and_confirm to, options }.to raise_error(Call::Hangup)
- end
-
- it "should not make any outbound calls" do
- expect(OutboundCall).to receive(:new).never
- expect { subject.dial_and_confirm to, options }.to raise_error
- end
- end
-
- describe "with multiple third parties specified" do
- let(:options) { {} }
- let(:other_options) { options }
- let(:second_other_options) { options }
-
- before do
- expect(OutboundCall).to receive(:new).and_return other_mock_call, second_other_mock_call
-
- expect(other_mock_call).to receive(:dial).once.with(to, other_options)
-
- expect(second_other_mock_call).to receive(:dial).once.with(second_to, second_other_options)
- expect(second_other_mock_call).to receive(:join).never
- end
-
- def dial_in_thread
- Thread.new do
- status = subject.dial_and_confirm [to, second_to], options
- latch.countdown!
- status
- end
- end
-
- it "dials all parties and joins the first one to answer, hanging up the rest" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
- expect(second_other_mock_call).to receive(:hangup).once do
- second_other_mock_call << mock_end
- end
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status).to be_a Dial::DialStatus
- expect(status.calls.size).to eq(2)
- status.calls.each { |c| expect(c).to be_a OutboundCall }
- end
-
- it "unblocks when the joined call unjoins, allowing it to proceed further" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
- expect(other_mock_call).to receive(:hangup).once
- expect(second_other_mock_call).to receive(:hangup).once do
- second_other_mock_call << mock_end
- end
-
- t = dial_in_thread
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status).to be_a Dial::DialStatus
- expect(status.calls.size).to eq(2)
- status.calls.each { |c| expect(c).to be_a OutboundCall }
- end
-
- describe "with options overrides" do
- let(:options) do
- {
- :from => 'foo',
- :timeout => 3000,
- :headers => {
- :x_foo => 'bar'
- }
- }
- end
-
- let(:dial_other_options) do
- {
- :foo => 'bar',
- :headers => {
- :x_foo => 'buzz'
- }
- }
- end
-
- let(:other_options) do
- {
- :from => 'foo',
- :timeout => 3000,
- :foo => 'bar',
- :headers => {
- :x_foo => 'buzz'
- }
-
- }
- end
-
- let(:dial_second_other_options) do
- {
- :timeout => 5000,
- :headers => {
- :x_bar => 'barbuzz'
- }
- }
- end
-
- let(:second_other_options) do
- {
- :from => 'foo',
- :timeout => 5000,
- :headers => {
- :x_foo => 'bar',
- :x_bar => 'barbuzz'
- }
- }
- end
-
- it "with multiple destinations as an hash, with overrides for each, and an options hash, it dials each call with specified options" do
- t = Thread.new do
- subject.dial_and_confirm({
- to => dial_other_options,
- second_to => dial_second_other_options
- }, options)
- latch.countdown!
- end
-
- expect(latch.wait(2)).to be_falsey
- other_mock_call << mock_end
- expect(latch.wait(2)).to be_falsey
- second_other_mock_call << mock_end
- expect(latch.wait(2)).to be_truthy
- t.join
- end
- end
-
- context "when all calls are rejected" do
- it "has an overall dial status of :no_answer" do
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_end(:reject)
- second_other_mock_call << mock_end(:reject)
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:no_answer)
- end
- end
-
- context "when a call is answered and joined, and the other ends with an error" do
- it "has an overall dial status of :answer" do
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
- expect(second_other_mock_call).to receive(:hangup).once do
- second_other_mock_call << mock_end(:error)
- end
-
- t = dial_in_thread
-
- sleep 0.5
-
- other_mock_call << mock_answered
- other_mock_call << mock_end
-
- expect(latch.wait(2)).to be_truthy
-
- t.join
- status = t.value
- expect(status.result).to eq(:answer)
- end
- end
- end
-
- describe "with a timeout specified" do
- let(:timeout) { 3 }
-
- it "should abort the dial after the specified timeout" do
- expect(other_mock_call).to receive(:dial).once
- expect(other_mock_call).to receive(:hangup).once
- expect(OutboundCall).to receive(:new).and_return other_mock_call
-
- time = Time.now
-
- t = Thread.new do
- status = subject.dial_and_confirm to, :timeout => timeout
- latch.countdown!
- status
- end
-
- latch.wait
- time = Time.now - time
- expect(time.round).to eq(timeout)
- t.join
- status = t.value
- expect(status.result).to eq(:timeout)
- end
-
- describe "if someone answers before the timeout elapses" do
- it "should not abort until the far end hangs up" do
- expect(other_mock_call).to receive(:dial).once.with(to, hash_including(:timeout => timeout))
- expect(call).to receive(:answer).once
- expect(other_mock_call).to receive(:join).once.with(call, {})
- expect(OutboundCall).to receive(:new).and_return other_mock_call
-
- time = Time.now
-
- t = Thread.new do
- status = subject.dial_and_confirm to, :timeout => timeout
- latch.countdown!
- status
- end
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_answered
-
- expect(latch.wait(2)).to be_falsey
-
- other_mock_call << mock_end
-
- expect(latch.wait(0.1)).to be_truthy
- time = Time.now - time
- expect(time.to_i).to be > timeout
- t.join
- status = t.value
- expect(status.result).to eq(:answer)
- end
- end
- end
-
- describe "with a confirmation controller" do
- let(:confirmation_controller) do
- latch = confirmation_latch
- Class.new(Adhearsion::CallController) do
- @@confirmation_latch = latch
-
- def run
- # Copy metadata onto call variables so we can assert it later. Ugly hack
- metadata.each_pair do |key, value|
- call[key] = value
- end
- @@confirmation_latch.countdown!
if delay = call['confirmation_delay']
sleep delay
end
call['confirm'] || hangup
end
@@ -2692,12 +1351,12 @@
other_mock_call << mock_end
end
other_mock_call['confirm'] = true
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
end
t = dial_in_thread
expect(latch.wait(2)).to be_falsey
@@ -2707,11 +1366,11 @@
other_mock_call << mock_answered
base_time = Time.local(2008, 9, 1, 12, 0, 42)
Timecop.freeze base_time
- other_mock_call << Punchblock::Event::Unjoined.new(call_uri: call.id)
+ other_mock_call << Adhearsion::Event::Unjoined.new(call_uri: call.id)
expect(latch.wait(2)).to be_truthy
t.join
status = t.value
@@ -2765,11 +1424,11 @@
expect(OutboundCall).to receive(:new).and_return other_mock_call, second_other_mock_call
end
def dial_in_thread
Thread.new do
- status = subject.dial_and_confirm [to, second_to], options
+ status = subject.dial [to, second_to], options
latch.countdown!
status
end
end
@@ -2782,12 +1441,12 @@
expect(call).to receive(:answer).once
expect(other_mock_call).to receive(:dial).once.with(to, from: nil)
expect(other_mock_call).to receive(:join).once.with(call, {}) do
- call << Punchblock::Event::Joined.new(call_uri: other_mock_call.id)
- other_mock_call << Punchblock::Event::Joined.new(call_uri: call.id)
+ call << Adhearsion::Event::Joined.new(call_uri: other_mock_call.id)
+ other_mock_call << Adhearsion::Event::Joined.new(call_uri: call.id)
end
expect(other_mock_call).to receive(:hangup).once do
other_mock_call.async.deliver_message mock_end
end
@@ -2805,10 +1464,10 @@
second_other_mock_call.async.deliver_message mock_answered
expect(confirmation_latch.wait(2)).to be_truthy
sleep 2
- other_mock_call.async.deliver_message Punchblock::Event::Unjoined.new(call_uri: call.id)
+ other_mock_call.async.deliver_message Adhearsion::Event::Unjoined.new(call_uri: call.id)
expect(latch.wait(2)).to be_truthy
expect(second_other_mock_call['apology_done']).to be_truthy
expect(second_other_mock_call['apology_metadata']).to eq({'foo' => 'bar'})