togglv8 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b2c12ae09772a1296677907a4e684d3ad5cfde5
4
- data.tar.gz: 5afd4390ec69c38f3a8795e55b9e38a14f96ada7
3
+ metadata.gz: f78f0515e742e278468d6265c6841df07f164230
4
+ data.tar.gz: f78a57c6e31c97ddc5b54679957228e7afac77ed
5
5
  SHA512:
6
- metadata.gz: 96b68a6420a5751a764a8bb54400be952281958d1325b86581ff39d5faa176807cd235a94795e5eb3802228e7f35bdc12bdda2c0b94b89fd07afbbb4b8844e38
7
- data.tar.gz: 2be636c2115bc9be8bb66ebcdedcf8f46be8897d40256deccf96e57af5c7078f5e83a975e58ea133f8ee599b2c263c49fb48cbc2b7ed321952af5c6470860a4c
6
+ metadata.gz: bd36c398494606943d6ba8793a3035864e155a1aae42bfc3844289a362f82e3cf58b9cb16bbc0b72539b3913e886dda59bc9fb7200b5d58dfd1e54935f08a570
7
+ data.tar.gz: fb47297ebb39ab70d08dd80b9e6380f6fdfd306a5aa9d746de1c37ed19f93ba3afb13fb7ac5a170056ccb04613c7694bb11dc77256ff1737268e615dfdbb58e2
data/README.md CHANGED
@@ -36,16 +36,18 @@ toggl_api = TogglV8::API.new(<API_TOKEN>)
36
36
  user = toggl_api.me(all=true)
37
37
  workspaces = toggl_api.my_workspaces(user)
38
38
  workspace_id = workspaces.first['id']
39
- toggl_api.create_time_entry({description: "Workspace time entry",
40
- wid: workspace_id,
41
- duration: 1200,
42
- start: "2015-08-18T01:13:40.000Z",
43
- created_with: "My awesome Ruby application"})
39
+ toggl_api.create_time_entry({
40
+ 'description' => "Workspace time entry",
41
+ 'wid' => workspace_id,
42
+ 'duration' => 1200,
43
+ 'start' => "2015-08-18T01:13:40.000Z",
44
+ 'created_with' => "My awesome Ruby application"
45
+ })
44
46
  ```
45
47
 
46
48
  See specs for more examples.
47
49
 
48
- **Note:** Requests are rate-limited. See [Toggl API docs](https://github.com/toggl/toggl_api_docs#the-api-format):
50
+ **Note:** Requests are rate-limited. The togglv8 gem will handle a 429 response by pausing for 1 second and trying again, for up to 3 attempts. See [Toggl API docs](https://github.com/toggl/toggl_api_docs#the-api-format):
49
51
 
50
52
  > For rate limiting we have implemented a Leaky bucket. When a limit has been hit the request will get a HTTP 429 response and it's the task of the client to sleep/wait until bucket is empty. Limits will and can change during time, but a safe window will be 1 request per second. Limiting is applied per api token per IP, meaning two users from the same IP will get their rate allocated separately.
51
53
 
@@ -59,7 +61,9 @@ Also available on [DocumentUp](https://documentup.com/kanet77/togglv8)
59
61
 
60
62
  Open `coverage/index.html` to see test coverage.
61
63
 
62
- As of 2015-08-21, coverage is "90.39% covered at 6.16 hits/line" according to [SimpleCov](https://rubygems.org/gems/simplecov).
64
+ As of 2015-12-10, coverage is "98.04% covered at 9.5 hits/line" according to [SimpleCov](https://rubygems.org/gems/simplecov).
65
+
66
+ **Note:** Coverage is 91.2% when Pro account features are not tested.
63
67
 
64
68
  ## Acknowledgements
65
69
 
@@ -68,12 +72,14 @@ As of 2015-08-21, coverage is "90.39% covered at 6.16 hits/line" according to [S
68
72
 
69
73
  ## Contributing
70
74
 
71
- 1. Fork it ( https://github.com/[my-github-username]/togglv8/fork )
75
+ 1. Fork it ( https://github.com/kanet77/togglv8/fork )
72
76
  2. Create your feature branch (`git checkout -b my-new-feature`)
73
77
  3. Commit your changes (`git commit -am 'Add some feature'`)
74
78
  4. Push to the branch (`git push origin my-new-feature`)
75
79
  5. Create a new Pull Request
76
80
 
81
+ Pull Requests that include tests are **much** more likely to be accepted and merged quickly.
82
+
77
83
  ## License
78
84
 
79
- Copyright (c) 2013-2015 Tom Kane. Released under the [MIT License](http://opensource.org/licenses/mit-license.php). See [LICENSE.txt](LICENSE.txt) for details.
85
+ Copyright (c) 2013-2015 Tom Kane. Released under the [MIT License](http://opensource.org/licenses/mit-license.php). See [LICENSE.txt](LICENSE.txt) for details.
@@ -14,7 +14,7 @@ module TogglV8
14
14
 
15
15
  def create_client(params)
16
16
  requireParams(params, ['name', 'wid'])
17
- post "clients", {client: params}
17
+ post "clients", { 'client' => params }
18
18
  end
19
19
 
20
20
  def get_client(client_id)
@@ -98,13 +98,14 @@ module TogglV8
98
98
 
99
99
  # [Get project tasks](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#get-project-tasks)
100
100
  def get_project_tasks(project_id)
101
- get "projects/#{project_id}/project_tasks"
101
+ get "projects/#{project_id}/tasks"
102
102
  end
103
103
 
104
104
  # [Get workspace projects](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#get-workspace-projects)
105
105
 
106
106
  # [Delete multiple projects](https://github.com/toggl/toggl_api_docs/blob/master/chapters/projects.md#delete-multiple-projects)
107
107
  def delete_projects(project_ids)
108
+ return if project_ids.nil?
108
109
  delete "projects/#{project_ids.join(',')}"
109
110
  end
110
111
  end
data/lib/togglv8/tasks.rb CHANGED
@@ -20,7 +20,7 @@ module TogglV8
20
20
  # uname : full name of the person to whom the task is assigned to
21
21
 
22
22
  def create_task(params)
23
- requireParams(params, [:name, :pid])
23
+ requireParams(params, ['name', 'pid'])
24
24
  post "tasks", { 'task' => params }
25
25
  end
26
26
 
@@ -30,11 +30,11 @@ module TogglV8
30
30
 
31
31
  # ex: update_task(1894675, {active: true, estimated_seconds: 4500, fields: "done_seconds,uname"})
32
32
  def update_task(task_id, params)
33
- put "tasks/#{task_id.join(',')}", { 'task' => params }
33
+ put "tasks/#{task_id}", { 'task' => params }
34
34
  end
35
35
 
36
36
  def delete_task(task_id)
37
- delete "tasks/#{task_id.join(',')}"
37
+ delete "tasks/#{task_id}"
38
38
  end
39
39
 
40
40
  # ------------ #
@@ -42,10 +42,12 @@ module TogglV8
42
42
  # ------------ #
43
43
 
44
44
  def update_tasks(task_ids, params)
45
+ return if task_ids.nil?
45
46
  put "tasks/#{task_ids.join(',')}", { 'task' => params }
46
47
  end
47
48
 
48
49
  def delete_tasks(task_ids)
50
+ return if task_ids.nil?
49
51
  delete "tasks/#{task_ids.join(',')}"
50
52
  end
51
53
 
@@ -82,9 +82,11 @@ module TogglV8
82
82
  get "time_entries%s" % [params.empty? ? "" : "?#{params.join('&')}"]
83
83
  end
84
84
 
85
- # Example params: {"tags":["billed","productive"], "tag_action": "add"}
85
+ # Example params: {'tags' =>['billed','productive'], 'tag_action' => 'add'}
86
86
  # tag_action can be 'add' or 'remove'
87
87
  def update_time_entries_tags(time_entry_ids, params)
88
+ return if time_entry_ids.nil?
89
+ requireParams(params, ['tags', 'tag_action'])
88
90
  put "time_entries/#{time_entry_ids.join(',')}", { 'time_entry' => params }
89
91
  end
90
92
  end
data/lib/togglv8/users.rb CHANGED
@@ -21,8 +21,8 @@ module TogglV8
21
21
  # new_blog_post : an object with toggl blog post title and link
22
22
 
23
23
  def me(all=nil)
24
- # TODO: Reconcile this with get_client_projects
25
- # NOTE: response['since'] is discarded
24
+ # NOTE: response['since'] is discarded because it is outside response['data']
25
+ # (See TogglV8::API#get in lib/togglv8.rb)
26
26
  get "me%s" % [all.nil? ? "" : "?with_related_data=#{all}"]
27
27
  end
28
28
 
@@ -38,7 +38,6 @@ module TogglV8
38
38
  projects.delete_if { |p| p['server_deleted_at'] }
39
39
  end
40
40
 
41
- # TODO: Test my_deleted_projects
42
41
  def my_deleted_projects(user=nil)
43
42
  user = me(all=true) if user.nil?
44
43
  return {} unless user['projects']
@@ -51,6 +50,11 @@ module TogglV8
51
50
  user['tags'] || {}
52
51
  end
53
52
 
53
+ def my_tasks(user=nil)
54
+ user = me(all=true) if user.nil?
55
+ user['tasks'] || {}
56
+ end
57
+
54
58
  def my_time_entries(user=nil)
55
59
  user = me(all=true) if user.nil?
56
60
  user['time_entries'] || {}
@@ -1,4 +1,4 @@
1
1
  module TogglV8
2
2
  # :section:
3
- VERSION = "1.0.0"
3
+ VERSION = "1.0.2"
4
4
  end
data/lib/togglv8.rb CHANGED
@@ -85,13 +85,12 @@ module TogglV8
85
85
  loop do
86
86
  i += 1
87
87
  full_resp = procs[:api_call].call
88
- @logger.ap(full_resp.env, :debug)
88
+ # @logger.ap(full_resp.env, :debug)
89
89
  break if full_resp.status != 429 || i >= MAX_RETRIES
90
90
  sleep(DELAY_SEC)
91
91
  end
92
92
 
93
- raise "HTTP Status: #{full_resp.status}" unless full_resp.status.between?(200,299)
94
- raise Oj.dump(full_resp.env) unless full_resp.success?
93
+ raise "HTTP Status: #{full_resp.status}" unless full_resp.success?
95
94
  return {} if full_resp.body.nil? || full_resp.body == 'null'
96
95
 
97
96
  full_resp
@@ -99,7 +98,7 @@ module TogglV8
99
98
 
100
99
  def get(resource)
101
100
  full_resp = _call_api(debug_output: lambda { "GET #{resource}" },
102
- api_call: lambda { self.conn.get(resource) } )
101
+ api_call: lambda { self.conn.get(resource) } )
103
102
  return {} if full_resp == {}
104
103
  resp = Oj.load(full_resp.body)
105
104
  return resp['data'] if resp.respond_to?(:has_key?) && resp.has_key?('data')
@@ -108,7 +107,7 @@ module TogglV8
108
107
 
109
108
  def post(resource, data='')
110
109
  full_resp = _call_api(debug_output: lambda { "POST #{resource} / #{data}" },
111
- api_call: lambda { self.conn.post(resource, Oj.dump(data)) } )
110
+ api_call: lambda { self.conn.post(resource, Oj.dump(data)) } )
112
111
  return {} if full_resp == {}
113
112
  resp = Oj.load(full_resp.body)
114
113
  resp['data']
@@ -116,7 +115,7 @@ module TogglV8
116
115
 
117
116
  def put(resource, data='')
118
117
  full_resp = _call_api(debug_output: lambda { "PUT #{resource} / #{data}" },
119
- api_call: lambda { self.conn.put(resource, Oj.dump(data)) } )
118
+ api_call: lambda { self.conn.put(resource, Oj.dump(data)) } )
120
119
  return {} if full_resp == {}
121
120
  resp = Oj.load(full_resp.body)
122
121
  resp['data']
@@ -124,7 +123,7 @@ module TogglV8
124
123
 
125
124
  def delete(resource)
126
125
  full_resp = _call_api(debug_output: lambda { "DELETE #{resource}" },
127
- api_call: lambda { self.conn.delete(resource) } )
126
+ api_call: lambda { self.conn.delete(resource) } )
128
127
  return {} if full_resp == {}
129
128
  full_resp.body
130
129
  end
@@ -127,12 +127,16 @@ describe 'Clients' do
127
127
  expect(client).to include(new_values)
128
128
  end
129
129
 
130
- it 'updates Pro project data', :pro_account do
130
+ # It appears hourly rate is no longer tied to a client despite the docs:
131
+ # https://github.com/toggl/toggl_api_docs/blob/master/chapters/clients.md#clients
132
+ xit 'updates Pro client data', :pro_account do
131
133
  new_values = {
132
134
  'hrate' => '7.77',
133
135
  'cur' => 'USD',
134
136
  }
135
137
  client = @toggl.update_client(@client['id'], new_values)
138
+
139
+ client = @toggl.get_client(@client['id'])
136
140
  expect(client).to include(new_values)
137
141
  end
138
142
  end
@@ -64,15 +64,14 @@ describe 'Projects' do
64
64
  'active' => false,
65
65
  'auto_estimates' => true,
66
66
  }
67
-
68
67
  project = @toggl.update_project(@project['id'], new_values)
69
68
  expect(project).to include(new_values)
70
69
  end
71
70
 
72
71
  it 'updates Pro project data', :pro_account do
73
72
  new_values = {
74
- 'template' => 'true',
75
- 'billable' => 'true',
73
+ 'template' => true,
74
+ 'billable' => true,
76
75
  }
77
76
  project = @toggl.update_project(@project['id'], new_values)
78
77
  expect(project).to include(new_values)
@@ -3,7 +3,7 @@ describe 'Tasks', :pro_account do
3
3
  @toggl = TogglV8::API.new(Testing::API_TOKEN)
4
4
  @workspaces = @toggl.workspaces
5
5
  @workspace_id = @workspaces.first['id']
6
- @project = @toggl.create_project({ name: 'project with a task', wid: @workspace_id })
6
+ @project = @toggl.create_project({ 'name' => 'project with a task', 'wid' => @workspace_id })
7
7
  end
8
8
 
9
9
  after :all do
@@ -12,13 +12,13 @@ describe 'Tasks', :pro_account do
12
12
 
13
13
  context 'new task' do
14
14
  before :all do
15
- @task = @toggl.create_task({ name: 'new task', pid: @project['id'] })
16
- task_ids = @toggl.get_project_tasks(@project['id']).map { |t| t['id'] }
17
- expect(task_ids).to eq [ @task['id'] ]
15
+ @task = @toggl.create_task({ 'name' => 'new task', 'pid' => @project['id'] })
16
+ @task_ids = @toggl.get_project_tasks(@project['id']).map { |t| t['id'] }
17
+ expect(@task_ids).to eq [ @task['id'] ]
18
18
  end
19
19
 
20
20
  after :all do
21
- TogglV8SpecHelper.delete_all_tasks(@toggl)
21
+ @toggl.delete_tasks(@task_ids)
22
22
  tasks = @toggl.get_project_tasks(@project['id'])
23
23
  expect(tasks).to be_empty
24
24
  end
@@ -33,13 +33,15 @@ describe 'Tasks', :pro_account do
33
33
 
34
34
  it 'gets a task' do
35
35
  task = @toggl.get_task(@task['id'])
36
- expect(task).to eq @task
36
+ expect(task).to include('at') # 'at' is last updated timestamp
37
+ task.delete('at') # 'at' is not included in POST response
38
+ expect(task).to eq @task # compare POST and GET responses
37
39
  end
38
40
  end
39
41
 
40
42
  context 'updated task' do
41
43
  before :each do
42
- @task = @toggl.create_task({ name: 'task to update', pid: @project['id'] })
44
+ @task = @toggl.create_task({ 'name' => 'task to update', 'pid' => @project['id'] })
43
45
  end
44
46
 
45
47
  after :each do
@@ -58,29 +60,30 @@ describe 'Tasks', :pro_account do
58
60
 
59
61
  context 'multiple tasks' do
60
62
  before :each do
61
- @task1 = @toggl.create_task({ name: 'task1', pid: @project['id'] })
62
- @task2 = @toggl.create_task({ name: 'task2', pid: @project['id'] })
63
- @task3 = @toggl.create_task({ name: 'task3', pid: @project['id'] })
63
+ timestamp = Time.now.strftime("%H%M%S.%9N")
64
+ @task1 = @toggl.create_task({ 'name' => "task1-#{timestamp}", 'pid' => @project['id'] })
65
+ @task2 = @toggl.create_task({ 'name' => "task2-#{timestamp}", 'pid' => @project['id'] })
66
+ @task3 = @toggl.create_task({ 'name' => "task3-#{timestamp}", 'pid' => @project['id'] })
67
+ @task_ids = [ @task1['id'], @task2['id'], @task3['id'] ]
64
68
  end
65
69
 
66
70
  after :all do
67
- TogglV8SpecHelper.delete_all_tasks(@toggl)
71
+ @toggl.delete_tasks(@task_ids)
68
72
  end
69
73
 
70
74
  it 'updates multiple tasks' do
71
75
  # start with 3 active tasks
72
76
  tasks = @toggl.get_project_tasks(@project['id'])
73
77
  active_flags = tasks.map { |t| t['active'] }
74
- expect().to match_array(['true', 'true', 'true'])
78
+ expect(active_flags).to match_array([true, true, true])
75
79
 
76
80
  t_ids = [@task1, @task2, @task3].map { |t| t['id'] }
77
- params = { 'active': true }
81
+ params = { 'active': false }
78
82
  @toggl.update_tasks(t_ids, params)
79
83
 
80
- # end with 3 inactive tasks
84
+ # end with no active tasks
81
85
  tasks = @toggl.get_project_tasks(@project['id'])
82
- active_flags = tasks.map { |t| t['active'] }
83
- expect().to match_array(['true', 'true', 'true'])
86
+ expect(tasks).to be_empty
84
87
  end
85
88
 
86
89
  it 'deletes multiple tasks' do
@@ -90,8 +93,8 @@ describe 'Tasks', :pro_account do
90
93
  t_ids = [@task1, @task2, @task3].map { |t| t['id'] }
91
94
  @toggl.delete_tasks(t_ids)
92
95
 
93
- # end with no tasks
94
- expect(@toggl.get_project_tasks(@project['id']).length).to be_empty
96
+ # end with no active tasks
97
+ expect(@toggl.get_project_tasks(@project['id'])).to be_empty
95
98
  end
96
99
  end
97
100
  end
@@ -101,9 +101,7 @@ describe 'Time Entries' do
101
101
  end
102
102
 
103
103
  after :all do
104
- @toggl.delete_time_entry(@last_week_id)
105
- @toggl.delete_time_entry(@now_id)
106
- @toggl.delete_time_entry(@next_week_id)
104
+ TogglV8SpecHelper.delete_all_time_entries(@toggl)
107
105
  end
108
106
 
109
107
  it 'gets time entries (reaching back 9 days up till now)' do
@@ -116,11 +114,6 @@ describe 'Time Entries' do
116
114
  expect(ids).to eq [ @now_id ]
117
115
  end
118
116
 
119
- it 'gets time entries between 9 days ago and end_date' do
120
- ids = @toggl.get_time_entries({end_date: @now + 1}).map { |t| t['id']}
121
- expect(ids).to eq [ @last_week_id, @now_id ]
122
- end
123
-
124
117
  it 'gets time entries between start_date and end_date' do
125
118
  ids = @toggl.get_time_entries({start_date: @now - 1, end_date: @now + 1}).map { |t| t['id']}
126
119
  expect(ids).to eq [ @now_id ]
@@ -181,6 +174,124 @@ describe 'Time Entries' do
181
174
  end
182
175
  end
183
176
 
177
+ context 'time entry tags' do
178
+ before :each do
179
+ time_entry_info = {
180
+ 'wid' => @workspace_id,
181
+ 'duration' => 7777
182
+ }
183
+ @now = DateTime.now
184
+
185
+ start = { 'start' => @toggl.iso8601(@now - 7) }
186
+ @time7 = @toggl.create_time_entry(time_entry_info.merge(start))
187
+
188
+ start = { 'start' => @toggl.iso8601(@now - 6) }
189
+ @time6 = @toggl.create_time_entry(time_entry_info.merge(start))
190
+
191
+ start = { 'start' => @toggl.iso8601(@now - 5) }
192
+ @time5 = @toggl.create_time_entry(time_entry_info.merge(start))
193
+
194
+ start = { 'start' => @toggl.iso8601(@now - 4) }
195
+ @time4 = @toggl.create_time_entry(time_entry_info.merge(start))
196
+
197
+ @time_entry_ids = [ @time7['id'], @time6['id'], @time5['id'], @time4['id']]
198
+ end
199
+
200
+ after :each do
201
+ TogglV8SpecHelper.delete_all_time_entries(@toggl)
202
+ TogglV8SpecHelper.delete_all_tags(@toggl)
203
+ end
204
+
205
+ it 'adds and removes one tag' do
206
+ # Add one tag
207
+ @toggl.update_time_entries_tags(@time_entry_ids,
208
+ {'tags' =>['money'], 'tag_action' => 'add'})
209
+
210
+ time_entries = @toggl.get_time_entries
211
+ tags = time_entries.map { |t| t['tags'] }
212
+ expect(tags).to eq [
213
+ ['money'],
214
+ ['money'],
215
+ ['money'],
216
+ ['money']
217
+ ]
218
+
219
+ # Remove one tag
220
+ @toggl.update_time_entries_tags(@time_entry_ids,
221
+ {'tags' =>['money'], 'tag_action' => 'remove'})
222
+
223
+ time_entries = @toggl.get_time_entries
224
+ tags = time_entries.map { |t| t['tags'] }.compact
225
+ expect(tags).to eq []
226
+ end
227
+
228
+ it '"removes" a non-existent tag' do
229
+ # Not tags to start
230
+ time_entries = @toggl.get_time_entries
231
+ tags = time_entries.map { |t| t['tags'] }.compact
232
+ expect(tags).to eq []
233
+
234
+ # "Remove" a tag
235
+ @toggl.update_time_entries_tags(@time_entry_ids,
236
+ {'tags' =>['void'], 'tag_action' => 'remove'})
237
+
238
+ # No tags to finish
239
+ time_entries = @toggl.get_time_entries
240
+ tags = time_entries.map { |t| t['tags'] }.compact
241
+ expect(tags).to eq []
242
+ end
243
+
244
+ it 'adds and removes multiple tags' do
245
+ # Add multiple tags
246
+ @toggl.update_time_entries_tags(@time_entry_ids,
247
+ {'tags' =>['billed', 'productive'], 'tag_action' => 'add'})
248
+
249
+ time_entries = @toggl.get_time_entries
250
+ tags = time_entries.map { |t| t['tags'] }
251
+ expect(tags).to eq [
252
+ ['billed', 'productive'],
253
+ ['billed', 'productive'],
254
+ ['billed', 'productive'],
255
+ ['billed', 'productive']
256
+ ]
257
+
258
+ # Remove multiple tags
259
+ @toggl.update_time_entries_tags(@time_entry_ids,
260
+ {'tags' =>['billed','productive'], 'tag_action' => 'remove'})
261
+
262
+ time_entries = @toggl.get_time_entries
263
+ tags = time_entries.map { |t| t['tags'] }.compact
264
+ expect(tags).to eq []
265
+ end
266
+
267
+ it 'manages multiple tags' do
268
+ # Add some tags
269
+ @toggl.update_time_entries_tags(@time_entry_ids,
270
+ {'tags' =>['billed', 'productive'], 'tag_action' => 'add'})
271
+
272
+ # Remove some tags
273
+ @toggl.update_time_entries_tags([ @time6['id'], @time4['id'] ],
274
+ {'tags' =>['billed'], 'tag_action' => 'remove'})
275
+
276
+ # Add some tags
277
+ @toggl.update_time_entries_tags([ @time7['id'] ],
278
+ {'tags' =>['best'], 'tag_action' => 'add'})
279
+
280
+ time7 = @toggl.get_time_entry(@time7['id'])
281
+ time6 = @toggl.get_time_entry(@time6['id'])
282
+ time5 = @toggl.get_time_entry(@time5['id'])
283
+ time4 = @toggl.get_time_entry(@time4['id'])
284
+
285
+ tags = [ time7['tags'], time6['tags'], time5['tags'], time4['tags'] ]
286
+ expect(tags).to eq [
287
+ ['best', 'billed', 'productive'],
288
+ [ 'productive'],
289
+ [ 'billed', 'productive'],
290
+ [ 'productive']
291
+ ]
292
+ end
293
+ end
294
+
184
295
  context 'iso8601' do
185
296
  before :all do
186
297
  @ts = DateTime.new(2008,6,21, 13,30,2, "+09:00")
@@ -210,13 +321,6 @@ describe 'Time Entries' do
210
321
  end
211
322
 
212
323
  context 'String' do
213
- xit 'converts Zulu to +00:00' do
214
- ts = '2015-08-21T09:21:02Z'
215
- expected = '2015-08-21T09:21:02+00:00'
216
-
217
- expect(@toggl.iso8601(ts)).to eq expected
218
- end
219
-
220
324
  it 'converts +00:00 to Zulu' do
221
325
  ts = '2015-08-21T09:21:02+00:00'
222
326
  expected = '2015-08-21T09:21:02Z'
@@ -2,39 +2,66 @@ describe 'Users' do
2
2
  before :all do
3
3
  @toggl = TogglV8::API.new(Testing::API_TOKEN)
4
4
  @user = @toggl.me(all=true)
5
+ @workspaces = @toggl.workspaces
6
+ @workspace_id = @workspaces.first['id']
5
7
  end
6
8
 
7
9
  it 'returns /me' do
8
10
  expect(@user).to_not be_nil
9
- expect(@user['id']).to eq 1820939
10
- expect(@user['fullname']).to eq 'togglv8'
11
- expect(@user['image_url']).to eq 'https://assets.toggl.com/avatars/a5d106126b6bed8df283e708af0828ee.png'
12
- expect(@user['timezone']).to eq 'Etc/UTC'
13
- expect(@user['workspaces'].length).to eq 1
14
- expect(@user['workspaces'].first['name']).to eq "togglv8's workspace"
11
+ expect(@user['id']).to eq Testing::USER_ID
12
+ # expect(@user['fullname']).to eq 'togglv8'
13
+ # expect(@user['image_url']).to eq 'https://assets.toggl.com/avatars/a5d106126b6bed8df283e708af0828ee.png'
14
+ # expect(@user['timezone']).to eq 'Etc/UTC'
15
+ # expect(@user['workspaces'].length).to eq 1
16
+ # expect(@user['workspaces'].first['name']).to eq "togglv8's workspace"
15
17
  end
16
18
 
17
- it 'returns /my_clients' do
19
+ it 'returns my_clients' do
18
20
  my_clients = @toggl.my_clients(@user)
19
21
  expect(my_clients).to be_empty
20
22
  end
21
23
 
22
- it 'returns /my_projects' do
24
+ it 'returns my_projects' do
23
25
  my_projects = @toggl.my_projects(@user)
24
26
  expect(my_projects).to be_empty
25
27
  end
26
28
 
27
- it 'returns /my_tags' do
29
+ it 'returns my_projects and my_deleted_projects' do
30
+ # Create project
31
+ project = @toggl.create_project({ 'name' => 'my project', 'wid' => @workspace_id })
32
+
33
+ my_project_ids = @toggl.my_projects.map { |p| p['id'] }
34
+ my_deleted_project_ids = @toggl.my_deleted_projects.map { |p| p['id'] }
35
+
36
+ expect(my_project_ids).to eq [ project['id'] ]
37
+ expect(my_deleted_project_ids).not_to include(project['id'])
38
+
39
+ # Delete project
40
+ @toggl.delete_project(project['id'])
41
+
42
+ my_project_ids = @toggl.my_projects.map { |p| p['id'] }
43
+ my_deleted_project_ids = @toggl.my_deleted_projects.map { |p| p['id'] }
44
+
45
+ expect(my_project_ids).to eq []
46
+ expect(my_deleted_project_ids).to include(project['id'])
47
+ end
48
+
49
+ it 'returns my_tags' do
28
50
  my_tags = @toggl.my_tags(@user)
29
51
  expect(my_tags).to be_empty
30
52
  end
31
53
 
32
- it 'returns /my_time_entries' do
54
+ it 'returns my_tasks' do
55
+ my_tasks = @toggl.my_tasks(@user)
56
+ expect(my_tasks).to be_empty
57
+ end
58
+
59
+ it 'returns my_time_entries' do
33
60
  my_time_entries = @toggl.my_time_entries(@user)
34
61
  expect(my_time_entries).to be_empty
35
62
  end
36
63
 
37
- it 'returns /my_workspaces' do
64
+ it 'returns my_workspaces' do
38
65
  my_workspaces = @toggl.my_workspaces(@user)
39
66
  expect(my_workspaces.length).to eq 1
40
67
  end
data/spec/spec_helper.rb CHANGED
@@ -1,45 +1,17 @@
1
- # require "codeclimate-test-reporter"
2
- # CodeClimate::TestReporter.start
1
+ require "simplecov"
2
+ require "coveralls"
3
3
 
4
- require 'coveralls'
5
- Coveralls.wear!
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
6
9
 
7
- # require 'simplecov'
8
- # SimpleCov.start do
9
- # require 'simplecov-badge'
10
- # add_group 'lib', 'lib/'
11
- # add_filter '/doc/'
12
- # add_filter '/spec/'
13
- # add_filter '/pkg/'
14
- # # configure any options you want for SimpleCov::Formatter::BadgeFormatter
15
- # SimpleCov::Formatter::BadgeFormatter.generate_groups = true
16
- # SimpleCov::Formatter::BadgeFormatter.timestamp = true
17
- # SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
18
- # SimpleCov::Formatter::HTMLFormatter,
19
- # SimpleCov::Formatter::BadgeFormatter,
20
- # ]
21
- # end
22
- # NOTE: SimpleCov.start must be issued before any application code is required!
23
- # -----------------------------------------------------------------------------
10
+ require 'pry-byebug'
24
11
 
25
12
  require_relative 'togglv8_spec_helper'
26
13
  require_relative '../lib/togglv8'
27
14
 
28
- # This file was generated by the `rspec --init` command. Conventionally, all
29
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
30
- # The generated `.rspec` file contains `--require spec_helper` which will cause this
31
- # file to always be loaded, without a need to explicitly require it in any files.
32
- #
33
- # Given that it is always loaded, you are encouraged to keep this file as
34
- # light-weight as possible. Requiring heavyweight dependencies from this file
35
- # will add to the boot time of your test suite on EVERY test run, even for an
36
- # individual file that may not need all of that loaded. Instead, consider making
37
- # a separate helper file that requires the additional dependencies and performs
38
- # the additional setup, and require it from the spec files that actually need it.
39
- #
40
- # The `.rspec` file also contains a few flags that are not defaults but that
41
- # users commonly want.
42
- #
43
15
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
44
16
  RSpec.configure do |config|
45
17
  config.filter_run :focus
@@ -49,27 +21,12 @@ RSpec.configure do |config|
49
21
  config.order = :random
50
22
  Kernel.srand config.seed
51
23
 
52
- # rspec-expectations config goes here. You can use an alternate
53
- # assertion/expectation library such as wrong or the stdlib/minitest
54
- # assertions if you prefer.
55
24
  config.expect_with :rspec do |expectations|
56
- # This option will default to `true` in RSpec 4. It makes the `description`
57
- # and `failure_message` of custom matchers include text for helper methods
58
- # defined using `chain`, e.g.:
59
- # be_bigger_than(2).and_smaller_than(4).description
60
- # # => "be bigger than 2 and smaller than 4"
61
- # ...rather than:
62
- # # => "be bigger than 2"
63
25
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
64
26
  expectations.syntax = :expect
65
27
  end
66
28
 
67
- # rspec-mocks config goes here. You can use an alternate test double
68
- # library (such as bogus or mocha) by changing the `mock_with` option here.
69
29
  config.mock_with :rspec do |mocks|
70
- # Prevents you from mocking or stubbing a method that does not exist on
71
- # a real object. This is generally recommended, and will default to
72
- # `true` in RSpec 4.
73
30
  mocks.verify_partial_doubles = true
74
31
  end
75
32
 
@@ -77,59 +34,11 @@ RSpec.configure do |config|
77
34
  toggl = TogglV8::API.new(Testing::API_TOKEN)
78
35
  TogglV8SpecHelper.setUp(toggl)
79
36
  end
80
-
81
- # The settings below are suggested to provide a good initial experience
82
- # with RSpec, but feel free to customize to your heart's content.
83
- =begin
84
- # These two settings work together to allow you to limit a spec run
85
- # to individual examples or groups you care about by tagging them with
86
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
87
- # get run.
88
- config.filter_run :focus
89
- config.run_all_when_everything_filtered = true
90
-
91
- # Limits the available syntax to the non-monkey patched syntax that is recommended.
92
- # For more details, see:
93
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
94
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
95
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
96
- config.disable_monkey_patching!
97
-
98
- # This setting enables warnings. It's recommended, but in some cases may
99
- # be too noisy due to issues in dependencies.
100
- config.warnings = true
101
-
102
- # Many RSpec users commonly either run the entire suite or an individual
103
- # file, and it's useful to allow more verbose output when running an
104
- # individual spec file.
105
- if config.files_to_run.one?
106
- # Use the documentation formatter for detailed output,
107
- # unless a formatter has already been configured
108
- # (e.g. via a command-line flag).
109
- config.default_formatter = 'doc'
110
- end
111
-
112
- # Print the 10 slowest examples and example groups at the
113
- # end of the spec run, to help surface which specs are running
114
- # particularly slow.
115
- config.profile_examples = 10
116
-
117
- # Run specs in random order to surface order dependencies. If you find an
118
- # order dependency and want to debug it, you can fix the order by providing
119
- # the seed, which is printed after each run.
120
- # --seed 1234
121
- config.order = :random
122
-
123
- # Seed global randomization in this process using the `--seed` CLI option.
124
- # Setting this allows you to use `--seed` to deterministically reproduce
125
- # test failures related to randomization by passing the same `--seed` value
126
- # as the one that triggered the failure.
127
- Kernel.srand config.seed
128
- =end
129
37
  end
130
38
 
131
39
  class Testing
132
- API_TOKEN = '4880adbe1bee9a241fa08070d33bd49f'
133
- USERNAME = 'togglv8@mailinator.com'
134
- PASSWORD = 'togglv8'
40
+ API_TOKEN = ENV['API_TOKEN'] || '4880adbe1bee9a241fa08070d33bd49f'
41
+ USERNAME = ENV['USERNAME'] || 'togglv8@mailinator.com'
42
+ PASSWORD = ENV['PASSWORD'] || 'togglv8'
43
+ USER_ID = (ENV['USER_ID'] || 1820939).to_i
135
44
  end
@@ -6,69 +6,69 @@ class TogglV8SpecHelper
6
6
  @logger.level = Logger::WARN
7
7
 
8
8
  def self.setUp(toggl)
9
- @toggl = toggl
10
- user = @toggl.me(all=true)
9
+ user = toggl.me(all=true)
11
10
  @default_workspace_id = user['default_wid']
12
11
 
13
- delete_all_projects(@toggl)
14
- delete_all_clients(@toggl)
15
- delete_all_tags(@toggl)
16
- delete_all_time_entries(@toggl)
17
- delete_all_workspaces(@toggl)
12
+ delete_all_projects(toggl)
13
+ delete_all_clients(toggl)
14
+ delete_all_tags(toggl)
15
+ delete_all_time_entries(toggl)
16
+ delete_all_workspaces(toggl)
18
17
  end
19
18
 
20
19
  def self.delete_all_clients(toggl)
21
- clients = @toggl.my_clients
20
+ clients = toggl.my_clients
22
21
  unless clients.nil?
23
22
  client_ids ||= clients.map { |c| c['id'] }
24
23
  @logger.debug("Deleting #{client_ids.length} clients")
25
24
  client_ids.each do |c_id|
26
- @toggl.delete_client(c_id)
25
+ toggl.delete_client(c_id)
27
26
  end
28
27
  end
29
28
  end
30
29
 
31
30
  def self.delete_all_projects(toggl)
32
- projects = @toggl.projects(@default_workspace_id)
31
+ projects = toggl.projects(@default_workspace_id)
33
32
  unless projects.nil?
34
33
  project_ids ||= projects.map { |p| p['id'] }
35
34
  @logger.debug("Deleting #{project_ids.length} projects")
36
35
  return unless project_ids.length > 0
37
- @toggl.delete_projects(project_ids)
36
+ toggl.delete_projects(project_ids)
38
37
  end
39
38
  end
40
39
 
41
40
  def self.delete_all_tags(toggl)
42
- tags = @toggl.my_tags
41
+ tags = toggl.my_tags
43
42
  unless tags.nil?
44
43
  tag_ids ||= tags.map { |t| t['id'] }
45
44
  @logger.debug("Deleting #{tag_ids.length} tags")
46
45
  tag_ids.each do |t_id|
47
- @toggl.delete_tag(t_id)
46
+ toggl.delete_tag(t_id)
48
47
  end
49
48
  end
50
49
  end
51
50
 
52
51
  def self.delete_all_time_entries(toggl)
53
- time_entries = @toggl.my_time_entries
52
+ time_entries = toggl.get_time_entries(
53
+ { start_date: DateTime.now - 30, end_date: DateTime.now + 30 } )
54
54
  unless time_entries.nil?
55
55
  time_entry_ids ||= time_entries.map { |t| t['id'] }
56
56
  @logger.debug("Deleting #{time_entry_ids.length} time_entries")
57
57
  time_entry_ids.each do |t_id|
58
- @toggl.delete_time_entry(t_id)
58
+ toggl.delete_time_entry(t_id)
59
59
  end
60
60
  end
61
61
  end
62
62
 
63
63
  def self.delete_all_workspaces(toggl)
64
- user = @toggl.me(all=true)
65
- workspaces = @toggl.my_workspaces(user)
64
+ user = toggl.me(all=true)
65
+ workspaces = toggl.my_workspaces(user)
66
66
  unless workspaces.nil?
67
67
  workspace_ids ||= workspaces.map { |w| w['id'] }
68
68
  workspace_ids.delete(user['default_wid'])
69
69
  @logger.debug("Leaving #{workspace_ids.length} workspaces")
70
70
  workspace_ids.each do |w_id|
71
- @toggl.leave_workspace(w_id)
71
+ toggl.leave_workspace(w_id)
72
72
  end
73
73
  end
74
74
  end
data/togglv8.gemspec CHANGED
@@ -25,10 +25,8 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rspec-mocks"
26
26
  spec.add_development_dependency "awesome_print"
27
27
  spec.add_development_dependency "fivemat"
28
- spec.add_development_dependency "simplecov"
29
- # spec.add_development_dependency "simplecov-badge"
30
- # spec.add_development_dependency "codeclimate-test-reporter"
31
28
  spec.add_development_dependency "coveralls"
29
+ spec.add_development_dependency "pry-byebug"
32
30
 
33
31
  spec.add_dependency "logger"
34
32
  spec.add_dependency "faraday"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: togglv8
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-06 00:00:00.000000000 Z
11
+ date: 2015-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: simplecov
98
+ name: coveralls
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: coveralls
112
+ name: pry-byebug
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="