From 44cc57ad850ed8049b72a34f9c14d75a1663a0c1 Mon Sep 17 00:00:00 2001 From: Nuwan Date: Sun, 8 Feb 2026 12:15:30 +0530 Subject: [PATCH] docs(17): create phase plan for Jest unit tests Phase 17: Unit Tests (Jest) - 1 plan in 1 wave - 1 parallel, 0 sequential - Covers UNIT-01, UNIT-02, UNIT-03 requirements - Ready for execution Co-Authored-By: Claude Opus 4.5 --- .../phases/17-unit-tests-jest/17-01-PLAN.md | 325 ++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 .planning/phases/17-unit-tests-jest/17-01-PLAN.md diff --git a/.planning/phases/17-unit-tests-jest/17-01-PLAN.md b/.planning/phases/17-unit-tests-jest/17-01-PLAN.md new file mode 100644 index 000000000..b132c9a4f --- /dev/null +++ b/.planning/phases/17-unit-tests-jest/17-01-PLAN.md @@ -0,0 +1,325 @@ +--- +phase: 17-unit-tests-jest +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js +autonomous: true + +must_haves: + truths: + - "Test file exists and runs without errors" + - "UNIT-01: Test verifies modal renders with currentSession props (privacy, description displayed)" + - "UNIT-02: Test verifies save button calls onSave with correctly transformed payload" + - "UNIT-03: Test verifies loading state disables form interactions" + - "All tests pass with npm run test:unit" + artifacts: + - path: "jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js" + provides: "Jest unit tests for JKSessionSettingsModal component" + min_lines: 80 + contains: "describe('JKSessionSettingsModal'" + key_links: + - from: "JKSessionSettingsModal.test.js" + to: "JKSessionSettingsModal.js" + via: "import" + pattern: "import JKSessionSettingsModal from" + - from: "JKSessionSettingsModal.test.js" + to: "globals.js" + via: "import SESSION_PRIVACY_MAP" + pattern: "SESSION_PRIVACY_MAP" +--- + + +Create Jest unit tests for JKSessionSettingsModal component covering all three requirements: rendering with props, save payload transformation, and loading state behavior. + +Purpose: Enable confident changes to Session Settings modal by having automated test coverage for critical paths +Output: Test file with passing tests for UNIT-01, UNIT-02, UNIT-03 + + + +@/Users/nuwan/.claude/get-shit-done/workflows/execute-plan.md +@/Users/nuwan/.claude/get-shit-done/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md + +# Component under test +@jam-ui/src/components/client/JKSessionSettingsModal.js + +# Existing test pattern to follow +@jam-ui/src/components/client/chat/__tests__/JKChatMessageList.test.js + +# Globals with SESSION_PRIVACY_MAP +@jam-ui/src/helpers/globals.js + + + + + + Task 1: Create test file with setup and mocks + jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js + +Create the __tests__ directory if needed and test file with proper setup: + +1. Create directory structure: + - `jam-ui/src/components/client/__tests__/` (may already exist) + +2. Set up test file with required imports: + ```javascript + import React from 'react'; + import { render, screen, fireEvent } from '@testing-library/react'; + import JKSessionSettingsModal from '../JKSessionSettingsModal'; + import { SESSION_PRIVACY_MAP } from '../../../helpers/globals.js'; + ``` + +3. Mock react-i18next (required because component uses useTranslation): + ```javascript + jest.mock('react-i18next', () => ({ + useTranslation: () => ({ + t: (key) => { + const translations = { + 'new.privacy_opt_public': 'Public', + 'new.privacy_opt_private_invite': 'Private (Invite Only)', + 'new.privacy_opt_private_approve': 'Private (Approval Required)' + }; + return translations[key] || key; + } + }) + })); + ``` + +4. Create helper function for rendering component: + ```javascript + const renderModal = (props = {}) => { + const defaultProps = { + isOpen: true, + toggle: jest.fn(), + currentSession: { + privacy: SESSION_PRIVACY_MAP.private_approve, + description: 'Test session description' + }, + onSave: jest.fn(), + loading: false + }; + return render(); + }; + ``` + +5. Add describe block shell: + ```javascript + describe('JKSessionSettingsModal', () => { + // Tests will be added in next task + }); + ``` + + +File exists at jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js +File compiles without syntax errors: `cd jam-ui && npm run test:unit -- --testPathPattern=JKSessionSettingsModal --passWithNoTests` + + Test file created with all setup code, mocks, and helper functions in place + + + + Task 2: Write tests for all three requirements + jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js + +Add test cases inside the describe block for each requirement: + +**UNIT-01: Modal renders with currentSession props** +```javascript +describe('rendering with currentSession props (UNIT-01)', () => { + test('displays privacy value from currentSession', () => { + renderModal({ + currentSession: { + privacy: SESSION_PRIVACY_MAP.public, + description: '' + } + }); + + const privacySelect = screen.getByTestId('session-privacy'); + expect(privacySelect.value).toBe(String(SESSION_PRIVACY_MAP.public)); + }); + + test('displays description value from currentSession', () => { + const testDescription = 'My test session description'; + renderModal({ + currentSession: { + privacy: SESSION_PRIVACY_MAP.private_approve, + description: testDescription + } + }); + + const descriptionInput = screen.getByRole('textbox'); + expect(descriptionInput.value).toBe(testDescription); + }); + + test('renders modal title', () => { + renderModal(); + expect(screen.getByText('Session Settings')).toBeInTheDocument(); + }); +}); +``` + +**UNIT-02: Save button calls onSave with correct payload** +```javascript +describe('save functionality (UNIT-02)', () => { + test('calls onSave with privacy and description when save clicked', () => { + const mockOnSave = jest.fn(); + renderModal({ + currentSession: { + privacy: SESSION_PRIVACY_MAP.public, + description: 'Original description' + }, + onSave: mockOnSave + }); + + const saveButton = screen.getByRole('button', { name: /save/i }); + fireEvent.click(saveButton); + + expect(mockOnSave).toHaveBeenCalledTimes(1); + expect(mockOnSave).toHaveBeenCalledWith({ + privacy: String(SESSION_PRIVACY_MAP.public), + description: 'Original description' + }); + }); + + test('calls onSave with updated values after user changes', () => { + const mockOnSave = jest.fn(); + renderModal({ + currentSession: { + privacy: SESSION_PRIVACY_MAP.private_approve, + description: '' + }, + onSave: mockOnSave + }); + + // Change privacy + const privacySelect = screen.getByTestId('session-privacy'); + fireEvent.change(privacySelect, { target: { value: SESSION_PRIVACY_MAP.public } }); + + // Change description + const descriptionInput = screen.getByRole('textbox'); + fireEvent.change(descriptionInput, { target: { value: 'New description' } }); + + // Click save + const saveButton = screen.getByRole('button', { name: /save/i }); + fireEvent.click(saveButton); + + expect(mockOnSave).toHaveBeenCalledWith({ + privacy: String(SESSION_PRIVACY_MAP.public), + description: 'New description' + }); + }); +}); +``` + +**UNIT-03: Loading state disables form interactions** +```javascript +describe('loading state (UNIT-03)', () => { + test('disables save button when loading', () => { + renderModal({ loading: true }); + + const saveButton = screen.getByRole('button', { name: /saving/i }); + expect(saveButton).toBeDisabled(); + }); + + test('disables cancel button when loading', () => { + renderModal({ loading: true }); + + const cancelButton = screen.getByRole('button', { name: /cancel/i }); + expect(cancelButton).toBeDisabled(); + }); + + test('disables description textarea when loading', () => { + renderModal({ loading: true }); + + const descriptionInput = screen.getByRole('textbox'); + expect(descriptionInput).toBeDisabled(); + }); + + test('shows "Saving..." text on save button when loading', () => { + renderModal({ loading: true }); + + expect(screen.getByRole('button', { name: /saving/i })).toBeInTheDocument(); + }); +}); +``` + +Note: The privacy select dropdown is NOT disabled when loading (based on component code review - only description textarea has `disabled={loading}`). The tests reflect actual component behavior. + + +Run tests: `cd jam-ui && npm run test:unit -- --testPathPattern=JKSessionSettingsModal` +All tests pass (exit code 0) + + +All three requirements covered with passing tests: +- UNIT-01: 3 tests for rendering (privacy, description, title) +- UNIT-02: 2 tests for save functionality (initial values, updated values) +- UNIT-03: 4 tests for loading state (save disabled, cancel disabled, textarea disabled, button text) + + + + + Task 3: Verify full test suite and clean up + jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js + +1. Run full unit test suite to ensure no regressions: + ```bash + cd jam-ui && npm run test:unit + ``` + +2. Verify test count matches expectations (9 tests total: 3 + 2 + 4) + +3. Check test output shows all test names correctly grouped: + - JKSessionSettingsModal + - rendering with currentSession props (UNIT-01) + - save functionality (UNIT-02) + - loading state (UNIT-03) + +4. If any tests fail, debug and fix: + - Check if component behavior differs from expectations + - Adjust test assertions to match actual component behavior + - Do NOT modify the component - only fix test expectations + +5. Add any missing edge case tests if time permits: + - Empty description handling + - Default privacy value when currentSession.privacy is undefined + + +`cd jam-ui && npm run test:unit` passes with 0 failures +Test file has proper structure with requirement labels in describe blocks + + +All unit tests pass, test file is complete and properly structured with requirement traceability (UNIT-01, UNIT-02, UNIT-03) + + + + + + +1. Test file exists: `ls jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js` +2. All tests pass: `cd jam-ui && npm run test:unit -- --testPathPattern=JKSessionSettingsModal` +3. Full unit test suite passes: `cd jam-ui && npm run test:unit` +4. Requirement coverage: + - UNIT-01: Tests in "rendering with currentSession props" describe block + - UNIT-02: Tests in "save functionality" describe block + - UNIT-03: Tests in "loading state" describe block + + + +1. Test file exists at `jam-ui/src/components/client/__tests__/JKSessionSettingsModal.test.js` +2. UNIT-01 covered: Tests verify privacy and description from currentSession are displayed +3. UNIT-02 covered: Tests verify onSave called with correct payload on save click +4. UNIT-03 covered: Tests verify loading state disables save button, cancel button, and description input +5. All tests pass with `npm run test:unit` +6. No regressions in existing test suite + + + +After completion, create `.planning/phases/17-unit-tests-jest/17-01-SUMMARY.md` +