Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5f931b0
test: add pytest infrastructure and unit tests for 5 integrations
TheRealAgentK Apr 16, 2026
542fcb8
style: fix ruff lint and formatting in unit tests
TheRealAgentK Apr 16, 2026
2aed826
style: reformat all files with tooling ruff.toml (line-length=120)
TheRealAgentK Apr 16, 2026
dadcaf5
fix: move nosec B105 to flagged line in notion tests
TheRealAgentK Apr 16, 2026
17eaf31
fix: suppress bandit B110 for expected try/except/pass in nzbn tests
TheRealAgentK Apr 16, 2026
803a446
fix(shopify-customer): handle SDK version differences in validation e…
TheRealAgentK Apr 16, 2026
d56ca40
fix(shopify-customer): pin SDK to ~=1.0.2 and use pytest.raises for v…
TheRealAgentK Apr 16, 2026
d196d90
fix: remove SDK from requirements-test.txt, use pytest.raises for val…
TheRealAgentK Apr 16, 2026
160256e
style: remove unused ResultType import
TheRealAgentK Apr 16, 2026
6a24020
ci: retrigger CI
TheRealAgentK Apr 16, 2026
b972487
ci: retrigger CI
Shubhank-Jonnada Apr 16, 2026
51dc803
ci: touch README to satisfy readme check
TheRealAgentK Apr 16, 2026
fbf91f0
ci: retrigger with tooling 2.0.5
TheRealAgentK Apr 16, 2026
3ca9671
chore(bitly,notion,nzbn): patch bump to 1.0.1 for formatting changes
TheRealAgentK Apr 16, 2026
7361baf
docs: update CONTRIBUTING.md with per-integration SDK install workflow
TheRealAgentK Apr 16, 2026
72438d4
feat(perplexity): port integration from private repo with security cl…
TheRealAgentK Apr 17, 2026
092285d
test(perplexity): add unit and integration tests
TheRealAgentK Apr 20, 2026
10a2f1c
refactor(perplexity): remove legacy manual test runner and context.py
TheRealAgentK Apr 20, 2026
5b502c7
test(hackernews): add e2e integration tests, remove legacy manual runner
TheRealAgentK Apr 20, 2026
5ebcee1
test(bitly): add e2e integration tests, remove legacy manual runner
TheRealAgentK Apr 20, 2026
d0cb150
docs: document unit/integration test separation in CONTRIBUTING.md an…
TheRealAgentK Apr 20, 2026
00ed5d7
ci: retrigger CI with tooling 2.0.6
TheRealAgentK Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ============================================================================
# Autohive Integrations — environment variables for integration tests
# ============================================================================
#
# Copy this file to .env and fill in values for the integrations you need
# to test against live APIs. The .env file is gitignored.
#
# Unit tests (pytest -m unit) never need these — they use mocks.
# Integration tests (pytest -m integration) will skip if the required
# variable is missing.
#
# Format: VARIABLE_NAME=value (no quotes needed)
# ============================================================================

# -- Bitly --
# BITLY_ACCESS_TOKEN=

# -- NZBN --
# NZBN_CLIENT_ID=
# NZBN_CLIENT_SECRET=
# NZBN_SUBSCRIPTION_KEY=

# -- Notion --
# NOTION_ACCESS_TOKEN=

# -- Perplexity --
# PERPLEXITY_API_KEY=

# -- Shopify Customer --
# SHOPIFY_CUSTOMER_ACCESS_TOKEN=
# SHOPIFY_CUSTOMER_SHOP_URL=

# -- Stripe --
# STRIPE_TEST_API_KEY=

# -- Zoom --
# ZOOM_ACCESS_TOKEN=

# -- Xero --
# (uses platform OAuth — tokens are short-lived, typically not set here)
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@
.idea/

*/.env
.env
.venv/
.coverage
/.agents
196 changes: 196 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,202 @@ ruff check --fix my-integration
ruff format my-integration
```

## Running Tests

Unit tests and integration tests are **run separately** — they use different file naming, markers, and discovery rules so they never interfere with each other.

| | Unit tests | Integration tests |
|---|---|---|
| **File naming** | `test_*_unit.py` | `test_*_integration.py` |
| **Marker** | `@pytest.mark.unit` | `@pytest.mark.integration` |
| **Auto-discovered** | Yes (via `python_files` in `pyproject.toml`) | No — must pass the file path explicitly |
| **Runs in CI** | Yes | No |
| **Needs credentials** | No (fully mocked) | Yes (real API calls) |
| **Default `pytest`** | ✅ Selected by `-m unit` in `addopts` | ❌ Excluded by `-m unit` in `addopts` |

Tests use [pytest](https://docs.pytest.org/) and run from the repo root. They use the same Python environment as the tooling (see [Local Validation](#local-validation) above).

### Prerequisites

Python 3.13+ is required (the SDK depends on it). Create a venv and install test dependencies:

```bash
cd autohive-integrations
uv venv --python 3.13 .venv
source .venv/bin/activate
uv pip install -r requirements-test.txt
```

Each integration pins its own SDK version in its `requirements.txt`. Install the dependencies for the integration(s) you want to test:

```bash
uv pip install -r hackernews/requirements.txt
```

If you don't have [uv](https://docs.astral.sh/uv/), you can use any Python 3.13+ interpreter directly:

```bash
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r requirements-test.txt
pip install -r hackernews/requirements.txt
```

### Running unit tests

Unit tests are mocked — no API credentials or network access needed. They are auto-discovered by pytest from `test_*_unit.py` files.

```bash
# Run unit tests for a single integration
pytest hackernews/

# Run a specific test file
pytest hackernews/tests/test_hackernews_unit.py

# Run all unit tests (only if all integrations share the same SDK version)
pytest

# Verbose output
pytest hackernews/ -v
```

If integrations pin different SDK versions, run them separately to ensure each uses its own pinned version:

```bash
uv pip install -r bitly/requirements.txt
pytest bitly/

uv pip install -r notion/requirements.txt
pytest notion/
```

The default `pytest` command only runs tests marked `unit` (configured in `pyproject.toml`).

### Running integration tests

Integration tests call real APIs and require credentials. They are **not** auto-discovered — you must pass the test file path explicitly and override the marker filter.

Set up a `.env` file in the repo root (see `.env.example` for the template):

```bash
cp .env.example .env
# Edit .env and add your test credentials
```

Then run by passing the file path directly with `-m integration`:

```bash
# Run integration tests for one integration
pytest perplexity/tests/test_perplexity_integration.py -m integration
```

> **Why the explicit file path?** `pyproject.toml` restricts `python_files` to `test_*_unit.py`, so `pytest -m integration perplexity/` will **not** discover `test_*_integration.py` files. You must name the file directly.

To run both unit and integration tests together:

```bash
pytest perplexity/tests/test_perplexity_unit.py perplexity/tests/test_perplexity_integration.py -m "unit or integration"
```

Integration tests will `pytest.skip()` if the required environment variables are missing.

### Coverage

```bash
# Coverage for a single integration (unit tests only)
pytest --cov=hackernews hackernews/

# Coverage for multiple integrations
pytest --cov=hackernews --cov=bitly hackernews/ bitly/

# All tested integrations with line-level detail
pytest --cov=hackernews --cov=bitly --cov=nzbn --cov=notion --cov=shopify-customer
```

Coverage is configured in `pyproject.toml` to exclude test files — only integration source code is measured.

### Writing tests for a new integration

#### Unit tests

Unit test files go in `<integration>/tests/test_<name>_unit.py`. This naming is required for auto-discovery.

```python
import os
import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../dependencies")))

import pytest
from unittest.mock import AsyncMock, MagicMock

from my_integration.my_integration import my_integration

pytestmark = pytest.mark.unit


@pytest.fixture
def mock_context():
ctx = MagicMock(name="ExecutionContext")
ctx.fetch = AsyncMock(name="fetch")
ctx.auth = {"credentials": {"api_key": "test_key"}}
return ctx


class TestMyAction:
async def test_success(self, mock_context):
mock_context.fetch.return_value = {"data": "value"}
result = await my_integration.execute_action("my_action", {"input": "x"}, mock_context)
assert result.result.data["data"] == "value"
```

#### Integration tests (optional)

Integration test files go in `<integration>/tests/test_<name>_integration.py`. They are excluded from CI by both naming and marker.

```python
import pytest

pytestmark = pytest.mark.integration


@pytest.fixture
def live_context():
api_key = os.environ.get("MY_API_KEY", "")
if not api_key:
pytest.skip("MY_API_KEY not set")
# ... set up context with real credentials ...


class TestMyAction:
async def test_real_api_call(self, live_context):
result = await my_integration.execute_action("my_action", {"input": "x"}, live_context)
assert "data" in result.result.data
```

#### Shared conventions

- Use `pytestmark = pytest.mark.unit` at module level for mocked tests
- Use `pytestmark = pytest.mark.integration` for tests that hit real APIs
- Mock `context.fetch` return values to simulate API responses
- Test both success and error paths
- Also add a `conftest.py` in the integration's `tests/` dir:

```python
import sys
import os

sys.path.insert(0, os.path.dirname(__file__))
```

### Test markers

| Marker | Purpose | Needs credentials? | Runs in CI? | Auto-discovered? |
|--------|---------|-------------------|-------------|-----------------|
| `unit` | Mocked tests, no network | No | Yes | Yes (`test_*_unit.py`) |
| `integration` | Real API calls | Yes (via `.env`) | No | No (explicit file path) |

## Integration Structure

See the SDK's [Integration Structure Reference](https://github.com/autohive-ai/integrations-sdk/blob/master/docs/manual/integration_structure.md) for directory layouts, required files, and the full `config.json` schema. The [Building Your First Integration](https://github.com/autohive-ai/integrations-sdk/blob/master/docs/manual/building_your_first_integration.md) tutorial covers the development workflow end-to-end, and [samples/template/](https://github.com/autohive-ai/integrations-sdk/tree/master/samples/template) provides a ready-to-copy starter.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Integrations by Autohive

This repository hosts Autohive integrations made and maintained by the Autohive team.

## Getting Started
Expand Down Expand Up @@ -120,6 +121,11 @@ Supports basic HTTP authentication and Bearer token authentication via the SDK.
### Pipedrive

[pipedrive](pipedrive): Pipedrive CRM integration for managing deals, contacts, organizations, activities, and sales pipelines. Supports API token authentication. Supports full CRUD operations for deals (sales opportunities) with values, currencies, and expected close dates. Features complete contact management (persons) with email and phone information, organization management with company details, activity tracking for tasks, calls, meetings, deadlines, emails, and lunch meetings with scheduling and duration tracking. Includes note management with HTML formatting support, pipeline and stage discovery for sales workflow configuration, and universal search across all items (deals, persons, organizations, products) with exact match and custom field search capabilities. Features API token authentication, pagination support for large datasets (up to 500 items per request), and comprehensive filtering options by user, status, and custom filters. Comprises 30 actions covering deals, persons, organizations, activities, notes, pipelines, stages, and search. Ideal for sales pipeline management, customer relationship tracking, activity scheduling, and CRM automation workflows.

### Perplexity

[perplexity](perplexity): Web search integration powered by Perplexity's AI search API. Search the web and get ranked, structured results with titles, URLs, snippets, and dates. Supports content depth control (quick, default, detailed extraction), geographic filtering by country, multi-query search (up to 5 queries per request), and configurable result limits (1-20). Requires a `PERPLEXITY_API_KEY` environment variable. Includes 1 action for web search. Ideal for real-time web research, competitive intelligence, content curation, and market research automation.

### Facebook Pages

[facebook](facebook): Comprehensive Facebook Pages integration for managing social media presence through the Graph API v21.0. Supports page discovery, full post lifecycle (create, retrieve, schedule, delete) with text, photo, video, and link content types, comment management (read, reply, hide/unhide, like/unlike, delete), and page/post-level analytics. Features scheduled posting (10 min to 75 days ahead) with ISO 8601 and Unix timestamp support. Uses a multi-file structure pattern for maintainability with separate action modules. Includes OAuth2 authentication with comprehensive page permissions. Tested.
Expand Down Expand Up @@ -331,3 +337,8 @@ Supports basic HTTP authentication and Bearer token authentication via the SDK.
## Template

Use the [starter template](https://github.com/autohive-ai/integrations-sdk/tree/master/samples/template) in the SDK repo as the starting point for new integrations.

## Testing

See [CONTRIBUTING.md](CONTRIBUTING.md) for instructions on running and writing unit tests.

Loading
Loading