# Test Suite

This project uses Node.js built-in test runner (requires Node 18+). No external testing dependencies required.

## Running Tests

```bash
# Run all tests
npm test

# Run only unit tests
npm run test:unit

# Run only integration tests
npm run test:integration

# Run tests in watch mode (auto-rerun on file changes)
npm run test:watch
```

## Test Structure

```
test/
├── unit/              # Unit tests for isolated components
│   ├── basicauth.test.js
│   ├── callback_queue.test.js
│   ├── dynamic_record.test.js
│   ├── host_features.test.js
│   ├── host_lookup.test.js
│   ├── hostname_validate.test.js
│   ├── host_sso.test.js
│   ├── oidc.test.js
│   ├── password_policy.test.js
│   ├── roles.test.js
│   ├── safe_redirect.test.js
│   ├── unix_socket.test.js
│   └── wildcard_matchany.test.js
├── integration/       # Integration tests for complex interactions
│   └── dns_provider.test.js
└── helpers/           # Test utilities and contracts
    └── dns_provider_contract.js
```

## What We Test

### Unit Tests

**callback_queue.test.js**
- Callback registration and invocation
- Multiple callbacks with arguments
- Error handling

**host_lookup.test.js**
- Host lookup tree algorithm
- Wildcard matching (single and double)
- Exact match priority
- Edge cases (no match, empty input, etc.)

**unix_socket.test.js**
- Unix socket server creation
- JSON message parsing
- Partial data buffering
- Multiple connections
- Error handling

### Integration Tests

**dns_provider.test.js**
- DNS provider contract compliance
- All existing providers (Cloudflare, DigitalOcean, PorkBun, DuckDNS)
- Method signatures
- Key mapping
- Type validation

## Adding a New DNS Provider

When you add a new DNS provider, you MUST add tests to ensure it meets the contract:

1. Create your provider class extending `DnsApi` in `models/dns_provider/yourprovider.js`

2. Add a test block in `test/integration/dns_provider.test.js`:

```javascript
describe('YourProvider Provider', () => {
    const YourProvider = require('../../models/dns_provider/yourprovider');

    test('should meet DNS provider contract', () => {
        const mockCredentials = {api_key: 'mock-key'};
        const instance = validateDnsProviderContract(YourProvider, mockCredentials);
        assert.ok(instance, 'YourProvider should be instantiated');
    });

    test('should have correct _keyMap structure', () => {
        // Test your specific credential requirements
        assert.ok(YourProvider._keyMap.api_key);
        assert.strictEqual(YourProvider._keyMap.api_key.type, 'string');
        assert.strictEqual(YourProvider._keyMap.api_key.isRequired, true);
    });

    test('should have valid method signatures', () => {
        const instance = new YourProvider({api_key: 'mock'});
        validateMethodSignatures(instance);
    });

    test('should validate key mapping', () => {
        const instance = new YourProvider({api_key: 'mock'});
        validateKeyMapping(instance);
    });

    test('should validate type checking', () => {
        const instance = new YourProvider({api_key: 'mock'});
        validateTypeChecking(instance);
    });
});
```

3. Run tests to verify compliance:

```bash
npm run test:integration
```

## DNS Provider Contract

All DNS providers must:

1. Extend `DnsApi` base class
2. Define static `_keyMap` with required credentials
3. Define static display properties: `displayName`, `displayIconHtml`, `displayIconUni`
4. Implement required methods:
   - `listDomains()` - Returns array of `{domain, zoneId}`
   - `getRecords(domain, options)` - Returns array of DNS records
   - `createRecord(domain, options)` - Creates a record
   - `deleteRecords(domain, options)` - Deletes matching records
5. Define `__apiKeyMap` to translate between class keys and API keys
6. Implement or inherit `__typeCheck()` for record type validation
7. Throw appropriate errors from `this.errors` object

## CI/CD Integration

Tests can be run in GitHub Actions, GitLab CI, or any CI/CD system:

```yaml
# Example GitHub Actions workflow
- name: Run tests
  run: npm test
```

## Philosophy

We test **custom logic**, not third-party code:
- YES: Test our host lookup algorithm
- YES: Test our socket buffering logic
- YES: Test DNS provider contracts
- NO: Don't test Express.js routing
- NO: Don't test the Redis ORM
- NO: Don't test external DNS APIs (use mocks)

## Notes

- Tests use Node's built-in `node:test` and `node:assert` modules
- No external testing framework needed
- Tests are fast and run in parallel by default
- Mock external services (Redis, DNS APIs) to avoid network calls
- Focus on testing business logic, not infrastructure
