Finishes the master-cms-module feature (Units 1-4): runs Build and Test across master-backend, slave-availability-extension and frontend-cms-page, fixes a missing Availability EF migration for MasterRegistration and a TanStack Query v5 mutation-callback type break, adds the missing MasterModule appsettings section, and documents the module in README.md. Also seeds a tech-debt-backlog feature to track dead config and pre-existing/introduced frontend lint findings for later cleanup.
83 lines
5.3 KiB
Markdown
83 lines
5.3 KiB
Markdown
# Integration Test Instructions
|
|
|
|
## Purpose
|
|
Verify that the three units of the Master CMS Module work together: the Master module (Unit 1), the slave-side Availability extension (Unit 2), and the `/cms` frontend page (Unit 3).
|
|
|
|
## Test Scenarios
|
|
|
|
### Scenario 1: Owner Adds a Slave — Master Pushes Registration (Unit 1 → Unit 2)
|
|
- **Description**: The Owner registers a slave CMS from the Master `/cms` page; the Master generates an API key and pushes registration to the slave.
|
|
- **Setup**: Run two instances of the API — one configured as Master (`SlpModularCms.Modules.Master` enabled), one as Slave (`SlpModularCms.Modules.Availability` running, reachable at a known URL).
|
|
- **Test Steps**:
|
|
1. On the Master, call `POST /api/v1/CmsInstances` with the slave's URL.
|
|
2. `CmsInstanceService` generates an API key, stores it (Data-Protection-encrypted) in `CmsInstance`, and calls `ISlaveApiClient.RegisterMasterAsync` which `POST`s to the slave's `/api/v1/master/register` with the `X-Master-Api-Key` header.
|
|
3. Query the Master's `GET /api/v1/CmsInstances` list endpoint.
|
|
4. Query the slave's `GET /api/v1/master/registered-url` (with the same header) to confirm it stored the registration.
|
|
- **Expected Results**: The new instance appears in the Master's `CmsInstance` list (API key never included in the DTO); the slave's `MasterRegistration` table stores the Master's URL and the Data-Protection-encrypted API key.
|
|
- **Cleanup**: Stop both instances; clear both DBs if reused.
|
|
|
|
### Scenario 2: Master Sets Slave to Inactive → Slave Enforces via Two-Phase Middleware (Unit 1 → Unit 2)
|
|
- **Description**: Owner disables a slave from the Master `/cms` page; the Master pushes the new status to the slave, whose `AvailabilityMiddleware` blocks CMS requests.
|
|
- **Setup**: Both instances running and registered (per Scenario 1).
|
|
- **Test Steps**:
|
|
1. On the Master, call `PUT /api/v1/CmsInstances/{id}/status` with `Inactive`.
|
|
2. Confirm the Master's `SlaveApiClient` pushes the status to the slave synchronously as part of the same request (`SlaveContactSuccess` in the response).
|
|
3. Send a request to the slave's CMS route.
|
|
- **Expected Results**: Slave's static `_masterIsAvailable` flag flips immediately on push; slave responds with `503` and the extended response body signaling master-controlled unavailability; frontend on the slave redirects to the disable message.
|
|
- **Cleanup**: Set status back to `Active` on the Master.
|
|
|
|
### Scenario 3: Fail-Open on Master Unreachable or Slave Restart (Unit 1 & Unit 2)
|
|
- **Description**: The slave gate must never hard-fail when it cannot reach the Master.
|
|
- **Setup A (push failure)**: Registered slave; stop the Slave instance, then call the status-update endpoint on the Master.
|
|
- **Test Steps A**:
|
|
1. Stop the Slave process.
|
|
2. On the Master, call `PUT /api/v1/CmsInstances/{id}/status` with `Inactive`.
|
|
3. Inspect the Master's response body and `CmsInstance.LastIntegrityCheckFailedAt`.
|
|
- **Expected Results A**: The DB status change is NOT rolled back; response reports `SlaveContactSuccess = false`; `IntegrityCheckBackgroundService` will retry and update `LastIntegrityCheckFailedAt` on its next interval (`IntegrityCheckIntervalMinutes`, default 60).
|
|
- **Setup B (slave restart)**: Restart the Slave process while the Master is unreachable.
|
|
- **Test Steps B**:
|
|
1. Stop both Master and Slave.
|
|
2. Start only the Slave.
|
|
3. Send a request to the slave's CMS route immediately after startup.
|
|
- **Expected Results B**: `_masterIsAvailable` defaults to `true` on process start (fail-open), so the slave is reachable even before the Master pushes a fresh status.
|
|
|
|
### Scenario 4: Frontend CMS Page End-to-End (Unit 3 → Unit 1)
|
|
- **Description**: Owner manages slave CMS instances through the `/cms` page.
|
|
- **Setup**: Master API running; frontend dev server pointed at it (`npm run dev`); logged in as Administrator.
|
|
- **Test Steps**:
|
|
1. Navigate to `/cms`.
|
|
2. Add a new CMS instance via `AddCmsInstanceDialog`.
|
|
3. Confirm it appears in `CmsInstanceList`.
|
|
4. Open `SetStatusDialog` and toggle its status.
|
|
- **Expected Results**: List refreshes via TanStack Query invalidation after each mutation; API key is never shown in the list response (per NFR).
|
|
|
|
## Setup Integration Test Environment
|
|
|
|
### 1. Start Required Services
|
|
```bash
|
|
# Terminal 1 — Master instance
|
|
dotnet run --project src/SlpModularCms.Api --urls http://localhost:5001
|
|
|
|
# Terminal 2 — Slave instance (separate DB, MasterUrl pointing at Terminal 1)
|
|
dotnet run --project src/SlpModularCms.Api --urls http://localhost:5002
|
|
```
|
|
|
|
### 2. Configure Frontend
|
|
```bash
|
|
cd frontend
|
|
npm run dev # defaults to Master instance per vite proxy config
|
|
```
|
|
|
|
## Run Integration Tests
|
|
These scenarios are currently **manual** (no automated cross-process integration test harness exists in this codebase). Automated coverage for the underlying units (registration logic, middleware two-phase check, cache/fallback, frontend mutations) is provided by the unit test suites listed in `unit-test-instructions.md`.
|
|
|
|
### Verify Service Interactions
|
|
- Check Master logs for registration and status-update requests
|
|
- Check Slave logs for `MasterAvailabilityService` pull attempts and cache hits/misses
|
|
- Check browser dev tools network tab for `/api/v1/CmsInstances` calls from the frontend
|
|
|
|
### Cleanup
|
|
```bash
|
|
# Stop both dotnet run processes (Ctrl+C)
|
|
```
|