npm package: @majkapp/journey
Description: Contract-first journey testing with auto-generated user guides, coverage tracking, and living documentation
Author: MAJK Team
Latest version: 1.2.2

# @majkapp/journey

Document and test user journeys with living documentation and screenshots.

## Features

- **Unified Testing & Documentation** - Write tests that generate docs
- **Implementation-Independent** - Tests survive UI refactors
- **Screenshot Contracts** - Document what each screenshot should show
- **Living Documentation** - Docs auto-generate from passing tests
- **High-Level API** - Describe user journeys, not DOM selectors
- **Journey Artifacts** - Save complete execution snapshots with git tracking
- **Reproducible Documentation** - Generate docs from saved artifacts without re-running tests

## Installation

```bash
npm install --save-dev @majkapp/journey
```

## Quick Start

```typescript
import { UserJourney } from '@majkapp/journey';
import { runBot } from '@majkapp/bot-plugin-server';

test('User can create a task', async () => {
  await runBot({ /* config */ }, async (bot) => {
    const page = bot.getPage();

    const journey = new UserJourney(bot, page, {
      pageName: 'task-creation'
    });

    journey
      .defineUseCase({
        title: 'Create Task',
        description: 'User creates a new task',
        implementationIndependence: {
          dontCareAbout: [
            'Button text',
            'Form layout',
            'Color schemes'
          ],
          careAbout: [
            'Actions work correctly',
            'States transition properly',
            'Data appears accurately'
          ]
        }
      })
      .addStep({
        title: 'Open form',
        description: 'User clicks to open task creation form',
        action: async (page, bot) => {
          await bot.click('start-task');
        },
        visual: {
          description: 'Form opens with empty fields',
          expectedElements: [
            '[data-majk-role="task-form"]'
          ]
        }
      })
      .addStep({
        title: 'Submit task',
        description: 'User fills and submits form',
        action: async (page, bot) => {
          await page.locator('[data-majk-role="title-input"]').fill('Test');
          await bot.click('submit-task');
        },
        verify: async (page) => {
          const list = await page.locator('[data-majk-role="task-list"]');
          const state = await list.getAttribute('data-majk-state');
          if (state !== 'populated') throw new Error('Task not created');
        },
        visual: {
          description: 'New task appears in list',
          expectedElements: [
            '[data-majk-role="task-list-item"]'
          ],
          expectedStates: [
            'task-list: state="populated"'
          ]
        }
      });

    await journey.execute();
  });
});
```

## Generated Documentation

Running the test generates `docs/UserFlows/create-task.md`:

```markdown
# Create Task

> **Status**: ✅ All steps passing
> **Last Updated**: 2025-11-15T...

## Use Case
User creates a new task

## Workflow
1. Open form
2. Submit task

## Implementation Independence
**We don't care about:**
- Button text
- Form layout
- Color schemes

**We only care about:**
- Actions work correctly
- States transition properly
- Data appears accurately

## Step-by-Step Flow

### Step 1: Open form
![Open form](../../screenshots/task-creation/01-open-form.png)

**What you should see:**
Form opens with empty fields

**Expected Elements:**
- [data-majk-role="task-form"]
```

## API

### `UserJourney`

Constructor:
```typescript
new UserJourney(bot: BotHelper, page: Page, options: JourneyOptions)
```

Methods:
- `defineUseCase(useCase: UseCase): this` - Define the use case
- `addStep(step: JourneyStep): this` - Add a step
- `execute(): Promise<JourneyResult>` - Run journey

### Types

See `src/types.ts` for full type definitions.

## Journey Artifacts

Every journey execution creates a complete artifact that captures:
- Use case and implementation independence
- Git commit, branch, and clean/dirty status
- Execution timestamp and total duration
- Every step with timing, status, and visual contracts
- All screenshots in a self-contained directory

### Artifact Structure

```
.journey-artifacts/
  task-creation/
    2025-11-15T14-10-30_6a4ecd3/    # timestamp_gitCommit
      manifest.json                  # Complete execution data
      screenshots/
        01-open-form.png
        02-submit-task.png
```

### manifest.json

```json
{
  "journey": {
    "name": "task-creation",
    "useCase": { "title": "...", "description": "..." }
  },
  "execution": {
    "timestamp": "2025-11-15T14:10:30.778Z",
    "duration": 10070,
    "status": "passed",
    "gitCommit": "6a4ecd3",
    "gitBranch": "feature_task_manager",
    "gitClean": false
  },
  "steps": [
    {
      "index": 1,
      "title": "Open form",
      "status": "passed",
      "duration": 4422,
      "timestamp": "2025-11-15T14:10:30.779Z",
      "screenshot": "screenshots/01-open-form.png",
      "visual": { "description": "...", "expectedElements": [...] }
    }
  ]
}
```

### Generate Docs from Artifacts

Once you have artifacts, you can regenerate documentation without re-running tests:

```typescript
import { UserJourney } from '@majkapp/journey';

// Generate docs from latest artifact run
await UserJourney.generateDocsFromArtifact(
  '.journey-artifacts/task-creation/2025-11-15T14-10-30_6a4ecd3',
  'docs/UserFlows'
);
```

Generated documentation includes:
- Git commit info and timestamp
- Individual step durations
- Status indicators (✅/❌)
- Absolute paths to artifact screenshots

### Benefits of Artifacts

1. **Historical Record** - Track how journeys evolved across commits
2. **No Re-runs Required** - Generate docs anytime without browser tests
3. **Review Process** - Share artifacts with stakeholders for review
4. **CI/CD Integration** - Archive artifacts, compare across builds
5. **Regression Detection** - Compare screenshots between commits
6. **Performance Tracking** - Monitor journey duration over time

### Configuration

```typescript
const journey = new UserJourney(bot, page, {
  pageName: 'task-creation',
  docsDir: './docs/UserFlows',
  screenshotsDir: './screenshots',
  artifactsDir: './.journey-artifacts',  // default
  saveArtifacts: true,                    // default
  generateDocs: true                      // default
});
```

## Best Practices

1. **Use semantic data-majk-* attributes** in your UI
2. **Document what users see**, not implementation details
3. **Test behavior**, not markup
4. **Generate docs from tests** to keep them in sync
5. **Commit artifacts to git** for historical tracking (optional)
6. **Use artifacts for documentation** in CI/CD pipelines

## License

MIT