koala 1.0.0 → 1.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/.autotest +12 -0
- data/.gitignore +3 -1
- data/.travis.yml +8 -0
- data/CHANGELOG +26 -2
- data/Gemfile +4 -0
- data/autotest/discover.rb +1 -0
- data/koala.gemspec +8 -8
- data/lib/koala/batch_operation.rb +74 -0
- data/lib/koala/graph_api.rb +103 -102
- data/lib/koala/graph_batch_api.rb +87 -0
- data/lib/koala/graph_collection.rb +54 -0
- data/lib/koala/http_services/net_http_service.rb +92 -0
- data/lib/koala/http_services/typhoeus_service.rb +37 -0
- data/lib/koala/http_services.rb +13 -113
- data/lib/koala/oauth.rb +181 -0
- data/lib/koala/realtime_updates.rb +5 -14
- data/lib/koala/rest_api.rb +13 -8
- data/lib/koala/uploadable_io.rb +137 -77
- data/lib/koala.rb +36 -196
- data/readme.md +51 -32
- data/spec/cases/api_base_spec.rb +4 -4
- data/spec/cases/graph_api_batch_spec.rb +609 -0
- data/spec/cases/http_services/http_service_spec.rb +87 -12
- data/spec/cases/http_services/net_http_service_spec.rb +259 -77
- data/spec/cases/http_services/typhoeus_service_spec.rb +29 -21
- data/spec/cases/koala_spec.rb +55 -0
- data/spec/cases/oauth_spec.rb +1 -1
- data/spec/cases/realtime_updates_spec.rb +3 -3
- data/spec/cases/test_users_spec.rb +1 -1
- data/spec/cases/uploadable_io_spec.rb +56 -14
- data/spec/fixtures/cat.m4v +0 -0
- data/spec/fixtures/mock_facebook_responses.yml +100 -5
- data/spec/spec_helper.rb +2 -1
- data/spec/support/graph_api_shared_examples.rb +106 -35
- data/spec/support/json_testing_fix.rb +18 -0
- data/spec/support/mock_http_service.rb +57 -56
- data/spec/support/rest_api_shared_examples.rb +131 -7
- data/spec/support/setup_mocks_or_live.rb +3 -4
- metadata +34 -47
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
include Koala::TyphoeusService
|
|
6
|
-
end
|
|
4
|
+
Deer = Koala::TyphoeusService
|
|
7
5
|
|
|
8
6
|
describe "TyphoeusService" do
|
|
9
7
|
|
|
10
8
|
describe "TyphoeusService module holder class Deer" do
|
|
11
9
|
before :each do
|
|
12
|
-
# reset
|
|
13
|
-
Deer.always_use_ssl = nil
|
|
10
|
+
# reset global settings
|
|
11
|
+
Deer.always_use_ssl = Deer.proxy = Deer.timeout = nil
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
it "should define a make_request static module method" do
|
|
@@ -29,55 +27,55 @@ describe "TyphoeusService" do
|
|
|
29
27
|
@mock_http_response = stub(Typhoeus::Response, :code => 1, :headers_hash => @mock_headers_hash, :body => @mock_body)
|
|
30
28
|
|
|
31
29
|
# Typhoeus is an included module, so we stub methods on Deer itself
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
Typhoeus::Request.stub(:post).and_return(@mock_http_response)
|
|
31
|
+
Typhoeus::Request.stub(:get).and_return(@mock_http_response)
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
it "should use POST if verb is not GET" do
|
|
37
|
-
|
|
35
|
+
Typhoeus::Request.should_receive(:post).and_return(@mock_http_response)
|
|
38
36
|
Deer.make_request('anything', {}, 'anything')
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
it "should use GET if that verb is specified" do
|
|
42
|
-
|
|
40
|
+
Typhoeus::Request.should_receive(:get).and_return(@mock_http_response)
|
|
43
41
|
Deer.make_request('anything', {}, 'get')
|
|
44
42
|
end
|
|
45
43
|
|
|
46
44
|
describe "the connection" do
|
|
47
45
|
it "should use SSL if the request has an access token" do
|
|
48
|
-
|
|
46
|
+
Typhoeus::Request.should_receive(:post).with(/https\:/, anything)
|
|
49
47
|
|
|
50
48
|
Deer.make_request('anything', {"access_token" => "123"}, 'anything')
|
|
51
49
|
end
|
|
52
50
|
|
|
53
51
|
it "should use SSL if always_use_ssl is true, even if there's no token" do
|
|
54
|
-
|
|
52
|
+
Typhoeus::Request.should_receive(:post).with(/https\:/, anything)
|
|
55
53
|
|
|
56
54
|
Deer.always_use_ssl = true
|
|
57
55
|
Deer.make_request('anything', {}, 'anything')
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
it "should use SSL if the :use_ssl option is provided, even if there's no token" do
|
|
61
|
-
|
|
59
|
+
Typhoeus::Request.should_receive(:post).with(/https\:/, anything)
|
|
62
60
|
|
|
63
61
|
Deer.always_use_ssl = true
|
|
64
62
|
Deer.make_request('anything', {}, 'anything', :use_ssl => true)
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
it "should not use SSL if always_use_ssl is false and there's no token" do
|
|
68
|
-
|
|
66
|
+
Typhoeus::Request.should_receive(:post).with(/http\:/, anything)
|
|
69
67
|
|
|
70
68
|
Deer.make_request('anything', {}, 'anything')
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
it "should use the graph server by default" do
|
|
74
|
-
|
|
72
|
+
Typhoeus::Request.should_receive(:post).with(Regexp.new(Koala::Facebook::GRAPH_SERVER), anything)
|
|
75
73
|
|
|
76
74
|
Deer.make_request('anything', {}, 'anything')
|
|
77
75
|
end
|
|
78
76
|
|
|
79
77
|
it "should use the REST server if the :rest_api option is true" do
|
|
80
|
-
|
|
78
|
+
Typhoeus::Request.should_receive(:post).with(Regexp.new(Koala::Facebook::REST_SERVER), anything)
|
|
81
79
|
|
|
82
80
|
Deer.make_request('anything', {}, 'anything', :rest_api => true)
|
|
83
81
|
end
|
|
@@ -85,35 +83,45 @@ describe "TyphoeusService" do
|
|
|
85
83
|
|
|
86
84
|
it "should pass the arguments to Typhoeus under the :params key" do
|
|
87
85
|
args = {:a => 2}
|
|
88
|
-
|
|
86
|
+
Typhoeus::Request.should_receive(:post).with(anything, hash_including(:params => args))
|
|
89
87
|
|
|
90
88
|
Deer.make_request('anything', args, "post")
|
|
91
89
|
end
|
|
92
90
|
|
|
93
91
|
it "should add the method to the arguments if the method isn't get or post" do
|
|
94
92
|
method = "telekenesis"
|
|
95
|
-
|
|
93
|
+
Typhoeus::Request.should_receive(:post).with(anything, hash_including(:params => {:method => method}))
|
|
96
94
|
|
|
97
95
|
Deer.make_request('anything', {}, method)
|
|
98
96
|
end
|
|
99
97
|
|
|
100
98
|
it "should pass :typhoeus_options to Typhoeus if provided" do
|
|
101
99
|
t_options = {:a => :b}
|
|
102
|
-
|
|
100
|
+
Typhoeus::Request.should_receive(:post).with(anything, hash_including(t_options))
|
|
103
101
|
|
|
104
102
|
Deer.make_request("anything", {}, "post", :typhoeus_options => t_options)
|
|
105
103
|
end
|
|
106
|
-
|
|
104
|
+
|
|
105
|
+
it "should pass proxy and timeout :typhoeus_options to Typhoeus if set globally" do
|
|
106
|
+
Deer.proxy = "http://defaultproxy"
|
|
107
|
+
Deer.timeout = 20
|
|
108
|
+
|
|
109
|
+
t_options = {:proxy => "http://defaultproxy", :timeout => 20}
|
|
110
|
+
Typhoeus::Request.should_receive(:post).with(anything, hash_including(t_options))
|
|
111
|
+
|
|
112
|
+
Deer.make_request("anything", {}, "post")
|
|
113
|
+
end
|
|
114
|
+
|
|
107
115
|
# for live tests, run the Graph API tests with Typhoues, which will run file uploads
|
|
108
116
|
it "should pass any files directly on to Typhoues" do
|
|
109
117
|
args = {:file => File.new(__FILE__, "r")}
|
|
110
|
-
|
|
118
|
+
Typhoeus::Request.should_receive(:post).with(anything, hash_including(:params => args)).and_return(Typhoeus::Response.new)
|
|
111
119
|
Deer.make_request("anything", args, :post)
|
|
112
120
|
end
|
|
113
121
|
|
|
114
122
|
it "should include the path in the request" do
|
|
115
123
|
path = "/a/b/c/1"
|
|
116
|
-
|
|
124
|
+
Typhoeus::Request.should_receive(:post).with(Regexp.new(path), anything)
|
|
117
125
|
|
|
118
126
|
Deer.make_request(path, {}, "post")
|
|
119
127
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Koala" do
|
|
4
|
+
it "has an http_service accessor" do
|
|
5
|
+
Koala.respond_to?(:http_service)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "should let an http service be set" do
|
|
9
|
+
current_service = Koala.http_service
|
|
10
|
+
Koala.http_service = Koala::MockHTTPService
|
|
11
|
+
Koala.http_service.should == Koala::MockHTTPService
|
|
12
|
+
# reset the service back to the original one (important for live tests)
|
|
13
|
+
Koala.http_service = current_service
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "sets Net::HTTP as the base service" do
|
|
17
|
+
Koala.base_http_service.should == Koala::NetHTTPService
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe ".always_use_ssl" do
|
|
21
|
+
it "should be added" do
|
|
22
|
+
# in Ruby 1.8, .methods returns strings
|
|
23
|
+
# in Ruby 1.9, .method returns symbols
|
|
24
|
+
Koala.methods.collect {|m| m.to_sym}.should include(:always_use_ssl)
|
|
25
|
+
Koala.methods.collect {|m| m.to_sym}.should include(:always_use_ssl=)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe ".make_request" do
|
|
30
|
+
|
|
31
|
+
before :each do
|
|
32
|
+
@old_service = Koala.http_service
|
|
33
|
+
Koala.http_service = Koala::MockHTTPService
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
after :each do
|
|
37
|
+
Koala.http_service = @old_service
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should use SSL if Koala.always_use_ssl is set to true, even if there's no token" do
|
|
41
|
+
Koala.http_service.should_receive(:make_request).with(anything, anything, anything, hash_including(:use_ssl => true))
|
|
42
|
+
|
|
43
|
+
Koala.always_use_ssl = true
|
|
44
|
+
Koala.make_request('anything', {}, 'anything')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should allow the caller to override the http_service" do
|
|
48
|
+
http_service = stub
|
|
49
|
+
http_service.should_receive(:make_request)
|
|
50
|
+
|
|
51
|
+
Koala.make_request(anything, anything, anything, :http_service => http_service)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
data/spec/cases/oauth_spec.rb
CHANGED
|
@@ -391,7 +391,7 @@ describe "Koala::Facebook::OAuth" do
|
|
|
391
391
|
# the signed request code is ported directly from Facebook
|
|
392
392
|
# so we only need to test at a high level that it works
|
|
393
393
|
it "should throw an error if the algorithm is unsupported" do
|
|
394
|
-
|
|
394
|
+
MultiJson.stub(:decode).and_return("algorithm" => "my fun algorithm")
|
|
395
395
|
lambda { @oauth.parse_signed_request(@signed_request) }.should raise_error
|
|
396
396
|
end
|
|
397
397
|
|
|
@@ -43,19 +43,19 @@ describe "Koala::Facebook::RealtimeUpdates" do
|
|
|
43
43
|
it "should not allow write access to app_id" do
|
|
44
44
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
|
45
45
|
# this should not throw errors
|
|
46
|
-
|
|
46
|
+
updates.methods.map(&:to_sym).should_not include(:app_id=)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
it "should not allow write access to app_access_token" do
|
|
50
50
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
|
51
51
|
# this should not throw errors
|
|
52
|
-
|
|
52
|
+
updates.methods.map(&:to_sym).should_not include(:app_access_token=)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it "should not allow write access to secret" do
|
|
56
56
|
updates = Koala::Facebook::RealtimeUpdates.new(:app_id => @app_id, :app_access_token => @app_access_token)
|
|
57
57
|
# this should not throw errors
|
|
58
|
-
|
|
58
|
+
updates.methods.map(&:to_sym).should_not include(:secret=)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# init with secret / fetching the token
|
|
@@ -16,7 +16,7 @@ describe "Koala::Facebook::TestUsers" do
|
|
|
16
16
|
raise Exception, "Must supply OAuth app id, secret, app_access_token, and callback to run live subscription tests!"
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
@is_mock =
|
|
19
|
+
@is_mock = Koala.http_service.respond_to?(:mock?) && Koala.http_service.mock?
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
describe "when initializing" do
|
|
@@ -9,6 +9,21 @@ module Koala::MIME
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
describe "Koala::UploadableIO" do
|
|
12
|
+
def rails_3_mocks
|
|
13
|
+
tempfile = stub('Tempfile', :path => "foo")
|
|
14
|
+
uploaded_file = stub('ActionDispatch::Http::UploadedFile',
|
|
15
|
+
:content_type => true,
|
|
16
|
+
:tempfile => tempfile
|
|
17
|
+
)
|
|
18
|
+
tempfile.stub!(:respond_to?).with(:path).and_return(true)
|
|
19
|
+
|
|
20
|
+
[tempfile, uploaded_file]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def sinatra_mocks
|
|
24
|
+
{:type => "type", :tempfile => "Tempfile"}
|
|
25
|
+
end
|
|
26
|
+
|
|
12
27
|
describe "the constructor" do
|
|
13
28
|
describe "when given a file path" do
|
|
14
29
|
before(:each) do
|
|
@@ -29,6 +44,12 @@ describe "Koala::UploadableIO" do
|
|
|
29
44
|
stub_type = @koala_io_params[1] = stub('Content Type')
|
|
30
45
|
Koala::UploadableIO.new(*@koala_io_params).content_type.should == stub_type
|
|
31
46
|
end
|
|
47
|
+
|
|
48
|
+
it "should detect that NetHTTPService must be used" do
|
|
49
|
+
@koala_io_params[0] = mock
|
|
50
|
+
@koala_io_params[0].stub!(:read)
|
|
51
|
+
Koala::UploadableIO.new(*@koala_io_params).requires_base_http_service.should be_true
|
|
52
|
+
end
|
|
32
53
|
end
|
|
33
54
|
|
|
34
55
|
describe "and no content type" do
|
|
@@ -63,13 +84,7 @@ describe "Koala::UploadableIO" do
|
|
|
63
84
|
|
|
64
85
|
describe "when given a Rails 3 ActionDispatch::Http::UploadedFile" do
|
|
65
86
|
before(:each) do
|
|
66
|
-
@tempfile
|
|
67
|
-
@uploaded_file = stub('ActionDispatch::Http::UploadedFile',
|
|
68
|
-
:content_type => true,
|
|
69
|
-
:tempfile => @tempfile
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
@tempfile.stub!(:respond_to?).with(:path).and_return(true)
|
|
87
|
+
@tempfile, @uploaded_file = rails_3_mocks
|
|
73
88
|
end
|
|
74
89
|
|
|
75
90
|
it "should get the content type via the content_type method" do
|
|
@@ -87,10 +102,7 @@ describe "Koala::UploadableIO" do
|
|
|
87
102
|
|
|
88
103
|
describe "when given a Sinatra file parameter hash" do
|
|
89
104
|
before(:each) do
|
|
90
|
-
@file_hash =
|
|
91
|
-
:type => "type",
|
|
92
|
-
:tempfile => "Tempfile"
|
|
93
|
-
}
|
|
105
|
+
@file_hash = sinatra_mocks
|
|
94
106
|
end
|
|
95
107
|
|
|
96
108
|
it "should get the content type from the :type key" do
|
|
@@ -130,9 +142,19 @@ describe "Koala::UploadableIO" do
|
|
|
130
142
|
UploadIO.stub!(:new).with(anything, anything, anything).and_return(@upload_io)
|
|
131
143
|
end
|
|
132
144
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
145
|
+
context "if no filename was provided" do
|
|
146
|
+
it "should call the constructor with the content type, file name, and a dummy file name" do
|
|
147
|
+
UploadIO.should_receive(:new).with(BEACH_BALL_PATH, "content/type", anything).and_return(@upload_io)
|
|
148
|
+
Koala::UploadableIO.new(BEACH_BALL_PATH, "content/type").to_upload_io.should == @upload_io
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
context "if a filename was provided" do
|
|
153
|
+
it "should call the constructor with the content type, file name, and the filename" do
|
|
154
|
+
filename = "file"
|
|
155
|
+
UploadIO.should_receive(:new).with(BEACH_BALL_PATH, "content/type", filename).and_return(@upload_io)
|
|
156
|
+
Koala::UploadableIO.new(BEACH_BALL_PATH, "content/type", filename).to_upload_io
|
|
157
|
+
end
|
|
136
158
|
end
|
|
137
159
|
end
|
|
138
160
|
|
|
@@ -148,4 +170,24 @@ describe "Koala::UploadableIO" do
|
|
|
148
170
|
Koala::UploadableIO.new(BEACH_BALL_PATH).to_file.should == result
|
|
149
171
|
end
|
|
150
172
|
end
|
|
173
|
+
|
|
174
|
+
describe "#binary_content?" do
|
|
175
|
+
it "returns true for Rails 3 file uploads" do
|
|
176
|
+
Koala::UploadableIO.binary_content?(rails_3_mocks.last).should be_true
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it "returns true for Sinatra file uploads" do
|
|
180
|
+
Koala::UploadableIO.binary_content?(rails_3_mocks.last).should be_true
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it "returns true for File objects" do
|
|
184
|
+
Koala::UploadableIO.binary_content?(File.open(BEACH_BALL_PATH)).should be_true
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "returns false for everything else" do
|
|
188
|
+
Koala::UploadableIO.binary_content?(StringIO.new).should be_false
|
|
189
|
+
Koala::UploadableIO.binary_content?(BEACH_BALL_PATH).should be_false
|
|
190
|
+
Koala::UploadableIO.binary_content?(nil).should be_false
|
|
191
|
+
end
|
|
192
|
+
end
|
|
151
193
|
end # describe UploadableIO
|
|
Binary file
|
|
@@ -24,6 +24,18 @@ rest_api:
|
|
|
24
24
|
with_token: '[{"read_stream":1}]'
|
|
25
25
|
no_token: '{"error_code":104,"error_msg":"Requires valid signature","request_args":[{"key":"method","value":"fql.query"},{"key":"format","value":"json"},{"key":"query","value":"select read_stream from permissions where uid = 216743"}]}'
|
|
26
26
|
|
|
27
|
+
/method/fql.multiquery:
|
|
28
|
+
'queries=<%= MultiJson.encode({"query1" => "select post_id from stream where source_id = me()", "query2" => "select fromid from comment where post_id in (select post_id from #query1)", "query3" => "select uid, name from user where uid in (select fromid from #query2)"}) %>':
|
|
29
|
+
get:
|
|
30
|
+
with_token: '[{"name":"query1", "fql_result_set":[]},{"name":"query2", "fql_result_set":[]},{"name":"query3", "fql_result_set":[]}]'
|
|
31
|
+
no_token: '{"error_code":104,"error_msg":"Requires valid signature","request_args":[{"key":"method","value":"fql.query"},{"key":"format","value":"json"},{"key":"query","value":"select read_stream from permissions where uid = 216743"}]}'
|
|
32
|
+
'queries=<%= MultiJson.encode({"query1" => "select first_name from user where uid = 216743", "query2" => "select first_name from user where uid = 2905623"}) %>':
|
|
33
|
+
get:
|
|
34
|
+
with_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Chris"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
|
|
35
|
+
no_token: '[{"name":"query1", "fql_result_set":[{"first_name":"Chris"}]},{"name":"query2", "fql_result_set":[{"first_name":"Alex"}]}]'
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
27
39
|
|
|
28
40
|
# ====== GRAPH API =====
|
|
29
41
|
graph_api:
|
|
@@ -49,7 +61,7 @@ graph_api:
|
|
|
49
61
|
|
|
50
62
|
test_user_no_perms: &test_user_no_perms
|
|
51
63
|
post:
|
|
52
|
-
with_token: '{"id": "777777777", "access_token":"<%=
|
|
64
|
+
with_token: '{"id": "777777777", "access_token":"<%= APP_ACCESS_TOKEN %>", "login_url":"https://www.facebook.com/platform/test_account.."}'
|
|
53
65
|
|
|
54
66
|
test_user_befriended: &test_user_befriended
|
|
55
67
|
post:
|
|
@@ -59,8 +71,60 @@ graph_api:
|
|
|
59
71
|
root:
|
|
60
72
|
ids=contextoptional,naitik:
|
|
61
73
|
get:
|
|
62
|
-
with_token: '
|
|
63
|
-
no_token: '
|
|
74
|
+
with_token: '{"contextoptional":"{}","naitik":"{}"}'
|
|
75
|
+
no_token: '{"contextoptional":"{}","naitik":"{}"}'
|
|
76
|
+
# Ruby 1.8.7 and 1.9.2 generate JSON with different key ordering, hence we have to dynamically generate it here
|
|
77
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "koppel"}]) %>:
|
|
78
|
+
post:
|
|
79
|
+
with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"id\":\"456\"}"}]'
|
|
80
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/picture"}]) %>:
|
|
81
|
+
post:
|
|
82
|
+
with_token: '[{"headers":[{"name":"Location","value":"http://google.com"}]}]'
|
|
83
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me"},{"method" => "get", "relative_url" => "me/friends"}]) %>:
|
|
84
|
+
post:
|
|
85
|
+
with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[]}"}]'
|
|
86
|
+
batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"me"}, {"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
|
|
87
|
+
post:
|
|
88
|
+
with_token: '[{"body":"{\"id\":\"123\"}"}, {"body":"{\"data\":[]}"}]'
|
|
89
|
+
batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights"}, {"method"=>"get", "relative_url"=>"koppel?access_token=#{CGI.escape APP_ACCESS_TOKEN}"}]) %>:
|
|
90
|
+
post:
|
|
91
|
+
with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},{"body":"{\"id\":\"123\"}"}]'
|
|
92
|
+
batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"FEED_ITEM_BATCH/likes"}, {"method"=>"delete", "relative_url"=> "FEED_ITEM_BATCH"}]) %>:
|
|
93
|
+
post:
|
|
94
|
+
with_token: '[{"body": "{\"id\": \"MOCK_LIKE\"}"},{"body":true}]'
|
|
95
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5", "name" => "get-friends"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=get-friends:$.data.*.id}"}"}]) %>:
|
|
96
|
+
post:
|
|
97
|
+
with_token: '[null,{"body":"{}"}]'
|
|
98
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5", "name" => "get-friends", "omit_response_on_success" => false}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=get-friends:$.data.*.id}"}"}]) %>:
|
|
99
|
+
post:
|
|
100
|
+
with_token: '[{"body":"{\"data\":[]}"},{"body":"{}"}]'
|
|
101
|
+
batch=<%= MultiJson.encode([{"method" => "get", "relative_url" => "me/friends?limit=5"}, {"method" => "get", "relative_url" => "?ids=#{CGI.escape "{result=i-dont-exist:$.data.*.id}"}"}]) %>:
|
|
102
|
+
post:
|
|
103
|
+
with_token: '{"error":190,"error_description":"Error validating access token."}'
|
|
104
|
+
batch=<%= MultiJson.encode([{"method" => "post", "relative_url" => "method/fql.query", "body" => "query=select+name+from+user+where+uid%3D4"}]) %>:
|
|
105
|
+
post:
|
|
106
|
+
with_token: '[{"body":"[{\"name\":\"Mark Zuckerberg\"}]"}]'
|
|
107
|
+
|
|
108
|
+
# dependencies
|
|
109
|
+
batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"me", "name" => "getme"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getme"}]) %>:
|
|
110
|
+
post: &batch_dependent
|
|
111
|
+
with_token: '[null,{"body":"{\"id\":\"123\"}"}]'
|
|
112
|
+
batch=<%= MultiJson.encode([{"method"=>"get", "relative_url"=>"#{OAUTH_DATA["app_id"]}/insights", "name" => "getdata"}, {"method"=>"get", "relative_url"=>"koppel", "depends_on" => "getdata"}]) %>:
|
|
113
|
+
post:
|
|
114
|
+
with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
|
|
115
|
+
|
|
116
|
+
# attached files tests
|
|
117
|
+
batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
|
|
118
|
+
post:
|
|
119
|
+
with_token: '[{"body": "{\"error\":{\"type\":\"AnError\", \"message\":\"An error occurred!.\"}}"},null]'
|
|
120
|
+
batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}]) %>&op1_file0=[FILE]:
|
|
121
|
+
post:
|
|
122
|
+
with_token: '[{"body":"{\"id\": \"MOCK_PHOTO\"}"}]'
|
|
123
|
+
batch=<%= MultiJson.encode([{"method"=>"post", "relative_url"=>"me/photos", "attached_files" => "op1_file0"}, {"method"=>"post", "relative_url"=>"koppel/photos", "attached_files" => "op2_file0"}]) %>&op1_file0=[FILE]&op2_file0=[FILE]:
|
|
124
|
+
post:
|
|
125
|
+
with_token: '[{"body":"{\"id\": \"MOCK_PHOTO\"}"}, {"body":"{\"id\": \"MOCK_PHOTO\"}"}]'
|
|
126
|
+
|
|
127
|
+
|
|
64
128
|
/me:
|
|
65
129
|
no_args:
|
|
66
130
|
get:
|
|
@@ -83,6 +147,9 @@ graph_api:
|
|
|
83
147
|
message=Hello, world, from the test suite delete method!:
|
|
84
148
|
post:
|
|
85
149
|
with_token: '{"id": "FEED_ITEM_DELETE"}'
|
|
150
|
+
message=Hello, world, from the test suite batch API!:
|
|
151
|
+
post:
|
|
152
|
+
with_token: '{"id": "FEED_ITEM_BATCH"}'
|
|
86
153
|
link=http://oauth.twoalex.com/&message=Hello, world, from the test suite again!&name=OAuth Playground:
|
|
87
154
|
post:
|
|
88
155
|
with_token: '{"id": "FEED_ITEM_CONTEXT"}'
|
|
@@ -95,6 +162,16 @@ graph_api:
|
|
|
95
162
|
post:
|
|
96
163
|
<<: *token_required
|
|
97
164
|
with_token: '{"id": "MOCK_PHOTO"}'
|
|
165
|
+
/me/videos:
|
|
166
|
+
source=[FILE]:
|
|
167
|
+
post:
|
|
168
|
+
<<: *token_required
|
|
169
|
+
with_token: '{"id": "MOCK_PHOTO"}'
|
|
170
|
+
message=This is the test message&source=[FILE]:
|
|
171
|
+
post:
|
|
172
|
+
<<: *token_required
|
|
173
|
+
with_token: '{"id": "MOCK_PHOTO"}'
|
|
174
|
+
|
|
98
175
|
/koppel:
|
|
99
176
|
no_args:
|
|
100
177
|
get:
|
|
@@ -144,6 +221,24 @@ graph_api:
|
|
|
144
221
|
headers:
|
|
145
222
|
Location: http://facebook.com/
|
|
146
223
|
|
|
224
|
+
/comments:
|
|
225
|
+
ids=http://developers.facebook.com/blog/post/472:
|
|
226
|
+
get:
|
|
227
|
+
with_token: '{"http://developers.facebook.com/blog/post/472": []}'
|
|
228
|
+
no_token: '{"http://developers.facebook.com/blog/post/472": []}'
|
|
229
|
+
ids=http://developers.facebook.com/blog/post/490,http://developers.facebook.com/blog/post/472:
|
|
230
|
+
get:
|
|
231
|
+
with_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
|
|
232
|
+
no_token: '{"http://developers.facebook.com/blog/post/490": [], "http://developers.facebook.com/blog/post/472": []}'
|
|
233
|
+
ids=:
|
|
234
|
+
get:
|
|
235
|
+
body: '{"error": {"type": "OAuthException","message": "Cannot specify an empty identifier"}}'
|
|
236
|
+
code: 400
|
|
237
|
+
no_args:
|
|
238
|
+
get:
|
|
239
|
+
body: '{"error": {"type": "Exception","message": "No node specified"}}'
|
|
240
|
+
code: 500
|
|
241
|
+
|
|
147
242
|
/search:
|
|
148
243
|
q=facebook:
|
|
149
244
|
get:
|
|
@@ -169,7 +264,7 @@ graph_api:
|
|
|
169
264
|
<<: *oauth_error
|
|
170
265
|
client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&type=client_cred:
|
|
171
266
|
post:
|
|
172
|
-
no_token: access_token=<%=
|
|
267
|
+
no_token: access_token=<%= APP_ACCESS_TOKEN %>
|
|
173
268
|
/oauth/exchange_sessions:
|
|
174
269
|
client_id=<%= APP_ID %>&client_secret=<%= SECRET %>&sessions=<%= OAUTH_DATA["session_key"] %>&type=client_cred:
|
|
175
270
|
post:
|
|
@@ -311,4 +406,4 @@ graph_api:
|
|
|
311
406
|
|
|
312
407
|
/777777777:
|
|
313
408
|
no_args:
|
|
314
|
-
<<: *item_deleted
|
|
409
|
+
<<: *item_deleted
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
begin
|
|
2
2
|
require 'bundler/setup'
|
|
3
3
|
rescue LoadError
|
|
4
|
-
puts '
|
|
4
|
+
puts 'Although not required, bundler is recommended for running the tests.'
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
# load the libraries
|
|
@@ -9,6 +9,7 @@ require 'koala'
|
|
|
9
9
|
|
|
10
10
|
# load testing data libraries
|
|
11
11
|
require 'support/live_testing_data_helper'
|
|
12
|
+
require 'support/json_testing_fix' # ensure consistent to_json behavior
|
|
12
13
|
require 'support/mock_http_service'
|
|
13
14
|
require 'support/rest_api_shared_examples'
|
|
14
15
|
require 'support/graph_api_shared_examples'
|