baidu-sdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +15 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +17 -0
  7. data/Guardfile +6 -0
  8. data/HISTORY.md +2 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +161 -0
  11. data/Rakefile +4 -0
  12. data/baidu-pcs.gemspec +24 -0
  13. data/lib/baidu/configure.rb +27 -0
  14. data/lib/baidu/core.rb +19 -0
  15. data/lib/baidu/errors/error.rb +22 -0
  16. data/lib/baidu/oauth.rb +11 -0
  17. data/lib/baidu/oauth/client.rb +66 -0
  18. data/lib/baidu/oauth/flow/base.rb +44 -0
  19. data/lib/baidu/oauth/flow/code.rb +69 -0
  20. data/lib/baidu/oauth/flow/device.rb +75 -0
  21. data/lib/baidu/pcs.rb +19 -0
  22. data/lib/baidu/pcs/client.rb +1090 -0
  23. data/lib/baidu/session.rb +36 -0
  24. data/lib/baidu/support/cacert.pem +37 -0
  25. data/lib/baidu/support/request.rb +127 -0
  26. data/lib/baidu/support/util.rb +67 -0
  27. data/lib/baidu/version.rb +5 -0
  28. data/spec/baidu/core_spec.rb +20 -0
  29. data/spec/baidu/oauth/client_spec.rb +199 -0
  30. data/spec/baidu/pcs/client_spec.rb +878 -0
  31. data/spec/baidu/session_spec.rb +27 -0
  32. data/spec/baidu/support/request_spec.rb +58 -0
  33. data/spec/baidu/support/util_spec.rb +48 -0
  34. data/spec/fixtures/add_task.json +1 -0
  35. data/spec/fixtures/cancel_task.json +3 -0
  36. data/spec/fixtures/copy.json +7 -0
  37. data/spec/fixtures/delete.json +3 -0
  38. data/spec/fixtures/diff.json +17 -0
  39. data/spec/fixtures/empty.json +1 -0
  40. data/spec/fixtures/get_token_code.json +8 -0
  41. data/spec/fixtures/get_token_device.json +8 -0
  42. data/spec/fixtures/list.json +11 -0
  43. data/spec/fixtures/list_task_0.json +1 -0
  44. data/spec/fixtures/list_task_1.json +1 -0
  45. data/spec/fixtures/listrecycle.json +23 -0
  46. data/spec/fixtures/logo.png +0 -0
  47. data/spec/fixtures/meta.json +11 -0
  48. data/spec/fixtures/mkdir.json +7 -0
  49. data/spec/fixtures/move.json +8 -0
  50. data/spec/fixtures/query_task_0.json +24 -0
  51. data/spec/fixtures/query_task_1.json +22 -0
  52. data/spec/fixtures/quota.json +5 -0
  53. data/spec/fixtures/rapidupload.json +10 -0
  54. data/spec/fixtures/refresh_token.json +8 -0
  55. data/spec/fixtures/restore.json +1 -0
  56. data/spec/fixtures/search.json +11 -0
  57. data/spec/fixtures/stream_list.json +16 -0
  58. data/spec/fixtures/streaming.m3u8 +5 -0
  59. data/spec/fixtures/upload.json +9 -0
  60. data/spec/fixtures/upload_block.json +4 -0
  61. data/spec/fixtures/user_and_device_code.json +8 -0
  62. data/spec/spec_helper.rb +66 -0
  63. metadata +169 -0
@@ -0,0 +1,36 @@
1
+ # encoding: UTF-8
2
+
3
+ module Baidu
4
+ class Session
5
+ # 用户身份验证和授权的凭证
6
+ # @return [String]
7
+ attr_accessor :access_token
8
+ # 用于刷新 Access Token 的 Refresh Token,并不是所有应用都会返回该参数(10年的有效期)
9
+ # @return [String]
10
+ attr_accessor :refresh_token
11
+ # Access Token 最终的访问范围,即用户实际授予的权限列表
12
+ # @return [String]
13
+ attr_accessor :scope
14
+ # 基于 http 调用 Open API 时所需要的 Session Key
15
+ # @return [String]
16
+ attr_accessor :session_key
17
+ # 基于 http 调用 Open API 时计算参数签名用的签名密钥
18
+ # @return [String]
19
+ attr_accessor :session_secret
20
+
21
+ class << self
22
+ # 根据 Hash 数据创建一个新的 +Session+ 实例
23
+ # @param [Hash] hash 包含 Session 所需数据的 Hash
24
+ # @return [Session]
25
+ def from(hash)
26
+ session = Session.new
27
+ session.access_token = hash[:access_token]
28
+ session.refresh_token = hash[:refresh_token]
29
+ session.scope = hash[:scope]
30
+ session.session_key = hash[:session_key]
31
+ session.session_secret = hash[:session_secret]
32
+ session
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ VeriSign Class 3 International Server CA - G3
2
+ =============================================
3
+ -----BEGIN CERTIFICATE-----
4
+ MIIGKTCCBRGgAwIBAgIQZBvoIM4CCBPzLU0tldZ+ZzANBgkqhkiG9w0BAQUFADCB
5
+ yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
6
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
7
+ U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
8
+ ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
9
+ aG9yaXR5IC0gRzUwHhcNMTAwMjA4MDAwMDAwWhcNMjAwMjA3MjM1OTU5WjCBvDEL
10
+ MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
11
+ ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2UgYXQg
12
+ aHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDE2MDQGA1UEAxMtVmVy
13
+ aVNpZ24gQ2xhc3MgMyBJbnRlcm5hdGlvbmFsIFNlcnZlciBDQSAtIEczMIIBIjAN
14
+ BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmdacYvAV9IGaQQhZjxOdF8mfUdza
15
+ sVLv/+NB3eDfxCjG4615HycQmLi7IJfBKERBD+qpqFLPTU4bi7u1xHbZzFYG7rNV
16
+ ICreFY1xy1TIbxfNiQDk3P/hwB9ocenHKS5+vDv85burJlSLZpDN9pK5MSSAvJ5s
17
+ 1fx+0uFLjNxC+kRLX/gYtS4w9D0SmNNiBXNUppyiHb5SgzoHRsQ7AlYhv/JRT9Cm
18
+ mTnprqU/iZucff5NYAclIPe712mDK4KTQzfZg0EbawurSmaET0qO3n40mY5o1so5
19
+ BptMs5pITRNGtFghBMT7oE2sLktiEuP7TfbJUQABH/weaoEqOOC5T9YtRQIDAQAB
20
+ o4ICFTCCAhEwEgYDVR0TAQH/BAgwBgEB/wIBADBwBgNVHSAEaTBnMGUGC2CGSAGG
21
+ +EUBBxcDMFYwKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9j
22
+ cHMwKgYIKwYBBQUHAgIwHhocaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTAO
23
+ BgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
24
+ Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDov
25
+ L2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwNAYDVR0lBC0wKwYIKwYBBQUH
26
+ AwEGCCsGAQUFBwMCBglghkgBhvhCBAEGCmCGSAGG+EUBCAEwNAYIKwYBBQUHAQEE
27
+ KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC52ZXJpc2lnbi5jb20wNAYDVR0f
28
+ BC0wKzApoCegJYYjaHR0cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy1nNS5jcmww
29
+ KAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFZlcmlTaWduTVBLSS0yLTcwHQYDVR0O
30
+ BBYEFNebfNgioBX33a1fzimbWMO8RgC1MB8GA1UdIwQYMBaAFH/TZafC3ey78DAJ
31
+ 80M5+gKvMzEzMA0GCSqGSIb3DQEBBQUAA4IBAQBxtX1zUkrd1000Ky6vlEalSVAC
32
+ T/gvF3DyE9wfIYaqwk98NzzURniuXXhv0bpavBCrWDbFjGIVRWAXIeLVQqh3oVXY
33
+ QwRR9m66SOZdTLdE0z6k1dYzmp8N5tdOlkSVWmzWoxZTDphDzqS4w2Z6BVxiEOgb
34
+ Ett9LnZQ/9/XaxvMisxx+rNAVnwzeneUW/ULU/sOX7xo+68q7jA3eRaTJX9NEP9X
35
+ +79uOzMh3nnchhdZLUNkt6Zmh+q8lkYZGoaLb9e3SQBb26O/KZru99MzrqP0nkzK
36
+ XmnUG623kHdq2FlveasB+lXwiiFm5WVu/XzT3x7rfj8GkPsZC9MGAht4Q5mo
37
+ -----END CERTIFICATE-----
@@ -0,0 +1,127 @@
1
+ # encoding: UTF-8
2
+
3
+ module Baidu
4
+ module Support
5
+ module Request
6
+ include Baidu::Support
7
+
8
+ # 最多重定向次数
9
+ MAX_REDIRECT_LIMIT = 10
10
+
11
+ # 发送 GET 请求
12
+ #
13
+ # @param [String] path
14
+ # @param [Hash] query 自动清理 value 为 nil 的数据
15
+ # @option options [String] :site
16
+ # @option options [Boolean] :raw 直接返回 response.body
17
+ # @option options [Hash] :headers
18
+ # @yield [segment] 可选,如果提供 block,则以流的方式获取内容
19
+ def get(path, query={}, options={}, &block)
20
+ url = build_url path, query, options[:site]
21
+ req = Net::HTTP::Get.new(url, options[:headers])
22
+ if block_given?
23
+ request(req) do |resp|
24
+ resp.read_body &block
25
+ end
26
+ else
27
+ request(req, nil, options[:raw])
28
+ end
29
+ end
30
+
31
+ # 发送 POST 请求
32
+ #
33
+ # @param [String] path
34
+ # @param [Hash] query 自动清理 value 为 nil 的数据
35
+ # @param [Hash] body 自动清理 value 为 nil 的数据,可以包含响应 +#read+ 的对象,如:+File+
36
+ # @option options [String] :site
37
+ def post(path, query={}, body={}, options={})
38
+ uri = build_url path, query, options[:site]
39
+ Util.clean_params(body)
40
+ if body.select{ |_, v| v.respond_to? :read }.empty?
41
+ req = Net::HTTP::Post.new uri
42
+ req.body = (body.empty? ? nil : Util.encode_params(body))
43
+ else
44
+ require 'net/http/post/multipart'
45
+ body.each { |k, v| body[k] = UploadIO.new v, 'application/octet-stream' if v.respond_to? :read }
46
+ req = Net::HTTP::Post::Multipart.new uri, body
47
+ end
48
+ request req
49
+ end
50
+
51
+ private
52
+
53
+ def request(req, body=nil, raw=false, limit=0, &block)
54
+ uri = URI(req.path)
55
+ http = Net::HTTP.new uri.host, uri.port
56
+ # trick for 1.9 support, just use req.uri for ruby version 2
57
+ path_uri = URI(uri.path)
58
+ path_uri.query = uri.query
59
+ req.instance_variable_set(:@path, path_uri.to_s)
60
+ # end trick
61
+ http.set_debug_output $stdout if Baidu.debug
62
+ http.use_ssl = uri.scheme == 'https'
63
+ if http.use_ssl?
64
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
65
+ http.cert_store = OpenSSL::X509::Store.new
66
+ http.cert_store.set_default_paths
67
+ http.cert_store.add_file File.expand_path('../cacert.pem', __FILE__)
68
+ end
69
+
70
+ req['User-Agent'] = "UnofficialRubySDK/baidu-sdk/#{Baidu::VERSION}"
71
+
72
+ if block_given?
73
+ # To avoid read_body read called twice
74
+ return http.request req, body, &block
75
+ else
76
+ resp = http.request req, body
77
+ resp_body = resp.body
78
+
79
+ # when raw, return quickly without JSON parse
80
+ return resp_body if resp.is_a?(Net::HTTPSuccess) && raw
81
+
82
+ resp_hash = begin
83
+ JSON.parse(resp_body, symbolize_names: true) unless resp_body.nil?
84
+ rescue
85
+ nil
86
+ end || {}
87
+
88
+ case resp
89
+ when Net::HTTPSuccess
90
+ return resp_hash
91
+ when Net::HTTPRedirection
92
+ # Process redirection
93
+ limit += 1
94
+ return process_redirect resp['Location'], raw, limit
95
+ end
96
+
97
+ # error
98
+ err = case resp
99
+ when Net::HTTPUnauthorized then Baidu::Errors::AuthError
100
+ when Net::HTTPClientError then Baidu::Errors::ClientError
101
+ when Net::HTTPServerError then Baidu::Errors::ServerError
102
+ else Baidu::Errors::Error
103
+ end
104
+
105
+ code = resp_hash.nil? ? resp.code : (resp_hash[:error_code] || resp_hash[:error])
106
+ msg = resp_hash.nil? ? resp.msg : (resp_hash[:error_msg] || resp_hash[:error_description])
107
+ raise err.new(msg, code, resp)
108
+ end
109
+ end
110
+
111
+ def build_url(path, query, site)
112
+ uri = URI(site || @site)
113
+ uri.path = path
114
+ unless Util.blank? query
115
+ Util.clean_params query
116
+ uri.query = Util.encode_params(query)
117
+ end
118
+ uri.to_s
119
+ end
120
+
121
+ def process_redirect(url, raw, limit)
122
+ raise Baidu::Errors::Error.new('Too many redirects') if limit > MAX_REDIRECT_LIMIT
123
+ request(Net::HTTP::Get.new(url), nil, raw, limit)
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: UTF-8
2
+
3
+ module Baidu
4
+ module Support
5
+ module Util
6
+ class << self
7
+ # Check whether +obj+ is blank or not
8
+ # @example
9
+ # blank?(' ') #true
10
+ # blank?('i ') #false
11
+ # blank?(nil) #true
12
+ # blank?(true) #false
13
+ # blank?(false) #true
14
+ # blank?({}) #true
15
+ #
16
+ # @param [Object] obj
17
+ def blank?(obj)
18
+ case obj
19
+ when String then /[^[:space:]]/ !~ obj
20
+ when NilClass then true
21
+ when TrueClass then false
22
+ when FalseClass then true
23
+ else obj.respond_to?(:empty?) ? obj.empty? : !obj
24
+ end
25
+ end
26
+
27
+ # Encode params to www form style
28
+ # @example
29
+ # encode_params({first: 'Lonre', last: 'Wang'})
30
+ # => 'first=Lonre&last=Wang'
31
+ # @param [Hash] params
32
+ # @return [String]
33
+ def encode_params(params)
34
+ raise ArgumentError, 'require Hash instance' unless params.is_a? Hash
35
+ URI::encode_www_form params
36
+ end
37
+
38
+ # Delete object which value is +nil+ from params
39
+ # @example
40
+ # clean_params({first: 'Lonre', middle: nil, last: 'Wang'})
41
+ # => {first: 'Lonre', last: 'Wang'}
42
+ # @param [Hash] params
43
+ # @return [Hash]
44
+ def clean_params(params)
45
+ raise ArgumentError, 'require Hash instance' unless params.is_a? Hash
46
+ unless blank? params
47
+ params.delete_if { |k, v| v.nil? }
48
+ end
49
+ end
50
+
51
+ # Change +"\\ ? | " > < : "*+ to +"_"+, multi "/" to one "/"
52
+ # @example
53
+ # edit_path(" .hello///path<f:aa/go.zip. ")
54
+ # => "hello/path_f_aa/go.zip"
55
+ # @return [String]
56
+ def edit_path(path)
57
+ return nil if path.nil?
58
+ path = path.gsub(/\/+/, '/')
59
+ path = path.gsub(/\A[\s\.]*/, '')
60
+ path = path.gsub(/[\s\.]*\z/, '')
61
+ path = path.gsub(/[\\\|\?"><:\*]/, '_')
62
+ path
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+
3
+ module Baidu
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Baidu do
6
+ describe '.config' do
7
+ before do
8
+ Baidu.config {}
9
+ end
10
+
11
+ it 'has default debug config' do
12
+ expect(Baidu.debug).to be_false
13
+ end
14
+
15
+ it 'sets debug config to true' do
16
+ Baidu.config { |c| c.debug = true }
17
+ expect(Baidu.debug).to be_true
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,199 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+ require 'baidu/oauth'
5
+
6
+ describe Baidu::OAuth::Client do
7
+ let(:authorization_endpoint) { 'https://openapi.baidu.com/oauth/2.0/authorize' }
8
+ let(:device_endpoint) { 'https://openapi.baidu.com/oauth/2.0/device/code' }
9
+
10
+ before(:all) do
11
+ Baidu.config do |c|
12
+ c.client_id = 'ci'
13
+ c.client_secret = 'cs'
14
+ end
15
+ end
16
+
17
+ before(:each) do
18
+ @client = Baidu::OAuth::Client.new do |config|
19
+ config.access_token = 'at'
20
+ config.refresh_token = 'rt'
21
+ config.session_key = 'sk'
22
+ config.session_secret = 'ss'
23
+ end
24
+ end
25
+
26
+ context '.initialize' do
27
+ it 'assigns right config' do
28
+ expect(@client.client_id).to eq('ci')
29
+ expect(@client.client_secret).to eq('cs')
30
+ end
31
+
32
+ it 'overwrites client_id and client_secret' do
33
+ @client = Baidu::OAuth::Client.new('ci2', 'cs2')
34
+ expect(@client.client_id).to eq('ci2')
35
+ expect(@client.client_secret).to eq('cs2')
36
+ end
37
+
38
+ it 'does not touch endpoint' do
39
+ expect(Baidu::OAuth::SITE).to eq('https://openapi.baidu.com')
40
+ expect(Baidu::OAuth::AUTHORIZATION_ENDPOINT).to eq('/oauth/2.0/authorize')
41
+ expect(Baidu::OAuth::TOKEN_ENDPOINT).to eq('/oauth/2.0/token')
42
+ expect(@client.instance_variable_get('@site')).to eq('https://openapi.baidu.com')
43
+ end
44
+ end
45
+
46
+ context '#authorize_url' do
47
+ it 'generates "Authorization Code" authorize url' do
48
+ url = @client.code_flow.authorize_url('oob')
49
+ expect(url).to eq("#{authorization_endpoint}?response_type=code&display=page&" \
50
+ "client_id=ci&redirect_uri=oob")
51
+ end
52
+
53
+ it 'generates "Authorization Code" authorize url with params' do
54
+ url = @client.code_flow.authorize_url('http://www.example.com/oauth_redirect',
55
+ scope: 'email', state: 'xyz', display: 'tv',
56
+ force_login: 1, confirm_login: 1)
57
+ expect(url).to eq("#{authorization_endpoint}?response_type=code&display=tv&" \
58
+ "scope=email&state=xyz&force_login=1&confirm_login=1&client_id=ci&" \
59
+ "redirect_uri=http%3A%2F%2Fwww.example.com%2Foauth_redirect")
60
+ end
61
+
62
+ it 'raises error when using device flow' do
63
+ expect {
64
+ @client.device_flow.authorize_url
65
+ }.to raise_error(NoMethodError, 'no such method in device flow')
66
+ end
67
+ end
68
+
69
+ context '#user_and_device_code' do
70
+
71
+ it 'requests user and device code' do
72
+ stub_get(:oauth, '/oauth/2.0/device/code', client_id: 'ci', response_type: 'device_code').
73
+ to_return(status: 200, body: ft('user_and_device_code.json'))
74
+ @client.device_flow.user_and_device_code
75
+ a_get(:oauth, '/oauth/2.0/device/code', client_id: 'ci', response_type: 'device_code').
76
+ should have_been_made
77
+ end
78
+
79
+ it 'requests user and device code with scope' do
80
+ stub_get(:oauth, '/oauth/2.0/device/code', client_id: 'ci',
81
+ response_type: 'device_code', scope: 'basic netdisk').
82
+ to_return(status: 200, body: ft('user_and_device_code.json'))
83
+ @client.device_flow.user_and_device_code 'basic netdisk'
84
+ a_get(:oauth, '/oauth/2.0/device/code', client_id: 'ci',
85
+ response_type: 'device_code', scope: 'basic netdisk').
86
+ should have_been_made
87
+ end
88
+
89
+ it 'responses user and device code' do
90
+ stub_get(:oauth, '/oauth/2.0/device/code', client_id: 'ci', response_type: 'device_code').
91
+ to_return(status: 200, body: ft('user_and_device_code.json'))
92
+ result = @client.device_flow.user_and_device_code
93
+ expect(result).to be_instance_of(Hash)
94
+ expect(result).to have_key(:device_code)
95
+ expect(result).to have_key(:user_code)
96
+ expect(result).to have_key(:verification_url)
97
+ expect(result).to have_key(:qrcode_url)
98
+ expect(result).to have_key(:expires_in)
99
+ expect(result).to have_key(:interval)
100
+ end
101
+ end
102
+
103
+ context '#get_token' do
104
+ context 'with code flow' do
105
+ before do
106
+ stub_post(:oauth, '/oauth/2.0/token',
107
+ grant_type: 'authorization_code',
108
+ code: 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
109
+ client_id: 'ci', client_secret: 'cs',
110
+ redirect_uri: 'http://www.example.com/oauth_redirect').
111
+ to_return(status: 200, body: ft('get_token_code.json'))
112
+ end
113
+
114
+ it 'requests access tokey' do
115
+ @client.code_flow.get_token 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
116
+ 'http://www.example.com/oauth_redirect'
117
+ a_post(:oauth, '/oauth/2.0/token',
118
+ grant_type: 'authorization_code',
119
+ code: 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
120
+ client_id: 'ci', client_secret: 'cs',
121
+ redirect_uri: 'http://www.example.com/oauth_redirect').should have_been_made
122
+ end
123
+
124
+ it 'responses access token' do
125
+ result = @client.code_flow.get_token 'ANXxSNjwQDugOnqeikRMu2bKaXCdlLxn',
126
+ 'http://www.example.com/oauth_redirect'
127
+ expect(result).to be_instance_of(Baidu::Session)
128
+ expect(result).to respond_to(:access_token)
129
+ expect(result).to respond_to(:refresh_token)
130
+ expect(result).to respond_to(:scope)
131
+ expect(result).to respond_to(:session_key)
132
+ expect(result).to respond_to(:session_secret)
133
+ end
134
+ end
135
+
136
+ context 'with device flow' do
137
+ before do
138
+ stub_post(:oauth, '/oauth/2.0/token', grant_type: 'device_token',
139
+ code: 'a82hjs723h72h3a82hjs723h72h3vb', client_id: 'ci', client_secret: 'cs').
140
+ to_return(status: 200, body: ft('get_token_device.json'))
141
+ end
142
+
143
+ it 'requests access tokey' do
144
+ @client.device_flow.get_token 'a82hjs723h72h3a82hjs723h72h3vb'
145
+ a_post(:oauth, '/oauth/2.0/token', grant_type: 'device_token',
146
+ code: 'a82hjs723h72h3a82hjs723h72h3vb',
147
+ client_id: 'ci', client_secret: 'cs').should have_been_made
148
+ end
149
+
150
+ it 'responses access token' do
151
+ result = @client.device_flow.get_token 'a82hjs723h72h3a82hjs723h72h3vb'
152
+ expect(result).to be_instance_of(Baidu::Session)
153
+ expect(result).to respond_to(:access_token)
154
+ expect(result).to respond_to(:refresh_token)
155
+ expect(result).to respond_to(:scope)
156
+ expect(result).to respond_to(:session_key)
157
+ expect(result).to respond_to(:session_secret)
158
+ end
159
+ end
160
+ end
161
+
162
+ context '#refresh_token' do
163
+ before do
164
+ stub_post(:oauth, '/oauth/2.0/token', grant_type: 'refresh_token',
165
+ refresh_token: '2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328',
166
+ client_id: 'ci', client_secret: 'cs').
167
+ to_return(status: 200, body: ft('refresh_token.json'))
168
+ end
169
+
170
+ it 'requests access token by refresh token' do
171
+ @client.refresh('2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328')
172
+ a_post(:oauth, '/oauth/2.0/token', grant_type: 'refresh_token',
173
+ refresh_token: '2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328',
174
+ client_id: 'ci', client_secret: 'cs').should have_been_made
175
+ end
176
+
177
+ it 'requests access token by refresh token with params' do
178
+ stub_post(:oauth, '/oauth/2.0/token', grant_type: 'refresh_token',
179
+ refresh_token: '2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328',
180
+ scope: 'basic netdisk', client_id: 'ci', client_secret: 'cs').
181
+ to_return(status: 200, body: ft('refresh_token.json'))
182
+ @client.refresh('2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328',
183
+ scope: 'basic netdisk')
184
+ a_post(:oauth, '/oauth/2.0/token', grant_type: 'refresh_token',
185
+ refresh_token: '2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328',
186
+ scope: 'basic netdisk', client_id: 'ci', client_secret: 'cs').should have_been_made
187
+ end
188
+
189
+ it 'responses access token by refresh token' do
190
+ result = @client.refresh('2.af3d55f8615fdfd9edb7c4b5ebdc3e32.604800.1293440400-2346678-124328')
191
+ expect(result).to be_instance_of(Baidu::Session)
192
+ expect(result).to respond_to(:access_token)
193
+ expect(result).to respond_to(:refresh_token)
194
+ expect(result).to respond_to(:scope)
195
+ expect(result).to respond_to(:session_key)
196
+ expect(result).to respond_to(:session_secret)
197
+ end
198
+ end
199
+ end