harvested2 5.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +35 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +34 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +12 -0
  8. data/Gemfile +20 -0
  9. data/HISTORY.md +118 -0
  10. data/MIT-LICENSE +21 -0
  11. data/README.md +66 -0
  12. data/Rakefile +24 -0
  13. data/harvested2.gemspec +30 -0
  14. data/lib/ext/array.rb +52 -0
  15. data/lib/ext/date.rb +9 -0
  16. data/lib/ext/hash.rb +17 -0
  17. data/lib/ext/time.rb +5 -0
  18. data/lib/harvest/account.rb +13 -0
  19. data/lib/harvest/api/account.rb +25 -0
  20. data/lib/harvest/api/base.rb +72 -0
  21. data/lib/harvest/api/clients.rb +10 -0
  22. data/lib/harvest/api/company.rb +12 -0
  23. data/lib/harvest/api/contacts.rb +9 -0
  24. data/lib/harvest/api/expense_categories.rb +9 -0
  25. data/lib/harvest/api/expenses.rb +26 -0
  26. data/lib/harvest/api/invoice_categories.rb +9 -0
  27. data/lib/harvest/api/invoice_messages.rb +86 -0
  28. data/lib/harvest/api/invoice_payments.rb +41 -0
  29. data/lib/harvest/api/invoices.rb +9 -0
  30. data/lib/harvest/api/projects.rb +9 -0
  31. data/lib/harvest/api/task_assignments.rb +75 -0
  32. data/lib/harvest/api/tasks.rb +9 -0
  33. data/lib/harvest/api/time_entry.rb +19 -0
  34. data/lib/harvest/api/user_assignments.rb +75 -0
  35. data/lib/harvest/api/users.rb +10 -0
  36. data/lib/harvest/base.rb +333 -0
  37. data/lib/harvest/behavior/activatable.rb +31 -0
  38. data/lib/harvest/behavior/crud.rb +80 -0
  39. data/lib/harvest/client.rb +23 -0
  40. data/lib/harvest/company.rb +8 -0
  41. data/lib/harvest/contact.rb +20 -0
  42. data/lib/harvest/credentials.rb +34 -0
  43. data/lib/harvest/errors.rb +27 -0
  44. data/lib/harvest/expense.rb +54 -0
  45. data/lib/harvest/expense_category.rb +10 -0
  46. data/lib/harvest/hardy_client.rb +80 -0
  47. data/lib/harvest/invoice.rb +75 -0
  48. data/lib/harvest/invoice_category.rb +8 -0
  49. data/lib/harvest/invoice_message.rb +8 -0
  50. data/lib/harvest/invoice_payment.rb +8 -0
  51. data/lib/harvest/line_item.rb +21 -0
  52. data/lib/harvest/model.rb +133 -0
  53. data/lib/harvest/project.rb +41 -0
  54. data/lib/harvest/receipt.rb +12 -0
  55. data/lib/harvest/task.rb +21 -0
  56. data/lib/harvest/task_assignment.rb +27 -0
  57. data/lib/harvest/time_entry.rb +57 -0
  58. data/lib/harvest/timezones.rb +130 -0
  59. data/lib/harvest/user.rb +58 -0
  60. data/lib/harvest/user_assignment.rb +27 -0
  61. data/lib/harvest/version.rb +3 -0
  62. data/lib/harvested2.rb +96 -0
  63. data/spec/factories/client.rb +14 -0
  64. data/spec/factories/contact.rb +8 -0
  65. data/spec/factories/expense.rb +10 -0
  66. data/spec/factories/expenses_category.rb +7 -0
  67. data/spec/factories/invoice.rb +25 -0
  68. data/spec/factories/invoice_category.rb +5 -0
  69. data/spec/factories/invoice_message.rb +9 -0
  70. data/spec/factories/invoice_payment.rb +7 -0
  71. data/spec/factories/line_item.rb +9 -0
  72. data/spec/factories/project.rb +15 -0
  73. data/spec/factories/task.rb +8 -0
  74. data/spec/factories/task_assignment.rb +8 -0
  75. data/spec/factories/time_entry.rb +13 -0
  76. data/spec/factories/user.rb +19 -0
  77. data/spec/factories/user_assigment.rb +7 -0
  78. data/spec/functional/clients_spec.rb +105 -0
  79. data/spec/functional/errors_spec.rb +42 -0
  80. data/spec/functional/expenses_spec.rb +97 -0
  81. data/spec/functional/invoice_messages_spec.rb +48 -0
  82. data/spec/functional/invoice_payments_spec.rb +51 -0
  83. data/spec/functional/invoice_spec.rb +138 -0
  84. data/spec/functional/project_spec.rb +76 -0
  85. data/spec/functional/tasks_spec.rb +119 -0
  86. data/spec/functional/time_entries_spec.rb +87 -0
  87. data/spec/functional/users_spec.rb +72 -0
  88. data/spec/harvest/base_spec.rb +10 -0
  89. data/spec/harvest/basic_auth_credentials_spec.rb +12 -0
  90. data/spec/harvest/expense_category_spec.rb +5 -0
  91. data/spec/harvest/expense_spec.rb +18 -0
  92. data/spec/harvest/invoice_message_spec.rb +5 -0
  93. data/spec/harvest/invoice_payment_spec.rb +5 -0
  94. data/spec/harvest/invoice_spec.rb +5 -0
  95. data/spec/harvest/oauth_credentials_spec.rb +11 -0
  96. data/spec/harvest/project_spec.rb +5 -0
  97. data/spec/harvest/task_assignment_spec.rb +5 -0
  98. data/spec/harvest/task_spec.rb +5 -0
  99. data/spec/harvest/time_entry_spec.rb +23 -0
  100. data/spec/harvest/user_assignment_spec.rb +5 -0
  101. data/spec/harvest/user_spec.rb +34 -0
  102. data/spec/spec_helper.rb +22 -0
  103. data/spec/support/factory_bot.rb +5 -0
  104. data/spec/support/harvested_helpers.rb +28 -0
  105. data/spec/support/json_examples.rb +9 -0
  106. 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,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::Base do
4
+ describe 'username/password errors' do
5
+ it 'should raise error if missing credentials' do
6
+ lambda { Harvest::Base.new }
7
+ .should raise_error(/must provide either/i)
8
+ end
9
+ end
10
+ 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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::ExpenseCategory do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ 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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::InvoiceMessage do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::InvoicePayment do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::Invoice do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ 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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::Project do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::TaskAssignment do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::Task do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ 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,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Harvest::UserAssignment do
4
+ it_behaves_like 'a json sanitizer', %w(cache_version)
5
+ 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