Skip to content

TypeError when toggling "Enable automated testing" checkbox #198

@AhamSammich

Description

@AhamSammich

Bug: TypeError when toggling "Enable automated testing" checkbox on existing features

Description

When editing an existing feature and unchecking the "Enable automated testing" checkbox (to enable manual verification), the app crashes with:

TypeError: Cannot read properties of undefined (reading 'map')
  at TestingTabContent (testing-tab-content.tsx:63)
Screen.Recording.2025-12-20.at.2.22.36.PM.mov

Steps to Reproduce

  1. Open an existing feature that was created before the verification steps field was added
  2. Open the edit feature dialog
  3. Navigate to the "Options" tab
  4. Uncheck the "Enable automated testing" checkbox
  5. App crashes immediately

Expected Behavior

The verification steps section should appear with the add button or the existing steps, allowing the user to add manual verification steps.

Actual Behavior

The app crashes with a TypeError because steps is undefined when steps.map() is called.

Root Cause Analysis

The Feature interface declares steps as a required field:

export interface Feature {
  // ...
  steps: string[];  // Required, not optional
  // ...
}

However, there's a type/runtime data mismatch:

  1. Old persisted data: Features created before the verification steps feature was added don't have a steps field in their feature.json files
  2. Missing data migration: When features are loaded in use-board-features.ts (lines 62-72), there's backward compatibility logic for model and thinkingLevel, but not for steps:
    const featuresWithIds = result.features.map(
      (f: any, index: number) => ({
        ...f,
        // ... other fields ...
        model: f.model || "opus",
        thinkingLevel: f.thinkingLevel || "none",
        // ❌ Missing: steps: f.steps || [],
      })
    );
  3. Component assumes valid data: TestingTabContent calls steps.map() without checking if steps exists, causing the crash when the verification section renders

Proposed Solutions

Solution 1: Add data migration at load time ⭐ Primary Fix

Initialize steps when loading features, like other backward-compatible fields. This ensures all features entering the application state conform to the Feature interface contract:

// apps/ui/src/components/views/board-view/hooks/use-board-features.ts (line ~62)
const featuresWithIds = result.features.map(
  (f: any, index: number) => ({
    ...f,
    id: f.id || `feature-${index}-${Date.now()}`,
    status: f.status || "backlog",
    startedAt: f.startedAt,
    model: f.model || "opus",
    thinkingLevel: f.thinkingLevel || "none",
    steps: f.steps || [],  // ✅ Add this line
  })
);

Solution 2: Add defensive coding in component (Defense in depth)

While the data should always be valid after Solution 1, add defensive checks in TestingTabContent as a safety measure:

// apps/ui/src/components/views/board-view/shared/testing-tab-content.tsx (line ~63)
{(steps || []).map((step, index) => (
  <Input
    key={index}
    value={step}
    placeholder={`Verification step ${index + 1}`}
    onChange={(e) => handleStepChange(index, e.target.value)}
    data-testid={`${testIdPrefix ? testIdPrefix + "-" : ""}feature-step-${index}${testIdPrefix ? "" : "-input"}`}
  />
))}

Also update helper functions:

const handleStepChange = (index: number, value: string) => {
  const newSteps = [...(steps || [])];  // ✅ Add defensive check
  newSteps[index] = value;
  onStepsChange(newSteps);
};

const handleAddStep = () => {
  onStepsChange([...(steps || []), ""]);  // ✅ Add defensive check
};

Environment

  • App: Automaker
  • Affected files:
    • apps/ui/src/store/app-store.ts (interface definition)
    • apps/ui/src/components/views/board-view/hooks/use-board-features.ts (data loading)
    • apps/ui/src/components/views/board-view/shared/testing-tab-content.tsx (component)

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions