# AIPaper-assisant - Testing & Development Workflow

## 🧪 Testing Strategy

### Testing Philosophy
- **Test-Driven Development**: Write tests before implementation
- **Platform Isolation**: Each platform tested independently
- **Error Scenario Coverage**: Test failure modes extensively
- **Performance Validation**: Ensure rate limiting works correctly
- **Integration Confidence**: Cross-platform compatibility verified

### Test Categories

#### 1. Unit Tests
**Purpose**: Test individual components in isolation

**Coverage**:
- Model validation (`PaperFactory`)
- Rate limiting logic
- Error handling utilities
- Data transformation functions

**Example**:
```typescript
describe('PaperFactory', () => {
  it('should validate required fields', () => {
    const invalidData = { title: '', authors: [] };
    expect(() => PaperFactory.create(invalidData)).toThrow();
  });

  it('should normalize DOI format', () => {
    const paper = PaperFactory.create({ doi: '10.1000/abc' });
    expect(paper.doi).toBe('10.1000/abc');
  });
});
```

#### 2. Integration Tests
**Purpose**: Test platform API integrations

**Coverage**:
- Actual API calls to platforms
- Authentication validation
- Response parsing
- Error handling from APIs

**Example**:
```typescript
describe('ArxivSearcher Integration', () => {
  it('should search for papers successfully', async () => {
    const searcher = new ArxivSearcher();
    const results = await searcher.search('machine learning');

    expect(results).toBeInstanceOf(Array);
    expect(results.length).toBeGreaterThan(0);
    expect(results[0]).toHaveProperty('title');
    expect(results[0]).toHaveProperty('authors');
  });

  it('should handle rate limiting', async () => {
    const searcher = new ArxivSearcher();

    // Make multiple rapid requests
    const promises = Array(20).fill(null).map(() =>
      searcher.search('test')
    );

    await expect(Promise.all(promises)).resolves.not.toThrow();
  });
});
```

#### 3. End-to-End Tests
**Purpose**: Test complete user workflows

**Coverage**:
- MCP tool registration
- Full search workflows
- Download processes
- Multi-platform searches

**Example**:
```typescript
describe('E2E Search Workflow', () => {
  it('should search across multiple platforms', async () => {
    const client = await connectToMCP();

    const results = await client.callTool('search_papers', {
      query: 'quantum computing',
      maxResults: 5
    });

    expect(results.papers).toBeDefined();
    expect(results.papers.length).toBeLessThanOrEqual(5);
    expect(results.metadata.totalResults).toBeGreaterThan(0);
  });
});
```

#### 4. Performance Tests
**Purpose**: Validate system performance under load

**Coverage**:
- Rate limiting effectiveness
- Concurrent request handling
- Memory usage patterns
- Response time benchmarks

**Example**:
```typescript
describe('Performance Tests', () => {
  it('should handle 100 concurrent searches', async () => {
    const startTime = Date.now();

    const searches = Array(100).fill(null).map(() =>
      searchPapers('artificial intelligence', { maxResults: 10 })
    );

    const results = await Promise.all(searches);
    const duration = Date.now() - startTime;

    expect(duration).toBeLessThan(30000); // 30 seconds max
    expect(results.every(r => r.success)).toBe(true);
  });
});
```

#### 5. Security Tests
**Purpose**: Ensure secure operation

**Coverage**:
- Input sanitization
- API key protection
- Error message safety
- Rate limit enforcement

**Example**:
```typescript
describe('Security Tests', () => {
  it('should sanitize malicious input', async () => {
    const maliciousQuery = '<script>alert("xss")</script>';
    const results = await searchPapers(maliciousQuery);

    // Verify no script tags in results
    const hasScript = results.papers.some(p =>
      p.title.includes('<script>') || p.abstract.includes('<script>')
    );
    expect(hasScript).toBe(false);
  });

  it('should not expose API keys in errors', async () => {
    process.env.WOS_API_KEY = 'secret-key-123';

    try {
      await searchPapers('test', { platform: 'wos' });
    } catch (error) {
      expect(error.message).not.toContain('secret-key-123');
    }
  });
});
```

### Test Structure

```
src/test/
├── unit/                    # Unit tests
│   ├── models/
│   ├── utils/
│   └── platforms/
├── integration/             # Integration tests
│   ├── platforms/
│   └── api/
├── e2e/                     # End-to-end tests
│   ├── mcp/
│   └── workflows/
├── fixtures/                # Test data
│   ├── papers/
│   └── responses/
└── helpers/                 # Test utilities
    ├── mock-server/
    └── test-data/
```

## 🔧 Development Workflow

### 1. Local Development Setup

```bash
# 1. Clone and setup
git clone https://github.com/yourusername/paper-search-nodejs.git
cd paper-search-nodejs

# 2. Install dependencies
npm install

# 3. Setup environment
cp .env.example .env
# Edit .env with your configurations

# 4. Run in development mode
npm run dev

# 5. Run tests
npm test
```

### 2. Development Cycle

#### Feature Development
1. **Create feature branch**
```bash
git checkout -b feature/new-platform-integration
```

2. **Write tests first**
```typescript
// test/platforms/new-platform.test.ts
describe('NewPlatformSearcher', () => {
  it('should implement search interface', async () => {
    const searcher = new NewPlatformSearcher();
    const results = await searcher.search('test query');
    expect(results).toBeInstanceOf(Array);
  });
});
```

3. **Implement feature**
```typescript
// src/platforms/NewPlatformSearcher.ts
export class NewPlatformSearcher extends PaperSource {
  constructor() {
    super('new-platform', {
      rateLimit: { tokens: 10, refillRate: 1 }
    });
  }

  async search(query: string): Promise<Paper[]> {
    // Implementation
  }
}
```

4. **Run tests continuously**
```bash
npm run test:watch
```

5. **Refactor and optimize**
```bash
npm run lint
npm run format
npm run type-check
```

#### Bug Fix Process
1. **Write failing test**
2. **Fix the bug**
3. **Verify test passes**
4. **Check for regressions**

### 3. Code Quality Tools

#### Linting
```bash
npm run lint              # Run ESLint
npm run lint:fix          # Auto-fix issues
```

#### Formatting
```bash
npm run format            # Format with Prettier
npm run format:check      # Check formatting
```

#### Type Checking
```bash
npm run type-check        # TypeScript validation
```

#### Pre-commit Hooks
Automatic checks before commits:
- Lint validation
- Type checking
- Test execution
- Format verification

### 4. Testing Commands

```bash
# Run all tests
npm test

# Run specific test suite
npm run test:unit
npm run test:integration
npm run test:e2e

# Run with coverage
npm run test:coverage

# Run in watch mode
npm run test:watch

# Run specific test file
npm test -- --testNamePattern="ArxivSearcher"

# Debug tests
npm run test:debug
```

### 5. Platform-Specific Testing

#### Testing New Platform Integration

1. **Create test file**
```bash
touch src/test/platforms/your-platform.test.ts
```

2. **Write comprehensive tests**
```typescript
describe('YourPlatformSearcher', () => {
  let searcher: YourPlatformSearcher;

  beforeEach(() => {
    searcher = new YourPlatformSearcher();
  });

  describe('search', () => {
    it('should return valid paper structure', async () => {
      const results = await searcher.search('machine learning');

      expect(results).toBeInstanceOf(Array);
      results.forEach(paper => {
        expect(paper).toHaveProperty('title');
        expect(paper).toHaveProperty('authors');
        expect(paper).toHaveProperty('year');
        expect(paper.source).toBe('your-platform');
      });
    });

    it('should handle empty results', async () => {
      const results = await searcher.search('xyzxyzxyz-noresults');
      expect(results).toEqual([]);
    });

    it('should handle API errors gracefully', async () => {
      // Mock API failure
      jest.spyOn(searcher, 'performSearch').mockRejectedValue(
        new Error('API Error')
      );

      await expect(searcher.search('test')).rejects.toThrow('API Error');
    });
  });

  describe('rate limiting', () => {
    it('should respect rate limits', async () => {
      const startTime = Date.now();

      // Make multiple requests
      await Promise.all([
        searcher.search('test1'),
        searcher.search('test2'),
        searcher.search('test3')
      ]);

      const duration = Date.now() - startTime;
      expect(duration).toBeGreaterThanOrEqual(2000); // Minimum delay
    });
  });
});
```

3. **Test with real API**
```typescript
describe('YourPlatform API Integration', () => {
  // Skip if no API key
  const describeIfKey = process.env.YOUR_PLATFORM_API_KEY ? describe : describe.skip;

  describeIfKey('with API key', () => {
    it('should authenticate successfully', async () => {
      const searcher = new YourPlatformSearcher();
      const results = await searcher.search('test query');

      expect(results.length).toBeGreaterThan(0);
    });
  });
});
```

## 📊 Test Coverage Guidelines

### Coverage Targets
- **Statements**: > 85%
- **Branches**: > 80%
- **Functions**: > 90%
- **Lines**: > 85%

### Coverage Reports
```bash
# Generate coverage report
npm run test:coverage

# View HTML report
open coverage/index.html

# Check specific file coverage
npm run test:coverage -- --testPathPattern=ArxivSearcher
```

### What to Test

#### Must Test
- Core business logic
- Error handling paths
- Rate limiting behavior
- Data transformation
- Authentication flows

#### Should Test
- Edge cases
- Boundary conditions
- Concurrent operations
- Performance benchmarks

#### Optional
- Simple getters/setters
- Third-party integrations (mock)
- Configuration loading

## 🚀 Continuous Integration

### CI/CD Pipeline

```yaml
# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
    - uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Run linting
      run: npm run lint

    - name: Type check
      run: npm run type-check

    - name: Run tests
      run: npm run test:coverage

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
```

### Pre-release Checks

1. **Version bump**
```bash
npm version patch  # or minor/major
```

2. **Update changelog**
```bash
npm run changelog
```

3. **Full test suite**
```bash
npm run test:all
```

4. **Security audit**
```bash
npm audit
npm audit fix
```

5. **Build verification**
```bash
npm run build
npm pack
```

## 🏗️ Test Data Management

### Mock Data Strategy

#### 1. Platform Responses
```typescript
// test/fixtures/responses/arxiv-response.xml
export const arxivResponse = `
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <title>Test Paper Title</title>
    <author><name>John Doe</name></author>
    <published>2024-01-01T00:00:00Z</published>
  </entry>
</feed>`;
```

#### 2. Test Paper Objects
```typescript
// test/fixtures/papers/sample-papers.ts
export const samplePapers: Paper[] = [
  {
    title: 'Attention Is All You Need',
    authors: ['Ashish Vaswani', 'Noam Shazeer'],
    year: 2017,
    doi: '10.5555/3295222.3295349',
    source: 'arxiv',
    pdfUrl: 'https://arxiv.org/pdf/1706.03762.pdf'
  }
];
```

### Test Environment Setup

#### 1. Test Database (optional)
```typescript
// test/helpers/test-db.ts
export async function setupTestDB() {
  // Setup in-memory database for tests
}

export async function teardownTestDB() {
  // Cleanup
}
```

#### 2. Mock Servers
```typescript
// test/helpers/mock-server.ts
export function createMockPlatform() {
  return http.createServer((req, res) => {
    if (req.url?.includes('/search')) {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify(mockSearchResponse));
    }
  });
}
```

## 📈 Quality Metrics

### Code Quality Gates

#### Pre-commit
- Lint passes
- Type checks pass
- Unit tests > 90% pass
- No console.log statements

#### Pre-push
- All tests pass
- Coverage > 85%
- No security vulnerabilities
- Documentation updated

#### Pre-merge
- CI pipeline passes
- Code review approved
- Integration tests pass
- Performance benchmarks met

### Monitoring

#### Test Flakiness
```bash
# Run tests multiple times to detect flaky tests
for i in {1..10}; do
  npm test -- --testNamePattern="unreliable test"
done
```

#### Performance Regression
```bash
# Benchmark current performance
npm run test:performance:baseline

# Compare with previous
npm run test:performance:compare
```

## 🔧 Debugging Tips

### Test Debugging

1. **Enable verbose output**
```bash
DEBUG=* npm test
```

2. **Run single test**
```bash
npm test -- --testNamePattern="specific test name"
```

3. **Debug in VS Code**
```json
{
  "type": "node",
  "request": "launch",
  "name": "Debug Tests",
  "program": "${workspaceFolder}/node_modules/.bin/jest",
  "args": ["--runInBand", "--testNamePattern", "${input:testName}"]
}
```

### Platform Debugging

1. **Check API responses**
```typescript
// Add logging to platform searcher
async search(query: string): Promise<Paper[]> {
  console.log('Search request:', { query, timestamp: Date.now() });
  const response = await this.makeRequest(query);
  console.log('Raw response:', response.data);
  return this.transformResults(response.data);
}
```

2. **Mock network issues**
```typescript
// Test network failures
jest.spyOn(axios, 'get').mockRejectedValue(new Error('Network error'));
```

---

*This testing and development workflow ensures high-quality code and reliable platform integrations. Regular updates to testing strategies should be made as the project evolves.*