2.1.0 • Published 8 months ago

iterator-matcher v2.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

iterator-matcher

version Maintenance Security Responsible Disclosure mit

Easily found out if an ES6 Iterator match what you expected

Limitations

  • No built-in mechanism to match on non-primitive values.

Requirements

Getting Started

This package is available in the Node Package Repository and can be easily installed with npm or yarn.

$ npm i iterator-matcher
# or
$ yarn add iterator-matcher

Usage example

import { IteratorMatcher } from "iterator-matcher";
import assert from "node:assert";

function* dummyGen() {
  yield "console";
  yield "trace";
  yield "error";
}

const result = new IteratorMatcher()
  .expect("console")
  .expect(["trace", "error"], { occurence: 2 })
  .execute(dummyGen());

assert.ok(result.isMatching, true);
assert.equal(result.elapsedSteps, 3);

!NOTE You can re-use the same IteratorMatcher multiple time.

API

No options are required.

The options payload is described by the following TypeScript interface:

export interface IteratorMatcherExpectOptions {
  /**
   * When a value is not mandatory the Executor continue his job/execution.
   *
   * @default true
   */
  mandatory?: boolean;
  /**
   * Number of occurences of the expected value
   *
   * @default 1
   */
  occurence?: number;
}

In usage the expectedValue can be an Array or a ES6 Set.

new IteratorMatcher()
  .expect("primitive", { mandatory: false })
  .expect([1, 2, 3])
  .expect(new Set(["oh", "hey", "oh"]), { occurence: 2 });

The options payload is described by the following TypeScript interface:

interface DefaultIteratorMatcherExecutorOptions {
  /**
   * Stop the executor on the first matching value.
   *
   * @default false
   */
  stopOnFirstMatch?: boolean;

  /**
   * When enabled it return isMatching: true if no value has been matched (like an empty Iterator for example).
   *
   * @default true
   */
  allowNoMatchingValues?: boolean;
}

interface DefaultUnpreservedIteratorMatcherExecutorOptions
  extends DefaultIteratorMatcherExecutorOptions {
  /**
   * Authorize unexpected value to appear
   *
   * @default false
   */
  allowUnexpectedValue?: boolean;
}

export type IteratorMatcherExecutorOptions = {
  /**
   * When enabled it preserve the order of expectation
   */
  preserveExpectationOrder?: true;
} & DefaultIteratorMatcherExecutorOptions | {
  /**
   * When disabled it will iterate all expectations and try to match them all with no order.
   */
  preserveExpectationOrder?: false;
} & DefaultUnpreservedIteratorMatcherExecutorOptions;

The response is described by the following TypeScript type:

export type IteratorMatcherExecutorResult = {
  isMatching: boolean;
  elapsedSteps: number;
}

EventListener

The IteratorMatcher expose an additional EventListener helper class useful for testing purpose with Node.js EventEmitter.

Here a real world example extracted from the UT one of my package:

import assert from "node:assert";
import { test } from "node:test";

import { TimeStore } from "@openally/timestore";
import { IteratorMatcher, EventListener } from "iterator-matcher";

test("Example with TimeStore, IteratorMatcher and EventListener", () => {
  const store = new TimeStore({ ttl })
  .add("foo").add("bar");
  const eeListener = new EventListener(store, TimeStore.Expired);

  // Doing some work with store

  assert.equal(eeListener.listenerCount, 2);
  const { isMatching } = new IteratorMatcher()
    .expect("foo")
    .expect("bar")
    .execute(eeListener.names(), { allowNoMatchingValues: false });
  assert.ok(isMatching, true);
});

Contributors ✨

All Contributors

Thanks goes to these wonderful people (emoji key):

License

MIT

2.1.0

8 months ago

2.0.0

1 year ago

1.0.1

2 years ago

1.0.0

2 years ago