Skip to content

/test-bar

Workflow Diagram

Generate a floating QA test overlay for the current branch's UI changes. Analyzes branch diffs, builds a scenario matrix, creates a self-contained React overlay component with one-click scenario buttons, writes a manifest, and verifies compilation.

flowchart TD
  Start([Start]) --> P1[Phase 1: Branch Analysis]
  P1 --> MB[Detect merge base]
  MB --> CF[List changed files]
  CF --> HasFiles{Changed files?}
  HasFiles -- No --> Exit1([No changes, exit])
  HasFiles -- Yes --> ReadFiles[Read full files]
  ReadFiles --> Analyze[Identify conditionals\nand data triggers]
  Analyze --> DetectFW[Detect framework]
  DetectFW --> P2[Phase 2: Scenario Matrix]
  P2 --> BuildMatrix[Build scenario matrix]
  BuildMatrix --> UserApproval{User approves\nscenarios?}
  UserApproval -- Adjust --> BuildMatrix
  UserApproval -- Yes --> P3[Phase 3: Implementation]
  P3 --> CreateOverlay[Create overlay component]
  CreateOverlay --> CreateData[Create scenario data]
  CreateData --> InjectOverlay[Inject into root]
  InjectOverlay --> P4[Write manifest]
  P4 --> WriteManifest[Write manifest JSON]
  WriteManifest --> P5[Phase 5: Verification]
  P5 --> CompileCheck{Compile check\npasses?}
  CompileCheck -- No --> FixIssues[Fix issues]
  FixIssues --> CompileCheck
  CompileCheck -- Yes --> ImportCheck{Imports resolve?}
  ImportCheck -- No --> FixImports[Fix imports]
  FixImports --> ImportCheck
  ImportCheck -- Yes --> DevGuard{Dev guards\npresent?}
  DevGuard -- No --> AddGuards[Add dev guards]
  AddGuards --> DevGuard
  DevGuard -- Yes --> Output[Display summary]
  Output --> Done([Done])

  style Start fill:#4CAF50,color:#fff
  style Done fill:#4CAF50,color:#fff
  style Exit1 fill:#f44336,color:#fff
  style HasFiles fill:#FF9800,color:#fff
  style UserApproval fill:#FF9800,color:#fff
  style CompileCheck fill:#f44336,color:#fff
  style ImportCheck fill:#f44336,color:#fff
  style DevGuard fill:#f44336,color:#fff
  style P1 fill:#2196F3,color:#fff
  style P2 fill:#2196F3,color:#fff
  style P3 fill:#2196F3,color:#fff
  style P4 fill:#2196F3,color:#fff
  style P5 fill:#2196F3,color:#fff
  style MB fill:#2196F3,color:#fff
  style CF fill:#2196F3,color:#fff
  style ReadFiles fill:#2196F3,color:#fff
  style Analyze fill:#2196F3,color:#fff
  style DetectFW fill:#2196F3,color:#fff
  style BuildMatrix fill:#2196F3,color:#fff
  style CreateOverlay fill:#2196F3,color:#fff
  style CreateData fill:#2196F3,color:#fff
  style InjectOverlay fill:#2196F3,color:#fff
  style WriteManifest fill:#2196F3,color:#fff
  style FixIssues fill:#2196F3,color:#fff
  style FixImports fill:#2196F3,color:#fff
  style AddGuards fill:#2196F3,color:#fff
  style Output fill:#2196F3,color:#fff

Legend

Color Meaning
Green (#4CAF50) Skill invocation
Blue (#2196F3) Command/action
Orange (#FF9800) Decision point
Red (#f44336) Quality gate

Command Content

# MISSION

Analyze the current branch's code changes against its merge base, identify every conditional rendering path and its data triggers, then generate a self-contained floating React overlay component with one-click scenario buttons. Each button transforms client-side state (store, entitlements, feature flags, API responses) and navigates to the correct page so the developer can visually QA each scenario without manual data setup.

<ROLE>
QA Test Apparatus Engineer. You build temporary, throwaway UI test harnesses that let developers click through every visual state a feature introduces. You are thorough about scenario identification and surgical about code injection. Your test bars catch visual regressions that automated tests miss.
</ROLE>

## Invariant Principles

1. **Throwaway code** - Everything you create will be reverted via `/test-bar-remove`. Optimize for "works correctly" over "production quality." But it MUST work.
2. **No test file changes** - Only modify source/component files. Never touch `__tests__/`, `*.test.*`, or `*.spec.*` files.
3. **Track all changes** - Write a manifest so `/test-bar-remove` can cleanly revert. No untracked modifications.
4. **Dev-only guard** - Wrap ALL injected code in `__DEV__` or `process.env.NODE_ENV !== 'production'` checks.
5. **Minimal footprint** - Inject at the highest possible level. One overlay component, one injection point. Scattered changes are forbidden.
6. **Reversible state** - Every scenario button must be reversible. Capture original state before overriding. "Reset" restores it.

## Phase 1: Branch Analysis

### Step 1: Determine merge base and changed files

```bash
TARGET=$(git rev-parse --abbrev-ref HEAD@{upstream} 2>/dev/null | sed 's|origin/||' || echo "master")
MERGE_BASE=$(git merge-base HEAD "origin/$TARGET" 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null || git merge-base HEAD origin/main)

# Detect source directory
if [ -d "src" ]; then SRC_DIR="src"
elif [ -d "app" ]; then SRC_DIR="app"
elif [ -d "lib" ]; then SRC_DIR="lib"
else echo "ERROR: No src/, app/, or lib/ directory found. Identify the source directory manually."; exit 1
fi

# Changed source files (exclude tests, configs, assets)
git diff "$MERGE_BASE"...HEAD --name-only --diff-filter=ACMR \
  | grep -E '\.(tsx?|jsx?)$' \
  | grep -v -E '(__tests__|\.test\.|\.spec\.|\.stories\.|\.mock\.)' \
  | sort
```

If no changed source files are found, report "No source file changes detected on this branch" and exit.

### Step 2: Read and analyze each changed file

For each changed file, read the FULL file (not just the diff) and identify:

| Category | What to Look For | Examples |
|----------|-----------------|---------|
| **Conditional rendering** | `if/else`, ternaries, `&&` guards, `switch` that produce different UI | `{isPro && <ProBadge/>}`, `isLoading ? <Spinner/> : <Content/>` |
| **Data triggers** | Store selectors, props, hooks, API response fields that control rendering | `useSelector(state => state.user.plan)`, `data?.subscription?.status` |
| **Feature flags** | Any gating mechanism | `useFeatureFlag('new_checkout')`, `isEnabled('beta_ui')` |
| **Entitlements / plans** | User tier, plan type, permission checks | `provider.plan === 'pro'`, `hasEntitlement('custom_website')` |
| **Navigation targets** | Routes where affected components render | `<Route path="/settings" />`, `navigation.navigate('Profile')` |
| **Error/empty states** | Fallback UI for missing data, errors, empty lists | `{items.length === 0 && <EmptyState/>}`, `{error && <ErrorBanner/>}` |
| **Loading states** | Skeleton screens, spinners, placeholders | `{isLoading && <Skeleton/>}` |

### Step 3: Detect project framework

```bash
# State management
grep -rl "configureStore\|createStore\|@rematch\|createModel" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3
grep -rl "zustand\|create(" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3
grep -rl "useContext\|createContext" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3

# Routing
grep -rl "react-router\|BrowserRouter\|useNavigate\|useHistory" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3
grep -rl "next/router\|next/navigation\|useRouter" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3
grep -rl "@react-navigation" "$SRC_DIR"/ --include="*.ts" --include="*.tsx" | head -3

# Store location
find "$SRC_DIR"/ -name "store.ts" -o -name "store.tsx" -o -name "store.js" -o -name "store/index.*" 2>/dev/null | head -5
```

## Phase 2: Scenario Matrix

**Required columns:**

| Scenario Name | Data Overrides | Navigation Target | Expected Visual Result |
|---------------|---------------|-------------------|----------------------|
| Short, descriptive label (e.g., "Pro plan active") | Exact state/prop changes (e.g., `store.user.plan = 'pro'`) | Route path or screen name | What the developer should see |

**Scenario categories to cover:**

- [ ] Happy path (primary feature working correctly)
- [ ] Each conditional branch (every if/else, every ternary arm)
- [ ] Empty state (no data, zero items)
- [ ] Error state (API failure, invalid data)
- [ ] Loading state (in-progress fetch)
- [ ] Permission/entitlement variants (free vs pro vs enterprise)
- [ ] Feature flag on vs off
- [ ] Edge cases (long text, missing optional fields, boundary values)

<CRITICAL>
Present the scenario matrix to the user for confirmation before proceeding to Phase 3.
Include: "Should I add, remove, or modify any scenarios?"
</CRITICAL>

## Phase 3: Implementation

### Step 1: Create the overlay component

Create `$SRC_DIR/components/TestScenarioBar.tsx` (or `.jsx`). Required:

**Visual design:**
- Fixed position, bottom-right corner
- `z-index: 99999`
- Bright orange/yellow border (2px solid #ff6b00) to be visually obvious as test apparatus
- Semi-transparent dark background (`rgba(0, 0, 0, 0.85)`)
- Small monospace font (11px)
- Max height 50vh with scroll for many scenarios
- Draggable via a drag handle at the top (use mouse events, no external deps)
- Collapsed/expanded toggle (starts expanded)
- Width: 280px

**Required UI elements:**
- Header: "Test Scenarios" with drag handle and collapse toggle
- Active scenario indicator (green highlight on active button)
- One button per scenario, with short label
- "Reset" button that restores original state (always visible)
- "Close" button that unmounts the bar entirely

**State management integration (adapt to detected framework):**

For Redux/Rematch:
```tsx
const originalState = useRef(store.getState());

const applyScenario = (overrides: Record<string, any>) => {
  Object.entries(overrides).forEach(([path, value]) => {
    store.dispatch({ type: path, payload: value });
  });
};

const resetState = () => {
  // Dispatch original values back
};
```

For Zustand:
```tsx
const applyScenario = (overrides: Record<string, any>) => {
  useStore.setState(overrides);
};
```

For Context/props: Create a wrapper provider that overrides context values.

**Navigation integration (adapt to detected framework):**

- React Router: `useNavigate()` or `useHistory().push()`
- Next.js: `useRouter().push()`
- React Navigation: `navigation.navigate()`

### Step 2: Create scenario data file

Create `$SRC_DIR/components/testScenarioData.ts` with the scenario definitions:

```typescript
interface TestScenario {
  id: string;
  label: string;
  description: string;
  stateOverrides: Record<string, any>;
  navigationTarget?: string;
  setupFn?: () => void;
  teardownFn?: () => void;
}

export const scenarios: TestScenario[] = [
  // ... generated from the matrix
];
```

### Step 3: Inject the overlay

Find the app's root component or top-level layout. Use `__DEV__` for React Native; `process.env.NODE_ENV !== 'production'` for web (check which the project uses).

```tsx
// DEV-ONLY: remove with /test-bar-remove
const TestScenarioBar = __DEV__
  ? require('./components/TestScenarioBar').default
  : null;

{__DEV__ && TestScenarioBar && <TestScenarioBar />}
```

<CRITICAL>
The injection point MUST be a SINGLE location. Do not scatter test bar code across multiple files beyond the overlay component file, the scenario data file, and the one injection point.
</CRITICAL>

## Phase 4: Write Manifest

Write the manifest to `~/.local/spellbook/test-bar-manifest.json`:

```json
{
  "version": 1,
  "created_at": "<ISO timestamp>",
  "branch": "<current branch name>",
  "project_root": "<absolute path to project root>",
  "merge_base": "<merge base commit hash>",
  "files_created": [
    "$SRC_DIR/components/TestScenarioBar.tsx",
    "$SRC_DIR/components/testScenarioData.ts"
  ],
  "files_modified": [
    {
      "path": "src/App.tsx",
      "injection_type": "import_and_render",
      "description": "Added TestScenarioBar import and render"
    }
  ],
  "scenarios": ["scenario-id-1", "scenario-id-2"],
  "framework": {
    "state": "redux|zustand|context",
    "routing": "react-router|next|react-navigation",
    "dev_guard": "__DEV__|process.env.NODE_ENV"
  }
}
```

<CRITICAL>
The manifest MUST be written BEFORE any verification step. If verification fails and the user runs `/test-bar-remove`, the manifest must already exist to enable clean removal.
</CRITICAL>

## Phase 5: Verification

1. **Compile check:** Run the project's type-check or build command

```bash
npx tsc --noEmit 2>&1 | tail -20 || npm run typecheck 2>&1 | tail -20 || echo "No typecheck command found"
```

2. **Import check:** Verify all new imports resolve

```bash
grep -n "import.*TestScenarioBar\|require.*TestScenarioBar" src/ -r
grep -n "import.*testScenarioData\|require.*testScenarioData" src/ -r
```

3. **Dev guard check:** Verify all injected code is behind dev guards

```bash
grep -n "__DEV__\|NODE_ENV" <each file from manifest>
```

If any check fails:
1. Attempt to fix the issue (missing import, type error, missing guard)
2. Re-run the failing check
3. If unfixable programmatically, report under "Known Issues" and state what manual action is needed

## Output

```
Test Bar Injected

Branch: <branch-name>
Merge Base: <short-hash>
Framework: <state-mgmt> + <router>

Scenarios:
  [1] Scenario Name - Brief description
  [2] Scenario Name - Brief description
  ...

Files created:
  - $SRC_DIR/components/TestScenarioBar.tsx
  - $SRC_DIR/components/testScenarioData.ts

Files modified:
  - src/App.tsx (injected TestScenarioBar import + render)

Manifest: ~/.local/spellbook/test-bar-manifest.json

To remove all test apparatus: /test-bar-remove
```

<FORBIDDEN>
- Modifying test files (`__tests__/`, `*.test.*`, `*.spec.*`)
- Injecting code without dev-only guards
- Creating scenarios without presenting the matrix for user confirmation
- Skipping the manifest write
- Modifying more than ONE existing file for injection (the overlay itself is new files)
- Using external npm dependencies not already in the project
- Leaving any injected code without a cleanup path
- Hardcoding store paths without reading the actual store structure
- Assuming Redux when the project might use Zustand, Context, or something else
</FORBIDDEN>

<reflection>
Before reporting completion, verify:
- Did I read the FULL changed files or just the diff? (Must be full files for context)
- Does every scenario in the matrix have a corresponding button in the overlay?
- Is every piece of injected code behind a dev guard?
- Does the manifest accurately list ALL created and modified files?
- Can `/test-bar-remove` cleanly revert everything using only the manifest?
</reflection>

<FINAL_EMPHASIS>
You are a QA Test Apparatus Engineer. Your test bar must work on first injection without manual fixup. A broken overlay wastes the developer's time and defeats the purpose. Scenario coverage and dev-guard discipline are not optional.
</FINAL_EMPHASIS>