Metadata-Version: 2.4
Name: api-forge-cli
Version: 1.0.0
Summary: CLI tool for API testing, load testing, and mock server generation
Project-URL: Homepage, https://github.com/SanjaySundarMurthy/api-forge
Project-URL: Repository, https://github.com/SanjaySundarMurthy/api-forge
Project-URL: Issues, https://github.com/SanjaySundarMurthy/api-forge/issues
Author-email: Sanjay Sundar Murthy <sanjaysundarmurthy@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: api,cli,http,load-testing,mock,rest,testing
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.9
Requires-Dist: click>=8.0
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# api-forge

**CLI tool for API testing, load testing, and mock server generation.**

[![PyPI version](https://badge.fury.io/py/api-forge-cli.svg)](https://pypi.org/project/api-forge-cli/)
[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

---

## Why api-forge?

Testing APIs shouldn't require heavy frameworks or complex setup. **api-forge** is a lightweight CLI tool that provides:

- **Test Suites** — Define API tests in simple YAML files
- **Assertions** — Validate status codes, headers, JSON paths, response times
- **Variable Chaining** — Extract values from responses for use in subsequent requests
- **Load Testing** — Stress test endpoints with configurable concurrency
- **Mock Server** — Spin up mock APIs from YAML for development/testing
- **Quick Requests** — cURL-like commands with pretty output

---

## Installation

```bash
pip install api-forge-cli
```

---

## Quick Start

```bash
# Make a quick GET request
api-forge get https://jsonplaceholder.typicode.com/posts/1

# Run a test suite
api-forge test suite.yaml

# Load test an endpoint
api-forge load https://api.example.com/health -n 50 -d 10

# Start a mock server
api-forge mock mock.yaml

# Generate example configs
api-forge init --type test -o suite.yaml
```

---

## Commands

### `get` / `post` / `put` / `delete` — Quick Requests

```bash
# GET request
api-forge get https://api.example.com/users

# POST with JSON body
api-forge post https://api.example.com/users -d '{"name": "Alice"}'

# With custom headers
api-forge get https://api.example.com/users -H "Authorization:Bearer token"

# PUT request
api-forge put https://api.example.com/users/1 -d '{"name": "Bob"}'

# DELETE request
api-forge delete https://api.example.com/users/1
```

### `test` — Run API Test Suites

```bash
api-forge test suite.yaml
api-forge test tests/api-tests.yaml -v
```

Test suites are defined in YAML:

```yaml
name: "User API Tests"
base_url: "https://api.example.com"

headers:
  Authorization: "Bearer {{token}}"

variables:
  token: "your-api-token"

requests:
  - name: "Get all users"
    url: "/users"
    method: GET
    assertions:
      - type: status
        expected: 200
      - type: response_time
        expected: 2000

  - name: "Create user"
    url: "/users"
    method: POST
    body:
      name: "Alice"
      email: "alice@example.com"
    assertions:
      - type: status
        expected: 201
      - type: json_path
        path: "id"
        expected: 1
    variables:
      new_user_id: "id"  # Extract for next request

  - name: "Get created user"
    url: "/users/{{new_user_id}}"
    method: GET
    assertions:
      - type: status
        expected: 200
```

### `load` — Load Testing

```bash
# Quick load test
api-forge load https://api.example.com/health -n 50 -d 30

# From config file
api-forge load -c loadtest.yaml
```

| Option | Description |
|--------|-------------|
| `-n, --concurrency` | Number of concurrent connections (default: 10) |
| `-d, --duration` | Test duration in seconds (default: 10) |
| `--rps` | Requests per second limit (0 = unlimited) |
| `-c, --config` | Load test config YAML file |

Load test config:

```yaml
url: "https://api.example.com/users"
method: GET
concurrency: 100
duration_seconds: 60
requests_per_second: 500
timeout: 10.0
headers:
  Authorization: "Bearer token"
```

**Output includes:**
- Total requests, success/failure counts
- Requests per second achieved
- Latency percentiles (min, avg, p50, p95, p99, max)
- Status code distribution
- Error samples

### `mock` — Mock Server

```bash
# Start mock server from config
api-forge mock mock.yaml

# Custom port
api-forge mock mock.yaml -p 3000

# Default server (returns 404 for all)
api-forge mock
```

Mock server config:

```yaml
name: "Test API"
port: 8000
cors: true

endpoints:
  - path: "/health"
    method: GET
    status: 200
    body:
      status: "healthy"

  - path: "/users"
    method: GET
    status: 200
    headers:
      X-Total-Count: "100"
    body:
      - id: 1
        name: "Alice"
      - id: 2
        name: "Bob"

  - path: "/users"
    method: POST
    status: 201
    body:
      id: 3
      message: "Created"

  - path: "/slow"
    method: GET
    status: 200
    delay_ms: 2000  # Simulate latency
    body:
      message: "Slow response"

  - path: "/users/*"  # Wildcard matching
    method: GET
    status: 200
    body:
      id: 1
      name: "User"
```

### `init` — Generate Examples

```bash
api-forge init --type test -o suite.yaml
api-forge init --type load -o loadtest.yaml
api-forge init --type mock -o mock.yaml
```

---

## Assertion Types

| Type | Description | Example |
|------|-------------|---------|
| `status` | HTTP status code | `expected: 200` or `expected: [200, 201]` |
| `header` | Header value contains | `header: Content-Type`, `expected: json` |
| `body_contains` | Body contains string | `expected: "success"` |
| `json_path` | JSON path equals value | `path: user.id`, `expected: 123` |
| `body_regex` | Body matches regex | `expected: "\\d{5}"` |
| `response_time` | Max response time (ms) | `expected: 500` |

---

## Variable Substitution

Use `{{variable_name}}` syntax in URLs, headers, and body:

```yaml
variables:
  api_key: "secret123"
  user_id: "456"

requests:
  - name: "Get user"
    url: "/users/{{user_id}}"
    headers:
      X-API-Key: "{{api_key}}"
```

**Extract variables from responses** for request chaining:

```yaml
requests:
  - name: "Login"
    url: "/auth/login"
    method: POST
    body:
      username: "admin"
      password: "secret"
    variables:
      auth_token: "token"  # Extract $.token from response

  - name: "Protected endpoint"
    url: "/protected"
    headers:
      Authorization: "Bearer {{auth_token}}"
```

---

## Examples

### Full Test Suite with Chaining

```yaml
name: "E-commerce API"
base_url: "https://api.shop.example.com"

requests:
  - name: "Create product"
    url: "/products"
    method: POST
    body:
      name: "Widget"
      price: 29.99
    assertions:
      - type: status
        expected: 201
    variables:
      product_id: "id"

  - name: "Get product"
    url: "/products/{{product_id}}"
    assertions:
      - type: json_path
        path: "name"
        expected: "Widget"

  - name: "Delete product"
    url: "/products/{{product_id}}"
    method: DELETE
    assertions:
      - type: status
        expected: 204
```

### Load Test with Detailed Config

```yaml
url: "https://api.example.com/search"
method: POST
concurrency: 200
duration_seconds: 120
requests_per_second: 1000
timeout: 5.0
headers:
  Content-Type: "application/json"
body:
  query: "test"
  limit: 10
```

---

## Development

```bash
git clone https://github.com/SanjaySundarMurthy/api-forge.git
cd api-forge
pip install -e ".[dev]"
pytest tests/ -v
```

---

## Author

**Sanjay Sundar Murthy**
- GitHub: [@SanjaySundarMurthy](https://github.com/SanjaySundarMurthy)
- Email: sanjaysundarmurthy@gmail.com

---

## License

MIT License — see [LICENSE](LICENSE) for details.
