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 🙏

© 2024 – Pkg Stats / Ryan Hefner

most-test

v1.3.0

Published

Unit testing tools for Most.js

Downloads

5,392

Readme

Unit Testing Tools for Most.js

Build Status Gitter

This is a library to make unit testing of Most.js streams easier.

Though I expect to include more in the future, the most important (and currently only) tool provided is a stream runner utilizing a virtual timer with which you can test your streams on your own terms, rather than being subject to the unpredictability and imprecision of the OS timer. Being able to test with single-millisecond granularity can make your tests clearer and more concise as well.

Special thanks to @RamIdeas for testing and contributing fixes and enhancements to the library.

Installation

npm install --save-dev most-test

Stream Runner

Testing a stream using the virtual timer is very straightforward. Simply import the run function from most-test and use it instead of stream.observe. Call tick() or tick(interval) to advance time forward by either 1 millisecond (default) or a custom interval. The function returns a promise containing a summary of the events that occurred during that time interval. To advance time again, simply call tick(interval?) again, returning the promise so that it resolves as the next step in the promise chain.

API

type Stream: most.Stream
type Time: Number
type Interval: Number

run: (stream:Stream) => BasicTestEnvironment

type BasicTestEnvironment: {
  tick: (min?:Interval) => Promise<Result>
  now: Time,
  results: [Result]
}

type Result: {
  events: Array,
  end?: true|A,
  error?: Error
}

The tick() method advances the timer by the specified interval and returns a promise for the events that occurred during that interval.

A Result object always contains an events property, which is an array of zero or more values that were emitted by the stream during the elapsed interval. If the stream completed, it'll also have an end property which will have the completion value emitted with the end event, or true if no completion value was emitted. If a completion value was provided, the end property will be an object with a value property; e.g. {value: 'x'}

A BasicTestEnvironment object also contains a results property (getter only), which is an array of all of the Result objects created as a result of each tick() call.

Example

This example uses Mocha's BDD API. You should use whatever you prefer.

import {run} from 'most-test';
import assert from 'assert';

describe('most-test', () => {
  describe('run()' => {
    it('is easy to use', () => {
      const stream = most
        .periodic(1000, 0)
        .scan(x => x + 1, 0)
        .skip(1)
        .take(2);

      const env = run(stream);

      return env.tick(/* advance by 1ms */)
        .then(result => {
          // Make sure the stream didn't terminate
          assert.ok(!('end' in result));
          assert.ok(!('error' in result));

          // Ensure that the initial `periodic` value was emitted
          assert.equal(result.events.length, 1);
          assert.equal(result.events[0], 1);

          // Advance 1000ms; the stream should emit the second event and complete
          return env.tick(1000);
        })
        .then(result => {
          assert.equal(result.events.length, 1);
          assert.equal(result.events[0], 2);
          assert.ok(result.end);
        });
    });
  });
});

As of version 1.2.0:

As of version 1.2.0, run(stream) returns a BasicTestEnvironment which is a wrapper around TestEnvironment.

run(stream) works best when instantiating the stream under test within the test itself.

If you are testing a stream instantiated externally of your tests (eg. an imported module), the environment created when running this stream can remain associated with it and, therefore, future tests on the same stream can have unpredictable results.

In this situation, you should create a TestEnvironment and share it amongst your tests. Remembering to .reset() the environment after each test.

import { TestEnvironment } from 'most-test'
import { stream1, stream2 } from './streams'

const env = new TestEnvironment();

// returns a promise - either return it to `afterEach` or `await` it
afterEach( () => env.reset() );

it( 'test stream1 after 1ms', async () => {
  const { events } = await env.tick().collect( stream1 );
  assert.equal( events.length, ... );
});

it( 'test stream1 after 10ms', async () => {
  const { events } = await env.tick(10).collect( stream1 );
  assert.equal( events.length, ... );
});

tick() initiates a promise chain but returns the TestEnvironment instance. Subsequent calls to collect() wait for this promise and then return a Result.

collect(stream) implicitly calls track(stream) - this helps avoid repetition. If collect() isn't being called within the same frame as tick(), you'll need to call track() explicitly, upfront.

it( 'test stream1 then test stream2', async () => {
  env.track( stream1, stream2 ); // could also chain calls: env.track( stream1 ).track( stream2 );
  
  const results1 = await env.tick().collect( stream1 );
  assert.equal( results1.events.length, ... );
  
  const results2 = await env.tick().collect( stream2 );
  assert.equal( results2.events.length, ... );
});