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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@olane/o-test

v0.7.37

Published

Comprehensive testing utilities and best practices for O-Network node development using Mocha/Chai (libp2p ecosystem)

Readme

@olane/o-test

Testing utilities and best practices for O-Network node development

⚠️ Important: We Use Mocha, Not Jest

Since O-Network is built on the libp2p ecosystem, we use aegir with Mocha for testing (NOT Jest).

  • ✅ Use: aegir, chai, Mocha syntax (before, after, .to.equal())
  • ❌ Don't use: jest, @types/jest, ts-jest

See MOCHA-MIGRATION.md for migration guide.

Overview

@olane/o-test provides comprehensive testing guidelines, utilities, and examples for building reliable O-Network nodes in the Olane OS ecosystem.

Quick Start

Installation

# From your package directory
pnpm install --save-dev @olane/o-test

# Install testing dependencies (aegir uses Mocha internally)
pnpm install --save-dev aegir chai

Important: Since we're using the libp2p ecosystem, we use aegir as our test runner, which uses Mocha (not Jest). Do not install Jest dependencies.

Basic Test Structure

import 'dotenv/config';
import { describe, it, before, after } from 'mocha';
import { expect } from 'chai';
import { oLeaderNode } from '@olane/o-leader';
import { MyTool } from '../src/my-tool.tool.js';

describe('MyTool', () => {
  let leaderNode: oLeaderNode;
  let tool: MyTool;

  before(async () => {
    // Create leader
    leaderNode = new oLeaderNode({
      parent: null,
      leader: null,
    });
    await leaderNode.start();

    // Create tool
    tool = new MyTool({
      parent: leaderNode.address,
      leader: leaderNode.address,
    });

    // Register with parent
    (tool as any).hookInitializeFinished = () => {
      leaderNode.addChildNode(tool);
    };

    await tool.start();
  });

  after(async () => {
    await tool.stop();
    await leaderNode.stop();
  });

  it('should start successfully', () => {
    expect(tool.state).to.equal(NodeState.RUNNING);
  });

  it('should execute method', async () => {
    const result = await tool.useSelf({
      method: 'my_method',
      params: { test: 'value' },
    });

    expect(result.success).to.be.true;
    expect(result.result.data).to.exist;
  });
});

Documentation

📚 Complete Testing Guide

Comprehensive guide covering:

  • Testing philosophy and baseline requirements
  • Testing stack and configuration
  • Lifecycle, method, and parent-child testing patterns
  • Error handling and validation tests
  • Test helpers and utilities
  • CI/CD integration
  • Common pitfalls and troubleshooting

🔄 Jest to Mocha Migration Guide

Quick reference for converting tests from Jest to Mocha:

  • Side-by-side syntax comparison
  • Complete code examples
  • Common pitfalls and solutions
  • Quick reference table

Baseline Requirements

Every O-Network package must have:

| Requirement | File/Location | |-------------|---------------| | Test directory | /test/ | | Lifecycle test | test/lifecycle.spec.ts | | Method tests | test/methods.spec.ts | | Aegir config | .aegir.js (optional) | | Test script | "test": "aegir test" in package.json |

Note: No Jest configuration needed - aegir uses Mocha internally for the libp2p ecosystem.

Minimum Test Coverage

  •  All nodes must have lifecycle tests (start/stop)
  •  All public methods (_tool_*) must have happy path tests
  •  All required parameters must have validation tests
  •  Parent-child patterns must test registration and routing
  •  Critical error paths must be tested

Running Tests

# Run all tests
pnpm test

# Run in watch mode
pnpm test:watch

# Run specific test file
pnpm test test/lifecycle.spec.ts

# Run with coverage
pnpm test -- --coverage

Configuration Files

.aegir.js (Optional)

Aegir works out of the box with sensible defaults. Configuration is only needed for customization:

export default {
  test: {
    target: ['node'],  // or ['browser'], or ['node', 'browser']
  },
  build: {
    bundlesizeMax: '100KB',
  },
};

Important for libp2p ecosystem:

  • ✅ Aegir uses Mocha as the test runner (not Jest)
  • ✅ Use Mocha syntax: before, after, beforeEach, afterEach
  • ✅ Use Chai assertions: expect().to.equal(), expect().to.exist, etc.
  • ❌ Do NOT install or use jest, @types/jest, or ts-jest

Critical Testing Rules

 DO:

  • Load environment with import 'dotenv/config'
  • Use .js extensions in imports (ESM requirement)
  • Create leader node before child nodes
  • Inject hookInitializeFinished for parent-child registration
  • Clean up all nodes in afterEach
  • Access response data via result.result.data
  • Test both success and error paths

L DON'T:

  • Override start() method (use hooks instead)
  • Forget to call stop() on nodes
  • Access result.data directly (use result.result.data)
  • Use mocks for node instances (use real nodes)
  • Share mutable state between tests

Testing Philosophy

We prioritize practical, integration-oriented tests that validate real node behavior:

  •  Real node instances over mocks
  •  Actual lifecycle management
  •  Parent-child relationships
  •  Simple, focused test cases
  •  Integration over unit isolation

Test Patterns

Lifecycle Testing

it('should start and stop successfully', async () => {
  const node = new MyTool({
    parent: null,
    leader: null,
  });

  await node.start();
  expect(node.state).to.equal(NodeState.RUNNING);

  await node.stop();
  expect(node.state).to.equal(NodeState.STOPPED);
});

Method Testing

it('should validate required parameters', async () => {
  const result = await tool.useSelf({
    method: 'my_method',
    params: {}, // Missing required params
  });

  expect(result.success).to.be.false;
  expect(result.error).to.include('required');
});

Parent-Child Testing

it('should create and route to child', async () => {
  // Create child
  const createResult = await manager.useSelf({
    method: 'create_worker',
    params: { workerId: 'worker-1' },
  });
  expect(createResult.success).to.be.true;

  // Route to child
  const routeResult = await manager.useSelf({
    method: 'use_worker',
    params: {
      workerId: 'worker-1',
      method: 'process_task',
      params: { data: 'test' },
    },
  });
  expect(routeResult.success).to.be.true;
});

Common Pitfalls

Pitfall 1: Missing Hook Injection

// L WRONG
const tool = new MyTool({ parent: leader.address, leader: leader.address });
await tool.start(); // Child not registered!

//  CORRECT
const tool = new MyTool({ parent: leader.address, leader: leader.address });
(tool as any).hookInitializeFinished = () => {
  leaderNode.addChildNode(tool);
};
await tool.start();

Pitfall 2: No Cleanup

// L WRONG
it('test', async () => {
  const tool = new MyTool({});
  await tool.start();
  // No cleanup - nodes leak!
});

//  CORRECT
afterEach(async () => {
  if (tool) await tool.stop();
  if (leader) await leader.stop();
});

Pitfall 3: Wrong Response Access

// L WRONG
const data = result.data; // undefined!

//  CORRECT
const data = result.result.data;

Test Helpers

Create shared utilities for common patterns:

// test/helpers/test-utils.ts
export async function createToolWithLeader<T>(
  ToolClass: new (config: any) => T,
  config: any = {}
): Promise<{ leader: oLeaderNode; tool: T }> {
  const leader = new oLeaderNode({ parent: null, leader: null });
  await leader.start();

  const tool = new ToolClass({
    ...config,
    parent: leader.address,
    leader: leader.address,
  });

  (tool as any).hookInitializeFinished = () => {
    leader.addChildNode(tool as any);
  };

  await (tool as any).start();

  return { leader, tool };
}

Example Tests

See the test/ directory for complete examples:

  • test/lifecycle.spec.ts - Node lifecycle testing
  • test/methods.spec.ts - Method validation and execution
  • test/parent-child.spec.ts - Manager/worker pattern testing
  • test/helpers/ - Shared test utilities

Resources

Package Structure

o-test/
�� src/
   �� index.ts                  # Public exports
   �� example-tool.tool.ts      # Example tool implementation
   �� methods/
       �� example.methods.ts    # Method definitions
�� test/
   �� lifecycle.spec.ts         # Lifecycle tests
   �� methods.spec.ts           # Method tests
   �� parent-child.spec.ts      # Parent-child tests
   �� helpers/
      �� test-utils.ts         # Test utilities
   �� fixtures/
       �� mock-data.ts          # Test data
�� jest.config.js                # Jest configuration
�� .aegir.js                     # Aegir configuration
�� tsconfig.json                 # TypeScript configuration
�� package.json                  # Package metadata
�� README.md                     # This file
�� TESTING.md                    # Complete testing guide
�� CLAUDE.md                     # Development guide

Contributing

When adding tests:

  1. Follow the patterns in TESTING.md
  2. Ensure all baseline requirements are met
  3. Test both success and error paths
  4. Clean up all resources
  5. Use descriptive test names

License

See the root LICENSE file in the Olane monorepo.

Support


Remember:

  •  Real nodes, not mocks
  •  Proper lifecycle management
  •  Clean up in afterEach
  •  Test integration, not isolation
  •  Keep it simple

For detailed testing patterns and examples, see TESTING.md.