# GraphQL Testing in Xtrem Framework

## Overview

Xtrem framework provides comprehensive GraphQL testing capabilities with two distinct approaches:

1. **Static GraphQL Tests**: Simple input/output with static test data
2. **Parametric GraphQL Tests**: Dynamic testing with multiple scenarios using Handlebars templating

GraphQL tests provide extensive implicit coverage of node lifecycle, business logic, and API functionality, complementing traditional Mocha unit tests.

## Static GraphQL Tests

### File Structure

```text
test/graphql/[test-name]/
├── request.graphql          # Simple GraphQL query/mutation
├── response.json           # Expected response
└── parameters.json         # (Optional) Environment variables and mocks
```

### Characteristics

- Static input and output - tests run only once
- Environment variables available for dynamic values (e.g., `today`)
- Mocks available for external service calls
- Simple to write and maintain
- Low cost implementation
- Ideal for basic CRUD operations and straightforward business scenarios

### Example - Item Creation

**request.graphql**:

```graphql
mutation {
    xtremMasterData {
        item {
            create(data: { code: "CHOC001", name: "Chocolate Bar", isActive: true, type: "finished" }) {
                _id
                code
                name
                isActive
                type
            }
        }
    }
}
```

**response.json**:

```json
{
    "data": {
        "xtremMasterData": {
            "item": {
                "create": {
                    "_id": "#new",
                    "code": "CHOC001",
                    "name": "Chocolate Bar",
                    "isActive": true,
                    "type": "finished"
                }
            }
        }
    }
}
```

## Parametric GraphQL Tests

### File Structure

```text
test/graphql/[test-name]/
├── parameters.json         # Test scenarios with variables/input/output
├── request.graphql.hbs     # Handlebars template for GraphQL requests
└── response.json.hbs       # Handlebars template for expected responses
```

### Advanced Features

- Multiple test scenarios from single test definition
- Dynamic data generation using Handlebars templating
- Complex scenario testing with varied inputs
- Comprehensive coverage with minimal maintenance
- Environment variables and mocking support

### Simplified Parametric Testing Pattern

**Recommended Approach**: Use `inputParameters` and `{{{output}}}` keys for cleaner template syntax:

**parameters.json** (Simplified Pattern):

```json
{
    "Create basic item": {
        "input": {
            "properties": {
                "code": "ITEM001",
                "name": "Standard Item",
                "type": "finished",
                "isActive": true
            }
        },
        "output": {
            "_id": "#new",
            "code": "ITEM001",
            "name": "Standard Item",
            "type": "finished",
            "isActive": true
        }
    },
    "Create inactive item": {
        "input": {
            "properties": {
                "code": "ITEM002",
                "name": "Inactive Item",
                "type": "finished",
                "isActive": false
            }
        },
        "output": {
            "_id": "#new",
            "code": "ITEM002",
            "name": "Inactive Item",
            "type": "finished",
            "isActive": false
        }
    }
}
```

**request.graphql.hbs** (Simplified):

```graphql
mutation {
    xtremMasterData {
        item {
            create(data: {{inputParameters}}) {
                _id
                code
                name
                type
                isActive
            }
        }
    }
}
```

**response.json.hbs** (Simplified):

```json
{
    "data": {
        "xtremMasterData": {
            "item": {
                "create": {{{output}}}
            }
        }
    }
}
```

### Example - Multi-Scenario Item Testing

**parameters.json**:

```json
{
    "scenarios": [
        {
            "name": "Create finished item",
            "input": {
                "code": "ITEM001",
                "name": "Standard Item",
                "type": "finished",
                "isActive": true
            },
            "expected": {
                "code": "ITEM001",
                "name": "Standard Item",
                "type": "finished",
                "isActive": true
            }
        },
        {
            "name": "Create raw material",
            "input": {
                "code": "RAW001",
                "name": "Raw Material",
                "type": "raw",
                "isActive": true
            },
            "expected": {
                "code": "RAW001",
                "name": "Raw Material",
                "type": "raw",
                "isActive": true
            }
        }
    ]
}
```

**request.graphql.hbs**:

```graphql
mutation {
    xtremMasterData {
        item {
            create(
                data: {
                    code: "{{input.code}}"
                    name: "{{input.name}}"
                    type: "{{input.type}}"
                    isActive: {{input.isActive}}
                }
            ) {
                _id
                code
                name
                type
                isActive
            }
        }
    }
}
```

**response.json.hbs**:

```json
{
    "data": {
        "xtremMasterData": {
            "item": {
                "create": {
                    "_id": "#new",
                    "code": "{{expected.code}}",
                    "name": "{{expected.name}}",
                    "type": "{{expected.type}}",
                    "isActive": {{expected.isActive}}
                }
            }
        }
    }
}
```

## GraphQL Test Patterns by Operation Type

### CRUD Operations

**Create Operations**:

```graphql
mutation {
    xtremMasterData {
        [nodeName] {
            create(data: {
                # Required properties
                code: "TEST001"
                name: "Test Item"
                # Optional properties
                isActive: true
            }) {
                _id
                code
                name
                isActive
                # Include all properties being tested
            }
        }
    }
}
```

**Read Operations**:

```graphql
query {
    xtremMasterData {
        [nodeName] {
            getByCode(code: "TEST001") {
                _id
                code
                name
                isActive
                # All properties to verify
            }
        }
    }
}
```

**Update Operations**:

```graphql
mutation {
    xtremMasterData {
        [nodeName] {
            update(
                identifier: { code: "TEST001" }
                data: {
                    name: "Updated Name"
                    isActive: false
                }
            ) {
                _id
                code
                name
                isActive
            }
        }
    }
}
```

**Delete Operations**:

```graphql
mutation {
    xtremMasterData {
        [nodeName] {
            delete(identifier: { code: "TEST001" }) {
                success
                message
            }
        }
    }
}
```

### Document with Collections Testing

For nodes with collection properties, test both the parent document and collection items:

```graphql
mutation {
    xtremDistribution {
        salesOrder {
            create(
                data: {
                    customerCode: "CUST001"
                    orderDate: "{{today}}"
                    lines: [
                        { itemCode: "ITEM001", quantity: 10, unitPrice: 25.00 }
                        { itemCode: "ITEM002", quantity: 5, unitPrice: 15.00 }
                    ]
                }
            ) {
                _id
                number
                customerCode
                orderDate
                lines {
                    _id
                    itemCode
                    quantity
                    unitPrice
                    totalAmount
                }
                totalAmount
            }
        }
    }
}
```

## Environment Variables and Mocking

### Environment Variables

Available in both static and parametric tests:

- `{{today}}` - Current date in ISO format
- `{{now}}` - Current timestamp
- `{{user}}` - Current user identifier
- `{{uuid}}` - Generated UUID for unique values

**Example**:

```json
{
    "data": {
        "orderDate": "{{today}}",
        "createdBy": "{{user}}",
        "id": "{{uuid}}"
    }
}
```

### External Service Mocking

Mock external service calls in parameters.json:

```json
{
    "mocks": {
        "notificationService": {
            "sendEmail": {
                "success": true,
                "messageId": "msg-12345"
            }
        },
        "inventoryService": {
            "checkStock": {
                "available": true,
                "quantity": 100
            }
        }
    }
}
```

## GraphQL Test Coverage Analysis

### Implicit Coverage Areas

GraphQL tests automatically provide coverage for:

1. **Node Lifecycle**:
    - Object creation and initialization
    - Property validation and assignment
    - Default value application
    - Identifier generation

2. **Business Logic**:
    - Property filters and validation
    - Calculated fields and derived values
    - Business rule enforcement
    - Cross-property dependencies

3. **Data Persistence**:
    - Database operations (insert, update, delete)
    - Transaction management
    - Data integrity constraints
    - Relationship maintenance

4. **API Layer**:
    - GraphQL schema validation
    - Query/mutation execution
    - Response formatting
    - Error handling at API level

### Coverage Calculation

**Formula**: `Coverage = (CRUD + BusinessLogic + Integration + ErrorHandling) / TotalComponents`

**Component Weights**:

- **CRUD Operations** (25%): Basic create, read, update, delete functionality
- **Business Logic** (35%): Property validation, calculations, business rules
- **Integration Points** (20%): External service interactions, messaging
- **Error Handling** (20%): Error scenarios, validation failures, edge cases

### Coverage Assessment

- **90-100%**: Comprehensive - All major operations and error scenarios covered
- **80-89%**: High - Good coverage with minor gaps in error handling
- **70-79%**: Medium - Basic operations covered, missing error scenarios
- **60-69%**: Low - Minimal coverage, significant gaps in business logic
- **Below 60%**: Inadequate - Major functionality untested

## GraphQL vs Mocha Test Strategy

### Use Parametric GraphQL Tests For

1. **All CRUD Operations**: Create, read, update, delete with multiple scenarios
2. **Business Workflow Testing**: End-to-end scenario validation with various inputs
3. **Integration Testing**: API layer and database interaction verification
4. **Regression Testing**: Ensuring existing functionality with multiple data combinations
5. **Error Scenario Testing**: Multiple failure cases in single parametric test
6. **Edge Case Validation**: Various boundary conditions and data patterns

### Use Mocha Tests For

1. **Complex Async Operations**: Background processing, messaging verification
2. **Advanced Business Logic**: Multi-step calculations requiring detailed assertions
3. **Performance Testing**: Load testing and timing validations
4. **Mock Verification**: When detailed mock interaction verification is needed

### Combined Strategy

```text
Parametric GraphQL Tests (80% of coverage):
├── All CRUD operations with multiple scenarios
├── Business workflows with various inputs
├── Integration scenarios
├── Error handling with multiple failure cases
└── Edge cases with boundary data

Mocha Tests (20% of coverage):
├── Complex async operations
├── Advanced business logic testing
├── Performance validations
└── Detailed mock verifications
```

## GraphQL Test Execution

### Running Tests

```bash
# Run all GraphQL tests
npm run test:graphql

# Run specific test directory
npm run test:graphql -- --grep "item-management"

# Run with detailed output
npm run test:graphql -- --verbose

# Run specific node tests
npm run test:graphql -- --grep "customer"
```

### Test Results Analysis

GraphQL test output includes:

- **Scenario Results**: Pass/fail status for each test scenario
- **Coverage Report**: Areas of code exercised by tests
- **Performance Metrics**: Execution time for operations
- **Error Details**: Specific failures and validation issues

### Debugging Failed Tests

1. **Check Request/Response Matching**: Verify expected vs actual responses
2. **Validate Test Data**: Ensure test data meets business rules
3. **Review Error Messages**: Check GraphQL error details
4. **Verify Environment Setup**: Confirm database state and mocks

## Integration with Unit Test Analysis

### Complementary Testing Strategy

GraphQL tests should be considered when analyzing unit test coverage:

1. **Identify GraphQL Coverage**: Document what's already tested via GraphQL
2. **Focus Mocha Tests**: Target areas not covered by GraphQL tests
3. **Avoid Duplication**: Don't create redundant tests for well-covered areas
4. **Fill Critical Gaps**: Use Mocha for error scenarios and edge cases

### Coverage Reporting

When reporting test coverage, include:

- **GraphQL Test Coverage**: Operations and workflows tested
- **Mocha Test Coverage**: Explicit error and edge case testing
- **Combined Coverage**: Overall percentage across both test types
- **Gap Analysis**: Areas requiring additional testing

## Best Practices

### Test Design Guidelines

1. **Prefer Parametric Tests**: Use parametric tests over static tests for better maintainability
2. **Use Simplified Parameter Pattern**: Use `inputParameters` and `output` keys instead of complex Handlebars syntax
3. **Include All Properties**: Test all important node properties
4. **Test Business Rules**: Verify calculated fields and validations
5. **Use Realistic Data**: Test with production-like scenarios
6. **Multiple Scenarios**: Cover different data combinations in single parametric test

### Parametric Test Pattern Recommendations

**DO - Use Simple Parameter Keys**:

```json
{
    "Test scenario name": {
        "input": {
            "properties": {
                /* input data */
            }
        },
        "output": {
            /* expected output data directly */
        }
    }
}
```

**Template Usage**:

```graphql
mutation {
    xtremSales {
        [nodeName] {
            create(data: {{inputParameters}}) {
                # return fields
            }
        }
    }
}
```

```json
{
    "data": {
        "xtremSales": {
            "[nodeName]": {
                "create": {{{output}}}
            }
        }
    }
}
```

**AVOID - Complex Handlebars Logic**:

- Avoid `{{#each}}` loops in templates
- Avoid conditional `{{#if}}` statements in templates
- Avoid nested property access like `{{input.nested.property}}`
- Keep templates simple and use `{{inputParameters}}` / `{{{output}}}`

### Test Maintenance

1. **Keep Tests Simple**: Avoid overly complex test scenarios
2. **Document Test Purpose**: Clear names and descriptions
3. **Regular Test Review**: Ensure tests remain relevant
4. **Update with Changes**: Modify tests when business logic changes

### Performance Considerations

1. **Limit Test Scope**: Focus on specific functionality per test
2. **Use Test Data Efficiently**: Minimize database operations
3. **Clean Up Resources**: Proper test data cleanup
4. **Monitor Execution Time**: Keep tests fast and reliable

## Usage Keywords

Trigger GraphQL testing assistance with:

- "graphql test analysis"
- "graphql test coverage"
- "suggest parametric graphql tests"
- "parametric test creation"
- "inputParameters pattern"
- "create graphql test for [node]"
- "graphql vs mocha testing"
- "api testing strategy"
- "simplified parametric tests"
- "graphql error testing"
- "document collection testing"
- "multiple scenario testing"
