/async-test-util

Utility functions that are useful in async/await tests :thumbsup:

Primary LanguageJavaScriptApache License 2.0Apache-2.0

async-test-util

Utility-functions that can be usefull when you have asynchronous tests in javascript.

Installation

$ npm install async-test-util --save-dev
// es6
import AsyncTestUtil from 'async-test-util';

// es5
var AsyncTestUtil = require('async-test-util');

wait()

Waits until the given time has expired and then resolves.

it('should wait', async() => {
    await AsyncTestUtil.wait(200);
    console.log('200 ms is over');
});

waitResolveable()

Waits until the given timeout has expired or the resolve was triggered manually

it('should wait until observable fired or time is over', async() => {
    const resolveable = AsyncTestUtil.waitResolveable(200);
    myObservable.subscribe(sth => {
        console.log('got first event');
        resolveable.resolve();
    });
    await resolveable.promise;
});

waitUntil()

Waits until the given predicate-function returns a truthy value. Throws if the optional timeout has passed before.

it('should wait until server is online', async() => {
    const checkServer = async() => {
        try{
            await fetch('http://example.com/api/');
            return true;
        }catch(err) {
            return false;
        }
    };
    await AsyncTestUtil.waitUntil(checkServer);
});

With timeout:

it('should wait until server is online (maxtime: 1000ms)', async() => {
    const checkServer = async() => {
        try{
            await fetch('http://example.com/api/');
            return true;
        }catch(err) {
            return false;
        }
    };
    await AsyncTestUtil.waitUntil(checkServer, 1000);
});

With return value:

it('should wait until server is online (maxtime: 1000ms)', async() => {
    const checkServer = async() => {
        try{
            const response = await fetch('http://example.com/api/');
            return await response.json();
        }catch(err) {
            return false;
        }
    };
    const firstSuccessfullResponse = await AsyncTestUtil.waitUntil(checkServer, 1000);
});

waitForever()

Waits forever, never resolves.

it('should never resolve', async() => {
    let resolved = false;
    AsyncTestUtil
        .waitForever()
        .then(() => resolved = true);
    await AsyncTestUtil.wait(100);
    assert.equal(false, resolved);
});

runForever()

Runs the given predicate-function forever. Between each run, the interval-time is awaited.

it('should run forever', async() => {
    let t = 0;
    const pred = () => t++;
    AsyncTestUtil.runForever(
        pred, // predicate-function
        10    // interval
     );

    await AsyncTestUtil.wait(100);
    assert.ok(t > 4);
    const lastT = t;
    await AsyncTestUtil.wait(100);
    assert.ok(t > lastT);
});

assertThrows()

Async-Form of assert.throws. Asserts that the given function throws with the defined error, throws if not.

// with error-type
it('should throw because route does not exist', async() => {
    const getServerVersion = async() => {
        const response = await fetch('http://example.com/foobar/');
        return response;
    };
    await AsyncTestUtil.assertThrows(
        () => getServerVersion(),       // function that throws (required)
        Error                   // Error-type           (optional)
    );
});

// with error-text-flag
it('should throw because route does not exist', async() => {
    const pingServer = async() => {
        try{
            await fetch('http://example.com/foobar/');            
        }catch(err) {
            throw new Error('route not reachable');
        }
    };
    await AsyncTestUtil.assertThrows(
        () => pingServer(),       // function that throws                                    (required)
        Error,                    // Error-type                                              (optional)
        'reachable'               // text-flag, throw if error-message does not include this (optional)  
    );

    // or you can pass a string-array to ensure all is in error message
    await AsyncTestUtil.assertThrows(
        () => pingServer(),       // function that throws                                    (required)
        Error,                    // Error-type                                              (optional)
        ['route', 'reachable']    // text-flag, throw if error-message does not include this (optional)  
    );
});

// assertThrows returns the error
it('should have the custom error-property', async() => {
    const throwingFunction = async()=>{
        const error = new Error('error message');
        error.foo = 'bar';
        throw error;
    }
    const thrown = await AsyncTestUtil.assertThrows(
        () => pingServer(),       // function that throws                                    (required)
        Error,                    // Error-type                                              (optional)
        'message'               // text-flag, throw if error-message does not include this (optional)  
    );
    assert.equal(thrown.foo, 'bar');
});

resolveValues()

Recieves an object with promises as values. Returns ans object with the resolved promises as values. Use this in test-setups to improve the test-speed by running everything in parallel.

// instead of this
const database = await connectDatabase();
const user1 = await getUser();
const user2 = await getUser();

// do this
const {
    database,
    user1,
    user2
} = await AsyncTestUtil.resolveValues({
    database: connectDatabase();
    user1: getUser();
    user2: getUser();
});

isPromise()

Returns true if the given value is a Promise;

const is = AsyncTestUtil.isPromise(myAsyncFunction()); // true
const is = AsyncTestUtil.isPromise('foobar'); // false

promisify

Transforms the given value to a promise if it was no promise before.

const ensurePromise = AsyncTestUtil.promisify(maybeAsyncFunction());

// now you are sure this is a promise
ensurePromise.then(/* ... */)

randomString()

Creates a random string. Takes length as first parameter an custom charset as second.

console.log(AsyncTestUtil.randomString());
// > 'rhfkx'

console.log(AsyncTestUtil.randomString(10));
// > 'dhcvkledzu'

console.log(AsyncTestUtil.randomString(
    6,    // (optional) length
    'abc' // (optional) charset, only this will be used to create the string
));
// > 'acbcba'

randomNumber()

Creates a random number. Optional range can be given.

console.log(AsyncTestUtil.randomNumber());
// > 56

console.log(AsyncTestUtil.randomNumber(
    1000, // min-value (default=0)
    2000 // max-value (default=1000)
));
// > 1768

randomBoolean()

Creates a random boolean. Returns true or false.

console.log(AsyncTestUtil.randomBoolean());
// > true

clone()

Reference to clone. Does exactly the same thing.

it('should not modify the original object', () => {
    const original = {
        foo: 'bar',
        level: 1
    };
    const cloned = AsyncTestUtil.clone(original);
    cloned.level = 2;
    assert.equal(original.level, 1);
});

deepEqual()

Reference to deep-equal. Does exactly the same thing.

it('the 2 objects should be equal', () => {
    const obj1 = {
        foo: 'bar',
        level: 1
    };
    const obj2 = {
        foo: 'bar',
        level: 1
    };
    assert.ok(AsyncTestUtil.deepEqual(obj1, obj2));
});

performanceNow()

Works equal to performance.now but works in browsers and nodeJs.

it('should take less then 200 milliseconds', () => {
    const now = AsyncTestUtil.performanceNow(); // in milliseconds
    await doSomething();
    const later = AsyncTestUtil.performanceNow(); // in milliseconds
    assert.ok((now + 50 * 1000 ) > later);
});