<commit_before>/*jslint forin:true sub:true anon:true, sloppy:true, stupid:true nomen:true, node:true continue:true*/

/*
 * Copyright (c) 2012, Yahoo! Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
var log4js = require("log4js");
var SessionFactory = require("./sessionfactory");
var ReportManager = require("../util/reportmanager");
var FileUtil = require("../util/fileutil");
var WdSession = require("../session/wdsession");
var TestSession = require("../session/testsession");
var ProxyManager = require("../proxy/proxymanager");
var clone = require('clone');
var path = require("path");
var os = require("os");
var fs = require("fs");
var async = require("async");

var sf;
var testExecutor;
var curSessionCount;
var totalSessionCount;
var wdSessions;
var parallelCount;
var tests;
var testQueues;

function TestExecutor(sessionFactory) {

    sf = sessionFactory;

    this.logger = log4js.getLogger("TestExecutor");
    testExecutor = this;
    tests = [];
    wdSessions = [];
    testQueues = [];
    curSessionCount = 0;
    totalSessionCount = 0;
    parallelCount = 0;

}

TestExecutor.prototype.writeReportForDescriptor = function(testSession, callback) {

    var descriptor,
        testSessionsArr,
        currTime,
        reportObj,
        reportManager;

    for (descriptor in sf.descriptorMap) {

        if (descriptor === testSession.descriptorPath) {

            // Store testSessions array for each descriptor in testSessionMap
            if (sf.testSessionMap[descriptor]) {
                testSessionsArr = sf.testSessionMap[descriptor];
            } else {
                testSessionsArr = [];
            }
            testSessionsArr.push(testSession);

            sf.testSessionMap[descriptor] = testSessionsArr;

            sf.descriptorMap[descriptor] = sf.descriptorMap[descriptor] - 1;

            if (sf.descriptorMap[descriptor] === 0) {

                sf.timeReportObj[testSession.descriptorPath].endTime = Date.now(); // TODO Is endTime required ???
                sf.timeReportObj[testSession.descriptorPath].timeTaken =
                    ((sf.timeReportObj[testSession.descriptorPath].endTime - sf.timeReportObj[testSession.descriptorPath].startTime) / 1000).toFixed(2);

                testExecutor.logger.info('Time taken to run descriptor-' + testSession.descriptorPath + ' = ' + sf.timeReportObj[testSession.descriptorPath].timeTaken);

                testExecutor.logger.info('All tests over for descriptor:' + testSession.descriptorPath);
                reportObj = {
                    "reportFolder" : global.reportFolder,
                    "arrTestSessions" : sf.testSessionMap[descriptor],
                    "descriptor" : testSession.descriptorPath,
                    "reuseSession" : sf.reuseSession,
                    "testSuiteName" : sf.testSuiteName,
                    "driver" : sf.driver,
                    "browser" : sf.browser,
                    "group" : sf.args.group,
                    "testName" : sf.args.testName

                };
                reportManager = new ReportManager(reportObj);
                reportManager.totalTimeTaken = sf.timeReportObj[testSession.descriptorPath].timeTaken;
                reportManager.writeReports();

            }

        }
    }
    callback();
};

TestExecutor.prototype.startProxy = function(routerConfigPath, callback) {

    //TODO - move this to index.js
    if (os.type() === "Darwin") {
        global.hostname = "localhost";
    } else {
        global.hostname = os.hostname();
    }

    testExecutor.logger.info('Starting proxy server : ' + routerConfigPath);

    var proxyManager = new ProxyManager(path.resolve(global.workingDirectory, routerConfigPath));

    proxyManager.runRouterProxy(sf.config.minPort, sf.config.maxPort, global.hostname, function(proxyHost) {

        if (proxyHost) {
            if (proxyHost.indexOf("Error") === -1) {
                testExecutor.logger.info("Running Proxy Server at " + proxyHost + ' for :::' + routerConfigPath);
                global.routerMap[routerConfigPath] = proxyHost;
            } else {
                testExecutor.logger.info("Unable to Start Proxy, " + proxyHost);
                testExecutor.logger.info("Running Tests Without Proxy! ");
            }
        } else {
            testExecutor.logger.info("Some error while starting proxy");
            //TODO - What message to show here??
        }

    });

    setTimeout(callback, 500);

};

TestExecutor.prototype.runNextTest = function(testQueue) {

    var testSession,
        testSessionTimeArr = [];

    if (testQueue.curIndex === testQueue.sessions.length) {
        return; // all done with this queue
    }

    testSession = testQueue.sessions[testQueue.curIndex];
    testQueue.curIndex += 1;

    // If first test session is starting for the descriptor, note start time
    if (!sf.timeReportObj[testSession.descriptorPath]) {
        sf.timeReportObj[testSession.descriptorPath] = [];
        sf.timeReportObj[testSession.descriptorPath].startTime = Date.now();
    }

    testSession.runTest(function (error) {

        if (error) {
            var obj = {};
            obj.error = error;
            testSession.driver.reports.addReport(obj);
            testExecutor.logger.debug("Error : " + error);
        }

        testExecutor.logger.trace("Run Test :" + curSessionCount + "==" + totalSessionCount);
        testSession.endTime = Date.now();

        // Write report per descriptor ( if all testsessions for the descriptor ( to which the current test session belongs ) are run )

        if (sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr) {
            testSessionTimeArr = sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr;
        } else {
            testSessionTimeArr = {};
        }

        testSessionTimeArr[testSession.args.testName] = {};

        testSessionTimeArr[testSession.args.testName].timeTaken = ((testSession.endTime - testSession.startTime) / 1000).toFixed(2);
        sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr = testSessionTimeArr;

        testExecutor.logger.info('Time taken to run - ' + testSession.args.testName + ' is::' +
            testSessionTimeArr[testSession.args.testName].timeTaken);

        testExecutor.writeReportForDescriptor(testSession, function() {

            curSessionCount += 1;
            if (curSessionCount === totalSessionCount) {
                testExecutor.logger.trace("Done with all the sessions");
                sf.tearDown(testQueue, wdSessions);
            } else {
                testExecutor.logger.trace("Calling Next Test : " + curSessionCount);
                testExecutor.runNextTest(testQueue);
            }
        });

    });
};

TestExecutor.prototype.runTests = function(testQueues, parallelCount) {

    var i, j;
    for (i = 0; i < testQueues.length; i += 1) {
        // start running as many sessions as we can in parallel as specified
        for (j = 0; j < parallelCount; j += 1) {
            testExecutor.runNextTest(testQueues[i]);
        }
    }

};

TestExecutor.prototype.setupTestQueues = function(callback) {

    var test,
        browsers,
        i,
        j;

    // there may be more than one independent queue that can always run in parallel
    if (wdSessions.length > 0) {
        parallelCount = 1; // when reusing sessions, items in a single queue cannot run in parallel

        // every wd session gets its own queue
        for (i = 0; i < wdSessions.length; i += 1) {
            testQueues[i] = {curIndex: 0, sessions: []};
            for (j = 0; j < tests.length; j += 1) {
                test = clone(tests[j]);

                // If proxy set to true , ignore reuseSession
                if (test.startProxyServer === true) {
                    testQueues[i].sessions.push(new TestSession(sf.config, test));
                } else {
                    testQueues[i].sessions.push(new TestSession(sf.config, test, wdSessions[i]));
                }

            }
            totalSessionCount += tests.length;
        }
    } else {
        // when not reusing sessions, a single queue contains all the items
        // parallelism is controlled by the "parallel" argument passed by the user
        testQueues[0] = {curIndex: 0, sessions: []};
        for (i = 0; i < tests.length; i += 1) {
            browsers = sf.getBrowsers(tests[i]);
            for (j = 0; j < browsers.length; j += 1) {
                test = clone(tests[i]);
                test.browser = browsers[j];
                testQueues[0].sessions.push(new TestSession(sf.config, test));
            }
            totalSessionCount += browsers.length;
        }
    }
    testExecutor.logger.info("Total test sessions: " + totalSessionCount);
    callback();

};

TestExecutor.prototype.getTests = function(callback) {

    var testParams,
        test,
        i;

    if (sf.arrDescriptor) {

        tests = sf.getFactoryTests();

        if (tests.length === 0) {
            sf.tearDown({}, null);
        }
    } else if (sf.tests) {
        for (i = 0; i < sf.tests.length; i += 1) {
            testParams = clone(sf.args);
            testParams.test = sf.tests[i];
            // convert the cmd line test to look like a descriptor test
            test = {
                config : {},
                params : testParams,
                testName : "Default",
                driver : sf.args.driver,
                controller : sf.args.controller,
                browser : sf.browser
            };
            tests.push(test);
        }
    } else {
        // convert the cmd line test to look like a descriptor test
        test = {
            config: {},
            params : sf.args,
            testName : "Default",
            driver : sf.args.driver,
            controller : sf.args.controller,
            browser : sf.browser
        };
        test.params.lib = sf.args.lib;
        tests.push(test);
    }

    callback();

};

TestExecutor.prototype.populateRouterProxyConfigList = function(callback) {

    var i,
        proxyConfig;

    // Get how many unique proxy servers we need to start
    for (i = 0; i < tests.length; i += 1) {

        if (tests[i].startProxyServer === false) {
            continue;
        }

        // If test has routerProxyConfig
        if (tests[i].routerProxyConfig) {

            proxyConfig = tests[i].routerProxyConfig;

            if (tests[i].relativePath) {
                proxyConfig = path.resolve(global.workingDirectory, tests[i].relativePath, proxyConfig);
            } else {
                proxyConfig = path.resolve(global.workingDirectory, proxyConfig);
            }

        } else if (sf.args.routerProxyConfig) { // If routerProxyConfig is passed as an argument
            proxyConfig = path.resolve(global.workingDirectory, sf.args.routerProxyConfig);
        }

        if (proxyConfig) {

            tests[i].resolvedRouterConfigPath = proxyConfig;
            // Add routerConfig to the list ,if not already added
            if (sf.routerConfigList.indexOf(proxyConfig) === -1) {
                sf.routerConfigList.push(proxyConfig);
            }
        }
    }
    callback();

};

TestExecutor.prototype.setupProxy = function(callback) {

    // If set from command line
    if (sf.args.startProxyServer === true || sf.args.startProxyServer === undefined) {

        testExecutor.populateRouterProxyConfigList(function () {

            if (sf.routerConfigList && sf.routerConfigList.length > 0) {

                testExecutor.logger.info('Number of Proxy servers needed to start:' + sf.routerConfigList.length);

                async.eachSeries(sf.routerConfigList, testExecutor.startProxy, function(err) {

                    if (err) {
                        testExecutor.logger.info('ERROR !! Failed to start proxy servers..');
                    } else {
                        testExecutor.logger.info('Started all proxy servers..Now running tests\n\n');
                    }
                    callback();

                });

            } else {
                callback();
            }
        });

    } else {
        callback();
    }

};

TestExecutor.prototype.startTest = function() {

    testExecutor.getTests(function() {
        parallelCount = parseInt(sf.parallel, 10);
        if (isNaN(parallelCount) || (parallelCount <= 0)) {
            parallelCount = 1;
        }
        testExecutor.setupProxy(function() {
            testExecutor.setupTestQueues(function() {
                testExecutor.runTests(testQueues, parallelCount);
            });
        });

    });

};

//TODO cleanup , move this to a proper class ???
//TestExecutor.prototype.deleteReport = function(descriptorFile, callback) {
//
//
//    var descFile = path.basename(descriptorFile, '.json'),
//        xmlReport = path.resolve(global.reportFolder, 'arrow-report', descFile + "-report.xml"),
//        jsonReport = path.resolve(global.reportFolder, 'arrow-report', descFile + "-report.json"),
//        fileUtil = new FileUtil();
//
//    try {
//
//        fileUtil.deleteFile(xmlReport, function() {
//            fileUtil.deleteFile(jsonReport, function() {
//                callback();
//            });
//        });
//
//    } catch (e) {
//        console.log(e);
//        callback();
//    }
//};

//TestExecutor.prototype.cleanupReports = function(callback) {
//
//    if (sf.arrDescriptor) {
//
//        async.eachSeries(sf.arrDescriptor, testExecutor.deleteReport, function(err) {
//            if (err) {
//                testExecutor.logger.info('ERROR !! Failed to cleanup reports..');
//            } else {
//                testExecutor.logger.info('Cleaned up all reports\n\n');
//            }
//            callback();
//
//        });
//
//    } else {
//        callback();
//    }
//
//};

TestExecutor.prototype.executeTests = function () {
    var hub;

    // get all wd sessions if applicable (based on reuseSession flag)
    if (sf.reuseSession) {
        hub = new WdSession(sf.config);
        hub.getSessions(sf, function (error, sf, arrSessions) {
            if (error) {
                // logger.error('No sessions found..'); TODO  search for this msg
                process.exit(1);
            }
            wdSessions = arrSessions;
            testExecutor.startTest();
        });
    } else {
        testExecutor.startTest();
    }

};

module.exports = TestExecutor;<commit_msg>Cleanup<commit_after>/*jslint forin:true sub:true anon:true, sloppy:true, stupid:true nomen:true, node:true continue:true*/

/*
 * Copyright (c) 2012, Yahoo! Inc. All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */
var log4js = require("log4js");
var SessionFactory = require("./sessionfactory");
var ReportManager = require("../util/reportmanager");
var FileUtil = require("../util/fileutil");
var WdSession = require("../session/wdsession");
var TestSession = require("../session/testsession");
var ProxyManager = require("../proxy/proxymanager");
var clone = require('clone');
var path = require("path");
var os = require("os");
var fs = require("fs");
var async = require("async");

var sf;
var testExecutor;
var curSessionCount;
var totalSessionCount;
var wdSessions;
var parallelCount;
var tests;
var testQueues;

function TestExecutor(sessionFactory) {

    sf = sessionFactory;

    this.logger = log4js.getLogger("TestExecutor");
    testExecutor = this;
    tests = [];
    wdSessions = [];
    testQueues = [];
    curSessionCount = 0;
    totalSessionCount = 0;
    parallelCount = 0;

}

TestExecutor.prototype.writeReportForDescriptor = function(testSession, callback) {

    var descriptor,
        testSessionsArr,
        currTime,
        reportObj,
        reportManager;

    for (descriptor in sf.descriptorMap) {

        if (descriptor === testSession.descriptorPath) {

            // Store testSessions array for each descriptor in testSessionMap
            if (sf.testSessionMap[descriptor]) {
                testSessionsArr = sf.testSessionMap[descriptor];
            } else {
                testSessionsArr = [];
            }
            testSessionsArr.push(testSession);

            sf.testSessionMap[descriptor] = testSessionsArr;

            sf.descriptorMap[descriptor] = sf.descriptorMap[descriptor] - 1;

            if (sf.descriptorMap[descriptor] === 0) {

                sf.timeReportObj[testSession.descriptorPath].endTime = Date.now(); // TODO Is endTime required ???
                sf.timeReportObj[testSession.descriptorPath].timeTaken =
                    ((sf.timeReportObj[testSession.descriptorPath].endTime - sf.timeReportObj[testSession.descriptorPath].startTime) / 1000).toFixed(2);

                testExecutor.logger.info('Time taken to run descriptor-' + testSession.descriptorPath + ' = ' + sf.timeReportObj[testSession.descriptorPath].timeTaken);

                testExecutor.logger.info('All tests over for descriptor:' + testSession.descriptorPath);
                reportObj = {
                    "reportFolder" : global.reportFolder,
                    "arrTestSessions" : sf.testSessionMap[descriptor],
                    "descriptor" : testSession.descriptorPath,
                    "reuseSession" : sf.reuseSession,
                    "testSuiteName" : sf.testSuiteName,
                    "driver" : sf.driver,
                    "browser" : sf.browser,
                    "group" : sf.args.group,
                    "testName" : sf.args.testName

                };
                reportManager = new ReportManager(reportObj);
                reportManager.totalTimeTaken = sf.timeReportObj[testSession.descriptorPath].timeTaken;
                reportManager.writeReports();

            }

        }
    }
    callback();
};

TestExecutor.prototype.startProxy = function(routerConfigPath, callback) {

    //TODO - move this to index.js
    if (os.type() === "Darwin") {
        global.hostname = "localhost";
    } else {
        global.hostname = os.hostname();
    }

    testExecutor.logger.info('Starting proxy server : ' + routerConfigPath);

    var proxyManager = new ProxyManager(path.resolve(global.workingDirectory, routerConfigPath));

    proxyManager.runRouterProxy(sf.config.minPort, sf.config.maxPort, global.hostname, function(proxyHost) {

        if (proxyHost) {
            if (proxyHost.indexOf("Error") === -1) {
                testExecutor.logger.info("Running Proxy Server at " + proxyHost + ' for :::' + routerConfigPath);
                global.routerMap[routerConfigPath] = proxyHost;
            } else {
                testExecutor.logger.info("Unable to Start Proxy, " + proxyHost);
                testExecutor.logger.info("Running Tests Without Proxy! ");
            }
        } else {
            testExecutor.logger.info("Some error while starting proxy");
            //TODO - What message to show here??
        }

    });

    setTimeout(callback, 500);

};

TestExecutor.prototype.runNextTest = function(testQueue) {

    var testSession,
        testSessionTimeArr = [];

    if (testQueue.curIndex === testQueue.sessions.length) {
        return; // all done with this queue
    }

    testSession = testQueue.sessions[testQueue.curIndex];
    testQueue.curIndex += 1;

    // If first test session is starting for the descriptor, note start time
    if (!sf.timeReportObj[testSession.descriptorPath]) {
        sf.timeReportObj[testSession.descriptorPath] = [];
        sf.timeReportObj[testSession.descriptorPath].startTime = Date.now();
    }

    testSession.runTest(function (error) {

        if (error) {
            var obj = {};
            obj.error = error;
            testSession.driver.reports.addReport(obj);
            testExecutor.logger.debug("Error : " + error);
        }

        testExecutor.logger.trace("Run Test :" + curSessionCount + "==" + totalSessionCount);
        testSession.endTime = Date.now();

        // Write report per descriptor ( if all testsessions for the descriptor ( to which the current test session belongs ) are run )

        if (sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr) {
            testSessionTimeArr = sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr;
        } else {
            testSessionTimeArr = {};
        }

        testSessionTimeArr[testSession.args.testName] = {};

        testSessionTimeArr[testSession.args.testName].timeTaken = ((testSession.endTime - testSession.startTime) / 1000).toFixed(2);
        sf.timeReportObj[testSession.descriptorPath].testSessionTimeArr = testSessionTimeArr;

        testExecutor.logger.info('Time taken to run - ' + testSession.args.testName + ' is::' +
            testSessionTimeArr[testSession.args.testName].timeTaken);

        testExecutor.writeReportForDescriptor(testSession, function() {

            curSessionCount += 1;
            if (curSessionCount === totalSessionCount) {
                testExecutor.logger.trace("Done with all the sessions");
                sf.tearDown(testQueue, wdSessions);
            } else {
                testExecutor.logger.trace("Calling Next Test : " + curSessionCount);
                testExecutor.runNextTest(testQueue);
            }
        });

    });
};

TestExecutor.prototype.runTests = function(testQueues, parallelCount) {

    var i, j;
    for (i = 0; i < testQueues.length; i += 1) {
        // start running as many sessions as we can in parallel as specified
        for (j = 0; j < parallelCount; j += 1) {
            testExecutor.runNextTest(testQueues[i]);
        }
    }

};

TestExecutor.prototype.setupTestQueues = function(callback) {

    var test,
        browsers,
        i,
        j;

    // there may be more than one independent queue that can always run in parallel
    if (wdSessions.length > 0) {
        parallelCount = 1; // when reusing sessions, items in a single queue cannot run in parallel

        // every wd session gets its own queue
        for (i = 0; i < wdSessions.length; i += 1) {
            testQueues[i] = {curIndex: 0, sessions: []};
            for (j = 0; j < tests.length; j += 1) {
                test = clone(tests[j]);

                // If proxy set to true , ignore reuseSession
                if (test.startProxyServer === true) {
                    testQueues[i].sessions.push(new TestSession(sf.config, test));
                } else {
                    testQueues[i].sessions.push(new TestSession(sf.config, test, wdSessions[i]));
                }

            }
            totalSessionCount += tests.length;
        }
    } else {
        // when not reusing sessions, a single queue contains all the items
        // parallelism is controlled by the "parallel" argument passed by the user
        testQueues[0] = {curIndex: 0, sessions: []};
        for (i = 0; i < tests.length; i += 1) {
            browsers = sf.getBrowsers(tests[i]);
            for (j = 0; j < browsers.length; j += 1) {
                test = clone(tests[i]);
                test.browser = browsers[j];
                testQueues[0].sessions.push(new TestSession(sf.config, test));
            }
            totalSessionCount += browsers.length;
        }
    }
    testExecutor.logger.info("Total test sessions: " + totalSessionCount);
    callback();

};

TestExecutor.prototype.getTests = function(callback) {

    var testParams,
        test,
        i;

    if (sf.arrDescriptor) {

        tests = sf.getFactoryTests();

        if (tests.length === 0) {
            sf.tearDown({}, null);
        }
    } else if (sf.tests) {
        for (i = 0; i < sf.tests.length; i += 1) {
            testParams = clone(sf.args);
            testParams.test = sf.tests[i];
            // convert the cmd line test to look like a descriptor test
            test = {
                config : {},
                params : testParams,
                testName : "Default",
                driver : sf.args.driver,
                controller : sf.args.controller,
                browser : sf.browser
            };
            tests.push(test);
        }
    } else {
        // convert the cmd line test to look like a descriptor test
        test = {
            config: {},
            params : sf.args,
            testName : "Default",
            driver : sf.args.driver,
            controller : sf.args.controller,
            browser : sf.browser
        };
        test.params.lib = sf.args.lib;
        tests.push(test);
    }

    callback();

};

TestExecutor.prototype.populateRouterProxyConfigList = function(callback) {

    var i,
        proxyConfig;

    // Get how many unique proxy servers we need to start
    for (i = 0; i < tests.length; i += 1) {

        if (tests[i].startProxyServer === false) {
            continue;
        }

        // If test has routerProxyConfig
        if (tests[i].routerProxyConfig) {

            proxyConfig = tests[i].routerProxyConfig;

            if (tests[i].relativePath) {
                proxyConfig = path.resolve(global.workingDirectory, tests[i].relativePath, proxyConfig);
            } else {
                proxyConfig = path.resolve(global.workingDirectory, proxyConfig);
            }

        } else if (sf.args.routerProxyConfig) { // If routerProxyConfig is passed as an argument
            proxyConfig = path.resolve(global.workingDirectory, sf.args.routerProxyConfig);
        }

        if (proxyConfig) {

            tests[i].resolvedRouterConfigPath = proxyConfig;
            // Add routerConfig to the list ,if not already added
            if (sf.routerConfigList.indexOf(proxyConfig) === -1) {
                sf.routerConfigList.push(proxyConfig);
            }
        }
    }
    callback();

};

TestExecutor.prototype.setupProxy = function(callback) {

    // If set from command line
    if (sf.args.startProxyServer === true || sf.args.startProxyServer === undefined) {

        testExecutor.populateRouterProxyConfigList(function () {

            if (sf.routerConfigList && sf.routerConfigList.length > 0) {

                testExecutor.logger.info('Number of Proxy servers needed to start:' + sf.routerConfigList.length);

                async.eachSeries(sf.routerConfigList, testExecutor.startProxy, function(err) {

                    if (err) {
                        testExecutor.logger.info('ERROR !! Failed to start proxy servers..');
                    } else {
                        testExecutor.logger.info('Started all proxy servers..Now running tests\n\n');
                    }
                    callback();

                });

            } else {
                callback();
            }
        });

    } else {
        callback();
    }

};

TestExecutor.prototype.startTest = function() {

    testExecutor.getTests(function() {
        parallelCount = parseInt(sf.parallel, 10);
        if (isNaN(parallelCount) || (parallelCount <= 0)) {
            parallelCount = 1;
        }
        testExecutor.setupProxy(function() {
            testExecutor.setupTestQueues(function() {
                testExecutor.runTests(testQueues, parallelCount);
            });
        });

    });

};

TestExecutor.prototype.executeTests = function () {
    var hub;

    // get all wd sessions if applicable (based on reuseSession flag)
    if (sf.reuseSession) {
        hub = new WdSession(sf.config);
        hub.getSessions(sf, function (error, sf, arrSessions) {
            if (error) {
                // logger.error('No sessions found..'); TODO  search for this msg
                process.exit(1);
            }
            wdSessions = arrSessions;
            testExecutor.startTest();
        });
    } else {
        testExecutor.startTest();
    }

};

module.exports = TestExecutor;<|endoftext|>


<commit_before>EPUBJS.Render.Iframe = function() {
	this.iframe = null;
	this.document = null;
	this.window = null;
	this.docEl = null;
	this.bodyEl = null;

	this.leftPos = 0;
	this.pageWidth = 0;
};

//-- Build up any html needed
EPUBJS.Render.Iframe.prototype.create = function(){
	this.iframe = document.createElement('iframe');
	this.iframe.id = "epubjs-iframe:" + EPUBJS.core.uuid();
	this.iframe.scrolling = "no";
	this.iframe.seamless = "seamless";
	// Back up if seamless isn't supported
	this.iframe.style.border = "none";

	this.iframe.addEventListener("load", this.loaded.bind(this), false);
	return this.iframe;
};

/**
* Sets the source of the iframe with the given URL string
* Takes:  URL string
* Returns: promise with document element
*/
EPUBJS.Render.Iframe.prototype.load = function(url){
	var render = this,
			deferred = new RSVP.defer();

	this.iframe.src = url;

	// Reset the scroll position
	render.leftPos = 0;

	if(this.window) {
		this.unload();
	}

	this.iframe.onload = function(e) {
		render.document = render.iframe.contentDocument;
		render.docEl = render.document.documentElement;
		render.headEl = render.document.head;
		render.bodyEl = render.document.body;
		render.window = render.iframe.contentWindow;

		render.window.addEventListener("resize", render.resized.bind(render), false);

		//-- Clear Margins
		if(render.bodyEl) {
			render.bodyEl.style.margin = "0";
		}

		deferred.resolve(render.docEl);
	};

	this.iframe.onerror = function(e) {
		//console.error("Error Loading Contents", e);
		deferred.reject({
				message : "Error Loading Contents: " + e,
				stack : new Error().stack
			});
	};
	return deferred.promise;
};

EPUBJS.Render.Iframe.prototype.loaded = function(v){
	var url = this.iframe.contentWindow.location.href;
	this.trigger("render:loaded", url);
};

// Resize the iframe to the given width and height
EPUBJS.Render.Iframe.prototype.resize = function(width, height){
	var iframeBox;

	if(!this.iframe) return;

	this.iframe.height = height;

	if(!isNaN(width) && width % 2 !== 0){
		width += 1; //-- Prevent cutting off edges of text in columns
	}

	this.iframe.width = width;
	// Get the fractional height and width of the iframe
	// Default to orginal if bounding rect is 0
	this.width = this.iframe.getBoundingClientRect().width || width;
	this.height = this.iframe.getBoundingClientRect().height || height;
};

EPUBJS.Render.Iframe.prototype.resized = function(e){
	// Get the fractional height and width of the iframe
	this.width = this.iframe.getBoundingClientRect().width;
	this.height = this.iframe.getBoundingClientRect().height;
};

EPUBJS.Render.Iframe.prototype.totalWidth = function(){
	return this.docEl.scrollWidth;
};

EPUBJS.Render.Iframe.prototype.totalHeight = function(){
	return this.docEl.scrollHeight;
};

EPUBJS.Render.Iframe.prototype.setPageDimensions = function(pageWidth, pageHeight){
	this.pageWidth = pageWidth;
	this.pageHeight = pageHeight;
	//-- Add a page to the width of the document to account an for odd number of pages
	// this.docEl.style.width = this.docEl.scrollWidth + pageWidth + "px";
};

EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
	// this.bodyEl.style.marginLeft = -leftPos + "px";
	// this.docEl.style.marginLeft = -leftPos + "px";
	// this.docEl.style[EPUBJS.Render.Iframe.transform] = 'translate('+ (-leftPos) + 'px, 0)';
	this.document.defaultView.scrollTo(leftPos, 0);
};

EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
	if(prefixed) {
		style = EPUBJS.core.prefixed(style);
	}

	if(this.bodyEl) this.bodyEl.style[style] = val;
};

EPUBJS.Render.Iframe.prototype.removeStyle = function(style){

	if(this.bodyEl) this.bodyEl.style[style] = '';

};

EPUBJS.Render.Iframe.prototype.addHeadTag = function(tag, attrs) {
	var tagEl = document.createElement(tag);

	for(var attr in attrs) {
		tagEl[attr] = attrs[attr];
	}

	if(this.headEl) this.headEl.appendChild(tagEl);
};

EPUBJS.Render.Iframe.prototype.page = function(pg){
	this.leftPos = this.pageWidth * (pg-1); //-- pages start at 1
	this.setLeft(this.leftPos);
};

//-- Show the page containing an Element
EPUBJS.Render.Iframe.prototype.getPageNumberByElement = function(el){
	var left, pg;
	if(!el) return;

	left = this.leftPos + el.getBoundingClientRect().left; //-- Calculate left offset compaired to scrolled position

	pg = Math.floor(left / this.pageWidth) + 1; //-- pages start at 1

	return pg;
};

//-- Show the page containing an Element
EPUBJS.Render.Iframe.prototype.getPageNumberByRect = function(boundingClientRect){
	var left, pg;

	left = this.leftPos + boundingClientRect.left; //-- Calculate left offset compaired to scrolled position
	pg = Math.floor(left / this.pageWidth) + 1; //-- pages start at 1

	return pg;
};

// Return the root element of the content
EPUBJS.Render.Iframe.prototype.getBaseElement = function(){
	return this.bodyEl;
};

// Checks if an element is on the screen
EPUBJS.Render.Iframe.prototype.isElementVisible = function(el){
	var rect;
	var left;

	if(el && typeof el.getBoundingClientRect === 'function'){
		rect = el.getBoundingClientRect();
		left = rect.left; //+ rect.width;
		if( rect.width !== 0 &&
				rect.height !== 0 && // Element not visible
				left >= 0 &&
				left < this.pageWidth ) {
			return true;
		}
	}

	return false;
};

EPUBJS.Render.Iframe.prototype.scroll = function(bool){
	if(bool) {
		this.iframe.scrolling = "yes";
	} else {
		this.iframe.scrolling = "no";
	}
};

// Cleanup event listeners
EPUBJS.Render.Iframe.prototype.unload = function(){
	this.window.removeEventListener("resize", this.resized);
};

//-- Enable binding events to Render
RSVP.EventTarget.mixin(EPUBJS.Render.Iframe.prototype);<commit_msg>Replace contentWindow location will not interefere on parent window history<commit_after>EPUBJS.Render.Iframe = function() {
	this.iframe = null;
	this.document = null;
	this.window = null;
	this.docEl = null;
	this.bodyEl = null;

	this.leftPos = 0;
	this.pageWidth = 0;
};

//-- Build up any html needed
EPUBJS.Render.Iframe.prototype.create = function(){
	this.iframe = document.createElement('iframe');
	this.iframe.id = "epubjs-iframe:" + EPUBJS.core.uuid();
	this.iframe.scrolling = "no";
	this.iframe.seamless = "seamless";
	// Back up if seamless isn't supported
	this.iframe.style.border = "none";

	this.iframe.addEventListener("load", this.loaded.bind(this), false);
	return this.iframe;
};

/**
* Sets the source of the iframe with the given URL string
* Takes:  URL string
* Returns: promise with document element
*/
EPUBJS.Render.Iframe.prototype.load = function(url){
	var render = this,
			deferred = new RSVP.defer();

	this.iframe.contentWindow.location.replace(url);

	// Reset the scroll position
	render.leftPos = 0;

	if(this.window) {
		this.unload();
	}

	this.iframe.onload = function(e) {
		render.document = render.iframe.contentDocument;
		render.docEl = render.document.documentElement;
		render.headEl = render.document.head;
		render.bodyEl = render.document.body;
		render.window = render.iframe.contentWindow;

		render.window.addEventListener("resize", render.resized.bind(render), false);

		//-- Clear Margins
		if(render.bodyEl) {
			render.bodyEl.style.margin = "0";
		}

		deferred.resolve(render.docEl);
	};

	this.iframe.onerror = function(e) {
		//console.error("Error Loading Contents", e);
		deferred.reject({
				message : "Error Loading Contents: " + e,
				stack : new Error().stack
			});
	};
	return deferred.promise;
};

EPUBJS.Render.Iframe.prototype.loaded = function(v){
	var url = this.iframe.contentWindow.location.href;
	this.trigger("render:loaded", url);
};

// Resize the iframe to the given width and height
EPUBJS.Render.Iframe.prototype.resize = function(width, height){
	var iframeBox;

	if(!this.iframe) return;

	this.iframe.height = height;

	if(!isNaN(width) && width % 2 !== 0){
		width += 1; //-- Prevent cutting off edges of text in columns
	}

	this.iframe.width = width;
	// Get the fractional height and width of the iframe
	// Default to orginal if bounding rect is 0
	this.width = this.iframe.getBoundingClientRect().width || width;
	this.height = this.iframe.getBoundingClientRect().height || height;
};

EPUBJS.Render.Iframe.prototype.resized = function(e){
	// Get the fractional height and width of the iframe
	this.width = this.iframe.getBoundingClientRect().width;
	this.height = this.iframe.getBoundingClientRect().height;
};

EPUBJS.Render.Iframe.prototype.totalWidth = function(){
	return this.docEl.scrollWidth;
};

EPUBJS.Render.Iframe.prototype.totalHeight = function(){
	return this.docEl.scrollHeight;
};

EPUBJS.Render.Iframe.prototype.setPageDimensions = function(pageWidth, pageHeight){
	this.pageWidth = pageWidth;
	this.pageHeight = pageHeight;
	//-- Add a page to the width of the document to account an for odd number of pages
	// this.docEl.style.width = this.docEl.scrollWidth + pageWidth + "px";
};

EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
	// this.bodyEl.style.marginLeft = -leftPos + "px";
	// this.docEl.style.marginLeft = -leftPos + "px";
	// this.docEl.style[EPUBJS.Render.Iframe.transform] = 'translate('+ (-leftPos) + 'px, 0)';
	this.document.defaultView.scrollTo(leftPos, 0);
};

EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
	if(prefixed) {
		style = EPUBJS.core.prefixed(style);
	}

	if(this.bodyEl) this.bodyEl.style[style] = val;
};

EPUBJS.Render.Iframe.prototype.removeStyle = function(style){

	if(this.bodyEl) this.bodyEl.style[style] = '';

};

EPUBJS.Render.Iframe.prototype.addHeadTag = function(tag, attrs) {
	var tagEl = document.createElement(tag);

	for(var attr in attrs) {
		tagEl[attr] = attrs[attr];
	}

	if(this.headEl) this.headEl.appendChild(tagEl);
};

EPUBJS.Render.Iframe.prototype.page = function(pg){
	this.leftPos = this.pageWidth * (pg-1); //-- pages start at 1
	this.setLeft(this.leftPos);
};

//-- Show the page containing an Element
EPUBJS.Render.Iframe.prototype.getPageNumberByElement = function(el){
	var left, pg;
	if(!el) return;

	left = this.leftPos + el.getBoundingClientRect().left; //-- Calculate left offset compaired to scrolled position

	pg = Math.floor(left / this.pageWidth) + 1; //-- pages start at 1

	return pg;
};

//-- Show the page containing an Element
EPUBJS.Render.Iframe.prototype.getPageNumberByRect = function(boundingClientRect){
	var left, pg;

	left = this.leftPos + boundingClientRect.left; //-- Calculate left offset compaired to scrolled position
	pg = Math.floor(left / this.pageWidth) + 1; //-- pages start at 1

	return pg;
};

// Return the root element of the content
EPUBJS.Render.Iframe.prototype.getBaseElement = function(){
	return this.bodyEl;
};

// Checks if an element is on the screen
EPUBJS.Render.Iframe.prototype.isElementVisible = function(el){
	var rect;
	var left;

	if(el && typeof el.getBoundingClientRect === 'function'){
		rect = el.getBoundingClientRect();
		left = rect.left; //+ rect.width;
		if( rect.width !== 0 &&
				rect.height !== 0 && // Element not visible
				left >= 0 &&
				left < this.pageWidth ) {
			return true;
		}
	}

	return false;
};

EPUBJS.Render.Iframe.prototype.scroll = function(bool){
	if(bool) {
		this.iframe.scrolling = "yes";
	} else {
		this.iframe.scrolling = "no";
	}
};

// Cleanup event listeners
EPUBJS.Render.Iframe.prototype.unload = function(){
	this.window.removeEventListener("resize", this.resized);
};

//-- Enable binding events to Render
RSVP.EventTarget.mixin(EPUBJS.Render.Iframe.prototype);<|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;

var Generator = require('../index');

var data = [
  "Lorem ipsum dolor sit amet",
  "Lorem ipsum duplicate start words",
  "Consectetur adipiscing elit",
  "Quisque tempor, erat vel lacinia imperdiet",
  "Justo nisi fringilla dui",
  "Egestas bibendum eros nisi ut lacus",
  "fringilla dui avait annoncé une rupture avec le erat vel: il n'en est rien…",
  "Fusce tincidunt tempor, erat vel lacinia vel ex pharetra pretium lacinia imperdiet"
];

describe('Options parser', function() {
  it('should have the right values', function() {
    var generator = new Generator([], {});
    expect(generator.options.stateSize).to.equal(2);
  });
});

describe('Generator builder', function() {

  var generator;
  before(function() {
    generator = new Generator(data)
  });

  describe('StartWords array', function() {
    it('should contain the right values', function() {
      var start = generator.startWords;
      expect(start).to.contain('Lorem ipsum');
      expect(start).to.contain('Consectetur adipiscing');
      expect(start).to.contain('Quisque tempor,');
      expect(start).to.contain('Justo nisi');
      expect(start).to.contain('Egestas bibendum');
    });

    it('should have the right length', function() {
      expect(generator.startWords).to.have.lengthOf(7);
    });
  });

  describe('EndWords array', function() {
    it('should have the right length', function() {
      expect(generator.endWords).to.have.lengthOf(7);
    });

    it('should contain the right values', function() {
      var end = generator.endWords;
      expect(end).to.contain('sit amet');
      expect(end).to.contain('start words');
      expect(end).to.contain('adipiscing elit');
      expect(end).to.contain('fringilla dui');
      expect(end).to.contain('ut lacus');
      expect(end).to.contain('est rien…');
    });
  });

  describe('Corpus', function() {
    it('should have the right values for the right keys', function() {
      var corpus = generator.corpus;
      expect(corpus['Lorem ipsum']).to.contain('dolor sit');
      expect(corpus['Lorem ipsum']).to.contain('duplicate start');
      expect(corpus['tempor, erat']).to.contain('vel lacinia');
    });
  });
});

describe('Sentence generator', function() {

  var generator;
  before(function() {
    generator = new Generator(data)
  });

  it('should output a sentence', function() {
    let result = generator.generateSentence({
      stateSize: 1
    });
    expect(result).to.exist;
  });

  it('should throw an error when a sentence cannot be built', function() {
    for (let i = 0; i < 10; i++) {
      expect(() => {
        generator.generateSentence({
          stateSize: 3
        }).to.throw(Error);
      })
    }
  });

  it('should end with a value from endWords', function() {
    let result = generator.generateSentence().string;
    let arr = result.split(' ');
    let end = arr.slice(arr.length - 2, arr.length);

    for (let i = 0; i < 10; i++) {
      expect(generator.endWords).to.contain(end.join(' '));
    }
  });

  it('should reject all sentences', function() {
    let options = {minWords:5};
    for (let i = 0; i < 10; i++) {
      expect(() => {
        generator.generateSentence(options, result => result.split(' ').length < 5)
      }).to.throw(Error);
    }
  });

  it('should accept all sentences', function() {
    for (let i = 0; i < 10; i++) {
      expect(() => {
        generator.generateSentence({}, result => true)
      }).to.exist;
    }
  });

  it('should reject if the options values are not met', function() {
    expect(() => {
      generator.generateSentence({maxLength:1, minWords:0, maxWords:0})
    }).to.throw(Error);

    expect(() => {
      generator.generateSentence({minWords:100})
    }).to.throw(Error);

    expect(() => {
      generator.generateSentence({minScore: 20})
    }).to.throw(Error);

    expect(() => {
      generator.generateSentence({maxWords: 1, minWords:0})
    }).to.throw(Error);

  });

});
<commit_msg>Better and faster tests<commit_after>'use strict';

var expect = require('chai').expect;

var Generator = require('../index');

var data = [
  "Lorem ipsum dolor sit amet",
  "Lorem ipsum duplicate start words",
  "Consectetur adipiscing elit",
  "Quisque tempor, erat vel lacinia imperdiet",
  "Justo nisi fringilla dui",
  "Egestas bibendum eros nisi ut lacus",
  "fringilla dui avait annoncé une rupture avec le erat vel: il n'en est rien…",
  "Fusce tincidunt tempor, erat vel lacinia vel ex pharetra pretium lacinia imperdiet"
];

describe('Options parser', function() {
  it('should have the right values', function() {
    var generator = new Generator([], {});
    expect(generator.options.stateSize).to.equal(2);
  });
});

describe('Generator builder', function() {

  var generator;
  before(function() {
    generator = new Generator(data)
  });

  describe('StartWords array', function() {
    it('should contain the right values', function() {
      var start = generator.startWords;
      expect(start).to.contain('Lorem ipsum');
      expect(start).to.contain('Consectetur adipiscing');
      expect(start).to.contain('Quisque tempor,');
      expect(start).to.contain('Justo nisi');
      expect(start).to.contain('Egestas bibendum');
    });

    it('should have the right length', function() {
      expect(generator.startWords).to.have.lengthOf(7);
    });
  });

  describe('EndWords array', function() {
    it('should have the right length', function() {
      expect(generator.endWords).to.have.lengthOf(7);
    });

    it('should contain the right values', function() {
      var end = generator.endWords;
      expect(end).to.contain('sit amet');
      expect(end).to.contain('start words');
      expect(end).to.contain('adipiscing elit');
      expect(end).to.contain('fringilla dui');
      expect(end).to.contain('ut lacus');
      expect(end).to.contain('est rien…');
    });
  });

  describe('Corpus', function() {
    it('should have the right values for the right keys', function() {
      var corpus = generator.corpus;
      expect(corpus['Lorem ipsum']).to.contain('dolor sit');
      expect(corpus['Lorem ipsum']).to.contain('duplicate start');
      expect(corpus['tempor, erat']).to.contain('vel lacinia');
    });
  });
});

describe('Sentence generator', function() {

  var generator;
  before(function() {
    generator = new Generator(data)
  });

  it('should output a sentence', function() {
    let result = generator.generateSentence({
      stateSize: 1
    });
    expect(result).to.exist;
  });

  it('should throw an error when a sentence cannot be built', function() {
    for (let i = 0; i < 10; i++) {
      expect(() => {
        generator.generateSentence({
          stateSize: 3
        }).to.throw(Error);
      })
    }
  });

  it('should end with a value from endWords', function() {
    let result = generator.generateSentence().string;
    let arr = result.split(' ');
    let end = arr.slice(arr.length - 2, arr.length);

    for (let i = 0; i < 10; i++) {
      expect(generator.endWords).to.contain(end.join(' '));
    }
  });

  it('should reject the sentence', function() {
    let options = {minWords: 5, maxTries: 10};
    expect(() => {
      generator.generateSentence(options, result => result.split(' ').length < 5)
    }).to.throw(Error);
  });

  it('should accept the sentence', function() {
    expect(() => {
      generator.generateSentence({}, result => true)
    }).to.exist;
  });

  it('should reject because maxLength is unattainable', function() {
    expect(() => {
      generator.generateSentence({maxTries: 10, maxLength: 1, minWords: 0, maxWords: 0})
    }).to.throw(Error);
  });

  it('should reject because minWords is unattainable', function() {
    expect(() => {
      generator.generateSentence({maxTries: 10, minWords: 100})
    }).to.throw(Error);
  });

  it('should reject because minScore is unattainable', function() {
    expect(() => {
      generator.generateSentence({maxTries: 10, minScore: 20})
    }).to.throw(Error);
  });

  it('should reject because maxWords is unattainable', function() {
    expect(() => {
      generator.generateSentence({maxTries: 10, maxWords: 1, minWords: 0})
    }).to.throw(Error);
  });

});
<|endoftext|>


<commit_before>angular.module('enki.user',[])

.controller('userController', function ($scope, $window, $location, User, $state, UserResources, $ionicHistory) {
  // console.log("ITEM: ", $window.localStorage.getItem('com.fickle'));
  $scope.likedResources = [];
  $scope.dislikedResources = [];
  var user = JSON.parse(window.localStorage.getItem('com.fickle'));
  var username = user.username;

  User.getUser($window.localStorage.getItem('com.fickle'))
  .then(function (user) {
  });

	User.getLikes($window.localStorage.getItem('com.fickle')).then(function(data) {
	 $scope.likedResources = data;
   console.log("LIKES: ", data);
	});

  User.getDislike($window.localStorage.getItem('com.fickle')).then(function(data){
    $scope.dislikedResources = data;
  });

  $scope.logout = function() {
    window.localStorage.setItem('com.fickle', null);
    $ionicHistory.clearCache();
    $ionicHistory.clearHistory();
    $state.go('login');
  };

  $scope.onItemDelete = function(resource) {
    console.log("Attempted to Delete");
    var userpref = {
      'username' : username,
      'episodeTitle' : resource[0].title,
      'showName' : resource[1].name
    };
    console.log(userpref);
    UserResources.removeRelationship(userpref)
    .then(function(message){
      console.log("Response Message: ",message);
      if(message === 200){
        console.log("You have removed this like/dislke");
      }
    })
    .catch(function (error) {
      console.error(error);
    });
    $scope.likedResources.splice($scope.likedResources.indexOf(resource), 1);
  };
});
<commit_msg>explore page is now clearing session when logged out<commit_after>angular.module('enki.user',[])

.controller('userController', function ($scope, $window, $location, User, $state, UserResources, $ionicHistory, $ionicLoading) {
  // console.log("ITEM: ", $window.localStorage.getItem('com.fickle'));
  $scope.likedResources = [];
  $scope.dislikedResources = [];
  var user = JSON.parse(window.localStorage.getItem('com.fickle'));
  var username = user.username;

  User.getUser($window.localStorage.getItem('com.fickle'))
  .then(function (user) {
  });

	User.getLikes($window.localStorage.getItem('com.fickle')).then(function(data) {
	 $scope.likedResources = data;
   console.log("LIKES: ", data);
	});

  User.getDislike($window.localStorage.getItem('com.fickle')).then(function(data){
    $scope.dislikedResources = data;
  });

  $scope.logout = function() {
    window.localStorage.setItem('com.fickle', null);
    window.localStorage.clear();
     setTimeout(function () {
      $ionicHistory.clearCache();
      $ionicHistory.clearHistory();
      // $ionicHistory.nextViewOptions({ disableBack: true, historyRoot: true });
      $state.go('login');
    }, 300);
  };

//   $scope.logout = function(){
//     $ionicLoading.show({template:'Logging out....'});
//     window.localStorage.setItem('com.fickle', null);

//     $timeout(function () {
//         $ionicLoading.hide();
//         $ionicHistory.clearCache();
//         $ionicHistory.clearHistory();
//         $ionicHistory.nextViewOptions({ disableBack: true, historyRoot: true });
//         $state.go('login');
//         }, 30);

// };

  $scope.onItemDelete = function(resource) {
    console.log("Attempted to Delete");
    var userpref = {
      'username' : username,
      'episodeTitle' : resource[0].title,
      'showName' : resource[1].name
    };
    console.log(userpref);
    UserResources.removeRelationship(userpref)
    .then(function(message){
      console.log("Response Message: ",message);
      if(message === 200){
        console.log("You have removed this like/dislke");
      }
    })
    .catch(function (error) {
      console.error(error);
    });
    $scope.likedResources.splice($scope.likedResources.indexOf(resource), 1);
  };
});
<|endoftext|>


<commit_before>/* global describe */
/* global it */

const should = require('should')
const sw = require('../lib/stopword.js')

describe('general stopwordiness:', function () {
  it('should remove stopwords, should default to english, should preserve case', function () {
    const oldString = 'a really Interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString)
    should.exist(sw.removeStopwords(oldString))
    newString.should.eql([ 'really', 'Interesting', 'string', 'words' ])
  })

  it('should remove custom stopwords', function () {
    const oldString = 'a really interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString, ['interesting'])
    newString.should.eql([ 'a', 'really', 'string', 'with', 'some', 'words' ])
  })

  it('should not remove any stopwords', function () {
    const oldString = 'a really interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString, [])
    newString.should.eql([ 'a', 'really', 'interesting', 'string', 'with', 'some', 'words' ])
  })

  it('should remove stopwords that have a non standard separator', function () {
    const oldString = 'a.really,interesting string.with,some.words'.split(/[\\., ]+/)
    const newString = sw.removeStopwords(oldString)
    newString.should.eql([ 'really', 'interesting', 'string', 'words' ])
  })

  it('should specify a custom input separator', function () {
    const oldString = 'a-really-interesting-string-with-some words'.split('-')
    const newString = sw.removeStopwords(oldString)
    newString.should.eql([ 'really', 'interesting', 'string', 'some words' ])
  })

  it('should remove norwegian stopwords', function () {
    const oldString = 'dette er en tekst som har nørske tegn øæåø øæåø æææ'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.no)
    newString.should.eql([ 'tekst', 'nørske', 'tegn', 'øæåø', 'øæåø', 'æææ' ])
  })

  it('should remove swedish stopwords and preserve case', function () {
    const oldString = 'Trädgårdsägare är beredda att pröva vad som helst för att bli av med de hatade mördarsniglarna åäö'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.sv)
    newString.should.eql([ 'Trädgårdsägare', 'beredda', 'pröva', 'helst', 'hatade', 'mördarsniglarna', 'åäö' ])
  })

  it('should remove danish stopwords', function () {
    const oldString = 'gæsterne i musikhuset i aarhus bør fremover sende en venlig tanke til den afdøde købmand herman salling når de skal til koncert eller se teater i det aarhusianske kulturhus æøå'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.da)
    newString.should.eql([ 'gæsterne', 'musikhuset', 'aarhus', 'bør', 'fremover', 'sende', 'venlig', 'tanke', 'afdøde', 'købmand', 'herman', 'salling', 'koncert', 'teater', 'aarhusianske', 'kulturhus', 'æøå' ])
  })

  it('should remove hindu stopwords', function () {
    const oldString = 'सूत्रों ने बताया कि ऊर्जा मंत्रालय के अंतर्गत काम करने वाले ब्यूरो ऑफ एनर्जी एफ़िशंसी एक योजना पर काम कर रहा है। मकसद ऐसे घरों को बढ़ावा देना है जहां ऊर्जा का प्रभावशाली इस्तेमाल हो सके। यानी यहां रोशनी या कूलिंग के लिए संसाधनों की कम डिमांड विकसित की जा सके। इसी कोशिश के तहत वर्तमान रेजिडेंशल इमारतों में भी नए उपकरणों का इस्तेमाल करके ऊर्जा के कम और प्रभावशाली इस्तेमाल को बढ़ावा देना है। बता दें कि मोदी सरकार की ओर से उजाला स्कीम ऊर्जा संसाधनों के बेहतर इस्तेमाल की दिशा में ही उठाया गया कदम है। इसके तहत सरकार ने पुराने फिलामेंट वाले और सीएफएल बल्बों को आधुनिक एलईडी लाइट्स से बदला है। बढ़ते शहरी दायरे और पर्यावरण पर पड़ते प्रभाव के मद्देनजर के जरिए सरकारी कोशिशों को नई ताकत मिलने की उम्मीद है। इससे प्रॉपर्टी सेक्टर में नौकरियां पैदा होने की भी पूरी गुंजाइश है।'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.hi)
    newString.should.eql([ 'सूत्रों', 'ने', 'बताया', 'कि', 'ऊर्जा', 'मंत्रालय', 'के', 'अंतर्गत', 'काम', 'करने', 'वाले', 'ब्यूरो', 'ऑफ', 'एनर्जी', 'एफ़िशंसी', 'एक', 'योजना', 'पर', 'काम', 'कर', 'रहा', 'है।', 'मकसद', 'ऐसे', 'घरों', 'को', 'बढ़ावा', 'देना', 'है,', 'जहां', 'ऊर्जा', 'का', 'प्रभावशाली', 'इस्तेमाल', 'हो', 'सके।', 'यानी', 'यहां', 'रोशनी', 'या', 'कूलिंग', 'के', 'लिए', 'संसाधनों', 'की', 'कम', 'डिमांड', 'विकसित', 'की', 'जा', 'सके।', 'इसी', 'कोशिश', 'के', 'तहत,', 'वर्तमान', 'रेजिडेंशल', 'इमारतों', 'में', 'भी', 'नए', 'उपकरणों', 'का', 'इस्तेमाल', 'करके', 'ऊर्जा', 'के', 'कम', 'और', 'प्रभावशाली', 'इस्तेमाल', 'को', 'बढ़ावा', 'देना', 'है।', 'बता', 'दें', 'कि', 'मोदी', 'सरकार', 'की', 'ओर', 'से', 'उजाला', 'स्कीम', 'ऊर्जा', 'संसाधनों', 'के', 'बेहतर', 'इस्तेमाल', 'की', 'दिशा', 'में', 'ही', 'उठाया', 'गया', 'कदम', 'है।', 'इसके', 'तहत', 'सरकार', 'ने', 'पुराने', 'फिलामेंट', 'वाले', 'और', 'सीएफएल', 'बल्बों', 'को', 'आधुनिक', 'एलईडी', 'लाइट्स', 'से', 'बदला', 'है।', 'बढ़ते', 'शहरी', 'दायरे', 'और', 'पर्यावरण', 'पर', 'पड़ते', 'प्रभाव', 'के', 'मद्देनजर', 'के', 'जरिए', 'सरकारी', 'कोशिशों', 'को', 'नई', 'ताकत', 'मिलने', 'की', 'उम्मीद', 'है।', 'इससे', 'प्रॉपर्टी', 'सेक्टर', 'में', 'नौकरियां', 'पैदा', 'होने', 'की', 'भी', 'पूरी', 'गुंजाइश', 'है।' ])
  })

})

describe('error handling', function () {
  it('should return throw an error if specified language is not supported', function () {
    (function () {
      sw.getStopwords('xx')
    }).should.throw()
  })
})
<commit_msg>Update test.js<commit_after>/* global describe */
/* global it */

const should = require('should')
const sw = require('../lib/stopword.js')

describe('general stopwordiness:', function () {
  it('should remove stopwords, should default to english, should preserve case', function () {
    const oldString = 'a really Interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString)
    should.exist(sw.removeStopwords(oldString))
    newString.should.eql([ 'really', 'Interesting', 'string', 'words' ])
  })

  it('should remove custom stopwords', function () {
    const oldString = 'a really interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString, ['interesting'])
    newString.should.eql([ 'a', 'really', 'string', 'with', 'some', 'words' ])
  })

  it('should not remove any stopwords', function () {
    const oldString = 'a really interesting string with some words'.split(' ')
    const newString = sw.removeStopwords(oldString, [])
    newString.should.eql([ 'a', 'really', 'interesting', 'string', 'with', 'some', 'words' ])
  })

  it('should remove stopwords that have a non standard separator', function () {
    const oldString = 'a.really,interesting string.with,some.words'.split(/[\\., ]+/)
    const newString = sw.removeStopwords(oldString)
    newString.should.eql([ 'really', 'interesting', 'string', 'words' ])
  })

  it('should specify a custom input separator', function () {
    const oldString = 'a-really-interesting-string-with-some words'.split('-')
    const newString = sw.removeStopwords(oldString)
    newString.should.eql([ 'really', 'interesting', 'string', 'some words' ])
  })

  it('should remove norwegian stopwords', function () {
    const oldString = 'dette er en tekst som har nørske tegn øæåø øæåø æææ'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.no)
    newString.should.eql([ 'tekst', 'nørske', 'tegn', 'øæåø', 'øæåø', 'æææ' ])
  })

  it('should remove swedish stopwords and preserve case', function () {
    const oldString = 'Trädgårdsägare är beredda att pröva vad som helst för att bli av med de hatade mördarsniglarna åäö'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.sv)
    newString.should.eql([ 'Trädgårdsägare', 'beredda', 'pröva', 'helst', 'hatade', 'mördarsniglarna', 'åäö' ])
  })

  it('should remove danish stopwords', function () {
    const oldString = 'gæsterne i musikhuset i aarhus bør fremover sende en venlig tanke til den afdøde købmand herman salling når de skal til koncert eller se teater i det aarhusianske kulturhus æøå'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.da)
    newString.should.eql([ 'gæsterne', 'musikhuset', 'aarhus', 'bør', 'fremover', 'sende', 'venlig', 'tanke', 'afdøde', 'købmand', 'herman', 'salling', 'koncert', 'teater', 'aarhusianske', 'kulturhus', 'æøå' ])
  })

  it('should remove hindu stopwords', function () {
    const oldString = 'सूत्रों ने बताया कि ऊर्जा मंत्रालय के अंतर्गत काम करने वाले ब्यूरो ऑफ एनर्जी एफ़िशंसी एक योजना पर काम कर रहा है। मकसद ऐसे घरों को बढ़ावा देना है जहां ऊर्जा का प्रभावशाली इस्तेमाल हो सके। यानी यहां रोशनी या कूलिंग के लिए संसाधनों की कम डिमांड विकसित की जा सके। इसी कोशिश के तहत वर्तमान रेजिडेंशल इमारतों में भी नए उपकरणों का इस्तेमाल करके ऊर्जा के कम और प्रभावशाली इस्तेमाल को बढ़ावा देना है। बता दें कि मोदी सरकार की ओर से उजाला स्कीम ऊर्जा संसाधनों के बेहतर इस्तेमाल की दिशा में ही उठाया गया कदम है। इसके तहत सरकार ने पुराने फिलामेंट वाले और सीएफएल बल्बों को आधुनिक एलईडी लाइट्स से बदला है। बढ़ते शहरी दायरे और पर्यावरण पर पड़ते प्रभाव के मद्देनजर के जरिए सरकारी कोशिशों को नई ताकत मिलने की उम्मीद है। इससे प्रॉपर्टी सेक्टर में नौकरियां पैदा होने की भी पूरी गुंजाइश है।'.split(' ')
    const newString = sw.removeStopwords(oldString, sw.hi)
    newString.should.eql([ 'सूत्रों', 'ने', 'बताया', 'कि', 'ऊर्जा', 'मंत्रालय', 'के', 'अंतर्गत', 'काम', 'करने', 'वाले', 'ब्यूरो', 'ऑफ', 'एनर्जी', 'एफ़िशंसी', 'एक', 'योजना', 'पर', 'काम', 'कर', 'रहा', 'है।', 'मकसद', 'ऐसे', 'घरों', 'को', 'बढ़ावा', 'देना', 'है', 'जहां', 'ऊर्जा', 'का', 'प्रभावशाली', 'इस्तेमाल', 'हो', 'सके।', 'यानी', 'यहां', 'रोशनी', 'या', 'कूलिंग', 'के', 'लिए', 'संसाधनों', 'की', 'कम', 'डिमांड', 'विकसित', 'की', 'जा', 'सके।', 'इसी', 'कोशिश', 'के', 'तहत', 'वर्तमान', 'रेजिडेंशल', 'इमारतों', 'में', 'भी', 'नए', 'उपकरणों', 'का', 'इस्तेमाल', 'करके', 'ऊर्जा', 'के', 'कम', 'और', 'प्रभावशाली', 'इस्तेमाल', 'को', 'बढ़ावा', 'देना', 'है।', 'बता', 'दें', 'कि', 'मोदी', 'सरकार', 'की', 'ओर', 'से', 'उजाला', 'स्कीम', 'ऊर्जा', 'संसाधनों', 'के', 'बेहतर', 'इस्तेमाल', 'की', 'दिशा', 'में', 'ही', 'उठाया', 'गया', 'कदम', 'है।', 'इसके', 'तहत', 'सरकार', 'ने', 'पुराने', 'फिलामेंट', 'वाले', 'और', 'सीएफएल', 'बल्बों', 'को', 'आधुनिक', 'एलईडी', 'लाइट्स', 'से', 'बदला', 'है।', 'बढ़ते', 'शहरी', 'दायरे', 'और', 'पर्यावरण', 'पर', 'पड़ते', 'प्रभाव', 'के', 'मद्देनजर', 'के', 'जरिए', 'सरकारी', 'कोशिशों', 'को', 'नई', 'ताकत', 'मिलने', 'की', 'उम्मीद', 'है।', 'इससे', 'प्रॉपर्टी', 'सेक्टर', 'में', 'नौकरियां', 'पैदा', 'होने', 'की', 'भी', 'पूरी', 'गुंजाइश', 'है।' ])
  })

})

describe('error handling', function () {
  it('should return throw an error if specified language is not supported', function () {
    (function () {
      sw.getStopwords('xx')
    }).should.throw()
  })
})
<|endoftext|>


<commit_before>'use strict';

var exec = require('child_process').exec;
var jsxTask = require('./grunt/tasks/jsx');
var browserifyTask = require('./grunt/tasks/browserify');
var populistTask = require('./grunt/tasks/populist');
var webdriverPhantomJSTask = require('./grunt/tasks/webdriver-phantomjs');
var webdriverJasmineTasks = require('./grunt/tasks/webdriver-jasmine');
var npmTask = require('./grunt/tasks/npm');
var releaseTasks = require('./grunt/tasks/release');

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: require('./grunt/config/copy'),
    jsx: require('./grunt/config/jsx/jsx'),
    browserify: require('./grunt/config/browserify'),
    populist: require('./grunt/config/populist'),
    connect: require('./grunt/config/server')(grunt),
    "webdriver-jasmine": require('./grunt/config/webdriver-jasmine.js'),
    npm: require('./grunt/config/npm'),
    clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
    jshint: require('./grunt/config/jshint'),
    compare_size: require('./grunt/config/compare_size')
  });

  grunt.config.set('compress', require('./grunt/config/compress'));

  for (var key in grunt.file.readJSON("package.json").devDependencies) {
      if (key !== "grunt" && key.indexOf("grunt") === 0) grunt.loadNpmTasks(key);
  }

  // Alias 'jshint' to 'lint' to better match the workflow we know
  grunt.registerTask('lint', ['jshint']);

  // Register jsx:debug and :release tasks.
  grunt.registerMultiTask('jsx', jsxTask);

  // Our own browserify-based tasks to build a single JS file build
  grunt.registerMultiTask('browserify', browserifyTask);

  grunt.registerMultiTask('populist', populistTask);

  grunt.registerMultiTask('webdriver-jasmine', webdriverJasmineTasks);

  grunt.registerMultiTask('npm', npmTask);

  // Check that the version we're exporting is the same one we expect in the
  // package. This is not an ideal way to do this, but makes sure that we keep
  // them in sync.
  var reactVersionExp = /\bReact\.version\s*=\s*['"]([^'"]+)['"];/;
  grunt.registerTask('version-check', function() {
    var version = reactVersionExp.exec(
      grunt.file.read('./build/modules/React.js')
    )[1];
    var expectedVersion = grunt.config.data.pkg.version;
    if (version !== expectedVersion) {
      grunt.log.error('Versions do not match. Expected %s, saw %s', expectedVersion, version);
      return false;
    }
  });

  grunt.registerTask('build:basic', ['jsx:debug', 'version-check', 'browserify:basic']);
  grunt.registerTask('build:addons', ['jsx:debug', 'browserify:addons']);
  grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
  grunt.registerTask('build:min', ['jsx:release', 'version-check', 'browserify:min']);
  grunt.registerTask('build:addons-min', ['jsx:debug', 'browserify:addonsMin']);
  grunt.registerTask('build:test', [
    'jsx:jasmine',
    'jsx:test',
    'version-check',
    'populist:test'
  ]);

  grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);

  grunt.registerTask('test:webdriver:phantomjs', [
    'connect',
    'webdriver-phantomjs',
    'webdriver-jasmine:local'
  ]);
  grunt.registerTask('test', ['build:test', 'build:basic', 'test:webdriver:phantomjs']);
  grunt.registerTask('npm:test', ['build', 'npm:pack']);

  // Optimized build task that does all of our builds. The subtasks will be run
  // in order so we can take advantage of that and only run jsx:debug once.
  grunt.registerTask('build', [
    'jsx:debug',
    'version-check',
    'browserify:basic',
    'browserify:transformer',
    'browserify:addons',
    'jsx:release',
    'browserify:min',
    'browserify:addonsMin',
    'copy:react_docs',
    'compare_size'
  ]);

  // Automate the release!
  grunt.registerTask('release:setup', releaseTasks.setup);
  grunt.registerTask('release:bower', releaseTasks.bower);
  grunt.registerTask('release:docs', releaseTasks.docs);
  grunt.registerTask('release:msg', releaseTasks.msg);
  grunt.registerTask('release:starter', releaseTasks.starter);

  grunt.registerTask('release', [
    'release:setup',
    'clean',
    'build',
    'gem:only',
    'release:bower',
    'release:starter',
    'compress',
    'release:docs',
    'release:msg'
  ]);

  // `gem` task to build the react-source gem
  grunt.registerTask('gem', ['build', 'gem:only']);

  grunt.registerTask('gem:only', function() {
    var done = this.async();
    exec('gem build react-source.gemspec', done);
  });

  // The default task - build - to keep setup easy
  grunt.registerTask('default', ['build']);
};
<commit_msg>cleanup loadNpmTasks<commit_after>'use strict';

var exec = require('child_process').exec;
var jsxTask = require('./grunt/tasks/jsx');
var browserifyTask = require('./grunt/tasks/browserify');
var populistTask = require('./grunt/tasks/populist');
var webdriverPhantomJSTask = require('./grunt/tasks/webdriver-phantomjs');
var webdriverJasmineTasks = require('./grunt/tasks/webdriver-jasmine');
var npmTask = require('./grunt/tasks/npm');
var releaseTasks = require('./grunt/tasks/release');

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    copy: require('./grunt/config/copy'),
    jsx: require('./grunt/config/jsx/jsx'),
    browserify: require('./grunt/config/browserify'),
    populist: require('./grunt/config/populist'),
    connect: require('./grunt/config/server')(grunt),
    "webdriver-jasmine": require('./grunt/config/webdriver-jasmine.js'),
    npm: require('./grunt/config/npm'),
    clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
    jshint: require('./grunt/config/jshint'),
    compare_size: require('./grunt/config/compare_size')
  });

  grunt.config.set('compress', require('./grunt/config/compress'));

  Object.keys(grunt.file.readJSON('package.json').devDependencies)
    .filter(function(npmTaskName){ return npmTaskName.indexOf('grunt-') === 0;})
    .forEach(function(npmTaskName){
      grunt.loadNpmTasks(npmTaskName);
    })
  ;

  // Alias 'jshint' to 'lint' to better match the workflow we know
  grunt.registerTask('lint', ['jshint']);

  // Register jsx:debug and :release tasks.
  grunt.registerMultiTask('jsx', jsxTask);

  // Our own browserify-based tasks to build a single JS file build
  grunt.registerMultiTask('browserify', browserifyTask);

  grunt.registerMultiTask('populist', populistTask);

  grunt.registerMultiTask('webdriver-jasmine', webdriverJasmineTasks);

  grunt.registerMultiTask('npm', npmTask);

  // Check that the version we're exporting is the same one we expect in the
  // package. This is not an ideal way to do this, but makes sure that we keep
  // them in sync.
  var reactVersionExp = /\bReact\.version\s*=\s*['"]([^'"]+)['"];/;
  grunt.registerTask('version-check', function() {
    var version = reactVersionExp.exec(
      grunt.file.read('./build/modules/React.js')
    )[1];
    var expectedVersion = grunt.config.data.pkg.version;
    if (version !== expectedVersion) {
      grunt.log.error('Versions do not match. Expected %s, saw %s', expectedVersion, version);
      return false;
    }
  });

  grunt.registerTask('build:basic', ['jsx:debug', 'version-check', 'browserify:basic']);
  grunt.registerTask('build:addons', ['jsx:debug', 'browserify:addons']);
  grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
  grunt.registerTask('build:min', ['jsx:release', 'version-check', 'browserify:min']);
  grunt.registerTask('build:addons-min', ['jsx:debug', 'browserify:addonsMin']);
  grunt.registerTask('build:test', [
    'jsx:jasmine',
    'jsx:test',
    'version-check',
    'populist:test'
  ]);

  grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);

  grunt.registerTask('test:webdriver:phantomjs', [
    'connect',
    'webdriver-phantomjs',
    'webdriver-jasmine:local'
  ]);
  grunt.registerTask('test', ['build:test', 'build:basic', 'test:webdriver:phantomjs']);
  grunt.registerTask('npm:test', ['build', 'npm:pack']);

  // Optimized build task that does all of our builds. The subtasks will be run
  // in order so we can take advantage of that and only run jsx:debug once.
  grunt.registerTask('build', [
    'jsx:debug',
    'version-check',
    'browserify:basic',
    'browserify:transformer',
    'browserify:addons',
    'jsx:release',
    'browserify:min',
    'browserify:addonsMin',
    'copy:react_docs',
    'compare_size'
  ]);

  // Automate the release!
  grunt.registerTask('release:setup', releaseTasks.setup);
  grunt.registerTask('release:bower', releaseTasks.bower);
  grunt.registerTask('release:docs', releaseTasks.docs);
  grunt.registerTask('release:msg', releaseTasks.msg);
  grunt.registerTask('release:starter', releaseTasks.starter);

  grunt.registerTask('release', [
    'release:setup',
    'clean',
    'build',
    'gem:only',
    'release:bower',
    'release:starter',
    'compress',
    'release:docs',
    'release:msg'
  ]);

  // `gem` task to build the react-source gem
  grunt.registerTask('gem', ['build', 'gem:only']);

  grunt.registerTask('gem:only', function() {
    var done = this.async();
    exec('gem build react-source.gemspec', done);
  });

  // The default task - build - to keep setup easy
  grunt.registerTask('default', ['build']);
};
<|endoftext|>


<commit_before>'use strict';
var chai = require('chai')
var assert = chai.assert;
var expect = chai.expect;
var cuid = require('cuid');

var Promise = require('promise');
var LocalStorageReplicator = require('../');
var LocalStorage = require('node-localstorage').LocalStorage;

describe('localstorage-replicate-webrtc node module', function () {
  var store1, store2, store3, replicator1, replicator2, replicator3;
  var signalUrl = 'http://localhost:3000/';

  beforeEach(function(done) {
    var rtcOpts = {
      room: cuid(),
      nick: 'foo',
      plugins: [ require('rtc-plugin-node') ]
    };

    store1 = new LocalStorage('./store1');
    store2 = new LocalStorage('./store2');
    store3 = new LocalStorage('./store3');

    replicator1 = new LocalStorageReplicator('replicator1', signalUrl, rtcOpts, store1);
    replicator2 = new LocalStorageReplicator('replicator2', signalUrl, rtcOpts, store2);
    replicator3 = new LocalStorageReplicator('replicator3', signalUrl, rtcOpts, store3);

    Promise.all([replicator1.join(2), replicator2.join(2), replicator3.join(2)])
      .then(function() {
        done();
      });

  });

  afterEach(function() {
    store1._deleteLocation();
    store2._deleteLocation();
    store3._deleteLocation();
  });

  it('should replicate', function (done) {

    var namespace = 'localstore-replicate';
    var data = {
      a: 'a',
      b: 'b'
    };

    replicator2.on('endreplicate', function(ns, store) {
      var storeObj = JSON.parse(store);
      var storeObj2 = JSON.parse(store2.getItem(ns));

      // verify namespace
      assert.equal(namespace, ns);

      // verify emitted data
      assert.equal(data.a, storeObj.a);
      assert.equal(data.b, storeObj.b);

      // verify localstorage data
      assert.equal(data.a, storeObj2.a);
      assert.equal(data.b, storeObj2.b);

      done();
    });

    store1.setItem(namespace, JSON.stringify(data));
    replicator1.replicate(namespace);
  });

});<commit_msg>Add test case to verify array replication.<commit_after>'use strict';
var chai = require('chai')
var assert = chai.assert;
var expect = chai.expect;
var cuid = require('cuid');

var Promise = require('promise');
var LocalStorageReplicator = require('../');
var LocalStorage = require('node-localstorage').LocalStorage;

describe('localstorage-replicate-webrtc node module', function () {
  var store1, store2, store3, replicator1, replicator2, replicator3;
  var signalUrl = 'http://localhost:3000/';

  beforeEach(function(done) {
    var rtcOpts = {
      room: cuid(),
      nick: 'foo',
      plugins: [ require('rtc-plugin-node') ]
    };

    store1 = new LocalStorage('./store1');
    store2 = new LocalStorage('./store2');
    store3 = new LocalStorage('./store3');

    replicator1 = new LocalStorageReplicator('replicator1', signalUrl, rtcOpts, store1);
    replicator2 = new LocalStorageReplicator('replicator2', signalUrl, rtcOpts, store2);
    replicator3 = new LocalStorageReplicator('replicator3', signalUrl, rtcOpts, store3);

    Promise.all([replicator1.join(2), replicator2.join(2), replicator3.join(2)])
      .then(function() {
        done();
      });

  });

  afterEach(function() {
    store1._deleteLocation();
    store2._deleteLocation();
    store3._deleteLocation();
  });

  it('should replicate an object', function (done) {

    var namespace = 'localstore-replicate';
    var data = {
      a: 'a',
      b: 'b'
    };

    replicator2.on('endreplicate', function(ns, store) {
      var storeObj = JSON.parse(store);
      var storeObj2 = JSON.parse(store2.getItem(ns));

      // verify namespace
      assert.equal(namespace, ns);

      // verify emitted data
      assert.equal(data.a, storeObj.a);
      assert.equal(data.b, storeObj.b);

      // verify localstorage data
      assert.equal(data.a, storeObj2.a);
      assert.equal(data.b, storeObj2.b);

      done();
    });

    store1.setItem(namespace, JSON.stringify(data));
    replicator1.replicate(namespace);
  });

  it('should replicate an array', function (done) {

    var namespace = 'localstore-replicate';
    var data = [
      {a: '1'},
      {a: '2'}
      ];

    replicator2.on('endreplicate', function(ns, store) {
      var storeObj = JSON.parse(store);
      var storeObj2 = JSON.parse(store2.getItem(ns));

      // verify namespace
      assert.equal(namespace, ns);

      // verify emitted data
      assert.equal(data[0].a, storeObj[0].a);
      assert.equal(data[1].a, storeObj[1].a);

      // verify localstorage data
      assert.equal(data[0].a, storeObj2[0].a);
      assert.equal(data[1].a, storeObj2[1].a);

      done();
    });

    store1.setItem(namespace, JSON.stringify(data));
    replicator1.replicate(namespace);
  });
});<|endoftext|>


<commit_before><commit_msg>Remove unused script create-graph.js<commit_after><|endoftext|>


<commit_before>var fs = require('fs')
var test = require('tap').test
var walkSync = require('../')

test('walkSync', function (t) {
  t.deepEqual(walkSync('fixtures'), [
    'dir/',
    'dir/bar.txt',
    'dir/subdir/',
    'dir/subdir/baz.txt',
    'dir/zzz.txt',
    'foo.txt',
    'some-other-dir/',
    'some-other-dir/qux.txt',
    'symlink1/',
    'symlink1/qux.txt',
    'symlink2',
  ])

  t.throws(function () {
    walkSync('doesnotexist')
  }, {
    name: 'Error',
    message: "ENOENT, no such file or directory 'doesnotexist/'"
  })

  t.throws(function () {
    walkSync('fixtures/foo.txt')
  }, {
    name: 'Error',
    message: "ENOTDIR, not a directory 'fixtures/foo.txt/'"
  })

  t.end()
})
<commit_msg>error messages appear to change between versions of node / platforms, so prefer a fuzzier approach<commit_after>var fs = require('fs')
var tap = require('tap')
var test = tap.test
var walkSync = require('../')

function captureError(fn) {
  try {
    fn();
  } catch(e) {
    return e;
  }
}

tap.Test.prototype.addAssert('matchThrows', 2, function(fn, expectedError) {
  var error = captureError(fn)

  this.type(error, Error);
  this.equal(error.name, expectedError.name)
  this.match(error.message, expectedError.message)
})

test('walkSync', function (t) {
  t.deepEqual(walkSync('test/fixtures'), [
    'dir/',
    'dir/bar.txt',
    'dir/subdir/',
    'dir/subdir/baz.txt',
    'dir/zzz.txt',
    'foo.txt',
    'some-other-dir/',
    'some-other-dir/qux.txt',
    'symlink1/',
    'symlink1/qux.txt',
    'symlink2',
  ])

  t.matchThrows(function() {
    walkSync('test/doesnotexist')
  }, {
    name: 'Error',
    message: /ENOENT.* 'test\/doesnotexist/
  })

  t.matchThrows(function() {
    walkSync('test/fixtures/foo.txt')
  }, {
    name: 'Error',
    message: /ENOTDIR.* 'test\/fixtures\/foo.txt/
  })

  t.end()
})
<|endoftext|>


<commit_before>/**
 * Imports
 */

import PlaylistItem from 'components/PlaylistItem'
import {Button, MenuItem} from 'vdux-containers'
import EmptyState from 'components/EmptyState'
import {Block, Icon, Menu} from 'vdux-ui'
import {component, element} from 'vdux'
import UpNext from 'components/UpNext'
import mapValues from '@f/map-values'
import orderBy from 'lodash/orderBy'
import Link from 'components/Link'
import fire from 'vdux-fire'

/**
 * <Progress/>
 */

const btnProps = {
	fs: 'l',
	p: '12px 24px',
	bgColor: 'blue',
	boxShadow: '0px 1px 3px rgba(0,0,0,.5)'
}

export default fire((props) => ({
  coursesVal: '/courses#bindAs=object',
	inProgress: {
		ref: `/playlistsByUser/${props.uid}/inProgress#orderByChild=lastEdited`,
		join: {
			ref: '/playlistInstances',
			child: 'playlistValue',
			childRef: (val, ref) => val.map(v => ref.child(v.key))
		}
	},
	completed: {
		ref: `/playlistsByUser/${props.uid}/completed#orderByChild=lastEdited`,
		join: {
			ref: '/playlistInstances',
			child: 'playlistValue',
			childRef: (val, ref) => val.map(v => ref.child(v.key))
		}
	}
}))(component({
  render ({props, context}) {
  	const {userProfile, inProgress, coursesVal} = props
  	const {value, loading} = coursesVal
		const {value: inProgressValue, loading: inProgressLoading} = inProgress

  	if (loading || inProgressLoading) return

  	const orderedLists = (inProgressValue || []).reverse()
  	const next = orderedLists[0]

    return (
    	<Block tall bg='#f0f0f0' align='center' overflowY='auto'>
				<Block p='l' pt flex maxWidth='1100' mt={orderedLists.length === 1 ? 75 : 0}>
					{
						next && <UpNext
							playlistRef={next.playlistRef}
							instanceRef={next.key}
							current={next.playlistValue.current}
							uid={context.uid} />
					}
					<Block align='start'>
						{/* <Sidebar mr items={value} /> */}
						<Block flex>
							{
								orderedLists && Object.keys(orderedLists).length
					    		? orderedLists.map((list, i) =>
					    				<Block hide={!i}>
						    				<PlaylistItem
								          key={list.key}
													uid={context.uid}
													instanceRef={list.key}
													myProgress={list}
								          clickHandler={context.setUrl(`/playlist/${list.playlistRef}`)}
								          lastEdited={list.lastEdited}
								          playlistRef={list.playlistRef} />
						          </Block>
				    				)
					    		: <EmptyState icon='access_time' title='In Progress Projects' description={'You don\'t currently have any projects in progress. In progress projects will appear here so you can continue where you left off. '} />
							}
						</Block>
					</Block>
				</Block>
    	</Block>
    )
  }
}))

const Sidebar = component({
	render({props}) {
		const {items, ...rest} = props

		return (
			<Block tall w={200} pb border='1px solid grey' bg='white' {...rest}>
				<Block color='blue' textAlign='center' p mb='s' borderBottom='1px solid divider'>Active Course</Block>
				<Menu column overflowY='auto' wide px='s'>
					{
						mapValues((course) => <Item title={course.title}/>, items)
					}
				</Menu>
			</Block>
		)
	}
})

const Item = component({
	render({props, context}) {
		const {icon, title, ...rest} = props

		return (
			<Link bgColor='white' color='primary' fs='xs' py='10' align='start center' ui={MenuItem} currentProps={{bgColor: '#EEE'}} ellipsis {...rest}>
				<Block circle='24' bgColor='green' color='white' align='center center' mr='s'>
					{title[0]}
				</Block>
				<Block flex>{ title }</Block>
				{Math.floor(Math.random() * 100)}%
			</Link>
		)
	}
})
<commit_msg>add completed<commit_after>/**
 * Imports
 */

import PlaylistItem from 'components/PlaylistItem'
import {Button, MenuItem} from 'vdux-containers'
import EmptyState from 'components/EmptyState'
import {Block, Icon, Menu} from 'vdux-ui'
import {component, element} from 'vdux'
import UpNext from 'components/UpNext'
import mapValues from '@f/map-values'
import orderBy from 'lodash/orderBy'
import Link from 'components/Link'
import fire from 'vdux-fire'

/**
 * <Progress/>
 */

const btnProps = {
	fs: 'l',
	p: '12px 24px',
	bgColor: 'blue',
	boxShadow: '0px 1px 3px rgba(0,0,0,.5)'
}

export default fire((props) => ({
  coursesVal: '/courses#bindAs=object',
	inProgress: {
		ref: `/playlistsByUser/${props.uid}/inProgress#orderByChild=lastEdited`,
		join: {
			ref: '/playlistInstances',
			child: 'playlistValue',
			childRef: (val, ref) => val.map(v => ref.child(v.key))
		}
	},
	completed: {
		ref: `/playlistsByUser/${props.uid}/completed#orderByChild=lastEdited`,
		join: {
			ref: '/playlistInstances',
			child: 'playlistValue',
			childRef: (val, ref) => val.map(v => ref.child(v.key))
		}
	}
}))(component({
  render ({props, context}) {
  	const {userProfile, inProgress, coursesVal, completed} = props
  	const {value, loading} = coursesVal
		const {value: inProgressValue, loading: inProgressLoading} = inProgress
		const {value: completedValue, loading: completedLoading} = completed

  	if (loading || inProgressLoading || completedLoading) return

  	const orderedLists = (inProgressValue || []).reverse()
  	const next = orderedLists[0]
		console.log(completedValue)

    return (
    	<Block tall bg='#f0f0f0' align='center' overflowY='auto'>
				<Block p='l' pt flex maxWidth='1100' mt={orderedLists.length === 1 ? 75 : 0}>
					{
						next && <UpNext
							playlistRef={next.playlistRef}
							instanceRef={next.key}
							current={next.playlistValue.current}
							uid={context.uid} />
					}
					<Block align='start'>
						{/* <Sidebar mr items={value} /> */}
						<Block flex>
							{
								orderedLists && Object.keys(orderedLists).length
					    		? orderedLists.map((list, i) =>
					    				<Block hide={!i}>
						    				<PlaylistItem
								          key={list.key}
													uid={context.uid}
													instanceRef={list.key}
													myProgress={list}
								          clickHandler={context.setUrl(`/playlist/${list.playlistRef}`)}
								          lastEdited={list.lastEdited}
								          playlistRef={list.playlistRef} />
						          </Block>
				    				)
					    		: <EmptyState icon='access_time' title='In Progress Projects' description={'You don\'t currently have any projects in progress. In progress projects will appear here so you can continue where you left off. '} />
							}
						</Block>
					</Block>
				</Block>
    	</Block>
    )
  }
}))

const Sidebar = component({
	render({props}) {
		const {items, ...rest} = props

		return (
			<Block tall w={200} pb border='1px solid grey' bg='white' {...rest}>
				<Block color='blue' textAlign='center' p mb='s' borderBottom='1px solid divider'>Active Course</Block>
				<Menu column overflowY='auto' wide px='s'>
					{
						mapValues((course) => <Item title={course.title}/>, items)
					}
				</Menu>
			</Block>
		)
	}
})

const Item = component({
	render({props, context}) {
		const {icon, title, ...rest} = props

		return (
			<Link bgColor='white' color='primary' fs='xs' py='10' align='start center' ui={MenuItem} currentProps={{bgColor: '#EEE'}} ellipsis {...rest}>
				<Block circle='24' bgColor='green' color='white' align='center center' mr='s'>
					{title[0]}
				</Block>
				<Block flex>{ title }</Block>
				{Math.floor(Math.random() * 100)}%
			</Link>
		)
	}
})
<|endoftext|>


<commit_before>//
//  TGJSBridge.js
//  TGJSBridge
//
//  Created by Chao Shen on 12-3-1.
//  Copyright (c) 2012年 Hangzhou Jiuyan Technology Co., Ltd. All rights reserved.
//

(function(context){
    function bridgeCall(src,callback) {
		iframe = document.createElement("iframe");
		iframe.style.display = "none";
		iframe.src = src;
		var cleanFn = function(state){
		   console.log(state)
		    try {
		        iframe.parentNode.removeChild(iframe);
		    } catch (error) {}
		    if(callback) callback();
		};
        iframe.onload = cleanFn;
		document.documentElement.appendChild(iframe);
	}

    function JSBridge()
    {
        this.callbackDict = {};
        this.notificationIdCount = 0;
        this.notificationDict = {};

        var that = this;
        context.document.addEventListener('DOMContentLoaded',function(){
            bridgeCall('jsbridge://NotificationReady',that.trigger('jsBridgeReady',{}));
        },false);
    }

    JSBridge.prototype = {
        constructor: JSBridge,
        //js向oc发送消息
        postNotification: function(name, userInfo){
            this.notificationIdCount++;

            this.notificationDict[this.notificationIdCount] = {name:name, userInfo:userInfo};

            bridgeCall('jsbridge://PostNotificationWithId-' + this.notificationIdCount);
        },
        //oc获取消息数据
        popNotificationObject: function(notificationId){
            var result = JSON.stringify(this.notificationDict[notificationId]);
            delete this.notificationDict[notificationId];
            return result;
        },
        //oc向js发送消息
        trigger: function(name, userInfo) {
            if(this.callbackDict[name]){
                var callList = this.callbackDict[name];

                for(var i=0,len=callList.length;i<len;i++){
                    callList[i](userInfo);
                }
            }
        },
        //绑定消息
        bind: function(name, callback){
            if(!this.callbackDict[name]){
                //创建对应数组
                this.callbackDict[name] = [];
            }
            this.callbackDict[name].push(callback);
        },
        //解除绑定
        unbind: function(name, callback){
            //如果只提供消息名，则删除整个对应的数组
            if(arguments.length == 1){
                delete this.callbackDict[name];
            } else if(arguments.length > 1) {
                //搜索相应的callback，并删除
                if(this.callbackDict[name]){
                    var callList = this.callbackDict[name];

                    for(var i=0,len=callList.length;i<len;i++){
                        if(callList[i] == callback){
                            callList.splice(i,1);
                            break;
                        }
                    }
                }
                //如果数组为空，则删除
                if(this.callbackDict[name].length == 0){
                    delete this.callbackDict[name];
                }
            }

        }

    };

    context.jsBridge = new JSBridge();

})(window);
<commit_msg>translate the annotation into English<commit_after>//
//  TGJSBridge.js
//  TGJSBridge
//
//  Created by Chao Shen on 12-3-1.
//  Copyright (c) 2012年 Hangzhou Jiuyan Technology Co., Ltd. All rights reserved.
//

(function(context){
    function bridgeCall(src,callback) {
		iframe = document.createElement("iframe");
		iframe.style.display = "none";
		iframe.src = src;
		var cleanFn = function(state){
		   console.log(state)
		    try {
		        iframe.parentNode.removeChild(iframe);
		    } catch (error) {}
		    if(callback) callback();
		};
        iframe.onload = cleanFn;
		document.documentElement.appendChild(iframe);
	}

    function JSBridge()
    {
        this.callbackDict = {};
        this.notificationIdCount = 0;
        this.notificationDict = {};

        var that = this;
        context.document.addEventListener('DOMContentLoaded',function(){
            bridgeCall('jsbridge://NotificationReady',that.trigger('jsBridgeReady',{}));
        },false);
    }

    JSBridge.prototype = {
        constructor: JSBridge,
        //send notification to WebView
        postNotification: function(name, userInfo){
            this.notificationIdCount++;

            this.notificationDict[this.notificationIdCount] = {name:name, userInfo:userInfo};

            bridgeCall('jsbridge://PostNotificationWithId-' + this.notificationIdCount);
        },
        //pop the notification in the cache
        popNotificationObject: function(notificationId){
            var result = JSON.stringify(this.notificationDict[notificationId]);
            delete this.notificationDict[notificationId];
            return result;
        },
        //trigger the js event
        trigger: function(name, userInfo) {
            if(this.callbackDict[name]){
                var callList = this.callbackDict[name];

                for(var i=0,len=callList.length;i<len;i++){
                    callList[i](userInfo);
                }
            }
        },
        //bind js event
        bind: function(name, callback){
            if(!this.callbackDict[name]){
                //create the array
                this.callbackDict[name] = [];
            }
            this.callbackDict[name].push(callback);
        },
        //unbind js event
        unbind: function(name, callback){
            if(arguments.length == 1){
                delete this.callbackDict[name];
            } else if(arguments.length > 1) {
                if(this.callbackDict[name]){
                    var callList = this.callbackDict[name];

                    for(var i=0,len=callList.length;i<len;i++){
                        if(callList[i] == callback){
                            callList.splice(i,1);
                            break;
                        }
                    }
                }
                if(this.callbackDict[name].length == 0){
                    delete this.callbackDict[name];
                }
            }

        }

    };

    context.jsBridge = new JSBridge();

})(window);
<|endoftext|>


<commit_before>var jDistiller = require('jdistiller').jDistiller,
  Source = require('../../source').Source;

exports.source = new Source({
  source: "Github",
  description: 'Trending and featured repos on Github.com',
  headlineURL: 'https://github.com/explore',
  headlineDistiller: new jDistiller()
    .set('headlines', '#trending-repositories li h3, .ranked-repositories li h3', function(element) {
      return [{
        title: element.text().trim(),
        href: 'https://github.com' + element.find('a:last').attr('href')
      }]
    }),
  articleDistiller: new jDistiller()
    .set('title', '.entry-title', function(element) {
      return element.find('.author').text().trim() + ' / ' + element.find('strong').text().trim();
    })
    .set('body', '#repository_description p')
});
<commit_msg>github now pulls in the markdown body, way cooler.<commit_after>var jDistiller = require('jdistiller').jDistiller,
  Source = require('../../source').Source;

exports.source = new Source({
  source: "Github",
  description: 'Trending and featured repos on Github.com',
  headlineURL: 'https://github.com/explore',
  headlineDistiller: new jDistiller()
    .set('headlines', '#trending-repositories li h3, .ranked-repositories li h3', function(element) {
      return [{
        title: element.text().trim(),
        href: 'https://github.com' + element.find('a:last').attr('href')
      }]
    }),
  articleDistiller: new jDistiller()
    .set('title', '.entry-title', function(element) {
      return element.find('.author').text().trim() + ' / ' + element.find('strong').text().trim();
    })
    .set('body', '.markdown-body p', function(element, prev) {
      prev.body = prev.body || '';
      prev.body += element.text().trim() + '\n\n';
      return prev.body
    })
});
<|endoftext|>