---
name: step-07-tests
description: Final Test Sweep — security tests, coverage analysis, remaining failures
model: opus
prev_step: steps/step-06-resolve.md
next_step: steps/step-08-run-tests.md
---

# Step 7: Final Test Sweep

> **MANDATORY STEP — This is NOT optional.** APEX requires a final test sweep for completion.
> Backend and frontend tests were already scaffolded and run inline (Layer 2 and Layer 3).
> This step focuses on: security tests, coverage gaps, cross-layer scenarios, and remaining failures.

**Goal:** Ensure comprehensive test coverage. Target: >= 80% coverage, 100% pass rate. Acceptable fallback: skip failing tests with TODO comment after 3 fix attempts — escalate to user rather than blocking indefinitely.

---

## Task Progress

### Progress Tracker Update
```
TaskUpdate(taskId: progress_tracker_id,
  description: "Module: {module_code}. Current: step-07 (Final Test Sweep)",
  activeForm: "Running test sweep")
```

---

## 0. Ensure Test Infrastructure Exists

> **Note:** These infrastructure checks are idempotent safety nets. If inline tests (step-03 Layer 2/3) ran successfully, the infrastructure already exists. These checks guard against edge cases where inline test scaffolding was skipped or partially completed.

### 0a. Frontend Test Tooling (if frontend was generated)

> **Before scaffolding additional frontend tests, the test infrastructure must be in place.**

```bash
# Check if Vitest is installed
WEB_DIR=$(find . -name "package.json" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
if [ -n "$WEB_DIR" ]; then
  cd "$WEB_DIR"

  # Install test dependencies if missing
  if ! grep -q '"vitest"' package.json 2>/dev/null; then
    npm install -D vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom @types/testing-library__jest-dom
  fi

  # Create vitest.config.ts if missing
  if [ ! -f "vitest.config.ts" ]; then
    cat > vitest.config.ts << 'VITEST_EOF'
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
    css: true,
    include: ['src/**/*.test.{ts,tsx}'],
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
});
VITEST_EOF
  fi

  # Create test setup file if missing
  mkdir -p src/test
  if [ ! -f "src/test/setup.ts" ]; then
    cat > src/test/setup.ts << 'SETUP_EOF'
import '@testing-library/jest-dom';
SETUP_EOF
  fi

  # Add test script to package.json if missing
  if ! grep -q '"test"' package.json 2>/dev/null; then
    # Use npm pkg set for safe JSON manipulation
    npm pkg set scripts.test="vitest run"
    npm pkg set scripts.test:watch="vitest"
    npm pkg set scripts.test:coverage="vitest run --coverage"
  fi

  cd -
fi
```

### 0b. Backend Test Projects

```bash
# Check for existing unit test project
UNIT_PROJECT=$(find tests/ -name "*.Tests.Unit.csproj" 2>/dev/null | head -1)

if [ -z "$UNIT_PROJECT" ]; then
  PROJECT_NAME=$(basename *.sln .sln)
  dotnet new xunit -n "${PROJECT_NAME}.Tests.Unit" -o "tests/${PROJECT_NAME}.Tests.Unit"
  dotnet add "tests/${PROJECT_NAME}.Tests.Unit" package Moq
  dotnet add "tests/${PROJECT_NAME}.Tests.Unit" package FluentAssertions
  for proj in src/*/*.csproj; do
    dotnet add "tests/${PROJECT_NAME}.Tests.Unit" reference "$proj"
  done
  dotnet sln add "tests/${PROJECT_NAME}.Tests.Unit/${PROJECT_NAME}.Tests.Unit.csproj"
fi
```

### 0c. Integration Test Project (for DB validation)

```bash
# Check for existing integration test project
INT_PROJECT=$(find tests/ -name "*.Tests.Integration.csproj" 2>/dev/null | head -1)

if [ -z "$INT_PROJECT" ]; then
  PROJECT_NAME=$(basename *.sln .sln)
  dotnet new xunit -n "${PROJECT_NAME}.Tests.Integration" -o "tests/${PROJECT_NAME}.Tests.Integration"
  dotnet add "tests/${PROJECT_NAME}.Tests.Integration" package Moq
  dotnet add "tests/${PROJECT_NAME}.Tests.Integration" package FluentAssertions
  dotnet add "tests/${PROJECT_NAME}.Tests.Integration" package Respawn
  dotnet add "tests/${PROJECT_NAME}.Tests.Integration" package Microsoft.EntityFrameworkCore.SqlServer
  for proj in src/*/*.csproj; do
    dotnet add "tests/${PROJECT_NAME}.Tests.Integration" reference "$proj"
  done
  dotnet sln add "tests/${PROJECT_NAME}.Tests.Integration/${PROJECT_NAME}.Tests.Integration.csproj"
fi
```

> **Note:** Integration tests use `DatabaseFixture` + `Respawn` with SQL Server LocalDB.
> See step-04 section 5c for details.

---

## 1. Conditional Skip — Inline Tests Already Scaffolded

> **Backend and frontend tests were already scaffolded inline in step-03 (Layer 2 and Layer 3).**
> Do NOT re-scaffold tests that already exist. Only scaffold NEW test types here.

```
Check existing tests:
  → If domain tests exist (from Layer 2 inline): SKIP domain scaffold
  → If application tests exist (from Layer 2 inline): SKIP application scaffold
  → If API integration tests exist (from Layer 2 inline): SKIP API scaffold
  → If frontend form tests exist (from Layer 3 inline): SKIP frontend form scaffold
```

---

## 2. Security Tests (PRIMARY focus of this step)

```
Call: mcp__smartstack__scaffold_tests
  module: "{module_code}"
  test_type: "security"

Tests: RequirePermission enforcement, multi-tenant isolation, tenant boundary violations
```

> **Security tests are the main value-add of step-07.** Inline tests cover CRUD functionality;
> security tests verify authorization and isolation — these require cross-layer awareness.

---

## 3. Scaffold Missing Tests (if any layers skipped inline)

For each layer that was NOT tested inline:

### Domain Tests (if not already scaffolded)
```
Call: mcp__smartstack__scaffold_tests
  target_layer: "domain"
  module: "{module_code}"
  test_type: "unit"

Tests: entity creation, validation, domain events, value objects
```

### Application Tests (if not already scaffolded)
```
Call: mcp__smartstack__scaffold_tests
  target_layer: "application"
  module: "{module_code}"
  test_type: "unit"

Tests: service logic, CQRS handlers, FluentValidation
```

### API Tests (if not already scaffolded)
```
Call: mcp__smartstack__scaffold_tests
  target_layer: "api"
  module: "{module_code}"
  test_type: "integration"

Tests: controller endpoints, authorization, response DTOs
```

### Frontend Form Tests (if not already scaffolded)
```
For each module with create/edit pages:
  → Generate EntityCreatePage.test.tsx and EntityEditPage.test.tsx
  → Co-located next to the page component (NOT in __tests__/ folder)

Required test coverage:
  - Rendering: form renders with all expected fields
  - Validation: required fields show errors on empty submit
  - Submission: successful submit calls API and navigates back
  - Pre-fill (edit only): entity data loaded into fields
  - Navigation: back/cancel button calls navigate(-1)
  - Error handling: API error displays error message

Tools: Vitest + React Testing Library + @testing-library/user-event
Mock API: vi.mock() or MSW — NEVER real API calls
```

---

## 4. Suggest Additional Scenarios

```
Call: mcp__smartstack__suggest_test_scenarios
  module: "{module_code}"

Review suggestions and add relevant test cases.
```

---

## 5. Analyze Coverage

```
Call: mcp__smartstack__analyze_test_coverage
  module: "{module_code}"

Target: >= 80% coverage
If under 80%: identify uncovered paths, scaffold additional tests
```

---

## 6. Test Summary

```
**APEX SmartStack - Final Test Sweep**

| Layer | Inline Tests | Final Sweep | Total |
|-------|-------------|-------------|-------|
| Domain | {count} (Layer 2) | {count} | {total} |
| Application | {count} (Layer 2) | {count} | {total} |
| API | {count} (Layer 2) | {count} | {total} |
| Security | — | {count} | {count} |
| Frontend Forms | {count} (Layer 3) | {count} | {total} |

**Total tests:** {count}
**Estimated coverage:** {%}
```

---

## 7. Save Output (if save_mode)

Write to `{output_dir}/07-tests.md` with test scaffolding results.

---

## NEXT STEP

Load `steps/step-08-run-tests.md`
