cloud_door 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.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +204 -0
- data/Rakefile +11 -0
- data/bin/dropbox +133 -0
- data/bin/onedrive +133 -0
- data/cloud_door.gemspec +38 -0
- data/cloud_door_config.yml +12 -0
- data/data/.gitkeep +0 -0
- data/data/testlist +0 -0
- data/lib/cloud_door.rb +114 -0
- data/lib/cloud_door/account.rb +27 -0
- data/lib/cloud_door/cloud_storage.rb +294 -0
- data/lib/cloud_door/cloud_yaml.rb +45 -0
- data/lib/cloud_door/config.rb +61 -0
- data/lib/cloud_door/console.rb +334 -0
- data/lib/cloud_door/dropbox.rb +166 -0
- data/lib/cloud_door/exceptions.rb +153 -0
- data/lib/cloud_door/file_list.rb +164 -0
- data/lib/cloud_door/onedrive.rb +180 -0
- data/lib/cloud_door/onedrive_api.rb +169 -0
- data/lib/cloud_door/token.rb +67 -0
- data/lib/cloud_door/version.rb +3 -0
- data/log/.gitkeep +0 -0
- data/spec/cloud_door/account_spec.rb +96 -0
- data/spec/cloud_door/cloud_storage_spec.rb +10 -0
- data/spec/cloud_door/cloud_yaml_spec.rb +32 -0
- data/spec/cloud_door/config_spec.rb +95 -0
- data/spec/cloud_door/console_spec.rb +633 -0
- data/spec/cloud_door/dropbox_spec.rb +625 -0
- data/spec/cloud_door/file_list_spec.rb +451 -0
- data/spec/cloud_door/onedrive_api_spec.rb +256 -0
- data/spec/cloud_door/onedrive_spec.rb +652 -0
- data/spec/cloud_door/token_spec.rb +81 -0
- data/spec/fabricators/account_fabricator.rb +5 -0
- data/spec/fabricators/cloud_yaml_fabricator.rb +5 -0
- data/spec/fabricators/config_fabrication.rb +5 -0
- data/spec/fabricators/token_fabricator.rb +10 -0
- data/spec/spec_helper.rb +55 -0
- metadata +380 -0
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'rest_client'
|
4
|
+
|
5
|
+
module CloudDoor
|
6
|
+
class OneDriveApi
|
7
|
+
attr_accessor :access_token
|
8
|
+
|
9
|
+
# domain for auth
|
10
|
+
AUTH_BASE = 'https://login.live.com/'
|
11
|
+
# URL for auth
|
12
|
+
AUTH_FORMAT = AUTH_BASE +
|
13
|
+
'oauth20_authorize.srf?client_id=%s&scope=%s&response_type=code&redirect_uri=%s'
|
14
|
+
# URL for get token
|
15
|
+
TOKEN_URL = AUTH_BASE + 'oauth20_token.srf'
|
16
|
+
# domain for action
|
17
|
+
ACTION_BASE = 'https://apis.live.net/v5.0/'
|
18
|
+
# URL for get user info
|
19
|
+
USER_FORMAT = ACTION_BASE + 'me?access_token=%s'
|
20
|
+
# URL for get directory
|
21
|
+
DIR_FORMAT = ACTION_BASE + '%s/files?access_token=%s'
|
22
|
+
# URL for get file info
|
23
|
+
FILE_FORMAT = ACTION_BASE + '%s?access_token=%s'
|
24
|
+
# URL for download file
|
25
|
+
DOWNLOAD_FORMAT = ACTION_BASE + '%s/content?suppress_redirects=true&access_token=%s'
|
26
|
+
# URL for upload file
|
27
|
+
UPLOAD_FORMAT = ACTION_BASE + '%s/files?access_token=%s'
|
28
|
+
# URL for delete file
|
29
|
+
DELETE_FORMAT = ACTION_BASE + '%s?access_token=%s'
|
30
|
+
# URL for make directory
|
31
|
+
MKDIR_FORMAT = ACTION_BASE + '%s'
|
32
|
+
# update scope
|
33
|
+
UPDATE_SCOPE = 'wl.skydrive_update,wl.offline_access'
|
34
|
+
# log_file
|
35
|
+
LOG_FILE = './log/request.log'
|
36
|
+
|
37
|
+
def initialize(access_token)
|
38
|
+
@access_token = access_token
|
39
|
+
end
|
40
|
+
|
41
|
+
def request_get_token(code, client_id, client_secret, redirect_url)
|
42
|
+
post_body = {
|
43
|
+
client_id: client_id,
|
44
|
+
client_secret: client_secret,
|
45
|
+
redirect_uri: redirect_url,
|
46
|
+
code: code,
|
47
|
+
grant_type: 'authorization_code'
|
48
|
+
}
|
49
|
+
header = {content_type: 'application/x-www-form-urlencoded'}
|
50
|
+
send_request(:post, TOKEN_URL, post_body, header)
|
51
|
+
end
|
52
|
+
|
53
|
+
def request_refresh_token(refresh_token, client_id, client_secret, redirect_url)
|
54
|
+
post_body = {
|
55
|
+
client_id: client_id,
|
56
|
+
client_secret: client_secret,
|
57
|
+
redirect_uri: redirect_url,
|
58
|
+
grant_type: 'refresh_token',
|
59
|
+
refresh_token: refresh_token
|
60
|
+
}
|
61
|
+
header = {content_type: 'application/x-www-form-urlencoded'}
|
62
|
+
send_request(:post, TOKEN_URL, post_body, header)
|
63
|
+
end
|
64
|
+
|
65
|
+
def request_user
|
66
|
+
url = USER_FORMAT % @access_token
|
67
|
+
send_request(:get, url)
|
68
|
+
end
|
69
|
+
|
70
|
+
def request_dir(file_id)
|
71
|
+
url = DIR_FORMAT % [file_id, @access_token]
|
72
|
+
send_request(:get, url)
|
73
|
+
end
|
74
|
+
|
75
|
+
def request_file(file_id)
|
76
|
+
url = FILE_FORMAT % [file_id, @access_token]
|
77
|
+
send_request(:get, url)
|
78
|
+
end
|
79
|
+
|
80
|
+
def request_download(file_id)
|
81
|
+
url = DOWNLOAD_FORMAT % [file_id, @access_token]
|
82
|
+
info = send_request(:get, url)
|
83
|
+
key = 'location'
|
84
|
+
raise NoDataException if info.nil? || !info.is_a?(Hash) || !info.key?(key)
|
85
|
+
file_url = info[key]
|
86
|
+
open(file_url).read
|
87
|
+
end
|
88
|
+
|
89
|
+
def request_upload(file_path, parent_id)
|
90
|
+
url = UPLOAD_FORMAT % [parent_id, @access_token]
|
91
|
+
send_request(:post_file, url, File.new(file_path, 'rb'))
|
92
|
+
end
|
93
|
+
|
94
|
+
def request_delete(file_id)
|
95
|
+
url = DELETE_FORMAT % [file_id, @access_token]
|
96
|
+
send_request(:delete, url)
|
97
|
+
end
|
98
|
+
|
99
|
+
def request_mkdir(name, parent_id)
|
100
|
+
url = MKDIR_FORMAT % parent_id
|
101
|
+
body = JSON('name' => name)
|
102
|
+
header = {
|
103
|
+
'Authorization' => "Bearer #{@access_token}",
|
104
|
+
'Content-Type' => 'application/json'
|
105
|
+
}
|
106
|
+
send_request(:post, url, body, header)
|
107
|
+
end
|
108
|
+
|
109
|
+
class << self
|
110
|
+
def make_auth_url(client_id, redirect_url)
|
111
|
+
AUTH_FORMAT % [client_id, UPDATE_SCOPE, redirect_url]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def send_request(method, url, body = '', header = {})
|
118
|
+
# if method == :get
|
119
|
+
# res = RestClient.get(url) do |response, request, result|
|
120
|
+
# request_log(response, request, result)
|
121
|
+
# response
|
122
|
+
# end
|
123
|
+
# elsif method == :post
|
124
|
+
# res = RestClient.post(url, body, header) do |response, request, result|
|
125
|
+
# request_log(response, request, result)
|
126
|
+
# response
|
127
|
+
# end
|
128
|
+
# elsif method == :delete
|
129
|
+
# res = RestClient.delete(url) do |response, request, result|
|
130
|
+
# request_log(response, request, result)
|
131
|
+
# response
|
132
|
+
# end
|
133
|
+
# elsif method == :post_file
|
134
|
+
# res = RestClient.post(url, :file => body) do |response, request, result|
|
135
|
+
# request_log(response, request, result)
|
136
|
+
# response
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
if method == :get
|
140
|
+
res = RestClient.get(url)
|
141
|
+
elsif method == :post
|
142
|
+
res = RestClient.post(url, body, header)
|
143
|
+
elsif method == :delete
|
144
|
+
res = RestClient.delete(url)
|
145
|
+
elsif method == :post_file
|
146
|
+
res = RestClient.post(url, file: body)
|
147
|
+
end
|
148
|
+
# raise NoDataException if res.body.nil? || res.body.empty?
|
149
|
+
return if res.body.nil? || res.body.empty?
|
150
|
+
JSON.parse(res.body)
|
151
|
+
rescue => e
|
152
|
+
if e.is_a?(RestClient::Unauthorized)
|
153
|
+
raise UnauthorizedException
|
154
|
+
elsif e.class.to_s.include?('RestClient')
|
155
|
+
raise HttpConnectionException
|
156
|
+
else
|
157
|
+
raise
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def request_log(response, request, result)
|
162
|
+
logger = Logger.new(LOG_FILE)
|
163
|
+
log = "request:\n#{request.args.inspect}\n"
|
164
|
+
log << "result:\n#{result.inspect}\n"
|
165
|
+
log << "response:\n#{JSON.parse(response.body).inspect}\n"
|
166
|
+
logger.info(log)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CloudDoor
|
2
|
+
class Token
|
3
|
+
attr_accessor :token_file, :token_type, :expires_in, :scope, :access_token,
|
4
|
+
:refresh_token, :user_id, :token_name
|
5
|
+
attr_reader :data_path
|
6
|
+
|
7
|
+
TOKEN_ITEMS = [
|
8
|
+
'token_type',
|
9
|
+
'expires_in',
|
10
|
+
'scope',
|
11
|
+
'access_token',
|
12
|
+
'refresh_token',
|
13
|
+
'user_id'
|
14
|
+
]
|
15
|
+
|
16
|
+
def initialize(token_name, data_path, id = nil)
|
17
|
+
@token_name = token_name
|
18
|
+
@data_path = data_path
|
19
|
+
if id.nil?
|
20
|
+
@token_file = @data_path + @token_name
|
21
|
+
else
|
22
|
+
token_dir = @data_path + "#{id}"
|
23
|
+
unless File.exists?(token_dir)
|
24
|
+
Dir.mkdir(token_dir)
|
25
|
+
end
|
26
|
+
@token_file = "#{token_dir}/#{@token_name}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_locate(id)
|
31
|
+
token_dir = @data_path + "#{id}"
|
32
|
+
unless File.exists?(token_dir)
|
33
|
+
Dir.mkdir(token_dir)
|
34
|
+
end
|
35
|
+
@token_file = "#{token_dir}/#{@token_name}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_attributes(attributes)
|
39
|
+
TOKEN_ITEMS.each do |item|
|
40
|
+
instance_variable_set("@#{item}", attributes[item]) if attributes.key?(item)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_token
|
45
|
+
marshal = Marshal.dump(self)
|
46
|
+
open(@token_file, 'wb') { |file| file << marshal }
|
47
|
+
true
|
48
|
+
rescue
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.load_token(token_name, data_path, id = nil)
|
53
|
+
if id.nil?
|
54
|
+
token_file = data_path + token_name
|
55
|
+
else
|
56
|
+
token_file = data_path + "#{id}/#{token_name}"
|
57
|
+
end
|
58
|
+
return nil unless File.exist?(token_file)
|
59
|
+
marshal = File.open(token_file).read
|
60
|
+
token = Marshal.load(marshal)
|
61
|
+
return nil unless token.is_a?(Token)
|
62
|
+
token
|
63
|
+
rescue
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/log/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Account' do
|
4
|
+
let(:account_file) { './data/test.yml' }
|
5
|
+
describe 'isset_account?' do
|
6
|
+
subject { account.isset_account? }
|
7
|
+
let(:account) { Fabricate.build(:account, storage: 'onedrive', file: account_file) }
|
8
|
+
context 'account & password setted' do
|
9
|
+
before(:each) do
|
10
|
+
account.login_account = 'login@onedrive.com'
|
11
|
+
account.login_password = 'onedrive.com'
|
12
|
+
end
|
13
|
+
it { is_expected.to be_truthy }
|
14
|
+
end
|
15
|
+
context 'account not setted' do
|
16
|
+
before(:each) do
|
17
|
+
account.login_account = 'login@onedrive.com'
|
18
|
+
account.login_password = ''
|
19
|
+
end
|
20
|
+
it { is_expected.to be_falsey }
|
21
|
+
end
|
22
|
+
context 'password not setted' do
|
23
|
+
before(:each) do
|
24
|
+
account.login_account = ''
|
25
|
+
account.login_password = 'onedrive.com'
|
26
|
+
end
|
27
|
+
it { is_expected.to be_falsey }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'load_yaml' do
|
32
|
+
before(:all) do
|
33
|
+
accounts = {
|
34
|
+
'onedrive' => {
|
35
|
+
'login_account' => 'login@onedrive.com',
|
36
|
+
'login_password' => 'onedrive'
|
37
|
+
},
|
38
|
+
'dropbox' => {
|
39
|
+
'login_account' => 'login@dropbox.com',
|
40
|
+
'login_password' => 'dropbox'
|
41
|
+
}
|
42
|
+
}
|
43
|
+
open('./data/test.yml', 'wb') { |file| YAML.dump(accounts, file) }
|
44
|
+
end
|
45
|
+
before(:each) { account.load_yaml }
|
46
|
+
context 'onedrive' do
|
47
|
+
let(:account) { Fabricate.build(:account, storage: 'onedrive', file: account_file) }
|
48
|
+
it { expect(account.login_account).to eq 'login@onedrive.com' }
|
49
|
+
it { expect(account.login_password).to eq 'onedrive' }
|
50
|
+
end
|
51
|
+
context 'dropbox' do
|
52
|
+
let(:account) { Fabricate.build(:account, storage: 'dropbox', file: account_file) }
|
53
|
+
it { expect(account.login_account).to eq 'login@dropbox.com' }
|
54
|
+
it { expect(account.login_password).to eq 'dropbox' }
|
55
|
+
end
|
56
|
+
after(:all) do
|
57
|
+
File.delete('./data/test.yml') if File.exist?('./data/test.yml')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'update_yaml' do
|
62
|
+
before(:each) do
|
63
|
+
File.delete(account_file) if File.exist?(account_file)
|
64
|
+
account.update_yaml(update_params)
|
65
|
+
end
|
66
|
+
context 'onedrive' do
|
67
|
+
let(:account) { Fabricate.build(:account, storage: 'onedrive', file: account_file) }
|
68
|
+
let(:update_params) do
|
69
|
+
{
|
70
|
+
'login_account' => 'login@onedrive.com',
|
71
|
+
'login_password' => 'onedrive'
|
72
|
+
}
|
73
|
+
end
|
74
|
+
let(:load_file) { YAML.load_file(account_file)['onedrive'] }
|
75
|
+
it { expect(File.exist?(account_file)).to be_truthy }
|
76
|
+
it { expect(load_file['login_account']).to eq 'login@onedrive.com' }
|
77
|
+
it { expect(load_file['login_password']).to eq 'onedrive' }
|
78
|
+
end
|
79
|
+
context 'dropbox' do
|
80
|
+
let(:account) { Fabricate.build(:account, storage: 'dropbox', file: account_file) }
|
81
|
+
let(:update_params) do
|
82
|
+
{
|
83
|
+
'login_account' => 'login@dropbox.com',
|
84
|
+
'login_password' => 'dropbox'
|
85
|
+
}
|
86
|
+
end
|
87
|
+
let(:load_file) { YAML.load_file(account_file)['dropbox'] }
|
88
|
+
it { expect(File.exist?(account_file)).to be_truthy }
|
89
|
+
it { expect(load_file['login_account']).to eq 'login@dropbox.com' }
|
90
|
+
it { expect(load_file['login_password']).to eq 'dropbox' }
|
91
|
+
end
|
92
|
+
after(:each) do
|
93
|
+
File.delete(account_file) if File.exist?(account_file)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# CloudStorage class is abstract class.
|
4
|
+
# then, test inherited subclass.
|
5
|
+
describe 'CloudStorage' do
|
6
|
+
describe 'initialize' do
|
7
|
+
subject { CloudDoor::CloudStorage.new }
|
8
|
+
it { expect { subject }.to raise_error(CloudDoor::AbstractClassException) }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'CloudYaml' do
|
4
|
+
describe 'load_yaml' do
|
5
|
+
subject { account.load_yaml }
|
6
|
+
account_file = './data/test.yml'
|
7
|
+
before(:all) do
|
8
|
+
accounts = {
|
9
|
+
'onedrive' => {
|
10
|
+
'login_account' => 'login@onedrive.com',
|
11
|
+
'login_password' => 'onedrive'
|
12
|
+
}
|
13
|
+
}
|
14
|
+
open(account_file, 'wb') { |file| YAML.dump(accounts, file) }
|
15
|
+
end
|
16
|
+
context 'file & storage exists' do
|
17
|
+
let(:account) { Fabricate.build(:cloud_yaml, file: account_file) }
|
18
|
+
it { is_expected.to be_truthy }
|
19
|
+
end
|
20
|
+
context 'file not exists' do
|
21
|
+
let(:account) { Fabricate.build(:cloud_yaml, file: './data/example.yml') }
|
22
|
+
it { is_expected.to be_falsey }
|
23
|
+
end
|
24
|
+
context 'storage exists' do
|
25
|
+
let(:account) { Fabricate.build(:cloud_yaml, file: account_file, storage: 'example') }
|
26
|
+
it { is_expected.to be_falsey }
|
27
|
+
end
|
28
|
+
after(:all) do
|
29
|
+
File.delete(account_file) if File.exist?(account_file)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Config' do
|
4
|
+
describe 'load_yaml' do
|
5
|
+
let(:config_file) { './data/test.yml' }
|
6
|
+
before(:all) do
|
7
|
+
configs = {
|
8
|
+
'onedrive' => {
|
9
|
+
'client_id' => '1234',
|
10
|
+
'client_secret' => 'abcd',
|
11
|
+
'redirect_url' => 'onedrive'
|
12
|
+
},
|
13
|
+
'dropbox' => {
|
14
|
+
'client_id' => '5678',
|
15
|
+
'client_secret' => 'efgh',
|
16
|
+
'redirect_url' => 'dropbox'
|
17
|
+
}
|
18
|
+
}
|
19
|
+
open('./data/test.yml', 'wb') { |file| YAML.dump(configs, file) }
|
20
|
+
end
|
21
|
+
before(:each) { config.load_yaml }
|
22
|
+
context 'onedrive' do
|
23
|
+
let(:config) { Fabricate.build(:config, storage: 'onedrive', file: config_file) }
|
24
|
+
it { expect(config.client_id).to eq '1234' }
|
25
|
+
it { expect(config.client_secret).to eq 'abcd' }
|
26
|
+
it { expect(config.redirect_url).to eq 'onedrive' }
|
27
|
+
end
|
28
|
+
context 'dropbox' do
|
29
|
+
let(:config) { Fabricate.build(:config, storage: 'dropbox', file: config_file) }
|
30
|
+
it { expect(config.client_id).to eq '5678' }
|
31
|
+
it { expect(config.client_secret).to eq 'efgh' }
|
32
|
+
it { expect(config.redirect_url).to eq 'dropbox' }
|
33
|
+
end
|
34
|
+
after(:all) do
|
35
|
+
File.delete('./data/test.yml') if File.exist?('./data/test.yml')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'update_yaml' do
|
40
|
+
let(:config_file) { './data/test.yml' }
|
41
|
+
before(:each) do
|
42
|
+
File.delete(config_file) if File.exist?(config_file)
|
43
|
+
account.update_yaml(update_params)
|
44
|
+
end
|
45
|
+
context 'onedrive' do
|
46
|
+
let(:account) { Fabricate.build(:config, storage: 'onedrive', file: config_file) }
|
47
|
+
let(:update_params) do
|
48
|
+
{
|
49
|
+
'client_id' => '1234',
|
50
|
+
'client_secret' => 'abcd',
|
51
|
+
'redirect_url' => 'onedrive'
|
52
|
+
}
|
53
|
+
end
|
54
|
+
let(:load_file) { YAML.load_file(config_file)['onedrive'] }
|
55
|
+
it { expect(File.exist?(config_file)).to be_truthy }
|
56
|
+
it { expect(load_file['client_id']).to eq '1234' }
|
57
|
+
it { expect(load_file['client_secret']).to eq 'abcd' }
|
58
|
+
it { expect(load_file['redirect_url']).to eq 'onedrive' }
|
59
|
+
end
|
60
|
+
context 'dropbox' do
|
61
|
+
let(:account) { Fabricate.build(:config, storage: 'dropbox', file: config_file) }
|
62
|
+
let(:update_params) do
|
63
|
+
{
|
64
|
+
'client_id' => '5678',
|
65
|
+
'client_secret' => 'efgh',
|
66
|
+
'redirect_url' => 'dropbox'
|
67
|
+
}
|
68
|
+
end
|
69
|
+
let(:load_file) { YAML.load_file(config_file)['dropbox'] }
|
70
|
+
it { expect(File.exist?(config_file)).to be_truthy }
|
71
|
+
it { expect(load_file['client_id']).to eq '5678' }
|
72
|
+
it { expect(load_file['client_secret']).to eq 'efgh' }
|
73
|
+
it { expect(load_file['redirect_url']).to eq 'dropbox' }
|
74
|
+
end
|
75
|
+
after(:each) do
|
76
|
+
File.delete(config_file) if File.exist?(config_file)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'init?' do
|
81
|
+
subject { config.init? }
|
82
|
+
let(:config) { Fabricate.build(:config) }
|
83
|
+
context 'initialized' do
|
84
|
+
before(:each) do
|
85
|
+
config.client_id = '1234'
|
86
|
+
config.client_secret = 'abcd'
|
87
|
+
config.redirect_url = 'onedrive'
|
88
|
+
end
|
89
|
+
it { is_expected.to be_truthy }
|
90
|
+
end
|
91
|
+
context 'not initialized' do
|
92
|
+
it { is_expected.to be_falsey }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|