backbone-bucket 0.4.6

Bucket Bounded Context: File Storage Module for Backbone Framework
Documentation
# Bucket Integration Tests

Integration test framework for the bucket bounded context module.

## Quick Start

```bash
# 1. Start the API server (in a separate terminal)
cargo run --bin backbone

# 2. Run all integration tests
cargo test --package backbone-bucket --test run_integration_tests -- --ignored --nocapture

# 3. Run specific test suites
cargo test --package backbone-bucket --test run_integration_tests run_{{entity_name}}_api_tests -- --ignored --nocapture
```

## Directory Structure

```
tests/
├── README.md                          # This file
├── run_integration_tests.rs           # Main integration test runner (generated)
│
├── integration/                       # Integration test framework
│   ├── mod.rs                         # Module exports
│   │
│   ├── framework/                     # Core test framework
│   │   ├── mod.rs                     # Framework exports
│   │   ├── base_test.rs               # Test trait, TestResult, TestSuiteResult
│   │   └── api_test.rs                # HTTP client for API testing
│   │
│   ├── helpers/                       # Test utilities
│   │   ├── mod.rs                     # Helper exports
│   │   ├── common_utils.rs            # ID generation, data utilities
│   │   ├── jwt_manager.rs             # JWT token generation
│   │   └── setup_manager.rs           # Test setup/teardown
│   │
│   └── tests/                         # Entity-specific tests
│       ├── mod.rs                     # Test exports
│       ├── crud_test_base.rs          # Generic CRUD test framework (generated)
│       └── {{entity_name}}_api_test.rs # Entity-specific tests (generated)
│
└── results/                           # Test output (gitignored)
    └── *.json                         # Test result files
```

## Generating Tests

Tests are generated by the schema generator:

```bash
# Generate integration tests from schema
backbone schema generate bucket --target all

# Or specifically generate tests
backbone test generate bucket
```

## Test Framework Overview

### Core Components

| Component | Purpose |
|-----------|---------|
| `Test` trait | Standard interface for all tests |
| `TestResult` | Result container with details |
| `TestSuiteResult` | Aggregated results from test suite |
| `ApiTest` | HTTP client with auth support |
| `JwtTokenManager` | JWT token creation for testing |
| `TestSetupManager` | Setup/teardown management |
| `CommonUtils` | Helper utilities |

### Generic CRUD Tests

The framework provides 14 standard test cases for each entity:

| # | Test | HTTP Method | Endpoint | Expected |
|---|------|-------------|----------|----------|
| 1 | List | GET | `/collection` | 200 |
| 2 | Pagination | GET | `/collection?page=1&per_page=5` | 200 |
| 3 | Create | POST | `/collection` | 201/200 |
| 4 | Create Invalid | POST | `/collection` | 400/422 |
| 5 | Get By ID | GET | `/collection/:id` | 200 |
| 6 | Update (PUT) | PUT | `/collection/:id` | 200 |
| 7 | Patch | PATCH | `/collection/:id` | 200 |
| 8 | Delete | DELETE | `/collection/:id` | 200/204 |
| 9 | List Trash | GET | `/collection/trash` | 200 |
| 10 | Restore | POST | `/collection/:id/restore` | 200 |
| 11 | Get Not Found | GET | `/collection/:fake-id` | 404 |
| 12 | Bulk Create | POST | `/collection/bulk` | 201/200 |
| 13 | Upsert | POST | `/collection/upsert` | 201/200 |
| 14 | Empty Trash | DELETE | `/collection/empty` | 200/204 |

## Creating Custom Tests

### Step 1: Create Data Generator

Create a new file in `integration/tests/` (e.g., `my_entity_api_test.rs`):

```rust
//! MyEntity API Integration Tests

use async_trait::async_trait;
use serde_json::{json, Value};

use crate::integration::framework::{Test, TestError, TestResult};
use crate::integration::helpers::CommonUtils;
use super::crud_test_base::{CrudTestConfig, GenericCrudTest, TestDataGenerator};

pub struct MyEntityDataGenerator;

impl TestDataGenerator for MyEntityDataGenerator {
    fn generate_create_payload(&self, utils: &CommonUtils) -> Value {
        json!({
            "name": utils.generate_id("myentity"),
            "description": "Test entity",
            "status": "ACTIVE"
        })
    }

    fn generate_update_payload(&self, utils: &CommonUtils) -> Value {
        json!({
            "name": utils.generate_id("updated"),
            "description": "Updated entity",
            "status": "INACTIVE"
        })
    }

    fn generate_patch_payload(&self, _utils: &CommonUtils) -> Value {
        json!({
            "status": "ARCHIVED"
        })
    }

    fn generate_invalid_payload(&self) -> Value {
        json!({
            "name": "",  // Empty - should fail validation
            "status": "INVALID_STATUS"
        })
    }
}
```

### Step 2: Create Test Suite

```rust
pub struct MyEntityApiTest {
    crud_test: GenericCrudTest<MyEntityDataGenerator>,
}

impl MyEntityApiTest {
    pub fn new() -> Self {
        let config = CrudTestConfig::new("/api/v1/my-entities", "MyEntity")
            .with_required_fields(vec!["name", "status"])
            .with_unique_fields(vec!["name"]);

        Self {
            crud_test: GenericCrudTest::new(config, MyEntityDataGenerator),
        }
    }

    pub fn with_auth(mut self, token: &str) -> Self {
        self.crud_test = self.crud_test.with_auth(token);
        self
    }
}

#[async_trait]
impl Test for MyEntityApiTest {
    fn name(&self) -> &str {
        "my_entity_api_test"
    }

    async fn setup(&mut self) -> Result<(), TestError> {
        Ok(())
    }

    async fn run_tests(&mut self) -> Vec<TestResult> {
        self.crud_test.run_all_tests().await.results
    }

    async fn teardown(&mut self) -> Result<(), TestError> {
        Ok(())
    }
}
```

### Step 3: Register Test

Add to `integration/tests/mod.rs`:

```rust
pub mod my_entity_api_test;
pub use my_entity_api_test::MyEntityApiTest;
```

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `API_BASE_URL` | `http://127.0.0.1:3000` | API server URL |
| `JWT_SECRET` | `test-secret-key` | JWT signing secret |
| `TEST_RESULTS_DIR` | `./test-results` | Output directory |
| `TEST_VERBOSE` | `false` | Enable verbose logging |

## Running Tests

```bash
# Run all tests (requires --ignored flag since they need running server)
cargo test --package backbone-bucket --test run_integration_tests -- --ignored --nocapture

# Run unit tests (no server required)
cargo test --package backbone-bucket --test integration_tests

# Run with verbose output
TEST_VERBOSE=1 cargo test --package backbone-bucket --test run_integration_tests -- --ignored --nocapture
```

## Test Output

### Console Output

```
══════════════════════════════════════════════════════════
Test Suite: {{entity_name}}_api_test
══════════════════════════════════════════════════════════
  ✓ Create {{ENTITY_NAME_PASCAL}} - Success (0.009s): Entity created successfully
  ✓ List {{ENTITY_NAME_PASCAL}}s (0.000s): Entities listed successfully
  ✓ Get {{ENTITY_NAME_PASCAL}} By ID (0.001s): Entity retrieved successfully
──────────────────────────────────────────────────────────
Results: 3 passed, 0 failed, 3 total (100.0%)
Duration: 0.010s
══════════════════════════════════════════════════════════
```

### JSON Output

Test results are saved to `tests/results/`:

```json
{
  "suite_name": "{{ENTITY_NAME_PASCAL}} CRUD Tests",
  "results": [
    {
      "test_name": "{{ENTITY_NAME_PASCAL}} - Create",
      "success": true,
      "details": "Entity created successfully",
      "duration_seconds": 0.009
    }
  ],
  "total_duration_seconds": 0.010
}
```

## Troubleshooting

### Tests return 404

The API endpoint doesn't exist yet. Implement the endpoint in the module.

### Tests return 500

Server-side error. Check the API server logs for details.

### Tests return 422

Validation error. Update the `generate_create_payload()` to match the API's expected schema.

### Connection refused

The API server isn't running. Start it with:
```bash
cargo run --bin backbone
```

## Best Practices

1. **Use descriptive test names** - The test name appears in output and helps debugging
2. **Include input/output in results** - Use `.with_input()` and `.with_output()` for traceability
3. **Clean up test data** - Delete created entities in teardown to avoid pollution
4. **Use unique identifiers** - Use `utils.generate_id()` to avoid conflicts
5. **Handle expected failures** - Some tests (like validation) expect failure responses
6. **Test edge cases** - Include tests for invalid data, missing fields, duplicates