baidu-sdk 0.0.1

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.
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