cucumber-voip 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ log/*.log
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ # develop
2
+
3
+ # [v0.1.0](https://github.com/benlangfeld/cucumber-voip/compare/f34e659a9ee5ecbb739aafc88f8e760260366b10...v0.1.0) - [2012-03-14](https://rubygems.org/gems/cucumber-voip/versions/0.1.0)
4
+ * First public release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cucumber-voip.gemspec
4
+ gemspec
5
+
6
+ if RUBY_PLATFORM =~ /darwin/
7
+ gem 'growl_notify'
8
+ gem 'rb-fsevent'
9
+ end
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'cucumber' do
2
+ watch(%r{^features/.+\.feature$})
3
+ watch(%r{^features/support/.+$}) { 'features' }
4
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ben Langfeld
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ cucumber-voip
2
+ ===========
3
+
4
+ Automated functional testing of voice applications is typically difficult and expensive. Not so when we can specify our systems using Cucumber. cucumber-voip provides a powerful set of features based on Punchblock and rspec-rayo which allow you, using the Rayo protocol, to drive a voice application using plain English Cucumber scenarios as if you're the end user.
5
+
6
+ Features
7
+ --------
8
+
9
+ * Rayo connection manager and Cucumber step definitions for common functional testing scenarios
10
+
11
+ Requirements
12
+ ------------
13
+
14
+ * A Rayo server, eg rayo-server on Voxeo PRISM
15
+
16
+ Install
17
+ -------
18
+
19
+ gem install cucumber-voip FIXME (gem install, anything else)
20
+
21
+ Examples
22
+ --------
23
+
24
+ See the features/ directory
25
+
26
+ Author
27
+ ------
28
+
29
+ Original author: Ben Langfeld
30
+
31
+ Links
32
+ -----
33
+ * [Source](https://github.com/benlangfeld/cucumber-voip)
34
+ * [Documentation](http://rdoc.info/github/benlangfeld/cucumber-voip/master/frames)
35
+ * [Bug Tracker](https://github.com/benlangfeld/cucumber-voip/issues)
36
+
37
+ TODO
38
+ ----
39
+
40
+ There is a huge list of things that need to be done in order for this project to be more useful:
41
+
42
+ * A whole bunch more step definitions need to be added
43
+ * Generators should be provided for in-app and standalone usage
44
+ * A boat-load of documentation is required on the following topics:
45
+ * How to setup cucumber-voip in your application or stand-alone
46
+ * How to write features
47
+ * How to write extra step definitions
48
+
49
+ Note on Patches/Pull Requests
50
+ -----------------------------
51
+
52
+ * Fork the project.
53
+ * Make your feature addition or bug fix.
54
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
55
+ * Commit, do not mess with rakefile, version, or history.
56
+ * If you want to have your own version, that is fine but bump version in a commit by itself so I can ignore when I pull
57
+ * Send me a pull request. Bonus points for topic branches.
58
+
59
+ Copyright
60
+ ---------
61
+
62
+ Copyright (c) 2011 Ben Langfeld. MIT licence (see LICENSE for details).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'yard'
5
+ YARD::Rake::YardocTask.new
6
+
7
+ require 'cucumber/rake/task'
8
+
9
+ Cucumber::Rake::Task.new do |t|
10
+ t.cucumber_opts = %w{--tags ~@jruby} unless defined?(JRUBY_VERSION)
11
+ end
12
+
13
+ Cucumber::Rake::Task.new(:wip) do |t|
14
+ t.cucumber_opts = %w{-p wip}
15
+ end
16
+
17
+ task :default => :cucumber
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "cucumber-voip/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "cucumber-voip"
7
+ s.version = CucumberVoIP::VERSION
8
+ s.authors = ["Ben Langfeld"]
9
+ s.email = ["ben@langfeld.me"]
10
+ s.homepage = "https://github.com/benlangfeld/cucumber-voip"
11
+ s.summary = %q{Plain-english functional testing of voice systems}
12
+ s.description = %q{Automated functional testing of voice applications is typically difficult and expensive. Not so when we can specify our systems using Cucumber.}
13
+
14
+ s.rubyforge_project = "cucumber-voip"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency 'cucumber', '>= 1.0.2'
22
+ s.add_runtime_dependency 'activesupport', '>= 3.0.10'
23
+ s.add_runtime_dependency 'rspec-rayo', '>= 0.3.0'
24
+
25
+ s.add_development_dependency 'bundler', '>= 1.0.0'
26
+ s.add_development_dependency 'yard', '>= 0.6.0'
27
+ s.add_development_dependency 'rake', '>= 0'
28
+ s.add_development_dependency 'guard-cucumber'
29
+ end
data/cucumber.yml ADDED
@@ -0,0 +1,2 @@
1
+ default: --tags ~@wip
2
+ wip: --wip --tags @wip
@@ -0,0 +1,28 @@
1
+ Feature: Outbound calls
2
+ As an awesome Ruby telephony developer
3
+ In order to check the most basic operation of my application
4
+ I want to be able to make outbound calls and perform assertions on their progress
5
+
6
+ Scenario: Making a call which is accepted and then hung up
7
+ Given an app which does:
8
+ """
9
+ accept
10
+ hangup
11
+ """
12
+ And a caller ID of 'sip:ben@langfeld.me'
13
+ When I dial 'sip:usera@127.0.0.1'
14
+ Then the call should ring
15
+ And the call should be rejected
16
+
17
+ Scenario: Making a call which is accepted, answered and then hung up
18
+ Given an app which does:
19
+ """
20
+ accept
21
+ answer
22
+ hangup
23
+ """
24
+ And my standard caller ID
25
+ When I dial my app
26
+ Then the call should ring
27
+ And the call should be answered
28
+ And the call should be hung up
@@ -0,0 +1,34 @@
1
+ Feature: Speaking
2
+ As an awesome Ruby telephony developer
3
+ In order to imitate a human being during testing
4
+ I want to be able to use a TTS engine to speak to my app
5
+
6
+ Scenario: Saying hello
7
+ Given an app which does:
8
+ """
9
+ accept
10
+ answer
11
+ sleep 1
12
+ hangup
13
+ """
14
+ And my standard caller ID
15
+ When I dial my app
16
+ Then the call should ring
17
+ And the call should be answered
18
+ When I say 'hello world'
19
+ Then the call should be hung up
20
+
21
+ Scenario: Playing DTMF
22
+ Given an app which does:
23
+ """
24
+ accept
25
+ answer
26
+ sleep 0.5
27
+ hangup
28
+ """
29
+ And my standard caller ID
30
+ When I dial my app
31
+ Then the call should ring
32
+ And the call should be answered
33
+ When I press '5'
34
+ Then the call should be hung up
@@ -0,0 +1,3 @@
1
+ Given /^an app which does:$/ do |script|
2
+ RayoDriver.target_instance.script = script
3
+ end
@@ -0,0 +1,48 @@
1
+ require 'cucumber-voip/cucumber'
2
+
3
+ include CucumberVoIP
4
+
5
+ RayoDriver.options = {
6
+ :standard_caller_id => 'sip:ben@langfeld.me',
7
+ :standard_dial_target => 'sip:usera@127.0.0.1',
8
+ # :jid => 'userb@127.0.0.1',
9
+ # :password => '1',
10
+ # :queue_timeout => 30,
11
+ # :write_timeout => 30,
12
+ # :log_file => 'log/cucumber_voip.log'
13
+ }
14
+
15
+ class RayoDriver
16
+ attr_accessor :script
17
+
18
+ class << self
19
+ def target_instance
20
+ @@target_instance ||= new
21
+ end
22
+ end
23
+ end
24
+
25
+ RayoDriver.target_instance.instance_exec do
26
+ self.options = {
27
+ :jid => 'usera@127.0.0.1',
28
+ # :password => '1',
29
+ # :queue_timeout => 30,
30
+ # :write_timeout => 30,
31
+ }
32
+
33
+ start
34
+
35
+ Thread.new do
36
+ while (call = @rayo.call_queue.pop)
37
+ begin
38
+ call.instance_eval script
39
+ rescue => e
40
+ puts "Exception in the call target script:"
41
+ puts e.message
42
+ puts e.backtrace.join("\n")
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ RayoDriver.start
@@ -0,0 +1,5 @@
1
+ require "cucumber-voip/version"
2
+
3
+ module CucumberVoIP
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,31 @@
1
+ module CucumberVoIP
2
+ module API
3
+ def start_rayo_driver
4
+ RayoDriver.start
5
+ end
6
+
7
+ def cleanup_calls
8
+ RayoDriver.cleanup_calls
9
+ end
10
+
11
+ def standard_caller_id
12
+ RayoDriver.options[:standard_caller_id]
13
+ end
14
+
15
+ def standard_dial_target
16
+ RayoDriver.options[:standard_dial_target]
17
+ end
18
+
19
+ def dial(options = {})
20
+ RayoDriver.dial options
21
+ end
22
+
23
+ def audio_ssml(url)
24
+ "<audio src='#{url}' />"
25
+ end
26
+
27
+ def dtmf_ssml(digit)
28
+ audio_ssml "dtmf:#{digit}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ module Punchblock
2
+ module Component
3
+ class ComponentNode
4
+ attr_accessor :event_queue
5
+
6
+ def initialize(*args)
7
+ super
8
+ @event_queue = Queue.new
9
+ register_event_handler do |event|
10
+ @event_queue << event
11
+ end
12
+ end
13
+
14
+ def next_event(timeout = nil)
15
+ Timeout::timeout(timeout) { event_queue.pop }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ %w{
2
+ rayo_driver
3
+ api
4
+ hooks
5
+ step_definitions
6
+ }.each { |f| require "cucumber-voip/#{f}" }
7
+
8
+ World CucumberVoIP::API
@@ -0,0 +1,13 @@
1
+ # TODO: Figure out how to do this before the suite, rather than before each scenario
2
+ Before do
3
+ # begin
4
+ # start_rayo_driver
5
+ # rescue => e
6
+ # puts e.message
7
+ # puts e.backtrace.join("\n")
8
+ # end
9
+ end
10
+
11
+ After do
12
+ cleanup_calls
13
+ end
@@ -0,0 +1,68 @@
1
+ %w{
2
+ punchblock
3
+ rspec-rayo
4
+ active_support/core_ext/module/delegation
5
+
6
+ cucumber-voip/core_ext/punchblock/component/component_node
7
+ }.each { |f| require f }
8
+
9
+ module CucumberVoIP
10
+ class RayoDriver
11
+ attr_reader :options
12
+
13
+ delegate :cleanup_calls, :dial, :to => :@rayo
14
+
15
+ class << self
16
+ def tester_instance
17
+ @@tester_instance ||= new
18
+ end
19
+
20
+ def method_missing(method_name, *args, &block)
21
+ if tester_instance.respond_to? method_name
22
+ tester_instance.send method_name, *args, &block
23
+ else
24
+ super
25
+ end
26
+ end
27
+
28
+ def respond_to?(method_name)
29
+ super || tester_instance.respond_to?(method_name)
30
+ end
31
+ end
32
+
33
+ def initialize
34
+ @options = {
35
+ :jid => 'userb@127.0.0.1',
36
+ :password => '1',
37
+ :host => '127.0.0.1',
38
+ :queue_timeout => 30,
39
+ :write_timeout => 30
40
+ }
41
+ end
42
+
43
+ def options=(other)
44
+ options.merge! other
45
+ end
46
+
47
+ def start
48
+ raise StandardError, 'You cannot start the Rayo driver more than once!' if @rayo
49
+ @rayo = RSpecRayo::RayoDriver.new :username => options[:jid],
50
+ :password => options[:password],
51
+ :host => options[:host],
52
+ :port => options[:port],
53
+ :queue_timeout => options[:queue_timeout],
54
+ :write_timeout => options[:write_timeout]
55
+ begin
56
+ @rayo.wait_for_connection 10
57
+ rescue Timeout::Error
58
+ abort 'Could not connect to Rayo Server. Aborting!'
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def logger
65
+ @logger ||= Logger.new options[:log_file]
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,45 @@
1
+ Given /^a caller ID of '([\w\d\s\.\:\@]+)'$/ do |caller_id|
2
+ @outbound_caller_id = caller_id
3
+ end
4
+
5
+ Given /^my standard caller ID$/ do
6
+ @outbound_caller_id = standard_caller_id
7
+ end
8
+
9
+ When /^I dial my app$/ do
10
+ @call = dial :from => @outbound_caller_id, :to => standard_dial_target
11
+ end
12
+
13
+ When /^I dial '([\w\d\s\.\:\@]+)'$/ do |target_address|
14
+ @call = dial :from => @outbound_caller_id, :to => target_address
15
+ end
16
+
17
+ Then /^the call should ring$/ do
18
+ @call.next_event.should be_a_valid_ringing_event
19
+ end
20
+
21
+ Then /^the call should be answered$/ do
22
+ @call.next_event.should be_a_valid_answered_event
23
+ end
24
+
25
+ Then /^the call should be hung up$/ do
26
+ @call.next_event.should be_a_valid_hangup_event
27
+ end
28
+
29
+ Then /^the call should be rejected$/ do
30
+ @call.next_event.should be_a_valid_reject_event
31
+ end
32
+
33
+ When /^I hang up$/ do
34
+ @call.hangup.should have_executed_correctly
35
+ end
36
+
37
+ When /^I say '([\w\s]+)'$/ do |phrase|
38
+ component = @call.say(:text => phrase).should have_executed_correctly
39
+ component.next_event.should be_a_valid_say_event
40
+ end
41
+
42
+ When /^I press '([\d\*\#])'$/ do |digit|
43
+ component = @call.output(:ssml => dtmf_ssml(digit)).should have_executed_correctly
44
+ component.next_event.should be_a_valid_output_event
45
+ end
@@ -0,0 +1,3 @@
1
+ module CucumberVoIP
2
+ VERSION = "0.1.0"
3
+ end
data/log/.gitkeep ADDED
File without changes
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber-voip
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ben Langfeld
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: cucumber
16
+ requirement: &2161551780 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.0.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2161551780
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ requirement: &2161551140 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.10
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2161551140
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec-rayo
38
+ requirement: &2161549600 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 0.3.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2161549600
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: &2161549060 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2161549060
58
+ - !ruby/object:Gem::Dependency
59
+ name: yard
60
+ requirement: &2161548180 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 0.6.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *2161548180
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: &2161538500 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *2161538500
80
+ - !ruby/object:Gem::Dependency
81
+ name: guard-cucumber
82
+ requirement: &2161537600 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *2161537600
91
+ description: Automated functional testing of voice applications is typically difficult
92
+ and expensive. Not so when we can specify our systems using Cucumber.
93
+ email:
94
+ - ben@langfeld.me
95
+ executables: []
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - .gitignore
100
+ - CHANGELOG.md
101
+ - Gemfile
102
+ - Guardfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - cucumber-voip.gemspec
107
+ - cucumber.yml
108
+ - features/outbound_calls.feature
109
+ - features/speaking.feature
110
+ - features/step_definitions.rb
111
+ - features/support/env.rb
112
+ - lib/cucumber-voip.rb
113
+ - lib/cucumber-voip/api.rb
114
+ - lib/cucumber-voip/core_ext/punchblock/component/component_node.rb
115
+ - lib/cucumber-voip/cucumber.rb
116
+ - lib/cucumber-voip/hooks.rb
117
+ - lib/cucumber-voip/rayo_driver.rb
118
+ - lib/cucumber-voip/step_definitions.rb
119
+ - lib/cucumber-voip/version.rb
120
+ - log/.gitkeep
121
+ homepage: https://github.com/benlangfeld/cucumber-voip
122
+ licenses: []
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ segments:
134
+ - 0
135
+ hash: -866167120225335433
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ segments:
143
+ - 0
144
+ hash: -866167120225335433
145
+ requirements: []
146
+ rubyforge_project: cucumber-voip
147
+ rubygems_version: 1.8.10
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Plain-english functional testing of voice systems
151
+ test_files:
152
+ - features/outbound_calls.feature
153
+ - features/speaking.feature
154
+ - features/step_definitions.rb
155
+ - features/support/env.rb