llparse Test Fixture

raw JSON →
5.1.0 verified Thu Apr 23 auth: no javascript

llparse-test-fixture is a utility package designed to provide a consistent and controlled environment for testing parsers generated by `llparse` and other `llparse`-based modules. `llparse` itself is an API for compiling incremental parsers into highly optimized C output, often used in performance-critical applications like `llhttp` (the HTTP parser in Node.js). This fixture, currently at version 5.1.0, facilitates the creation of test cases, feeding input data, and asserting on the behavior and output of such low-level parsers. It primarily serves as a development dependency for projects that utilize `llparse` to ensure the correctness and robustness of their generated parsers, offering abstractions to simplify complex parsing scenarios in tests. Its release cadence is likely tied to updates in the core `llparse` project. It differentiates itself by providing specialized tools for a generated C-based parser, contrasting with general-purpose testing libraries.

error Error: Cannot find module 'llparse-test-fixture'
cause The package is not installed or the import path is incorrect, or it's a CommonJS project trying to import an ESM-only library.
fix
Run npm install llparse-test-fixture or yarn add llparse-test-fixture. For CJS projects, ensure proper transpilation or switch to ESM if possible, as the library is primarily designed for ESM.
error TypeError: Cannot read properties of undefined (reading 'on_data')
cause The mocked parser or the fixture was not correctly initialized with the expected callback handlers, or the `llparse` parser logic changed its expected callback names.
fix
Double-check the createFixture call to ensure all expected llparse callbacks are provided. Consult the documentation for your llparse-generated parser to confirm the exact callback API.
error TS2742: The inferred type of '...' cannot be named without a reference to '.../node_modules/llparse-test-fixture/index.d.ts'. This is likely not portable. A type annotation is necessary.
cause This TypeScript error indicates that a type inference resulted in a complex type that TypeScript cannot easily name or reference across module boundaries without an explicit import, often seen when `isolatedModules` is enabled.
fix
Explicitly import and use the necessary types, e.g., import type { IParsedEvent } from 'llparse-test-fixture'; for type-only imports, or add explicit type annotations to variables where the complex type is inferred.
breaking Major versions of `llparse-test-fixture` are typically tied to `llparse` itself. Upgrading `llparse` may require upgrading the fixture, as internal APIs or expected parser behavior might change, leading to test failures or incorrect mock interactions.
fix Always check the release notes for `llparse-test-fixture` when upgrading `llparse` to ensure compatibility. Re-evaluate parser mock implementations and event expectations.
gotcha When testing `llparse`-generated C code (e.g., via `napi-rs` or direct C++ bindings), ensure your testing environment has the necessary C/C++ toolchain configured. Mismatched compiler versions or missing build tools can lead to compilation errors during test setup.
fix Verify that `node-gyp` (or equivalent build tool) is correctly installed and configured. Check system environment variables like `CC`, `CXX`, and `PATH` for proper compiler access. For CI/CD, use Docker images with pre-installed toolchains.
gotcha Asynchronous event handling in `llparse` parsers (e.g., `on_data` callbacks) can lead to race conditions or incomplete test assertions if not properly awaited. Tests might pass spuriously if assertions run before all parser events have fired.
fix Ensure that your test suite (e.g., Jest, Mocha) is configured to handle asynchronous tests. Use `async/await` with `Promise` or `setTimeout(..., 0)` to defer assertions until all expected parser events have been processed. The `ParserTestStream` helps, but custom callbacks might need explicit waiting.
npm install llparse-test-fixture
yarn add llparse-test-fixture
pnpm add llparse-test-fixture

Demonstrates how to use `llparse-test-fixture` to test a hypothetical `llparse`-generated parser, feeding it data, capturing events, and asserting expected outcomes.

import { createFixture, ParserTestStream, IParsedEvent } from 'llparse-test-fixture';
// Assume 'my-llparse-parser' is a module that exports a class
// generated by llparse, with a parse() method and event callbacks.
// For demonstration, we'll mock a simple parser structure.

interface MyParserCallbackEvents {
  on_data?: (value: number) => void;
  on_complete?: () => void;
}

class MockLLParseParser {
  private callbacks: MyParserCallbackEvents = {};
  constructor(callbacks: MyParserCallbackEvents) {
    this.callbacks = callbacks;
  }

  // Simulate parsing, calling callbacks based on input
  parse(data: Buffer): number {
    for (const byte of data) {
      if (byte === 0x01 && this.callbacks.on_data) {
        this.callbacks.on_data(byte);
      } else if (byte === 0x02 && this.callbacks.on_complete) {
        this.callbacks.on_complete();
      }
    }
    return data.length;
  }

  // Simulate reinitialization
  reset(): void {
    console.log('Parser reset.');
  }
}

describe('My LLParse Parser', () => {
  it('should parse simple data and trigger complete event', async () => {
    const events: IParsedEvent[] = [];
    const fixture = createFixture(MockLLParseParser, {
      on_data: (value) => events.push({ type: 'data', value }),
      on_complete: () => events.push({ type: 'complete' })
    });

    const parser = fixture.parser; // Access the mocked parser instance
    const stream = new ParserTestStream(parser);

    stream.feed(Buffer.from([0x01, 0x01]));
    stream.feed(Buffer.from([0x02]));
    stream.end();

    // Wait for all async parsing to settle if applicable (mocked here as sync)
    await new Promise(resolve => setImmediate(resolve));

    expect(events).toEqual([
      { type: 'data', value: 1 },
      { type: 'data', value: 1 },
      { type: 'complete' }
    ]);
    expect(fixture.getCalls('on_complete').length).toBe(1);
  });

  it('should handle parser reset correctly', async () => {
    const events: IParsedEvent[] = [];
    const fixture = createFixture(MockLLParseParser, {
      on_data: (value) => events.push({ type: 'data', value })
    });

    const parser = fixture.parser;
    parser.parse(Buffer.from([0x01]));
    fixture.reset(); // Calls the parser's reset method

    parser.parse(Buffer.from([0x01]));
    expect(events.length).toBe(2); // Events before and after reset
  });
});