spark_api 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/History.txt +14 -0
  2. data/README.md +42 -233
  3. data/VERSION +1 -1
  4. data/lib/spark_api.rb +1 -0
  5. data/lib/spark_api/authentication/oauth2.rb +39 -9
  6. data/lib/spark_api/authentication/oauth2_impl/cli_provider.rb +96 -0
  7. data/lib/spark_api/authentication/oauth2_impl/faraday_middleware.rb +28 -0
  8. data/lib/spark_api/authentication/oauth2_impl/grant_type_base.rb +7 -2
  9. data/lib/spark_api/authentication/oauth2_impl/single_session_provider.rb +27 -0
  10. data/lib/spark_api/cli.rb +29 -10
  11. data/lib/spark_api/cli/api_auth.rb +1 -0
  12. data/lib/spark_api/cli/oauth2.rb +23 -8
  13. data/lib/spark_api/cli/setup.rb +31 -0
  14. data/lib/spark_api/configuration.rb +10 -2
  15. data/lib/spark_api/configuration/yaml.rb +6 -1
  16. data/lib/spark_api/connection.rb +1 -1
  17. data/lib/spark_api/errors.rb +48 -0
  18. data/lib/spark_api/models.rb +3 -0
  19. data/lib/spark_api/models/account.rb +9 -1
  20. data/lib/spark_api/models/base.rb +24 -19
  21. data/lib/spark_api/models/concerns.rb +7 -0
  22. data/lib/spark_api/models/concerns/destroyable.rb +32 -0
  23. data/lib/spark_api/models/concerns/savable.rb +66 -0
  24. data/lib/spark_api/models/contact.rb +6 -25
  25. data/lib/spark_api/models/dirty.rb +57 -0
  26. data/lib/spark_api/models/finders.rb +0 -4
  27. data/lib/spark_api/models/saved_search.rb +10 -0
  28. data/lib/spark_api/models/subresource.rb +5 -1
  29. data/lib/spark_api/models/subscription.rb +52 -0
  30. data/lib/spark_api/request.rb +17 -4
  31. data/lib/spark_api/response.rb +0 -37
  32. data/script/combined_flow_example.rb +3 -3
  33. data/script/oauth2_example.rb +3 -3
  34. data/spec/fixtures/base.json +3 -1
  35. data/spec/fixtures/contacts/new.json +2 -3
  36. data/spec/fixtures/contacts/new_empty.json +2 -3
  37. data/spec/fixtures/contacts/new_notify.json +1 -1
  38. data/spec/fixtures/{listings/saved_search.json → saved_searches/get.json} +1 -1
  39. data/spec/fixtures/saved_searches/new.json +8 -0
  40. data/spec/fixtures/saved_searches/post.json +12 -0
  41. data/spec/fixtures/saved_searches/update.json +6 -0
  42. data/spec/fixtures/subscriptions/get.json +19 -0
  43. data/spec/fixtures/subscriptions/new.json +13 -0
  44. data/spec/fixtures/subscriptions/post.json +10 -0
  45. data/spec/fixtures/subscriptions/put.json +12 -0
  46. data/spec/fixtures/subscriptions/subscribe.json +5 -0
  47. data/spec/fixtures/subscriptions/update.json +6 -0
  48. data/spec/mock_helper.rb +14 -6
  49. data/spec/oauth2_helper.rb +2 -0
  50. data/spec/spec_helper.rb +4 -7
  51. data/spec/unit/spark_api/authentication/api_auth_spec.rb +0 -1
  52. data/spec/unit/spark_api/authentication/oauth2_impl/faraday_middleware_spec.rb +32 -0
  53. data/spec/unit/spark_api/authentication/oauth2_impl/single_session_provider_spec.rb +9 -0
  54. data/spec/unit/spark_api/authentication/oauth2_spec.rb +29 -3
  55. data/spec/unit/spark_api/authentication_spec.rb +4 -10
  56. data/spec/unit/spark_api/configuration/yaml_spec.rb +4 -3
  57. data/spec/unit/spark_api/configuration_spec.rb +22 -8
  58. data/spec/unit/spark_api/models/account_spec.rb +5 -0
  59. data/spec/unit/spark_api/models/base_spec.rb +27 -0
  60. data/spec/unit/spark_api/models/concerns/destroyable_spec.rb +28 -0
  61. data/spec/unit/spark_api/models/concerns/savable_spec.rb +61 -0
  62. data/spec/unit/spark_api/models/contact_spec.rb +5 -5
  63. data/spec/unit/spark_api/models/dirty_spec.rb +46 -0
  64. data/spec/unit/spark_api/models/finders_spec.rb +0 -7
  65. data/spec/unit/spark_api/models/saved_search_spec.rb +34 -3
  66. data/spec/unit/spark_api/models/shared_listing_spec.rb +1 -1
  67. data/spec/unit/spark_api/models/subscription_spec.rb +106 -0
  68. data/spec/unit/spark_api/multi_client_spec.rb +14 -4
  69. data/spec/unit/spark_api/paginate_spec.rb +0 -1
  70. data/spec/unit/spark_api/request_spec.rb +10 -0
  71. data/spec/unit/spark_api_spec.rb +0 -3
  72. metadata +127 -45
  73. data/lib/spark_api/authentication/oauth2_impl/password_provider.rb +0 -24
@@ -1,15 +1,12 @@
1
1
  require './spec/spec_helper'
2
2
 
3
3
  describe SparkApi::Client, "Client config" do
4
- after(:all) do
5
- reset_config
6
- end
7
-
8
4
  describe "default settings" do
9
5
  it "should return the proper defaults when called with no arguments" do
10
6
  SparkApi.api_key.should be_nil
11
7
  SparkApi.api_secret.should be_nil
12
8
  SparkApi.version.should match("v1")
9
+ SparkApi.ssl_verify.should be_true
13
10
  SparkApi.auth_endpoint.should match("sparkplatform.com/openid")
14
11
  SparkApi.endpoint.should match("api.sparkapi.com")
15
12
  SparkApi.user_agent.should match(/Spark API Ruby Gem .*/)
@@ -33,6 +30,22 @@ describe SparkApi::Client, "Client config" do
33
30
  client.endpoint.should match("http://api.wade.dev.fbsdata.com")
34
31
  client.version.should match("v1")
35
32
  end
33
+
34
+ it "should allow unverified ssl certificates when verification is off" do
35
+ client = SparkApi::Client.new(:auth_endpoint => "https://login.wade.dev.fbsdata.com",
36
+ :endpoint => "https://api.wade.dev.fbsdata.com",
37
+ :ssl_verify => false)
38
+ client.ssl_verify.should be_false
39
+ client.connection.ssl.should eq({:verify=>false})
40
+ end
41
+
42
+ it "should allow restrict ssl certificates when verification is on" do
43
+ client = SparkApi::Client.new(:auth_endpoint => "https://login.wade.dev.fbsdata.com",
44
+ :endpoint => "https://api.wade.dev.fbsdata.com",
45
+ :ssl_verify => true)
46
+ client.ssl_verify.should be_true
47
+ client.connection.ssl.should eq({})
48
+ end
36
49
  end
37
50
 
38
51
  describe "oauth2 instance configuration" do
@@ -44,7 +57,7 @@ describe SparkApi::Client, "Client config" do
44
57
  :endpoint => "http://api.wade.dev.fbsdata.com",
45
58
  :authentication_mode => SparkApi::Authentication::OAuth2)
46
59
  end
47
-
60
+
48
61
  it "should convert the configuration to oauth2 when specified" do
49
62
  oauth2_client.oauthify!
50
63
  oauth2_client.oauth2_provider.should be_a(SparkApi::Authentication::SimpleProvider)
@@ -144,19 +157,20 @@ describe SparkApi::Client, "Client config" do
144
157
  end
145
158
 
146
159
  it "should have correct headers based on configuration" do
160
+ reset_config
147
161
  stub_auth_request
148
162
  stub_request(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/headers").
149
163
  with(:query => {
150
- :ApiSig => "6f0cfef263e0bfe7a9ae1f60063a8ad9",
164
+ :ApiUser => "foobar",
165
+ :ApiSig => "717a066c4f4302c5ca9507e484db4812",
151
166
  :AuthToken => "c401736bf3d3f754f07c04e460e09573"
152
167
  }).
153
168
  to_return(:body => '{"D":{"Success": true,"Results": []}}')
154
- SparkApi.reset
155
169
  SparkApi.configure do |config|
156
170
  config.user_agent = "my useragent"
157
171
  end
158
172
  SparkApi.client.get '/headers'
159
- WebMock.should have_requested(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/headers?ApiSig=6f0cfef263e0bfe7a9ae1f60063a8ad9&AuthToken=c401736bf3d3f754f07c04e460e09573").
173
+ WebMock.should have_requested(:get, "#{SparkApi.endpoint}/#{SparkApi.version}/headers?ApiUser=foobar&ApiSig=717a066c4f4302c5ca9507e484db4812&AuthToken=c401736bf3d3f754f07c04e460e09573").
160
174
  with(:headers => {
161
175
  'User-Agent' => SparkApi::Configuration::DEFAULT_USER_AGENT,
162
176
  SparkApi::Configuration::X_SPARK_API_USER_AGENT => "my useragent",
@@ -72,6 +72,11 @@ describe Account do
72
72
  "Name"=>"My Photo two",
73
73
  "Uri"=>"http://photos.flexmls.com/az/...."
74
74
  },
75
+ {
76
+ "Type"=>"Photo",
77
+ "Name"=>nil,
78
+ "Uri"=>"http://photos.flexmls.com/az/...."
79
+ },
75
80
  {
76
81
  "Type"=>"Logo",
77
82
  "Name"=>"1 My Logo",
@@ -9,8 +9,23 @@ end
9
9
  class MyDefaultModel < Base
10
10
  end
11
11
 
12
+ describe MyExampleModel, "Example model" do
13
+ before(:each) do
14
+ stub_auth_request
15
+ stub_api_get("/test/example", 'base.json')
16
+ @model = MyExampleModel.first
17
+ end
18
+ it "should be persisted" do
19
+ @model.persisted?.should eq(true)
20
+ end
21
+ it "should not be persisted" do
22
+ @new_model = MyExampleModel.new()
23
+ @new_model.persisted?.should eq(false)
24
+ end
25
+ end
12
26
 
13
27
  describe Base, "Base model" do
28
+
14
29
  describe "class methods" do
15
30
  it "should set the element name" do
16
31
  MyExampleModel.element_name.should eq("example")
@@ -69,6 +84,10 @@ describe Base, "Base model" do
69
84
  @model.Name?.should satisfy { |p| [true, false].include?(p) }
70
85
  end
71
86
 
87
+ it "should return a boolean for whether or not a model is persisted through the api" do
88
+ @model.persisted?.should satisfy { |p| [true, false].include?(p) }
89
+ end
90
+
72
91
  it "should raise an Error for a predicate for a non-existant attribute" do
73
92
  lambda { @model.Nonsense? }.should raise_error(NoMethodError)
74
93
  end
@@ -101,6 +120,14 @@ describe Base, "Base model" do
101
120
  @model.should respond_to(:freeze)
102
121
  end
103
122
 
123
+ it "should respond_to a will_change! method for an existing attribute" do
124
+ @model.should respond_to(:Name_will_change!)
125
+ end
126
+
127
+ it "should not respond_to a will_change! method for a non-existant attribute" do
128
+ @model.should_not respond_to(:Nonsense_will_change!)
129
+ end
130
+
104
131
  end
105
132
 
106
133
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ class MyExampleModel < Base
4
+ include Concerns::Destroyable
5
+ self.prefix = "/test/"
6
+ self.element_name = "example"
7
+ end
8
+
9
+ describe Concerns::Destroyable, "Destroyable Concern" do
10
+
11
+ before :each do
12
+ stub_auth_request
13
+ stub_api_get("/test/example", 'base.json')
14
+ @model = MyExampleModel.first
15
+ end
16
+
17
+ it "should not be destroyed" do
18
+ @model.destroyed?.should eq(false)
19
+ end
20
+
21
+ it "should be destroyable" do
22
+ stub_api_delete("/test/example/1")
23
+ @model = MyExampleModel.first
24
+ @model.destroy
25
+ @model.destroyed?.should eq(true)
26
+ end
27
+
28
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ class MyExampleModel < Base
4
+ include Concerns::Savable
5
+ self.prefix = "/test/"
6
+ self.element_name = "example"
7
+ end
8
+
9
+ class MyOtherExampleModel < Base
10
+ include Concerns::Savable
11
+ self.prefix = "/test/"
12
+ self.element_name = "example"
13
+ private
14
+ def resource_pluralized
15
+ "MyOtherExampleModelThatIsPluralized"
16
+ end
17
+ end
18
+
19
+ class MyPluralizedModels < Base
20
+ include Concerns::Savable
21
+ self.prefix = "/test/"
22
+ self.element_name = "example"
23
+ end
24
+
25
+ describe Concerns::Savable, "Model" do
26
+
27
+ before :each do
28
+ stub_auth_request
29
+ end
30
+
31
+ it "should be creatable" do
32
+ @model = MyExampleModel.new({ :Name => "my name" })
33
+ stub_api_post("/test/example", { :MyExampleModels => [ @model.attributes ] }, "base.json")
34
+ @model.save.should eq(true)
35
+ @model.persisted?.should eq(true)
36
+ end
37
+
38
+ it "should be updatable" do
39
+ stub_api_get("/test/example", 'base.json')
40
+ @model = MyExampleModel.first
41
+ @model.Name = "new name"
42
+ stub_api_put("/test/example/1", @model.dirty_attributes)
43
+ @model.save.should eq(true)
44
+ @model.persisted?.should eq(true)
45
+ end
46
+
47
+ it "should allow the pluralize method to be overriden" do
48
+ @model = MyOtherExampleModel.new({ :Name => "my name" })
49
+ stub_api_post("/test/example", { :MyOtherExampleModelThatIsPluralized => [ @model.attributes ] }, "base.json")
50
+ @model.save.should eq(true)
51
+ @model.persisted?.should eq(true)
52
+ end
53
+
54
+ it "should not pluralize the resource if it already is" do
55
+ @model = MyPluralizedModels.new({ :Name => "my name" })
56
+ stub_api_post("/test/example", { :MyPluralizedModels => [ @model.attributes ] }, "base.json")
57
+ @model.save.should eq(true)
58
+ @model.persisted?.should eq(true)
59
+ end
60
+
61
+ end
@@ -1,6 +1,5 @@
1
1
  require './spec/spec_helper'
2
2
 
3
-
4
3
  describe Contact do
5
4
  before(:each) do
6
5
  stub_auth_request
@@ -23,20 +22,21 @@ describe Contact do
23
22
  on_post_it "should save a new contact" do
24
23
  stub_api_post("/contacts", 'contacts/new.json', 'contacts/post.json')
25
24
  c=Contact.new
26
- c.attributes["DisplayName"] = "Contact Four"
27
- c.attributes["PrimaryEmail"] = "contact4@fbsdata.com"
25
+ c.DisplayName = "Contact Four"
26
+ c.PrimaryEmail = "contact4@fbsdata.com"
28
27
  c.save.should be(true)
29
28
  c.Id.should eq('20101230223226074204000000')
30
29
  end
31
30
 
32
31
  on_post_it "should save a new contact and notify" do
33
32
  stub_api_post("/contacts", 'contacts/new_notify.json', 'contacts/post.json')
34
- c=Contact.new
35
- c.notify=true
33
+ c = Contact.new
34
+ c.notify = true
36
35
  c.attributes["DisplayName"] = "Contact Four"
37
36
  c.attributes["PrimaryEmail"] = "contact4@fbsdata.com"
38
37
  c.save.should be(true)
39
38
  c.Id.should eq('20101230223226074204000000')
39
+ c.ResourceUri.should eq('/v1/contacts/20101230223226074204000000')
40
40
  end
41
41
 
42
42
  on_post_it "should fail saving" do
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ class MyExampleModel < Base
4
+ include Concerns::Savable
5
+ self.prefix = "/test/"
6
+ self.element_name = "example"
7
+ end
8
+
9
+ describe Dirty do
10
+
11
+ before :each do
12
+ stub_auth_request
13
+ @model = MyExampleModel.new(:Name => "some old name")
14
+ @model.Name = "a new name"
15
+ end
16
+
17
+ it "should return an array of the attributes that have been changed" do
18
+ @model.changed.should eq(["Name"])
19
+ end
20
+
21
+ it "should return a hash diff of current changes on a model" do
22
+ @model.changes.should eq({
23
+ "Name" => ["some old name", "a new name"]
24
+ })
25
+ end
26
+
27
+ it "should return previously changed attributes after save" do
28
+ stub_api_post('/test/example', { :MyExampleModels => [ @model.attributes ] }, 'base.json')
29
+ @model.save
30
+ @model.previous_changes.should eq({
31
+ })
32
+ end
33
+
34
+ it "should return changed attributes with old values" do
35
+ @model.changed_attributes.should eq({
36
+ "Name" => "some old name"
37
+ })
38
+ end
39
+
40
+ it "should return changed attributes with new values" do
41
+ @model.dirty_attributes.should eq({
42
+ "Name" => "a new name"
43
+ })
44
+ end
45
+
46
+ end
@@ -9,22 +9,15 @@ describe Finders, "Finders model" do
9
9
 
10
10
  before(:each) do
11
11
  stub_auth_request
12
- end
13
-
14
- it "should get all results" do
15
12
  stub_api_get("/my_resource", 'finders.json')
16
- resources = MyResource.all
17
- resources.size.should eq(2)
18
13
  end
19
14
 
20
15
  it "should get first result" do
21
- stub_api_get("/my_resource", 'finders.json')
22
16
  resource = MyResource.first
23
17
  resource.Id.should eq(1)
24
18
  end
25
19
 
26
20
  it "should get last result" do
27
- stub_api_get("/my_resource", 'finders.json')
28
21
  resource = MyResource.last
29
22
  resource.Id.should eq(2)
30
23
  end
@@ -9,27 +9,58 @@ describe SavedSearch do
9
9
  let(:id){ "20100815220615294367000000" }
10
10
 
11
11
  context "/savedsearches", :support do
12
+
12
13
  on_get_it "should get all SavedSearches" do
13
- stub_api_get("/#{subject.class.element_name}", 'listings/saved_search.json')
14
+ stub_api_get("/#{subject.class.element_name}", 'saved_searches/get.json')
14
15
  resources = subject.class.get
15
16
  resources.should be_an(Array)
16
17
  resources.length.should eq(2)
17
18
  resources.first.Id.should eq(id)
18
19
  end
20
+
21
+ on_post_it "should create a saved search" do
22
+ stub_api_post("/#{subject.class.element_name}", "saved_searches/new.json", "saved_searches/post.json")
23
+ resource = SavedSearch.new({ :Name => "A new search name here" })
24
+ resource.should respond_to(:save)
25
+ resource.save
26
+ resource.persisted?.should eq(true)
27
+ resource.attributes['Id'].should eq("20100815220615294367000000")
28
+ resource.attributes['ResourceUri'].should eq("/v1/savedsearches/20100815220615294367000000")
29
+ end
30
+
19
31
  end
20
32
 
21
33
  context "/savedsearches/<search_id>", :support do
34
+
22
35
  on_get_it "should get a SavedSearch" do
23
- stub_api_get("/#{subject.class.element_name}/#{id}", 'listings/saved_search.json')
36
+ stub_api_get("/#{subject.class.element_name}/#{id}", 'saved_searches/get.json')
24
37
  resource = subject.class.find(id)
25
38
  resource.Id.should eq(id)
26
39
  resource.Name.should eq("Search name here")
27
40
  end
41
+
42
+ on_put_it "should update a SavedSearch" do
43
+ stub_api_get("/#{subject.class.element_name}/#{id}", "saved_searches/get.json")
44
+ stub_api_put("/#{subject.class.element_name}/#{id}", "saved_searches/update.json", "saved_searches/post.json")
45
+ resource = subject.class.find(id)
46
+ resource.should respond_to(:save)
47
+ resource.Name = "A new search name here"
48
+ resource.save
49
+ end
50
+
51
+ on_delete_it "should delete a saved search" do
52
+ stub_api_get("/#{subject.class.element_name}/#{id}", "saved_searches/get.json")
53
+ stub_api_delete("/#{subject.class.element_name}/#{id}", "generic_delete.json")
54
+ resource = subject.class.find(id)
55
+ resource.should respond_to(:delete)
56
+ resource.delete
57
+ end
58
+
28
59
  end
29
60
 
30
61
  context "/provided/savedsearches", :support do
31
62
  on_get_it "should get provided SavedSearches" do
32
- stub_api_get("/provided/#{subject.class.element_name}", 'listings/saved_search.json')
63
+ stub_api_get("/provided/#{subject.class.element_name}", 'saved_searches/get.json')
33
64
  resources = subject.class.provided.get
34
65
  resources.should be_an(Array)
35
66
  resources.length.should eq(2)
@@ -20,7 +20,7 @@ describe SharedListing do
20
20
  end
21
21
 
22
22
  on_post_it "should fail creating" do
23
- stub_api_post("/#{subject.class.element_name}",'empty.json') do |request|
23
+ stub_api_post("/#{subject.class.element_name}",{}) do |request|
24
24
  request.to_return(:status => 400, :body => fixture('errors/failure.json'))
25
25
  end
26
26
  subject
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ describe Subscription do
4
+
5
+ it "responds to crud methods" do
6
+ Subscription.should respond_to(:get)
7
+ Subscription.new.should respond_to(:save)
8
+ Subscription.new.should respond_to(:delete)
9
+ end
10
+
11
+ before :each do
12
+ stub_auth_request
13
+ end
14
+
15
+ let(:id){ "20101230223226074204000000" }
16
+
17
+ context "/subscriptions", :support do
18
+
19
+ on_get_it "should get sum subscriptions" do
20
+ stub_api_get("/subscriptions", "subscriptions/get.json")
21
+ subject.class.get
22
+ end
23
+
24
+ on_post_it "should create a new subscription" do
25
+ @subscription = Subscription.new({
26
+ :Name => "A new subscription name",
27
+ :SearchId => "20101230223226074204000000",
28
+ :RecipientIds => [ "20101230223226074204000000" ],
29
+ :Subject => "my subject",
30
+ :Message => "my message"
31
+ })
32
+ stub_api_post("/subscriptions", 'subscriptions/new.json', 'subscriptions/post.json')
33
+ @subscription.save.should be(true)
34
+ @subscription.persisted?.should eq(true)
35
+ end
36
+
37
+ it "should subscribe a contact by id" do
38
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
39
+ stub_api_put("/subscriptions/#{id}/subscribers/20101230223226074306000000", nil, 'subscriptions/subscribe.json')
40
+ resource = subject.class.find(id)
41
+ resource.subscribe("20101230223226074306000000")
42
+ resource.RecipientIds.size.should eq(2)
43
+ resource.RecipientIds.any? { |c| c == "20101230223226074306000000" }.should eq(true)
44
+ end
45
+
46
+ it "should unsubscribe a contact by id" do
47
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
48
+ stub_api_delete("/subscriptions/#{id}/subscribers/20101230223226074307000000", 'generic_delete.json')
49
+ resource = subject.class.find(id)
50
+ resource.unsubscribe("20101230223226074307000000")
51
+ resource.RecipientIds.size.should eq(0)
52
+ end
53
+
54
+ it "should subscribe a contact by Contact object" do
55
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
56
+ stub_api_put("/subscriptions/#{id}/subscribers/20101230223226074306000000", nil, 'subscriptions/subscribe.json')
57
+ resource = subject.class.find(id)
58
+ resource.subscribe(Contact.new({ :Id => "20101230223226074306000000" }))
59
+ resource.RecipientIds.size.should eq(2)
60
+ resource.RecipientIds.any? { |c| c == "20101230223226074306000000" }.should eq(true)
61
+ end
62
+
63
+ it "should unsubscribe a contact by Contact object" do
64
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
65
+ stub_api_delete("/subscriptions/#{id}/subscribers/20101230223226074307000000", 'generic_delete.json')
66
+ resource = subject.class.find(id)
67
+ resource.unsubscribe(Contact.new({ :Id => "20101230223226074307000000" }))
68
+ resource.RecipientIds.size.should eq(0)
69
+ end
70
+
71
+ it "should initialize RecipientIds as an array if nil" do
72
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
73
+ stub_api_put("/subscriptions/#{id}/subscribers/20101230223226074306000000", nil, 'subscriptions/subscribe.json')
74
+ resource = subject.class.find(id)
75
+ resource.RecipientIds = nil
76
+ resource.subscribe(Contact.new({ :Id => "20101230223226074306000000" }))
77
+ resource.RecipientIds.size.should eq(1)
78
+ end
79
+
80
+ end
81
+
82
+ context "/subscriptions/:id", :support do
83
+
84
+ on_get_it "should get a subscription" do
85
+ stub_api_get("/subscriptions/#{id}", "subscriptions/get.json")
86
+ subject.class.find(id)
87
+ end
88
+
89
+ on_put_it "should update a subscription" do
90
+ stub_api_get("/subscriptions/#{id}", 'subscriptions/get.json')
91
+ stub_api_put("/subscriptions/#{id}", 'subscriptions/update.json', 'subscriptions/post.json')
92
+ resource = subject.class.find(id)
93
+ resource.Name = "A new subscription name"
94
+ resource.save.should be(true)
95
+ end
96
+
97
+ on_delete_it "should delete a subscription" do
98
+ stub_api_get("/subscriptions/#{id}", 'subscriptions/get.json')
99
+ stub_api_delete("/subscriptions/#{id}", 'generic_delete.json')
100
+ resource = subject.class.find(id)
101
+ resource.delete
102
+ end
103
+
104
+ end
105
+
106
+ end