# QuantEngine - Testing & Deployment Guide

**Status**: Phase 6 (Testing) & Phase 8 (Deployment) - Configuration & Documentation

---

## Phase 6: Testing & Optimization

### 6.1 Unit Testing (bUnit)

#### Setup
```bash
cd src/dotnet
dotnet add package bunit
dotnet add package bunit.web
```

#### Example Test: Dashboard Component
```csharp
// Tests/Pages/DashboardTests.cs
[TestFixture]
public class DashboardTests
{
    [Test]
    public void Dashboard_Renders_KPICards()
    {
        // Arrange
        var cut = new TestContext().RenderComponent<Dashboard>();

        // Act & Assert
        var kpiCards = cut.FindAll(".mud-card-kpi");
        kpiCards.Count.Should().Be(4);
    }

    [Test]
    public async Task Dashboard_LoadsAssets_OnInitialize()
    {
        // Arrange
        var httpClient = new HttpClientStub();
        var cut = new TestContext();
        cut.Services.AddScoped(sp => httpClient);
        var dashboard = cut.RenderComponent<Dashboard>();

        // Act
        await Task.Delay(100); // Wait for async init

        // Assert
        httpClient.Requests.Should().Contain(r => r.Url.Contains("/api/portfolio"));
    }
}
```

#### Test Coverage Targets
- Dashboard rendering (4 KPI cards)
- Users list (search, filter, pagination)
- Portfolio components (asset table, categories)
- Form fields (all input types)
- Dialogs (confirm/cancel actions)

#### Run Tests
```bash
dotnet test src/dotnet/QuantEngine.Web.Client.Tests
dotnet test src/dotnet/QuantEngine.Web.Tests
```

### 6.2 Integration Tests

#### Database Test Setup
```csharp
[TestFixture]
public class RepositoryIntegrationTests
{
    private IDbConnectionFactory _connectionFactory;
    private ICollectionRepository _repository;

    [OneTimeSetUp]
    public void OneTimeSetUp()
    {
        _connectionFactory = new DbConnectionFactory(
            "Host=localhost;Database=quantengine_test;..."
        );
    }

    [Test]
    public async Task SaveCollectionRun_Persists_ToDatabase()
    {
        // Arrange
        var run = new CollectionRun { RunId = Guid.NewGuid().ToString(), ... };

        // Act
        await _repository.SaveRunAsync(run);

        // Assert
        var retrieved = await _repository.GetRunAsync(run.RunId);
        retrieved.Should().NotBeNull();
        retrieved.RunId.Should().Be(run.RunId);
    }
}
```

### 6.3 Performance Optimization

#### Bundle Size Optimization
```bash
# Check bundle sizes
dotnet publish -c Release --output ./publish
du -sh publish/wwwroot/_framework/*
```

**Targets**:
- dotnet.wasm: < 2MB
- app.js: < 500KB
- Total: < 5MB

#### Loading Time Optimization
```csharp
// Use lazy loading for pages
[lazy: Dashboard]
@rendermode InteractiveWebAssembly

// Pre-load critical resources
<link rel="prefetch" href="/_framework/QuantEngine.Web.Client.wasm" />
```

### 6.4 Accessibility Testing (WCAG 2.1 AA)

#### Automated Checks
```bash
dotnet add package Deque.AxeCore.Selenium
```

#### Manual Checklist
- [ ] Keyboard navigation (Tab, Enter, Escape)
- [ ] Screen reader support (NVDA, JAWS)
- [ ] Color contrast (4.5:1 for text)
- [ ] Form labels properly associated
- [ ] Error messages clear and descriptive
- [ ] Focus indicators visible
- [ ] No automatic content changes

---

## Phase 8: Deployment & Operations

### 8.1 Production Build

#### Release Build Configuration
```bash
# Build Release configuration
cd src/dotnet
dotnet build -c Release

# Publish for deployment
dotnet publish -c Release -o ./publish/quantengine

# Size check
ls -lh publish/quantengine/
```

#### Build Output
- `publish/quantengine/` - Complete deployment package
- `publish/quantengine/wwwroot/` - Static assets
- `publish/quantengine/QuantEngine.Web.exe` - Server executable
- `publish/quantengine/appsettings.production.json` - Configuration

### 8.2 Docker Deployment

#### Dockerfile
```dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 80 443

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY ["src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj", "QuantEngine.Web/"]
RUN dotnet restore "QuantEngine.Web/QuantEngine.Web.csproj"

COPY src/dotnet/ .
RUN dotnet build "QuantEngine.Web/QuantEngine.Web.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "QuantEngine.Web/QuantEngine.Web.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "QuantEngine.Web.dll"]
```

#### Docker Build & Run
```bash
# Build image
docker build -t quantengine:latest .

# Run container
docker run -d \
  -p 5265:80 \
  -e ConnectionStrings__DefaultConnection="Host=db;Database=quantenginedb;..." \
  -e ASPNETCORE_ENVIRONMENT=Production \
  quantengine:latest

# Check logs
docker logs -f <container_id>
```

### 8.3 Nginx Reverse Proxy

#### Nginx Configuration
```nginx
upstream quantengine {
    server 127.0.0.1:5000;
    server 127.0.0.1:5001;
}

server {
    listen 80;
    server_name quantengine.example.com;

    # Redirect to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name quantengine.example.com;

    ssl_certificate /etc/ssl/certs/cert.pem;
    ssl_certificate_key /etc/ssl/private/key.pem;

    location / {
        proxy_pass http://quantengine;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location ~* \.(js|css|wasm|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}
```

### 8.4 Environment Configuration

#### appsettings.production.json
```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "System": "Warning",
      "Microsoft": "Warning"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Host=prod-db-host;Database=quantenginedb;Username=quantengine_app;Password=***;SslMode=Require;",
    "HangfireConnection": "Host=prod-db-host;Database=quantengine_hangfire;..."
  },
  "AdminSettings": {
    "Username": "admin",
    "Password": "***"
  },
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://0.0.0.0:5000"
      }
    }
  }
}
```

### 8.5 Deployment Checklist

#### Pre-Deployment
- [ ] All tests pass (`dotnet test`)
- [ ] Code reviewed and approved
- [ ] Security vulnerabilities scanned (`dotnet package-search`)
- [ ] Database migrations tested
- [ ] Hangfire schedules configured
- [ ] Secrets properly managed (not in code)
- [ ] Environment variables documented

#### Deployment Steps
```bash
# 1. Create backup
pg_dump -h prod-db-host -U quantengine_app quantenginedb > backup-$(date +%Y%m%d).sql

# 2. Deploy application
docker pull quantengine:latest
docker stop quantengine
docker run -d --name quantengine -p 5000:80 quantengine:latest

# 3. Health check
curl https://quantengine.example.com/health

# 4. Monitor logs
docker logs -f quantengine

# 5. Verify features
- [ ] Login works
- [ ] Dashboard loads
- [ ] Data collection runs
- [ ] Hangfire jobs scheduled
```

#### Post-Deployment
- [ ] Monitor error logs (Serilog, Telegram alerts)
- [ ] Check Hangfire dashboard
- [ ] Verify scheduled jobs running
- [ ] Monitor database performance
- [ ] Check API response times (< 200ms)

### 8.6 Monitoring & Observability

#### Health Checks
```csharp
app.MapHealthChecks("/health", new HealthCheckOptions
{
    Predicate = _ => true,
    ResponseWriter = WriteResponse
});

// Add health checks
builder.Services.AddHealthChecks()
    .AddDbContextCheck<QuantEngineDbContext>()
    .AddCheck("Database", () => HealthCheckResult.Healthy())
    .AddCheck("KIS API", () => CheckKisApiAsync());
```

#### Logging (Serilog)
```csharp
Log.Information("Collection run completed: {RunId}, {Count} items", runId, itemCount);
Log.Warning("API rate limit warning: {Remaining}", remaining);
Log.Error(ex, "Collection failed: {RunId}", runId);
```

#### Monitoring Metrics
- Request rate (requests/sec)
- Error rate (errors/requests)
- Database query time (p50, p95, p99)
- Hangfire job success rate
- API response time by endpoint

### 8.7 Rollback Plan

#### If Deployment Fails
```bash
# 1. Stop current deployment
docker stop quantengine

# 2. Restore previous version
docker run -d --name quantengine -p 5000:80 quantengine:v1.0.0

# 3. Restore database from backup
psql -h prod-db-host -U quantengine_app -d quantenginedb < backup-20260705.sql

# 4. Verify health
curl https://quantengine.example.com/health
```

---

## Deployment Timeline

| Milestone | Target Date | Status |
|-----------|-------------|--------|
| Phase 6: Tests | 2026-07-06 | 📋 |
| Phase 7: Hangfire | 2026-07-05 | ✅ |
| Phase 8: Deploy | 2026-07-07 | 📋 |
| Production Release | 2026-07-10 | 📅 |

---

## Success Criteria

**Phase 6**:
- [ ] 80%+ test coverage
- [ ] All component tests passing
- [ ] WCAG AA compliance verified
- [ ] Bundle size < 5MB

**Phase 8**:
- [ ] Docker image builds successfully
- [ ] Production config validated
- [ ] Database backups automated
- [ ] Rollback plan documented
- [ ] Monitoring alerts configured
- [ ] 99.5% uptime target established

---

**Next**: Execute deployment pipeline and monitor production metrics.
