spreedly 1.0.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.
Files changed (67) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +66 -0
  3. data/README.txt +68 -0
  4. data/Rakefile +72 -0
  5. data/lib/spreedly.rb +154 -0
  6. data/lib/spreedly/common.rb +24 -0
  7. data/lib/spreedly/mock.rb +113 -0
  8. data/lib/spreedly/version.rb +3 -0
  9. data/test/spreedly_gem_test.rb +152 -0
  10. data/test/test_site.yml +2 -0
  11. data/vendor/httparty/History +108 -0
  12. data/vendor/httparty/MIT-LICENSE +20 -0
  13. data/vendor/httparty/Manifest +55 -0
  14. data/vendor/httparty/README +35 -0
  15. data/vendor/httparty/Rakefile +47 -0
  16. data/vendor/httparty/bin/httparty +98 -0
  17. data/vendor/httparty/cucumber.yml +1 -0
  18. data/vendor/httparty/examples/aaws.rb +32 -0
  19. data/vendor/httparty/examples/basic.rb +11 -0
  20. data/vendor/httparty/examples/delicious.rb +37 -0
  21. data/vendor/httparty/examples/google.rb +16 -0
  22. data/vendor/httparty/examples/rubyurl.rb +14 -0
  23. data/vendor/httparty/examples/twitter.rb +31 -0
  24. data/vendor/httparty/examples/whoismyrep.rb +10 -0
  25. data/vendor/httparty/features/basic_authentication.feature +20 -0
  26. data/vendor/httparty/features/command_line.feature +7 -0
  27. data/vendor/httparty/features/deals_with_http_error_codes.feature +26 -0
  28. data/vendor/httparty/features/handles_multiple_formats.feature +34 -0
  29. data/vendor/httparty/features/steps/env.rb +15 -0
  30. data/vendor/httparty/features/steps/httparty_response_steps.rb +26 -0
  31. data/vendor/httparty/features/steps/httparty_steps.rb +15 -0
  32. data/vendor/httparty/features/steps/mongrel_helper.rb +55 -0
  33. data/vendor/httparty/features/steps/remote_service_steps.rb +47 -0
  34. data/vendor/httparty/features/supports_redirection.feature +22 -0
  35. data/vendor/httparty/httparty.gemspec +37 -0
  36. data/vendor/httparty/lib/core_extensions.rb +189 -0
  37. data/vendor/httparty/lib/httparty.rb +201 -0
  38. data/vendor/httparty/lib/httparty/cookie_hash.rb +9 -0
  39. data/vendor/httparty/lib/httparty/exceptions.rb +7 -0
  40. data/vendor/httparty/lib/httparty/logging.rb +35 -0
  41. data/vendor/httparty/lib/httparty/module_inheritable_attributes.rb +25 -0
  42. data/vendor/httparty/lib/httparty/parsers.rb +4 -0
  43. data/vendor/httparty/lib/httparty/parsers/json.rb +74 -0
  44. data/vendor/httparty/lib/httparty/parsers/xml.rb +209 -0
  45. data/vendor/httparty/lib/httparty/request.rb +169 -0
  46. data/vendor/httparty/lib/httparty/response.rb +17 -0
  47. data/vendor/httparty/lib/httparty/version.rb +3 -0
  48. data/vendor/httparty/setup.rb +1585 -0
  49. data/vendor/httparty/spec/fixtures/delicious.xml +23 -0
  50. data/vendor/httparty/spec/fixtures/empty.xml +0 -0
  51. data/vendor/httparty/spec/fixtures/google.html +3 -0
  52. data/vendor/httparty/spec/fixtures/twitter.json +1 -0
  53. data/vendor/httparty/spec/fixtures/twitter.xml +403 -0
  54. data/vendor/httparty/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  55. data/vendor/httparty/spec/hash_spec.rb +49 -0
  56. data/vendor/httparty/spec/httparty/cookie_hash_spec.rb +38 -0
  57. data/vendor/httparty/spec/httparty/parsers/json_spec.rb +44 -0
  58. data/vendor/httparty/spec/httparty/parsers/xml_spec.rb +454 -0
  59. data/vendor/httparty/spec/httparty/request_spec.rb +203 -0
  60. data/vendor/httparty/spec/httparty/response_spec.rb +53 -0
  61. data/vendor/httparty/spec/httparty_spec.rb +259 -0
  62. data/vendor/httparty/spec/spec.opts +3 -0
  63. data/vendor/httparty/spec/spec_helper.rb +21 -0
  64. data/vendor/httparty/spec/string_spec.rb +29 -0
  65. data/vendor/httparty/website/css/common.css +47 -0
  66. data/vendor/httparty/website/index.html +74 -0
  67. metadata +141 -0
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2009-03-17
2
+
3
+ * 1 major enhancement
4
+
5
+ * Initial release.
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,66 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/spreedly.rb
6
+ lib/spreedly/common.rb
7
+ lib/spreedly/mock.rb
8
+ lib/spreedly/version.rb
9
+ test/spreedly_gem_test.rb
10
+ test/test_site.yml
11
+ vendor/httparty/History
12
+ vendor/httparty/MIT-LICENSE
13
+ vendor/httparty/Manifest
14
+ vendor/httparty/README
15
+ vendor/httparty/Rakefile
16
+ vendor/httparty/bin/httparty
17
+ vendor/httparty/cucumber.yml
18
+ vendor/httparty/examples/aaws.rb
19
+ vendor/httparty/examples/basic.rb
20
+ vendor/httparty/examples/delicious.rb
21
+ vendor/httparty/examples/google.rb
22
+ vendor/httparty/examples/rubyurl.rb
23
+ vendor/httparty/examples/twitter.rb
24
+ vendor/httparty/examples/whoismyrep.rb
25
+ vendor/httparty/features/basic_authentication.feature
26
+ vendor/httparty/features/command_line.feature
27
+ vendor/httparty/features/deals_with_http_error_codes.feature
28
+ vendor/httparty/features/handles_multiple_formats.feature
29
+ vendor/httparty/features/steps/env.rb
30
+ vendor/httparty/features/steps/httparty_response_steps.rb
31
+ vendor/httparty/features/steps/httparty_steps.rb
32
+ vendor/httparty/features/steps/mongrel_helper.rb
33
+ vendor/httparty/features/steps/remote_service_steps.rb
34
+ vendor/httparty/features/supports_redirection.feature
35
+ vendor/httparty/httparty.gemspec
36
+ vendor/httparty/lib/core_extensions.rb
37
+ vendor/httparty/lib/httparty.rb
38
+ vendor/httparty/lib/httparty/cookie_hash.rb
39
+ vendor/httparty/lib/httparty/exceptions.rb
40
+ vendor/httparty/lib/httparty/logging.rb
41
+ vendor/httparty/lib/httparty/module_inheritable_attributes.rb
42
+ vendor/httparty/lib/httparty/parsers.rb
43
+ vendor/httparty/lib/httparty/parsers/json.rb
44
+ vendor/httparty/lib/httparty/parsers/xml.rb
45
+ vendor/httparty/lib/httparty/request.rb
46
+ vendor/httparty/lib/httparty/response.rb
47
+ vendor/httparty/lib/httparty/version.rb
48
+ vendor/httparty/setup.rb
49
+ vendor/httparty/spec/fixtures/delicious.xml
50
+ vendor/httparty/spec/fixtures/empty.xml
51
+ vendor/httparty/spec/fixtures/google.html
52
+ vendor/httparty/spec/fixtures/twitter.json
53
+ vendor/httparty/spec/fixtures/twitter.xml
54
+ vendor/httparty/spec/fixtures/undefined_method_add_node_for_nil.xml
55
+ vendor/httparty/spec/hash_spec.rb
56
+ vendor/httparty/spec/httparty/cookie_hash_spec.rb
57
+ vendor/httparty/spec/httparty/parsers/json_spec.rb
58
+ vendor/httparty/spec/httparty/parsers/xml_spec.rb
59
+ vendor/httparty/spec/httparty/request_spec.rb
60
+ vendor/httparty/spec/httparty/response_spec.rb
61
+ vendor/httparty/spec/httparty_spec.rb
62
+ vendor/httparty/spec/spec.opts
63
+ vendor/httparty/spec/spec_helper.rb
64
+ vendor/httparty/spec/string_spec.rb
65
+ vendor/httparty/website/css/common.css
66
+ vendor/httparty/website/index.html
data/README.txt ADDED
@@ -0,0 +1,68 @@
1
+ = Spreedly-Gem
2
+
3
+ * http://terralien.com/static/projects/spreedly-gem/
4
+ * http://github.com/terralien/spreedly-gem
5
+
6
+ == DESCRIPTION:
7
+
8
+ The Spreedly gem provides a convenient Ruby wrapper for the goodness that is
9
+ the http://spreedly.com API. Created by Terralien[http://terralien.com].
10
+
11
+ == FEATURES:
12
+
13
+ * Makes it easy to get started.
14
+ * Fully tested.
15
+ * (Mostly) fully substitutable mock implementation for fast tests.
16
+ * Great example code.
17
+
18
+ == SYNOPSIS:
19
+
20
+ # For real
21
+ require 'spreedly'
22
+ Spreedly.configure('site name', 'crazy hash token')
23
+ url = Spreedly.subscribe_url(:id => 'customer id', :plan => 'plan id')
24
+ subscriber = Spreedly::Subscriber.find('customer id')
25
+ subscriber.active?
26
+
27
+ # For mock
28
+ require 'spreedly/mock'
29
+ Spreedly.configure('site name', 'crazy hash token')
30
+ url = Spreedly.subscribe_url(:id => 'customer id', :plan => 'plan id')
31
+ subscriber = Spreedly::Subscriber.find('customer id')
32
+ subscriber.active?
33
+
34
+ Yup, they're exactly the same except for the require and the speed!
35
+
36
+ == REQUIREMENTS:
37
+
38
+ * A (free) Spreedly account.
39
+ * HTTParty (vendored for now).
40
+
41
+ == INSTALL:
42
+
43
+ `sudo gem install spreedly-gem`
44
+
45
+ == LICENSE:
46
+
47
+ (The MIT License)
48
+
49
+ Copyright (c) 2009 Nathaniel Talbott
50
+
51
+ Permission is hereby granted, free of charge, to any person obtaining
52
+ a copy of this software and associated documentation files (the
53
+ 'Software'), to deal in the Software without restriction, including
54
+ without limitation the rights to use, copy, modify, merge, publish,
55
+ distribute, sublicense, and/or sell copies of the Software, and to
56
+ permit persons to whom the Software is furnished to do so, subject to
57
+ the following conditions:
58
+
59
+ The above copyright notice and this permission notice shall be
60
+ included in all copies or substantial portions of the Software.
61
+
62
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
63
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
64
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
65
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
66
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
67
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
68
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,72 @@
1
+ require 'hoe'
2
+ require './lib/spreedly/version.rb'
3
+
4
+ ENV["COPYFILE_DISABLE"] = "true" # Lose all the fugly ._ files when tar'ing
5
+
6
+ hoe = nil
7
+ Hoe.new('spreedly', Spreedly::VERSION) do |project|
8
+ hoe = project
9
+ project.rubyforge_name = 'terralien'
10
+ project.developer('Nathaniel Talbott', 'nathaniel@terralien.com')
11
+ project.test_globs = ["test/**/*_test.rb"]
12
+ project.extra_dev_deps = ["thoughtbot-shoulda"]
13
+ end
14
+
15
+ def remove_task(*task_names)
16
+ task_names.each do |task_name|
17
+ Rake.application.instance_eval{@tasks.delete(task_name.to_s)}
18
+ end
19
+ end
20
+
21
+ def replace_task(task_name, *args, &block)
22
+ name = (task_name.is_a?(Hash) ? task_name.keys.first : task_name)
23
+ remove_task(name)
24
+ task(task_name, *args, &block)
25
+ end
26
+
27
+ remove_task :docs, 'doc/index.html'
28
+ Rake::RDocTask.new(:docs) do |rd|
29
+ rd.main = hoe.readme_file
30
+ rd.rdoc_dir = 'doc'
31
+
32
+ rd.rdoc_files += ['lib/spreedly.rb', 'lib/spreedly/common.rb', hoe.readme_file]
33
+
34
+ title = "Terralien's Spreedly Gem (#{hoe.version}) Documentation"
35
+
36
+ rd.options << "-t" << title << "-f" << "darkfish"
37
+ end
38
+
39
+ replace_task :publish_docs => [:clean, :docs] do
40
+ host = "terralien@terralien.biz"
41
+
42
+ remote_dir = "/var/www/terralien/www/shared/static/projects/spreedly-gem"
43
+ local_dir = 'doc'
44
+
45
+ sh %{rsync #{hoe.rsync_args} #{local_dir}/ #{host}:#{remote_dir}}
46
+ end
47
+
48
+ desc "Run tests with and without mocking."
49
+ replace_task :test do
50
+ hoe.run_tests
51
+
52
+ ENV["SPREEDLY_TEST"] = "REAL"
53
+ hoe.run_tests
54
+ end
55
+
56
+ desc "Run only mock tests."
57
+ task :test_mock do
58
+ hoe.run_tests
59
+ end
60
+
61
+ desc "Run only real tests."
62
+ task :test_real do
63
+ ENV["SPREEDLY_TEST"] = "REAL"
64
+ hoe.run_tests
65
+ end
66
+
67
+ desc "Run both sets of tests under multiruby"
68
+ replace_task :multi do
69
+ hoe.run_tests(true)
70
+ ENV["SPREEDLY_TEST"] = "REAL"
71
+ hoe.run_tests(true)
72
+ end
data/lib/spreedly.rb ADDED
@@ -0,0 +1,154 @@
1
+ require 'spreedly/common'
2
+ require 'httparty'
3
+
4
+ raise "Mock Spreedly already required!" if defined?(Spreedly::MOCK)
5
+
6
+ =begin rdoc
7
+ Provides a convenient wrapper around the http://spreedly.com API.
8
+ Instead of mucking around with http you can just Spreedly.configure
9
+ and Spreedly::Subscriber.find. Much of the functionality is hung off
10
+ of the Spreedly::Subscriber class, and there's also a
11
+ Spreedly::SubscriptionPlan class.
12
+
13
+ One of the goals of this wrapper is to keep your tests fast while
14
+ also keeping your app working. It does this by providing a drop-in
15
+ replacement for the real Spreedly functionality that skips the
16
+ network and gives you a simple (some might call it stupid)
17
+ implementation that will work for 90% of your tests. At least we
18
+ hope so.
19
+
20
+ Help us make the mock work better by telling us when it doesn't work
21
+ so we can improve it. Thanks!
22
+
23
+ ==Example mock usage:
24
+
25
+ if ENV["SPREEDLY"] == "REAL"
26
+ require 'spreedly'
27
+ else
28
+ require 'spreedly/mock'
29
+ end
30
+ =end
31
+
32
+ module Spreedly
33
+ REAL = "real" # :nodoc:
34
+
35
+ include HTTParty
36
+ headers 'Accept' => 'text/xml'
37
+ headers 'Content-Type' => 'text/xml'
38
+ format :xml
39
+
40
+ # Call this before you start using the API to set things up.
41
+ def self.configure(site_name, token)
42
+ base_uri "https://spreedly.com/api/v4/#{site_name}"
43
+ basic_auth token, 'X'
44
+ @site_name = site_name
45
+ end
46
+
47
+ def self.site_name # :nodoc:
48
+ @site_name
49
+ end
50
+
51
+ def self.to_xml_params(hash) # :nodoc:
52
+ hash.collect do |key, value|
53
+ tag = key.to_s.tr('_', '-')
54
+ result = "<#{tag}>"
55
+ if value.is_a?(Hash)
56
+ result << to_xml_params(value)
57
+ else
58
+ result << value.to_s
59
+ end
60
+ result << "</#{tag}>"
61
+ result
62
+ end.join('')
63
+ end
64
+
65
+ class Resource # :nodoc: all
66
+ def initialize(data)
67
+ @data = data
68
+ end
69
+
70
+ def method_missing(method, *args, &block)
71
+ if method.to_s =~ /\?$/
72
+ send(method.to_s[0..-2])
73
+ elsif @data.include?(method.to_s)
74
+ @data[method.to_s]
75
+ else
76
+ super
77
+ end
78
+ end
79
+ end
80
+
81
+ class Subscriber < Resource
82
+
83
+ # This will DELETE all the subscribers from the site.
84
+ #
85
+ # Only works for tests sites (enforced on the Spreedly side).
86
+ def self.wipe!
87
+ Spreedly.delete('/subscribers.xml')
88
+ end
89
+
90
+ # Creates a new subscriber on Spreedly. The subscriber will NOT
91
+ # be active - they have to pay or you have to comp them for that
92
+ # to happen.
93
+ def self.create!(id, email=nil, screen_name=nil)
94
+ result = Spreedly.post('/subscribers.xml', :body =>
95
+ Spreedly.to_xml_params(:subscriber => {:customer_id => id, :email => email, :screen_name => screen_name}))
96
+ case result.code
97
+ when /2../
98
+ new(result['subscriber'])
99
+ when '403'
100
+ raise "Could not create subscriber: no id passed OR already exists."
101
+ else
102
+ raise "Could not create subscriber: result code #{result.code}."
103
+ end
104
+ end
105
+
106
+ # Looks a subscriber up by id.
107
+ def self.find(id)
108
+ new(Spreedly.get("/subscribers/#{id}.xml")['subscriber'])
109
+ end
110
+
111
+ # Returns all the subscribers in your site.
112
+ def self.all
113
+ Spreedly.get('/subscribers.xml')['subscribers'].collect{|data| new(data)}
114
+ end
115
+
116
+ # Spreedly calls your id for the user the "customer id". This
117
+ # gives you a handy alias so you can just call it "id".
118
+ def id
119
+ customer_id
120
+ end
121
+
122
+ # Allows you to give a complimentary subscription (if the
123
+ # subscriber is inactive) or a complimentary time extension (if
124
+ # the subscriber is inactive). Automatically figures out which
125
+ # to do.
126
+ #
127
+ # Note: units must be one of "days" or "months" (Spreedly
128
+ # enforced).
129
+ def comp(quantity, units, feature_level=nil)
130
+ params = {:duration_quantity => quantity, :duration_units => units}
131
+ params[:feature_level] = feature_level if feature_level
132
+ endpoint = (active? ? "complimentary_time_extensions" : "complimentary_subscriptions")
133
+ result = Spreedly.post("/subscribers/#{id}/#{endpoint}.xml", :body => Spreedly.to_xml_params(endpoint[0..-2] => params))
134
+ case result.code
135
+ when /2../
136
+ when '404'
137
+ raise "Could not comp subscriber: no longer exists."
138
+ when '422'
139
+ raise "Could not comp subscriber: validation failed."
140
+ when '403'
141
+ raise "Could not comp subscriber: invalid comp type (#{endpoint})."
142
+ else
143
+ raise "Could not comp subscriber: result code #{result.code}."
144
+ end
145
+ end
146
+ end
147
+
148
+ class SubscriptionPlan < Resource
149
+ # Returns all of the subscription plans defined in your site.
150
+ def self.all
151
+ Spreedly.get('/subscription_plans.xml')['subscription_plans'].collect{|data| new(data)}
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,24 @@
1
+ Dir[File.dirname(__FILE__) + '/../../vendor/*'].each do |directory|
2
+ next unless File.directory?(directory)
3
+ $LOAD_PATH.unshift File.expand_path(directory + '/lib')
4
+ end
5
+
6
+ require 'uri'
7
+ require 'bigdecimal'
8
+
9
+ require 'spreedly/version'
10
+
11
+ module Spreedly
12
+ # Generates a subscribe url for the given user id and plan.
13
+ def self.subscribe_url(id, plan, screen_name=nil)
14
+ screen_name = (screen_name ? URI.escape(screen_name) : "")
15
+ "https://spreedly.com/#{site_name}/subscribers/#{id}/subscribe/#{plan}/#{screen_name}"
16
+ end
17
+
18
+ # Generates an edit subscriber for the given subscriber token. The
19
+ # token is returned with the subscriber info (i.e. by
20
+ # Subscriber.find).
21
+ def self.edit_subscriber_url(token)
22
+ "https://spreedly.com/#{site_name}/subscriber_accounts/#{token}"
23
+ end
24
+ end
@@ -0,0 +1,113 @@
1
+ require 'spreedly/common'
2
+
3
+ raise "Real Spreedly already required!" if defined?(Spreedly::REAL)
4
+
5
+ module Spreedly
6
+ MOCK = "mock"
7
+
8
+ def self.configure(name, token)
9
+ @site_name = name
10
+ end
11
+
12
+ def self.site_name
13
+ @site_name
14
+ end
15
+
16
+ class Resource
17
+ def self.attributes
18
+ @attributes ||= {}
19
+ end
20
+
21
+ def self.attributes=(value)
22
+ @attributes = value
23
+ end
24
+
25
+ def initialize(params={})
26
+ @attributes = params
27
+ self.class.attributes.each{|k,v| @attributes[k] = v.call}
28
+ end
29
+
30
+ def id
31
+ @attributes[:id]
32
+ end
33
+
34
+ def method_missing(method, *args)
35
+ if method.to_s =~ /\?$/
36
+ send(method.to_s[0..-2], *args)
37
+ elsif @attributes.include?(method)
38
+ @attributes[method]
39
+ else
40
+ super
41
+ end
42
+ end
43
+ end
44
+
45
+ class Subscriber < Resource
46
+ self.attributes = {
47
+ :created_at => proc{Time.now},
48
+ :token => proc{(rand * 1000).round},
49
+ :active => proc{false},
50
+ :store_credit => proc{BigDecimal("0.0")},
51
+ :active_until => proc{nil},
52
+ :feature_level => proc{""},
53
+ }
54
+
55
+ def self.wipe! # :nodoc: all
56
+ @subscribers = nil
57
+ end
58
+
59
+ def self.create!(id, email=nil, screen_name=nil) # :nodoc: all
60
+ sub = new({:id => id, :email => email, :screen_name => screen_name})
61
+
62
+ if subscribers[sub.id]
63
+ raise "Could not create subscriber: already exists."
64
+ end
65
+
66
+ subscribers[sub.id] = sub
67
+ sub
68
+ end
69
+
70
+ def self.find(id)
71
+ subscribers[id]
72
+ end
73
+
74
+ def self.subscribers
75
+ @subscribers ||= {}
76
+ end
77
+
78
+ def self.all
79
+ @subscribers.values
80
+ end
81
+
82
+ def initialize(params={})
83
+ super
84
+ if !id || id == ''
85
+ raise "Could not create subscriber: no id passed OR already exists."
86
+ end
87
+ end
88
+
89
+ def comp(quantity, units, feature_level=nil)
90
+ raise "Could not comp subscriber: no longer exists." unless self.class.find(id)
91
+ raise "Could not comp subscriber: validation failed." unless units && quantity
92
+ current_active_until = (active_until || Time.now)
93
+ @attributes[:active_until] = case units
94
+ when 'days'
95
+ current_active_until + (quantity.to_i * 86400)
96
+ when 'months'
97
+ current_active_until + (quantity.to_i * 30 * 86400)
98
+ end
99
+ @attributes[:feature_level] = feature_level if feature_level
100
+ @attributes[:active] = true
101
+ end
102
+ end
103
+
104
+ class SubscriptionPlan < Resource
105
+ def self.all
106
+ plans.values
107
+ end
108
+
109
+ def self.plans
110
+ @plans ||= {1 => new(:id => 1, :name => 'Default mock plan')}
111
+ end
112
+ end
113
+ end