Easily found out if an ES6 Iterator match what you expected
MIT License
Easily found out if an ES6 Iterator match what you expected
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
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.
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;
}
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);
});
Thanks goes to these wonderful people (emoji key):
MIT