# TypeScript Mutation Testing Example

This example demonstrates how to use PMAT for mutation testing on a TypeScript project.

## Overview

Mutation testing is a technique to evaluate the quality of your test suite by introducing small changes (mutations) to your code and checking if your tests detect them.

**Mutation Score** = (Killed Mutants / Total Valid Mutants) × 100%

- **Killed**: Test suite detected the mutation (good!)
- **Survived**: Test suite did not detect the mutation (test gap!)
- **CompileError**: Mutation caused invalid syntax
- **Timeout**: Mutation caused infinite loop

## Project Structure

```
typescript-mutation-testing/
├── src/
│   └── calculator.ts         # Calculator module with 8 functions
├── tests/
│   └── calculator.test.ts    # Comprehensive test suite (24 tests)
├── package.json               # Node.js dependencies
├── tsconfig.json              # TypeScript configuration
├── jest.config.js             # Jest test configuration
└── README.md                  # This file
```

## Getting Started

### 1. Install Dependencies

First, install the required Node.js packages:

```bash
cd examples/typescript-mutation-testing
npm install
```

### 2. Run Tests

Verify that all tests pass:

```bash
npm test
```

You should see:

```
PASS  tests/calculator.test.ts
  Arithmetic Operations
    ✓ add should correctly add two numbers (2 ms)
    ✓ subtract should correctly subtract two numbers
    ✓ multiply should correctly multiply two numbers
    ✓ divide should correctly divide two numbers (1 ms)
  Logical Operations
    ✓ isEven should detect even numbers
    ✓ max should return maximum value
  Complex Operations
    ✓ factorial should calculate factorial correctly (1 ms)
    ✓ factorial should throw error for negative numbers
    ✓ isPrime should detect prime numbers
  Edge Cases
    ✓ add with large numbers
    ✓ multiply by zero
    ✓ divide by zero returns null
    ✓ isEven with negative numbers
    ✓ max with equal numbers
    ✓ factorial of zero
    ✓ isPrime for 2
    ✓ isPrime for large numbers

Test Suites: 1 passed, 1 total
Tests:       24 passed, 24 total
```

### 3. Run Mutation Testing

Use PMAT to perform mutation testing on the calculator module:

```bash
# Install pmat if not already installed
cargo install pmat

# Run mutation testing on the calculator module
pmat mutate --target src/calculator.ts
```

### 4. Analyze Results

PMAT will generate mutants and run your tests against each one. Example output:

```
Mutation Testing Results
========================
Total Mutants: 55
Killed: 50 (90.9%)
Survived: 3 (5.5%)
Compile Errors: 2 (3.6%)
Timeouts: 0 (0.0%)

Mutation Score: 90.9%
```

### 5. Review Survived Mutants (Test Gaps)

Use `--failures-only` to see only survived mutants:

```bash
pmat mutate --target src/calculator.ts --failures-only
```

This shows which mutations your tests failed to catch, indicating gaps in test coverage.

## Example: Detecting Test Gaps

### Original Code
```typescript
export function max(a: number, b: number): number {
  if (a > b) {  // Mutation: change > to >=
    return a;
  } else {
    return b;
  }
}
```

### Mutation
```typescript
export function max(a: number, b: number): number {
  if (a >= b) {  // Mutated: > changed to >=
    return a;
  } else {
    return b;
  }
}
```

### Test That Catches It
```typescript
test('max should return maximum value', () => {
  expect(max(5, 3)).toBe(5);  // Would pass with either > or >=
  expect(max(2, 8)).toBe(8);  // Would pass with either > or >=
  expect(max(4, 4)).toBe(4);  // CRITICAL: Catches the >= mutation!
});
```

Without the `max(4, 4)` test case, the `> to >=` mutation would **survive**, indicating a test gap.

## Output Formats

### Text (Default)
```bash
pmat mutate --target src/calculator.ts
```

Color-coded terminal output with summary and individual mutant details.

### JSON
```bash
pmat mutate --target src/calculator.ts --output-format json > results.json
```

Machine-readable JSON for CI/CD integration.

### Markdown
```bash
pmat mutate --target src/calculator.ts --output-format markdown > results.md
```

Human-readable report with tables and statistics.

## Advanced Usage

### Control Concurrency
```bash
# Use 4 parallel jobs
pmat mutate --target src/calculator.ts --jobs 4
```

### Set Timeout
```bash
# Timeout individual tests after 10 seconds
pmat mutate --target src/calculator.ts --timeout 10
```

### Enforce Mutation Score Threshold
```bash
# Fail if mutation score is below 85%
pmat mutate --target src/calculator.ts --threshold 85
```

This will exit with code 1 if the mutation score is below 85%, useful for CI/CD quality gates.

## CI/CD Integration

### GitHub Actions

Create `.github/workflows/mutation-testing.yml`:

```yaml
name: Mutation Testing

on: [push, pull_request]

jobs:
  mutation-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: |
          cd examples/typescript-mutation-testing
          npm install

      - name: Run tests
        run: |
          cd examples/typescript-mutation-testing
          npm test

      - name: Install Rust and pmat
        run: |
          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
          source $HOME/.cargo/env
          cargo install pmat

      - name: Run mutation tests
        run: |
          cd examples/typescript-mutation-testing
          pmat mutate --target src/calculator.ts --failures-only --threshold 80
```

### GitLab CI

Add to `.gitlab-ci.yml`:

```yaml
mutation-testing:
  image: node:18
  stage: test
  before_script:
    - cd examples/typescript-mutation-testing
    - npm install
    - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
    - source $HOME/.cargo/env
    - cargo install pmat
  script:
    - npm test
    - pmat mutate --target src/calculator.ts --output-format json > mutation_results.json
  artifacts:
    reports:
      junit: mutation_results.json
```

## Best Practices

1. **Run mutation testing regularly** - Integrate into CI/CD pipeline
2. **Set reasonable thresholds** - 80-90% mutation score is excellent
3. **Focus on critical code** - Test business logic thoroughly
4. **Review survived mutants** - Each one represents a potential bug
5. **Use `--failures-only`** - Reduces noise in large codebases
6. **Test edge cases** - Boundary values catch more mutations
7. **Combine with coverage** - High code coverage + high mutation score = robust tests

## Understanding Mutation Operators

PMAT applies various mutation operators to TypeScript code:

### Arithmetic Operators
- `+` → `-`, `*`, `/`, `%`
- `-` → `+`, `*`, `/`, `%`
- `*` → `+`, `-`, `/`, `%`
- `/` → `+`, `-`, `*`, `%`
- `%` → `+`, `-`, `*`, `/`

### Comparison Operators
- `===` → `!==`, `<`, `>`, `<=`, `>=`
- `==` → `!=`, `<`, `>`, `<=`, `>=`
- `<` → `<=`, `>`, `>=`, `===`, `!==`
- `>` → `>=`, `<`, `<=`, `===`, `!==`
- `<=` → `<`, `>=`, `!==`
- `>=` → `>`, `<=`, `!==`
- `!==` → `===`, `<`, `>`, `<=`, `>=`
- `!=` → `==`, `<`, `>`, `<=`, `>=`

### Logical Operators
- `&&` → `||`
- `||` → `&&`
- `!` → (removed)

### Boundary Values
- `<` → `<=`
- `>` → `>=`
- `0` → `1`, `-1`
- `i++` → `i--`

### Return Values
- `return x` → `return null`, `return 0`, `return -1`
- `return true` → `return false`
- `return false` → `return true`

## Example Results

```
╔═══════════════════════════════════════════╗
║     Mutation Testing Summary              ║
╠═══════════════════════════════════════════╣
║ Total Mutants:        55                  ║
║ Killed:               50 (90.9%)          ║
║ Survived:             3 (5.5%)            ║
║ Compile Errors:       2 (3.6%)            ║
║ Timeouts:             0 (0.0%)            ║
╠═══════════════════════════════════════════╣
║ Mutation Score:       90.9% ✓             ║
╚═══════════════════════════════════════════╝
```

## Running Tests Manually

### With Jest
```bash
# Run all tests
npm test

# Run with coverage report
npm run test:coverage

# Run in watch mode
npm run test:watch
```

### Build TypeScript
```bash
npm run build
```

## Troubleshooting

### Module Resolution Errors

If you get `Cannot find module` errors, ensure your `tsconfig.json` is properly configured:

```json
{
  "compilerOptions": {
    "esModuleInterop": true,
    "resolveJsonModule": true
  }
}
```

### Jest Configuration Issues

If tests don't run, verify `jest.config.js` has the correct preset:

```javascript
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};
```

### Mutation Testing Takes Too Long

Use the `--timeout` flag to limit test execution time:

```bash
pmat mutate --target src/calculator.ts --timeout 5
```

Or reduce concurrency if tests are CPU-bound:

```bash
pmat mutate --target src/calculator.ts --jobs 1
```

## Resources

- **PMAT Repository**: https://github.com/paiml/paiml-mcp-agent-toolkit
- **Crates.io**: https://crates.io/crates/pmat
- **Documentation**: `server/README.md`
- **Mutation Testing Paper**: [Mutation Testing: An Empirical Evaluation](https://dl.acm.org/doi/10.1145/3183440) *(requires ACM subscription)*

## License

This example is part of the PMAT project and is provided as-is for demonstration purposes.
