atsid/restwalker

View on GitHub
src/walker.js

Summary

Maintainability
A
0 mins
Test Coverage
"use strict";
let debug = require("debug")("restwalker");
let Promise = Promise || require("bluebird");
let isFunction = (x) => typeof x === "function";
let isString = (x) => typeof x === "string";
let isArray = (x) => Array.isArray(x);

/**
 * An integration test helper for "walking" across RESTful rels and performing
 * verification steps when necessary.
 */
class RestWalker {
    constructor(parser, executor) {
        if (!parser) {
            throw new Error("parser must be defined");
        }
        if (!executor) {
            throw new Error("executor must be defined");
        }
        this.parser = parser;
        this.executor = executor;
    }

    setRoot(root) {
        this.executor.setRoot(root);
    }


    /**
     * Invokes a RESTful testing sequence
     * @param sequence An array of commands. A command may be:
     *        * A function to invoke, e.g. for verification of the context; "this" context === bound to the context argument
     *        * A RESTful rel path from the service root. The test runner wil walk the rel-graph and adjusts the context as necessary.
     *        * An array of RESTful rel paths to invoke in parallel.
     * @param context The context object for all of the invocations
     * @returns {Promise} A promise that resolves when the sequence is complete.
     */
    invoke(sequence, context = {}) {
        let promise = Promise.resolve(true);
        sequence.forEach((item) => {
            promise = promise.then(() => this.handleSequenceItem(item, context));
        });
        return promise;
    }

    handleSequenceItem(item, context) {
        if (isFunction(item)) {
            debug(`handling sequence function`);
            return Promise.resolve(item.apply(context));
        } else if (isString(item)) {
            debug(`handling sequence command "${item}"`);
            return this.executeCommand(this.parseInstruction(item), context);
        } else if (isArray(item)) {
            debug(`handling sequence array`);
            return Promise.all(item.map((i) => this.parseInstruction(i)).map((cmd) => this.executeCommand(cmd, context)));
        } else {
            throw new Error(`Could not handle sequence item: ${item}`);
        }
    }

    parseInstruction(instruction) {
        return this.parser.parse(instruction);
    }

    executeCommand(command, context) {
        return this.executor.execute(command, context);
    }
}

module.exports = RestWalker;