diff --git a/apps/api/src/job-steps/job-steps.controller.spec.ts b/apps/api/src/job-steps/job-steps.controller.spec.ts index 6da9bee..c331ab2 100644 --- a/apps/api/src/job-steps/job-steps.controller.spec.ts +++ b/apps/api/src/job-steps/job-steps.controller.spec.ts @@ -1,12 +1,41 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; +import { ExecutionContext } from "@nestjs/common"; + +// Mock @prisma/client BEFORE importing other modules +vi.mock("@prisma/client", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + JobStepPhase: { + SETUP: "SETUP", + EXECUTION: "EXECUTION", + VALIDATION: "VALIDATION", + CLEANUP: "CLEANUP", + }, + JobStepType: { + COMMAND: "COMMAND", + AI_ACTION: "AI_ACTION", + GATE: "GATE", + ARTIFACT: "ARTIFACT", + }, + JobStepStatus: { + PENDING: "PENDING", + RUNNING: "RUNNING", + COMPLETED: "COMPLETED", + FAILED: "FAILED", + SKIPPED: "SKIPPED", + }, + }; +}); + +// Import after mocking import { JobStepsController } from "./job-steps.controller"; import { JobStepsService } from "./job-steps.service"; import { JobStepPhase, JobStepType, JobStepStatus } from "@prisma/client"; import { AuthGuard } from "../auth/guards/auth.guard"; import { WorkspaceGuard } from "../common/guards/workspace.guard"; import { PermissionGuard } from "../common/guards/permission.guard"; -import { ExecutionContext } from "@nestjs/common"; describe("JobStepsController", () => { let controller: JobStepsController; diff --git a/apps/api/src/job-steps/job-steps.service.spec.ts b/apps/api/src/job-steps/job-steps.service.spec.ts index 76a3a1a..95c8ef3 100644 --- a/apps/api/src/job-steps/job-steps.service.spec.ts +++ b/apps/api/src/job-steps/job-steps.service.spec.ts @@ -1,11 +1,42 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import { Test, TestingModule } from "@nestjs/testing"; -import { JobStepsService } from "./job-steps.service"; -import { PrismaService } from "../prisma/prisma.service"; -import { JobStepPhase, JobStepType, JobStepStatus } from "@prisma/client"; import { NotFoundException } from "@nestjs/common"; import { CreateStepDto, UpdateStepDto } from "./dto"; +// Mock @prisma/client BEFORE importing the service +vi.mock("@prisma/client", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + JobStepPhase: { + SETUP: "SETUP", + EXECUTION: "EXECUTION", + VALIDATION: "VALIDATION", + CLEANUP: "CLEANUP", + }, + JobStepType: { + COMMAND: "COMMAND", + AI_ACTION: "AI_ACTION", + GATE: "GATE", + ARTIFACT: "ARTIFACT", + }, + JobStepStatus: { + PENDING: "PENDING", + RUNNING: "RUNNING", + COMPLETED: "COMPLETED", + FAILED: "FAILED", + SKIPPED: "SKIPPED", + }, + }; +}); + +// Import after mocking +import { JobStepsService } from "./job-steps.service"; +import { PrismaService } from "../prisma/prisma.service"; + +// Re-import the enums from the mock for use in tests +import { JobStepPhase, JobStepType, JobStepStatus } from "@prisma/client"; + describe("JobStepsService", () => { let service: JobStepsService; let prisma: PrismaService; diff --git a/docs/scratchpads/182-fix-prisma-enum-tests.md b/docs/scratchpads/182-fix-prisma-enum-tests.md new file mode 100644 index 0000000..7d2371c --- /dev/null +++ b/docs/scratchpads/182-fix-prisma-enum-tests.md @@ -0,0 +1,101 @@ +# Issue #182: [BLOCKER] Fix failing Prisma enum import tests in job-steps.service.spec.ts + +## Objective + +Fix Prisma enum import issues in job-steps.service.spec.ts that are causing test failures and blocking other work. + +## Approach + +1. Read the failing test file to understand the issue +2. Check the Prisma schema to understand the correct enum definitions +3. Fix the enum imports and usage in the test file +4. Run tests to verify the fix +5. Ensure 85% coverage is maintained + +## Progress + +- [x] Read job-steps.service.spec.ts +- [x] Read Prisma schema to verify enum definitions +- [x] Identify the root cause of the import failures +- [x] Fix enum imports and usage +- [x] Run tests to verify fix +- [x] Run full test suite to check for regressions +- [x] Verify test coverage (16/16 tests passing) +- [ ] Commit changes + +## Root Cause Analysis + +The test file imports `JobStepPhase`, `JobStepType`, and `JobStepStatus` from `@prisma/client`: + +```typescript +import { JobStepPhase, JobStepType, JobStepStatus } from "@prisma/client"; +``` + +However, in the test environment with mocked Prisma, these enum imports are undefined, causing errors like: + +- `Cannot read properties of undefined (reading 'SETUP')` +- `Cannot read properties of undefined (reading 'COMPLETED')` + +The Prisma schema defines these enums at lines 147-167: + +- `JobStepPhase`: SETUP, EXECUTION, VALIDATION, CLEANUP +- `JobStepType`: COMMAND, AI_ACTION, GATE, ARTIFACT +- `JobStepStatus`: PENDING, RUNNING, COMPLETED, FAILED, SKIPPED + +## Solution + +Instead of importing from `@prisma/client`, we need to manually define these enums in the test file or import them from the DTOs which properly export the types. Since the DTOs already import from `@prisma/client`, we'll define the enum constants directly in the test file to avoid circular dependencies. + +### Implementation + +Used `vi.mock()` with `importOriginal` to mock the `@prisma/client` module and provide the enum values: + +```typescript +vi.mock("@prisma/client", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + JobStepPhase: { + SETUP: "SETUP", + EXECUTION: "EXECUTION", + VALIDATION: "VALIDATION", + CLEANUP: "CLEANUP", + }, + JobStepType: { + COMMAND: "COMMAND", + AI_ACTION: "AI_ACTION", + GATE: "GATE", + ARTIFACT: "ARTIFACT", + }, + JobStepStatus: { + PENDING: "PENDING", + RUNNING: "RUNNING", + COMPLETED: "COMPLETED", + FAILED: "FAILED", + SKIPPED: "SKIPPED", + }, + }; +}); +``` + +This approach: + +1. Imports the actual Prisma client using `importOriginal` +2. Spreads the actual exports to preserve PrismaClient and other types +3. Overrides only the enum values that were undefined in the test environment +4. Must be placed BEFORE importing any modules that depend on @prisma/client + +### Files Modified + +- `/home/localadmin/src/mosaic-stack/apps/api/src/job-steps/job-steps.service.spec.ts` +- `/home/localadmin/src/mosaic-stack/apps/api/src/job-steps/job-steps.controller.spec.ts` + +## Testing + +- Run unit tests: `pnpm test:api` +- Verify coverage: `pnpm test:coverage` + +## Notes + +- This is a BLOCKER issue - must be resolved before other work can proceed +- Need to maintain minimum 85% coverage