togglv8 0.2.0
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +4 -0
- data/.rdoc_options +23 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/API calls.md +330 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +75 -0
- data/Rakefile +8 -0
- data/lib/togglv8/clients.rb +37 -0
- data/lib/togglv8/dashboard.rb +14 -0
- data/lib/togglv8/project_users.rb +32 -0
- data/lib/togglv8/projects.rb +111 -0
- data/lib/togglv8/tags.rb +25 -0
- data/lib/togglv8/tasks.rb +53 -0
- data/lib/togglv8/time_entries.rb +89 -0
- data/lib/togglv8/users.rb +60 -0
- data/lib/togglv8/version.rb +4 -0
- data/lib/togglv8/workspaces.rb +43 -0
- data/lib/togglv8.rb +137 -0
- data/spec/lib/togglv8/clients_spec.rb +139 -0
- data/spec/lib/togglv8/dashboard_spec.rb +31 -0
- data/spec/lib/togglv8/projects_spec.rb +105 -0
- data/spec/lib/togglv8/tags_spec.rb +47 -0
- data/spec/lib/togglv8/tasks_spec.rb +97 -0
- data/spec/lib/togglv8/time_entries_spec.rb +247 -0
- data/spec/lib/togglv8/users_spec.rb +55 -0
- data/spec/lib/togglv8_spec.rb +59 -0
- data/spec/spec_helper.rb +140 -0
- data/spec/togglv8_spec_helper.rb +71 -0
- data/togglv8.gemspec +35 -0
- metadata +227 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
describe 'Dashboard' do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
4
|
+
@workspaces = @toggl.workspaces
|
5
|
+
@workspace_id = @workspaces.first['id']
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'gets nil dashboard data' do
|
9
|
+
dashboard = @toggl.dashboard(@workspace_id)
|
10
|
+
expect(dashboard).to eq Hash['most_active_user' => nil, 'activity' => nil]
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'gets dashboard time entries' do
|
14
|
+
before :all do
|
15
|
+
@new_time_entry = @toggl.start_time_entry({ 'wid' => @workspace_id, 'description' => 'new time entry' })
|
16
|
+
end
|
17
|
+
|
18
|
+
after :all do
|
19
|
+
@toggl.delete_time_entry(@new_time_entry['id'])
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'gets dashboard data' do
|
23
|
+
dashboard = @toggl.dashboard(@workspace_id)
|
24
|
+
expect(dashboard['most_active_user']).to be nil
|
25
|
+
expect(dashboard['activity']).to_not be nil
|
26
|
+
expect(dashboard['activity'].first['user_id']).to eq @toggl.me['id']
|
27
|
+
expect(dashboard['activity'].first['project_id']).to be nil
|
28
|
+
expect(dashboard['activity'].first['description']).to eq 'new time entry'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
describe 'Projects' do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
4
|
+
@workspaces = @toggl.workspaces
|
5
|
+
@workspace_id = @workspaces.first['id']
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'gets {} if there are no workspace projects' do
|
9
|
+
projects = @toggl.projects(@workspace_id)
|
10
|
+
expect(projects).to be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'new project' do
|
14
|
+
before :all do
|
15
|
+
@project = @toggl.create_project({ 'name' => 'new project', 'wid' => @workspace_id })
|
16
|
+
project_ids = @toggl.my_projects.map { |p| p['id'] }
|
17
|
+
expect(project_ids).to eq [ @project['id'] ]
|
18
|
+
end
|
19
|
+
|
20
|
+
after :all do
|
21
|
+
TogglV8SpecHelper.delete_all_projects(@toggl)
|
22
|
+
projects = @toggl.my_projects
|
23
|
+
expect(projects).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'creates a project' do
|
27
|
+
expect(@project).to_not be nil
|
28
|
+
expect(@project['name']).to eq 'new project'
|
29
|
+
expect(@project['billable']).to eq false
|
30
|
+
expect(@project['is_private']).to eq true
|
31
|
+
expect(@project['active']).to eq true
|
32
|
+
expect(@project['template']).to eq false
|
33
|
+
expect(@project['auto_estimates']).to eq false
|
34
|
+
expect(@project['wid']).to eq @workspace_id
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'gets project data' do
|
38
|
+
project = @toggl.get_project(@project['id'])
|
39
|
+
expect(project).to_not be nil
|
40
|
+
expect(project['wid']).to eq @project['wid']
|
41
|
+
expect(project['name']).to eq @project['name']
|
42
|
+
expect(project['billable']).to eq @project['billable']
|
43
|
+
expect(project['is_private']).to eq @project['is_private']
|
44
|
+
expect(project['active']).to eq @project['active']
|
45
|
+
expect(project['template']).to eq @project['template']
|
46
|
+
expect(project['auto_estimates']).to eq @project['auto_estimates']
|
47
|
+
expect(project['at']).to_not be nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'updated project' do
|
52
|
+
before :each do
|
53
|
+
@project = @toggl.create_project({ 'name' => 'project to update', 'wid' => @workspace_id })
|
54
|
+
end
|
55
|
+
|
56
|
+
after :each do
|
57
|
+
@toggl.delete_project(@project['id'])
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'updates project data' do
|
61
|
+
new_values = {
|
62
|
+
'name' => 'PROJECT-NEW',
|
63
|
+
'is_private' => false,
|
64
|
+
'active' => false,
|
65
|
+
'auto_estimates' => true,
|
66
|
+
}
|
67
|
+
|
68
|
+
project = @toggl.update_project(@project['id'], new_values)
|
69
|
+
expect(project).to include(new_values)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'updates Pro project data', :pro_account do
|
73
|
+
new_values = {
|
74
|
+
'template' => 'true',
|
75
|
+
'billable' => 'true',
|
76
|
+
}
|
77
|
+
project = @toggl.update_project(@project['id'], new_values)
|
78
|
+
expect(project).to include(new_values)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'multiple projects' do
|
83
|
+
after :all do
|
84
|
+
TogglV8SpecHelper.delete_all_projects(@toggl)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'deletes multiple projects' do
|
88
|
+
# start with no projects
|
89
|
+
expect(@toggl.projects(@workspace_id)).to be_empty
|
90
|
+
|
91
|
+
p1 = @toggl.create_project({ 'name' => 'p1', 'wid' => @workspace_id })
|
92
|
+
p2 = @toggl.create_project({ 'name' => 'p2', 'wid' => @workspace_id })
|
93
|
+
p3 = @toggl.create_project({ 'name' => 'p3', 'wid' => @workspace_id })
|
94
|
+
|
95
|
+
# see 3 new projects
|
96
|
+
expect(@toggl.projects(@workspace_id).length).to eq 3
|
97
|
+
|
98
|
+
p_ids = [p1, p2, p3].map { |p| p['id'] }
|
99
|
+
@toggl.delete_projects(p_ids)
|
100
|
+
|
101
|
+
# end with no projects
|
102
|
+
expect(@toggl.projects(@workspace_id)).to be_empty
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
describe 'Tags' do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
4
|
+
@workspaces = @toggl.workspaces
|
5
|
+
@workspace_id = @workspaces.first['id']
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'new tag' do
|
9
|
+
before :all do
|
10
|
+
@tag = @toggl.create_tag({ 'name' => 'new tag', 'wid' => @workspace_id })
|
11
|
+
tag_ids = @toggl.my_tags.map { |t| t['id'] }
|
12
|
+
expect(tag_ids).to eq [ @tag['id'] ]
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
TogglV8SpecHelper.delete_all_tags(@toggl)
|
17
|
+
tags = @toggl.my_tags
|
18
|
+
expect(tags).to be_empty
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a tag' do
|
22
|
+
expect(@tag).to_not be nil
|
23
|
+
expect(@tag['name']).to eq 'new tag'
|
24
|
+
expect(@tag['notes']).to eq nil
|
25
|
+
expect(@tag['wid']).to eq @workspace_id
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'updated tag' do
|
30
|
+
before :each do
|
31
|
+
@tag = @toggl.create_tag({ 'name' => 'tag to update', 'wid' => @workspace_id })
|
32
|
+
end
|
33
|
+
|
34
|
+
after :each do
|
35
|
+
@toggl.delete_tag(@tag['id'])
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'updates tag data' do
|
39
|
+
new_values = {
|
40
|
+
'name' => 'TAG-NEW',
|
41
|
+
}
|
42
|
+
|
43
|
+
tag = @toggl.update_tag(@tag['id'], new_values)
|
44
|
+
expect(tag).to include(new_values)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
describe 'Tasks', :pro_account do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
4
|
+
@workspaces = @toggl.workspaces
|
5
|
+
@workspace_id = @workspaces.first['id']
|
6
|
+
@project = @toggl.create_project({ name: 'project with a task', wid: @workspace_id })
|
7
|
+
end
|
8
|
+
|
9
|
+
after :all do
|
10
|
+
@toggl.delete_project(@project['id'])
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'new task' do
|
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'] ]
|
18
|
+
end
|
19
|
+
|
20
|
+
after :all do
|
21
|
+
TogglV8SpecHelper.delete_all_tasks(@toggl)
|
22
|
+
tasks = @toggl.get_project_tasks(@project['id'])
|
23
|
+
expect(tasks).to be_empty
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'creates a task' do
|
27
|
+
expect(@task).to_not be nil
|
28
|
+
expect(@task['name']).to eq 'new task'
|
29
|
+
expect(@task['pid']).to eq @project['id']
|
30
|
+
expect(@task['wid']).to eq @workspace_id
|
31
|
+
expect(@task['active']).to eq true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'gets a task' do
|
35
|
+
task = @toggl.get_task(@task['id'])
|
36
|
+
expect(task).to eq @task
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'updated task' do
|
41
|
+
before :each do
|
42
|
+
@task = @toggl.create_task({ name: 'task to update', pid: @project['id'] })
|
43
|
+
end
|
44
|
+
|
45
|
+
after :each do
|
46
|
+
@toggl.delete_task(@task['id'])
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'updates task data' do
|
50
|
+
new_values = {
|
51
|
+
'name' => 'task-NEW',
|
52
|
+
}
|
53
|
+
|
54
|
+
task = @toggl.update_task(@task['id'], new_values)
|
55
|
+
expect(task).to include(new_values)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'multiple tasks' do
|
60
|
+
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'] })
|
64
|
+
end
|
65
|
+
|
66
|
+
after :all do
|
67
|
+
TogglV8SpecHelper.delete_all_tasks(@toggl)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'updates multiple tasks' do
|
71
|
+
# start with 3 active tasks
|
72
|
+
tasks = @toggl.get_project_tasks(@project['id'])
|
73
|
+
active_flags = tasks.map { |t| t['active'] }
|
74
|
+
expect().to match_array(['true', 'true', 'true'])
|
75
|
+
|
76
|
+
t_ids = [@task1, @task2, @task3].map { |t| t['id'] }
|
77
|
+
params = { 'active': true }
|
78
|
+
@toggl.update_tasks(t_ids, params)
|
79
|
+
|
80
|
+
# end with 3 inactive tasks
|
81
|
+
tasks = @toggl.get_project_tasks(@project['id'])
|
82
|
+
active_flags = tasks.map { |t| t['active'] }
|
83
|
+
expect().to match_array(['true', 'true', 'true'])
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'deletes multiple tasks' do
|
87
|
+
# start with 3 new tasks
|
88
|
+
expect(@toggl.get_project_tasks(@project['id']).length).to eq 3
|
89
|
+
|
90
|
+
t_ids = [@task1, @task2, @task3].map { |t| t['id'] }
|
91
|
+
@toggl.delete_tasks(t_ids)
|
92
|
+
|
93
|
+
# end with no tasks
|
94
|
+
expect(@toggl.get_project_tasks(@project['id']).length).to be_empty
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
describe 'Time Entries' do
|
4
|
+
before :all do
|
5
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
6
|
+
@workspaces = @toggl.workspaces
|
7
|
+
@workspace_id = @workspaces.first['id']
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'CRUD time entry' do
|
11
|
+
before :each do
|
12
|
+
time_entry_info = {
|
13
|
+
'wid' => @workspace_id,
|
14
|
+
'start' => @toggl.iso8601(DateTime.now),
|
15
|
+
'duration' => 77
|
16
|
+
}
|
17
|
+
|
18
|
+
@expected = time_entry_info.clone
|
19
|
+
|
20
|
+
@time_entry = @toggl.create_time_entry(time_entry_info)
|
21
|
+
end
|
22
|
+
|
23
|
+
after :each do
|
24
|
+
@toggl.delete_time_entry(@time_entry['id'])
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates a time entry' do
|
28
|
+
expect(@time_entry).to include(@expected)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'requires a workspace, project, or task to create' do
|
32
|
+
time_entry_info = {
|
33
|
+
'start' => @toggl.iso8601(DateTime.now),
|
34
|
+
'duration' => 77
|
35
|
+
}
|
36
|
+
|
37
|
+
expect {
|
38
|
+
@toggl.create_time_entry(time_entry_info)
|
39
|
+
}.to raise_error(ArgumentError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'gets a time entry' do
|
43
|
+
retrieved_time_entry = @toggl.get_time_entry(@time_entry['id'])
|
44
|
+
|
45
|
+
['start', 'stop'].each do |key|
|
46
|
+
expect(retrieved_time_entry[key]).to eq_ts @time_entry[key]
|
47
|
+
retrieved_time_entry.delete(key)
|
48
|
+
@time_entry.delete(key)
|
49
|
+
end
|
50
|
+
|
51
|
+
expect(retrieved_time_entry).to eq @time_entry
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'updates a time entry' do
|
55
|
+
time_entry_info = {
|
56
|
+
'start' => '2010-02-13T23:31:30+00:00',
|
57
|
+
'duration' => 42
|
58
|
+
}
|
59
|
+
|
60
|
+
expected = time_entry_info.clone
|
61
|
+
|
62
|
+
time_entry_updated = @toggl.update_time_entry(@time_entry['id'], time_entry_info)
|
63
|
+
expect(time_entry_updated).to include(expected)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'deletes a time entry' do
|
67
|
+
existing_time_entry = @toggl.get_time_entry(@time_entry['id'])
|
68
|
+
expect(existing_time_entry.has_key?('server_deleted_at')).to eq false
|
69
|
+
|
70
|
+
deleted_time_entry = @toggl.delete_time_entry(@time_entry['id'])
|
71
|
+
expect(deleted_time_entry).to eq "[#{ @time_entry['id'] }]"
|
72
|
+
|
73
|
+
zombie_time_entry = @toggl.get_time_entry(@time_entry['id'])
|
74
|
+
expect(zombie_time_entry.has_key?('server_deleted_at')).to eq true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'multiple time entries' do
|
79
|
+
before :all do
|
80
|
+
time_entry_info = {
|
81
|
+
'wid' => @workspace_id,
|
82
|
+
'duration' => 77
|
83
|
+
}
|
84
|
+
@now = DateTime.now
|
85
|
+
|
86
|
+
start = { 'start' => @toggl.iso8601(@now - 7) }
|
87
|
+
@time_entry_last_week = @toggl.create_time_entry(time_entry_info.merge(start))
|
88
|
+
@last_week_id = @time_entry_last_week['id']
|
89
|
+
|
90
|
+
start = { 'start' => @toggl.iso8601(@now) }
|
91
|
+
@time_entry_now = @toggl.create_time_entry(time_entry_info.merge(start))
|
92
|
+
@now_id = @time_entry_now['id']
|
93
|
+
|
94
|
+
start = { 'start' => @toggl.iso8601(@now + 7) }
|
95
|
+
@time_entry_next_week = @toggl.create_time_entry(time_entry_info.merge(start))
|
96
|
+
@next_week_id = @time_entry_next_week['id']
|
97
|
+
end
|
98
|
+
|
99
|
+
after :all do
|
100
|
+
@toggl.delete_time_entry(@last_week_id)
|
101
|
+
@toggl.delete_time_entry(@now_id)
|
102
|
+
@toggl.delete_time_entry(@next_week_id)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'gets time entries (reaching back 9 days up till now)' do
|
106
|
+
ids = @toggl.get_time_entries.map { |t| t['id']}
|
107
|
+
expect(ids).to eq [ @last_week_id, @now_id ]
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'gets time entries after start timestamp (up till now)' do
|
111
|
+
ids = @toggl.get_time_entries(start_timestamp = @now - 1).map { |t| t['id']}
|
112
|
+
expect(ids).to eq [ @now_id ]
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'gets time entries before end timestamp' do
|
116
|
+
ids = @toggl.get_time_entries(end_timestamp = @now + 1).map { |t| t['id']}
|
117
|
+
expect(ids).to be_empty
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'gets time entries between start and end timestamps' do
|
121
|
+
ids = @toggl.get_time_entries(start_timestamp = @now - 1, end_timestamp = @now + 1).map { |t| t['id']}
|
122
|
+
expect(ids).to eq [ @now_id ]
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'gets time entries in the future' do
|
126
|
+
ids = @toggl.get_time_entries(start_timestamp = @now - 1, end_timestamp = @now + 8).map { |t| t['id']}
|
127
|
+
expect(ids).to eq [ @now_id, @next_week_id ]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'start and stop time entry' do
|
132
|
+
it 'starts and stops a time entry' do
|
133
|
+
time_entry_info = {
|
134
|
+
'wid' => @workspace_id,
|
135
|
+
'description' => 'time entry description'
|
136
|
+
}
|
137
|
+
|
138
|
+
# start time entry
|
139
|
+
running_time_entry = @toggl.start_time_entry(time_entry_info)
|
140
|
+
|
141
|
+
# get current time entry by '/current'
|
142
|
+
time_entry_current = @toggl.get_current_time_entry
|
143
|
+
# get current time entry by id
|
144
|
+
time_entry_by_id = @toggl.get_time_entry(running_time_entry['id'])
|
145
|
+
|
146
|
+
# compare two methods of getting current time entry
|
147
|
+
expect(time_entry_current).to eq time_entry_by_id
|
148
|
+
|
149
|
+
# compare current time entry with running time entry
|
150
|
+
expect(time_entry_by_id['start']).to eq_ts running_time_entry['start']
|
151
|
+
time_entry_by_id.delete('start')
|
152
|
+
running_time_entry.delete('start')
|
153
|
+
|
154
|
+
expect(time_entry_by_id).to eq running_time_entry
|
155
|
+
expect(time_entry_by_id.has_key?('stop')).to eq false
|
156
|
+
|
157
|
+
# stop time entry
|
158
|
+
stopped_time_entry = @toggl.stop_time_entry(running_time_entry['id'])
|
159
|
+
expect(stopped_time_entry.has_key?('stop')).to eq true
|
160
|
+
|
161
|
+
@toggl.delete_time_entry(stopped_time_entry['id'])
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'returns nil if there is no current time entry' do
|
165
|
+
time_entry = @toggl.get_current_time_entry
|
166
|
+
expect(time_entry).to be nil
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'requires a workspace, project, or task to start' do
|
170
|
+
time_entry_info = {
|
171
|
+
'description' => 'time entry description'
|
172
|
+
}
|
173
|
+
|
174
|
+
expect {
|
175
|
+
@toggl.start_time_entry(time_entry_info)
|
176
|
+
}.to raise_error(ArgumentError)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context 'iso8601' do
|
181
|
+
before :all do
|
182
|
+
@ts = DateTime.new(2008,6,21, 13,30,2, "+09:00")
|
183
|
+
@expected = '2008-06-21T13:30:02+09:00'
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'formats a DateTime' do
|
187
|
+
expect(@toggl.iso8601(@ts)).to eq @expected
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'formats a Date' do
|
191
|
+
ts = @ts.to_date
|
192
|
+
expect(@toggl.iso8601(@ts)).to eq @expected
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'formats a Time' do
|
196
|
+
ts = @ts.to_time
|
197
|
+
expect(@toggl.iso8601(@ts)).to eq @expected
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'cannot format a FixNum' do
|
201
|
+
expect{ @toggl.iso8601(1234567890) }.to raise_error(ArgumentError)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'cannot format a malformed timestamp' do
|
205
|
+
expect{ @toggl.iso8601('X') }.to raise_error(ArgumentError)
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'String' do
|
209
|
+
xit 'converts Zulu to +00:00' do
|
210
|
+
ts = '2015-08-21T09:21:02Z'
|
211
|
+
expected = '2015-08-21T09:21:02+00:00'
|
212
|
+
|
213
|
+
expect(@toggl.iso8601(ts)).to eq expected
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'converts +00:00 to Zulu' do
|
217
|
+
ts = '2015-08-21T09:21:02+00:00'
|
218
|
+
expected = '2015-08-21T09:21:02Z'
|
219
|
+
|
220
|
+
expect(@toggl.iso8601(ts)).to eq expected
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'converts -00:00 to Z' do
|
224
|
+
ts = '2015-08-21T09:21:02-00:00'
|
225
|
+
expected = '2015-08-21T09:21:02Z'
|
226
|
+
|
227
|
+
expect(@toggl.iso8601(ts)).to eq expected
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'maintains an offset' do
|
231
|
+
expect(@toggl.iso8601('2015-08-21T04:21:02-05:00')).to eq '2015-08-21T04:21:02-05:00'
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
RSpec::Matchers.define :eq_ts do |expected|
|
237
|
+
# Matching actual time is necessary due to differing formats.
|
238
|
+
# Example:
|
239
|
+
# 1) POST time_entries/start returns 2015-08-21T07:28:20Z
|
240
|
+
# when GET time_entries/{time_entry_id} returns 2015-08-21T07:28:20+00:00
|
241
|
+
# 2) 2015-08-21T03:20:30-05:00 and 2015-08-21T08:20:30+00:00 refer to
|
242
|
+
# the same moment in time, but one is in local time and the other in UTC
|
243
|
+
match do |actual|
|
244
|
+
DateTime.parse(actual) == DateTime.parse(expected)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
describe 'Users' do
|
2
|
+
before :all do
|
3
|
+
@toggl = TogglV8::API.new(Testing::API_TOKEN)
|
4
|
+
@user = @toggl.me(all=true)
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'returns /me' do
|
8
|
+
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"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns /my_clients' do
|
18
|
+
my_clients = @toggl.my_clients(@user)
|
19
|
+
expect(my_clients).to be_empty
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns /my_projects' do
|
23
|
+
my_projects = @toggl.my_projects(@user)
|
24
|
+
expect(my_projects).to be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns /my_tags' do
|
28
|
+
my_tags = @toggl.my_tags(@user)
|
29
|
+
expect(my_tags).to be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns /my_time_entries' do
|
33
|
+
my_time_entries = @toggl.my_time_entries(@user)
|
34
|
+
expect(my_time_entries).to be_empty
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns /my_workspaces' do
|
38
|
+
my_workspaces = @toggl.my_workspaces(@user)
|
39
|
+
expect(my_workspaces.length).to eq 1
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'new user' do
|
43
|
+
it 'creates a new user' do
|
44
|
+
now = Time.now.to_i
|
45
|
+
user_info = {
|
46
|
+
'email' => "test-#{now}@mailinator.com",
|
47
|
+
'timezone' => 'Etc/UTC'
|
48
|
+
}
|
49
|
+
user_password = { 'password' => "password-#{now}" }
|
50
|
+
|
51
|
+
new_user = @toggl.create_user(user_info.merge(user_password))
|
52
|
+
expect(new_user).to include(user_info)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
describe 'TogglV8::API' do
|
4
|
+
before :each do
|
5
|
+
sleep(Testing::DELAY_SEC)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'initializes with api_token' do
|
9
|
+
toggl = TogglV8::API.new(Testing::API_TOKEN)
|
10
|
+
me = toggl.me
|
11
|
+
expect(me).to_not be nil
|
12
|
+
expect(me['api_token']).to eq Testing::API_TOKEN
|
13
|
+
expect(me['email']).to eq Testing::USERNAME
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'initializes with username and password' do
|
17
|
+
toggl = TogglV8::API.new(Testing::USERNAME, Testing::PASSWORD)
|
18
|
+
me = toggl.me
|
19
|
+
expect(me).to_not be nil
|
20
|
+
expect(me['api_token']).to eq Testing::API_TOKEN
|
21
|
+
expect(me['email']).to eq Testing::USERNAME
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'does not initialize with bogus api_token' do
|
25
|
+
toggl = TogglV8::API.new('4880nqor1orr9n241sn08070q33oq49s')
|
26
|
+
expect { toggl.me } .to raise_error(RuntimeError)
|
27
|
+
end
|
28
|
+
|
29
|
+
context '.toggl file' do
|
30
|
+
before :each do
|
31
|
+
@home = File.join(Dir.pwd, "tmp")
|
32
|
+
Dir.mkdir(@home)
|
33
|
+
|
34
|
+
@original_home = Dir.home
|
35
|
+
ENV['HOME'] = @home
|
36
|
+
end
|
37
|
+
|
38
|
+
after :each do
|
39
|
+
FileUtils.rm_rf(@home)
|
40
|
+
ENV['HOME'] = @original_home
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'initializes with .toggl file' do
|
44
|
+
toggl_file = File.join(@home, '.toggl')
|
45
|
+
File.open(toggl_file, 'w') { |file| file.write(Testing::API_TOKEN) }
|
46
|
+
|
47
|
+
toggl = TogglV8::API.new
|
48
|
+
me = toggl.me
|
49
|
+
expect(me).to_not be nil
|
50
|
+
expect(me['api_token']).to eq Testing::API_TOKEN
|
51
|
+
expect(me['email']).to eq Testing::USERNAME
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises error if .toggl file is missing' do
|
55
|
+
expect{ toggl = TogglV8::API.new }.to raise_error(RuntimeError)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|