bill_forward 1.2014.296

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +27 -0
  2. data/.idea/.name +1 -0
  3. data/.idea/compiler.xml +23 -0
  4. data/.idea/copyright/profiles_settings.xml +3 -0
  5. data/.idea/encodings.xml +5 -0
  6. data/.idea/inspectionProfiles/Project_Default.xml +11 -0
  7. data/.idea/inspectionProfiles/profiles_settings.xml +7 -0
  8. data/.idea/misc.xml +23 -0
  9. data/.idea/modules.xml +9 -0
  10. data/.idea/scopes/scope_settings.xml +5 -0
  11. data/.idea/vcs.xml +7 -0
  12. data/.rspec +2 -0
  13. data/Gemfile +9 -0
  14. data/LICENSE.md +22 -0
  15. data/README.md +227 -0
  16. data/Rakefile +73 -0
  17. data/bill_forward.gemspec +29 -0
  18. data/bill_forward.iml +28 -0
  19. data/lib/bill_forward.rb +18 -0
  20. data/lib/bill_forward/billing_entity.rb +263 -0
  21. data/lib/bill_forward/client.rb +355 -0
  22. data/lib/bill_forward/custom_hash.rb +14 -0
  23. data/lib/bill_forward/deny_method.rb +4 -0
  24. data/lib/bill_forward/entities/account.rb +19 -0
  25. data/lib/bill_forward/entities/address.rb +25 -0
  26. data/lib/bill_forward/entities/amendments/amendment.rb +11 -0
  27. data/lib/bill_forward/entities/amendments/invoice_recalculation_amendment.rb +10 -0
  28. data/lib/bill_forward/entities/api_configuration.rb +11 -0
  29. data/lib/bill_forward/entities/authorize_net_token.rb +9 -0
  30. data/lib/bill_forward/entities/credit_note.rb +13 -0
  31. data/lib/bill_forward/entities/invoice.rb +25 -0
  32. data/lib/bill_forward/entities/invoice_parts/invoice_line.rb +37 -0
  33. data/lib/bill_forward/entities/invoice_parts/invoice_payment.rb +29 -0
  34. data/lib/bill_forward/entities/invoice_parts/tax_line.rb +23 -0
  35. data/lib/bill_forward/entities/invoice_parts/taxation_link.rb +5 -0
  36. data/lib/bill_forward/entities/organisation.rb +37 -0
  37. data/lib/bill_forward/entities/payment_method.rb +5 -0
  38. data/lib/bill_forward/entities/payment_method_subscription_link.rb +5 -0
  39. data/lib/bill_forward/entities/pricing_component.rb +21 -0
  40. data/lib/bill_forward/entities/pricing_component_tier.rb +5 -0
  41. data/lib/bill_forward/entities/pricing_component_value.rb +5 -0
  42. data/lib/bill_forward/entities/pricing_component_value_change.rb +5 -0
  43. data/lib/bill_forward/entities/product.rb +5 -0
  44. data/lib/bill_forward/entities/product_rate_plan.rb +19 -0
  45. data/lib/bill_forward/entities/profile.rb +15 -0
  46. data/lib/bill_forward/entities/role.rb +4 -0
  47. data/lib/bill_forward/entities/subscription.rb +53 -0
  48. data/lib/bill_forward/entities/unit_of_measure.rb +5 -0
  49. data/lib/bill_forward/insertable_entity.rb +32 -0
  50. data/lib/bill_forward/mutable_entity.rb +47 -0
  51. data/lib/bill_forward/resource_path.rb +11 -0
  52. data/lib/bill_forward/type_check.rb +21 -0
  53. data/lib/bill_forward/version.rb +4 -0
  54. data/spec/component/account_spec.rb +200 -0
  55. data/spec/component/billing_entity_spec.rb +153 -0
  56. data/spec/component/invoice_spec.rb +155 -0
  57. data/spec/component/subscription_spec.rb +357 -0
  58. data/spec/functional/account_spec.rb +25 -0
  59. data/spec/functional/bad_citizen/account_spec.rb +103 -0
  60. data/spec/functional/bad_citizen/credit_note_spec.rb +41 -0
  61. data/spec/functional/bad_citizen/payment_method_spec.rb +34 -0
  62. data/spec/functional/bad_citizen/product_rate_plan_spec.rb +105 -0
  63. data/spec/functional/bad_citizen/product_spec.rb +22 -0
  64. data/spec/functional/bad_citizen/situational/authorize_net_token_spec.rb +27 -0
  65. data/spec/functional/bad_citizen/situational/invoice_recalculation_amendment_spec.rb +27 -0
  66. data/spec/functional/bad_citizen/situational/invoice_spec.rb +22 -0
  67. data/spec/functional/bad_citizen/situational/malordered_entity_spec.rb +43 -0
  68. data/spec/functional/bad_citizen/situational/organisation_spec.rb +39 -0
  69. data/spec/functional/bad_citizen/situational/payment_method_spec.rb +47 -0
  70. data/spec/functional/bad_citizen/situational/subscription_chargeable_spec.rb +255 -0
  71. data/spec/functional/bad_citizen/subscription_spec.rb +179 -0
  72. data/spec/functional/bad_citizen/subscription_with_credit_spec.rb +240 -0
  73. data/spec/functional/bad_citizen/unit_of_measure_spec.rb +20 -0
  74. data/spec/functional/billing_entity_spec.rb +22 -0
  75. data/spec/functional/client_spec.rb +24 -0
  76. data/spec/functional/organisation_spec.rb +28 -0
  77. data/spec/setup_test_constants.rb +73 -0
  78. data/spec/spec_helper.rb +11 -0
  79. data/spec/syntax/account_spec.rb +24 -0
  80. data/spec/syntax/address_spec.rb +19 -0
  81. data/spec/syntax/api_configuration_spec.rb +13 -0
  82. data/spec/syntax/billing_entity_spec.rb +93 -0
  83. data/spec/syntax/client_spec.rb +8 -0
  84. metadata +287 -0
data/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea/dictionaries
24
+ .rakeTasks
25
+ onelinechange.bat
26
+ twolinechange.bat
27
+ spec/test_constants.rb
data/.idea/.name ADDED
@@ -0,0 +1 @@
1
+ bill_forward_api_client
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="CompilerConfiguration">
4
+ <option name="DEFAULT_COMPILER" value="Javac" />
5
+ <resourceExtensions />
6
+ <wildcardResourcePatterns>
7
+ <entry name="!?*.java" />
8
+ <entry name="!?*.form" />
9
+ <entry name="!?*.class" />
10
+ <entry name="!?*.groovy" />
11
+ <entry name="!?*.scala" />
12
+ <entry name="!?*.flex" />
13
+ <entry name="!?*.kt" />
14
+ <entry name="!?*.clj" />
15
+ </wildcardResourcePatterns>
16
+ <annotationProcessing>
17
+ <profile default="true" name="Default" enabled="false">
18
+ <processorPath useClasspath="true" />
19
+ </profile>
20
+ </annotationProcessing>
21
+ </component>
22
+ </project>
23
+
@@ -0,0 +1,3 @@
1
+ <component name="CopyrightManager">
2
+ <settings default="" />
3
+ </component>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
4
+ </project>
5
+
@@ -0,0 +1,11 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0" is_locked="false">
3
+ <option name="myName" value="Project Default" />
4
+ <option name="myLocal" value="false" />
5
+ <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
6
+ <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
7
+ <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
8
+ </inspection_tool>
9
+ <inspection_tool class="RubyQuotedStringsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
10
+ </profile>
11
+ </component>
@@ -0,0 +1,7 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="PROJECT_PROFILE" value="Project Default" />
4
+ <option name="USE_PROJECT_PROFILE" value="true" />
5
+ <version value="1.0" />
6
+ </settings>
7
+ </component>
data/.idea/misc.xml ADDED
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="ruby-2.0.0-p451" project-jdk-type="RUBY_SDK">
4
+ <output url="file://$PROJECT_DIR$/out" />
5
+ </component>
6
+ <component name="masterDetails">
7
+ <states>
8
+ <state key="ProjectJDKs.UI">
9
+ <settings>
10
+ <last-edited>1.7</last-edited>
11
+ <splitter-proportions>
12
+ <option name="proportions">
13
+ <list>
14
+ <option value="0.2" />
15
+ </list>
16
+ </option>
17
+ </splitter-proportions>
18
+ </settings>
19
+ </state>
20
+ </states>
21
+ </component>
22
+ </project>
23
+
data/.idea/modules.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/bill_forward_api_client.iml" filepath="$PROJECT_DIR$/bill_forward_api_client.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
9
+
@@ -0,0 +1,5 @@
1
+ <component name="DependencyValidationManager">
2
+ <state>
3
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
4
+ </state>
5
+ </component>
data/.idea/vcs.xml ADDED
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="" vcs="Git" />
5
+ </component>
6
+ </project>
7
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bill_forward.gemspec
4
+ gemspec
5
+
6
+ gem 'rest-client', '~> 1.6.8'
7
+ gem 'json', '~> 1.8.1'
8
+ gem 'require_all'
9
+ gem 'activesupport', '>= 3.1.0', '< 4'
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 BillForward, Inc
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # BillForwardApiClient
2
+
3
+ This client library provides (via Ruby) easy access to the BillForward API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile and run `bundle`:
8
+
9
+ ```ruby
10
+ gem 'bill_forward', :git => 'git@github.com:billforward/bf-ruby.git', :branch => 'master'
11
+ ```
12
+
13
+ Or install this source as a local gem using:
14
+
15
+ ```bash
16
+ bundle
17
+ gem build bill_forward.gemspec
18
+ gem install bill_forward
19
+ ```
20
+
21
+ ## Usage
22
+ ### Including the Gem
23
+
24
+ Once installed, require the BillForward gem:
25
+
26
+ ```ruby
27
+ require 'bill_forward'
28
+ ```
29
+
30
+ ### Getting Credentials
31
+ You will need an API token. First log into your [Sandbox account](https://app-sandbox.billforward.net/login/#/) ([register](https://app-sandbox.billforward.net/register/#/) if necessary).
32
+
33
+ Then [generate an API token](https://app-sandbox.billforward.net/setup/#/personal/api-keys).
34
+
35
+ We support also client-id and client-secret authentication. For details, please [contact BillForward support](http://www.billforward.net/contact-us/).
36
+
37
+ ### Connecting
38
+
39
+ Create a default Client. Requests will be sent using its credentials:
40
+
41
+ ```ruby
42
+ my_client = BillForward::Client.new(
43
+ :host => "API URL goes here",
44
+ :api_token => "API token goes here"
45
+ )
46
+ BillForward::Client.default_client = my_client
47
+ ```
48
+
49
+ ### Invocation
50
+
51
+ ##### Getting single entities:
52
+
53
+ e.g. Get Subscription by ID:
54
+
55
+ ```ruby
56
+ subscription = BillForward::Subscription.get_by_id '3C39A79F-777E-4BDF-BDDC-221652F74E9D'
57
+ puts subscription
58
+ ```
59
+
60
+ ##### Accessing entity variables:
61
+
62
+ The entity can be accessed as a HashWithIndifferentAccess, or as an array.
63
+
64
+ ```ruby
65
+ # The following are equivalent:
66
+ puts subscription.id
67
+ puts subscription['id']
68
+ puts subscription[:id]
69
+ ```
70
+
71
+ ##### Getting a list of entities:
72
+
73
+ e.g. List Accounts
74
+
75
+ ```ruby
76
+ query_params = {
77
+ 'records' => 3,
78
+ 'order_by' => 'created',
79
+ 'order' => 'ASC'
80
+ }
81
+ accounts = BillForward::Account.get_all query_params
82
+ puts accounts
83
+ ```
84
+
85
+ ##### Creating an entity:
86
+
87
+ e.g. Create simple Account
88
+
89
+ ```ruby
90
+ created_account = BillForward::Account.create
91
+ ```
92
+
93
+ e.g. Create complex Account
94
+
95
+ ```ruby
96
+ # Create an account with a profile (where the profile has addresses)
97
+ addresses = Array.new
98
+ addresses.push(
99
+ BillForward::Address.new({
100
+ 'addressLine1' => 'address line 1',
101
+ 'addressLine2' => 'address line 2',
102
+ 'addressLine3' => 'address line 3',
103
+ 'city' => 'London',
104
+ 'province' => 'London',
105
+ 'country' => 'United Kingdom',
106
+ 'postcode' => 'SW1 1AS',
107
+ 'landline' => '02000000000',
108
+ 'primaryAddress' => true
109
+ }))
110
+ profile = BillForward::Profile.new({
111
+ 'email' => 'always@testing.is.moe',
112
+ 'firstName' => 'Test',
113
+ 'addresses' => addresses
114
+ })
115
+ account = BillForward::Account.new({
116
+ 'profile' => profile
117
+ })
118
+ created_account = BillForward::Account.create account
119
+ puts created_account
120
+ ```
121
+
122
+ ##### Updating an entity
123
+
124
+ ```ruby
125
+ gotten_account = BillForward::Account.get_by_id '908AF77A-0E5D-4D80-9B91-31EDE9962BF6'
126
+ gotten_account.profile.email = 'sometimes@testing.is.moe'
127
+ updated_account = gotten_account.save() # or: gotten_account.profile.save()
128
+ puts updated_account
129
+ ```
130
+
131
+ ## Development
132
+ ### Building
133
+ Clone the source, then run `bundle`.
134
+ ```bash
135
+ bundle
136
+ ```
137
+ If ever you add a new dependency, you will need to run this again.
138
+
139
+ To install the gem, run:
140
+ ```ruby
141
+ gem build bill_forward.gemspec
142
+ gem install bill_forward
143
+ ```
144
+
145
+ ### Running tests
146
+ Development is decidedly test-driven.
147
+
148
+ We use RSpec for testing.
149
+
150
+ Run offline tests with:
151
+ ```bash
152
+ rake
153
+ ```
154
+
155
+ If you wish to run online tests also, you will need to declare some test constants. Create a file `test_constants.rb` in the directory `spec/`, containing the following declarations:
156
+
157
+ ```ruby
158
+ module BillForwardTest
159
+ BILLFORWARD_API_HOST='insert-API-URL-here'
160
+ BILLFORWARD_API_TOKEN="insert-access-token-here OR leave-blank-for-OAUTH"
161
+
162
+ ### alternatively:
163
+ # (these values are used if you leave API token blank)
164
+ # authenticate using OAUTH:
165
+ BILLFORWARD_USERNAME="insert-username"
166
+ BILLFORWARD_PASSWORD="insert-password"
167
+ BILLFORWARD_CLIENT_ID="insert-client-id"
168
+ BILLFORWARD_CLIENT_SECRET="insert-client-secret"
169
+
170
+
171
+ # ---- Enable logging if you want (shows request and response bodies)
172
+ USE_LOGGING=false
173
+
174
+
175
+ # ---- Enable proxy if you want (for example to see requests in Fiddler)
176
+ CLIENT_PROXY_ENABLED=false
177
+ CLIENT_PROXY_URL="http://127.0.0.1:8888"
178
+ end
179
+ ```
180
+
181
+ Run main functional tests + offline tests with:
182
+ ```bash
183
+ rake spec_main
184
+ ```
185
+
186
+ There are further tests still that can be run, but these are situational -- for example, they require an invoice to exist already, or require credentials to be declared for a payment gateway.
187
+
188
+ You can specify constants for use in situational tests in the usual test constants file, as before:
189
+
190
+ ```ruby
191
+ module BillForwardTest
192
+ BILLFORWARD_API_HOST='insert-API-URL-here'
193
+ BILLFORWARD_API_TOKEN="insert-access-token-here OR leave-blank-for-OAUTH"
194
+
195
+ ### alternatively:
196
+ # (these values are used if you leave API token blank)
197
+ # authenticate using OAUTH:
198
+ BILLFORWARD_USERNAME="insert-username"
199
+ BILLFORWARD_PASSWORD="insert-password"
200
+ BILLFORWARD_CLIENT_ID="insert-client-id"
201
+ BILLFORWARD_CLIENT_SECRET="insert-client-secret"
202
+
203
+
204
+ # ---- Enable logging if you want (shows request and response bodies)
205
+ USE_LOGGING=false
206
+
207
+
208
+ # ---- Enable proxy if you want (for example to see requests in Fiddler)
209
+ CLIENT_PROXY_ENABLED=false
210
+ CLIENT_PROXY_URL="http://127.0.0.1:8888"
211
+
212
+
213
+ ## These constants are required only for running situational tests (not in the main run):
214
+ # ---- Required for Authorize.Net gateway tests only
215
+ AUTHORIZE_NET_LOGIN_ID = 'FILL IN WITH AUTHORIZE NET LOGIN ID'
216
+ AUTHORIZE_NET_TRANSACTION_KEY = 'FILL IN WITH AUTHORIZE NET TRANSACTION KEY'
217
+ # ---- Required for Authorize.Net tokenization tests only
218
+ AUTHORIZE_NET_CUSTOMER_PROFILE_ID = 12345678 # FILL IN WITH AUTHORIZE NET CUSTOMER PROFILE ID
219
+ AUTHORIZE_NET_CUSTOMER_PAYMENT_PROFILE_ID = 12345678 # FILL IN WITH AUTHORIZE NET CUSTOMER PAYMENT PROFILE ID
220
+ AUTHORIZE_NET_CARD_LAST_4_DIGITS = 1234
221
+ end
222
+ ```
223
+
224
+ Run main functional tests + offline tests + situational tests with:
225
+ ```bash
226
+ rake spec_all
227
+ ```
data/Rakefile ADDED
@@ -0,0 +1,73 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ # these specs test syntax and language features
7
+ syntax_specs = FileList['spec/syntax/*_spec.rb']
8
+ # these specs use mocking to test entities without calling a real API
9
+ component_specs = FileList['spec/component/*_spec.rb']
10
+ # these specs call the API, but in a read-only manner
11
+ functional_good_citizen_specs = FileList['spec/functional/*_spec.rb']
12
+ # these specs call the API, leaving lasting side-effects
13
+ functional_bad_citizen_specs = FileList['spec/functional/bad_citizen/*_spec.rb']
14
+ # these specs call the API, and also require prior setup (for example, ensure an invoice exists beforehand)
15
+ # we do not consider these part of the main run, as they're particularly bad citizens
16
+ functional_situational_specs = FileList['spec/functional/bad_citizen/situational/*_spec.rb']
17
+
18
+ # offline tests
19
+ fast_specs = FileList[]
20
+ fast_specs.concat(syntax_specs)
21
+ fast_specs.concat(component_specs)
22
+
23
+ # offline tests + main functional run
24
+ main_specs = FileList[]
25
+ main_specs.concat(fast_specs)
26
+ puts functional_good_citizen_specs
27
+ main_specs.concat(functional_good_citizen_specs)
28
+ main_specs.concat(functional_bad_citizen_specs)
29
+
30
+ # offline tests + main functional run + situational functional
31
+ all_specs = FileList[]
32
+ all_specs.concat(main_specs)
33
+ all_specs.concat(functional_situational_specs)
34
+
35
+
36
+ RSpec::Core::RakeTask.new(:spec_offline) do |t|
37
+ spec_files = FileList[]
38
+ spec_files.concat(fast_specs)
39
+
40
+ # trick t.pattern into accepting a list of files (otherwise deprecated)
41
+ # otherwise globbing does not work on Windows (only first file is matched)
42
+ t.pattern = spec_files
43
+
44
+ t.rspec_opts = "--color --format documentation"
45
+ end
46
+
47
+ RSpec::Core::RakeTask.new(:spec_main) do |t|
48
+ spec_files = FileList[]
49
+ spec_files.concat(main_specs)
50
+
51
+ # trick t.pattern into accepting a list of files (otherwise deprecated)
52
+ # otherwise globbing does not work on Windows (only first file is matched)
53
+ t.pattern = spec_files
54
+
55
+ t.rspec_opts = "--color --format documentation"
56
+ end
57
+
58
+ RSpec::Core::RakeTask.new(:spec_all) do |t|
59
+ spec_files = FileList[]
60
+ spec_files.concat(all_specs)
61
+
62
+ # trick t.pattern into accepting a list of files (otherwise deprecated)
63
+ # otherwise globbing does not work on Windows (only first file is matched)
64
+ t.pattern = spec_files
65
+
66
+ t.rspec_opts = "--color --format documentation"
67
+ end
68
+
69
+ # Make 'Rspec test run' the default task
70
+ task :default => :spec_offline
71
+ rescue LoadError
72
+ # no rspec available
73
+ end