zendesk_api 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +59 -0
  7. data/LICENSE +19 -0
  8. data/Rakefile +49 -0
  9. data/Readme.md +178 -0
  10. data/lib/zendesk_api.rb +10 -0
  11. data/lib/zendesk_api/actions.rb +176 -0
  12. data/lib/zendesk_api/association.rb +267 -0
  13. data/lib/zendesk_api/client.rb +150 -0
  14. data/lib/zendesk_api/collection.rb +233 -0
  15. data/lib/zendesk_api/configuration.rb +52 -0
  16. data/lib/zendesk_api/core_ext/inflection.rb +13 -0
  17. data/lib/zendesk_api/core_ext/modulize.rb +10 -0
  18. data/lib/zendesk_api/core_ext/snakecase.rb +12 -0
  19. data/lib/zendesk_api/lru_cache.rb +38 -0
  20. data/lib/zendesk_api/middleware/request/etag_cache.rb +38 -0
  21. data/lib/zendesk_api/middleware/request/retry.rb +39 -0
  22. data/lib/zendesk_api/middleware/request/upload.rb +32 -0
  23. data/lib/zendesk_api/middleware/response/callback.rb +19 -0
  24. data/lib/zendesk_api/middleware/response/deflate.rb +18 -0
  25. data/lib/zendesk_api/middleware/response/gzip.rb +18 -0
  26. data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +29 -0
  27. data/lib/zendesk_api/rescue.rb +44 -0
  28. data/lib/zendesk_api/resource.rb +133 -0
  29. data/lib/zendesk_api/resources/forum.rb +51 -0
  30. data/lib/zendesk_api/resources/misc.rb +66 -0
  31. data/lib/zendesk_api/resources/playlist.rb +64 -0
  32. data/lib/zendesk_api/resources/ticket.rb +76 -0
  33. data/lib/zendesk_api/resources/user.rb +44 -0
  34. data/lib/zendesk_api/track_changes.rb +72 -0
  35. data/lib/zendesk_api/trackie.rb +8 -0
  36. data/lib/zendesk_api/verbs.rb +43 -0
  37. data/lib/zendesk_api/version.rb +3 -0
  38. data/live/Readme.md +4 -0
  39. data/live/activity_spec.rb +5 -0
  40. data/live/audit_spec.rb +5 -0
  41. data/live/bookmark_spec.rb +11 -0
  42. data/live/category_spec.rb +12 -0
  43. data/live/collection_spec.rb +68 -0
  44. data/live/crm_spec.rb +11 -0
  45. data/live/custom_role_spec.rb +5 -0
  46. data/live/forum_spec.rb +14 -0
  47. data/live/forum_subscription_spec.rb +12 -0
  48. data/live/group_membership_spec.rb +18 -0
  49. data/live/group_spec.rb +14 -0
  50. data/live/identity_spec.rb +14 -0
  51. data/live/locale_spec.rb +11 -0
  52. data/live/macro_spec.rb +5 -0
  53. data/live/mobile_device_spec.rb +11 -0
  54. data/live/organization_spec.rb +12 -0
  55. data/live/satisfaction_rating_spec.rb +6 -0
  56. data/live/setting_spec.rb +5 -0
  57. data/live/suspended_ticket_spec.rb +8 -0
  58. data/live/ticket_field_spec.rb +12 -0
  59. data/live/ticket_metrics_spec.rb +6 -0
  60. data/live/ticket_spec.rb +88 -0
  61. data/live/topic_comment_spec.rb +13 -0
  62. data/live/topic_spec.rb +18 -0
  63. data/live/topic_subscription_spec.rb +12 -0
  64. data/live/topic_vote_spec.rb +13 -0
  65. data/live/upload_spec.rb +9 -0
  66. data/live/user_spec.rb +13 -0
  67. data/live/view_spec.rb +6 -0
  68. data/spec/association_spec.rb +210 -0
  69. data/spec/client_spec.rb +149 -0
  70. data/spec/collection_spec.rb +302 -0
  71. data/spec/configuration_spec.rb +24 -0
  72. data/spec/create_resource_spec.rb +39 -0
  73. data/spec/data_resource_spec.rb +229 -0
  74. data/spec/fixtures/Argentina.gif +0 -0
  75. data/spec/fixtures/Argentina2.gif +0 -0
  76. data/spec/fixtures/credentials.yml.example +3 -0
  77. data/spec/fixtures/test_resources.rb +8 -0
  78. data/spec/fixtures/zendesk.rb +88 -0
  79. data/spec/lru_cache_spec.rb +26 -0
  80. data/spec/macros/resource_macros.rb +157 -0
  81. data/spec/middleware/request/etag_cache_spec.rb +17 -0
  82. data/spec/middleware/request/retry_spec.rb +47 -0
  83. data/spec/middleware/request/test.jpg +0 -0
  84. data/spec/middleware/request/upload_spec.rb +74 -0
  85. data/spec/middleware/response/callback_spec.rb +17 -0
  86. data/spec/middleware/response/deflate_spec.rb +15 -0
  87. data/spec/middleware/response/gzip_spec.rb +19 -0
  88. data/spec/middleware/response/parse_iso_dates_spec.rb +44 -0
  89. data/spec/playlist_spec.rb +95 -0
  90. data/spec/read_resource_spec.rb +37 -0
  91. data/spec/rescue_spec.rb +94 -0
  92. data/spec/resource_spec.rb +332 -0
  93. data/spec/spec_helper.rb +120 -0
  94. data/spec/string_spec.rb +7 -0
  95. data/spec/trackie_spec.rb +39 -0
  96. data/zendesk_api.gemspec +38 -0
  97. metadata +364 -0
@@ -0,0 +1,24 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe ZendeskAPI::Configuration do
4
+ subject { ZendeskAPI::Configuration.new }
5
+
6
+ it "should properly merge options" do
7
+ url = "test.host"
8
+ subject.url = url
9
+ subject.options[:url].should == url
10
+ end
11
+
12
+ it "should set accept header properly" do
13
+ subject.options[:headers][:accept].should == 'application/json'
14
+ end
15
+
16
+ it "should set user agent header properly" do
17
+ subject.options[:headers][:user_agent].should =~ /ZendeskAPI API/
18
+ end
19
+
20
+ it "should merge options with client_options" do
21
+ subject.client_options = {:ssl => false}
22
+ subject.options[:ssl].should == false
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZendeskAPI::CreateResource do
4
+ context "create" do
5
+ let(:attr) { { :test_field => "blah" } }
6
+ subject { ZendeskAPI::TestResource }
7
+
8
+ before(:each) do
9
+ stub_request(:post, %r{test_resources}).to_return(:body => json)
10
+ end
11
+
12
+ it "should return instance of resource" do
13
+ subject.create(client, attr).should be_instance_of(subject)
14
+ end
15
+
16
+ context "with client error" do
17
+ before(:each) do
18
+ stub_request(:post, %r{test_resources}).to_return(:status => 500)
19
+ end
20
+
21
+ it "should handle it properly" do
22
+ expect { silence_logger { subject.create(client, attr).should be_nil } }.to_not raise_error
23
+ end
24
+ end
25
+ end
26
+
27
+ context "create!" do
28
+ subject { ZendeskAPI::TestResource }
29
+
30
+ before(:each) do
31
+ subject.should_receive(:create).and_return(nil)
32
+ end
33
+
34
+ it "should raise if save fails" do
35
+ expect { subject.create!(client, :test_field => "blah") }.to raise_error
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,229 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZendeskAPI::DataResource do
4
+ context "ZendeskAPI.get_class" do
5
+ it "should create a new class if there is none" do
6
+ ZendeskAPI.const_defined?("Blergh").should be_false
7
+ ZendeskAPI.get_class(:blergh).should == ZendeskAPI::Blergh
8
+ end
9
+
10
+ it "should find the class if it exists" do
11
+ ZendeskAPI.get_class(:tickets).should == ZendeskAPI::Tickets
12
+ end
13
+
14
+ it "should handle 'nil' be passed in" do
15
+ ZendeskAPI.get_class(nil).should be_false
16
+ end
17
+ end
18
+
19
+ specify "singular resource name" do
20
+ ZendeskAPI::Ticket.singular_resource_name.should == "ticket"
21
+ ZendeskAPI::TicketField.singular_resource_name.should == "ticket_field"
22
+ end
23
+
24
+ specify "resource name" do
25
+ ZendeskAPI::Ticket.resource_name.should == "tickets"
26
+ ZendeskAPI::TicketField.resource_name.should == "ticket_fields"
27
+ ZendeskAPI::Category.resource_name.should == "categories"
28
+ end
29
+
30
+ context "user" do
31
+ context "with first order attributes" do
32
+ subject { ZendeskAPI::TestResource.new(client) }
33
+ before(:each) { subject.attributes[:priority] = "normal" }
34
+
35
+ it "should be able to access underlying attributes" do
36
+ subject.priority.should == "normal"
37
+ end
38
+
39
+ it "should be able to change underlying attributes" do
40
+ expect { subject.priority = "urgent" }.to_not raise_error
41
+ end
42
+
43
+ it "should be able to iterate over underlying attributes" do
44
+ expect do
45
+ subject.map do |k, v|
46
+ [k.to_sym, v]
47
+ end
48
+ end.to_not raise_error
49
+ end
50
+ end
51
+
52
+ context "with second order attributes" do
53
+ subject { ZendeskAPI::TestResource.new(client) }
54
+ before(:each) { subject.priority = "normal" }
55
+
56
+ it "should be able to change underlying attributes" do
57
+ subject.priority.should == "normal"
58
+ end
59
+
60
+ it "should be able to change underlying attributes" do
61
+ expect { subject.priority = "urgent" }.to_not raise_error
62
+ end
63
+
64
+ it "should be able to iterate over underlying attributes" do
65
+ expect do
66
+ subject.map do |k, v|
67
+ [k.to_sym, v]
68
+ end
69
+ end.to_not raise_error
70
+ end
71
+ end
72
+ end
73
+
74
+ context "has" do
75
+ before(:each) { ZendeskAPI::TestResource.has :foo }
76
+
77
+ context "class methods" do
78
+ subject { ZendeskAPI::TestResource }
79
+ it "should define a method with the same name" do
80
+ subject.instance_methods.map(&:to_s).should include("foo")
81
+ end
82
+
83
+ it "should create a class if none exists" do
84
+ ZendeskAPI.const_defined?("Foo").should be_true
85
+ end
86
+
87
+ context "with explicit class name" do
88
+ before(:all) { ZendeskAPI::TestResource.has :baz, :class => :foo }
89
+
90
+ it "should not create a baz class" do
91
+ ZendeskAPI.const_defined?("Baz").should be_false
92
+ end
93
+ end
94
+ end
95
+
96
+ context "instance method" do
97
+ context "with no side-loading" do
98
+ subject { ZendeskAPI::TestResource.new(client, :id => 1) }
99
+ before(:each) { stub_json_request(:get, %r{test_resources/\d+/foo}, json(:foo => {})) }
100
+
101
+ it "should attempt to grab the resource from the host" do
102
+ subject.foo.should be_instance_of(ZendeskAPI::Foo)
103
+ end
104
+
105
+ it "should pass the path on to the resource" do
106
+ subject.foo.path.should == "foos"
107
+ end
108
+
109
+ context "with a client error" do
110
+ before(:each) { stub_request(:get, %r{test_resources/\d+/foo}).to_return(:status => 500) }
111
+
112
+ it "should handle it properly" do
113
+ expect { silence_logger{ subject.foo.should be_nil } }.to_not raise_error
114
+ end
115
+ end
116
+
117
+ context "with an explicit path set" do
118
+ before(:each) do
119
+ ZendeskAPI::TestResource.has :foo, :path => "blergh"
120
+ stub_json_request(:get, %r{test_resources/\d+/blergh}, json(:foo => {}))
121
+ end
122
+
123
+ it "should call the right path" do
124
+ subject.foo.should be_instance_of(ZendeskAPI::Foo)
125
+ end
126
+ end
127
+ end
128
+
129
+ context "with side-loading of resource" do
130
+ let(:foo) { { :message => "FOO_OBJ" } }
131
+ subject { ZendeskAPI::TestResource.new(client, :foo => foo) }
132
+
133
+ it "should load foo from the hash" do
134
+ subject.foo.should be_instance_of(ZendeskAPI::Foo)
135
+ end
136
+ end
137
+
138
+ context "with side-loading of id" do
139
+ subject { ZendeskAPI::TestResource.new(client, :foo_id => 1) }
140
+ before(:each) do
141
+ stub_json_request(:get, %r{foos/1}, json("foo" => {}))
142
+ end
143
+
144
+ it "should find foo_id and load it from the api" do
145
+ subject.foo
146
+ end
147
+
148
+ it "should handle nil response from find api" do
149
+ ZendeskAPI::Foo.should_receive(:find).twice.and_return(nil)
150
+ subject.foo.should be_nil
151
+ subject.foo
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ context "has_many" do
158
+ before(:each) { ZendeskAPI::TestResource.has_many :bars }
159
+
160
+ context "class methods" do
161
+ subject { ZendeskAPI::TestResource }
162
+ it "should define a method with the same name" do
163
+ subject.instance_methods.map(&:to_s).should include("bars")
164
+ end
165
+
166
+ it "should create a class if none exists" do
167
+ ZendeskAPI.const_defined?("Bar").should be_true
168
+ end
169
+
170
+ context "with explicit class name" do
171
+ before(:each) { ZendeskAPI::TestResource.has_many :cats, :class => :foo }
172
+
173
+ it "should not create a baz class" do
174
+ ZendeskAPI.const_defined?("Cat").should be_false
175
+ end
176
+ end
177
+ end
178
+
179
+ context "instance method" do
180
+ context "with no side-loading" do
181
+ subject { ZendeskAPI::TestResource.new(client, :id => 1) }
182
+
183
+ it "should not attempt to grab the resource from the host" do
184
+ subject.bars.should be_instance_of(ZendeskAPI::Collection)
185
+ end
186
+
187
+ it "should pass the path on to the resource" do
188
+ subject.bars.path.should == "test_resources/1/bars"
189
+ end
190
+
191
+ context "with an explicit path set" do
192
+ before(:each) do
193
+ ZendeskAPI::TestResource.has_many :bars, :path => "blargh"
194
+ end
195
+
196
+ it "should call the right path" do
197
+ subject.bars.path.should == "test_resources/1/blargh"
198
+ end
199
+ end
200
+ end
201
+
202
+ context "with side-loading of resource" do
203
+ let(:bars) { [{ :message => "FOO_OBJ" }] }
204
+ subject { ZendeskAPI::TestResource.new(client, :bars => bars) }
205
+
206
+ it "should map bars onto Bar class" do
207
+ subject.bars.first.should be_instance_of(ZendeskAPI::Bar)
208
+ end
209
+ end
210
+
211
+ context "with side-loading of id" do
212
+ let(:bars) { [1, 2, 3] }
213
+ subject { ZendeskAPI::TestResource.new(client, :bar_ids => bars) }
214
+
215
+ it "should find foo_id and load it from the api" do
216
+ ZendeskAPI::Bar.should_receive(:find).with(client, kind_of(Hash)).exactly(bars.length).times
217
+ subject.bars
218
+ end
219
+
220
+ it "should handle nil response from find api" do
221
+ ZendeskAPI::Bar.should_receive(:find).with(client, kind_of(Hash)).exactly(bars.length).times.and_return(nil)
222
+ subject.bars.should be_empty
223
+ subject.bars # Test expectations
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end
229
+
@@ -0,0 +1,3 @@
1
+ username: please.change
2
+ password: me
3
+ url: https://my.zendesk.com/api/v2
@@ -0,0 +1,8 @@
1
+ class ZendeskAPI::TestResource < ZendeskAPI::Resource
2
+ class TestChild < ZendeskAPI::Resource
3
+ end
4
+ end
5
+
6
+ class ZendeskAPI::NilResource < ZendeskAPI::Data; end
7
+
8
+ class ZendeskAPI::SingularTestResource < ZendeskAPI::SingularResource; end
@@ -0,0 +1,88 @@
1
+ def user
2
+ @user ||= find_or_create_user "end-user"
3
+ end
4
+
5
+ def current_user
6
+ VCR.use_cassette('current_user') do
7
+ @current_user ||= client.users.find(:id => 'me')
8
+ end
9
+ end
10
+
11
+ def agent
12
+ @agent ||= find_or_create_user "agent"
13
+ end
14
+
15
+ def find_or_create_user(role)
16
+ VCR.use_cassette("valid_user_#{role}") do
17
+ email = "zendesk-api-client-ruby-#{role}-#{client.config.username}"
18
+
19
+ client.users.detect {|u| u.email == email } ||
20
+ client.users.create(
21
+ :name => "Test Valid with role #{role}",
22
+ :verified => true,
23
+ :email => email,
24
+ :role => role
25
+ )
26
+ end
27
+ end
28
+
29
+ def topic
30
+ VCR.use_cassette('valid_topic') do
31
+ @topic ||= forum.topics.first
32
+ @topic ||= client.topics.create(
33
+ :title => "Test Topic",
34
+ :body => "This is the body of a topic.",
35
+ :forum_id => forum.id
36
+ )
37
+ end
38
+ end
39
+
40
+ def forum
41
+ VCR.use_cassette('valid_forum') do
42
+ @forum ||= client.forums.detect {|f| f.topics.any? }
43
+ @forum ||= client.forums.create(:name => "Test Forum", :access => "everybody")
44
+ end
45
+ end
46
+
47
+ def category
48
+ VCR.use_cassette('valid_category') do
49
+ @category ||= client.categories.first
50
+ @category ||= client.categories.create(:name => "Test Category")
51
+ end
52
+ end
53
+
54
+ def ticket
55
+ VCR.use_cassette('valid_ticket') do
56
+ @ticket ||= client.tickets.first
57
+ @ticket ||= client.tickets.create(
58
+ :subject => "Test Ticket",
59
+ :description => "This is a test of the emergency alert system.",
60
+ :requester_id => user.id
61
+ )
62
+ end
63
+ end
64
+
65
+ def suspended_ticket
66
+ VCR.use_cassette('valid_suspended_ticket') do
67
+ @suspended_ticket ||= client.suspended_tickets.first
68
+ end
69
+ end
70
+
71
+ def group
72
+ VCR.use_cassette('valid_group') do
73
+ @ticket ||= client.groups.detect {|g| !g.default}
74
+ @ticket ||= client.groups.create(:name => "Test Group")
75
+ end
76
+ end
77
+
78
+ def organization
79
+ VCR.use_cassette('valid_organization') do
80
+ @organization ||= current_user.organization
81
+ end
82
+ end
83
+
84
+ # Global default options, overwritten if using under
85
+ def default_options
86
+ {}
87
+ end
88
+
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe ZendeskAPI::LRUCache do
4
+ let(:cache){ ZendeskAPI::LRUCache.new(2) }
5
+
6
+ it "writes and reads" do
7
+ cache.write("x", 1).should == 1
8
+ cache.read("x").should == 1
9
+ end
10
+
11
+ it "drops" do
12
+ cache.write("x", 1)
13
+ cache.write("y", 1)
14
+ cache.write("x", 1)
15
+ cache.write("z", 1)
16
+ cache.read("z").should == 1
17
+ cache.read("x").should == 1
18
+ cache.read("y").should == nil
19
+ end
20
+
21
+ it "fetches" do
22
+ cache.fetch("x"){ 1 }.should == 1
23
+ cache.read("x").should == 1
24
+ cache.fetch("x"){ 2 }.should == 1
25
+ end
26
+ end
@@ -0,0 +1,157 @@
1
+ module ResourceMacros
2
+ def under(object, &blk)
3
+ context "under a #{object.class.singular_resource_name}" do
4
+ let(:default_options) { { "#{object.class.singular_resource_name}_id" => object.id } }
5
+ instance_eval(&blk)
6
+ end
7
+ end
8
+
9
+ def it_should_be_creatable(options={})
10
+ context "creation" do
11
+ use_vcr_cassette
12
+ subject { described_class }
13
+
14
+ before(:all) do
15
+ VCR.use_cassette("#{described_class.to_s}_create") do
16
+ @object = described_class.create(client, valid_attributes.merge(default_options))
17
+ end
18
+ end
19
+
20
+ it "should have an id" do
21
+ @object.should_not be_nil
22
+ @object.send(options[:id] || :id).should_not be_nil
23
+ end
24
+
25
+ it "should be findable", :unless => metadata[:not_findable] do
26
+ options = default_options
27
+ options.merge!(:id => @object.id) unless described_class.ancestors.include?(ZendeskAPI::SingularResource)
28
+ described_class.find(client, options).should == @object
29
+ end
30
+
31
+ after(:all) do
32
+ VCR.use_cassette("#{described_class.to_s}_create_delete") do
33
+ @object.destroy
34
+ end
35
+ end if metadata[:delete_after]
36
+ end
37
+ end
38
+
39
+ def it_should_be_updatable(attribute, value = "TESTDATA")
40
+ context "update" do
41
+ use_vcr_cassette
42
+
43
+ before(:all) do
44
+ VCR.use_cassette("#{described_class.to_s}_update_create") do
45
+ @object = described_class.create(client, valid_attributes.merge(default_options))
46
+ end
47
+ end
48
+
49
+ before(:each) do
50
+ @object.send("#{attribute}=", value)
51
+ end
52
+
53
+ it "should be savable" do
54
+ @object.save.should be_true
55
+ end
56
+
57
+ context "after save" do
58
+ before(:each) do
59
+ @object.save
60
+ end
61
+
62
+ it "should keep attributes" do
63
+ @object.send(attribute).should == value
64
+ end
65
+
66
+ it "should be findable", :unless => metadata[:not_findable] do
67
+ options = default_options
68
+ options.merge!(:id => @object.id) unless described_class.ancestors.include?(ZendeskAPI::SingularResource)
69
+ described_class.find(client, options).should == @object
70
+ end
71
+ end
72
+
73
+ after(:all, :if => metadata[:delete_after]) do
74
+ VCR.use_cassette("#{described_class.to_s}_update_delete") do
75
+ @object.destroy
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ def it_should_be_deletable(options = {})
82
+ context "deletion" do
83
+ use_vcr_cassette
84
+
85
+ before(:all) do
86
+ if options[:object]
87
+ @object = options.delete(:object)
88
+ else
89
+ VCR.use_cassette("#{described_class.to_s}_delete_create") do
90
+ @object = described_class.create(client, valid_attributes.merge(default_options))
91
+ end
92
+ end
93
+ end
94
+
95
+ it "should be destroyable" do
96
+ @object.destroy.should be_true
97
+ @object.destroyed?.should be_true
98
+
99
+ if (!options.key?(:find) || options[:find]) && !example.metadata[:not_findable]
100
+ opts = default_options
101
+ opts.merge!(:id => @object.id) unless described_class.ancestors.include?(ZendeskAPI::SingularResource)
102
+ obj = silence_logger{ described_class.find(client, opts) }
103
+
104
+ if options[:find]
105
+ obj.send(options[:find].first).should == options[:find].last
106
+ else
107
+ obj.should be_nil
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ def it_should_be_readable(*args)
115
+ options = args.last.is_a?(Hash) ? args.pop : {}
116
+ create = !!options.delete(:create)
117
+ klass = args.first.is_a?(ZendeskAPI::DataResource) ? args.shift : client
118
+ context_name = "read_#{klass.class}_#{args.join("_")}"
119
+
120
+ context context_name do
121
+ use_vcr_cassette
122
+
123
+ before(:all) do
124
+ VCR.use_cassette("#{described_class.to_s}_#{context_name}_create") do
125
+ @object = described_class.create!(client, valid_attributes.merge(default_options))
126
+ end
127
+ end if create
128
+
129
+ after(:all) do
130
+ VCR.use_cassette("#{described_class.to_s}_#{context_name}_delete") do
131
+ @object.destroy
132
+ end
133
+ end if create
134
+
135
+ it "should be findable" do
136
+ result = klass
137
+ args.each {|a| result = result.send(a, options) }
138
+
139
+ if result.is_a?(ZendeskAPI::Collection)
140
+ result.fetch(true).should_not be_empty
141
+ result.fetch.should include(@object) if create
142
+ object = result.first
143
+ else
144
+ result.should_not be_nil
145
+ result.should == @object if create
146
+ object = result
147
+ end
148
+
149
+ if described_class.respond_to?(:find) && !example.metadata[:not_findable]
150
+ options = default_options
151
+ options.merge!(:id => object.id) unless described_class.ancestors.include?(ZendeskAPI::SingularResource)
152
+ described_class.find(client, options).should_not be_nil
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end