Skip to content

Commit d7df4c6

Browse files
feat(harvest): upgrade SDK to 2.0.0, add pytest unit tests (#276)
* feat(harvest): upgrade SDK to 2.0.0, add pytest unit tests - Bump autohive-integrations-sdk pin to ~=2.0.0 - Update all context.fetch() return values to access .data - Convert all error returns from bare dicts to ActionError(message=...) - Convert all success returns to ActionResult(data={...}, cost_usd=0.0) - Import ActionResult, ActionError from SDK - Remove 'error' and 'success' fields from output schemas in config.json - Bump config.json version to 2.0.0 - Add harvest/tests/conftest.py, __init__.py, test_harvest_unit.py - 42 unit tests covering all 10 actions (happy path, request verification, error paths, edge cases) * fix(harvest): fix optional params to use .get(), add pytest tests, integration tests - Replace all optional inputs["param"] bracket access with inputs.get("param") to prevent KeyError when optional params are not provided (fixes 43 warnings) - Add harvest/tests/test_harvest_integration.py with real HTTP tests for list_time_entries, list_projects, list_clients, list_tasks, list_users - Delete old manual-run test_harvest.py (replaced by unit + integration tests) - Update conftest.py to insert parent dir into sys.path - Add HARVEST_ACCESS_TOKEN and HARVEST_ACCOUNT_ID to .env.example * test(harvest): modernize live test fixtures * test(harvest): document live test token setup * fix(harvest): allow null pagination fields in output schema; expand integration tests to all 10 actions * test(harvest): rewrite destructive fixture to use live_context.fetch temp_project_and_task now creates client/project/task/assignment through the authenticated live_context.fetch rather than a raw aiohttp session, which was returning 401 due to missing auth headers. * test(harvest): fix live test assertions and token/account setup * style(harvest): fix E501 lint errors and ruff formatting in integration tests * style(harvest): reformat with line-length=120 per tooling ruff config --------- Co-authored-by: Shubhank <72601061+Sagsgit@users.noreply.github.com> Co-authored-by: Kai Koenig <kai@ventego-creative.co.nz>
1 parent c8020c2 commit d7df4c6

9 files changed

Lines changed: 1010 additions & 603 deletions

File tree

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
# -- App Business Reviews --
8181
# APP_BUSINESS_REVIEWS_API_KEY=
8282

83+
# -- Harvest --
84+
# HARVEST_ACCESS_TOKEN=
85+
# HARVEST_ACCOUNT_ID=
86+
8387
# -- Gong --
8488
# GONG_ACCESS_KEY=
8589
# GONG_ACCESS_KEY_SECRET=

harvest/config.json

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "Harvest",
33
"display_name": "Harvest",
4-
"version": "0.1.0",
4+
"version": "2.0.0",
55
"description": "Harvest time tracking integration for managing time entries, projects, clients, tasks, and invoices.",
66
"entry_point": "harvest.py",
77
"auth": {
@@ -63,9 +63,7 @@
6363
"output_schema": {
6464
"type": "object",
6565
"properties": {
66-
"success": {"type": "boolean"},
67-
"time_entry": {"type": "object"},
68-
"error": {"type": "string"}
66+
"time_entry": {"type": "object"}
6967
}
7068
}
7169
},
@@ -85,9 +83,7 @@
8583
"output_schema": {
8684
"type": "object",
8785
"properties": {
88-
"success": {"type": "boolean"},
89-
"time_entry": {"type": "object"},
90-
"error": {"type": "string"}
86+
"time_entry": {"type": "object"}
9187
}
9288
}
9389
},
@@ -150,16 +146,14 @@
150146
"output_schema": {
151147
"type": "object",
152148
"properties": {
153-
"success": {"type": "boolean"},
154149
"time_entries": {"type": "array"},
155-
"per_page": {"type": "integer"},
156-
"total_pages": {"type": "integer"},
157-
"total_entries": {"type": "integer"},
150+
"per_page": {"type": ["integer", "null"]},
151+
"total_pages": {"type": ["integer", "null"]},
152+
"total_entries": {"type": ["integer", "null"]},
158153
"next_page": {"type": ["integer", "null"]},
159154
"previous_page": {"type": ["integer", "null"]},
160-
"page": {"type": "integer"},
161-
"links": {"type": "object"},
162-
"error": {"type": "string"}
155+
"page": {"type": ["integer", "null"]},
156+
"links": {"type": ["object", "null"]}
163157
}
164158
}
165159
},
@@ -212,9 +206,7 @@
212206
"output_schema": {
213207
"type": "object",
214208
"properties": {
215-
"success": {"type": "boolean"},
216-
"time_entry": {"type": "object"},
217-
"error": {"type": "string"}
209+
"time_entry": {"type": "object"}
218210
}
219211
}
220212
},
@@ -234,9 +226,7 @@
234226
"output_schema": {
235227
"type": "object",
236228
"properties": {
237-
"success": {"type": "boolean"},
238-
"message": {"type": "string"},
239-
"error": {"type": "string"}
229+
"message": {"type": "string"}
240230
}
241231
}
242232
},
@@ -273,16 +263,14 @@
273263
"output_schema": {
274264
"type": "object",
275265
"properties": {
276-
"success": {"type": "boolean"},
277266
"projects": {"type": "array"},
278-
"per_page": {"type": "integer"},
279-
"total_pages": {"type": "integer"},
280-
"total_entries": {"type": "integer"},
267+
"per_page": {"type": ["integer", "null"]},
268+
"total_pages": {"type": ["integer", "null"]},
269+
"total_entries": {"type": ["integer", "null"]},
281270
"next_page": {"type": ["integer", "null"]},
282271
"previous_page": {"type": ["integer", "null"]},
283-
"page": {"type": "integer"},
284-
"links": {"type": "object"},
285-
"error": {"type": "string"}
272+
"page": {"type": ["integer", "null"]},
273+
"links": {"type": ["object", "null"]}
286274
}
287275
}
288276
},
@@ -302,9 +290,7 @@
302290
"output_schema": {
303291
"type": "object",
304292
"properties": {
305-
"success": {"type": "boolean"},
306-
"project": {"type": "object"},
307-
"error": {"type": "string"}
293+
"project": {"type": "object"}
308294
}
309295
}
310296
},
@@ -337,16 +323,14 @@
337323
"output_schema": {
338324
"type": "object",
339325
"properties": {
340-
"success": {"type": "boolean"},
341326
"clients": {"type": "array"},
342-
"per_page": {"type": "integer"},
343-
"total_pages": {"type": "integer"},
344-
"total_entries": {"type": "integer"},
327+
"per_page": {"type": ["integer", "null"]},
328+
"total_pages": {"type": ["integer", "null"]},
329+
"total_entries": {"type": ["integer", "null"]},
345330
"next_page": {"type": ["integer", "null"]},
346331
"previous_page": {"type": ["integer", "null"]},
347-
"page": {"type": "integer"},
348-
"links": {"type": "object"},
349-
"error": {"type": "string"}
332+
"page": {"type": ["integer", "null"]},
333+
"links": {"type": ["object", "null"]}
350334
}
351335
}
352336
},
@@ -379,16 +363,14 @@
379363
"output_schema": {
380364
"type": "object",
381365
"properties": {
382-
"success": {"type": "boolean"},
383366
"tasks": {"type": "array"},
384-
"per_page": {"type": "integer"},
385-
"total_pages": {"type": "integer"},
386-
"total_entries": {"type": "integer"},
367+
"per_page": {"type": ["integer", "null"]},
368+
"total_pages": {"type": ["integer", "null"]},
369+
"total_entries": {"type": ["integer", "null"]},
387370
"next_page": {"type": ["integer", "null"]},
388371
"previous_page": {"type": ["integer", "null"]},
389-
"page": {"type": "integer"},
390-
"links": {"type": "object"},
391-
"error": {"type": "string"}
372+
"page": {"type": ["integer", "null"]},
373+
"links": {"type": ["object", "null"]}
392374
}
393375
}
394376
},
@@ -421,18 +403,17 @@
421403
"output_schema": {
422404
"type": "object",
423405
"properties": {
424-
"success": {"type": "boolean"},
425406
"users": {"type": "array"},
426-
"per_page": {"type": "integer"},
427-
"total_pages": {"type": "integer"},
428-
"total_entries": {"type": "integer"},
407+
"per_page": {"type": ["integer", "null"]},
408+
"total_pages": {"type": ["integer", "null"]},
409+
"total_entries": {"type": ["integer", "null"]},
429410
"next_page": {"type": ["integer", "null"]},
430411
"previous_page": {"type": ["integer", "null"]},
431-
"page": {"type": "integer"},
432-
"links": {"type": "object"},
433-
"error": {"type": "string"}
412+
"page": {"type": ["integer", "null"]},
413+
"links": {"type": ["object", "null"]}
434414
}
435415
}
436416
}
437417
}
438418
}
419+

0 commit comments

Comments
 (0)