--- phase: 04-review-download-security plan: 01 type: tdd wave: 1 depends_on: [] files_modified: - src/components/wizard/ReviewStep.test.tsx - src/store/reducer.test.ts autonomous: true requirements: [CONF-02, CONF-03, DOWN-01, DOWN-02, DOWN-03, DOWN-04, DOWN-05, DOWN-06, SECU-01, SECU-02, SECU-03] must_haves: truths: - "All ReviewStep requirement behaviors have named, failing test stubs (RED)" - "SECU-03 is verified by a spy on Storage.prototype.setItem in reducer.test.ts" - "Mock setup for URL.createObjectURL, URL.revokeObjectURL, navigator.clipboard.writeText exists in test file" - "npm test runs without crashes (passWithNoTests: true covers missing implementation)" artifacts: - path: "src/components/wizard/ReviewStep.test.tsx" provides: "RED test stubs for CONF-02, CONF-03, DOWN-01–DOWN-06, SECU-01, SECU-02" exports: [] - path: "src/store/reducer.test.ts" provides: "SECU-03 assertion added to existing reducer test suite" contains: "spyOn(Storage.prototype, 'setItem')" key_links: - from: "src/components/wizard/ReviewStep.test.tsx" to: "src/components/wizard/ReviewStep" via: "import ReviewStep" pattern: "import.*ReviewStep" - from: "src/components/wizard/ReviewStep.test.tsx" to: "src/utils/downloadFile" via: "import downloadFile (mocked)" pattern: "vi.mock.*downloadFile" --- Write Wave 0 TDD stubs: all failing test cases for Phase 4 requirements, plus SECU-03 assertion in existing reducer tests. Purpose: Establish the RED baseline before any implementation. Tests define the contract that implementation plans must satisfy. Following the established project pattern from Phases 1–3. Output: ReviewStep.test.tsx (stub file, RED tests for all 11 req IDs) + SECU-03 assertion in reducer.test.ts. @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/04-review-download-security/04-RESEARCH.md @.planning/phases/04-review-download-security/04-VALIDATION.md @src/store/types.ts @src/store/context.tsx @src/store/reducer.test.ts @src/generators/index.ts From src/store/types.ts: ```typescript export interface WizardState { currentStep: number; remote: { name: string; backendType: BackendType | null; params: Record; }; deployment: { includeInstall: boolean; configPath: 'machine-wide' | 'user-profile'; scriptTargets: ('intune' | 'rmm')[]; }; } ``` From src/store/context.tsx: ```typescript export function useWizard(): { state: WizardState; dispatch: React.Dispatch } export function WizardProvider({ children }: { children: React.ReactNode }): JSX.Element ``` From src/generators/index.ts: ```typescript export { buildRcloneConf } from './rclone-conf'; export { buildIntuneInstall } from './intune-install'; export { buildIntuneDetection } from './intune-detection'; export { buildRmmScript } from './rmm-script'; // All accept (state: WizardState): string // buildRcloneConf throws when backendType is null or name is empty ``` Task 1: Write ReviewStep.test.tsx with RED stubs for all Phase 4 requirements src/components/wizard/ReviewStep.test.tsx - CONF-02: rclone.conf preview text is present in rendered output when state has a valid backendType - CONF-03: clicking "Copy" on the rclone.conf block calls navigator.clipboard.writeText with the conf content - DOWN-01: clicking "Download rclone.conf" calls downloadFile with content and filename 'rclone.conf' - DOWN-02: clicking "Download Intune Install" calls downloadFile with content and filename 'intune-install.ps1' - DOWN-03: clicking "Download Intune Detection" calls downloadFile with content and filename 'intune-detection.ps1' - DOWN-04: clicking "Download RMM script" calls downloadFile with content and filename 'rmm-script.ps1' - DOWN-05: clicking "Download ZIP" calls downloadZip with all 4 file entries - DOWN-06: each output block has a copy button that calls clipboard.writeText with that block's content - SECU-01: download buttons are disabled when security checkbox is unchecked; enabled after checking - SECU-02: rendered output contains text about no data being sent to a server Create src/components/wizard/ReviewStep.test.tsx. Follow the established project pattern: - Use `expect.fail('not yet implemented')` for each stub (named RED failure, not import-error RED) - Import `{ describe, it, expect, vi, beforeEach }` from 'vitest' - Import `{ render, screen, fireEvent }` from '@testing-library/react' - Import `ReviewStep` from './ReviewStep' (will not exist yet — that is fine; tests will fail at import or at stub) - Import `* as downloadFileModule` from '../../utils/downloadFile' for mocking - Import `* as downloadZipModule` from '../../utils/downloadZip' for mocking File-level mock setup (before describe block): ```typescript vi.mock('../../utils/downloadFile', () => ({ downloadFile: vi.fn() })); vi.mock('../../utils/downloadZip', () => ({ downloadZip: vi.fn() })); ``` In a beforeEach, stub global APIs: ```typescript beforeEach(() => { vi.stubGlobal('navigator', { clipboard: { writeText: vi.fn().mockResolvedValue(undefined) }, }); vi.stubGlobal('URL', { createObjectURL: vi.fn(() => 'blob:mock'), revokeObjectURL: vi.fn(), }); vi.clearAllMocks(); }); ``` Helper: create a WizardProvider wrapper with a fully populated state (azureblob backend, name='my-remote', params={account:'acct',key:'k'}, deployment defaults) for rendering ReviewStep in tests. Write one `describe` block per requirement ID (embed ID in describe name for traceability, e.g. `describe('CONF-02: live rclone.conf preview', ...)`). Each describe contains an `it` that calls `expect.fail('not yet implemented')`. Do NOT write real assertions yet — the whole file should be stubs that fail with 'not yet implemented' (except the import/mock wiring which must work). Run: `npm test -- src/components/wizard/ReviewStep.test.tsx` — expect FAIL (RED) because ReviewStep does not exist yet. That is the correct Wave 0 state. npm test -- src/components/wizard/ReviewStep.test.tsx 2>&1 | tail -20 ReviewStep.test.tsx exists with named stubs for all 10 requirement behaviors (CONF-02, CONF-03, DOWN-01 through DOWN-06, SECU-01, SECU-02). npm test fails with import or stub errors for ReviewStep only — NOT with TypeScript compilation errors in the test file itself. Task 2: Add SECU-03 assertion to reducer.test.ts src/store/reducer.test.ts - SECU-03: localStorage.setItem and sessionStorage.setItem are never called during any wizard reducer dispatch Edit src/store/reducer.test.ts. Add a new `it` block at the end of the existing `describe('wizardReducer', ...)` block: ```typescript it('SECU-03: never writes to localStorage or sessionStorage', () => { const setItemSpy = vi.spyOn(Storage.prototype, 'setItem'); // Dispatch every action type to cover all reducer branches wizardReducer(INITIAL_STATE, { type: 'SET_STEP', payload: 1 }); wizardReducer(INITIAL_STATE, { type: 'SET_BACKEND_TYPE', payload: 'azureblob' }); wizardReducer(INITIAL_STATE, { type: 'SET_REMOTE_NAME', payload: 'test' }); wizardReducer(INITIAL_STATE, { type: 'SET_REMOTE_PARAMS', payload: { key: 'val' } }); wizardReducer(INITIAL_STATE, { type: 'SET_DEPLOYMENT', payload: { includeInstall: true } }); wizardReducer(INITIAL_STATE, { type: 'RESET' }); expect(setItemSpy).not.toHaveBeenCalled(); setItemSpy.mockRestore(); }); ``` Also add `vi` to the import line: change `import { describe, it, expect }` to `import { describe, it, expect, vi }`. Run: `npm test -- src/store/reducer.test.ts` — expect GREEN (reducer already does not touch storage). npm test -- src/store/reducer.test.ts 2>&1 | tail -10 reducer.test.ts has the SECU-03 test and it passes GREEN. All pre-existing reducer tests still pass. After both tasks: `npm test` runs without TypeScript errors in reviewed files. reducer.test.ts is fully GREEN. ReviewStep.test.tsx fails with stub or module-not-found errors (RED — expected). - src/components/wizard/ReviewStep.test.tsx exists with 10 named describe/it blocks (one per requirement behavior) - src/store/reducer.test.ts has SECU-03 assertion and passes fully GREEN - No new TypeScript compilation errors anywhere in the test files - Wave 0 baseline established: RED for ReviewStep, GREEN for SECU-03 After completion, create `.planning/phases/04-review-download-security/04-01-SUMMARY.md`