npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@majkapp/journey

v1.2.2

Published

Contract-first journey testing with auto-generated user guides, coverage tracking, and living documentation

Readme

@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

npm install --save-dev @majkapp/journey

Quick Start

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:

# 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:

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

{
  "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:

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

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