togglv8 1.2.0 → 1.2.1

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: 4c535170f2f4008596f53dd97645d5946d62740e
4
- data.tar.gz: f007be73994ef07272e1100e4f2046dc22d69e3a
3
+ metadata.gz: bcd7cc8508f9dd6457f7899cc9be1644e1453384
4
+ data.tar.gz: 9d7640b307c1d5fe4135c22dc368815ec60e595d
5
5
  SHA512:
6
- metadata.gz: 082469da76c56138a7bee169c205874a150384959b516b65633e4672288b0962fbfbccb1909ec2ad6a176bf076516d898b6a9fe3bc3bad52ac8048c2240a8d9a
7
- data.tar.gz: 64463ae5e379fee5e870be1c84e4a76d0b30138634f002371cd0fd08898cf6aa9bc0530287a540ffe1a4380dcc0c51214810c9acf614aa0802d1aa43f976cbbb
6
+ metadata.gz: d8b71a5a7d53c4ffac2a5a9d6621d313bafe4cafbcc45ec0142654b1d2f0c5e48004eaf9513e5278e357d21bef11fac86c6f75531d01061c3109b6cc1bb06314
7
+ data.tar.gz: 055a400ba85f3b4473f7a47f9a09daa0131f672a433bd109b8c28dc223dd51b1b5e253aee561a8d83b019268111cdb848297bcca15c4f6dbe03642f27bc77883
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  # Toggl API v8
3
3
 
4
- [![Build Status](https://api.travis-ci.org/kanet77/togglv8.svg "Build Status")](https://travis-ci.org/kanet77/togglv8) [![Coverage Status](https://coveralls.io/repos/kanet77/togglv8/badge.svg?branch=master&service=github)](https://coveralls.io/github/kanet77/togglv8?branch=master)
4
+ [![Gem Version](https://badge.fury.io/rb/togglv8.svg)](https://badge.fury.io/rb/togglv8) [![Build Status](https://api.travis-ci.org/kanet77/togglv8.svg "Build Status")](https://travis-ci.org/kanet77/togglv8) [![Coverage Status](https://coveralls.io/repos/kanet77/togglv8/badge.svg?branch=master&service=github)](https://coveralls.io/github/kanet77/togglv8?branch=master)
5
5
 
6
6
  [Toggl](http://www.toggl.com) is a time tracking tool.
7
7
 
@@ -38,7 +38,7 @@ TogglV8::API communicates with [Toggl API v8](https://github.com/toggl/toggl_api
38
38
  ```ruby
39
39
  TogglV8::API.new # reads API token from file ~/.toggl
40
40
  TogglV8::API.new(api_token) # explicit API token
41
- TogglV8::API.new(username, password) # username & password
41
+ TogglV8::API.new(email, password) # email & password
42
42
  ```
43
43
 
44
44
  ### TogglV8::ReportsV2
data/Rakefile CHANGED
@@ -1,8 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require 'fileutils'
2
+ require 'rake/clean'
3
3
 
4
- task :clean do
5
- FileUtils.remove_dir('coverage', force=true)
6
- FileUtils.remove_dir('doc', force=true)
7
- FileUtils.remove_dir('pkg', force=true)
8
- end
4
+ CLEAN.add 'coverage'
5
+ CLEAN.add 'doc'
6
+ CLEAN.include 'tmp-*'
@@ -1,3 +1,4 @@
1
+ # :nocov:
1
2
  require 'logger'
2
3
  require 'awesome_print' # for debug output
3
4
 
@@ -33,4 +34,5 @@ module Logging
33
34
  logger.level = Logger::WARN
34
35
  end
35
36
  end
36
- end
37
+ end
38
+ # :nocov:
@@ -13,18 +13,20 @@ module TogglV8
13
13
  def initialize(opts={})
14
14
  debug(false)
15
15
 
16
- @user_agent = 'togglv8'
16
+ @user_agent = TogglV8::NAME
17
17
 
18
18
  username = opts[:api_token]
19
19
  if username.nil?
20
20
  toggl_api_file = opts[:toggl_api_file] || File.join(Dir.home, TOGGL_FILE)
21
- if FileTest.exist?(toggl_api_file) then
21
+ if File.exist?(toggl_api_file) then
22
22
  username = IO.read(toggl_api_file)
23
23
  else
24
- raise "Expecting\n" +
24
+ raise "Expecting one of:\n" +
25
25
  " 1) api_token in file #{toggl_api_file}, or\n" +
26
- " 2) parameter: (api_token), or\n" +
27
- "\n\tSee https://github.com/toggl/toggl_api_docs/blob/master/reports.md#authentication"
26
+ " 2) parameter: (toggl_api_file), or\n" +
27
+ " 3) parameter: (api_token), or\n" +
28
+ "\n\tSee https://github.com/kanet77/togglv8#togglv8reportsv2" +
29
+ "\n\tand https://github.com/toggl/toggl_api_docs/blob/master/reports.md#authentication"
28
30
  end
29
31
  end
30
32
 
@@ -33,7 +35,7 @@ module TogglV8
33
35
 
34
36
  ##
35
37
  # ---------
36
- # :section: Reports
38
+ # :section: Report
37
39
  #
38
40
  # The following parameters and filters can be used in all of the reports
39
41
  #
@@ -70,26 +72,30 @@ module TogglV8
70
72
  # NB! Maximum date span (until - since) is one year.
71
73
 
72
74
  # extension can be one of ['.pdf', '.csv', '.xls']. Possibly others?
73
- def report(type, extension, opts)
75
+ def report(type, extension, params)
74
76
  raise "workspace_id is required" if @workspace_id.nil?
75
77
  get "#{type}#{extension}", {
76
78
  'user_agent': @user_agent,
77
79
  'workspace_id': @workspace_id,
78
- }.merge(opts)
80
+ }.merge(params)
79
81
  end
80
82
 
81
- def weekly(extension='', opts={})
82
- report('weekly', extension, opts)
83
+ def weekly(extension='', params={})
84
+ report('weekly', extension, params)
83
85
  end
84
86
 
85
- def details(extension='', opts={})
86
- report('details', extension, opts)
87
+ def details(extension='', params={})
88
+ report('details', extension, params)
87
89
  end
88
90
 
89
- def summary(extension='', opts={})
90
- report('summary', extension, opts)
91
+ def summary(extension='', params={})
92
+ report('summary', extension, params)
91
93
  end
92
94
 
95
+ ##
96
+ # ---------
97
+ # :section: Write report to file
98
+ #
93
99
  def write_report(filename)
94
100
  extension = File.extname(filename)
95
101
  report = yield(extension)
@@ -98,24 +104,29 @@ module TogglV8
98
104
  end
99
105
  end
100
106
 
101
- def write_weekly(filename, opts={})
107
+ def write_weekly(filename, params={})
102
108
  write_report(filename) do |extension|
103
- weekly(extension, opts)
109
+ weekly(extension, params)
104
110
  end
105
111
  end
106
112
 
107
- def write_details(filename, opts={})
113
+ def write_details(filename, params={})
108
114
  write_report(filename) do |extension|
109
- details(extension, opts)
115
+ details(extension, params)
110
116
  end
111
117
  end
112
118
 
113
- def write_summary(filename, opts={})
119
+ def write_summary(filename, params={})
114
120
  write_report(filename) do |extension|
115
- summary(extension, opts)
121
+ summary(extension, params)
116
122
  end
117
123
  end
118
124
 
125
+
126
+ ##
127
+ # ---------
128
+ # :section: Miscellaneous information
129
+ #
119
130
  def revision
120
131
  get "revision"
121
132
  end
@@ -124,25 +135,43 @@ module TogglV8
124
135
  get "index"
125
136
  end
126
137
 
127
- def project(opts={})
138
+ def env
139
+ get "env"
140
+ end
141
+
142
+ ##
143
+ # ---------
144
+ # :section: Project Dashboard
145
+ #
146
+ # Project dashboard returns at-a-glance information for a single project.
147
+ # This feature is only available with Toggl pro.
148
+ #
149
+ # user_agent : email, or other way to contact client application developer
150
+ # (string, *required*)
151
+ # workspace_id : The workspace whose data you want to access
152
+ # (integer, *required*)
153
+ # project_id : The project whose data you want to access
154
+ # (integer, *required*)
155
+ # page : number of 'tasks_page' you want to fetch
156
+ # (integer, optional)
157
+ # order_field string : name/assignee/duration/billable_amount/estimated_seconds
158
+ # order_desc string : on/off, on for descending and off for ascending order
159
+ def project(project_id, params={})
128
160
  raise "workspace_id is required" if @workspace_id.nil?
129
161
  get "project", {
130
162
  'user_agent': @user_agent,
131
163
  'workspace_id': @workspace_id,
132
- }.merge(opts)
133
- end
134
-
135
- def env
136
- get "env"
164
+ 'project_id': project_id,
165
+ }.merge(params)
137
166
  end
138
167
 
168
+ ##
169
+ # ---------
170
+ # :section: Error (for testing)
171
+ #
172
+ # excludes endpoints 'error500' and 'division_by_zero_error'
139
173
  def error400
140
174
  get "error400"
141
175
  end
142
-
143
- def error500
144
- get "error500"
145
- end
146
-
147
176
  end
148
177
  end
@@ -7,3 +7,7 @@ require_relative 'reportsv2'
7
7
 
8
8
  # :mode => :compat will convert symbols to strings
9
9
  Oj.default_options = { :mode => :compat }
10
+
11
+ module TogglV8
12
+ NAME = "TogglV8 v#{TogglV8::VERSION}"
13
+ end
@@ -13,26 +13,7 @@ module TogglV8
13
13
  API_TOKEN = 'api_token'
14
14
  TOGGL_FILE = '.toggl'
15
15
 
16
- def self.qualify(username, password)
17
- if username.nil? && password == API_TOKEN
18
- toggl_api_file = File.join(Dir.home, TOGGL_FILE)
19
-
20
- # logger.debug("toggl_api_file = #{toggl_api_file}")
21
- if FileTest.exist?(toggl_api_file) then
22
- username = IO.read(toggl_api_file)
23
- else
24
- raise "Expecting\n" +
25
- " 1) api_token in file #{toggl_api_file}, or\n" +
26
- " 2) parameter: (api_token), or\n" +
27
- " 3) parameters: (username, password).\n" +
28
- "\n\tSee https://github.com/toggl/toggl_api_docs/blob/master/chapters/authentication.md"
29
- end
30
- end
31
- return username, password
32
- end
33
-
34
16
  def self.open(username=nil, password=API_TOKEN, url=nil, opts={})
35
- username, password = qualify(username, password)
36
17
  raise 'Missing URL' if url.nil?
37
18
 
38
19
  Faraday.new(:url => url, :ssl => {:verify => true}) do |faraday|
@@ -25,7 +25,7 @@ module TogglV8
25
25
  # at : timestamp that is sent in the response, indicates the time item was last updated
26
26
 
27
27
  def create_time_entry(params)
28
- params['created_with'] = 'TogglV8' unless params.has_key?('created_with')
28
+ params['created_with'] = TogglV8::NAME unless params.has_key?('created_with')
29
29
  requireParams(params, ['start', 'duration', 'created_with'])
30
30
  if !params.has_key?('wid') and !params.has_key?('pid') and !params.has_key?('tid') then
31
31
  raise ArgumentError, "one of params['wid'], params['pid'], params['tid'] is required"
@@ -34,7 +34,7 @@ module TogglV8
34
34
  end
35
35
 
36
36
  def start_time_entry(params)
37
- params['created_with'] = 'TogglV8' unless params.has_key?('created_with')
37
+ params['created_with'] = TogglV8::NAME unless params.has_key?('created_with')
38
38
  if !params.has_key?('wid') and !params.has_key?('pid') and !params.has_key?('tid') then
39
39
  raise ArgumentError, "one of params['wid'], params['pid'], params['tid'] is required"
40
40
  end
@@ -21,6 +21,21 @@ module TogglV8
21
21
 
22
22
  def initialize(username=nil, password=API_TOKEN, opts={})
23
23
  debug(false)
24
+ if username.nil? && password == API_TOKEN
25
+ toggl_api_file = File.join(Dir.home, TOGGL_FILE)
26
+ # logger.debug("toggl_api_file = #{toggl_api_file}")
27
+ if File.exist?(toggl_api_file) then
28
+ username = IO.read(toggl_api_file)
29
+ else
30
+ raise "Expecting one of:\n" +
31
+ " 1) api_token in file #{toggl_api_file}, or\n" +
32
+ " 2) parameter: (api_token), or\n" +
33
+ " 3) parameters: (username, password).\n" +
34
+ "\n\tSee https://github.com/kanet77/togglv8#togglv8api" +
35
+ "\n\tand https://github.com/toggl/toggl_api_docs/blob/master/chapters/authentication.md"
36
+ end
37
+ end
38
+
24
39
  @conn = TogglV8::Connection.open(username, password,
25
40
  TOGGL_API_V8_URL, opts)
26
41
  end
@@ -66,7 +66,7 @@ module TogglV8
66
66
  end
67
67
 
68
68
  def create_user(params)
69
- params['created_with'] = 'TogglV8' unless params.has_key?('created_with')
69
+ params['created_with'] = TogglV8::NAME unless params.has_key?('created_with')
70
70
  requireParams(params, ['email', 'password', 'timezone', 'created_with'])
71
71
  post "signups", { 'user' => params }
72
72
  end
@@ -1,4 +1,4 @@
1
1
  module TogglV8
2
2
  # :section:
3
- VERSION = "1.2.0"
3
+ VERSION = "1.2.1"
4
4
  end
@@ -15,20 +15,18 @@ describe 'ReportsV2' do
15
15
 
16
16
  context '.toggl file' do
17
17
  before :each do
18
- @home = File.join(Dir.pwd, "tmp")
19
- Dir.mkdir(@home)
20
-
18
+ @tmp_home = mktemp_dir
21
19
  @original_home = Dir.home
22
- ENV['HOME'] = @home
20
+ ENV['HOME'] = @tmp_home
23
21
  end
24
22
 
25
23
  after :each do
26
- FileUtils.rm_rf(@home)
24
+ FileUtils.rm_rf(@tmp_home)
27
25
  ENV['HOME'] = @original_home
28
26
  end
29
27
 
30
28
  it 'initializes with .toggl file' do
31
- toggl_file = File.join(@home, '.toggl')
29
+ toggl_file = File.join(@tmp_home, '.toggl')
32
30
  File.open(toggl_file, 'w') { |file| file.write(Testing::API_TOKEN) }
33
31
 
34
32
  reports = TogglV8::ReportsV2.new
@@ -38,10 +36,10 @@ describe 'ReportsV2' do
38
36
  end
39
37
 
40
38
  it 'initializes with custom toggl file' do
41
- toggl_file = File.join(@home, 'my_toggl')
39
+ toggl_file = File.join(@tmp_home, 'my_toggl')
42
40
  File.open(toggl_file, 'w') { |file| file.write(Testing::API_TOKEN) }
43
41
 
44
- reports = TogglV8::ReportsV2.new({toggl_api_file: toggl_file})
42
+ reports = TogglV8::ReportsV2.new(toggl_api_file: toggl_file)
45
43
  env = reports.env
46
44
  expect(env).to_not be nil
47
45
  expect(env['user']['api_token']).to eq Testing::API_TOKEN
@@ -58,7 +56,7 @@ describe 'ReportsV2' do
58
56
  @reports.workspace_id = @workspace_id
59
57
  end
60
58
 
61
- it 'surfaces a Warning HTTP header in case of error' do
59
+ it 'surfaces a Warning HTTP header in case of 400 error' do
62
60
  # https://github.com/toggl/toggl_api_docs/blob/master/reports.md#failed-requests
63
61
  expect { @reports.error400 }.to raise_error(RuntimeError,
64
62
  "This URL is intended only for testing")
@@ -78,81 +76,76 @@ describe 'ReportsV2' do
78
76
  end
79
77
  end
80
78
 
81
- context 'revision' do
82
- it 'has not changed' do
79
+ context 'miscellaneous' do
80
+ it 'env returns environment' do
83
81
  reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
84
82
  reports.workspace_id = @workspace_id
85
- expect(reports.revision).to eq("0.0.38\n-8a007ca")
83
+ env = reports.env
84
+ expect(env['workspace']).to_not be nil
85
+ expect(env['user']).to_not be nil
86
+ expect(env['user']['id']).to eq Testing::USER_ID
87
+ end
88
+
89
+ it 'index returns endpoints' do
90
+ reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
91
+ reports.workspace_id = @workspace_id
92
+ index = reports.index
93
+ expect(index['Welcome to reports api V2. VALID requests are:']).to_not be nil
94
+ end
95
+
96
+ it 'revision has not changed' do
97
+ reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
98
+ reports.workspace_id = @workspace_id
99
+ expect(reports.revision).to eq "0.0.38\n-8a007ca"
86
100
  end
87
101
  end
88
102
 
89
- context 'blank reports' do
103
+ context 'project', :pro_account do
90
104
  before :all do
91
105
  @toggl = TogglV8::API.new(Testing::API_TOKEN)
92
- @workspaces = @toggl.workspaces
93
- @workspace_id = @workspaces.first['id']
94
- @reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
95
- @reports.workspace_id = @workspace_id
106
+ @project_name = "Project #{Time.now.iso8601}"
107
+ @project = @toggl.create_project({
108
+ 'name' => @project_name,
109
+ 'wid' => @workspace_id
110
+ })
96
111
  end
97
112
 
98
- it 'summary' do
99
- expect(@reports.summary).to eq []
113
+ after :all do
114
+ @toggl.delete_project(@project['id'])
100
115
  end
101
116
 
102
- it 'weekly' do
103
- expect(@reports.weekly).to eq []
104
- end
117
+ it 'dashboard' do
118
+ reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
119
+ reports.workspace_id = @toggl.workspaces.first['id']
120
+ project_dashboard = reports.project(@project['id'])
105
121
 
106
- it 'details' do
107
- expect(@reports.details).to eq []
122
+ expect(project_dashboard['name']).to eq @project_name
108
123
  end
109
124
  end
110
125
 
111
- context 'reports' do
126
+ context 'blank reports' do
112
127
  before :all do
113
128
  @toggl = TogglV8::API.new(Testing::API_TOKEN)
114
129
  @workspaces = @toggl.workspaces
115
130
  @workspace_id = @workspaces.first['id']
116
- time_entry_info = {
117
- 'wid' => @workspace_id,
118
- 'start' => @toggl.iso8601(DateTime.now),
119
- 'duration' => 77
120
- }
121
-
122
- @time_entry = @toggl.create_time_entry(time_entry_info)
123
-
124
131
  @reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
125
132
  @reports.workspace_id = @workspace_id
126
133
  end
127
134
 
128
- after :all do
129
- @toggl.delete_time_entry(@time_entry['id'])
130
- end
131
-
132
135
  it 'summary' do
133
- summary = @reports.summary
134
- expect(summary.length).to eq 1
135
- expect(summary.first['time']).to eq 77000
136
- expect(summary.first['items'].length).to eq 1
137
- expect(summary.first['items'].first['time']).to eq 77000
136
+ expect(@reports.summary).to eq []
138
137
  end
139
138
 
140
139
  it 'weekly' do
141
- weekly = @reports.weekly
142
- expect(weekly.length).to eq 1
143
- expect(weekly.first['details'].first['title']['user']).to eq 'togglv8'
144
- expect(weekly.first['totals'][7]).to eq 77000
140
+ expect(@reports.weekly).to eq []
145
141
  end
146
142
 
147
143
  it 'details' do
148
- details = @reports.details
149
- expect(details.length).to eq 1
150
- expect(details.first['user']).to eq 'togglv8'
151
- expect(details.first['dur']).to eq 77000
144
+ expect(@reports.details).to eq []
152
145
  end
153
146
  end
154
147
 
155
- context 'CSV reports' do
148
+ context 'reports' do
156
149
  before :all do
157
150
  @toggl = TogglV8::API.new(Testing::API_TOKEN)
158
151
  @workspaces = @toggl.workspaces
@@ -167,32 +160,95 @@ describe 'ReportsV2' do
167
160
 
168
161
  @reports = TogglV8::ReportsV2.new(api_token: Testing::API_TOKEN)
169
162
  @reports.workspace_id = @workspace_id
163
+
164
+ @tmp_home = mktemp_dir
165
+ @original_home = Dir.home
166
+ ENV['HOME'] = @tmp_home
170
167
  end
171
168
 
172
169
  after :all do
173
170
  @toggl.delete_time_entry(@time_entry['id'])
174
- end
175
171
 
176
- it 'summary' do
177
- summary = @reports.summary
178
- expect(summary.length).to eq 1
179
- expect(summary.first['time']).to eq 77000
180
- expect(summary.first['items'].length).to eq 1
181
- expect(summary.first['items'].first['time']).to eq 77000
182
- end
183
-
184
- it 'weekly' do
185
- weekly = @reports.weekly
186
- expect(weekly.length).to eq 1
187
- expect(weekly.first['details'].first['title']['user']).to eq 'togglv8'
188
- expect(weekly.first['totals'][7]).to eq 77000
172
+ FileUtils.rm_rf(@tmp_home)
173
+ ENV['HOME'] = @original_home
189
174
  end
190
175
 
191
- it 'details' do
192
- details = @reports.details
193
- expect(details.length).to eq 1
194
- expect(details.first['user']).to eq 'togglv8'
195
- expect(details.first['dur']).to eq 77000
176
+ context 'JSON reports' do
177
+ it 'summary' do
178
+ summary = @reports.summary
179
+ expect(summary.length).to eq 1
180
+ expect(summary.first['time']).to eq 77000
181
+ expect(summary.first['items'].length).to eq 1
182
+ expect(summary.first['items'].first['time']).to eq 77000
183
+ end
184
+
185
+ it 'weekly' do
186
+ weekly = @reports.weekly
187
+ expect(weekly.length).to eq 1
188
+ expect(weekly.first['details'].first['title']['user']).to eq Testing::USERNAME
189
+ expect(weekly.first['totals'][7]).to eq 77000
190
+ end
191
+
192
+ it 'details' do
193
+ details = @reports.details
194
+ expect(details.length).to eq 1
195
+ expect(details.first['user']).to eq Testing::USERNAME
196
+ expect(details.first['dur']).to eq 77000
197
+ end
198
+ end
199
+
200
+ context 'CSV reports' do
201
+ it 'summary' do
202
+ filename = File.join(@tmp_home, 'summary.csv')
203
+ summary = @reports.write_summary(filename)
204
+ expect(file_contains(filename, /00:01:17/))
205
+ end
206
+
207
+ it 'weekly' do
208
+ filename = File.join(@tmp_home, 'weekly.csv')
209
+ weekly = @reports.write_weekly(filename)
210
+ expect(file_contains(filename, /00:01:17/))
211
+ end
212
+
213
+ it 'details' do
214
+ filename = File.join(@tmp_home, 'details.csv')
215
+ details = @reports.write_details(filename)
216
+ expect(file_contains(filename, /00:01:17/))
217
+ end
218
+ end
219
+
220
+ context 'PDF reports' do
221
+ it 'summary' do
222
+ filename = File.join(@tmp_home, 'summary.pdf')
223
+ summary = @reports.write_summary(filename)
224
+ expect(file_is_pdf(filename))
225
+ end
226
+
227
+ it 'weekly' do
228
+ filename = File.join(@tmp_home, 'weekly.pdf')
229
+ weekly = @reports.write_weekly(filename)
230
+ expect(file_is_pdf(filename))
231
+ end
232
+
233
+ it 'details' do
234
+ filename = File.join(@tmp_home, 'details.pdf')
235
+ details = @reports.write_details(filename)
236
+ expect(file_is_pdf(filename))
237
+ end
238
+ end
239
+
240
+ context 'XLS reports' do
241
+ it 'summary' do
242
+ filename = File.join(@tmp_home, 'summary.xls')
243
+ summary = @reports.write_summary(filename)
244
+ expect(file_is_xls(filename))
245
+ end
246
+
247
+ it 'details' do
248
+ filename = File.join(@tmp_home, 'details.xls')
249
+ details = @reports.write_details(filename)
250
+ expect(file_is_xls(filename))
251
+ end
196
252
  end
197
253
  end
198
254
  end
@@ -127,6 +127,7 @@ describe 'Clients' do
127
127
  expect(client).to include(new_values)
128
128
  end
129
129
 
130
+ # :nocov:
130
131
  # It appears hourly rate is no longer tied to a client despite the docs:
131
132
  # https://github.com/toggl/toggl_api_docs/blob/master/chapters/clients.md#clients
132
133
  xit 'updates Pro client data', :pro_account do
@@ -139,5 +140,6 @@ describe 'Clients' do
139
140
  client = @toggl.get_client(@client['id'])
140
141
  expect(client).to include(new_values)
141
142
  end
143
+ # :nocov:
142
144
  end
143
145
  end
@@ -46,6 +46,13 @@ describe 'Projects' do
46
46
  expect(project['auto_estimates']).to eq @project['auto_estimates']
47
47
  expect(project['at']).to_not be nil
48
48
  end
49
+
50
+ it 'gets project users' do
51
+ users = @toggl.get_project_users(@project['id'])
52
+ expect(users.length).to eq 1
53
+ expect(users.first['uid']).to eq Testing::USER_ID
54
+ expect(users.first['manager']).to eq true
55
+ end
49
56
  end
50
57
 
51
58
  context 'updated project' do
@@ -9,7 +9,7 @@ describe 'Users' do
9
9
  it 'returns /me' do
10
10
  expect(@user).to_not be_nil
11
11
  expect(@user['id']).to eq Testing::USER_ID
12
- # expect(@user['fullname']).to eq 'togglv8'
12
+ expect(@user['fullname']).to eq Testing::USERNAME
13
13
  # expect(@user['image_url']).to eq 'https://assets.toggl.com/avatars/a5d106126b6bed8df283e708af0828ee.png'
14
14
  # expect(@user['timezone']).to eq 'Etc/UTC'
15
15
  # expect(@user['workspaces'].length).to eq 1
@@ -0,0 +1,40 @@
1
+ describe 'Workspaces' do
2
+ before :all do
3
+ @toggl = TogglV8::API.new(Testing::API_TOKEN)
4
+ @user = @toggl.me(all=true)
5
+ @workspaces = @toggl.workspaces
6
+ @workspace_id = @workspaces.first['id']
7
+ @project = @toggl.create_project({ 'name' => 'project with a task', 'wid' => @workspace_id })
8
+ end
9
+
10
+ after :all do
11
+ @toggl.delete_project(@project['id'])
12
+ end
13
+
14
+ it 'shows users' do
15
+ users = @toggl.users(@workspace_id)
16
+ expect(users.length).to eq 1
17
+ expect(users.first['id']).to eq Testing::USER_ID
18
+ expect(users.first['email']).to eq Testing::EMAIL
19
+ expect(users.first['fullname']).to eq Testing::USERNAME
20
+ expect(users.first['default_wid']).to eq @workspace_id
21
+ end
22
+
23
+ context 'tasks', :pro_account do
24
+ before :each do
25
+ @task = @toggl.create_task('name' => 'workspace task', 'pid' => @project['id'])
26
+ end
27
+
28
+ after :each do
29
+ @toggl.delete_task(@task['id'])
30
+ end
31
+
32
+ it 'shows tasks' do
33
+ tasks = @toggl.tasks(@workspace_id)
34
+ expect(tasks.length).to eq 1
35
+ expect(tasks.first['name']).to eq 'workspace task'
36
+ expect(tasks.first['pid']).to eq @project['id']
37
+ expect(tasks.first['wid']).to eq @workspace_id
38
+ end
39
+ end
40
+ end
@@ -6,15 +6,15 @@ describe 'TogglV8' do
6
6
  me = toggl.me
7
7
  expect(me).to_not be nil
8
8
  expect(me['api_token']).to eq Testing::API_TOKEN
9
- expect(me['email']).to eq Testing::USERNAME
9
+ expect(me['email']).to eq Testing::EMAIL
10
10
  end
11
11
 
12
12
  it 'initializes with username and password' do
13
- toggl = TogglV8::API.new(Testing::USERNAME, Testing::PASSWORD)
13
+ toggl = TogglV8::API.new(Testing::EMAIL, Testing::PASSWORD)
14
14
  me = toggl.me
15
15
  expect(me).to_not be nil
16
16
  expect(me['api_token']).to eq Testing::API_TOKEN
17
- expect(me['email']).to eq Testing::USERNAME
17
+ expect(me['email']).to eq Testing::EMAIL
18
18
  end
19
19
 
20
20
  it 'does not initialize with bogus api_token' do
@@ -24,27 +24,25 @@ describe 'TogglV8' do
24
24
 
25
25
  context '.toggl file' do
26
26
  before :each do
27
- @home = File.join(Dir.pwd, "tmp")
28
- Dir.mkdir(@home)
29
-
27
+ @tmp_home = mktemp_dir
30
28
  @original_home = Dir.home
31
- ENV['HOME'] = @home
29
+ ENV['HOME'] = @tmp_home
32
30
  end
33
31
 
34
32
  after :each do
35
- FileUtils.rm_rf(@home)
33
+ FileUtils.rm_rf(@tmp_home)
36
34
  ENV['HOME'] = @original_home
37
35
  end
38
36
 
39
37
  it 'initializes with .toggl file' do
40
- toggl_file = File.join(@home, '.toggl')
38
+ toggl_file = File.join(@tmp_home, '.toggl')
41
39
  File.open(toggl_file, 'w') { |file| file.write(Testing::API_TOKEN) }
42
40
 
43
41
  toggl = TogglV8::API.new
44
42
  me = toggl.me
45
43
  expect(me).to_not be nil
46
44
  expect(me['api_token']).to eq Testing::API_TOKEN
47
- expect(me['email']).to eq Testing::USERNAME
45
+ expect(me['email']).to eq Testing::EMAIL
48
46
  end
49
47
 
50
48
  it 'raises error if .toggl file is missing' do
@@ -52,9 +52,34 @@ class MockResponse
52
52
  end
53
53
  end
54
54
 
55
+ def mktemp_dir
56
+ dir = File.join(Dir.pwd, "tmp-#{Time.now.to_f}")
57
+ Dir.mkdir(dir)
58
+ dir
59
+ end
60
+
61
+ def file_contains(filename, pattern, maxlen=1000)
62
+ expect(File.exist?(filename))
63
+ contents = File.new(filename).sysread(maxlen)
64
+ expect(contents).to match pattern
65
+ end
66
+
67
+ def file_is_pdf(filename)
68
+ expect(File.exist?(filename))
69
+ first_line = File.foreach(filename).first
70
+ expect(first_line).to eq "%PDF-1.3\n"
71
+ end
72
+
73
+ def file_is_xls(filename)
74
+ expect(File.exist?(filename))
75
+ header = File.new(filename).sysread(8)
76
+ expect(header).to eq ['D0CF11E0A1B11AE1'].pack("H*")
77
+ end
78
+
55
79
  class Testing
56
80
  API_TOKEN = ENV['API_TOKEN'] || '4880adbe1bee9a241fa08070d33bd49f'
57
- USERNAME = ENV['USERNAME'] || 'togglv8@mailinator.com'
81
+ EMAIL = ENV['EMAIL'] || 'togglv8@mailinator.com'
82
+ USERNAME = ENV['USERNAME'] || 'togglv8'
58
83
  PASSWORD = ENV['PASSWORD'] || 'togglv8'
59
84
  USER_ID = (ENV['USER_ID'] || 1820939).to_i
60
85
  end
@@ -1,3 +1,4 @@
1
+ # :nocov:
1
2
  require_relative '../lib/togglv8'
2
3
 
3
4
  class TogglV8SpecHelper
@@ -70,4 +71,5 @@ class TogglV8SpecHelper
70
71
  end
71
72
  end
72
73
  end
73
- end
74
+ end
75
+ # :nocov:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: togglv8
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Kane
@@ -204,6 +204,7 @@ files:
204
204
  - spec/lib/togglv8/tasks_spec.rb
205
205
  - spec/lib/togglv8/time_entries_spec.rb
206
206
  - spec/lib/togglv8/users_spec.rb
207
+ - spec/lib/togglv8/workspaces_spec.rb
207
208
  - spec/lib/togglv8_spec.rb
208
209
  - spec/spec_helper.rb
209
210
  - spec/togglv8_spec_helper.rb
@@ -242,6 +243,7 @@ test_files:
242
243
  - spec/lib/togglv8/tasks_spec.rb
243
244
  - spec/lib/togglv8/time_entries_spec.rb
244
245
  - spec/lib/togglv8/users_spec.rb
246
+ - spec/lib/togglv8/workspaces_spec.rb
245
247
  - spec/lib/togglv8_spec.rb
246
248
  - spec/spec_helper.rb
247
249
  - spec/togglv8_spec_helper.rb