cloudapp 2.0.0.beta.5 → 2.0.0.beta.6

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/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloudapp (2.0.0.beta.5)
4
+ cloudapp (2.0.0.beta.6)
5
5
  leadlight (~> 0.0.7)
6
+ mime-types (~> 1.19)
6
7
  netrc (~> 0.7.7)
7
8
  typhoeus (~> 0.3.3)
8
9
 
@@ -10,6 +11,7 @@ GEM
10
11
  remote: http://rubygems.org/
11
12
  specs:
12
13
  addressable (2.2.8)
14
+ diff-lcs (1.1.3)
13
15
  fail-fast (1.0.0)
14
16
  faraday (0.8.1)
15
17
  multipart-post (~> 1.1)
@@ -37,6 +39,14 @@ GEM
37
39
  hpricot (>= 0.8.2)
38
40
  mustache (>= 0.7.0)
39
41
  rdiscount (>= 1.5.8)
42
+ rspec (2.12.0)
43
+ rspec-core (~> 2.12.0)
44
+ rspec-expectations (~> 2.12.0)
45
+ rspec-mocks (~> 2.12.0)
46
+ rspec-core (2.12.2)
47
+ rspec-expectations (2.12.1)
48
+ diff-lcs (~> 1.1.3)
49
+ rspec-mocks (2.12.0)
40
50
  typhoeus (0.3.3)
41
51
  mime-types
42
52
 
@@ -47,3 +57,4 @@ DEPENDENCIES
47
57
  cloudapp!
48
58
  rake
49
59
  ronn
60
+ rspec
data/README.md CHANGED
@@ -15,20 +15,38 @@ you're willing to lend a hand, we'd love to officially support it.
15
15
 
16
16
  ``` bash
17
17
  $ gem install cloudapp --pre
18
- $ cloudapp upload screenshot.png
19
18
  $ cloudapp bookmark http://getcloudapp.com
19
+ $ cloudapp upload screenshot.png
20
+ $ cloudapp upload --direct screenshot.png
21
+ ```
22
+
23
+ For a good time, install `gem-man` and read the man page or
24
+ [read it online][man].
25
+
26
+ [man]: http://cloudapp.github.com/cloudapp
27
+
28
+
29
+ ``` bash
30
+ $ gem install gem-man
31
+ $ gem man cloudapp
20
32
  ```
21
33
 
22
34
  ## Commands
23
35
 
24
- ### cloudapp upload
36
+ ### cloudapp upload `<file>`
37
+
38
+ Upload `<file>` and print its link to standard out. Use the `--direct` flag to
39
+ print the file's direct link which is suitable for use in places that expect a
40
+ link to a file like an HTML IMG tag.
25
41
 
26
42
  ``` bash
27
43
  $ cloudapp upload screenshot.png
28
44
  http://cl.ly/abc123
29
45
  ```
30
46
 
31
- ### cloudapp bookmark
47
+ ### cloudapp bookmark `<url>`
48
+
49
+ Bookmark `<url>` and print its link to standard out.
32
50
 
33
51
  ``` bash
34
52
  $ cloudapp bookmark http://getcloudapp.com
@@ -40,29 +58,12 @@ http://cl.ly/abc123
40
58
  A few simple commands to allow scripting and input from other Unix programs
41
59
  would be ideal.
42
60
 
43
- ### Phase: Next
44
-
45
61
  - Share several files: `cloudapp upload *.png`
46
62
  - Bookmark several links: `cloudapp bookmark http://douglasadams.com http://zombo.com`
47
63
  - Handle bookmarks from STDIN: `pbpaste | cloudapp bookmark`
48
- - Handle files from STDIN: `find *.png | cloudapp upload`
49
64
  - Download a drop: `cloudapp download http://cl.ly/abc123`
50
-
51
- ### Phase: Unstoppable
52
-
53
- - Archive and share several files: `cloudapp upload --archive *.png`
54
65
  - Encrypt and share a file: `cloudapp upload --encrypt launch_codes.txt`
55
66
  - Download and decrypt and encrypted drop: `cloudapp download --key=def456 http://cl.ly/abc123`
56
67
 
57
- ### Phase: World Domination
58
-
59
- While we're dreaming, what could you do if `cloudapp` had a database of all your
60
- drops? Bonus points for a light weight daemon that kept everything in sync at
61
- all times.
62
-
63
- - Find all your screen shots: `cloudapp list /^screen ?shot.*\.png$/`
64
- - Trash all your stale drops: `cloudapp delete --last-viewed="> 1 month ago"`
65
- - See your drop views in real time: `cloudapp --tail`
66
-
67
- There's bound to be a better way to express some of these commands, but you get
68
- the picture.
68
+ There's be a better way to express some of these commands, but you get the
69
+ picture.
data/bin/cloudapp CHANGED
@@ -1,30 +1,47 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'cloudapp/credentials'
4
+ require 'cloudapp/cli/prompt'
4
5
  require 'cloudapp/service'
5
6
 
6
7
  def service
7
- CloudApp::Service.using_token Credentials.token
8
+ CloudApp::Service.using_token token
9
+ end
10
+
11
+ def token
12
+ Credentials.token
13
+ end
14
+
15
+ def valid_token?
16
+ !token.nil? and service.root.authorized?
8
17
  end
9
18
 
10
19
  def error error
11
20
  puts "ERROR: #{error}"
12
- exit 1
21
+ exit 9
13
22
  end
14
23
 
15
- def validate_url url
24
+ def valid_url? url
16
25
  error 'URL missing' if url.nil?
17
26
  error "#{ url } doesn't look like a valid URL" unless url =~ URI.regexp
27
+ true
18
28
  end
19
29
 
20
- def validate_file file
30
+ def valid_file? file
21
31
  error "File doesn't exist" if file.is_a? Errno::ENOENT
22
32
  error 'File missing' if file.nil? or file == STDIN
33
+ not file.closed?
34
+ end
35
+
36
+ def next_file
37
+ ARGF.file rescue $!
23
38
  end
24
39
 
25
40
 
26
- while service.root.unauthorized?
27
- Credentials.new.ask_for_and_save_credentials
41
+ while not valid_token?
42
+ credentials = CloudApp::CLI::Prompt.new.ask_for_credentials
43
+ token = CloudApp::Service.token_for_account *credentials
44
+ Credentials.save_token token
28
45
  end
29
46
 
30
47
  link = ARGV.delete('--direct') || ARGV.delete('-d') ? :embed : :canonical
@@ -32,13 +49,16 @@ link = ARGV.delete('--direct') || ARGV.delete('-d') ? :embed : :canonical
32
49
  case ARGV.shift
33
50
  when 'bookmark'
34
51
  link = :canonical # No such thing as an embed link for a bookmark.
35
- url = ARGV.shift
36
- validate_url url
37
- puts service.bookmark(url).link(link)
52
+ while url = ARGV.shift
53
+ break unless valid_url? url
54
+ puts service.bookmark(url).link(link)
55
+ end
38
56
  when 'upload'
39
- file = ARGF.file rescue $!
40
- validate_file file
41
- puts service.upload(file).link(link)
57
+ while file = next_file
58
+ break unless valid_file? file
59
+ puts service.upload(file).link(link)
60
+ ARGF.skip
61
+ end
42
62
  else
43
63
  puts <<EOS
44
64
  Usage:
data/cloudapp.gemspec CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'cloudapp'
16
- s.version = '2.0.0.beta.5'
17
- s.date = '2012-12-17'
16
+ s.version = '2.0.0.beta.6'
17
+ s.date = '2012-12-23'
18
18
  s.rubyforge_project = 'cloudapp'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -43,14 +43,16 @@ Gem::Specification.new do |s|
43
43
 
44
44
  ## List your runtime dependencies here. Runtime dependencies are those
45
45
  ## that are needed for an end user to actually USE your code.
46
- s.add_dependency 'netrc', '~> 0.7.7'
47
- s.add_dependency 'leadlight', '~> 0.0.7'
48
- s.add_dependency 'typhoeus', '~> 0.3.3'
46
+ s.add_dependency 'netrc', '~> 0.7.7'
47
+ s.add_dependency 'leadlight', '~> 0.0.7'
48
+ s.add_dependency 'mime-types', '~> 1.19'
49
+ s.add_dependency 'typhoeus', '~> 0.3.3'
49
50
 
50
51
  ## List your development dependencies here. Development dependencies are
51
52
  ## those that are only needed during development
52
53
  s.add_development_dependency 'rake'
53
54
  s.add_development_dependency 'ronn'
55
+ s.add_development_dependency 'rspec'
54
56
 
55
57
  ## Leave this section as-is. It will be automatically generated from the
56
58
  ## contents of your Git repository via the gemspec task. DO NOT REMOVE
@@ -66,12 +68,21 @@ Gem::Specification.new do |s|
66
68
  cloudapp.gemspec
67
69
  lib/cloudapp.rb
68
70
  lib/cloudapp/authorized.rb
71
+ lib/cloudapp/cli/prompt.rb
69
72
  lib/cloudapp/collection_json.rb
73
+ lib/cloudapp/collection_json/collection.rb
74
+ lib/cloudapp/collection_json/item.rb
75
+ lib/cloudapp/collection_json/template.rb
70
76
  lib/cloudapp/credentials.rb
71
77
  lib/cloudapp/service.rb
72
78
  man/cloudapp.1
73
79
  man/cloudapp.1.html
74
80
  man/cloudapp.1.ronn
81
+ spec/cloudapp/authorized_spec.rb
82
+ spec/cloudapp/collection_json/collection_spec.rb
83
+ spec/cloudapp/collection_json/item_spec.rb
84
+ spec/cloudapp/collection_json/template_spec.rb
85
+ spec/cloudapp/credentials_spec.rb
75
86
  ]
76
87
  # = MANIFEST =
77
88
 
@@ -0,0 +1,34 @@
1
+ # Lovingly borrowed from the heroku gem:
2
+ # https://github.com/heroku/heroku/blob/master/lib/heroku/auth.rb
3
+ module CloudApp
4
+ module CLI
5
+ class Prompt
6
+ def ask_for_credentials
7
+ puts "Sign into CloudApp."
8
+ print "Email: "
9
+ email = ask
10
+ print "Password (typing will be hidden): "
11
+ password = ask_for_password
12
+ [ email, password ]
13
+ end
14
+
15
+ def ask() $stdin.gets.to_s.strip end
16
+ def ask_for_password
17
+ echo_off
18
+ password = ask
19
+ puts
20
+ echo_on
21
+ return password
22
+ end
23
+
24
+ def echo_on() with_tty { system "stty echo" } end
25
+ def echo_off() with_tty { system "stty -echo" } end
26
+ def with_tty(&block)
27
+ return unless $stdin.isatty
28
+ yield
29
+ rescue
30
+ # fails on windows
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ require 'cloudapp/collection_json/item'
2
+ require 'cloudapp/collection_json/template'
3
+
4
+ module CloudApp
5
+ module CollectionJson
6
+ class Collection < Item
7
+ def initialize representation
8
+ super representation.fetch('collection')
9
+ end
10
+
11
+ def item() items.first end
12
+ def items
13
+ fetch('items', []).map {|item| Item.new(item) }
14
+ end
15
+
16
+ def template
17
+ Template.new(fetch('template'), href)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'delegate'
2
+
3
+ module CloudApp
4
+ module CollectionJson
5
+ class Item < SimpleDelegator
6
+ def href() fetch('href') end
7
+ def rel() fetch('rel') end
8
+
9
+ def links
10
+ fetch('links', []).map {|link| Item.new(link) }
11
+ end
12
+
13
+ def link rel
14
+ links.find {|link| link.rel == rel.to_s }.href
15
+ end
16
+
17
+ def data
18
+ data = {}
19
+ fetch('data').each do |datum|
20
+ data[datum.fetch('name')] = datum.fetch('value')
21
+ end
22
+ data
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'cloudapp/collection_json/item'
2
+
3
+ module CloudApp
4
+ module CollectionJson
5
+ class Template < Item
6
+ attr_reader :href
7
+
8
+ def initialize item, href
9
+ @href = href
10
+ super item
11
+ end
12
+
13
+ def fill key, value
14
+ return self unless data.has_key? key
15
+ new_data = fetch('data').map {|datum|
16
+ if datum.fetch('name') == key
17
+ datum = datum.merge('value' => value)
18
+ end
19
+ datum
20
+ }
21
+ new_item = self.merge('data' => new_data)
22
+ Template.new new_item, href
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,7 @@
1
+ require 'cloudapp/collection_json/item'
2
+ require 'cloudapp/collection_json/collection'
3
+ require 'cloudapp/collection_json/template'
4
+
1
5
  module CloudApp
2
6
  module CollectionJson
3
7
  Tint = Leadlight::Tint.new 'collection+json', status: [ :success, 401 ] do
@@ -7,6 +11,7 @@ module CloudApp
7
11
 
8
12
  module Representation
9
13
  extend Forwardable
14
+ def_delegators :collection, :template, :item
10
15
 
11
16
  def self.extended representation
12
17
  Collection.new(representation).links.each do |link|
@@ -21,66 +26,6 @@ module CloudApp
21
26
  def collection
22
27
  Collection.new(self)
23
28
  end
24
-
25
- def_delegators :collection, :template, :item
26
-
27
- class Item < SimpleDelegator
28
- def links
29
- fetch('links', []).map {|link| Item.new(link) }
30
- end
31
-
32
- def link rel
33
- links.find {|link| link.rel == rel.to_s }.href
34
- end
35
-
36
- def href() fetch('href') end
37
- def rel() fetch('rel') end
38
- def data
39
- data = {}
40
- fetch('data').each do |datum|
41
- data[datum.fetch('name')] = datum.fetch('value')
42
- end
43
- data
44
- end
45
- end
46
-
47
- class Collection < Item
48
- def initialize representation
49
- super representation.fetch('collection')
50
- end
51
-
52
- def template() Template.new(fetch('template'), href) end
53
- def items
54
- fetch('items').map {|item| Item.new(item) }
55
- end
56
-
57
- def item
58
- items.first
59
- end
60
- end
61
-
62
- class Template < Item
63
- attr_reader :href
64
-
65
- def initialize item, href
66
- @href = href
67
- super item
68
- end
69
-
70
- def enctype() fetch('enctype') end
71
-
72
- def fill key, value
73
- return self unless data.has_key?(key)
74
- new_data = fetch('data').map {|datum|
75
- if datum.fetch('name') == key
76
- datum = datum.merge 'value' => value
77
- end
78
- datum
79
- }
80
- new_item = self.merge('data' => new_data)
81
- Template.new new_item, href
82
- end
83
- end
84
29
  end
85
30
  end
86
31
  end
@@ -1,115 +1,33 @@
1
- # Taken from the heroku gem.
2
- # https://github.com/heroku/heroku/blob/master/lib/heroku/auth.rb
3
1
  require 'netrc'
4
2
 
5
3
  class Credentials
6
- def self.token
7
- new.credentials.last
8
- end
4
+ attr_reader :netrc
9
5
 
10
- def netrc_path
11
- default = Netrc.default_path
12
- encrypted = default + ".gpg"
13
- if File.exists?(encrypted)
14
- encrypted
15
- else
16
- default
17
- end
6
+ def initialize netrc
7
+ @netrc = netrc
18
8
  end
19
9
 
20
- def netrc
21
- @netrc ||= begin
22
- File.exists?(netrc_path) && Netrc.read(netrc_path)
23
- rescue => error
24
- if error.message =~ /^Permission bits for/
25
- perm = File.stat(netrc_path).mode & 0777
26
- abort("Permissions #{perm} for '#{netrc_path}' are too open. You should run `chmod 0600 #{netrc_path}` so that your credentials are NOT accessible by others.")
27
- else
28
- raise error
29
- end
30
- end
10
+ def self.token netrc = Netrc.read
11
+ new(netrc).token
31
12
  end
32
13
 
33
- def credentials=(credentials) @credentials = credentials end
34
- def credentials()
35
- (@credentials ||= read_credentials) || ask_for_and_save_credentials
14
+ def self.save_token token, netrc = Netrc.read
15
+ new(netrc).save_token token
36
16
  end
37
17
 
38
- def read_credentials
39
- # TODO: convert legacy credentials to netrc
40
- # if File.exists?(legacy_credentials_path)
41
- # @api, @client = nil
42
- # @credentials = File.read(legacy_credentials_path).split("\n")
43
- # write_credentials
44
- # FileUtils.rm_f(legacy_credentials_path)
45
- # end
46
-
47
- # read netrc credentials if they exist
48
- self.credentials = netrc['api.getcloudapp.com'] if netrc
18
+ def token
19
+ credentials.last
49
20
  end
50
21
 
51
- def write_credentials
52
- FileUtils.mkdir_p(File.dirname(netrc_path))
53
- FileUtils.touch(netrc_path)
54
- FileUtils.chmod(0600, netrc_path)
55
- netrc['api.getcloudapp.com'] = credentials
22
+ def save_token token
23
+ return if token.nil? or token =~ /^\s*$/
24
+ netrc['api.getcloudapp.com'] = [ 'api@getcloudapp.com', token ]
56
25
  netrc.save
57
26
  end
58
27
 
59
- def delete_credentials
60
- # TODO: delete legacy credentials
61
- # if File.exists?(legacy_credentials_path)
62
- # FileUtils.rm_f(legacy_credentials_path)
63
- # end
64
- if netrc
65
- netrc.delete('api.getcloudapp.com')
66
- netrc.save
67
- end
68
- self.credentials = nil
69
- end
70
-
71
- def ask_for_and_save_credentials
72
- self.credentials = ask_for_credentials
73
- write_credentials
74
- credentials
75
- end
76
-
77
- def ask_for_credentials
78
- puts "Enter your CloudApp credentials."
79
-
80
- print "Email: "
81
- email = ask
82
-
83
- print "Password (typing will be hidden): "
84
- password = ask_for_password
85
-
86
- # TODO: Remove this dependency on Service.
87
- token = CloudApp::Service.token_for_account email, password
88
- unless token
89
- puts "Incorrect email or password."
90
- puts
91
- delete_credentials
92
- return ask_for_credentials
93
- end
94
-
95
- [ email, token ]
96
- end
97
-
98
- def ask() $stdin.gets.to_s.strip end
99
- def ask_for_password
100
- echo_off
101
- password = ask
102
- puts
103
- echo_on
104
- return password
105
- end
28
+ private
106
29
 
107
- def echo_on() with_tty { system "stty echo" } end
108
- def echo_off() with_tty { system "stty -echo" } end
109
- def with_tty(&block)
110
- return unless $stdin.isatty
111
- yield
112
- rescue
113
- # fails on windows
30
+ def credentials
31
+ Array netrc['api.getcloudapp.com']
114
32
  end
115
33
  end
@@ -1,12 +1,13 @@
1
1
  require 'leadlight'
2
2
  require 'cloudapp/authorized'
3
3
  require 'cloudapp/collection_json'
4
+ require 'mime/types'
4
5
  require 'uri'
5
6
 
6
7
  module CloudApp
7
8
  class Service
8
9
  Leadlight.build_service self do
9
- url 'http://api.getcloudapp.com'
10
+ url 'https://api.getcloudapp.com'
10
11
  tints << CloudApp::CollectionJson::Tint
11
12
  tints << CloudApp::Authorized::Tint
12
13
 
@@ -70,7 +71,7 @@ module CloudApp
70
71
 
71
72
  def upload_file(path, template)
72
73
  file = File.open path
73
- file_io = Faraday::UploadIO.new file, 'image/png' # TODO: Use correct mime type
74
+ file_io = Faraday::UploadIO.new file, mime_type_for(path)
74
75
  template = template.fill('file', file_io)
75
76
  uri = Addressable::URI.parse template.href
76
77
 
@@ -87,5 +88,10 @@ module CloudApp
87
88
  end
88
89
  end
89
90
  end
91
+
92
+ def mime_type_for path
93
+ MIME::Types.type_for(File.basename(path)).first ||
94
+ 'application/octet-stream'
95
+ end
90
96
  end
91
97
  end
data/lib/cloudapp.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CloudApp
2
- VERSION = '2.0.0.beta.5'
2
+ VERSION = '2.0.0.beta.6'
3
3
  end
data/man/cloudapp.1 CHANGED
@@ -19,7 +19,7 @@ Upload a file or share a bookmark with CloudApp\. The drop\'s share link will be
19
19
  .
20
20
  .TP
21
21
  \fB\-d\fR, \fB\-\-direct\fR
22
- Print the drop\'s direct link after creation\. The direct link is suitable for use in places that expect a link to a file content like an HTML IMG tag\.
22
+ Print the drop\'s direct link after creation\. The direct link is suitable for use in places that expect a link to a file like an HTML IMG tag\.
23
23
  .
24
24
  .SH "EXIT STATUS"
25
25
  cloudapp may return one of several error codes if it encouters problems\.
@@ -31,7 +31,7 @@ cloudapp may return one of several error codes if it encouters problems\.
31
31
  \fB1\fR File exceeds the limits of the account\'s plan
32
32
  .
33
33
  .IP "\(bu" 4
34
- \fB9\fR Something horrible has happened
34
+ \fB9\fR Some horrible, unexpected thing has happened
35
35
  .
36
36
  .IP "" 0
37
37
  .
data/man/cloudapp.1.html CHANGED
@@ -94,7 +94,7 @@ printed to standard output. Account credentials are stored in <code>~/.netrc</co
94
94
 
95
95
  <dl>
96
96
  <dt><code>-d</code>, <code>--direct</code></dt><dd>Print the drop's direct link after creation. The direct link is suitable for
97
- use in places that expect a link to a file content like an HTML IMG tag.</dd>
97
+ use in places that expect a link to a file like an HTML IMG tag.</dd>
98
98
  </dl>
99
99
 
100
100
 
@@ -105,7 +105,7 @@ use in places that expect a link to a file content like an HTML IMG tag.</dd>
105
105
  <ul>
106
106
  <li><code>0</code> Success</li>
107
107
  <li><code>1</code> File exceeds the limits of the account's plan</li>
108
- <li><code>9</code> Something horrible has happened</li>
108
+ <li><code>9</code> Some horrible, unexpected thing has happened</li>
109
109
  </ul>
110
110
 
111
111
 
data/man/cloudapp.1.ronn CHANGED
@@ -15,7 +15,7 @@ printed to standard output. Account credentials are stored in `~/.netrc`.
15
15
 
16
16
  - `-d`, `--direct`:
17
17
  Print the drop's direct link after creation. The direct link is suitable for
18
- use in places that expect a link to a file content like an HTML IMG tag.
18
+ use in places that expect a link to a file like an HTML IMG tag.
19
19
 
20
20
  ## EXIT STATUS
21
21
 
@@ -23,7 +23,7 @@ cloudapp may return one of several error codes if it encouters problems.
23
23
 
24
24
  - `0` Success
25
25
  - `1` File exceeds the limits of the account's plan
26
- - `9` Something horrible has happened
26
+ - `9` Some horrible, unexpected thing has happened
27
27
 
28
28
  ## FILES
29
29
 
@@ -0,0 +1,19 @@
1
+ require 'cloudapp/authorized'
2
+
3
+ describe CloudApp::Authorized::Representation do
4
+ let(:representation) { stub :representation, __response__: response }
5
+ let(:response) { stub :response, status: status }
6
+ subject { representation.extend described_class }
7
+
8
+ context 'an unauthorized response' do
9
+ let(:status) { 401 }
10
+ it { should be_unauthorized }
11
+ it { should_not be_authorized }
12
+ end
13
+
14
+ context 'a success response' do
15
+ let(:status) { 200 }
16
+ it { should_not be_unauthorized }
17
+ it { should be_authorized }
18
+ end
19
+ end
@@ -0,0 +1,69 @@
1
+ require 'cloudapp/collection_json/collection'
2
+
3
+ describe CloudApp::CollectionJson::Collection do
4
+ let(:collection) { described_class.new(data) }
5
+ subject { collection }
6
+
7
+ describe 'the collection item' do
8
+ let(:data) {{ 'collection' => { 'href' => 'http://href.com' }}}
9
+ its(:href) { should eq 'http://href.com' }
10
+ end
11
+
12
+ describe '#items' do
13
+ let(:data) {{
14
+ 'collection' => {
15
+ 'items' => [
16
+ { 'href' => 'http://one.com' },
17
+ { 'href' => 'http://two.com' } ]}
18
+ }}
19
+ subject { collection.items }
20
+
21
+ it { should be_an Array }
22
+ it { should have(2).items }
23
+
24
+ it 'returns an array of Items' do
25
+ subject.each do |item|
26
+ item.should be_an CloudApp::CollectionJson::Item
27
+ end
28
+
29
+ item = subject.first
30
+ item.href.should eq 'http://one.com'
31
+ end
32
+
33
+ context 'with no items' do
34
+ let(:data) {{ 'collection' => {} }}
35
+ it { should be_empty }
36
+ end
37
+ end
38
+
39
+ describe '#item' do
40
+ let(:data) {{
41
+ 'collection' => {
42
+ 'items' => [
43
+ { 'href' => 'http://one.com' },
44
+ { 'href' => 'http://two.com' } ]}}}
45
+ subject { collection.item }
46
+
47
+ it { should eq collection.items.first }
48
+
49
+ context 'with no items' do
50
+ let(:data) {{ 'collection' => {} }}
51
+ it { should be_nil }
52
+ end
53
+ end
54
+
55
+ describe '#template' do
56
+ let(:data) {{
57
+ 'collection' => {
58
+ 'href' => 'http://href.com',
59
+ 'template' => {
60
+ 'data' => [
61
+ { 'name' => 'first_name', 'value' => '' },
62
+ { 'name' => 'last_name', 'value' => '' } ]}}}}
63
+ subject { collection.template }
64
+
65
+ it { should be_an CloudApp::CollectionJson::Template }
66
+ its(:href) { should eq 'http://href.com' }
67
+ its(:data) { should eq 'first_name' => '', 'last_name' => '' }
68
+ end
69
+ end
@@ -0,0 +1,55 @@
1
+ require 'cloudapp/collection_json/item'
2
+
3
+ describe CloudApp::CollectionJson::Item do
4
+ subject { described_class.new(data) }
5
+
6
+ describe '#href' do
7
+ let(:data) {{ 'href' => 'http://getcloudapp.com' }}
8
+ its(:href) { should eq 'http://getcloudapp.com' }
9
+ end
10
+
11
+ describe '#rel' do
12
+ let(:data) {{ 'rel' => 'relation' }}
13
+ its(:rel) { should eq 'relation' }
14
+ end
15
+
16
+ describe '#links' do
17
+ subject { described_class.new(data).links }
18
+ let(:data) {{ 'links' => [
19
+ { 'rel' => 'self', 'href' => 'http://self.com' },
20
+ { 'rel' => 'next', 'href' => 'http://next.com' }] }}
21
+
22
+ it { should be_an Array }
23
+ it { should have(2).items }
24
+
25
+ it 'returns an array of Items' do
26
+ subject.each do |item|
27
+ item.should be_a described_class
28
+ end
29
+
30
+ item = subject.first
31
+ item.rel.should eq 'self'
32
+ item.href.should eq 'http://self.com'
33
+ end
34
+
35
+ context 'with no links' do
36
+ let(:data) { {} }
37
+ it { should be_empty }
38
+ end
39
+ end
40
+
41
+ describe '#link' do
42
+ subject { described_class.new(data).link('next') }
43
+ let(:data) {{ 'links' => [
44
+ { 'rel' => 'self', 'href' => 'http://self.com' },
45
+ { 'rel' => 'next', 'href' => 'http://next.com' }] }}
46
+
47
+ it { should eq 'http://next.com' }
48
+ end
49
+
50
+ describe '#data' do
51
+ let(:data) {{ 'data' => [{ 'name' => 'first_name', 'value' => 'Arthur' },
52
+ { 'name' => 'last_name', 'value' => 'Dent' }] }}
53
+ its(:data) { should eq 'first_name' => 'Arthur', 'last_name' => 'Dent' }
54
+ end
55
+ end
@@ -0,0 +1,35 @@
1
+ require 'cloudapp/collection_json/template'
2
+
3
+ describe CloudApp::CollectionJson::Template do
4
+ let(:template) { described_class.new(data, 'http://href.com') }
5
+ subject { template }
6
+
7
+ describe 'the template item' do
8
+ let(:data) {{ 'data' => [
9
+ { 'name' => 'first_name', 'value' => '' },
10
+ { 'name' => 'last_name', 'value' => '' } ]}}
11
+
12
+ its(:href) { should eq 'http://href.com' }
13
+ its(:data) { should eq 'first_name' => '', 'last_name' => '' }
14
+ end
15
+
16
+ describe '#fill' do
17
+ let(:data) {{ 'data' => [
18
+ { 'name' => 'first_name', 'value' => '' },
19
+ { 'name' => 'last_name', 'value' => '' } ]}}
20
+ subject { template.fill('first_name', 'Arthur') }
21
+
22
+ it { should be_a described_class }
23
+ it { should_not eq template }
24
+
25
+ it 'fills the datum' do
26
+ subject.data.fetch('first_name').should eq 'Arthur'
27
+ end
28
+
29
+ context 'a nonexistent key' do
30
+ it 'does nothing' do
31
+ subject.fill('bad', 'value').should eq subject
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,61 @@
1
+ require 'cloudapp/credentials'
2
+
3
+ describe Credentials do
4
+ describe '.token' do
5
+ let(:netrc) { stub :netrc, :[] => %w( arthur@dent.com towel ) }
6
+ subject { Credentials.token(netrc) }
7
+ it { should eq 'towel' }
8
+ end
9
+
10
+ describe '#token' do
11
+ let(:netrc) { stub :netrc, :[] => %w( arthur@dent.com towel ) }
12
+ subject { Credentials.new(netrc).token }
13
+
14
+ it { should eq 'towel' }
15
+
16
+ it 'fetches token from netrc' do
17
+ netrc.should_receive(:[]).with('api.getcloudapp.com').once
18
+ subject
19
+ end
20
+
21
+ context 'without saved token' do
22
+ let(:netrc) { stub :netrc, :[] => nil }
23
+ it { should be_nil }
24
+ end
25
+ end
26
+
27
+ describe '.save_token' do
28
+ let(:netrc) { stub :netrc, :[]= => nil }
29
+
30
+ it 'saves the token' do
31
+ netrc.should_receive(:save).once.ordered
32
+ Credentials.save_token 'new token', netrc
33
+ end
34
+ end
35
+
36
+ describe '#save_token' do
37
+ let(:netrc) { stub :netrc }
38
+ subject { Credentials.new(netrc) }
39
+
40
+ it 'saves the token' do
41
+ credentials = [ 'api@getcloudapp.com', 'new token' ]
42
+ netrc.should_receive(:[]=).with('api.getcloudapp.com', credentials)
43
+ .once.ordered
44
+ netrc.should_receive(:save).once.ordered
45
+ subject.save_token 'new token'
46
+ end
47
+
48
+ it 'ignores a nil token' do
49
+ netrc.should_not_receive(:[]=)
50
+ netrc.should_not_receive(:save)
51
+ subject.save_token nil
52
+ end
53
+
54
+ it 'ignores an empty token' do
55
+ netrc.should_not_receive(:[]=)
56
+ netrc.should_not_receive(:save)
57
+ subject.save_token ''
58
+ subject.save_token ' '
59
+ end
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta.5
4
+ version: 2.0.0.beta.6
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-17 00:00:00.000000000 Z
12
+ date: 2012-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: netrc
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
45
  version: 0.0.7
46
+ - !ruby/object:Gem::Dependency
47
+ name: mime-types
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '1.19'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.19'
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: typhoeus
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +107,22 @@ dependencies:
91
107
  - - ! '>='
92
108
  - !ruby/object:Gem::Version
93
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
94
126
  description: Experience all the pleasures of sharing with CloudApp now in your terminal.
95
127
  email: larry@marburger.cc
96
128
  executables:
@@ -109,12 +141,21 @@ files:
109
141
  - cloudapp.gemspec
110
142
  - lib/cloudapp.rb
111
143
  - lib/cloudapp/authorized.rb
144
+ - lib/cloudapp/cli/prompt.rb
112
145
  - lib/cloudapp/collection_json.rb
146
+ - lib/cloudapp/collection_json/collection.rb
147
+ - lib/cloudapp/collection_json/item.rb
148
+ - lib/cloudapp/collection_json/template.rb
113
149
  - lib/cloudapp/credentials.rb
114
150
  - lib/cloudapp/service.rb
115
151
  - man/cloudapp.1
116
152
  - man/cloudapp.1.html
117
153
  - man/cloudapp.1.ronn
154
+ - spec/cloudapp/authorized_spec.rb
155
+ - spec/cloudapp/collection_json/collection_spec.rb
156
+ - spec/cloudapp/collection_json/item_spec.rb
157
+ - spec/cloudapp/collection_json/template_spec.rb
158
+ - spec/cloudapp/credentials_spec.rb
118
159
  homepage: https://github.com/cloudapp/cloudapp
119
160
  licenses: []
120
161
  post_install_message: