Skip to content

Testing & Documentation #7

@ada-evorada

Description

@ada-evorada

Issue #9: Testing & Documentation

Epic: #1
Phase: 5 - Polish
Estimated Time: 4-5 days
Priority: High
Depends On: #2, #3, #4, #5, #6

Goal

Comprehensive testing suite and documentation for the Claude Code Mattermost plugin, ensuring reliability and ease of use.

Tasks

1. Unit Tests (Go Backend)

Plugin Core:

  • Slash command parsing and validation
  • Session management (create/stop/status)
  • Bot message posting
  • KV store operations

Bridge Client:

  • REST API calls
  • WebSocket message handling
  • Error handling and retries
  • Connection management

File Operations:

  • File path validation
  • Permission checks
  • Security filtering
// server/plugin_test.go
func TestExecuteCommand(t *testing.T) {
    tests := []struct {
        name    string
        command string
        want    *model.CommandResponse
        wantErr bool
    }{
        {
            name:    "claude without session",
            command: "/claude help me",
            want:    ephemeralResponse("No active session"),
            wantErr: false,
        },
        // ... more test cases
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // test implementation
        })
    }
}

2. Integration Tests (Go)

End-to-End Flows:

  • Start session → send message → receive response
  • File operations (browse → view → edit → save)
  • Interactive buttons (approve/reject)
  • Session lifecycle

Bridge Server Integration:

  • Mock bridge server for testing
  • Real bridge server tests (optional)
// server/integration_test.go
func TestSessionLifecycle(t *testing.T) {
    // Setup test environment
    plugin := setupTestPlugin(t)
    
    // Start session
    resp := plugin.ExecuteCommand(&model.CommandArgs{
        Command: "/claude-start /tmp/test-project",
    })
    assert.Nil(t, resp.Text)
    
    // Verify session created
    session := plugin.getActiveSession(testChannelID)
    assert.NotNil(t, session)
    
    // Send message
    resp = plugin.ExecuteCommand(&model.CommandArgs{
        Command: "/claude hello",
    })
    
    // Stop session
    resp = plugin.ExecuteCommand(&model.CommandArgs{
        Command: "/claude-stop",
    })
}

3. Frontend Tests (React)

Component Tests:

  • Message rendering
  • Interactive buttons
  • Dialogs
// webapp/src/components/test/MessageActions.test.tsx
import { render, fireEvent } from '@testing-library/react';
import MessageActions from '../MessageActions';

describe('MessageActions', () => {
  test('renders approve/reject buttons', () => {
    const { getByText } = render(
      <MessageActions changeId="test-123" />
    );
    
    expect(getByText('✅ Approve')).toBeInTheDocument();
    expect(getByText('❌ Reject')).toBeInTheDocument();
  });
  
  test('calls approve handler on click', () => {
    const onApprove = jest.fn();
    const { getByText } = render(
      <MessageActions changeId="test-123" onApprove={onApprove} />
    );
    
    fireEvent.click(getByText('✅ Approve'));
    expect(onApprove).toHaveBeenCalledWith('test-123');
  });
});

4. Bridge Server Tests (Node.js)

Unit Tests:

  • Session creation/deletion
  • Message handling
  • File operations
  • Database operations
// bridge-server/src/test/session.test.ts
import { SessionManager } from '../session-manager';

describe('SessionManager', () => {
  let manager: SessionManager;
  
  beforeEach(() => {
    manager = new SessionManager();
  });
  
  test('creates session with valid project path', async () => {
    const session = await manager.createSession({
      projectPath: '/tmp/test',
      userId: 'user123',
      channelId: 'channel456',
    });
    
    expect(session.id).toBeDefined();
    expect(session.status).toBe('active');
  });
  
  test('rejects invalid project path', async () => {
    await expect(
      manager.createSession({
        projectPath: '../../../etc/passwd',
        userId: 'user123',
        channelId: 'channel456',
      })
    ).rejects.toThrow('Invalid project path');
  });
});

5. E2E Tests (Optional)

Using Playwright or Cypress for full user flows:

// e2e/tests/basic-flow.spec.ts
import { test, expect } from '@playwright/test';

test('start session and send message', async ({ page }) => {
  // Login to Mattermost
  await page.goto('http://localhost:8065');
  await page.fill('input[name="loginId"]', 'testuser');
  await page.fill('input[name="password"]', 'testpass');
  await page.click('button[type="submit"]');
  
  // Execute slash command
  await page.fill('.post-textbox', '/claude-start /tmp/test-project');
  await page.keyboard.press('Enter');
  
  // Verify bot response
  await expect(page.locator('.post__body').last()).toContainText('Started Claude Code session');
  
  // Send message
  await page.fill('.post-textbox', '/claude add a hello world function');
  await page.keyboard.press('Enter');
  
  // Verify response
  await expect(page.locator('.post__body').last()).toContainText('I\'ll create');
});

6. User Documentation

README.md:

  • Quick start guide
  • Installation instructions
  • Basic usage examples
  • Troubleshooting

docs/USER_GUIDE.md:

# Claude Code Mattermost Plugin - User Guide

## Getting Started

### Starting a Session
1. Type `/claude-start` in any channel
2. Enter your project path
3. Wait for confirmation

### Sending Messages
Use `/claude <your message>` to interact:

/claude add authentication to the login page


### File Operations
Browse files with `/claude-files`:
1. Select a file from the list
2. Choose View, Edit, or Delete
3. Make changes in the dialog

### Interactive Actions
When Claude proposes changes:
- Click **✅ Approve** to accept
- Click **❌ Reject** to decline
- Click **✏️ Modify** to provide feedback

docs/TROUBLESHOOTING.md:

  • Common errors and solutions
  • Debug mode instructions
  • Bridge server issues
  • Permission problems

7. Developer Documentation

docs/DEVELOPMENT.md:

  • Development environment setup
  • Architecture overview
  • Code structure
  • Testing guidelines
  • Contributing workflow

docs/ARCHITECTURE.md:

  • System design
  • Component interactions
  • Data flow diagrams
  • Security considerations

docs/API.md:

  • Bridge server API reference
  • Plugin API endpoints
  • WebSocket protocol
  • Error codes

8. Test Coverage

Coverage Targets:

  • Go backend: ≥80%
  • TypeScript bridge: ≥70%
  • React frontend: ≥60%

Coverage Reports:

# Go coverage
make test-coverage
# Output: coverage.html

# TypeScript coverage
cd bridge-server && npm run test:coverage
# Output: coverage/index.html

# React coverage
cd webapp && npm run test:coverage
# Output: coverage/lcov-report/index.html

9. CI Integration

Add test stages to .github/workflows/ci.yml:

name: CI

on: [push, pull_request]

jobs:
  test-backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-go@v4
        with:
          go-version: '1.21'
      - name: Run tests
        run: |
          cd server
          go test -v -race -coverprofile=coverage.txt ./...
      - name: Upload coverage
        uses: codecov/codecov-action@v3
  
  test-bridge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22'
      - name: Run tests
        run: |
          cd bridge-server
          npm ci
          npm test
  
  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '22'
      - name: Run tests
        run: |
          cd webapp
          npm ci
          npm test

Acceptance Criteria

  • ≥80% backend test coverage
  • ≥70% bridge server test coverage
  • All critical paths have integration tests
  • User guide complete with examples
  • Developer documentation complete
  • API reference documented
  • Troubleshooting guide created
  • CI runs all tests automatically
  • Code coverage reports generated
  • All tests pass in CI

Related Issues

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions