CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hapi--lab

Comprehensive test utility framework for Node.js applications with advanced testing capabilities

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

test-organization.mddocs/

Test Organization

Core functionality for creating test scripts and organizing tests into experiments with setup/teardown hooks. This provides the fundamental building blocks for structuring test suites.

Capabilities

Script Creation

Creates a test script instance that provides the foundation for organizing and executing tests.

/**
 * Creates a test script with test organization capabilities
 * @param options - Optional configuration for script behavior
 * @returns Script instance with test organization methods
 */
function script(options?: ScriptOptions): Script;

interface ScriptOptions {
    /** Determines if execution should be delayed until CLI runs explicitly (default: true) */
    schedule?: boolean;
    /** CLI configuration options */
    cli?: CliOptions;
}

interface Script {
    experiment: Experiment;
    describe: Experiment;  // Alias for experiment
    suite: Experiment;     // Alias for experiment
    test: Test;
    it: Test;              // Alias for test
    before: Setup;
    after: Setup;
    beforeEach: Setup;
    afterEach: Setup;
}

Usage Examples:

const Lab = require('@hapi/lab');

// Basic script creation
const lab = exports.lab = Lab.script();

// Script with options
const lab = exports.lab = Lab.script({ 
    schedule: false  // Don't auto-execute
});

Experiment Definition

Creates test experiments (suites) for organizing related tests with shared setup and teardown.

/**
 * Creates a test experiment for organizing related tests
 * @param title - Descriptive name for the experiment
 * @param content - Function containing tests and sub-experiments
 */
experiment(title: string, content: () => void): void;

/**
 * Creates a test experiment with options
 * @param title - Descriptive name for the experiment
 * @param options - Experiment configuration (excluding plan)
 * @param content - Function containing tests and sub-experiments
 */
experiment(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;

interface Experiment {
    (title: string, content: () => void): void;
    (title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
    /** Run only this experiment, skipping all others */
    only(title: string, content: () => void): void;
    only(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
    /** Skip this experiment during execution */
    skip(title: string, content: () => void): void;
    skip(title: string, options: Omit<TestOptions, 'plan'>, content: () => void): void;
}

Usage Examples:

// Basic experiment
experiment('User authentication', () => {
    // tests go here
});

// Experiment with timeout
experiment('Database operations', { timeout: 5000 }, () => {
    // longer-running tests
});

// Skip experiment
experiment.skip('Broken feature', () => {
    // temporarily disabled tests
});

// Run only this experiment
experiment.only('Debug this', () => {
    // focus on specific tests
});

Test Definition

Defines individual test cases within experiments.

/**
 * Defines an individual test case
 * @param title - Descriptive name for the test
 * @param testFn - Test function to execute
 */
test(title: string, testFn: Action): void;

/**
 * Defines a test case with options
 * @param title - Descriptive name for the test
 * @param options - Test configuration options
 * @param testFn - Test function to execute
 */
test(title: string, options: TestOptions, testFn: Action): void;

interface Test {
    (title: string, test: Action): void;
    (title: string, options: TestOptions, test: Action): void;
    /** Run only this test, skipping all others */
    only(title: string, test: Action): void;
    only(title: string, options: TestOptions, test: Action): void;
    /** Skip this test during execution */
    skip(title: string, test: Action): void;
    skip(title: string, options: TestOptions, test: Action): void;
}

interface Action {
    /** Test function receiving flags for utilities and context */
    (flags: Flags): Promise<any> | void;
}

Usage Examples:

// Synchronous test
test('validates user input', () => {
    expect(validateEmail('test@example.com')).to.be.true();
});

// Asynchronous test
test('fetches user data', async () => {
    const user = await getUserById(123);
    expect(user.name).to.equal('John Doe');
});

// Test with options
test('complex operation', { timeout: 10000, plan: 3 }, (flags) => {
    // Test expecting exactly 3 assertions with 10s timeout
});

// Using test flags
test('cleanup test', (flags) => {
    flags.onCleanup = () => cleanupDatabase();
    // test implementation
});

Setup and Teardown Hooks

Provides setup and teardown functionality for experiments with flexible timing options.

/**
 * Runs setup function before all tests in the current experiment
 * @param action - Setup function to execute
 */
before(action: Action): void;

/**
 * Runs setup function with options before all tests
 * @param options - Setup configuration
 * @param action - Setup function to execute
 */
before(options: TestOptions, action: Action): void;

/**
 * Runs teardown function after all tests in the current experiment
 * @param action - Teardown function to execute
 */
after(action: Action): void;

/**
 * Runs teardown function with options after all tests
 * @param options - Teardown configuration
 * @param action - Teardown function to execute
 */
after(options: TestOptions, action: Action): void;

/**
 * Runs setup function before each test in the current experiment
 * @param action - Setup function to execute
 */
beforeEach(action: Action): void;

/**
 * Runs setup function with options before each test
 * @param options - Setup configuration
 * @param action - Setup function to execute
 */
beforeEach(options: TestOptions, action: Action): void;

/**
 * Runs teardown function after each test in the current experiment
 * @param action - Teardown function to execute
 */
afterEach(action: Action): void;

/**
 * Runs teardown function with options after each test
 * @param options - Teardown configuration
 * @param action - Teardown function to execute
 */
afterEach(options: TestOptions, action: Action): void;

interface Setup {
    (action: Action): void;
    (options: TestOptions, action: Action): void;
}

Usage Examples:

experiment('Database tests', () => {

    before(async () => {
        await setupDatabase();
    });

    after(async () => {
        await cleanupDatabase();
    });

    beforeEach(() => {
        resetTestData();
    });

    afterEach(() => {
        clearCache();
    });

    // Setup with timeout
    before({ timeout: 30000 }, async () => {
        await longRunningSetup();
    });

    test('user creation', () => {
        // test implementation
    });
});

Test Context and Utilities

Flags Interface

The Flags interface provides utilities and context available to test functions and setup/teardown hooks.

interface Flags {
    /** Shared object for passing data between setup, tests, and teardown */
    readonly context: Record<string, any>;
    
    /** 
     * Wraps a function to require a specific number of invocations
     * @param func - Function to wrap
     * @param count - Required number of calls
     * @returns Wrapped function that tracks call count
     */
    mustCall<T extends (...args: any[]) => any>(func: T, count: number): T;
    
    /** 
     * Adds notes to the test log for console reporter output
     * @param note - String to include in console output
     */
    note(note: string): void;
    
    /** Cleanup function executed after test completion */
    onCleanup?: Action;
    
    /** Override for global exception handling */
    onUncaughtException?: ErrorHandler;
    
    /** Override for global rejection handling */
    onUnhandledRejection?: ErrorHandler;
}

Usage Examples:

test('callback verification', (flags) => {
    const callback = flags.mustCall((result) => {
        expect(result).to.equal('success');
    }, 2); // Must be called exactly twice
    
    asyncFunction(callback);
    anotherAsyncFunction(callback);
});

test('with context', (flags) => {
    flags.context.userId = 123;
    flags.note('Testing with user ID: 123');
    
    flags.onCleanup = () => {
        cleanupUser(flags.context.userId);
    };
});

Configuration Options

Test Options

Configuration options available for tests, experiments, and setup/teardown hooks.

interface TestOptions {
    /** Skip this test/experiment during execution */
    skip?: boolean;
    
    /** Run only this test/experiment, skipping all others */
    only?: boolean;
    
    /** Override default timeout in milliseconds (default: 2000) */
    timeout?: number;
    
    /** Expected number of assertions this test must execute */
    plan?: number;
    
    /** Retry failed tests (true for default retries, number for specific count) */
    retry?: number | boolean;
}

docs

code-coverage.md

command-line-interface.md

index.md

memory-leak-detection.md

test-execution.md

test-organization.md

typescript-integration.md

tile.json