wl 0.0.3 → 0.0.4

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/lib/wl/cli.rb CHANGED
@@ -4,22 +4,32 @@ require 'highline'
4
4
  module Wl
5
5
  class CLI < Thor
6
6
  desc 'login', 'Logs in to Wunderlist'
7
- option :email, desc: 'Wunderlist email'
7
+ option :email, desc: 'Wunderlist email'
8
8
  option :password, desc: 'Wunderlist password'
9
9
  def login
10
- email = options[:email] || ui.ask('Wunderlist email: ')
10
+ email = options[:email] || ui.ask('Wunderlist email: ')
11
11
  password = options[:password] || ui.ask('Wunderlist password: ') { |q| q.echo = '*' }
12
12
 
13
- client = Wl::Client.new
14
13
  login = client.login(email, password)
15
-
16
- dotwl = Dotwl.new
17
14
  dotwl.login(login)
18
15
 
19
16
  say login.to_json
20
17
  end
21
18
 
19
+ desc 'tasks', 'Lists all your tasks'
20
+ def tasks
21
+ say client.tasks.to_json
22
+ end
23
+
22
24
  private
25
+ def client
26
+ @client ||= Wl::Client.new(dotwl: dotwl)
27
+ end
28
+
29
+ def dotwl
30
+ @dotwl ||= Dotwl.new
31
+ end
32
+
23
33
  def ui
24
34
  @ui ||= HighLine.new
25
35
  end
data/lib/wl/client.rb CHANGED
@@ -1,15 +1,28 @@
1
+ require 'shy'
1
2
  require 'api_smith'
2
3
 
3
4
  module Wl
4
- class Client < APISmith::Base
5
+ class Client < Shy.new(:dotwl)
6
+ include APISmith::Client
5
7
  base_uri 'https://api.wunderlist.com/'
6
8
 
7
9
  def login(email, password)
8
- response = post('login', extra_query: {email: email, password: password}, as: Login)
9
- if response.code == 200
10
- Login.new(response.parsed_response)
10
+ post('login', extra_query: {email: email, password: password}, transformer: Login)
11
+ end
12
+
13
+ def tasks
14
+ get('me/tasks', transformer: Task)
15
+ end
16
+
17
+ def base_request_options
18
+ if dotwl.token
19
+ {
20
+ headers: {
21
+ 'Authorization' => "Bearer #{dotwl.token}"
22
+ }
23
+ }
11
24
  else
12
- raise response.inspect
25
+ super
13
26
  end
14
27
  end
15
28
  end
data/lib/wl/dotwl.rb CHANGED
@@ -9,6 +9,10 @@ module Wl
9
9
  FileUtils.mkdir_p("#{Dir.home}/.wl", mode: 0700).last
10
10
  end
11
11
 
12
+ def token
13
+ File.read(token_path) rescue nil
14
+ end
15
+
12
16
  private
13
17
  def token_path
14
18
  "#{dir}/token"
data/lib/wl/login.rb CHANGED
@@ -14,5 +14,6 @@ module Wl
14
14
  property :confirmation_state
15
15
  property :type
16
16
  property :email_confirmed
17
+ property :errors
17
18
  end
18
19
  end
data/lib/wl/task.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'api_smith'
2
+
3
+ module Wl
4
+ class Task < APISmith::Smash
5
+ property :id
6
+ property :assignee_id
7
+ property :completed_at
8
+ property :created_at
9
+ property :created_by_id
10
+ property :deleted_at
11
+ property :due_date
12
+ property :list_id
13
+ property :local_identifier
14
+ property :note
15
+ property :owner_id
16
+ property :parent_id
17
+ property :position
18
+ property :recurrence_count
19
+ property :recurrence_type
20
+ property :recurring_parent_id
21
+ property :starred
22
+ property :title
23
+ property :type
24
+ property :updated_at
25
+ property :updated_by_id
26
+ property :user_id
27
+ property :version
28
+ property :errors
29
+ end
30
+ end
data/lib/wl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Wl
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/wl.rb CHANGED
@@ -5,4 +5,5 @@ module Wl
5
5
  autoload :CLI, 'wl/cli'
6
6
  autoload :Dotwl, 'wl/dotwl'
7
7
  autoload :Login, 'wl/login'
8
+ autoload :Task, 'wl/task'
8
9
  end
@@ -0,0 +1,125 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.wunderlist.com/me/tasks?
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Authorization:
11
+ - Bearer 131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741
12
+ response:
13
+ status:
14
+ code: 200
15
+ message: OK
16
+ headers:
17
+ Cache-Control:
18
+ - must-revalidate, private, max-age=0
19
+ Content-Type:
20
+ - application/json; charset=utf-8
21
+ Date:
22
+ - Sun, 24 Mar 2013 07:31:29 GMT
23
+ Etag:
24
+ - ! '"778391fe24fb7fcae2a445c4b3a7982a"'
25
+ Server:
26
+ - nginx
27
+ Status:
28
+ - 200 OK
29
+ Vary:
30
+ - Accept-Encoding
31
+ X-6w-Client-Status:
32
+ - unknown
33
+ X-6w-Timestamp:
34
+ - '1364110288'
35
+ X-Rack-Cache:
36
+ - miss
37
+ X-Ratelimit-Delay-Hard:
38
+ - '0'
39
+ X-Ratelimit-Delay-Soft:
40
+ - '620'
41
+ X-Request-Id:
42
+ - 25225fa3fe737f995481ab2cc5ec4548
43
+ X-Server:
44
+ - ip-10-227-29-235
45
+ Transfer-Encoding:
46
+ - chunked
47
+ Connection:
48
+ - keep-alive
49
+ body:
50
+ encoding: US-ASCII
51
+ string: ! "[{\n \"id\": \"ACIdABLJbhA\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n
52
+ \ \"updated_at\": \"2013-03-24T07:31:24Z\",\n \"title\": \"Do something you
53
+ want\",\n \"starred\": false,\n \"note\": null,\n \"completed_at\": null,\n
54
+ \ \"local_identifier\": \"localId:web:ABcDEFGhIJk:Task:BLAHBLAHBLAHBLAH_01\",\n
55
+ \ \"recurrence_type\": null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\":
56
+ null,\n \"due_date\": null,\n \"parent_id\": null,\n \"created_by_id\":
57
+ \"ABcDEFGhIJk\",\n \"updated_by_id\": \"ABcDEFGhIJk\",\n \"completed_by_id\":
58
+ null,\n \"version\": 1,\n \"assignee_id\": null,\n \"type\": \"Task\",\n
59
+ \ \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\": \"ABcDEFGhIJk\",\n \"position\":
60
+ 20.00006,\n \"list_id\": \"inbox\",\n \"deleted_at\": null\n}, {\n \"id\":
61
+ \"ACIdABLJbg4\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n \"updated_at\":
62
+ \"2013-03-24T07:31:24Z\",\n \"title\": \"Do something productive\",\n \"starred\":
63
+ false,\n \"note\": null,\n \"completed_at\": null,\n \"local_identifier\":
64
+ \"localId:web:ABcDEFGhIJk:Task:BLAHBLAHBLAHBLAH_02\",\n \"recurrence_type\":
65
+ null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\": null,\n \"due_date\":
66
+ null,\n \"parent_id\": null,\n \"created_by_id\": \"ABcDEFGhIJk\",\n \"updated_by_id\":
67
+ \"ABcDEFGhIJk\",\n \"completed_by_id\": null,\n \"version\": 1,\n \"assignee_id\":
68
+ null,\n \"type\": \"Task\",\n \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\":
69
+ \"ABcDEFGhIJk\",\n \"position\": 10.00003,\n \"list_id\": \"inbox\",\n \"deleted_at\":
70
+ null\n}, {\n \"id\": \"ACIdABLJbg0\",\n \"created_at\": \"2013-03-24T07:31:24Z\",\n
71
+ \ \"updated_at\": \"2013-03-24T07:31:24Z\",\n \"title\": \"Do something useful\",\n
72
+ \ \"starred\": false,\n \"note\": null,\n \"completed_at\": null,\n \"local_identifier\":
73
+ \"localId:web:ABcDEFGhIJk:Task:lw6d7911b474ef405b27406da031d526\",\n \"recurrence_type\":
74
+ null,\n \"recurrence_count\": 0,\n \"recurring_parent_id\": null,\n \"due_date\":
75
+ null,\n \"parent_id\": null,\n \"created_by_id\": \"ABcDEFGhIJk\",\n \"updated_by_id\":
76
+ \"ABcDEFGhIJk\",\n \"completed_by_id\": null,\n \"version\": 1,\n \"assignee_id\":
77
+ null,\n \"type\": \"Task\",\n \"user_id\": \"ABcDEFGhIJk\",\n \"owner_id\":
78
+ \"ABcDEFGhIJk\",\n \"position\": 2.0e-05,\n \"list_id\": \"inbox\",\n \"deleted_at\":
79
+ null\n}]\n"
80
+ http_version:
81
+ recorded_at: Sun, 24 Mar 2013 07:31:29 GMT
82
+ - request:
83
+ method: get
84
+ uri: https://api.wunderlist.com/me/tasks?
85
+ body:
86
+ encoding: US-ASCII
87
+ string: ''
88
+ headers: {}
89
+ response:
90
+ status:
91
+ code: 401
92
+ message: Unauthorized
93
+ headers:
94
+ Cache-Control:
95
+ - no-cache
96
+ Content-Type:
97
+ - application/json; charset=utf-8
98
+ Date:
99
+ - Sun, 24 Mar 2013 07:47:46 GMT
100
+ Server:
101
+ - nginx
102
+ Status:
103
+ - 401 Unauthorized
104
+ X-6w-Client-Status:
105
+ - unknown
106
+ X-6w-Timestamp:
107
+ - '1364111266'
108
+ X-Rack-Cache:
109
+ - miss
110
+ X-Ratelimit-Delay-Hard:
111
+ - '0'
112
+ X-Ratelimit-Delay-Soft:
113
+ - '755'
114
+ X-Request-Id:
115
+ - 251d1dd71af0be5b5359ab58a956c367
116
+ Content-Length:
117
+ - '85'
118
+ Connection:
119
+ - keep-alive
120
+ body:
121
+ encoding: US-ASCII
122
+ string: ! '{"errors":{"message":"You must be authenticated to continue.","type":"unauthorized"}}'
123
+ http_version:
124
+ recorded_at: Sun, 24 Mar 2013 07:47:46 GMT
125
+ recorded_with: VCR 2.4.0
data/spec/helpers/vcr.rb CHANGED
@@ -4,4 +4,5 @@ VCR.configure do |c|
4
4
  c.cassette_library_dir = 'spec/cassettes'
5
5
  c.hook_into :webmock
6
6
  c.configure_rspec_metadata!
7
+ c.default_cassette_options = { match_requests_on: [:method, :uri, :headers] }
7
8
  end
data/spec/wl/cli_spec.rb CHANGED
@@ -2,13 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  module Wl
4
4
  describe CLI do
5
- let(:dotwl) { double(Dotwl).as_null_object }
5
+ let(:dotwl) { double(Dotwl, token: nil).as_null_object }
6
6
 
7
7
  subject do
8
- Dotwl.stub(:new).and_return(dotwl)
9
8
  Wl::CLI.start(args)
10
9
  end
11
10
 
11
+ before do
12
+ Dotwl.stub(:new).and_return(dotwl)
13
+ end
14
+
12
15
  context "by default" do
13
16
  let(:args) { [] }
14
17
 
@@ -28,7 +31,7 @@ module Wl
28
31
 
29
32
  it 'stores the token' do
30
33
  dotwl.should_receive(:login).with(an_instance_of(Login))
31
- subject
34
+ capture(:stdout) { subject }
32
35
  end
33
36
 
34
37
  context 'when an email and password are not provided' do
@@ -48,5 +51,19 @@ module Wl
48
51
  end
49
52
  end
50
53
  end
54
+
55
+ describe 'tasks', vcr: {cassette_name: 'tasks'} do
56
+ let(:args) { %w"tasks" }
57
+
58
+ before do
59
+ dotwl.stub(token: '131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741')
60
+ end
61
+
62
+ it 'prints all the tasks' do
63
+ output = capture(:stdout) { subject }
64
+
65
+ JSON.parse(output).should have(3).tasks
66
+ end
67
+ end
51
68
  end
52
69
  end
@@ -2,20 +2,52 @@ require 'spec_helper'
2
2
 
3
3
  module Wl
4
4
  describe Client do
5
+ let(:dotwl) { double(Dotwl, token: nil) }
6
+
7
+ subject do
8
+ Client.new(dotwl: dotwl)
9
+ end
10
+
5
11
  describe '#login' do
6
12
  context 'when the email address and password are accepted', vcr: {cassette_name: 'login'} do
7
13
  it 'packages the api response in a Login object' do
8
14
  response = subject.login('fake@example.com', 'fakepass')
9
15
  response.should be_a(Login)
10
16
  response.email.should == 'fake@example.com'
17
+ response.errors.should be_nil
11
18
  end
12
19
  end
13
20
 
14
21
  context 'when something goes wrong' do
15
- it 'fails fast printing the raw api response', vcr: {cassette_name: 'login'} do
16
- expect {
17
- subject.login('fake@example.com', 'badpassword')
18
- }.to raise_error /We were unable to locate a user based on the credentials you supplied/
22
+ it 'inserts the errors into the Login object', vcr: {cassette_name: 'login'} do
23
+ response = subject.login('fake@example.com', 'badpassword')
24
+ response.should be_a(Login)
25
+ response.email.should be_nil
26
+ response.errors['type'].should eq('not_found.no_such_user')
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#tasks' do
32
+ context 'when the user has logged in', vcr: {cassette_name: 'tasks'} do
33
+ before do
34
+ dotwl.stub(token: '131378dbc2490bf87b6080ad6aeb758a46673270bbca9c7ea26f434473bbe741')
35
+ end
36
+
37
+ it 'lists all tasks' do
38
+ tasks = subject.tasks
39
+ tasks.map(&:title).should eq [
40
+ "Do something you want",
41
+ "Do something productive",
42
+ "Do something useful"
43
+ ]
44
+ end
45
+ end
46
+
47
+ context 'when the user has not logged in', vcr: {cassette_name: 'tasks' } do
48
+ it 'fails gracefully' do
49
+ tasks = subject.tasks
50
+ tasks.errors['type'].should eq('unauthorized')
19
51
  end
20
52
  end
21
53
  end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Wl
4
+ describe Task do
5
+ it { should be_an(APISmith::Smash) }
6
+ end
7
+ end
data/wl.gemspec CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "thor"
22
22
  spec.add_dependency "highline"
23
23
  spec.add_dependency "api_smith"
24
+ spec.add_dependency "shy"
24
25
 
25
26
  spec.add_development_dependency "bundler", "~> 1.3"
26
27
  spec.add_development_dependency "rake"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: shy
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: bundler
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -163,8 +179,10 @@ files:
163
179
  - lib/wl/client.rb
164
180
  - lib/wl/dotwl.rb
165
181
  - lib/wl/login.rb
182
+ - lib/wl/task.rb
166
183
  - lib/wl/version.rb
167
184
  - spec/cassettes/login.yml
185
+ - spec/cassettes/tasks.yml
168
186
  - spec/helpers/capture_output.rb
169
187
  - spec/helpers/vcr.rb
170
188
  - spec/spec_helper.rb
@@ -172,6 +190,7 @@ files:
172
190
  - spec/wl/client_spec.rb
173
191
  - spec/wl/dotwl_spec.rb
174
192
  - spec/wl/login_spec.rb
193
+ - spec/wl/task_spec.rb
175
194
  - wl.gemspec
176
195
  homepage: http://github.com/hiremaga/wl
177
196
  licenses:
@@ -188,7 +207,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
207
  version: '0'
189
208
  segments:
190
209
  - 0
191
- hash: 2086549849182975583
210
+ hash: 110259217908952548
192
211
  required_rubygems_version: !ruby/object:Gem::Requirement
193
212
  none: false
194
213
  requirements:
@@ -197,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
216
  version: '0'
198
217
  segments:
199
218
  - 0
200
- hash: 2086549849182975583
219
+ hash: 110259217908952548
201
220
  requirements: []
202
221
  rubyforge_project:
203
222
  rubygems_version: 1.8.25
@@ -207,6 +226,7 @@ summary: ! '`wl` is an unofficial Ruby client and command line interface for the
207
226
  awesome Wunderlist'
208
227
  test_files:
209
228
  - spec/cassettes/login.yml
229
+ - spec/cassettes/tasks.yml
210
230
  - spec/helpers/capture_output.rb
211
231
  - spec/helpers/vcr.rb
212
232
  - spec/spec_helper.rb
@@ -214,3 +234,4 @@ test_files:
214
234
  - spec/wl/client_spec.rb
215
235
  - spec/wl/dotwl_spec.rb
216
236
  - spec/wl/login_spec.rb
237
+ - spec/wl/task_spec.rb