harvested 0.3.3 → 0.4.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.
- data/Gemfile +15 -0
- data/HISTORY +11 -0
- data/README.md +14 -6
- data/Rakefile +13 -31
- data/TODO +2 -0
- data/VERSION +1 -1
- data/examples/user_assignments.rb +1 -1
- data/harvested.gemspec +114 -126
- 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/api/account.rb +8 -1
- data/lib/harvest/api/base.rb +32 -10
- data/lib/harvest/api/contacts.rb +1 -1
- data/lib/harvest/api/expenses.rb +3 -4
- data/lib/harvest/api/invoice_categories.rb +26 -0
- data/lib/harvest/api/invoices.rb +16 -0
- data/lib/harvest/api/projects.rb +2 -10
- data/lib/harvest/api/reports.rb +13 -16
- data/lib/harvest/api/task_assignments.rb +8 -6
- data/lib/harvest/api/tasks.rb +1 -1
- data/lib/harvest/api/time.rb +13 -13
- data/lib/harvest/api/user_assignments.rb +7 -5
- data/lib/harvest/base.rb +9 -1
- data/lib/harvest/behavior/activatable.rb +2 -2
- data/lib/harvest/behavior/crud.rb +15 -13
- data/lib/harvest/client.rb +18 -13
- data/lib/harvest/contact.rb +13 -11
- data/lib/harvest/errors.rb +6 -4
- data/lib/harvest/expense.rb +40 -14
- data/lib/harvest/expense_category.rb +10 -9
- data/lib/harvest/hardy_client.rb +1 -1
- data/lib/harvest/invoice.rb +103 -0
- data/lib/harvest/invoice_category.rb +18 -0
- data/lib/harvest/line_item.rb +12 -0
- data/lib/harvest/model.rb +120 -0
- data/lib/harvest/project.rb +55 -26
- data/lib/harvest/rate_limit_status.rb +9 -8
- data/lib/harvest/task.rb +17 -14
- data/lib/harvest/task_assignment.rb +27 -22
- data/lib/harvest/time_entry.rb +32 -30
- data/lib/harvest/user.rb +46 -22
- data/lib/harvest/user_assignment.rb +24 -17
- data/lib/harvested.rb +12 -5
- data/spec/functional/account_spec.rb +17 -0
- data/spec/functional/clients_spec.rb +58 -0
- data/spec/functional/errors_spec.rb +22 -0
- data/spec/functional/expenses_spec.rb +84 -0
- data/spec/functional/hardy_client_spec.rb +33 -0
- data/spec/functional/invoice_spec.rb +67 -0
- data/spec/functional/project_spec.rb +50 -0
- data/spec/functional/reporting_spec.rb +80 -0
- data/spec/functional/tasks_spec.rb +88 -0
- data/spec/functional/time_tracking_spec.rb +53 -0
- data/spec/functional/users_spec.rb +102 -0
- data/spec/harvest/base_spec.rb +1 -1
- data/spec/harvest/credentials_spec.rb +1 -1
- data/spec/harvest/expense_category_spec.rb +5 -0
- data/spec/harvest/expense_spec.rb +8 -5
- data/spec/harvest/invoice_spec.rb +47 -0
- data/spec/harvest/project_spec.rb +11 -0
- data/spec/harvest/task_assignment_spec.rb +4 -4
- data/spec/harvest/task_spec.rb +7 -0
- data/spec/harvest/time_entry_spec.rb +11 -10
- data/spec/harvest/user_assignment_spec.rb +3 -3
- data/spec/harvest/user_spec.rb +3 -1
- data/spec/spec_helper.rb +37 -6
- data/{features → spec}/support/harvest_credentials.example.yml +0 -1
- data/spec/support/harvested_helpers.rb +44 -0
- data/spec/support/json_examples.rb +11 -0
- data/spec/test_rubies +5 -0
- metadata +109 -85
- data/.gitignore +0 -28
- data/features/account.feature +0 -7
- data/features/client_contacts.feature +0 -23
- data/features/clients.feature +0 -29
- data/features/errors.feature +0 -25
- data/features/expense_categories.feature +0 -21
- data/features/expenses.feature +0 -55
- data/features/hardy_client.feature +0 -40
- data/features/projects.feature +0 -39
- data/features/reporting.feature +0 -72
- data/features/step_definitions/account_steps.rb +0 -7
- data/features/step_definitions/assignment_steps.rb +0 -100
- data/features/step_definitions/contact_steps.rb +0 -11
- data/features/step_definitions/debug_steps.rb +0 -3
- data/features/step_definitions/error_steps.rb +0 -113
- data/features/step_definitions/expenses_steps.rb +0 -46
- data/features/step_definitions/harvest_steps.rb +0 -8
- data/features/step_definitions/model_steps.rb +0 -90
- data/features/step_definitions/people_steps.rb +0 -4
- data/features/step_definitions/report_steps.rb +0 -91
- data/features/step_definitions/time_entry_steps.rb +0 -40
- data/features/support/env.rb +0 -37
- data/features/support/error_helpers.rb +0 -18
- data/features/support/fixtures/empty_clients.xml +0 -2
- data/features/support/fixtures/over_limit.xml +0 -8
- data/features/support/fixtures/receipt.png +0 -0
- data/features/support/fixtures/under_limit.xml +0 -8
- data/features/support/harvest_helpers.rb +0 -11
- data/features/support/inflections.rb +0 -9
- data/features/task_assignment.feature +0 -69
- data/features/tasks.feature +0 -25
- data/features/time_tracking.feature +0 -29
- data/features/user_assignments.feature +0 -33
- data/features/users.feature +0 -55
- data/lib/harvest/base_model.rb +0 -73
- data/spec/spec.default.opts +0 -1
data/features/clients.feature
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
@clean
|
2
|
-
Feature: Managing Clients
|
3
|
-
|
4
|
-
Scenario: Adding, Updating, and Removing a Client
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
When I create a client with the following:
|
7
|
-
| name | Client |
|
8
|
-
| details | Building API Widgets across the country |
|
9
|
-
Then there should be a client "Client"
|
10
|
-
When I update the client "Client" with the following:
|
11
|
-
| name | Updated Client |
|
12
|
-
| details | Building API Widgets in the Midwest |
|
13
|
-
Then the client "Updated Client" should have the following attributes:
|
14
|
-
| details | Building API Widgets in the Midwest |
|
15
|
-
When I delete the client "Updated Client"
|
16
|
-
Then there should not be a client "Updated Client"
|
17
|
-
|
18
|
-
Scenario: Activating and Deactivating a Client
|
19
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
20
|
-
When I create a client with the following:
|
21
|
-
| name | Client |
|
22
|
-
| details | Building API Widgets across the country |
|
23
|
-
Then the client "Client" should be activated
|
24
|
-
When I deactivate the client "Client"
|
25
|
-
Then the client "Client" should be deactivated
|
26
|
-
When I activate the client "Client"
|
27
|
-
Then the client "Client" should be activated
|
28
|
-
Then I delete the client "Client"
|
29
|
-
|
data/features/errors.feature
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
@disconnected
|
2
|
-
Feature: Handling Harvest Errors
|
3
|
-
|
4
|
-
Scenario: Raising Bad Responses
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
|
7
|
-
Given the next request will receive a bad request response
|
8
|
-
When I make a request with the standard client
|
9
|
-
Then a 400 error should be raised
|
10
|
-
|
11
|
-
Given the next request will receive a not found response
|
12
|
-
When I make a request with the standard client
|
13
|
-
Then a 404 error should be raised
|
14
|
-
|
15
|
-
Given the next request will receive a bad gateway response
|
16
|
-
When I make a request with the standard client
|
17
|
-
Then a 502 error should be raised
|
18
|
-
|
19
|
-
Given the next request will receive a server error response
|
20
|
-
When I make a request with the standard client
|
21
|
-
Then a 500 error should be raised
|
22
|
-
|
23
|
-
Given the next request will receive a rate limit response
|
24
|
-
When I make a request with the standard client
|
25
|
-
Then a 503 error should be raised
|
@@ -1,21 +0,0 @@
|
|
1
|
-
@clean
|
2
|
-
Feature: Expense Categories
|
3
|
-
|
4
|
-
Scenario: Adding, Updating, and Removing an Expense Category
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
When I create an expense category with the following:
|
7
|
-
| name | Mileage |
|
8
|
-
| unit_name | Miles |
|
9
|
-
| unit_price | 0.485 |
|
10
|
-
Then there should be an expense category "Mileage"
|
11
|
-
When I update the expense category "Mileage" with the following:
|
12
|
-
| unit_name | Kilometers |
|
13
|
-
| deactivated | true |
|
14
|
-
| unit_price | 1.2 |
|
15
|
-
Then the expense category "Mileage" should have the following attributes:
|
16
|
-
| unit_name | Kilometers |
|
17
|
-
| unit_price | 1.2 |
|
18
|
-
| deactivated | true |
|
19
|
-
| active? | false |
|
20
|
-
When I delete the expense category "Mileage"
|
21
|
-
Then there should not be an expense category "Mileage"
|
data/features/expenses.feature
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
@clean
|
2
|
-
Feature: Expenses
|
3
|
-
|
4
|
-
Scenario: Adding, Updating, and Removing an Expenses
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
When I create an expense category with the following:
|
7
|
-
| name | Mileage |
|
8
|
-
| unit_name | Miles |
|
9
|
-
| unit_price | 0.485 |
|
10
|
-
Then there should be an expense category "Mileage"
|
11
|
-
When I create a client with the following:
|
12
|
-
| name | Expense Client |
|
13
|
-
When I create a project for the client "Expense Client" with the following:
|
14
|
-
| name | Test Project |
|
15
|
-
When I create an expense for the project "Test Project" with the category "Mileage" with the following:
|
16
|
-
| notes | Drive to Chicago |
|
17
|
-
| total_cost | 75.00 |
|
18
|
-
| spent_at | 12/28/2009 |
|
19
|
-
Then there should be an expense "Drive to Chicago" on "12/28/2009"
|
20
|
-
And the expense "Drive to Chicago" on "12/28/2009" should have the following attributes:
|
21
|
-
| total_cost | 75.0 |
|
22
|
-
| units | 1 |
|
23
|
-
When I update the expense "Drive to Chicago" on "12/28/2009" with the following:
|
24
|
-
| total_cost | 50 |
|
25
|
-
Then the expense "Drive to Chicago" on "12/28/2009" should have the following attributes:
|
26
|
-
| total_cost | 50.0 |
|
27
|
-
| units | 1 |
|
28
|
-
When I update the expense "Drive to Chicago" on "12/28/2009" with the following:
|
29
|
-
| total_cost | |
|
30
|
-
| units | 3 |
|
31
|
-
Then the expense "Drive to Chicago" on "12/28/2009" should have the following attributes:
|
32
|
-
| total_cost | 1.46 |
|
33
|
-
| units | 3 |
|
34
|
-
When I delete the expense "Drive to Chicago" on "12/28/2009"
|
35
|
-
Then there should not be an expense "Drive to Chicago" on "12/28/2009"
|
36
|
-
|
37
|
-
@wip
|
38
|
-
Scenario: Attaching a receipt to an Expense
|
39
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
40
|
-
When I create an expense category with the following:
|
41
|
-
| name | Mileage |
|
42
|
-
| unit_name | Miles |
|
43
|
-
| unit_price | 0.485 |
|
44
|
-
Then there should be an expense category "Mileage"
|
45
|
-
When I create a client with the following:
|
46
|
-
| name | Expense Client |
|
47
|
-
When I create a project for the client "Expense Client" with the following:
|
48
|
-
| name | Test Project |
|
49
|
-
When I create an expense for the project "Test Project" with the category "Mileage" with the following:
|
50
|
-
| notes | Drive to Chicago |
|
51
|
-
| total_cost | 75.00 |
|
52
|
-
| spent_at | 12/28/2009 |
|
53
|
-
Then there should be an expense "Drive to Chicago" on "12/28/2009"
|
54
|
-
When I attach the receipt "./support/fixtures/receipt.png" to the expense "Drive to Chicago" on "12/28/2009"
|
55
|
-
Then there should be a receipt "./support/fixtures/receipt.png" attached to the expense "Drive to Chicago" on "12/28/2009"
|
@@ -1,40 +0,0 @@
|
|
1
|
-
@disconnected
|
2
|
-
Feature: Hardy Client
|
3
|
-
|
4
|
-
Background:
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
And the rate limit status indicates I'm under my limit
|
7
|
-
|
8
|
-
Scenario: Hardy Client waiting for Rate Limit resets
|
9
|
-
Given the next request will receive a rate limit response with a refresh in 5 seconds
|
10
|
-
When I make a request with the hardy client
|
11
|
-
Then the hardy client should wait 5 seconds for the rate limit to reset
|
12
|
-
And I should be able to make a request again
|
13
|
-
|
14
|
-
Scenario: Hardy Client waiting for Rate Limit resets
|
15
|
-
Given the next request will receive a rate limit response without a refresh set
|
16
|
-
When I make a request with the hardy client
|
17
|
-
Then the hardy client should wait 16 seconds for the rate limit to reset
|
18
|
-
And I should be able to make a request again
|
19
|
-
|
20
|
-
Scenario: Hardy Client retrying Bad Gateway responses
|
21
|
-
Given the next 2 requests will receive a bad gateway response
|
22
|
-
When I make a request with the hardy client
|
23
|
-
Then no errors should be raised
|
24
|
-
|
25
|
-
Scenario: Hardy Client retrying HTTP Errors
|
26
|
-
Given the next 2 requests will receive an HTTP Error
|
27
|
-
When I make a request with the hardy client
|
28
|
-
Then no errors should be raised
|
29
|
-
|
30
|
-
Scenario: Hardy Client stop retrying Bad Gateway responses
|
31
|
-
Given the next 6 requests will receive a bad gateway response
|
32
|
-
When I make a request with the hardy client
|
33
|
-
Then a 502 error should be raised
|
34
|
-
|
35
|
-
Scenario: Check rate limit before retrying bad gateway requests
|
36
|
-
Given the next request will receive a bad gateway response
|
37
|
-
And the rate limit status indicates I'm over my limit
|
38
|
-
When I make a request with the hardy client
|
39
|
-
Then the hardy client should wait 16 seconds for the rate limit to reset
|
40
|
-
And I should be able to make a request again
|
data/features/projects.feature
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
@clean
|
2
|
-
Feature: Managing Projects
|
3
|
-
|
4
|
-
Scenario: Adding, Updating, and Removing a Project
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
When I create a client with the following:
|
7
|
-
| name | Client Projects |
|
8
|
-
| details | Building API Widgets across the country |
|
9
|
-
When I create a project for the client "Client Projects" with the following:
|
10
|
-
| name | Test Project |
|
11
|
-
| active | true |
|
12
|
-
| notes | project to test the api |
|
13
|
-
Then there should be a project "Test Project"
|
14
|
-
When I update the project "Test Project" with the following:
|
15
|
-
| name | Updated Project |
|
16
|
-
| code | new-code |
|
17
|
-
| bill_by | Project |
|
18
|
-
| hourly_rate | 150 |
|
19
|
-
Then the project "Updated Project" should have the following attributes:
|
20
|
-
| code | new-code |
|
21
|
-
| bill_by | Project |
|
22
|
-
| hourly_rate | 150.0 |
|
23
|
-
When I delete the project "Updated Project"
|
24
|
-
Then there should not be a project "Updated Project"
|
25
|
-
|
26
|
-
Scenario: Activating and Deactivating a Project
|
27
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
28
|
-
And I create a client with the following:
|
29
|
-
| name | Client Projects |
|
30
|
-
| details | Building API Widgets across the country |
|
31
|
-
And I create a project for the client "Client Projects" with the following:
|
32
|
-
| name | Test Project |
|
33
|
-
| active | true |
|
34
|
-
| notes | project to test the api |
|
35
|
-
Then the project "Test Project" should be activated
|
36
|
-
When I deactivate the project "Test Project"
|
37
|
-
Then the project "Test Project" should be deactivated
|
38
|
-
When I activate the project "Test Project"
|
39
|
-
Then the project "Test Project" should be activated
|
data/features/reporting.feature
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
@clean
|
2
|
-
Feature: Harvest Reporting
|
3
|
-
|
4
|
-
Background:
|
5
|
-
Given I am using the credentials from "./support/harvest_credentials.yml"
|
6
|
-
And I create a client with the following:
|
7
|
-
| name | Report Client |
|
8
|
-
| details | Client to run reports |
|
9
|
-
And I create a project for the client "Report Client" with the following:
|
10
|
-
| name | Report Project1 |
|
11
|
-
And I create a project for the client "Report Client" with the following:
|
12
|
-
| name | Report Project2 |
|
13
|
-
|
14
|
-
Scenario: Time Entry Reporting
|
15
|
-
Given I create a task with the following:
|
16
|
-
| name | Report Task |
|
17
|
-
| billable | true |
|
18
|
-
| hourly_rate | 120 |
|
19
|
-
And I assign the task "Report Task" to the project "Report Project1"
|
20
|
-
And I assign the task "Report Task" to the project "Report Project2"
|
21
|
-
And I create a time entry for the project "Report Project1" and the task "Report Task" with the following:
|
22
|
-
| notes | project1 time |
|
23
|
-
| hours | 2.0 |
|
24
|
-
| spent_at | 12/28/2009 |
|
25
|
-
And I create a time entry for the project "Report Project2" and the task "Report Task" with the following:
|
26
|
-
| notes | project2 time |
|
27
|
-
| hours | 2.0 |
|
28
|
-
| spent_at | 12/28/2009 |
|
29
|
-
When I run a project report for "Report Project1" for "12/20/2009" and "12/30/2009" the following entries should be returned:
|
30
|
-
| project1 time |
|
31
|
-
When I run a project report for "Report Project1" for "12/20/2009" and "12/30/2009" the following entries should not be returned:
|
32
|
-
| project2 time |
|
33
|
-
When I run a a project report for "Report Project1" for "12/20/2009" and "12/30/2009" filtered by my user the following entries should be returned:
|
34
|
-
| project1 time |
|
35
|
-
When I run a a project report for "Report Project1" for "12/20/2009" and "12/30/2009" filtered by my user the following entries should not be returned:
|
36
|
-
| project2 time |
|
37
|
-
When I run a people report for my user for "12/20/2009" and "12/30/2009" the following entries should be returned:
|
38
|
-
| project1 time |
|
39
|
-
| project2 time |
|
40
|
-
|
41
|
-
@wip
|
42
|
-
Scenario: People Reports filtered by Project
|
43
|
-
Given I create a task with the following:
|
44
|
-
| name | Report Task |
|
45
|
-
| billable | true |
|
46
|
-
| hourly_rate | 120 |
|
47
|
-
And I assign the task "Report Task" to the project "Report Project1"
|
48
|
-
And I assign the task "Report Task" to the project "Report Project2"
|
49
|
-
And I create a time entry for the project "Report Project1" and the task "Report Task" with the following:
|
50
|
-
| notes | project1 time |
|
51
|
-
| hours | 2.0 |
|
52
|
-
| spent_at | 12/28/2009 |
|
53
|
-
And I create a time entry for the project "Report Project2" and the task "Report Task" with the following:
|
54
|
-
| notes | project2 time |
|
55
|
-
| hours | 2.0 |
|
56
|
-
| spent_at | 12/28/2009 |
|
57
|
-
When I run a people report for my user for "12/20/2009" and "12/30/2009" filtered by the project "Report Project1" the following entries should be returned:
|
58
|
-
| project1 time |
|
59
|
-
When I run a people report for my user for "12/20/2009" and "12/30/2009" filtered by the project "Report Project1" the following entries should not be returned:
|
60
|
-
| project2 time |
|
61
|
-
|
62
|
-
Scenario: Expenses by People
|
63
|
-
Given I create an expense category with the following:
|
64
|
-
| name | Conference |
|
65
|
-
| unit_name | Ticket |
|
66
|
-
| unit_price | 300 |
|
67
|
-
And I create an expense for the project "Report Project1" with the category "Conference" with the following:
|
68
|
-
| notes | RubyConf |
|
69
|
-
| total_cost | 300 |
|
70
|
-
| spent_at | 12/28/2009 |
|
71
|
-
When I run an expense report for my user for "12/20/2009" and "12/30/2009" the following entries should be returned:
|
72
|
-
| RubyConf |
|
@@ -1,100 +0,0 @@
|
|
1
|
-
When 'I create and assign a task "$1" to the project "$2"' do |task_name, project_name|
|
2
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
3
|
-
p = harvest_api.projects.create_task(project, task_name)
|
4
|
-
p.should == project
|
5
|
-
end
|
6
|
-
|
7
|
-
When 'I assign the task "$1" to the project "$2"' do |task_name, project_name|
|
8
|
-
task = Then %Q{there should be a task "#{task_name}"}
|
9
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
10
|
-
assignment = Harvest::TaskAssignment.new(:project => project, :task => task)
|
11
|
-
harvest_api.task_assignments.create(assignment)
|
12
|
-
end
|
13
|
-
|
14
|
-
Then 'the task "$1" should be assigned to the project "$2"' do |task_name, project_name|
|
15
|
-
task = Then %Q{there should be a task "#{task_name}"}
|
16
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
17
|
-
assignments = harvest_api.task_assignments.all(project)
|
18
|
-
assignment = assignments.detect {|a| a.project_id == project.to_i && a.task_id == task.to_i }
|
19
|
-
assignment.should_not be_nil
|
20
|
-
assignment
|
21
|
-
end
|
22
|
-
|
23
|
-
Then 'the task "$1" should not be assigned to the project "$2"' do |task_name, project_name|
|
24
|
-
task = Then %Q{there should be a task "#{task_name}"}
|
25
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
26
|
-
assignments = harvest_api.task_assignments.all(project)
|
27
|
-
assignment = assignments.detect {|a| a.project_id == project.to_i && a.task_id == task.to_i }
|
28
|
-
assignment.should be_nil
|
29
|
-
end
|
30
|
-
|
31
|
-
When 'I update the task "$1" for the project "$2" with the following:' do |task_name, project_name, table|
|
32
|
-
assignment = Then %Q{the task "#{task_name}" should be assigned to the project "#{project_name}"}
|
33
|
-
assignment.attributes = table.rows_hash
|
34
|
-
harvest_api.task_assignments.update(assignment)
|
35
|
-
end
|
36
|
-
|
37
|
-
Then 'the task "$1" for the project "$2" should have the following attributes:' do |task_name, project_name, table|
|
38
|
-
assignment = Then %Q{the task "#{task_name}" should be assigned to the project "#{project_name}"}
|
39
|
-
table.rows_hash.each do |key, value|
|
40
|
-
assignment.send(key).to_s.should == value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
When 'I remove the task "$1" from the project "$2"' do |task_name, project_name|
|
45
|
-
assignment = Then %Q{the task "#{task_name}" should be assigned to the project "#{project_name}"}
|
46
|
-
id = harvest_api.task_assignments.delete(assignment)
|
47
|
-
id.should == assignment.id
|
48
|
-
end
|
49
|
-
|
50
|
-
When 'I try to remove the task "$1" from the project "$2"' do |task_name, project_name|
|
51
|
-
assignment = Then %Q{the task "#{task_name}" should be assigned to the project "#{project_name}"}
|
52
|
-
begin
|
53
|
-
harvest_api.task_assignments.delete(assignment)
|
54
|
-
rescue Harvest::HTTPError => e
|
55
|
-
@error = e
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
When 'I assign the user "$1" to the project "$2"' do |email, project_name|
|
60
|
-
user = Then %Q{there should be a user "#{email}"}
|
61
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
62
|
-
assignment = Harvest::UserAssignment.new(:project => project, :user => user)
|
63
|
-
harvest_api.user_assignments.create(assignment)
|
64
|
-
end
|
65
|
-
|
66
|
-
When 'I remove the user "$1" from the project "$2"' do |email, project_name|
|
67
|
-
assignment = Then %Q{the user "#{email}" should be assigned to the project "#{project_name}"}
|
68
|
-
id = harvest_api.user_assignments.delete(assignment)
|
69
|
-
id.should == assignment.id
|
70
|
-
end
|
71
|
-
|
72
|
-
Then 'the user "$1" should be assigned to the project "$2"' do |email, project_name|
|
73
|
-
user = Then %Q{there should be a user "#{email}"}
|
74
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
75
|
-
assignments = harvest_api.user_assignments.all(project)
|
76
|
-
assignment = assignments.detect {|a| a.project_id == project.to_i && a.user_id == user.to_i }
|
77
|
-
assignment.should_not be_nil
|
78
|
-
assignment
|
79
|
-
end
|
80
|
-
|
81
|
-
Then 'the user "$1" should not be assigned to the project "$2"' do |email, project_name|
|
82
|
-
user = Then %Q{there should be a user "#{email}"}
|
83
|
-
project = Then %Q{there should be a project "#{project_name}"}
|
84
|
-
assignments = harvest_api.user_assignments.all(project)
|
85
|
-
assignment = assignments.detect {|a| a.project_id == project.to_i && a.user_id == user.to_i }
|
86
|
-
assignment.should be_nil
|
87
|
-
end
|
88
|
-
|
89
|
-
When 'I update the user "$1" on the project "$2" with the following:' do |email, project_name, table|
|
90
|
-
assignment = Then %Q{the user "#{email}" should be assigned to the project "#{project_name}"}
|
91
|
-
assignment.attributes = table.rows_hash
|
92
|
-
harvest_api.user_assignments.update(assignment)
|
93
|
-
end
|
94
|
-
|
95
|
-
Then 'the user "$1" on the project "$2" should have the following attributes:' do |email, project_name, table|
|
96
|
-
assignment = Then %Q{the user "#{email}" should be assigned to the project "#{project_name}"}
|
97
|
-
table.rows_hash.each do |key, value|
|
98
|
-
assignment.send(key).to_s.should == value
|
99
|
-
end
|
100
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
Then 'there should be a contact "$1" for the client "$2"' do |email, client_name|
|
2
|
-
client = Then %Q{there should be a client "#{client_name}"}
|
3
|
-
contact = Then %Q{there should be a contact "#{email}"}
|
4
|
-
contact.client_id.should == client.id
|
5
|
-
|
6
|
-
contacts = harvest_api.contacts.all(client.id)
|
7
|
-
contact2 = contacts.detect {|c| c.email == email}
|
8
|
-
contact2.should == contact
|
9
|
-
|
10
|
-
contact
|
11
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
Given /^the next request will receive a (bad request|not found|bad gateway|server error|rate limit) response$/ do |type|
|
2
|
-
statuses = {
|
3
|
-
'bad request' => ['400', 'Bad Request'],
|
4
|
-
'not found' => ['404', 'Not Found'],
|
5
|
-
'bad gateway' => ['502', 'Bad Gateway'],
|
6
|
-
'server error' => ['500', 'Server Error'],
|
7
|
-
'rate limit' => ['503', 'Rake Limited']
|
8
|
-
}
|
9
|
-
|
10
|
-
if status = statuses[type]
|
11
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
12
|
-
{:status => status, :times => 1},
|
13
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
14
|
-
])
|
15
|
-
else
|
16
|
-
pending
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
Given /^the next request will receive a rate limit response with a refresh in (\d+) seconds$/ do |seconds|
|
21
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
22
|
-
{:status => ['503', 'Rake Limited'], "Retry-After" => seconds},
|
23
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
24
|
-
])
|
25
|
-
end
|
26
|
-
|
27
|
-
Given 'the next request will receive a rate limit response without a refresh set' do
|
28
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
29
|
-
{:status => ['503', 'Rake Limited']},
|
30
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
31
|
-
])
|
32
|
-
end
|
33
|
-
|
34
|
-
When 'I make a request with the standard client' do
|
35
|
-
set_time_and_return_and_error do
|
36
|
-
standard_api.clients.all
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
When 'I make a request with the hardy client' do
|
41
|
-
set_time_and_return_and_error do
|
42
|
-
harvest_api.clients.all
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
When /^I make a request with the hardy client with (\d+) max retries$/ do |times|
|
47
|
-
set_time_and_return_and_error do
|
48
|
-
api = Harvest.hardy_client(@subdomain, @username, @password, :ssl => @ssl, :retry => times.to_i)
|
49
|
-
api.clients.all
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
Then /a (\d+) error should be raised/ do |code|
|
54
|
-
case code
|
55
|
-
when '400'
|
56
|
-
@error.should be_a(Harvest::BadRequest)
|
57
|
-
when '404'
|
58
|
-
@error.should be_a(Harvest::NotFound)
|
59
|
-
when '502'
|
60
|
-
@error.should be_a(Harvest::Unavailable)
|
61
|
-
when '500'
|
62
|
-
@error.should be_a(Harvest::ServerError)
|
63
|
-
when '503'
|
64
|
-
@error.should be_a(Harvest::RateLimited)
|
65
|
-
else
|
66
|
-
pending
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
Then /the hardy client should wait (\d+) seconds for the rate limit to reset/ do |seconds|
|
71
|
-
Time.now.should be_close(@time + seconds.to_i, 2)
|
72
|
-
end
|
73
|
-
|
74
|
-
Then 'I should be able to make a request again' do
|
75
|
-
harvest_api.clients.all
|
76
|
-
harvest_api.clients.all
|
77
|
-
end
|
78
|
-
|
79
|
-
Given /^the next (\d+) requests will receive a bad gateway response$/ do |times|
|
80
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
81
|
-
{:status => ['502', 'Bad Gateway'], :times => times.to_i},
|
82
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
83
|
-
])
|
84
|
-
end
|
85
|
-
|
86
|
-
Given /^the next (\d+) requests will receive a server error response$/ do |times|
|
87
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
88
|
-
{:status => ['500', 'Server Error'], :times => times.to_i},
|
89
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
90
|
-
])
|
91
|
-
end
|
92
|
-
|
93
|
-
Given /^the next (\d+) requests will receive an HTTP Error$/ do |times|
|
94
|
-
FakeWeb.register_uri(:get, /\/clients/, [
|
95
|
-
{:exception => Net::HTTPError, :times => times.to_i},
|
96
|
-
{:body => File.read(File.dirname(__FILE__) + '/../support/fixtures/empty_clients.xml')}
|
97
|
-
])
|
98
|
-
end
|
99
|
-
|
100
|
-
Then 'no errors should be raised' do
|
101
|
-
@error.should be_nil
|
102
|
-
@clients.should == []
|
103
|
-
end
|
104
|
-
|
105
|
-
Given 'the rate limit status indicates I\'m over my limit' do
|
106
|
-
over_limit_response = File.read(File.dirname(__FILE__) + '/../support/fixtures/over_limit.xml')
|
107
|
-
FakeWeb.register_uri(:get, /\/account\/rate_limit_status/, :body => over_limit_response)
|
108
|
-
end
|
109
|
-
|
110
|
-
Given 'the rate limit status indicates I\'m under my limit' do
|
111
|
-
over_limit_response = File.read(File.dirname(__FILE__) + '/../support/fixtures/under_limit.xml')
|
112
|
-
FakeWeb.register_uri(:get, /\/account\/rate_limit_status/, :body => over_limit_response)
|
113
|
-
end
|