var assert = require("assert");
var console = require("console");

var merge = function (dest, source) {
    for (var p in source) {
		dest[p] = source[p];
    };
	return dest;
}

var StatusSignal = function() {
    // Name of the test.
    this.name = "Unknown";
    // Path of the test relative to its parent tests
    this.path = [];
    // Status of the test one of `running`, `passed`, `failed`.
    this.status = "running";
    // If the test has failed an error object is available.
    this.error = null;
};

var StatusNode = function() {
    StatusSignal.call(this);
    // Index of the test within its parent test.
    this.index = 0;
    // Status of child tests
    this.children = [];
};

var update = function(node, path, status) {
    if (path.length == 0) {
        // If refering to the current node
        merge(node, status);
    } else {
        // If referring to a descendant node
        var pathIndex = path.shift();

        for (i=0; i<node.children.length; i++) {
            var testIndex = node.children[i].index;
            if (pathIndex >= testIndex)
                break;
        }

        if (i == pathIndex) {
            // If the child path exists
            update(node.children[i], path, status);
        } else {
            // Create it
            node.children.splice(i+1, 0, update(merge(new StatusNode, {index: pathIndex}), path, status));
        }
    }

    return node;
};

var root = new StatusNode();

update(root, [],{
    name: "root",
    path: [],
    status: "running",
    error: null
});
assert.deepEqual(root, {
    name: "root",
    path: [],
    status: "running",
    error: null,
    index: 0,
    children: []
});

update(root, [1], {
    name: "child-1",
    path: [1],
    status: "passed",
    error: null
});
assert.deepEqual(root, {
    name: "root",
    path: [],
    status: "running",
    error: null,
    index: 0,
    children: [{
        name: "child-1",
        path: [1],
        status: "passed",
        error: null,
        index: 1,
        children: []
    }]
});

update(root, [3], {
    name: "child-3",
    path: [3],
    status: "failed",
    error: null
});
assert.deepEqual(root, {
    name: "root",
    path: [],
    status: "running",
    error: null,
    index: 0,
    children: [{
        name: "child-1",
        path: [1],
        status: "passed",
        error: null,
        index: 1,
        children: []
    },
    {
        name: "child-3",
        path: [3],
        status: "failed",
        error: null,
        index: 3,
        children: []
    }]
});

update(root, [2], {
    name: "child-2",
    path: [2],
    status: "failed",
    error: null
});
assert.deepEqual(root, {
    name: "root",
    path: [],
    status: "running",
    error: null,
    index: 0,
    children: [{
        name: "child-1",
        path: [1],
        status: "passed",
        error: null,
        index: 1,
        children: []
    },
    {
        name: "child-2",
        path: [2],
        status: "failed",
        error: null,
        index: 2,
        children: []
    },
    {
        name: "child-3",
        path: [3],
        status: "failed",
        error: null,
        index: 3,
        children: []
    }]
});

@@ -3188,28 +3188,1186 @@
     children: %5B%5D%0A    %7D%5D%0A%7D);%0A
+%0Avar clear = function() %7B%0A    process.stdout.write(%22%5C033%5B1A%22);%0A%7D;%0A%0Avar StringBuffer = function() %7B%0A    this.buffer = %5B%5D;%0A%7D;%0AStringBuffer.prototype.write = function(s) %7B%0A    this.buffer.push(s);%0A%7D;%0AStringBuffer.prototype.toString = function() %7B%0A    return this.buffer.join(%22%22);%0A%7D;%0A%0Avar color = function(status) %7B%0A    switch (status) %7B%0A        case %22running%22: return %2233%22;%0A        case %22passed%22 : return %221;32%22;%0A        case %22failed%22 : return %221;31%22;%0A        default       : return %2231%22;%0A    %7D;%0A%7D;%0A%0Avar lout = function(output, line, depth, color) %7B%0A    output.write(Array(depth+1).join(%22%5Ct%22) + %22%5C033%5B2K%5C033%5B%22 + color + %22m%22 + line + %22%5Cn%5C033%5B37m%22);%0A%7D;%0A%0Avar render = function(output, node, depth) %7B%0A    var lines = 1;%0A    lout(output, node.name, depth, color(node.status));%0A%0A    if(node.status == %22failed%22 && node.err)%0A        node.err.msg.split(/%5Cr%5Cn%7C%5Cr%7C%5Cn/).forEach(function(l) %7B%0A            lines += 1;%0A            lout(output, l, depth+1, 37)%0A        %7D);%0A    node.children.forEach(function(c) %7B%0A        lines += render(output, c, depth+1)%0A    %7D);%0A%0A    return lines;%0A%7D;%0A%0Avar sb = new StringBuffer();%0A%0Arender(sb, root, 0);%0A%0Aprocess.stdout.write(sb.toString());%0A

Add a render function to output a tree of results to the console in pretty colors.