togglv8 1.0.0 → 1.0.2

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.
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
  - - ">="