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.
Files changed (60) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +7 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +97 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +81 -0
  7. data/Rakefile +22 -0
  8. data/bin/box +28 -0
  9. data/box-cli.gemspec +32 -0
  10. data/features/account_info_command.feature +12 -0
  11. data/features/cli.feature +21 -0
  12. data/features/create_folder_command.feature +11 -0
  13. data/features/delete_command.feature +21 -0
  14. data/features/info_command.feature +20 -0
  15. data/features/settings_command.feature +48 -0
  16. data/features/step_definitions/box.rb +43 -0
  17. data/features/step_definitions/environment.rb +12 -0
  18. data/features/support/box_helpers.rb +63 -0
  19. data/features/support/env.rb +6 -0
  20. data/features/support/hooks.rb +7 -0
  21. data/features/upload_command.feature +20 -0
  22. data/fixtures/cassettes/BoxCli_AccountInfoCommand/returns_account_info_for_good_credentials_and_an_api_key.json +1 -0
  23. data/fixtures/cassettes/BoxCli_CreateFolderCommand/creates_a_folder_when_none_by_that_name_already_exists.json +1 -0
  24. data/fixtures/cassettes/BoxCli_CreateFolderCommand/raises_an_exception_when_a_folder_by_that_name_already_exists.json +1 -0
  25. data/fixtures/cassettes/BoxCli_DeleteCommand/deletes_the_item_when_something_is_there.json +1 -0
  26. data/fixtures/cassettes/BoxCli_DeleteCommand/does_not_raise_an_exception_when_deleting_something_that_exists.json +1 -0
  27. data/fixtures/cassettes/BoxCli_DeleteCommand/raises_an_exception_when_there_is_nothing_to_delete.json +1 -0
  28. data/fixtures/cassettes/BoxCli_InfoCommand/provides_output_regarding_the_item_if_it_exists.json +1 -0
  29. data/fixtures/cassettes/BoxCli_InfoCommand/raises_an_exception_if_nothing_is_there.json +1 -0
  30. data/fixtures/cassettes/BoxCli_UploadCommand/raises_an_exception_when_a_file_by_that_name_already_exists.json +1 -0
  31. data/fixtures/cassettes/BoxCli_UploadCommand/uploads_a_file_when_none_by_that_name_already_exists.json +1 -0
  32. data/fixtures/cassettes/Generic_Box_Command/fails_for_a_bad_api_key.json +1 -0
  33. data/fixtures/cassettes/Generic_Box_Command/fails_for_bad_credentials.json +1 -0
  34. data/lib/box_cli/account_info_command.rb +7 -0
  35. data/lib/box_cli/auth_token_manager.rb +40 -0
  36. data/lib/box_cli/box_command.rb +13 -0
  37. data/lib/box_cli/command.rb +33 -0
  38. data/lib/box_cli/create_folder_command.rb +9 -0
  39. data/lib/box_cli/delete_command.rb +8 -0
  40. data/lib/box_cli/displayer.rb +10 -0
  41. data/lib/box_cli/hash_to_pretty.rb +28 -0
  42. data/lib/box_cli/info_command.rb +10 -0
  43. data/lib/box_cli/settings_command.rb +24 -0
  44. data/lib/box_cli/terminal.rb +13 -0
  45. data/lib/box_cli/upload_command.rb +8 -0
  46. data/lib/box_cli/version.rb +3 -0
  47. data/lib/box_cli/wrapper.rb +149 -0
  48. data/lib/box_cli.rb +27 -0
  49. data/spec/box_cli/account_info_command_spec.rb +8 -0
  50. data/spec/box_cli/box_command_spec.rb +51 -0
  51. data/spec/box_cli/create_folder_command_spec.rb +22 -0
  52. data/spec/box_cli/delete_command_spec.rb +27 -0
  53. data/spec/box_cli/generic_box_command_spec.rb +10 -0
  54. data/spec/box_cli/hash_to_pretty_spec.rb +57 -0
  55. data/spec/box_cli/info_command_spec.rb +22 -0
  56. data/spec/box_cli/settings_command_spec.rb +12 -0
  57. data/spec/box_cli/upload_command_spec.rb +30 -0
  58. data/spec/box_helpers.rb +40 -0
  59. data/spec/spec_helper.rb +41 -0
  60. 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,13 @@
1
+ module BoxCli
2
+ class Terminal
3
+ def self.ask(prompt)
4
+ highline.ask(prompt)
5
+ end
6
+
7
+ private
8
+
9
+ def self.highline
10
+ @highline ||= HighLine.new
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ module BoxCli
2
+ class UploadCommand < BoxCommand
3
+ def call
4
+ path, folder_path = @args
5
+ wrapper.upload(path, folder_path)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module BoxCli
2
+ VERSION = '0.1.0'
3
+ 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
@@ -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
@@ -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