<commit_before>var assert = require('assert');
var sinon = require('sinon');
var support = require('./support');
var check_err = support.check_err;
var caching = require('../index').caching;
var multi_caching = require('../index').multi_caching;
var memory_store = require('../lib/stores/memory');

function get_widget(name, cb) {
    cb(null, {name: name});
}

describe("multi_caching", function () {
    var redis_cache;
    var memory_cache;
    var memory_cache2;
    var multi_cache;
    var key;
    var memory_ttl;
    var redis_ttl;
    var name;

    beforeEach(function () {
        memory_ttl = 0.1;
        redis_ttl = 1;

        memory_cache = caching({store: 'memory', ttl: memory_ttl});
        memory_cache2 = caching({store: 'memory', ttl: memory_ttl});
        redis_cache = caching({store: 'redis', ttl: redis_ttl});

        key = support.random.string(20);
        name = support.random.string();
    });

    describe("get(), set(), del()", function () {
        var value;

        beforeEach(function () {
            multi_cache = multi_caching([memory_cache, redis_cache, memory_cache2]);
            key = support.random.string(20);
            value = support.random.string();
        });

        describe("set()", function () {
            it("lets us set data in all caches", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);
                    memory_cache.get(key, function (err, result) {
                        assert.equal(result, value);

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.equal(result, value);

                            memory_cache2.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, value);
                                done();
                            });
                        });
                    });
                });
            });

            it("lets us set data without a callback", function (done) {
                multi_cache.set(key, value);
                setTimeout(function () {
                    multi_cache.get(key, function (err, result) {
                        assert.equal(result, value);
                        memory_cache.get(key, function (err, result) {
                            assert.equal(result, value);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, value);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, value);
                                    done();
                                });
                            });
                        });
                    });
                }, 20);
            });
        });

        describe("get()", function () {
            it("gets data from first cache that has it", function (done) {
                redis_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.equal(result, value);
                        done();
                    });
                });
            });
        });

        describe("del()", function () {
            it("lets us delete data in all caches", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.del(key, function (err) {
                        check_err(err);

                        memory_cache.get(key, function (err, result) {
                            assert.ok(!result);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.ok(!result);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.ok(!result);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            it("lets us delete data without a callback", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.del(key);

                    setTimeout(function () {
                        memory_cache.get(key, function (err, result) {
                            assert.ok(!result);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.ok(!result);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.ok(!result);
                                    done();
                                });
                            });
                        });
                    });
                }, 10);
            });
        });
    });

    describe("wrap()", function () {
        describe("using a single cache store", function () {
            beforeEach(function () {
                multi_cache = multi_caching([redis_cache]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });
        });

        describe("using two cache stores", function () {
            beforeEach(function () {
                multi_cache = multi_caching([memory_cache, redis_cache]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });

            it("sets value in all caches", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});

                    memory_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.deepEqual(result, {name: name});

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.deepEqual(result, {name: name});
                            done();
                        });
                    });
                });
            });

            context("when value exists in first store but not second", function () {
                it("returns value from first store, does not set it in second", function (done) {
                    memory_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, null);
                                done();
                            });
                        });
                    });
                });
            });

            context("when value exists in second store but not first", function () {
                it("returns value from second store, sets it in first store", function (done) {
                    redis_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            memory_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});
                                done();
                            });
                        });
                    });
                });
            });
        });

        describe("using three cache stores", function () {
            beforeEach(function () {
                multi_cache = multi_caching([memory_cache, redis_cache, memory_cache2]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });

            it("sets value in all caches", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});

                    memory_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.deepEqual(result, {name: name});

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.deepEqual(result, {name: name});

                            memory_cache2.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});
                                done();
                            });
                        });
                    });
                });
            });

            context("when value exists in first store only", function () {
                it("returns value from first store, does not set it in second or third", function (done) {
                    memory_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, null);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, null);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            context("when value exists in second store only", function () {
                it("returns value from second store, sets it in first store, does not set third store", function (done) {
                    redis_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            memory_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, null);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            context("when value exists in third store only", function () {
                it("returns value from third store, sets it in first and second stores", function (done) {
                    memory_cache2.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});

                                memory_cache.get(key, function (err, result) {
                                    check_err(err);
                                    assert.deepEqual(result, {name: name});

                                    done();
                                });
                            });
                        });
                    });
                });
            });
        });

        context("error handling", function () {
            var memory_store_stub;
            var ttl;

            beforeEach(function () {
                ttl = 0.1;
                memory_store_stub = memory_store.create({ttl: ttl});
                sinon.stub(memory_store, 'create').returns(memory_store_stub);
                memory_cache = caching({store: 'memory', ttl: ttl});
                multi_cache = multi_caching([memory_cache]);
            });

            afterEach(function () {
                memory_store.create.restore();
            });

            context("when store.get() calls back with an error", function () {
                it("bubbles up that error", function (done) {
                    var fake_error = new Error(support.random.string());

                    sinon.stub(memory_store_stub, 'get', function (key, cb) {
                        cb(fake_error);
                    });

                    multi_cache.wrap(key, function (cb) {
                        get_widget(name, cb);
                    }, function (err) {
                        assert.equal(err, fake_error);
                        memory_store_stub.get.restore();
                        done();
                    });
                });
            });

            context("when store.set() calls back with an error", function () {
                it("bubbles up that error", function (done) {
                    var fake_error = new Error(support.random.string());

                    sinon.stub(memory_store_stub, 'set', function (key, val, cb) {
                        cb(fake_error);
                    });

                    multi_cache.wrap(key, function (cb) {
                        get_widget(name, cb);
                    }, function (err) {
                        assert.equal(err, fake_error);
                        memory_store_stub.set.restore();
                        done();
                    });
                });
            });
        });
    });

    context("when instantiated non-Array 'caches' arg", function () {
        it("throws an error", function () {
            assert.throws(function () {
                multi_caching({foo: 'bar'});
            }, /multi_caching requires an array/);
        });
    });
});
<commit_msg>typo fix<commit_after>var assert = require('assert');
var sinon = require('sinon');
var support = require('./support');
var check_err = support.check_err;
var caching = require('../index').caching;
var multi_caching = require('../index').multi_caching;
var memory_store = require('../lib/stores/memory');

function get_widget(name, cb) {
    cb(null, {name: name});
}

describe("multi_caching", function () {
    var redis_cache;
    var memory_cache;
    var memory_cache2;
    var multi_cache;
    var key;
    var memory_ttl;
    var redis_ttl;
    var name;

    beforeEach(function () {
        memory_ttl = 0.1;
        redis_ttl = 1;

        memory_cache = caching({store: 'memory', ttl: memory_ttl});
        memory_cache2 = caching({store: 'memory', ttl: memory_ttl});
        redis_cache = caching({store: 'redis', ttl: redis_ttl});

        key = support.random.string(20);
        name = support.random.string();
    });

    describe("get(), set(), del()", function () {
        var value;

        beforeEach(function () {
            multi_cache = multi_caching([memory_cache, redis_cache, memory_cache2]);
            key = support.random.string(20);
            value = support.random.string();
        });

        describe("set()", function () {
            it("lets us set data in all caches", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);
                    memory_cache.get(key, function (err, result) {
                        assert.equal(result, value);

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.equal(result, value);

                            memory_cache2.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, value);
                                done();
                            });
                        });
                    });
                });
            });

            it("lets us set data without a callback", function (done) {
                multi_cache.set(key, value);
                setTimeout(function () {
                    multi_cache.get(key, function (err, result) {
                        assert.equal(result, value);
                        memory_cache.get(key, function (err, result) {
                            assert.equal(result, value);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, value);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, value);
                                    done();
                                });
                            });
                        });
                    });
                }, 20);
            });
        });

        describe("get()", function () {
            it("gets data from first cache that has it", function (done) {
                redis_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.equal(result, value);
                        done();
                    });
                });
            });
        });

        describe("del()", function () {
            it("lets us delete data in all caches", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.del(key, function (err) {
                        check_err(err);

                        memory_cache.get(key, function (err, result) {
                            assert.ok(!result);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.ok(!result);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.ok(!result);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            it("lets us delete data without a callback", function (done) {
                multi_cache.set(key, value, function (err) {
                    check_err(err);

                    multi_cache.del(key);

                    setTimeout(function () {
                        memory_cache.get(key, function (err, result) {
                            assert.ok(!result);

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.ok(!result);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.ok(!result);
                                    done();
                                });
                            });
                        });
                    });
                }, 10);
            });
        });
    });

    describe("wrap()", function () {
        describe("using a single cache store", function () {
            beforeEach(function () {
                multi_cache = multi_caching([redis_cache]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });
        });

        describe("using two cache stores", function () {
            beforeEach(function () {
                multi_cache = multi_caching([memory_cache, redis_cache]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });

            it("sets value in all caches", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});

                    memory_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.deepEqual(result, {name: name});

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.deepEqual(result, {name: name});
                            done();
                        });
                    });
                });
            });

            context("when value exists in first store but not second", function () {
                it("returns value from first store, does not set it in second", function (done) {
                    memory_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, null);
                                done();
                            });
                        });
                    });
                });
            });

            context("when value exists in second store but not first", function () {
                it("returns value from second store, sets it in first store", function (done) {
                    redis_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            memory_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});
                                done();
                            });
                        });
                    });
                });
            });
        });

        describe("using three cache stores", function () {
            beforeEach(function () {
                multi_cache = multi_caching([memory_cache, redis_cache, memory_cache2]);
            });

            it("calls back with the result of a function", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});
                    done();
                });
            });

            it("sets value in all caches", function (done) {
                multi_cache.wrap(key, function (cb) {
                    get_widget(name, cb);
                }, function (err, widget) {
                    check_err(err);
                    assert.deepEqual(widget, {name: name});

                    memory_cache.get(key, function (err, result) {
                        check_err(err);
                        assert.deepEqual(result, {name: name});

                        redis_cache.get(key, function (err, result) {
                            check_err(err);
                            assert.deepEqual(result, {name: name});

                            memory_cache2.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});
                                done();
                            });
                        });
                    });
                });
            });

            context("when value exists in first store only", function () {
                it("returns value from first store, does not set it in second or third", function (done) {
                    memory_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.equal(result, null);

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, null);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            context("when value exists in second store only", function () {
                it("returns value from second store, sets it in first store, does not set third store", function (done) {
                    redis_cache.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            memory_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});

                                memory_cache2.get(key, function (err, result) {
                                    check_err(err);
                                    assert.equal(result, null);
                                    done();
                                });
                            });
                        });
                    });
                });
            });

            context("when value exists in third store only", function () {
                it("returns value from third store, sets it in first and second stores", function (done) {
                    memory_cache2.set(key, {name: name}, function (err) {
                        check_err(err);

                        multi_cache.wrap(key, function (cb) {
                            get_widget(name, cb);
                        }, function (err, widget) {
                            check_err(err);
                            assert.deepEqual(widget, {name: name});

                            redis_cache.get(key, function (err, result) {
                                check_err(err);
                                assert.deepEqual(result, {name: name});

                                memory_cache.get(key, function (err, result) {
                                    check_err(err);
                                    assert.deepEqual(result, {name: name});

                                    done();
                                });
                            });
                        });
                    });
                });
            });
        });

        context("error handling", function () {
            var memory_store_stub;
            var ttl;

            beforeEach(function () {
                ttl = 0.1;
                memory_store_stub = memory_store.create({ttl: ttl});
                sinon.stub(memory_store, 'create').returns(memory_store_stub);
                memory_cache = caching({store: 'memory', ttl: ttl});
                multi_cache = multi_caching([memory_cache]);
            });

            afterEach(function () {
                memory_store.create.restore();
            });

            context("when store.get() calls back with an error", function () {
                it("bubbles up that error", function (done) {
                    var fake_error = new Error(support.random.string());

                    sinon.stub(memory_store_stub, 'get', function (key, cb) {
                        cb(fake_error);
                    });

                    multi_cache.wrap(key, function (cb) {
                        get_widget(name, cb);
                    }, function (err) {
                        assert.equal(err, fake_error);
                        memory_store_stub.get.restore();
                        done();
                    });
                });
            });

            context("when store.set() calls back with an error", function () {
                it("bubbles up that error", function (done) {
                    var fake_error = new Error(support.random.string());

                    sinon.stub(memory_store_stub, 'set', function (key, val, cb) {
                        cb(fake_error);
                    });

                    multi_cache.wrap(key, function (cb) {
                        get_widget(name, cb);
                    }, function (err) {
                        assert.equal(err, fake_error);
                        memory_store_stub.set.restore();
                        done();
                    });
                });
            });
        });
    });

    context("when instantiated with a non-Array 'caches' arg", function () {
        it("throws an error", function () {
            assert.throws(function () {
                multi_caching({foo: 'bar'});
            }, /multi_caching requires an array/);
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Handlers for page-related and tab-related functionality
 */
function Page() {
}

/**
 * The current su state
 */
Page.state = [];

/**
 * Get the last known state of the provided tab
 *
 * @param {Number} tabid Tab ID
 * @return {Object} current state of tabid
 */
Page.lastState = function(tabid) {
	return Page.state[tabid] || {};
}

/**
 * Preload helper, takes an SU url object (usually the next stumble) and preloads that page
 *
 * @param {SuUrl} url SuUrl object to attempt to preload
 */
Page.preload = function(url) {
	Page._prerender.href  = url.url;
	Page._prefetch.href   = url.url;
	Page._preload.href    = url.url;
	debug("Preload", url.url);
}

/**
 * Browser icon click handler.  Pings the current tab to see if it has rendered.
 * If it has, it toggles hidden.  If it hasn't, it attempts to stumble.
 *
 * @param {event} e window.event object
 */
Page.handleIconClick = function(e) {
	Page.ping()
		.then(function(res) {
			return ToolbarEvent.handleRequest(
					{
						action: 'toggleHidden',
						url: {},
						data: {}
					},
					{ tab: res.tab },
					function() {}
				);
		})
		.catch(function(res) {
			ToolbarEvent.stumble({}, res)
				.catch(ToolbarEvent.loginPage);
		});
}

/**
 * Pings a tabid
 *
 * @param {Number} tabid Tab ID to ping
 * @return {Promise}
 */
Page.ping = function(tabid) {
	return new Promise(function(resolve, reject) {
		chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
			if (!tabs[0])
				return;
			chrome.tabs.sendMessage(tabid || tabs[0].id, {type: "ping", info: tabs[0]}, function(response) {
				// Handle pages that we can't inject
				if (!response || response.type != 'pong')
					reject({tab: {id: tabid || tabs[0].id}, response});
				else
					resolve({tab: {id: tabid || tabs[0].id}, response});
			});
		});
	});
}

/**
 * The current tab info
 */
Page.tab = {};

/**
 * Get the last url seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.lastUrl = function(tabid) {
	return Page.tab[tabid] && Page.tab[tabid].url;
}

/**
 * Get the last urlid seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.getUrlId = function(tabid) {
	return Page.tab[tabid] && Page.tab[tabid].url && Page.tab[tabid].url.urlid;
}

/**
 * Get the last urlid seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.getUrl = function(tabid) {
	var url = Page.tab[tabid] && Page.tab[tabid].url  && Page.tab[tabid].url.finalUrl
		   || Page.tab[tabid] && Page.tab[tabid].info && Page.tab[tabid].info.url;
	;

	if (!url)
		return Promise.reject({});

	return Promise.resolve(url);

//		chrome.tabs.get(tabid, function(tab) {
//			resolve(tab.url);
//		});
}

/**
 * A cache of fetched SuUrls
 */
Page.urlCache = [];
Page.urlMap   = {};

/**
 * Get a SuUrl from the urlCache
 *
 * @param {String} href The url to fetch from the cache
 * @return {Object}
 */
Page.getUrlByHref = function(href) {
	return Page.urlMap[href];
}

/**
 * Get a SuUrl by urlid from the urlCache.  Note that this may return an
 * url that was generated in another mode and has that mode's metadata.
 *
 * @param {String} urlid The public url id
 * @param {String} mode The mode
 * @return {SuUrl}
 */
Page.getUrlByUrlid = function(urlid, mode) {
	return Page.urlMap[mode + ':' + urlid] || Page.urlMap[urlid];
}

/**
 * Cleans up url cache by trimming the cache down to 1000 urls
 */
Page.cleanupUrlCache = function() {
	if (Page.urlCache.length >= 1e3) {
		var errantUrl = Page.urlCache.splice(0, 1)[0];
		Page.removeUrlFromUrlCache(errantUrl);
	}
}

/**
 * Removes a SuUrl from the url cache
 */
Page.removeUrlFromUrlCache = function(url) {
	if (!url)
		return;
	if (url.urlid && url.mode)
		delete Page.urlMap[url.urlid];
	if (url.urlid)
		delete Page.urlMap[url.mode + ':' + url.urlid];
	if (url.url)
		delete Page.urlMap[url.url];
	if (url.finalUrl)
		delete Page.urlMap[url.finalUrl];
}

/**
 * Note the current SuUrl loaded by the current tabid.  Adds url to the url cache, performs cleanup.
 *
 * @param {Number} tabid Tab ID
 * @param {SuUrl} url An SuUrl object
 * @return {SuUrl}
 */
Page.note = function(tabid, url, onlynote) {
	if (!Page.tab[tabid])
		Page.tab[tabid] = {};

	if (url.urlid && url.mode)
		Page.urlMap[url.mode + ':' + url.urlid] = url;
	if (url.urlid)
		Page.urlMap[url.urlid] = url;
	if (url.url)
		Page.urlMap[url.url] = url;
	if (url.finalUrl)
		Page.urlMap[url.finalUrl] = url;

	if (Page.urlCache.indexOf(url) == -1)
		Page.urlCache.push(url);

	Page.cleanupUrlCache();

	return onlynote ? url : Page.tab[tabid].url = url;
}

/**
 * Handle URL changes triggered by tab or stumble events
 *
 * @param {String} href The new uri
 * @param {Number} tabid Tab ID
 * @return {Promise}
 */
Page.urlChange = function(href, tabid) {
	chrome.tabs.getZoom(tabid, function(zoom) {
		chrome.tabs.sendMessage(tabid, { zoom: zoom });
	});

	// Handle http://su/su/{urlid} urls.  Stop the request, redirect directly to page, return a promise
	webtbPath = href.match(new RegExp("https?://" + config.baseUrl + config.webtbPath));
	if (webtbPath) {
		ToolbarEvent._sanity();
		var urlid = webtbPath[config.webtbPathNames.urlid];
		if (urlid) {
			// Stop current page from loading
			chrome.tabs.executeScript(tabid, {
				code: "window.stop();",
			});
			chrome.tabs.update(tabid, { url: 'about:blank' });

			return Promise.resolve(Page.getUrlByUrlid(urlid, config.mode) || ToolbarEvent.api.getUrlByUrlid(urlid))
				.then(function(url) {
					chrome.tabs.update(tabid, { url: url.url });
					ToolbarEvent.unhideToolbar();

					return ToolbarEvent._buildResponse({ url: url, hidden: false })
				})
				.catch(ToolbarEvent.error);
			;
		}
	}

	suPath = href.match(new RegExp("https?://" + config.baseUrl + '/logout'));
	if (suPath) {
		debug('LOGGING OUT');
		return;
	}

	// If we're hitting http://su/..., revalidate our auth
	suPath = href.match(new RegExp("https?://" + config.baseUrl + '/(.*)'));
	if (suPath && !config.authed) {
		if (path)
			ToolbarEvent._sanity();
		debug('SUPATH SANITY CHECK ' + href);
	}

	// If we're hitting http://su/convo/..., set the conversation id on the page state
	convoPath = href.match(new RegExp("https?://" + config.baseUrl + config.convoPath));
	if (convoPath) {
		Page.state[tabid] = { convo: convoPath[config.convoPathNames.convoid] };
		console.log('CONVO ON ' + tabid);
	}

	// Attempted to pull the current url from the page cache or SU api.  If we can,
	// report it to the toolbar in the current tab
	return Promise
		.resolve(Page.getUrlByHref(href))
		.then(function(url) {
			return url && Page.getUrlByUrlid(url.urlid, config.mode);
		})
		.then(function(url) {
			return url || ToolbarEvent.api.getUrlByHref(href);
		})
		.then(function(url) {
			Page.note(tabid, url, Page.tab[tabid].status.url == href);
			if (Page.tab[tabid].status.url == href)
				chrome.tabs.sendMessage(tabid, { url: url }, function() {});
		})
		.catch(function(error) {
			if (Page.tab[tabid].status.url == href)
				chrome.tabs.sendMessage(tabid, { url: { url: href } }, function() {});
		});
	;
}

/**
 * Handle tab loading and complete messages
 *
 * @param {Number} tabid Tab ID
 * @param {Object} info Tab info object
 * @param {Object} tab The new state of the tab
 */
Page.handleTabUpdate = function(tabid, info, tab) {
//	console.log('update', tabid, info, tab);
	Page.ping();

	if (!Page.tab[tabid])
		Page.tab[tabid] = {};

	if (info.status == "loading") {
		Page.tab[tabid].status = { state: info.status, url: tab.url };
		// User is changing the URL
		if (Page.tab[tabid].url && Page.tab[tabid].url.url != tab.url)
			Page.tab[tabid].url = {}
		Page.urlChange(info.url || tab.url, tabid);
	}

	if (info.status == "complete") {
		Page.tab[tabid].status = { state: info.status, url: tab.url };
		Page.tab[tabid].info = tab;
		if (Page.tab[tabid].url && !Page.tab[tabid].url.finalUrl)
			Page.tab[tabid].url.finalUrl = info.url;
		Page.urlChange(info.url || tab.url, tabid);
	}
}

/**
 * Does nothing, but in the future can be used to unload the stumblebar
 * from contexts to save memory
 */
Page.handleTabSwitch = function(e) {
	//console.log('switch', e);
}

/**
 * Clean up tab states and caches on tab close
 *
 * @param {Number} tabid Tab ID
 */
Page.handleTabClose = function(tabid) {
	if (Page.state[tabid])
		delete Page.state[tabid];
	if (Page.tab[tabid]) {
		Page.removeUrlFromUrlCache(Page.lastUrl(tabid));
		delete Page.tab[tabid];
	}
}

Page.handleZoom = function(zoom) {
	chrome.tabs.sendMessage(zoom.tabId, { zoom: zoom.newZoomFactor });
}

Page.handleFreshen = function() {
	chrome.tabs.query({}, function(tabs) {
		tabs.forEach(function(tab) {
			try {
				chrome.tabs.executeScript(tab.id, {code: "document.getElementById('discoverbar') && document.documentElement.removeChild(document.getElementById('discoverbar'), document.documentElement)"});
			} catch(e) {}
		});
	});
}

/**
 * Initialize page handlers
 */
Page.init = function() {
	// listen to tab URL changes
	chrome.tabs.onUpdated.addListener(Page.handleTabUpdate);

	// listen to tab switching
	chrome.tabs.onActivated.addListener(Page.handleTabSwitch);

	chrome.tabs.onRemoved.addListener(Page.handleTabClose);

	chrome.tabs.onZoomChange.addListener(Page.handleZoom);

	chrome.browserAction.onClicked.addListener(Page.handleIconClick);

	chrome.runtime.onInstalled.addListener(Page.handleFreshen);

	Page._prerender  = document.createElement('link');
	Page._prefetch   = document.createElement('link');
	Page._preload    = document.createElement('link');

	Page._prerender.rel  = 'prerender';
	Page._prefetch.rel   = 'prefetch';
	Page._preload.rel    = 'preload';

	document.body.appendChild(Page._prerender);
	document.body.appendChild(Page._prefetch);
	document.body.appendChild(Page._preload);
}

Page.init();
<commit_msg>Fix missing initial status<commit_after>/**
 * Handlers for page-related and tab-related functionality
 */
function Page() {
}

/**
 * The current su state
 */
Page.state = [];

/**
 * Get the last known state of the provided tab
 *
 * @param {Number} tabid Tab ID
 * @return {Object} current state of tabid
 */
Page.lastState = function(tabid) {
	return Page.state[tabid] || {};
}

/**
 * Preload helper, takes an SU url object (usually the next stumble) and preloads that page
 *
 * @param {SuUrl} url SuUrl object to attempt to preload
 */
Page.preload = function(url) {
	Page._prerender.href  = url.url;
	Page._prefetch.href   = url.url;
	Page._preload.href    = url.url;
	debug("Preload", url.url);
}

/**
 * Browser icon click handler.  Pings the current tab to see if it has rendered.
 * If it has, it toggles hidden.  If it hasn't, it attempts to stumble.
 *
 * @param {event} e window.event object
 */
Page.handleIconClick = function(e) {
	Page.ping()
		.then(function(res) {
			return ToolbarEvent.handleRequest(
					{
						action: 'toggleHidden',
						url: {},
						data: {}
					},
					{ tab: res.tab },
					function() {}
				);
		})
		.catch(function(res) {
			ToolbarEvent.stumble({}, res)
				.catch(ToolbarEvent.loginPage);
		});
}

/**
 * Pings a tabid
 *
 * @param {Number} tabid Tab ID to ping
 * @return {Promise}
 */
Page.ping = function(tabid) {
	return new Promise(function(resolve, reject) {
		chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
			if (!tabs[0])
				return;
			chrome.tabs.sendMessage(tabid || tabs[0].id, {type: "ping", info: tabs[0]}, function(response) {
				// Handle pages that we can't inject
				if (!response || response.type != 'pong')
					reject({tab: {id: tabid || tabs[0].id}, response});
				else
					resolve({tab: {id: tabid || tabs[0].id}, response});
			});
		});
	});
}

/**
 * The current tab info
 */
Page.tab = {};

/**
 * Get the last url seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.lastUrl = function(tabid) {
	return Page.tab[tabid] && Page.tab[tabid].url;
}

/**
 * Get the last urlid seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.getUrlId = function(tabid) {
	return Page.tab[tabid] && Page.tab[tabid].url && Page.tab[tabid].url.urlid;
}

/**
 * Get the last urlid seen by the provided tab id
 *
 * @param {Number} tabid Tab ID
 * @return {SuUrl}
 */
Page.getUrl = function(tabid) {
	var url = Page.tab[tabid] && Page.tab[tabid].url  && Page.tab[tabid].url.finalUrl
		   || Page.tab[tabid] && Page.tab[tabid].info && Page.tab[tabid].info.url;
	;

	if (!url)
		return Promise.reject({});

	return Promise.resolve(url);

//		chrome.tabs.get(tabid, function(tab) {
//			resolve(tab.url);
//		});
}

/**
 * A cache of fetched SuUrls
 */
Page.urlCache = [];
Page.urlMap   = {};

/**
 * Get a SuUrl from the urlCache
 *
 * @param {String} href The url to fetch from the cache
 * @return {Object}
 */
Page.getUrlByHref = function(href) {
	return Page.urlMap[href];
}

/**
 * Get a SuUrl by urlid from the urlCache.  Note that this may return an
 * url that was generated in another mode and has that mode's metadata.
 *
 * @param {String} urlid The public url id
 * @param {String} mode The mode
 * @return {SuUrl}
 */
Page.getUrlByUrlid = function(urlid, mode) {
	return Page.urlMap[mode + ':' + urlid] || Page.urlMap[urlid];
}

/**
 * Cleans up url cache by trimming the cache down to 1000 urls
 */
Page.cleanupUrlCache = function() {
	if (Page.urlCache.length >= 1e3) {
		var errantUrl = Page.urlCache.splice(0, 1)[0];
		Page.removeUrlFromUrlCache(errantUrl);
	}
}

/**
 * Removes a SuUrl from the url cache
 */
Page.removeUrlFromUrlCache = function(url) {
	if (!url)
		return;
	if (url.urlid && url.mode)
		delete Page.urlMap[url.urlid];
	if (url.urlid)
		delete Page.urlMap[url.mode + ':' + url.urlid];
	if (url.url)
		delete Page.urlMap[url.url];
	if (url.finalUrl)
		delete Page.urlMap[url.finalUrl];
}

/**
 * Note the current SuUrl loaded by the current tabid.  Adds url to the url cache, performs cleanup.
 *
 * @param {Number} tabid Tab ID
 * @param {SuUrl} url An SuUrl object
 * @return {SuUrl}
 */
Page.note = function(tabid, url, onlynote) {
	if (!Page.tab[tabid])
		Page.tab[tabid] = {};

	if (url.urlid && url.mode)
		Page.urlMap[url.mode + ':' + url.urlid] = url;
	if (url.urlid)
		Page.urlMap[url.urlid] = url;
	if (url.url)
		Page.urlMap[url.url] = url;
	if (url.finalUrl)
		Page.urlMap[url.finalUrl] = url;

	if (Page.urlCache.indexOf(url) == -1)
		Page.urlCache.push(url);

	Page.cleanupUrlCache();

	return onlynote ? url : Page.tab[tabid].url = url;
}

/**
 * Handle URL changes triggered by tab or stumble events
 *
 * @param {String} href The new uri
 * @param {Number} tabid Tab ID
 * @return {Promise}
 */
Page.urlChange = function(href, tabid) {
	chrome.tabs.getZoom(tabid, function(zoom) {
		chrome.tabs.sendMessage(tabid, { zoom: zoom });
	});

	// Handle http://su/su/{urlid} urls.  Stop the request, redirect directly to page, return a promise
	webtbPath = href.match(new RegExp("https?://" + config.baseUrl + config.webtbPath));
	if (webtbPath) {
		ToolbarEvent._sanity();
		var urlid = webtbPath[config.webtbPathNames.urlid];
		if (urlid) {
			// Stop current page from loading
			chrome.tabs.executeScript(tabid, {
				code: "window.stop();",
			});
			chrome.tabs.update(tabid, { url: 'about:blank' });

			return Promise.resolve(Page.getUrlByUrlid(urlid, config.mode) || ToolbarEvent.api.getUrlByUrlid(urlid))
				.then(function(url) {
					chrome.tabs.update(tabid, { url: url.url });
					ToolbarEvent.unhideToolbar();

					return ToolbarEvent._buildResponse({ url: url, hidden: false })
				})
				.catch(ToolbarEvent.error);
			;
		}
	}

	suPath = href.match(new RegExp("https?://" + config.baseUrl + '/logout'));
	if (suPath) {
		debug('LOGGING OUT');
		return;
	}

	// If we're hitting http://su/..., revalidate our auth
	suPath = href.match(new RegExp("https?://" + config.baseUrl + '/(.*)'));
	if (suPath && !config.authed) {
		if (path)
			ToolbarEvent._sanity();
		debug('SUPATH SANITY CHECK ' + href);
	}

	// If we're hitting http://su/convo/..., set the conversation id on the page state
	convoPath = href.match(new RegExp("https?://" + config.baseUrl + config.convoPath));
	if (convoPath) {
		Page.state[tabid] = { convo: convoPath[config.convoPathNames.convoid] };
		console.log('CONVO ON ' + tabid);
	}

	// Attempted to pull the current url from the page cache or SU api.  If we can,
	// report it to the toolbar in the current tab
	return Promise
		.resolve(Page.getUrlByHref(href))
		.then(function(url) {
			return url && Page.getUrlByUrlid(url.urlid, config.mode);
		})
		.then(function(url) {
			return url || ToolbarEvent.api.getUrlByHref(href);
		})
		.then(function(url) {
			Page.note(tabid, url, Page.tab[tabid].status.url == href);
			if (!(Page.tab[tabid] || {}).status || Page.tab[tabid].status.url == href)
				chrome.tabs.sendMessage(tabid, { url: url }, function() {});
		})
		.catch(function(error) {
			if (!(Page.tab[tabid] || {}).status || Page.tab[tabid].status.url == href)
				chrome.tabs.sendMessage(tabid, { url: { url: href } }, function() {});
		});
	;
}

/**
 * Handle tab loading and complete messages
 *
 * @param {Number} tabid Tab ID
 * @param {Object} info Tab info object
 * @param {Object} tab The new state of the tab
 */
Page.handleTabUpdate = function(tabid, info, tab) {
//	console.log('update', tabid, info, tab);
	Page.ping();

	if (!Page.tab[tabid])
		Page.tab[tabid] = {};

	if (info.status == "loading") {
		Page.tab[tabid].status = { state: info.status, url: tab.url };
		// User is changing the URL
		if (Page.tab[tabid].url && Page.tab[tabid].url.url != tab.url)
			Page.tab[tabid].url = {}
		Page.urlChange(info.url || tab.url, tabid);
	}

	if (info.status == "complete") {
		Page.tab[tabid].status = { state: info.status, url: tab.url };
		Page.tab[tabid].info = tab;
		if (Page.tab[tabid].url && !Page.tab[tabid].url.finalUrl)
			Page.tab[tabid].url.finalUrl = info.url;
		Page.urlChange(info.url || tab.url, tabid);
	}
}

/**
 * Does nothing, but in the future can be used to unload the stumblebar
 * from contexts to save memory
 */
Page.handleTabSwitch = function(e) {
	//console.log('switch', e);
}

/**
 * Clean up tab states and caches on tab close
 *
 * @param {Number} tabid Tab ID
 */
Page.handleTabClose = function(tabid) {
	if (Page.state[tabid])
		delete Page.state[tabid];
	if (Page.tab[tabid]) {
		Page.removeUrlFromUrlCache(Page.lastUrl(tabid));
		delete Page.tab[tabid];
	}
}

Page.handleZoom = function(zoom) {
	chrome.tabs.sendMessage(zoom.tabId, { zoom: zoom.newZoomFactor });
}

Page.handleFreshen = function() {
	chrome.tabs.query({}, function(tabs) {
		tabs.forEach(function(tab) {
			try {
				chrome.tabs.executeScript(tab.id, {code: "document.getElementById('discoverbar') && document.documentElement.removeChild(document.getElementById('discoverbar'), document.documentElement)"});
			} catch(e) {}
		});
	});
}

/**
 * Initialize page handlers
 */
Page.init = function() {
	// listen to tab URL changes
	chrome.tabs.onUpdated.addListener(Page.handleTabUpdate);

	// listen to tab switching
	chrome.tabs.onActivated.addListener(Page.handleTabSwitch);

	chrome.tabs.onRemoved.addListener(Page.handleTabClose);

	chrome.tabs.onZoomChange.addListener(Page.handleZoom);

	chrome.browserAction.onClicked.addListener(Page.handleIconClick);

	chrome.runtime.onInstalled.addListener(Page.handleFreshen);

	Page._prerender  = document.createElement('link');
	Page._prefetch   = document.createElement('link');
	Page._preload    = document.createElement('link');

	Page._prerender.rel  = 'prerender';
	Page._prefetch.rel   = 'prefetch';
	Page._preload.rel    = 'preload';

	document.body.appendChild(Page._prerender);
	document.body.appendChild(Page._prefetch);
	document.body.appendChild(Page._preload);
}

Page.init();
<|endoftext|>


<commit_before>//component/icon.js

var Icon = React.createClass({
  propTypes: {
    style: React.PropTypes.object,
    fixed: React.PropTypes.boolean,
  },
  render: function() {
    var className = 'icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon;
    return
  }
});

var toolTipStyle = {
  position: 'absolute',
  zIndex: '1',
  top: '100%',
  left: '-120px',
  width: '260px',
  padding: '15px',
  border: '1px solid #aaa',
  backgroundColor: '#fff',
  fontSize: '14px',
};
var ToolTip = React.createClass({
  propTypes: {
    open: React.PropTypes.bool.isRequired,
    onMouseOut: React.PropTypes.func
  },
  render: function() {
    return (

        {this.props.children}

    );
  }
});

var linkContainerStyle = {
  position: 'relative',
};
var Link = React.createClass({
  getInitialState: function() {
    return {
      showTooltip: false,
    };
  },
  handleClick: function() {
    if (this.props.tooltip) {
      this.setState({
        showTooltip: !this.state.showTooltip,
      });
    }
    if (this.props.onClick) {
      this.props.onClick();
    }
  },
  handleTooltipMouseOut: function() {
    this.setState({
      showTooltip: false,
    });
  },
  render: function() {
    var href = this.props.href ? this.props.href : 'javascript:;',
      icon = this.props.icon ? <Icon icon={this.props.icon} />  : '',
      className = (this.props.button ? 'button-block button-' + this.props.button : 'button-text') +
                  (this.props.hidden ? ' hidden' : '') + (this.props.disabled ? ' disabled' : '');

    return (

          {this.props.icon ? icon : '' }
          {this.props.label}

        {(!this.props.tooltip ? null :
          <ToolTip open={this.state.showTooltip} onMouseOut={this.handleTooltipMouseOut}>
            {this.props.tooltip}
          </ToolTip>
        )}

    );
  }
});

var DownloadLink = React.createClass({
  propTypes: {
    type: React.PropTypes.string,
    streamName: React.PropTypes.string,
    label: React.PropTypes.string,
    downloadingLabel: React.PropTypes.string,
    button: React.PropTypes.string,
    style: React.PropTypes.object,
    hidden: React.PropTypes.bool,
  },
  getDefaultProps: function() {
    return {
      icon: 'icon-download',
      label: 'Download',
      downloadingLabel: 'Downloading...',
    }
  },
  getInitialState: function() {
    return {
      downloading: false,
    }
  },
  startDownload: function() {
    if (!this.state.downloading) { //@TODO: Continually update this.state.downloading based on actual status of file
      this.setState({
        downloading: true
      });

      lbry.getStream(this.props.streamName, (streamInfo) => {
        alert('Downloading to ' + streamInfo.path);
        console.log(streamInfo);
      });
    }
  },
  render: function() {
    var label = (!this.state.downloading ? this.props.label : this.props.downloadingLabel);
    return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
                 disabled={this.state.downloading} label={label} icon={this.props.icon} onClick={this.startDownload} />;
  }
});

var WatchLink = React.createClass({
  propTypes: {
    type: React.PropTypes.string,
    streamName: React.PropTypes.string,
    label: React.PropTypes.string,
    button: React.PropTypes.string,
    style: React.PropTypes.object,
    hidden: React.PropTypes.bool,
  },

  getDefaultProps: function() {
    return {
      icon: 'icon-play',
      label: 'Watch',
    }
  },

  render: function() {
    var uri = "/?watch=" + this.props.streamName;

    return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
                 href={uri} label={this.props.label} icon={this.props.icon} onClick={this.onClick} />;
  }
});

// Generic menu styles
var menuStyle = {
  border: '1px solid #aaa',
  padding: '4px',
  whiteSpace: 'nowrap',
};

var Menu = React.createClass({
  handleWindowClick: function(e) {
    if (this.props.toggleButton && ReactDOM.findDOMNode(this.props.toggleButton).contains(e.target)) {
      // Toggle button was clicked
      this.setState({
        open: !this.state.open
      });
    } else if (this.state.open && !this.refs.div.contains(e.target)) {
      // Menu is open and user clicked outside of it
      this.setState({
        open: false
      });
    }
  },
  propTypes: {
    openButton: React.PropTypes.element,
  },
  getInitialState: function() {
    return {
      open: false,
    };
  },
  componentDidMount: function() {
    window.addEventListener('click', this.handleWindowClick, false);
  },
  componentWillUnmount: function() {
    window.removeEventListener('click', this.handleWindowClick, false);
  },
  render: function() {
    return (

        {this.props.children}

    );
  }
});

var menuItemStyle = {
  display: 'block',
};
var MenuItem = React.createClass({
  propTypes: {
    href: React.PropTypes.string,
    label: React.PropTypes.string,
    icon: React.PropTypes.string,
    onClick: React.PropTypes.function,
  },
  getDefaultProps: function() {
    return {
      iconPosition: 'left',
    }
  },
  render: function() {
    var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);

    return (

        {this.props.iconPosition == 'left' ? icon : null}
        {this.props.label}
        {this.props.iconPosition == 'left' ? null : icon}

    );
  }
});

var creditAmountStyle = {
  color: '#216C2A',
  fontWeight: 'bold',
  fontSize: '0.8em'
}, estimateStyle = {
  marginLeft : '5px',
  color: '#aaa',
};

var CreditAmount = React.createClass({
  propTypes: {
    amount: React.PropTypes.number,
  },
  render: function() {
    var formattedAmount = lbry.formatCredits(this.props.amount);
    return (

        {formattedAmount}
        { this.props.isEstimate ? (est) : null }

    );
  }
});

var subPageLogoStyle = {
  maxWidth: '150px',
  display: 'block',
  marginTop: '36px',
};

var SubPageLogo = React.createClass({
  render: function() {
    return ;
  }
});<commit_msg>Alert user if they don't have enough credits for watch/download<commit_after>//component/icon.js

var Icon = React.createClass({
  propTypes: {
    style: React.PropTypes.object,
    fixed: React.PropTypes.boolean,
  },
  render: function() {
    var className = 'icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') + this.props.icon;
    return
  }
});

var toolTipStyle = {
  position: 'absolute',
  zIndex: '1',
  top: '100%',
  left: '-120px',
  width: '260px',
  padding: '15px',
  border: '1px solid #aaa',
  backgroundColor: '#fff',
  fontSize: '14px',
};
var ToolTip = React.createClass({
  propTypes: {
    open: React.PropTypes.bool.isRequired,
    onMouseOut: React.PropTypes.func
  },
  render: function() {
    return (

        {this.props.children}

    );
  }
});

var linkContainerStyle = {
  position: 'relative',
};
var Link = React.createClass({
  getInitialState: function() {
    return {
      showTooltip: false,
    };
  },
  handleClick: function() {
    if (this.props.tooltip) {
      this.setState({
        showTooltip: !this.state.showTooltip,
      });
    }
    if (this.props.onClick) {
      this.props.onClick();
    }
  },
  handleTooltipMouseOut: function() {
    this.setState({
      showTooltip: false,
    });
  },
  render: function() {
    var href = this.props.href ? this.props.href : 'javascript:;',
      icon = this.props.icon ? <Icon icon={this.props.icon} />  : '',
      className = (this.props.button ? 'button-block button-' + this.props.button : 'button-text') +
                  (this.props.hidden ? ' hidden' : '') + (this.props.disabled ? ' disabled' : '');

    return (

          {this.props.icon ? icon : '' }
          {this.props.label}

        {(!this.props.tooltip ? null :
          <ToolTip open={this.state.showTooltip} onMouseOut={this.handleTooltipMouseOut}>
            {this.props.tooltip}
          </ToolTip>
        )}

    );
  }
});

var DownloadLink = React.createClass({
  propTypes: {
    type: React.PropTypes.string,
    streamName: React.PropTypes.string,
    label: React.PropTypes.string,
    downloadingLabel: React.PropTypes.string,
    button: React.PropTypes.string,
    style: React.PropTypes.object,
    hidden: React.PropTypes.bool,
  },
  getDefaultProps: function() {
    return {
      icon: 'icon-download',
      label: 'Download',
      downloadingLabel: 'Downloading...',
    }
  },
  getInitialState: function() {
    return {
      downloading: false,
    }
  },
  handleClick: function() {
    lbry.getCostEstimate(this.props.streamName, (amount) => {
      lbry.getBalance((balance) => {
        if (amount > balance) {
          alert("You don't have enough LBRY credits to pay for this stream.");
        } else {
          this.startDownload();
        }
      });
    });
  },
  startDownload: function() {
    if (!this.state.downloading) { //@TODO: Continually update this.state.downloading based on actual status of file
      this.setState({
        downloading: true
      });

      lbry.getStream(this.props.streamName, (streamInfo) => {
        alert('Downloading to ' + streamInfo.path);
        console.log(streamInfo);
      });
    }
  },
  render: function() {
    var label = (!this.state.downloading ? this.props.label : this.props.downloadingLabel);
    return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
                 disabled={this.state.downloading} label={label} icon={this.props.icon} onClick={this.handleClick} />;
  }
});

var WatchLink = React.createClass({
  propTypes: {
    type: React.PropTypes.string,
    streamName: React.PropTypes.string,
    label: React.PropTypes.string,
    button: React.PropTypes.string,
    style: React.PropTypes.object,
    hidden: React.PropTypes.bool,
  },
  handleClick: function() {
    lbry.getCostEstimate(this.props.streamName, (amount) => {
      lbry.getBalance((balance) => {
        if (amount > balance) {
          alert("You don't have enough LBRY credits to pay for this stream.");
        } else {
          window.location = '?watch=' + this.props.streamName;
        }
      });
    });
  },
  getDefaultProps: function() {
    return {
      icon: 'icon-play',
      label: 'Watch',
    }
  },

  render: function() {
    return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
                 label={this.props.label} icon={this.props.icon} onClick={this.handleClick} />;
  }
});

// Generic menu styles
var menuStyle = {
  border: '1px solid #aaa',
  padding: '4px',
  whiteSpace: 'nowrap',
};

var Menu = React.createClass({
  handleWindowClick: function(e) {
    if (this.props.toggleButton && ReactDOM.findDOMNode(this.props.toggleButton).contains(e.target)) {
      // Toggle button was clicked
      this.setState({
        open: !this.state.open
      });
    } else if (this.state.open && !this.refs.div.contains(e.target)) {
      // Menu is open and user clicked outside of it
      this.setState({
        open: false
      });
    }
  },
  propTypes: {
    openButton: React.PropTypes.element,
  },
  getInitialState: function() {
    return {
      open: false,
    };
  },
  componentDidMount: function() {
    window.addEventListener('click', this.handleWindowClick, false);
  },
  componentWillUnmount: function() {
    window.removeEventListener('click', this.handleWindowClick, false);
  },
  render: function() {
    return (

        {this.props.children}

    );
  }
});

var menuItemStyle = {
  display: 'block',
};
var MenuItem = React.createClass({
  propTypes: {
    href: React.PropTypes.string,
    label: React.PropTypes.string,
    icon: React.PropTypes.string,
    onClick: React.PropTypes.function,
  },
  getDefaultProps: function() {
    return {
      iconPosition: 'left',
    }
  },
  render: function() {
    var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);

    return (

        {this.props.iconPosition == 'left' ? icon : null}
        {this.props.label}
        {this.props.iconPosition == 'left' ? null : icon}

    );
  }
});

var creditAmountStyle = {
  color: '#216C2A',
  fontWeight: 'bold',
  fontSize: '0.8em'
}, estimateStyle = {
  marginLeft : '5px',
  color: '#aaa',
};

var CreditAmount = React.createClass({
  propTypes: {
    amount: React.PropTypes.number,
  },
  render: function() {
    var formattedAmount = lbry.formatCredits(this.props.amount);
    return (

        {formattedAmount}
        { this.props.isEstimate ? (est) : null }

    );
  }
});

var subPageLogoStyle = {
  maxWidth: '150px',
  display: 'block',
  marginTop: '36px',
};

var SubPageLogo = React.createClass({
  render: function() {
    return ;
  }
});<|endoftext|>


<commit_before>var helper = require('./helper');

var assert = helper.assert;
var expect = helper.expect;
var eventStream = helper.eventStream;
var Connection = require('mongodb-connection-model');
var ObjectId = require('bson').ObjectId;

var NativeClient = require('../lib/native-client');

describe('NativeClient', function() {
  var client = new NativeClient(helper.connection);

  before(require('mongodb-runner/mocha/before')({
    port: 27018
  }));

  after(require('mongodb-runner/mocha/after')({
    port: 27018
  }));

  before(function(done) {
    client.connect(done);
  });

  describe('#connect', function() {
    context('when an invalid connection was provided', function() {
      var badConnection =
        new Connection({ hostname: '127.0.0.1', port: 27050, ns: 'data-service' });
      var badClient = new NativeClient(badConnection);
      var message = 'MongoDB not running on the provided host and port';
      it('maps the error message', function(done) {
        badClient.connect(function(error) {
          expect(error.message).to.equal(message);
          done();
        });
      });
    });
  });

  describe('#new', function() {
    it('sets the model on the instance', function() {
      expect(client.model).to.equal(helper.connection);
    });
  });

  describe('#find', function() {
    before(function(done) {
      helper.insertTestDocuments(client, function() {
        done();
      });
    });

    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when a filter is provided', function() {
      it('returns a cursor for the matching documents', function(done) {
        client.find('data-service.test', { a: 1 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });

    context('when no filter is provided', function() {
      it('returns a cursor for all documents', function(done) {
        client.find('data-service.test', {}, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(2);
          done();
        });
      });
    });

    context('when options are provided', function() {
      it('returns a cursor for the documents', function(done) {
        client.find('data-service.test', {}, { skip: 1 }, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });
  });

  describe('#collectionDetail', function() {
    it('returns the collection details', function(done) {
      client.collectionDetail('data-service.test', function(err, coll) {
        assert.equal(null, err);
        expect(coll.ns).to.equal('data-service.test');
        expect(coll.index_count).to.equal(1);
        done();
      });
    });
  });

  describe('#collectionNames', function() {
    it('returns the collection names', function(done) {
      client.collectionNames('data-service', function(err, names) {
        assert.equal(null, err);
        expect(names[0]).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#collections', function() {
    it('returns the collections', function(done) {
      client.collections('data-service', function(err, collections) {
        assert.equal(null, err);
        expect(collections[0].name).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#collectionStats', function() {
    it('returns an object with the collection stats', function(done) {
      client.collectionStats('data-service', 'test', function(err, stats) {
        assert.equal(null, err);
        expect(stats.name).to.equal('test');
        done();
      });
    });
  });

  describe('#databaseDetail', function() {
    it('returns the database details', function(done) {
      client.databaseDetail('data-service', function(err, database) {
        assert.equal(null, err);
        expect(database._id).to.equal('data-service');
        expect(database.stats.document_count).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#databaseStats', function() {
    context('when the user is authorized', function() {
      it('returns an object with the db stats', function(done) {
        client.databaseStats('native-service', function(err, stats) {
          assert.equal(null, err);
          expect(stats.document_count).to.equal(0);
          done();
        });
      });
    });

    context('when the user is not authorized', function() {
      it('passes an error to the callback');
    });
  });

  describe('#count', function() {
    context('when a filter is provided', function() {
      it('returns a count for the matching documents', function(done) {
        client.count('data-service.test', { a: 1 }, {}, function(error, count) {
          assert.equal(null, error);
          expect(count).to.equal(0);
          done();
        });
      });
    });
  });

  describe('#explain', function() {
    context('when a filter is provided', function() {
      it('returns an explain object for the provided filter', function(done) {
        client.explain('data-service.test', { a: 1 }, {}, function(error, explanation) {
          assert.equal(null, error);
          expect(explanation).to.be.an('object');
          expect(explanation).to.contain.all.keys(['queryPlanner', 'executionStats']);
          done();
        });
      });
    });
  });

  describe('#deleteOne', function() {
    it('deletes the document from the collection', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.deleteOne('data-service.test', { a: 500 }, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(0);
            done();
          });
        });
      });
    });
  });

  describe('#deleteMany', function() {
    it('deletes the documents from the collection', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.deleteMany('data-service.test', { a: 500 }, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(0);
            done();
          });
        });
      });
    });
  });

  describe('#findOneAndReplace', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when no error occurs', function() {
      var id = new ObjectId();

      it('returns the updated document', function(done) {
        client.insertOne('data-service.test', { _id: id, a: 500 }, {}, function(err) {
          assert.equal(null, err);
          client.findOneAndReplace(
            'data-service.test',
            { _id: id },
            { b: 5 },
            { returnOriginal: false },
            function(error, result) {
              expect(error).to.equal(null);
              expect(result._id).to.deep.equal(id);
              expect(result.b).to.equal(5);
              expect(result.hasOwnProperty('a')).to.equal(false);
              done();
            }
          );
        });
      });
    });

    context('when an error occurs', function() {
      var id = new ObjectId();

      it('returns the updated document', function(done) {
        client.insertOne('data-service.test', { _id: id, a: 500 }, {}, function(err) {
          assert.equal(null, err);
          client.findOneAndReplace(
            'data-service.test',
            { _id: id },
            { '$b': 5 },
            { returnOriginal: false },
            function(error) {
              expect(error.message).to.not.equal(null);
              done();
            }
          );
        });
      });
    });
  });

  describe('#disconnect', function() {
    after(function(done) {
      client.connect(done);
    });

    it('disconnects the database', function(done) {
      client.disconnect();
      client.count('data-service.test', {}, {}, function(error) {
        expect(error.message).to.equal('topology was destroyed');
        done();
      });
    });
  });

  describe('#indexes', function() {
    it('returns the indexes', function(done) {
      client.indexes('data-service.test', function(err, indexes) {
        assert.equal(null, err);
        expect(indexes[0].name).to.equal('_id_');
        done();
      });
    });
  });

  describe('#instance', function() {
    it('returns the instance', function(done) {
      client.instance(function(err, instance) {
        assert.equal(null, err);
        expect(instance._id).to.not.equal(undefined);
        expect(instance.port).to.equal(27018);
        expect(instance.databases[0]._id).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#insertOne', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('inserts the document into the collection', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });
  });

  describe('#insertMany', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('inserts the documents into the collection', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(2);
          done();
        });
      });
    });
  });

  describe('#sample', function() {
    before(function(done) {
      helper.insertTestDocuments(client, function() {
        done();
      });
    });

    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when no filter is provided', function() {
      it('returns a stream of sampled documents', function(done) {
        var seen = 0;
        client.sample('data-service.test')
          .pipe(eventStream.through(function(doc) {
            seen++;
            this.emit('data', doc);
          }, function() {
            this.emit('end');
            expect(seen).to.equal(2);
            done();
          }));
      });
    });
  });

  /**
   * @see https://jira.mongodb.org/browse/INT-1294
   */
  describe('INT-1294: Collection name with `.`', () => {
    var ns = 'mydb.events.periodic';
    it('should return the correct databaseName', () => {
      expect(client._databaseName(ns)).to.equal('mydb');
    });

    it('should return the correct collectionName', () => {
      expect(client._collectionName(ns)).to.equal('events.periodic');
    });
  });

  describe('#updateOne', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('updates the document', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.updateOne('data-service.test', { a: 500 }, { '$set': { a: 600 }}, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 600 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(1);
            done();
          });
        });
      });
    });
  });

  describe('#updateMany', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('updates the documents', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.updateMany('data-service.test', { a: 500 }, { '$set': { a: 600 }}, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 600 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(2);
            done();
          });
        });
      });
    });
  });
});
<commit_msg>Dont make explain test version dependant<commit_after>var helper = require('./helper');

var assert = helper.assert;
var expect = helper.expect;
var eventStream = helper.eventStream;
var Connection = require('mongodb-connection-model');
var ObjectId = require('bson').ObjectId;

var NativeClient = require('../lib/native-client');

describe('NativeClient', function() {
  var client = new NativeClient(helper.connection);

  before(require('mongodb-runner/mocha/before')({
    port: 27018
  }));

  after(require('mongodb-runner/mocha/after')({
    port: 27018
  }));

  before(function(done) {
    client.connect(done);
  });

  describe('#connect', function() {
    context('when an invalid connection was provided', function() {
      var badConnection =
        new Connection({ hostname: '127.0.0.1', port: 27050, ns: 'data-service' });
      var badClient = new NativeClient(badConnection);
      var message = 'MongoDB not running on the provided host and port';
      it('maps the error message', function(done) {
        badClient.connect(function(error) {
          expect(error.message).to.equal(message);
          done();
        });
      });
    });
  });

  describe('#new', function() {
    it('sets the model on the instance', function() {
      expect(client.model).to.equal(helper.connection);
    });
  });

  describe('#find', function() {
    before(function(done) {
      helper.insertTestDocuments(client, function() {
        done();
      });
    });

    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when a filter is provided', function() {
      it('returns a cursor for the matching documents', function(done) {
        client.find('data-service.test', { a: 1 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });

    context('when no filter is provided', function() {
      it('returns a cursor for all documents', function(done) {
        client.find('data-service.test', {}, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(2);
          done();
        });
      });
    });

    context('when options are provided', function() {
      it('returns a cursor for the documents', function(done) {
        client.find('data-service.test', {}, { skip: 1 }, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });
  });

  describe('#collectionDetail', function() {
    it('returns the collection details', function(done) {
      client.collectionDetail('data-service.test', function(err, coll) {
        assert.equal(null, err);
        expect(coll.ns).to.equal('data-service.test');
        expect(coll.index_count).to.equal(1);
        done();
      });
    });
  });

  describe('#collectionNames', function() {
    it('returns the collection names', function(done) {
      client.collectionNames('data-service', function(err, names) {
        assert.equal(null, err);
        expect(names[0]).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#collections', function() {
    it('returns the collections', function(done) {
      client.collections('data-service', function(err, collections) {
        assert.equal(null, err);
        expect(collections[0].name).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#collectionStats', function() {
    it('returns an object with the collection stats', function(done) {
      client.collectionStats('data-service', 'test', function(err, stats) {
        assert.equal(null, err);
        expect(stats.name).to.equal('test');
        done();
      });
    });
  });

  describe('#databaseDetail', function() {
    it('returns the database details', function(done) {
      client.databaseDetail('data-service', function(err, database) {
        assert.equal(null, err);
        expect(database._id).to.equal('data-service');
        expect(database.stats.document_count).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#databaseStats', function() {
    context('when the user is authorized', function() {
      it('returns an object with the db stats', function(done) {
        client.databaseStats('native-service', function(err, stats) {
          assert.equal(null, err);
          expect(stats.document_count).to.equal(0);
          done();
        });
      });
    });

    context('when the user is not authorized', function() {
      it('passes an error to the callback');
    });
  });

  describe('#count', function() {
    context('when a filter is provided', function() {
      it('returns a count for the matching documents', function(done) {
        client.count('data-service.test', { a: 1 }, {}, function(error, count) {
          assert.equal(null, error);
          expect(count).to.equal(0);
          done();
        });
      });
    });
  });

  describe('#explain', function() {
    context('when a filter is provided', function() {
      it('returns an explain object for the provided filter', function(done) {
        client.explain('data-service.test', { a: 1 }, {}, function(error, explanation) {
          assert.equal(null, error);
          expect(explanation).to.be.an('object');
          done();
        });
      });
    });
  });

  describe('#deleteOne', function() {
    it('deletes the document from the collection', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.deleteOne('data-service.test', { a: 500 }, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(0);
            done();
          });
        });
      });
    });
  });

  describe('#deleteMany', function() {
    it('deletes the documents from the collection', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.deleteMany('data-service.test', { a: 500 }, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(0);
            done();
          });
        });
      });
    });
  });

  describe('#findOneAndReplace', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when no error occurs', function() {
      var id = new ObjectId();

      it('returns the updated document', function(done) {
        client.insertOne('data-service.test', { _id: id, a: 500 }, {}, function(err) {
          assert.equal(null, err);
          client.findOneAndReplace(
            'data-service.test',
            { _id: id },
            { b: 5 },
            { returnOriginal: false },
            function(error, result) {
              expect(error).to.equal(null);
              expect(result._id).to.deep.equal(id);
              expect(result.b).to.equal(5);
              expect(result.hasOwnProperty('a')).to.equal(false);
              done();
            }
          );
        });
      });
    });

    context('when an error occurs', function() {
      var id = new ObjectId();

      it('returns the updated document', function(done) {
        client.insertOne('data-service.test', { _id: id, a: 500 }, {}, function(err) {
          assert.equal(null, err);
          client.findOneAndReplace(
            'data-service.test',
            { _id: id },
            { '$b': 5 },
            { returnOriginal: false },
            function(error) {
              expect(error.message).to.not.equal(null);
              done();
            }
          );
        });
      });
    });
  });

  describe('#disconnect', function() {
    after(function(done) {
      client.connect(done);
    });

    it('disconnects the database', function(done) {
      client.disconnect();
      client.count('data-service.test', {}, {}, function(error) {
        expect(error.message).to.equal('topology was destroyed');
        done();
      });
    });
  });

  describe('#indexes', function() {
    it('returns the indexes', function(done) {
      client.indexes('data-service.test', function(err, indexes) {
        assert.equal(null, err);
        expect(indexes[0].name).to.equal('_id_');
        done();
      });
    });
  });

  describe('#instance', function() {
    it('returns the instance', function(done) {
      client.instance(function(err, instance) {
        assert.equal(null, err);
        expect(instance._id).to.not.equal(undefined);
        expect(instance.port).to.equal(27018);
        expect(instance.databases[0]._id).to.not.equal(undefined);
        done();
      });
    });
  });

  describe('#insertOne', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('inserts the document into the collection', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(1);
          done();
        });
      });
    });
  });

  describe('#insertMany', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('inserts the documents into the collection', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.find('data-service.test', { a: 500 }, {}, function(error, docs) {
          assert.equal(null, error);
          expect(docs.length).to.equal(2);
          done();
        });
      });
    });
  });

  describe('#sample', function() {
    before(function(done) {
      helper.insertTestDocuments(client, function() {
        done();
      });
    });

    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    context('when no filter is provided', function() {
      it('returns a stream of sampled documents', function(done) {
        var seen = 0;
        client.sample('data-service.test')
          .pipe(eventStream.through(function(doc) {
            seen++;
            this.emit('data', doc);
          }, function() {
            this.emit('end');
            expect(seen).to.equal(2);
            done();
          }));
      });
    });
  });

  /**
   * @see https://jira.mongodb.org/browse/INT-1294
   */
  describe('INT-1294: Collection name with `.`', () => {
    var ns = 'mydb.events.periodic';
    it('should return the correct databaseName', () => {
      expect(client._databaseName(ns)).to.equal('mydb');
    });

    it('should return the correct collectionName', () => {
      expect(client._collectionName(ns)).to.equal('events.periodic');
    });
  });

  describe('#updateOne', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('updates the document', function(done) {
      client.insertOne('data-service.test', { a: 500 }, {}, function(err) {
        assert.equal(null, err);
        client.updateOne('data-service.test', { a: 500 }, { '$set': { a: 600 }}, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 600 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(1);
            done();
          });
        });
      });
    });
  });

  describe('#updateMany', function() {
    after(function(done) {
      helper.deleteTestDocuments(client, function() {
        done();
      });
    });

    it('updates the documents', function(done) {
      client.insertMany('data-service.test', [{ a: 500 }, { a: 500 }], {}, function(err) {
        assert.equal(null, err);
        client.updateMany('data-service.test', { a: 500 }, { '$set': { a: 600 }}, {}, function(er) {
          assert.equal(null, er);
          client.find('data-service.test', { a: 600 }, {}, function(error, docs) {
            assert.equal(null, error);
            expect(docs.length).to.equal(2);
            done();
          });
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 5:28 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'modules/event'
], function defineWidgetEventManager(BaseEvent) {

    /**
     * Define widget event manager
     * @class WidgetEventManager
     * @constructor
     * @extends BaseEvent
     */
    var WidgetEventManager = function WidgetEventManager() {

        /**
         * Define events
         * @member WidgetEventManager
         * @type {{}}
         */
        this.events = {};
    };

    return WidgetEventManager.extend('WidgetEventManager', {

        /**
         * Define event list
         * @memberOf WidgetEventManager
         * @type {{
         *      initDraggable: string,
         *      enableDraggable: string,
         *      disableDraggable: string,
         *      destroyDraggable: string,
         *      createDraggable: string,
         *      startDraggable: string,
         *      dragDraggable: {eventName: string, params: {buffer: number}},
         *      stopDraggable: string,
         *      updateDraggable: string,
         *      initResizable: string,
         *      enableResizable: string,
         *      disableResizable: string,
         *      destroyResizable: string,
         *      createResizable: string,
         *      startResizable: string,
         *      resizeResizable: {eventName: string, params: {buffer: number}},
         *      stopResizable: string,
         *      updateResizable: string,
         *      loadContent: string,
         *      setContent: string,
         *      adoptDimensions: string,
         *      restoreLayerIndex: string,
         *      setLayerUp: string,
         *      setLayerDown: string,
         *      setAlwaysOnTop: string,
         *      setOnClickUrl: string,
         *      clearThumbnail: string,
         *      saveDom: string
         * }}
         */
        eventList: {

            // Drag events
            initDraggable: 'init.draggable',
            enableDraggable: 'enable.draggable',
            disableDraggable: 'disable.draggable',
            destroyDraggable: 'destroy.draggable',
            createDraggable: 'create.draggable',
            startDraggable: 'start.draggable',
            dragDraggable: {
                eventName: 'drag.draggable',
                params: { buffer: 50 }
            },
            stopDraggable: 'stop.draggable',
            updateDraggable: 'update.draggable',

            // Resize events
            initResizable: 'init.resizable',
            enableResizable: 'enable.resizable',
            disableResizable: 'disable.resizable',
            destroyResizable: 'destroy.resizable',
            createResizable: 'create.resizable',
            startResizable: 'start.resizable',
            resizeResizable: {
                eventName: 'resize.resizable',
                params: { buffer: 50 }
            },
            stopResizable: 'stop.resizable',
            updateResizable: 'update.resizable',

            adoptDimensions: 'adopt.dimensions',

            loadContent: 'load.content',
            setContent: 'set.content',

            setLayerUp: 'set.layer.up',
            setLayerDown: 'set.layer.down',
            restoreLayerIndex: 'restore.layer.index',
            updateLayerIndex: 'update.layer.index',
            setAlwaysOnTop: 'set.always.on.down',

            setOnClickUrl: 'set.on.click.url',
            clearThumbnail: 'clear.thumbnail',

            saveDom: 'save.dom'
        }

    }, BaseEvent.prototype);
});<commit_msg>fix event name<commit_after>/**
 * Created with JetBrains RubyMine.
 * User: teamco
 * Date: 11/17/12
 * Time: 5:28 PM
 * To change this template use File | Settings | File Templates.
 */

define([
    'modules/event'
], function defineWidgetEventManager(BaseEvent) {

    /**
     * Define widget event manager
     * @class WidgetEventManager
     * @constructor
     * @extends BaseEvent
     */
    var WidgetEventManager = function WidgetEventManager() {

        /**
         * Define events
         * @member WidgetEventManager
         * @type {{}}
         */
        this.events = {};
    };

    return WidgetEventManager.extend('WidgetEventManager', {

        /**
         * Define event list
         * @memberOf WidgetEventManager
         * @type {{
         *      initDraggable: string,
         *      enableDraggable: string,
         *      disableDraggable: string,
         *      destroyDraggable: string,
         *      createDraggable: string,
         *      startDraggable: string,
         *      dragDraggable: {eventName: string, params: {buffer: number}},
         *      stopDraggable: string,
         *      updateDraggable: string,
         *      initResizable: string,
         *      enableResizable: string,
         *      disableResizable: string,
         *      destroyResizable: string,
         *      createResizable: string,
         *      startResizable: string,
         *      resizeResizable: {eventName: string, params: {buffer: number}},
         *      stopResizable: string,
         *      updateResizable: string,
         *      loadContent: string,
         *      setContent: string,
         *      adoptDimensions: string,
         *      restoreLayerIndex: string,
         *      setLayerUp: string,
         *      setLayerDown: string,
         *      setAlwaysOnTop: string,
         *      setOnClickUrl: string,
         *      clearThumbnail: string,
         *      saveDom: string
         * }}
         */
        eventList: {

            // Drag events
            initDraggable: 'init.draggable',
            enableDraggable: 'enable.draggable',
            disableDraggable: 'disable.draggable',
            destroyDraggable: 'destroy.draggable',
            createDraggable: 'create.draggable',
            startDraggable: 'start.draggable',
            dragDraggable: {
                eventName: 'drag.draggable',
                params: { buffer: 50 }
            },
            stopDraggable: 'stop.draggable',
            updateDraggable: 'update.draggable',

            // Resize events
            initResizable: 'init.resizable',
            enableResizable: 'enable.resizable',
            disableResizable: 'disable.resizable',
            destroyResizable: 'destroy.resizable',
            createResizable: 'create.resizable',
            startResizable: 'start.resizable',
            resizeResizable: {
                eventName: 'resize.resizable',
                params: { buffer: 50 }
            },
            stopResizable: 'stop.resizable',
            updateResizable: 'update.resizable',

            adoptDimensions: 'adopt.dimensions',

            loadContent: 'load.content',
            setContent: 'set.content',

            setLayerUp: 'set.layer.up',
            setLayerDown: 'set.layer.down',
            restoreLayerIndex: 'restore.layer.index',
            updateLayerIndex: 'update.layer.index',
            setAlwaysOnTop: 'set.always.on.top',

            setOnClickUrl: 'set.on.click.url',
            clearThumbnail: 'clear.thumbnail',

            saveDom: 'save.dom'
        }

    }, BaseEvent.prototype);
});<|endoftext|>