box_cli 0.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/.gitignore +10 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +97 -0
- data/LICENSE.txt +20 -0
- data/README.md +81 -0
- data/Rakefile +22 -0
- data/bin/box +28 -0
- data/box-cli.gemspec +32 -0
- data/features/account_info_command.feature +12 -0
- data/features/cli.feature +21 -0
- data/features/create_folder_command.feature +11 -0
- data/features/delete_command.feature +21 -0
- data/features/info_command.feature +20 -0
- data/features/settings_command.feature +48 -0
- data/features/step_definitions/box.rb +43 -0
- data/features/step_definitions/environment.rb +12 -0
- data/features/support/box_helpers.rb +63 -0
- data/features/support/env.rb +6 -0
- data/features/support/hooks.rb +7 -0
- data/features/upload_command.feature +20 -0
- data/fixtures/cassettes/BoxCli_AccountInfoCommand/returns_account_info_for_good_credentials_and_an_api_key.json +1 -0
- data/fixtures/cassettes/BoxCli_CreateFolderCommand/creates_a_folder_when_none_by_that_name_already_exists.json +1 -0
- data/fixtures/cassettes/BoxCli_CreateFolderCommand/raises_an_exception_when_a_folder_by_that_name_already_exists.json +1 -0
- data/fixtures/cassettes/BoxCli_DeleteCommand/deletes_the_item_when_something_is_there.json +1 -0
- data/fixtures/cassettes/BoxCli_DeleteCommand/does_not_raise_an_exception_when_deleting_something_that_exists.json +1 -0
- data/fixtures/cassettes/BoxCli_DeleteCommand/raises_an_exception_when_there_is_nothing_to_delete.json +1 -0
- data/fixtures/cassettes/BoxCli_InfoCommand/provides_output_regarding_the_item_if_it_exists.json +1 -0
- data/fixtures/cassettes/BoxCli_InfoCommand/raises_an_exception_if_nothing_is_there.json +1 -0
- data/fixtures/cassettes/BoxCli_UploadCommand/raises_an_exception_when_a_file_by_that_name_already_exists.json +1 -0
- data/fixtures/cassettes/BoxCli_UploadCommand/uploads_a_file_when_none_by_that_name_already_exists.json +1 -0
- data/fixtures/cassettes/Generic_Box_Command/fails_for_a_bad_api_key.json +1 -0
- data/fixtures/cassettes/Generic_Box_Command/fails_for_bad_credentials.json +1 -0
- data/lib/box_cli/account_info_command.rb +7 -0
- data/lib/box_cli/auth_token_manager.rb +40 -0
- data/lib/box_cli/box_command.rb +13 -0
- data/lib/box_cli/command.rb +33 -0
- data/lib/box_cli/create_folder_command.rb +9 -0
- data/lib/box_cli/delete_command.rb +8 -0
- data/lib/box_cli/displayer.rb +10 -0
- data/lib/box_cli/hash_to_pretty.rb +28 -0
- data/lib/box_cli/info_command.rb +10 -0
- data/lib/box_cli/settings_command.rb +24 -0
- data/lib/box_cli/terminal.rb +13 -0
- data/lib/box_cli/upload_command.rb +8 -0
- data/lib/box_cli/version.rb +3 -0
- data/lib/box_cli/wrapper.rb +149 -0
- data/lib/box_cli.rb +27 -0
- data/spec/box_cli/account_info_command_spec.rb +8 -0
- data/spec/box_cli/box_command_spec.rb +51 -0
- data/spec/box_cli/create_folder_command_spec.rb +22 -0
- data/spec/box_cli/delete_command_spec.rb +27 -0
- data/spec/box_cli/generic_box_command_spec.rb +10 -0
- data/spec/box_cli/hash_to_pretty_spec.rb +57 -0
- data/spec/box_cli/info_command_spec.rb +22 -0
- data/spec/box_cli/settings_command_spec.rb +12 -0
- data/spec/box_cli/upload_command_spec.rb +30 -0
- data/spec/box_helpers.rb +40 -0
- data/spec/spec_helper.rb +41 -0
- metadata +332 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module BoxCli
|
2
|
+
class SettingsCommand < Command
|
3
|
+
def initialize(options, args)
|
4
|
+
super
|
5
|
+
collect_globals_from_env
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
STDOUT.puts("Options:\n".tap do |s|
|
10
|
+
if @options.__hash__.empty?
|
11
|
+
s << " (none)\n"
|
12
|
+
else
|
13
|
+
s << @options.__hash__.keys.map(&:to_s).sort.map { |k| " %s: %s" % [k, @options.__hash__[k.to_sym]] }.join("\n")
|
14
|
+
end
|
15
|
+
s << "\n\nArguments:\n"
|
16
|
+
if @args.empty?
|
17
|
+
s << " (none)\n"
|
18
|
+
else
|
19
|
+
s << @args.map { |p| " #{p}" }.join("\n")
|
20
|
+
end
|
21
|
+
end)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'box-api'
|
2
|
+
require 'mechanize'
|
3
|
+
require 'active_support/ordered_hash'
|
4
|
+
require 'active_support/hash_with_indifferent_access'
|
5
|
+
|
6
|
+
module Box
|
7
|
+
class Account
|
8
|
+
send(:public, :api)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Api
|
12
|
+
def auth_token
|
13
|
+
@auth_token
|
14
|
+
end
|
15
|
+
|
16
|
+
query_string_normalizer proc { |query|
|
17
|
+
indifferent = ActiveSupport::HashWithIndifferentAccess.new(query)
|
18
|
+
query.keys.map(&:to_s).sort.map do |key|
|
19
|
+
value = indifferent[key]
|
20
|
+
if value.nil?
|
21
|
+
key
|
22
|
+
elsif Array === value
|
23
|
+
value.map { |v| "#{key}[]=#{URI.encode(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}" }
|
24
|
+
else
|
25
|
+
"#{key}=#{value}"
|
26
|
+
end
|
27
|
+
end.flatten.join('&')
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module BoxCli
|
33
|
+
class Exception < ::Exception; end
|
34
|
+
class NotFound < Exception; end
|
35
|
+
class NotAuthorized < Exception; end
|
36
|
+
class FolderNameTaken < Exception; end
|
37
|
+
class FileNameTaken < Exception; end
|
38
|
+
|
39
|
+
class Wrapper
|
40
|
+
def initialize(api_key, username, password)
|
41
|
+
@api_key, @username, @password = api_key, username, password
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.auth_token_manager_class=(auth_token_manager_class)
|
45
|
+
@auth_token_manager_class = auth_token_manager_class
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.auth_token_manager_class
|
49
|
+
@auth_token_manager_class || AuthTokenManager
|
50
|
+
end
|
51
|
+
|
52
|
+
def auth_token_manager=(auth_token_manager)
|
53
|
+
@auth_token_manager = auth_token_manager
|
54
|
+
end
|
55
|
+
|
56
|
+
def auth_token_manager
|
57
|
+
@auth_token_manager || self.class.auth_token_manager_class.new(@username)
|
58
|
+
end
|
59
|
+
|
60
|
+
def account_info
|
61
|
+
api.get_account_info
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_folder(folder_name)
|
65
|
+
folder = root.create(folder_name)
|
66
|
+
folder.id
|
67
|
+
rescue Box::Api::NameTaken => e
|
68
|
+
raise FolderNameTaken.new("Folder '#{folder_name}' already exists")
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(remote_path)
|
72
|
+
item = root.at(remote_path)
|
73
|
+
raise NotFound.new("Nothing found at '#{remote_path}'") unless item
|
74
|
+
api.delete(item.type, item.id)
|
75
|
+
end
|
76
|
+
|
77
|
+
def info(remote_path)
|
78
|
+
item = root.at(remote_path)
|
79
|
+
raise NotFound.new("Nothing found at '#{remote_path}'") unless item
|
80
|
+
ActiveSupport::OrderedHash[:type, item.type, :data, item.data]
|
81
|
+
end
|
82
|
+
|
83
|
+
def upload(local_path, remote_path)
|
84
|
+
target_folder = root.at(remote_path)
|
85
|
+
basename = File.basename(local_path)
|
86
|
+
target_path = File.join(remote_path, basename)
|
87
|
+
if item = root.at(target_path)
|
88
|
+
raise FileNameTaken.new("File '#{basename}' already exists at #{remote_path}")
|
89
|
+
else
|
90
|
+
api.upload(local_path, target_folder.id)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def upload_or_overwrite(local_path, remote_path)
|
95
|
+
target_folder = root.at(remote_path)
|
96
|
+
target_path = File.join(remote_path, File.basename(local_path))
|
97
|
+
if item = root.at(target_path)
|
98
|
+
api.overwrite(local_path, item.id)
|
99
|
+
else
|
100
|
+
api.upload(local_path, target_folder.id)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def root_folder_id
|
105
|
+
root.id
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def api
|
111
|
+
account.api
|
112
|
+
end
|
113
|
+
|
114
|
+
def account
|
115
|
+
unless @account
|
116
|
+
@api = Box::Api.new(@api_key)
|
117
|
+
account = Box::Account.new(@api)
|
118
|
+
auth_token = auth_token_manager.get_auth_token
|
119
|
+
account.authorize(:auth_token => auth_token) do |auth_url|
|
120
|
+
authorize(auth_url, @username, @password)
|
121
|
+
end
|
122
|
+
unless account.authorized?
|
123
|
+
auth_token_manager.remove
|
124
|
+
raise NotAuthorized
|
125
|
+
end
|
126
|
+
auth_token_manager.save(auth_token)
|
127
|
+
@account = account
|
128
|
+
end
|
129
|
+
@account
|
130
|
+
end
|
131
|
+
|
132
|
+
def authorize(auth_url, username, password)
|
133
|
+
Mechanize.new do |agent|
|
134
|
+
agent.user_agent = :safari
|
135
|
+
agent.get(auth_url) do |login_page|
|
136
|
+
login_page.form_with(:name => 'login_form1') do |login_form|
|
137
|
+
login_form['login'] = username
|
138
|
+
login_form['password'] = password
|
139
|
+
return login_form.submit
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def root
|
146
|
+
account.root
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
data/lib/box_cli.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'box_cli/version'
|
2
|
+
require 'box_cli/auth_token_manager'
|
3
|
+
require 'box_cli/hash_to_pretty'
|
4
|
+
require 'box_cli/displayer'
|
5
|
+
require 'box_cli/wrapper'
|
6
|
+
|
7
|
+
require 'box_cli/command'
|
8
|
+
require 'box_cli/box_command'
|
9
|
+
require 'box_cli/account_info_command'
|
10
|
+
require 'box_cli/create_folder_command'
|
11
|
+
require 'box_cli/delete_command'
|
12
|
+
require 'box_cli/info_command'
|
13
|
+
require 'box_cli/settings_command'
|
14
|
+
require 'box_cli/terminal'
|
15
|
+
require 'box_cli/upload_command'
|
16
|
+
|
17
|
+
require 'active_support/inflector'
|
18
|
+
|
19
|
+
module BoxCli
|
20
|
+
def self.dispatch(name, options, args)
|
21
|
+
"BoxCli::#{name.camelize}Command".constantize.new(options, args).call
|
22
|
+
0
|
23
|
+
rescue Exception => e
|
24
|
+
puts "#{e.message}"
|
25
|
+
1
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::AccountInfoCommand do
|
4
|
+
it "returns account info for good credentials and an api key", :vcr do
|
5
|
+
BoxCli::Displayer.any_instance.expects(:display).with(regexp_matches(/Status\:\s+get_account_info_ok\s+User:\s+Access:\s+\d+\s+Email:\s+/))
|
6
|
+
BoxCli::AccountInfoCommand.new(options, []).call
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe BoxCli::BoxCommand, '.new', 'options' do
|
5
|
+
subject(:command) { BoxCli::BoxCommand.new(options_with_local_option, ['arg2', 'arg1']) }
|
6
|
+
it "partitions :user, :password, and :api_key into the global options" do
|
7
|
+
expect(command.global_options).to eq OpenStruct.new(options_hash)
|
8
|
+
end
|
9
|
+
it "partitions :some_local_option into the local options" do
|
10
|
+
expect(command.local_options).to eq OpenStruct.new(options_hash_local_option)
|
11
|
+
end
|
12
|
+
it "initializes the args" do
|
13
|
+
expect(command.args).to eq ['arg2', 'arg1']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe BoxCli::BoxCommand, '.new', 'prompting' do
|
18
|
+
before do
|
19
|
+
@save_password = ENV['BOX_CLI_PASSWORD']
|
20
|
+
ENV['BOX_CLI_PASSWORD'] = nil
|
21
|
+
BoxCli::Terminal.stubs(:ask)
|
22
|
+
BoxCli::BoxCommand.new(options_with_local_option_without_password, ['arg2', 'arg1'])
|
23
|
+
end
|
24
|
+
after do
|
25
|
+
ENV['BOX_CLI_PASSWORD'] = @save_password
|
26
|
+
end
|
27
|
+
it "prompts for missing global options" do
|
28
|
+
expect(BoxCli::Terminal).to have_received(:ask).with('password: ')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe BoxCli::BoxCommand, '#wrapper' do
|
33
|
+
subject(:command) { BoxCli::BoxCommand.new(options_with_local_option, ['arg2', 'arg1']) }
|
34
|
+
before do
|
35
|
+
BoxCli::Wrapper.stubs(:new)
|
36
|
+
command.wrapper
|
37
|
+
end
|
38
|
+
it "creates an instance of BoxCli::Wrapper with the user, password, and api_key" do
|
39
|
+
expect(BoxCli::Wrapper).to have_received(:new).with(options_hash[:api_key], options_hash[:user], options_hash[:password])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe BoxCli::BoxCommand, '#wrapper' do
|
44
|
+
subject(:command) { BoxCli::BoxCommand.new(options_with_local_option, ['arg2', 'arg1']) }
|
45
|
+
before do
|
46
|
+
command.wrapper
|
47
|
+
end
|
48
|
+
it "returns a kind of a BoxCli::Wrapper" do
|
49
|
+
expect(command.wrapper).to be_a_kind_of(BoxCli::Wrapper)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::CreateFolderCommand do
|
4
|
+
let(:folder_name) { 'a_very_unlikely_folder_name' }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
begin
|
8
|
+
BoxCli::DeleteCommand.new(options, [folder_name]).call
|
9
|
+
rescue BoxCli::NotFound
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "creates a folder when none by that name already exists", :vcr do
|
14
|
+
BoxCli::CreateFolderCommand.new(options, [folder_name]).call
|
15
|
+
expect { BoxCli::InfoCommand.new(options, [folder_name]).call }.to_not raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "raises an exception when a folder by that name already exists", :vcr do
|
19
|
+
BoxCli::CreateFolderCommand.new(options, [folder_name]).call
|
20
|
+
expect { BoxCli::CreateFolderCommand.new(options, [folder_name]).call }.to raise_error BoxCli::FolderNameTaken
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::DeleteCommand do
|
4
|
+
let(:folder_name) { 'a_very_unlikely_folder_name' }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
begin
|
8
|
+
BoxCli::DeleteCommand.new(options, [folder_name]).call
|
9
|
+
rescue BoxCli::NotFound
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises an exception when there is nothing to delete", :vcr do
|
14
|
+
expect { BoxCli::DeleteCommand.new(options, [folder_name]).call }.to raise_error BoxCli::NotFound
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does not raise an exception when deleting something that exists", :vcr do
|
18
|
+
BoxCli::CreateFolderCommand.new(options, [folder_name]).call
|
19
|
+
expect { BoxCli::DeleteCommand.new(options, [folder_name]).call }.to_not raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it "deletes the item when something is there", :vcr do
|
23
|
+
BoxCli::CreateFolderCommand.new(options, [folder_name]).call
|
24
|
+
BoxCli::DeleteCommand.new(options, [folder_name]).call
|
25
|
+
expect { BoxCli::InfoCommand.new(options, [folder_name]).call }.to raise_error BoxCli::NotFound
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Generic Box Command' do
|
4
|
+
it "fails for bad credentials", :vcr do
|
5
|
+
expect { BoxCli::AccountInfoCommand.new(options_with_bad_credentials, []).call }.to raise_error BoxCli::NotAuthorized
|
6
|
+
end
|
7
|
+
it "fails for a bad api key", :vcr do
|
8
|
+
expect { BoxCli::AccountInfoCommand.new(options_with_bad_api_key, []).call }.to raise_error Box::Api::Restricted
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::HashToPretty do
|
4
|
+
it "generates a pretty string for a hash" do
|
5
|
+
expect({ :a => 1, :b => 2 }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
6
|
+
A: 1
|
7
|
+
B: 2
|
8
|
+
PRETTY
|
9
|
+
end
|
10
|
+
it "can handle keys that are strings or symbols" do
|
11
|
+
expect({ :a => 1, 'b' => 2 }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
12
|
+
A: 1
|
13
|
+
B: 2
|
14
|
+
PRETTY
|
15
|
+
end
|
16
|
+
it "Preserves top-level key order when an ordered hash is used" do
|
17
|
+
expect(ActiveSupport::OrderedHash[:b, 2, :a, 1 ].extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
18
|
+
B: 2
|
19
|
+
A: 1
|
20
|
+
PRETTY
|
21
|
+
end
|
22
|
+
it "lines up the key/value pairs when the keys have different length" do
|
23
|
+
expect({ :a => 1, :beta => 2 }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
24
|
+
A: 1
|
25
|
+
Beta: 2
|
26
|
+
PRETTY
|
27
|
+
end
|
28
|
+
it "Humanizes the keys" do
|
29
|
+
expect({ :social_security_number => '457-55-5462', :title => 'LifeLock CEO' }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
30
|
+
Social security number: 457-55-5462
|
31
|
+
Title: LifeLock CEO
|
32
|
+
PRETTY
|
33
|
+
end
|
34
|
+
it "Indents values that are themselves hashes" do
|
35
|
+
expect({ :a => 1, :b => { :x => 2, :y => 3, :z => 4}, :c => 5 }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
36
|
+
A: 1
|
37
|
+
B:
|
38
|
+
X: 2
|
39
|
+
Y: 3
|
40
|
+
Z: 4
|
41
|
+
C: 5
|
42
|
+
PRETTY
|
43
|
+
end
|
44
|
+
it "Provides a means to display hierarchical hash data that don't look like garbage" do
|
45
|
+
expect({ "status" => "get_account_info_ok", "user" => { "login" => "john@iorahealth.com", "email" => "john@iorahealth.com", "access_id" => "11756654", "user_id" => "11756654", "space_amount" => "21474836480", "space_used" => "1657381031", "max_upload_size" => "2147483647" } }.extend(BoxCli::HashToPretty).to_pretty).to eq(<<-PRETTY.strip_heredoc)
|
46
|
+
Status: get_account_info_ok
|
47
|
+
User:
|
48
|
+
Access: 11756654
|
49
|
+
Email: john@iorahealth.com
|
50
|
+
Login: john@iorahealth.com
|
51
|
+
Max upload size: 2147483647
|
52
|
+
Space amount: 21474836480
|
53
|
+
Space used: 1657381031
|
54
|
+
User: 11756654
|
55
|
+
PRETTY
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::InfoCommand do
|
4
|
+
let(:folder_name) { 'a_very_unlikely_folder_name' }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
begin
|
8
|
+
BoxCli::DeleteCommand.new(options, [folder_name]).call
|
9
|
+
rescue BoxCli::NotFound
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "provides output regarding the item if it exists", :vcr do
|
14
|
+
BoxCli::CreateFolderCommand.new(options, [folder_name]).call
|
15
|
+
BoxCli::Displayer.any_instance.expects(:display).with(regexp_matches(/Type:\s+folder\s+Data:\s+.*?Name:\s+#{Regexp.escape(folder_name)}/m))
|
16
|
+
BoxCli::InfoCommand.new(options, [folder_name]).call
|
17
|
+
end
|
18
|
+
|
19
|
+
it "raises an exception if nothing is there", :vcr do
|
20
|
+
expect { BoxCli::InfoCommand.new(options, [folder_name]).call }.to raise_error BoxCli::NotFound
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::SettingsCommand do
|
4
|
+
it "provides output regarding options" do
|
5
|
+
STDOUT.expects(:puts).with(regexp_matches(/Options:\s+api_key:\s+\w+\s+password:\s+\w+\s+user:\s+\w+/m))
|
6
|
+
BoxCli::SettingsCommand.new(options, []).call
|
7
|
+
end
|
8
|
+
it "provides output regarding arguments" do
|
9
|
+
STDOUT.expects(:puts).with(regexp_matches(/Arguments:\s+arg2\s+arg1/m))
|
10
|
+
BoxCli::SettingsCommand.new(options, ['arg2', 'arg1']).call
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BoxCli::UploadCommand do
|
4
|
+
let(:file_name) { 'a_very_unlikely_file_name.txt' }
|
5
|
+
let(:temp_dir) { File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'tmp')) }
|
6
|
+
let(:local_path) { File.join(temp_dir, file_name) }
|
7
|
+
|
8
|
+
before(:each) do
|
9
|
+
begin
|
10
|
+
BoxCli::DeleteCommand.new(options, [file_name]).call
|
11
|
+
rescue BoxCli::NotFound
|
12
|
+
end
|
13
|
+
FileUtils.mkdir_p temp_dir
|
14
|
+
FileUtils.touch local_path
|
15
|
+
end
|
16
|
+
|
17
|
+
after(:each) do
|
18
|
+
FileUtils.rm local_path
|
19
|
+
end
|
20
|
+
|
21
|
+
it "uploads a file when none by that name already exists", :vcr do
|
22
|
+
BoxCli::UploadCommand.new(options, [local_path, '/']).call
|
23
|
+
expect { BoxCli::InfoCommand.new(options, [file_name]).call }.to_not raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises an exception when a file by that name already exists", :vcr do
|
27
|
+
BoxCli::UploadCommand.new(options, [local_path, '/']).call
|
28
|
+
expect { BoxCli::UploadCommand.new(options, [local_path, '/']).call }.to raise_error BoxCli::FileNameTaken
|
29
|
+
end
|
30
|
+
end
|
data/spec/box_helpers.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module BoxHelpers
|
2
|
+
class FakeCommanderOptions
|
3
|
+
attr_reader :__hash__
|
4
|
+
def initialize(options)
|
5
|
+
@__hash__ = options
|
6
|
+
end
|
7
|
+
def method_missing(m, *args)
|
8
|
+
@__hash__[m]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def options
|
13
|
+
FakeCommanderOptions.new(options_hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def options_with_local_option
|
17
|
+
FakeCommanderOptions.new(options_hash.merge(options_hash_local_option))
|
18
|
+
end
|
19
|
+
|
20
|
+
def options_with_local_option_without_password
|
21
|
+
FakeCommanderOptions.new(options_hash.merge(options_hash_local_option).reject { |k, v| k == :password })
|
22
|
+
end
|
23
|
+
|
24
|
+
def options_with_bad_credentials
|
25
|
+
FakeCommanderOptions.new(options_hash.merge(:user => 'nonexistent_user@iorahealth.com'))
|
26
|
+
end
|
27
|
+
|
28
|
+
def options_with_bad_api_key
|
29
|
+
FakeCommanderOptions.new(options_hash.merge(:api_key => 'mybaloneyhasafirstname'))
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def options_hash
|
34
|
+
{ :user => ENV['BOX_CLI_USER'], :password => ENV['BOX_CLI_PASSWORD'], :api_key => ENV['BOX_CLI_API_KEY'] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def options_hash_local_option
|
38
|
+
{ :local_option => 'extra' }
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'vcr'
|
4
|
+
require 'box_helpers'
|
5
|
+
require 'mocha_standalone'
|
6
|
+
require 'bourne'
|
7
|
+
|
8
|
+
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
9
|
+
$LOAD_PATH << File.join(PROJECT_ROOT, "lib")
|
10
|
+
require 'box_cli'
|
11
|
+
|
12
|
+
class String
|
13
|
+
# From ActiveSupport
|
14
|
+
def strip_heredoc
|
15
|
+
indent = chomp.scan(/^\s*/).min.size
|
16
|
+
gsub(/^\s{#{indent}}/, '')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
VCR.configure do |c|
|
21
|
+
c.cassette_library_dir = 'fixtures/cassettes'
|
22
|
+
c.hook_into :fakeweb
|
23
|
+
c.default_cassette_options = { :serialize_with => :json }
|
24
|
+
c.preserve_exact_body_bytes do |http_message|
|
25
|
+
RUBY_VERSION == '1.8.7' || (http_message.body.encoding.name == 'ASCII-8BIT' || !http_message.body.valid_encoding?)
|
26
|
+
end
|
27
|
+
c.filter_sensitive_data("<BOX_CLI_USER>") { ENV['BOX_CLI_USER'] }
|
28
|
+
c.filter_sensitive_data("<BOX_CLI_PASSWORD>") { ENV['BOX_CLI_PASSWORD'] }
|
29
|
+
c.filter_sensitive_data("<BOX_CLI_API_KEY>") { ENV['BOX_CLI_API_KEY'] }
|
30
|
+
c.configure_rspec_metadata!
|
31
|
+
end
|
32
|
+
|
33
|
+
RSpec.configure do |config|
|
34
|
+
config.mock_with :mocha
|
35
|
+
config.order = :random
|
36
|
+
config.include BoxHelpers
|
37
|
+
config.expect_with :rspec do |c|
|
38
|
+
c.syntax = :expect
|
39
|
+
end
|
40
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
41
|
+
end
|