Running Jasmine tests in C3 console

#1

Along with Automating console demos, the code below allows you to copy-paste an existing Jasmine test as-is into C3 console (tested on Chrome). Then you can insert c3Viz or make demos out of such existing tests.

The first part is Jasmine matchers, feel free to add some more.

// jasmine stubs to facilitate evaluating jasmine tests in console
var objIdMap = new WeakMap;
var objectCount = 0;
function objId(object) {
    if (!objIdMap.has(object))
        objIdMap.set(object,++objectCount);
    return objIdMap.get(object);
}

function JasmineObj(expected) {
    this.expected = expected;
}
JasmineObj.prototype.toEqual = function(actual) {
    var r = JSON.stringify(this.expected) === JSON.stringify(actual);
    if (!r) {
        console.log(
            'FAILED toEqual/expected:', this.expected,
            ', actual:', actual);
    }
};
JasmineObj.prototype.toBeGreaterThan = function(actual) {
    var r = this.expected > actual;
    if (!r) {
        console.log(
            'FAILED toBeGreaterThan/expected:', this.expected,
            ', actual:', actual);
    }
};
JasmineObj.prototype.toBe = function(actual) {
    var r = this.expected === actual;
    if (!r) {
        console.log(
            'FAILED toBe/expected:', this.expected,
            ', actual:', actual);
    }
};
JasmineObj.prototype.toThrowError = function(actual) {
    var r = false;
    try {
        actual();
    } catch (e) {
        r = true;
    }
    if (!r) console.log('FAILED toThrowError');
};
JasmineObj.prototype.toBeDefined = function() {
    var r = typeof this.expected !== 'undefined';
    if (!r) {
        console.log('FAILED toBeDefined/expected:', this.expected);
    }
}; // TODO: more matchers
function expect(val) {
    return new JasmineObj(val);
}

And the second part is support for (nested) describe, beforeAll, afterAll, beforeEach, afterEach and it.

function it(text, thunk) {
    var env = this.envStack[this.envStack.length - 1];
    // console.log(env.pfx, 'D it', text, objId(env), env);
    env.children.push([text, thunk]);
}
function beforeAll(thunk) {
    var env = this.envStack[this.envStack.length - 1];
    // console.log(env.pfx, 'D beforeAll', env.text, objId(env), this.envStack);
    var thisOne = this;
    env.fmap.beforeAll = function() {
        // console.log(env.pfx, 'Es beforeAll', env.text);
        thunk.call(thisOne);
        // console.log(env.pfx, 'Ee beforeAll', env.text);
    };
}
function beforeEach(thunk) {
    var env = this.envStack[this.envStack.length - 1];
    // console.log(env.pfx, 'D beforeEach', env.text, objId(env), this.envStack);
    var thisOne = this;
    env.fmap.beforeEach = function() {
        // console.log(env.pfx, 'Es beforeEach', env.text);
        thunk.call(thisOne);
        // console.log(env.pfx, 'Ee beforeEach', env.text);
    };
}
function afterAll(thunk) {
    var env = this.envStack[this.envStack.length - 1];
    // console.log(env.pfx, 'D afterAll', env.text, objId(env), this.envStack);

    var thisOne = this;
    env.fmap.afterAll = function() {
        // console.log(env.pfx, 'Es afterAll', env.text);
        thunk.call(thisOne);
        // console.log(env.pfx, 'Ee afterAll', env.text);
    };
}
function afterEach(thunk) {
    var env = this.envStack[this.envStack.length - 1];
    // console.log(env.pfx, 'D afterEach', env.text, objId(env), this.envStack);
    var thisOne = this;
    env.fmap.afterEach = function() {
        // console.log(env.pfx, 'Es afterEach', env.text);
        thunk.call(thisOne);
        // console.log(env.pfx, 'Ee afterEach', env.text);
    };
}
function describe(text, thunk) {
    if (!this.envStack ||
        (Array.isArray(this.envStack) && this.envStack.length === 0)) {
        this.envStack = [];
        this.envTree = null;
    }
    var env = {
        pfx: new Array(this.envStack.length * 2 + 1).join(' '),
        text: text,
        children: [],
        fmap: {
            beforeAll: function() {
                // console.log(env.pfx, 'E beforeAll empty');
            },
            beforeEach: function() {
                // console.log(env.pfx, 'E beforeEach empty');
            },
            afterAll: function() {
                // console.log(env.pfx, 'E afterAll empty');
            },
            afterEach: function() {
                // console.log(env.pfx, 'E afterEach empty');
            }
        }
    };
    // console.log(env.pfx, 'D describe', text, objId(env), this.envStack);

    try {
        if (this.envStack.length === 0) {
            this.envTree = env;
        } else {
            this.envTree.children.push(env);
        }
        this.envStack.push(env);

        // console.log(env.pfx, 'Cs describe', text);
        thunk.call(this);
        // console.log(env.pfx, 'Ce describe', text);
    } catch (e) {
        console.log(env.pfx, '  caught', e, env);
    } finally {
        this.envStack.pop();
    }
}
function runTest(test) {
    if (test)
        this.envTree = test;
    if (!this.envTree) {
        console.log('No test to run');
        return;
    }
    function runDesc(env) {
        this.envStack.push(env);
        try {
            env.fmap.beforeAll();
            for (p of env.children) {
                if (Array.isArray(p)) {
                    for (e2 of this.envStack) {
                        e2.fmap.beforeEach();
                    }
                    p[1].call(this);
                    for (e2 of this.envStack.reverse()) {
                        e2.fmap.afterEach();
                    }
                } else {
                    runDesc(p);
                }
            }
            env.fmap.afterAll();
        } catch (e) {
            console.log('runTest caught', e, env)
        } finally {
            this.envStack.pop();
        }
    }
    this.envStack = [];
    runDesc(this.envTree);
}

After pasting a Jasmine test into the console, enter runTest(). The test is kept in this.envTree so you can rerun it until

  • another describe is pasted/typed into the console, or
  • you pass another test (a previous value of this.envTree) as the argument to runTest.

Feedback is welcome.

0 Likes