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 +4 -4
- data/README.md +2 -2
- data/Rakefile +4 -6
- data/lib/logging.rb +3 -1
- data/lib/reportsv2.rb +60 -31
- data/lib/togglv8.rb +4 -0
- data/lib/togglv8/connection.rb +0 -19
- data/lib/togglv8/time_entries.rb +2 -2
- data/lib/togglv8/togglv8.rb +15 -0
- data/lib/togglv8/users.rb +1 -1
- data/lib/togglv8/version.rb +1 -1
- data/spec/lib/reportsv2_spec.rb +126 -70
- data/spec/lib/togglv8/clients_spec.rb +2 -0
- data/spec/lib/togglv8/projects_spec.rb +7 -0
- data/spec/lib/togglv8/users_spec.rb +1 -1
- data/spec/lib/togglv8/workspaces_spec.rb +40 -0
- data/spec/lib/togglv8_spec.rb +8 -10
- data/spec/spec_helper.rb +26 -1
- data/spec/togglv8_spec_helper.rb +3 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bcd7cc8508f9dd6457f7899cc9be1644e1453384
|
4
|
+
data.tar.gz: 9d7640b307c1d5fe4135c22dc368815ec60e595d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
[](https://travis-ci.org/kanet77/togglv8) [](https://coveralls.io/github/kanet77/togglv8?branch=master)
|
4
|
+
[](https://badge.fury.io/rb/togglv8) [](https://travis-ci.org/kanet77/togglv8) [](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(
|
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 '
|
2
|
+
require 'rake/clean'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
FileUtils.remove_dir('pkg', force=true)
|
8
|
-
end
|
4
|
+
CLEAN.add 'coverage'
|
5
|
+
CLEAN.add 'doc'
|
6
|
+
CLEAN.include 'tmp-*'
|
data/lib/logging.rb
CHANGED
data/lib/reportsv2.rb
CHANGED
@@ -13,18 +13,20 @@ module TogglV8
|
|
13
13
|
def initialize(opts={})
|
14
14
|
debug(false)
|
15
15
|
|
16
|
-
@user_agent =
|
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
|
21
|
+
if File.exist?(toggl_api_file) then
|
22
22
|
username = IO.read(toggl_api_file)
|
23
23
|
else
|
24
|
-
raise "Expecting
|
24
|
+
raise "Expecting one of:\n" +
|
25
25
|
" 1) api_token in file #{toggl_api_file}, or\n" +
|
26
|
-
" 2) parameter: (
|
27
|
-
"\n
|
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:
|
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,
|
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(
|
80
|
+
}.merge(params)
|
79
81
|
end
|
80
82
|
|
81
|
-
def weekly(extension='',
|
82
|
-
report('weekly', extension,
|
83
|
+
def weekly(extension='', params={})
|
84
|
+
report('weekly', extension, params)
|
83
85
|
end
|
84
86
|
|
85
|
-
def details(extension='',
|
86
|
-
report('details', extension,
|
87
|
+
def details(extension='', params={})
|
88
|
+
report('details', extension, params)
|
87
89
|
end
|
88
90
|
|
89
|
-
def summary(extension='',
|
90
|
-
report('summary', extension,
|
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,
|
107
|
+
def write_weekly(filename, params={})
|
102
108
|
write_report(filename) do |extension|
|
103
|
-
weekly(extension,
|
109
|
+
weekly(extension, params)
|
104
110
|
end
|
105
111
|
end
|
106
112
|
|
107
|
-
def write_details(filename,
|
113
|
+
def write_details(filename, params={})
|
108
114
|
write_report(filename) do |extension|
|
109
|
-
details(extension,
|
115
|
+
details(extension, params)
|
110
116
|
end
|
111
117
|
end
|
112
118
|
|
113
|
-
def write_summary(filename,
|
119
|
+
def write_summary(filename, params={})
|
114
120
|
write_report(filename) do |extension|
|
115
|
-
summary(extension,
|
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
|
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
|
-
|
133
|
-
|
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
|
data/lib/togglv8.rb
CHANGED
data/lib/togglv8/connection.rb
CHANGED
@@ -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|
|
data/lib/togglv8/time_entries.rb
CHANGED
@@ -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'] =
|
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'] =
|
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
|
data/lib/togglv8/togglv8.rb
CHANGED
@@ -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
|
data/lib/togglv8/users.rb
CHANGED
@@ -66,7 +66,7 @@ module TogglV8
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def create_user(params)
|
69
|
-
params['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
|
data/lib/togglv8/version.rb
CHANGED
data/spec/lib/reportsv2_spec.rb
CHANGED
@@ -15,20 +15,18 @@ describe 'ReportsV2' do
|
|
15
15
|
|
16
16
|
context '.toggl file' do
|
17
17
|
before :each do
|
18
|
-
@
|
19
|
-
Dir.mkdir(@home)
|
20
|
-
|
18
|
+
@tmp_home = mktemp_dir
|
21
19
|
@original_home = Dir.home
|
22
|
-
ENV['HOME'] = @
|
20
|
+
ENV['HOME'] = @tmp_home
|
23
21
|
end
|
24
22
|
|
25
23
|
after :each do
|
26
|
-
FileUtils.rm_rf(@
|
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(@
|
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(@
|
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(
|
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 '
|
82
|
-
it '
|
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
|
-
|
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 '
|
103
|
+
context 'project', :pro_account do
|
90
104
|
before :all do
|
91
105
|
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
92
|
-
@
|
93
|
-
@
|
94
|
-
|
95
|
-
|
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
|
-
|
99
|
-
|
113
|
+
after :all do
|
114
|
+
@toggl.delete_project(@project['id'])
|
100
115
|
end
|
101
116
|
|
102
|
-
it '
|
103
|
-
|
104
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 '
|
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
|
-
|
177
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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
|
-
|
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
|
data/spec/lib/togglv8_spec.rb
CHANGED
@@ -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::
|
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::
|
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::
|
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
|
-
@
|
28
|
-
Dir.mkdir(@home)
|
29
|
-
|
27
|
+
@tmp_home = mktemp_dir
|
30
28
|
@original_home = Dir.home
|
31
|
-
ENV['HOME'] = @
|
29
|
+
ENV['HOME'] = @tmp_home
|
32
30
|
end
|
33
31
|
|
34
32
|
after :each do
|
35
|
-
FileUtils.rm_rf(@
|
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(@
|
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::
|
45
|
+
expect(me['email']).to eq Testing::EMAIL
|
48
46
|
end
|
49
47
|
|
50
48
|
it 'raises error if .toggl file is missing' do
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
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
|
data/spec/togglv8_spec_helper.rb
CHANGED
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.
|
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
|