harvested2 5.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.gitignore +35 -0
- data/.rspec +1 -0
- data/.rubocop.yml +34 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +20 -0
- data/HISTORY.md +118 -0
- data/MIT-LICENSE +21 -0
- data/README.md +66 -0
- data/Rakefile +24 -0
- data/harvested2.gemspec +30 -0
- data/lib/ext/array.rb +52 -0
- data/lib/ext/date.rb +9 -0
- data/lib/ext/hash.rb +17 -0
- data/lib/ext/time.rb +5 -0
- data/lib/harvest/account.rb +13 -0
- data/lib/harvest/api/account.rb +25 -0
- data/lib/harvest/api/base.rb +72 -0
- data/lib/harvest/api/clients.rb +10 -0
- data/lib/harvest/api/company.rb +12 -0
- data/lib/harvest/api/contacts.rb +9 -0
- data/lib/harvest/api/expense_categories.rb +9 -0
- data/lib/harvest/api/expenses.rb +26 -0
- data/lib/harvest/api/invoice_categories.rb +9 -0
- data/lib/harvest/api/invoice_messages.rb +86 -0
- data/lib/harvest/api/invoice_payments.rb +41 -0
- data/lib/harvest/api/invoices.rb +9 -0
- data/lib/harvest/api/projects.rb +9 -0
- data/lib/harvest/api/task_assignments.rb +75 -0
- data/lib/harvest/api/tasks.rb +9 -0
- data/lib/harvest/api/time_entry.rb +19 -0
- data/lib/harvest/api/user_assignments.rb +75 -0
- data/lib/harvest/api/users.rb +10 -0
- data/lib/harvest/base.rb +333 -0
- data/lib/harvest/behavior/activatable.rb +31 -0
- data/lib/harvest/behavior/crud.rb +80 -0
- data/lib/harvest/client.rb +23 -0
- data/lib/harvest/company.rb +8 -0
- data/lib/harvest/contact.rb +20 -0
- data/lib/harvest/credentials.rb +34 -0
- data/lib/harvest/errors.rb +27 -0
- data/lib/harvest/expense.rb +54 -0
- data/lib/harvest/expense_category.rb +10 -0
- data/lib/harvest/hardy_client.rb +80 -0
- data/lib/harvest/invoice.rb +75 -0
- data/lib/harvest/invoice_category.rb +8 -0
- data/lib/harvest/invoice_message.rb +8 -0
- data/lib/harvest/invoice_payment.rb +8 -0
- data/lib/harvest/line_item.rb +21 -0
- data/lib/harvest/model.rb +133 -0
- data/lib/harvest/project.rb +41 -0
- data/lib/harvest/receipt.rb +12 -0
- data/lib/harvest/task.rb +21 -0
- data/lib/harvest/task_assignment.rb +27 -0
- data/lib/harvest/time_entry.rb +57 -0
- data/lib/harvest/timezones.rb +130 -0
- data/lib/harvest/user.rb +58 -0
- data/lib/harvest/user_assignment.rb +27 -0
- data/lib/harvest/version.rb +3 -0
- data/lib/harvested2.rb +96 -0
- data/spec/factories/client.rb +14 -0
- data/spec/factories/contact.rb +8 -0
- data/spec/factories/expense.rb +10 -0
- data/spec/factories/expenses_category.rb +7 -0
- data/spec/factories/invoice.rb +25 -0
- data/spec/factories/invoice_category.rb +5 -0
- data/spec/factories/invoice_message.rb +9 -0
- data/spec/factories/invoice_payment.rb +7 -0
- data/spec/factories/line_item.rb +9 -0
- data/spec/factories/project.rb +15 -0
- data/spec/factories/task.rb +8 -0
- data/spec/factories/task_assignment.rb +8 -0
- data/spec/factories/time_entry.rb +13 -0
- data/spec/factories/user.rb +19 -0
- data/spec/factories/user_assigment.rb +7 -0
- data/spec/functional/clients_spec.rb +105 -0
- data/spec/functional/errors_spec.rb +42 -0
- data/spec/functional/expenses_spec.rb +97 -0
- data/spec/functional/invoice_messages_spec.rb +48 -0
- data/spec/functional/invoice_payments_spec.rb +51 -0
- data/spec/functional/invoice_spec.rb +138 -0
- data/spec/functional/project_spec.rb +76 -0
- data/spec/functional/tasks_spec.rb +119 -0
- data/spec/functional/time_entries_spec.rb +87 -0
- data/spec/functional/users_spec.rb +72 -0
- data/spec/harvest/base_spec.rb +10 -0
- data/spec/harvest/basic_auth_credentials_spec.rb +12 -0
- data/spec/harvest/expense_category_spec.rb +5 -0
- data/spec/harvest/expense_spec.rb +18 -0
- data/spec/harvest/invoice_message_spec.rb +5 -0
- data/spec/harvest/invoice_payment_spec.rb +5 -0
- data/spec/harvest/invoice_spec.rb +5 -0
- data/spec/harvest/oauth_credentials_spec.rb +11 -0
- data/spec/harvest/project_spec.rb +5 -0
- data/spec/harvest/task_assignment_spec.rb +5 -0
- data/spec/harvest/task_spec.rb +5 -0
- data/spec/harvest/time_entry_spec.rb +23 -0
- data/spec/harvest/user_assignment_spec.rb +5 -0
- data/spec/harvest/user_spec.rb +34 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/factory_bot.rb +5 -0
- data/spec/support/harvested_helpers.rb +28 -0
- data/spec/support/json_examples.rb +9 -0
- metadata +238 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'harvest tasks' do
|
4
|
+
let(:harvest) { Harvest.client(access_token: 'mytoken', account_id: '123') }
|
5
|
+
|
6
|
+
describe 'tasks' do
|
7
|
+
let(:task) { create(:task) }
|
8
|
+
|
9
|
+
context 'allows to add invoice tasks' do
|
10
|
+
before do
|
11
|
+
allow(harvest.tasks).to receive(:create)
|
12
|
+
.and_return(task)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns true' do
|
16
|
+
expect(task.default_hourly_rate).to eql(120)
|
17
|
+
expect(task.name).to eql('A crud task')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'allows to update invoice tasks' do
|
22
|
+
before do
|
23
|
+
allow(harvest.tasks).to receive(:update)
|
24
|
+
.and_return(task)
|
25
|
+
task.default_hourly_rate = 140
|
26
|
+
task = harvest.tasks.update(task)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns true' do
|
30
|
+
expect(task.default_hourly_rate).to eql(140)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'allows to remove invoice tasks' do
|
35
|
+
before do
|
36
|
+
allow(harvest.tasks).to receive(:delete).and_return([])
|
37
|
+
allow(harvest.tasks).to receive(:all).and_return([])
|
38
|
+
harvest.tasks.delete(task)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'returns true' do
|
42
|
+
expect(harvest.tasks.all.select do |t|
|
43
|
+
t.name == 'A crud task'
|
44
|
+
end).to eql([])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'task assignments' do
|
50
|
+
let(:project) { create(:project) }
|
51
|
+
let(:task) do
|
52
|
+
create(:task, name: 'A task for joe', default_hourly_rate: 120)
|
53
|
+
end
|
54
|
+
let(:task_assignment) do
|
55
|
+
create(:task_assignment, project: project, task: task)
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'allows to add invoice task assignments' do
|
59
|
+
before do
|
60
|
+
allow(harvest.task_assignments).to receive(:create)
|
61
|
+
.and_return(task)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'returns true' do
|
65
|
+
expect(task_assignment.hourly_rate).to eql(120)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'allows to update invoice task assignments' do
|
70
|
+
before do
|
71
|
+
allow(harvest.task_assignments).to receive(:update)
|
72
|
+
.and_return(task)
|
73
|
+
task_assignment.hourly_rate = 100
|
74
|
+
task = harvest.task_assignments.update(task_assignment)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'returns true' do
|
78
|
+
expect(task_assignment.hourly_rate).to eql(100)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'allows to remove invoice task assignments' do
|
83
|
+
before do
|
84
|
+
allow(harvest.task_assignments).to receive(:delete)
|
85
|
+
.and_return([])
|
86
|
+
allow(harvest.task_assignments).to receive(:all)
|
87
|
+
.and_return([task_assignment])
|
88
|
+
harvest.task_assignments.delete(task_assignment)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'returns true' do
|
92
|
+
expect(harvest.task_assignments.all(project).count).to eql(1)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'projects' do
|
98
|
+
let(:project) { create(:project) }
|
99
|
+
let(:task) do
|
100
|
+
create(:task, name: 'A task for joe', default_hourly_rate: 120)
|
101
|
+
end
|
102
|
+
let(:task_assignment) do
|
103
|
+
create(:task_assignment, project: project, task: task)
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'allows to add project and task' do
|
107
|
+
before do
|
108
|
+
allow(harvest.projects).to receive(:create_task)
|
109
|
+
.and_return(task)
|
110
|
+
allow(harvest.task_assignments).to receive(:all)
|
111
|
+
.and_return([task_assignment])
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'returns true' do
|
115
|
+
expect(harvest.task_assignments.all(project).size).to eql(1)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'harvest time tracking' do
|
4
|
+
let(:harvest) { Harvest.client(access_token: 'mytoken', account_id: '123') }
|
5
|
+
|
6
|
+
describe 'time entries' do
|
7
|
+
let(:time_entry) { create(:time_entry) }
|
8
|
+
|
9
|
+
context 'allows to add time entry' do
|
10
|
+
before do
|
11
|
+
allow(harvest.time_entries).to receive(:create)
|
12
|
+
.and_return(time_entry)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'returns true' do
|
16
|
+
expect(time_entry.notes).to eql('Test api support')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'allows to update time entry' do
|
21
|
+
before do
|
22
|
+
allow(harvest.time_entries).to receive(:update)
|
23
|
+
.and_return(time_entry)
|
24
|
+
time_entry.notes = 'New test api support'
|
25
|
+
time_entry = harvest.time_entries.update(time_entry)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns true' do
|
29
|
+
expect(time_entry.notes).to eql('New test api support')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'allows to remove time entry' do
|
34
|
+
before do
|
35
|
+
allow(harvest.time_entries).to receive(:delete).and_return([])
|
36
|
+
allow(harvest.time_entries).to receive(:all).and_return([])
|
37
|
+
harvest.time_entries.delete(time_entry)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns true' do
|
41
|
+
expect(harvest.time_entries.all.select do |t|
|
42
|
+
t.notes == 'New test api support'
|
43
|
+
end).to eql([])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'toggle' do
|
49
|
+
let(:time_entry) { create(:time_entry, :started) }
|
50
|
+
|
51
|
+
before do
|
52
|
+
allow(harvest.time_entries).to receive(:toggle)
|
53
|
+
.and_return(time_entry)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should be active' do
|
57
|
+
expect(time_entry.timer_started_at).not_to be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should be deactive' do
|
61
|
+
time_entry.timer_started_at = nil
|
62
|
+
time_entry = harvest.time_entries.toggle(time_entry)
|
63
|
+
expect(time_entry.timer_started_at).to be_nil
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should reactive a time_entry' do
|
67
|
+
time_entry = harvest.time_entries.toggle(time_entry)
|
68
|
+
expect(time_entry).not_to be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'projects' do
|
73
|
+
let(:user) { create(:user) }
|
74
|
+
let(:time_entry) { create(:time_entry) }
|
75
|
+
|
76
|
+
context 'allows to add project and task' do
|
77
|
+
before do
|
78
|
+
allow(harvest.time_entries).to receive(:trackable_projects)
|
79
|
+
.and_return([])
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'returns true' do
|
83
|
+
expect(harvest.time_entries.trackable_projects(Time.now, user)).to eql([])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'harvest users' do
|
4
|
+
let(:harvest) { Harvest.client(access_token: 'mytoken', account_id: '123') }
|
5
|
+
|
6
|
+
describe 'users' do
|
7
|
+
let(:user) { create(:user) }
|
8
|
+
|
9
|
+
context 'allows to add users' do
|
10
|
+
before do
|
11
|
+
allow(harvest.users).to receive(:create).and_return(user)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns true' do
|
15
|
+
expect(user.id).not_to be_nil
|
16
|
+
expect(user.first_name).to eql('Edgar')
|
17
|
+
expect(user.last_name).to eql('Ruth')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'allows to update users' do
|
22
|
+
before do
|
23
|
+
allow(harvest.users).to receive(:update).and_return(user)
|
24
|
+
user.first_name = 'Joey'
|
25
|
+
user = harvest.users.update(user)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns true' do
|
29
|
+
expect(user.first_name).to eql('Joey')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'allows to remove users' do
|
34
|
+
before do
|
35
|
+
allow(harvest.users).to receive(:delete).and_return([])
|
36
|
+
allow(harvest.users).to receive(:all).and_return([])
|
37
|
+
harvest.users.delete(user)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns true' do
|
41
|
+
expect(harvest.users.all.select do |u|
|
42
|
+
u.first_name == 'Joey'
|
43
|
+
end).to eql([])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'allows activating and deactivating users' do
|
48
|
+
let(:user) { create(:user, :active) }
|
49
|
+
|
50
|
+
before do
|
51
|
+
allow(harvest.users).to receive(:update)
|
52
|
+
.and_return(user)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should be active' do
|
56
|
+
expect(user).to be_active
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should be deactive' do
|
60
|
+
user.is_active = false
|
61
|
+
user = harvest.users.update(user)
|
62
|
+
expect(user).not_to be_active
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should reactive a user' do
|
66
|
+
user.is_active = true
|
67
|
+
user = harvest.users.update(user)
|
68
|
+
expect(user).to be_active
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Harvest::BasicAuthCredentials do
|
4
|
+
context '#set_authentication' do
|
5
|
+
it 'should set the headers Authorization' do
|
6
|
+
credentials = Harvest::BasicAuthCredentials.new(access_token: 'mytoken', account_id: '1')
|
7
|
+
credentials.set_authentication(options = {})
|
8
|
+
|
9
|
+
expect(options[:headers]['Authorization']).to eql('Bearer mytoken')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Harvest::Expense do
|
4
|
+
it_behaves_like 'a json sanitizer', %w(cache_version)
|
5
|
+
|
6
|
+
describe "#spent_date" do
|
7
|
+
it "should parse strings" do
|
8
|
+
date = RUBY_VERSION =~ /1.8/ ? "12/01/2009" : "01/12/2009"
|
9
|
+
expense = Harvest::Expense.new(:spent_date => date)
|
10
|
+
expense.spent_date.should == Date.parse(date)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should accept times" do
|
14
|
+
expense = Harvest::Expense.new(:spent_date => Time.utc(2009, 12, 1))
|
15
|
+
expense.spent_date.should == Date.new(2009, 12, 1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Harvest::OAuthCredentials do
|
4
|
+
context '#set_authentication' do
|
5
|
+
it "should set the access token in the query" do
|
6
|
+
credentials = Harvest::OAuthCredentials.new(access_token: 'theaccesstoken')
|
7
|
+
credentials.set_authentication(options = {})
|
8
|
+
options[:query]['access_token'].should == 'theaccesstoken'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Harvest::TimeEntry do
|
4
|
+
context '#as_json' do
|
5
|
+
it 'builds a specialized hash' do
|
6
|
+
entry = Harvest::TimeEntry.new(:notes => 'the notes', :project_id => 'the project id', :task_id => 'the task id', :hours => 'the hours', :spent_date => Time.utc(2009, 12, 28))
|
7
|
+
entry.as_json.should == {"notes" => "the notes", "hours" => "the hours", "project_id" => "the project id", "task_id" => "the task id", "spent_date" => "2009-12-28"}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context "#spent_date" do
|
12
|
+
it "should parse strings" do
|
13
|
+
date = RUBY_VERSION =~ /1.8/ ? "12/01/2009" : "01/12/2009"
|
14
|
+
entry = Harvest::TimeEntry.new(:spent_date => date)
|
15
|
+
entry.spent_date.should == Date.parse(date)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should accept times" do
|
19
|
+
entry = Harvest::TimeEntry.new(:spent_date => Time.utc(2009, 12, 1))
|
20
|
+
entry.spent_date.should == Date.new(2009, 12, 1)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Harvest::User do
|
4
|
+
it_behaves_like 'a json sanitizer', %w(cache_version)
|
5
|
+
|
6
|
+
describe "#timezone" do
|
7
|
+
it "should convert friendly timezone setting" do
|
8
|
+
p = Harvest::User.new(:timezone => :cst)
|
9
|
+
p.timezone.should == 'Central Time (US & Canada)'
|
10
|
+
|
11
|
+
p = Harvest::User.new(:timezone => :est)
|
12
|
+
p.timezone.should == 'Eastern Time (US & Canada)'
|
13
|
+
|
14
|
+
p = Harvest::User.new(:timezone => :mst)
|
15
|
+
p.timezone.should == 'Mountain Time (US & Canada)'
|
16
|
+
|
17
|
+
p = Harvest::User.new(:timezone => :pst)
|
18
|
+
p.timezone.should == 'Pacific Time (US & Canada)'
|
19
|
+
|
20
|
+
p = Harvest::User.new(:timezone => 'pst')
|
21
|
+
p.timezone.should == 'Pacific Time (US & Canada)'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should convert standard zones" do
|
25
|
+
p = Harvest::User.new(:timezone => 'america/chicago')
|
26
|
+
p.timezone.should == 'Central Time (US & Canada)'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should leave literal zones" do
|
30
|
+
p = Harvest::User.new(:timezone => 'Central Time (US & Canada)')
|
31
|
+
p.timezone.should == 'Central Time (US & Canada)'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|