<commit_before>var newElement = (function(){

var _key = 0, _cache = {};

function Element(path, host) {
    this.host = host;
    this.path = path;
    this.name = decodeURIComponent(path.match(/([^\/]*)\/$/)[1]);
    this.key = _key++;
}

function _newElement(path, host, _initData) {
    host = host || Application.siteInfo.host;
    path = path || location.pathname;
    path = (path + '/').replace(/\/+/g, '/');
    var uri = host + path;
    var element = _cache[uri];
    if(!element) {
        _cache[uri] = element = new Element(path, host);
        if(_initData) element._setData(_initData);
        else element.load();
    }
    return element;
}

ex(Element.prototype, {
    host: null,
    path: null,
    name: null,
    author: null,
    data: null,
    owner: null,
    error: null,
    key: null,
    _loading: false,
    _inp: null,
    _children: null,

    type: function() {
        if(this.isRoot()) return "homepage";
        return this.get("type");
    },

    uri: function() {
        return this.host + this.path;
    },

    href: function() {
        return this.path;
    },

    aid: function() {
        return this.author && this.author.aid;
    },

    ev: function(fnName, args, confirmMsg) {
        return function(ev) {
            if(ev) {
                ev.preventDefault();
                ev.stopPropagation();
            }
            (!confirmMsg || confirm(transl(confirmMsg))) && this[fnName] && this[fnName].apply(this, args || []);
        }.bind(this);
    },

    remove: function() {
        this._setData({ data: "" });
        return this.save();
    },

    save: function(fn) {
        var parent = !this.isRoot() && this.parent();
        var ver = (this.ver|0) + 1;
        var uid = this.isRoot()? this.host : (this.uid || parent.uri());
        var name = this.name;
        var newData;
        if(this.isRemoved()) {
            newData = "";
        } else {
            newData = {};
            for(var i in this.data) {
                newData[i] = this.data[i];
            }
            for(i in this._inp) if(i[0] !== "_") { // set input values
                newData[i] = this.get(i);
            }
            for(i in newData) {
                if(newData[i] === null || newData[i] === undefined)
                    delete newData[i];
            }
            if(newData.name !== undefined) name = newData.name;
            delete newData.name;
            this.setName(name);
        }
        this._setData({
            _saving: true
        });
        baseAPI.postData({
            uid: uid,
            storage: this.storage,
            ring: this.ring,
            ver: ver,
            pos: name,
            data: newData
        }, function(err, resp) {
            this._setData({
                _saving: false,
                ver: ver,
                author: resp.author,
                data: err? this.data : newData,
                error: err
            })._refresh();
            if(!err) {
                this._inp = null;
                if(this.isRoot()) {
                    Application.siteInfo.title = this.get('title');
                    delete localStorage.siteInfo;
                }
                if(this._isNew) {
                    this._isNew = false;
                    if(parent) {
                        (parent._children || (parent._children = [])).unshift(this);
                        //todo: search position in _children by init.pos
                    }
                }
            }
            fn && fn(err, resp);
        }.bind(this));
        return this._refresh();
    },

    isRoot: function(){
        return this.host === Application.siteInfo.host
            && this.path === "/";
    },

    isNew: function(){
        return this._isNew;
    },

    isLoading: function(){
        return !!this._loading;
    },

    isLoaded: function(){
        return this.data !== null;
    },

    isRemoved: function(){
        return this.data === "";
    },

    isActive: function(){
        return this.host === Application.siteInfo.host
            && (location.pathname+"/").substr(0, this.path.length) === this.path;
    },

    isEditable: function(){
        return this.isLoaded() && this.author && this.author.isMe;
    },

    isAvailableToAdd: function() {
        var author = this.author, access = this.get("access") || "self";
        if(!author) return false;
        return author.isMe
            || access == "all"
            || access == "reg" && author.signed
            || access.split(",").indexOf(author.aid) > -1;
    },

    toString: function(){
        return this.get("title") || this.get("subject") || (this.error? '#ERROR{'+this.error+'}' : null) || this.name;
    },

    parent: function() {
        return !this.isRoot() && _newElement(this.path.replace(/[^\/]*\/$/, ""), this.host);
    },

    getChildStreamInfo: function() {
        var access = this.get("access")||"self";
        var strg = (access=="self"? "D" : "P") + Application.siteInfo.ring;  // <storage:CHAR><ring:int>
        return {
            uid: this.host + this.path,
            access: access,
            aid: /^[0-9a-zA-Z\-_]{20}$/.test(access)? access : this.author && this.author.aid || Application.siteInfo.owner,
            storage: strg.match(/^[A-Z]+/)[0],
            ring: strg.match(/[0-9]+/)[0]|0
        }
    },

    children: function() {
        if(this._children) return this._children;
        if(!this.isLoaded()) return [];
        this._children = [];
        var streamInf = this.getChildStreamInfo();
        var req = {
            cmd:     "top",
            uid:     streamInf.uid,
            aid:     streamInf.aid,
            ring:    streamInf.ring,
            storage: streamInf.storage,
            sse:     Application.element() === this
        };
        baseAPI.requestData(req, function(err, packs) {
            if(err && err !== "sse-updates") return {error: err};
            this._children = packs.map(function(pack){
                return _newElement(this.path + encodeURIComponent(pack.pos), this.host, pack);
            }.bind(this)).concat(this._children);
            this._refresh();
        }.bind(this));
        return this._children;
    },

    datetime: function() {
        var t = String(this.name).match(/^(20\d\d)([01]\d)([0-3]\d)([0-2]\d)([0-5]\d)([0-5]\d)\d\d\d$/);
        if(t) return [t[1],"-",t[2],"-",t[3]," ",t[4],":",t[5],":",t[6]].join("");
    },

    get: function(name) {
        if(!this.isLoaded()) {
            this.load();
            return null;
        }
        var parts = name.split('|'), val;
        if(parts.length > 1) {
            while(parts.length) {
                if(val = this.get(parts.shift())) return val;
            }
            return null;
        }
        if(this._inp && this._inp[name] !== undefined) {
            val = this._inp[name];
            if(val instanceof Function) return val.call(this);
            return val;
        }
        return this.data[name] !== undefined && this.data[name]
            || this[name] !== undefined && !(this[name] instanceof Function) && this[name]
            || null;
    },

    set: function(name, value) {
        if(arguments.length === 1) {
            for(var i in name) this.set(i, name[i]);
        } else {
            if(name === "pos") name = "name";
            this._inp = this._inp || {};
            this._inp[name] = value;
        }
        return this;
    },

    reset: function() {
        this._inp = {};
        return this;
    },

    setName: function(name) {
        this.name = name;
        this.path = (this.parent() || {path: ""}).path + encodeURIComponent(name) + "/";
        return this;
    },

    newChildElement: function(name) {
        // new element. (empty name is possible)
        var element = new Element(this.path + encodeURIComponent(name||"") + "/", this.host);
        var streamInf = this.getChildStreamInfo();
        element.storage = streamInf.storage;
        element.ring = streamInf.ring;
        element.data = {};
        element._isNew = true;
        return element;
    },

    load: function(fn) {
        if(this.isLoaded()) {
            fn && fn(this);
            return this;
        }
        if(this._loading) {
            this._loading.push(fn);
            return this;
        }
        this._loading = [];
        if(fn) this._loading.push(fn);

        var parent = this.parent();
        var onParentLoaded = function(){
            if(this.error = parent && parent.error) {
                return this._refresh();
            }
            var strmInf = parent? parent.getChildStreamInfo() : Application.siteInfo;
            var req = {
                cmd: "doc", // load single document
                ring: strmInf.ring,
                storage: strmInf.storage,
                aid: strmInf.aid || strmInf.owner,
                uid: strmInf.uid || strmInf.host,
                pos: this.name,
                limit: 1
            };
            baseAPI.requestData(req, function(err, packs) {
                err = err || !packs.length && 'Not found ' + this.uri();
                this._setData(err? { error: err } : packs[0]);

                // callbacks
                while(this._loading.length) setTimeout(this._loading.shift());
                this._loading = false;
                return this._refresh();
            }.bind(this));
        }.bind(this);

        if(!parent) {
            onParentLoaded();
            //if(!parent) return _upd();
        } else {
            if(parent._children) {
                //todo: search in children
            }
            parent.load(onParentLoaded);
        }
        return this;
    },

    _refresh: function() {
        this.data && this.author && setTimeout(Application.onElementUpdate.bind(application, this));
    },

    _setData: function(pack) {
        if(pack.pos !== undefined) { // .name is synonym of .pos
            this.name = pack.pos;
            delete pack.pos;
        }
        ex(this, pack);
        if(this.isRemoved()) { // deleted
            this.title = "*[REMOVED]*";
            // remove element from parent.children
            var par = this.parent(), children = par && par._children;
            if(children)
            for(var i in children)
                if(children[i] === this) {
                    delete children[i];
                    break;
                }
            par._refresh();
        }
        this.key = _key++;
        return this;
    }
});

return _newElement;
})();<commit_msg>fix duplicates of added elements<commit_after>var newElement = (function(){

var _key = 0, _cache = {};

function Element(path, host) {
    this.host = host;
    this.path = path;
    this.name = decodeURIComponent(path.match(/([^\/]*)\/$/)[1]);
    this.key = _key++;
}

function _newElement(path, host, _initData) {
    host = host || Application.siteInfo.host;
    path = path || location.pathname;
    path = (path + '/').replace(/\/+/g, '/');
    var uri = host + path;
    var element = _cache[uri];
    if(!element) {
        _cache[uri] = element = new Element(path, host);
        if(_initData) element._setData(_initData);
        else element.load();
    }
    return element;
}

ex(Element.prototype, {
    host: null,
    path: null,
    name: null,
    author: null,
    data: null,
    owner: null,
    error: null,
    key: null,
    _loading: false,
    _inp: null,
    _children: null,

    type: function() {
        if(this.isRoot()) return "homepage";
        return this.get("type");
    },

    uri: function() {
        return this.host + this.path;
    },

    href: function() {
        return this.path;
    },

    aid: function() {
        return this.author && this.author.aid;
    },

    ev: function(fnName, args, confirmMsg) {
        return function(ev) {
            if(ev) {
                ev.preventDefault();
                ev.stopPropagation();
            }
            (!confirmMsg || confirm(transl(confirmMsg))) && this[fnName] && this[fnName].apply(this, args || []);
        }.bind(this);
    },

    remove: function() {
        this._setData({ data: "" });
        return this.save();
    },

    save: function(fn) {
        var parent = !this.isRoot() && this.parent();
        var ver = (this.ver|0) + 1;
        var uid = this.isRoot()? this.host : (this.uid || parent.uri());
        var name = this.name;
        var newData;
        if(this.isRemoved()) {
            newData = "";
        } else {
            newData = {};
            for(var i in this.data) {
                newData[i] = this.data[i];
            }
            for(i in this._inp) if(i[0] !== "_") { // set input values
                newData[i] = this.get(i);
            }
            for(i in newData) {
                if(newData[i] === null || newData[i] === undefined)
                    delete newData[i];
            }
            if(newData.name !== undefined) name = newData.name;
            delete newData.name;
            this.setName(name);
        }
        this._setData({
            _saving: true
        });
        baseAPI.postData({
            uid: uid,
            storage: this.storage,
            ring: this.ring,
            ver: ver,
            pos: name,
            data: newData
        }, function(err, resp) {
            this._setData({
                _saving: false,
                ver: ver,
                author: resp.author,
                data: err? this.data : newData,
                error: err
            })._refresh();
            if(!err) {
                this._inp = null;
                if(this.isRoot()) {
                    Application.siteInfo.title = this.get('title');
                    delete localStorage.siteInfo;
                }
                if(this._isNew) {
                    this._isNew = false;
                    if(parent) {
                        (parent._children || (parent._children = [])).unshift(this);
                        //todo: search position in _children by init.pos
                    }
                }
            }
            fn && fn(err, resp);
        }.bind(this));
        return this._refresh();
    },

    isRoot: function(){
        return this.host === Application.siteInfo.host
            && this.path === "/";
    },

    isNew: function(){
        return this._isNew;
    },

    isLoading: function(){
        return !!this._loading;
    },

    isLoaded: function(){
        return this.data !== null;
    },

    isRemoved: function(){
        return this.data === "";
    },

    isActive: function(){
        return this.host === Application.siteInfo.host
            && (location.pathname+"/").substr(0, this.path.length) === this.path;
    },

    isEditable: function(){
        return this.isLoaded() && this.author && this.author.isMe;
    },

    isAvailableToAdd: function() {
        var author = this.author, access = this.get("access") || "self";
        if(!author) return false;
        return author.isMe
            || access == "all"
            || access == "reg" && author.signed
            || access.split(",").indexOf(author.aid) > -1;
    },

    toString: function(){
        return this.get("title") || this.get("subject") || (this.error? '#ERROR{'+this.error+'}' : null) || this.name;
    },

    parent: function() {
        return !this.isRoot() && _newElement(this.path.replace(/[^\/]*\/$/, ""), this.host);
    },

    getChildStreamInfo: function() {
        var access = this.get("access")||"self";
        var strg = (access=="self"? "D" : "P") + Application.siteInfo.ring;  // <storage:CHAR><ring:int>
        return {
            uid: this.host + this.path,
            access: access,
            aid: /^[0-9a-zA-Z\-_]{20}$/.test(access)? access : this.author && this.author.aid || Application.siteInfo.owner,
            storage: strg.match(/^[A-Z]+/)[0],
            ring: strg.match(/[0-9]+/)[0]|0
        }
    },

    children: function() {
        if(this._children) return this._children;
        if(!this.isLoaded()) return [];
        this._children = [];
        var streamInf = this.getChildStreamInfo();
        var req = {
            cmd:     "top",
            uid:     streamInf.uid,
            aid:     streamInf.aid,
            ring:    streamInf.ring,
            storage: streamInf.storage,
            sse:     Application.element() === this
        };
        baseAPI.requestData(req, function(err, packs) {
            var isSSE = err === "sse-updates";
            if(err && !isSSE) return {error: err};
            if(isSSE && this._children) {
                // remove added elements (elements without hash)
                this._children = this._children.filter(function(e){
                    return e.hash && e;
                });
            }
            this._children = packs.map(function(pack){
                return _newElement(this.path + encodeURIComponent(pack.pos), this.host, pack);
            }.bind(this)).concat(this._children);
            this._refresh();
        }.bind(this));
        return this._children;
    },

    datetime: function() {
        var t = String(this.name).match(/^(20\d\d)([01]\d)([0-3]\d)([0-2]\d)([0-5]\d)([0-5]\d)\d\d\d$/);
        if(t) return [t[1],"-",t[2],"-",t[3]," ",t[4],":",t[5],":",t[6]].join("");
    },

    get: function(name) {
        if(!this.isLoaded()) {
            this.load();
            return null;
        }
        var parts = name.split('|'), val;
        if(parts.length > 1) {
            while(parts.length) {
                if(val = this.get(parts.shift())) return val;
            }
            return null;
        }
        if(this._inp && this._inp[name] !== undefined) {
            val = this._inp[name];
            if(val instanceof Function) return val.call(this);
            return val;
        }
        return this.data[name] !== undefined && this.data[name]
            || this[name] !== undefined && !(this[name] instanceof Function) && this[name]
            || null;
    },

    set: function(name, value) {
        if(arguments.length === 1) {
            for(var i in name) this.set(i, name[i]);
        } else {
            if(name === "pos") name = "name";
            this._inp = this._inp || {};
            this._inp[name] = value;
        }
        return this;
    },

    reset: function() {
        this._inp = {};
        return this;
    },

    setName: function(name) {
        this.name = name;
        this.path = (this.parent() || {path: ""}).path + encodeURIComponent(name) + "/";
        return this;
    },

    newChildElement: function(name) {
        // new element. (empty name is possible)
        var element = new Element(this.path + encodeURIComponent(name||"") + "/", this.host);
        var streamInf = this.getChildStreamInfo();
        element.storage = streamInf.storage;
        element.ring = streamInf.ring;
        element.data = {};
        element._isNew = true;
        return element;
    },

    load: function(fn) {
        if(this.isLoaded()) {
            fn && fn(this);
            return this;
        }
        if(this._loading) {
            this._loading.push(fn);
            return this;
        }
        this._loading = [];
        if(fn) this._loading.push(fn);

        var parent = this.parent();
        var onParentLoaded = function(){
            if(this.error = parent && parent.error) {
                return this._refresh();
            }
            var strmInf = parent? parent.getChildStreamInfo() : Application.siteInfo;
            var req = {
                cmd: "doc", // load single document
                ring: strmInf.ring,
                storage: strmInf.storage,
                aid: strmInf.aid || strmInf.owner,
                uid: strmInf.uid || strmInf.host,
                pos: this.name,
                limit: 1
            };
            baseAPI.requestData(req, function(err, packs) {
                err = err || !packs.length && 'Not found ' + this.uri();
                this._setData(err? { error: err } : packs[0]);

                // callbacks
                while(this._loading.length) setTimeout(this._loading.shift());
                this._loading = false;
                return this._refresh();
            }.bind(this));
        }.bind(this);

        if(!parent) {
            onParentLoaded();
            //if(!parent) return _upd();
        } else {
            if(parent._children) {
                //todo: search in children
            }
            parent.load(onParentLoaded);
        }
        return this;
    },

    _refresh: function() {
        this.data && this.author && setTimeout(Application.onElementUpdate.bind(application, this));
    },

    _setData: function(pack) {
        if(pack.pos !== undefined) { // .name is synonym of .pos
            this.name = pack.pos;
            delete pack.pos;
        }
        ex(this, pack);
        if(this.isRemoved()) { // deleted
            this.title = "*[REMOVED]*";
            // remove element from parent.children
            var par = this.parent(), children = par && par._children;
            if(children)
            for(var i in children)
                if(children[i] === this) {
                    delete children[i];
                    break;
                }
            par._refresh();
        }
        this.key = _key++;
        return this;
    }
});

return _newElement;
})();<|endoftext|>


<commit_before>// Track main navbar links
mixpanel.track_links("#main-gl-nav a", "click nav link", {
  "referrer": document.referrer
});

mixpanel.track_links("#landing-cta a", "click landing page CTA link", {
  "referrer": document.referrer
});
<commit_msg>track subscription orders<commit_after>mixpanel.track_links("#order-plus", "Clicked Order Plus", {
  "referrer": document.referrer
});

mixpanel.track_links("#order-standard", "Clicked Order Standard", {
  "referrer": document.referrer
});

mixpanel.track_links("#order-basic", "Clicked Order Basic", {
  "referrer": document.referrer
});
<|endoftext|>


<commit_before>'use strict'
const PORT = 12346
const domain = require('domain')
const {test} = require('tap')
const net = require('net')
const dgram = require('dgram')
const fs = require('fs')
const tracer = require('../')('/dev/null', {suffix: {some: 'data'}, prefix: {other: 'data'}})
const {parse} = JSON
const fivePlus = process.versions.node[0] === '6' || process.versions.node[0] === '5'
const fiveTenPlus = fivePlus && +process.versions.node[2] >= 10
console.log('BOaua', fiveTenPlus)
fs.write = (f, s, cb) => {
  checker(f, s)
  cb()
}

const checker = (f, s) => {
  let fn = checker.q.shift()
  if (fn) { fn(s) }
}
checker.q = []

const check = (fn) => {
  if (Array.isArray(fn)) {
    checker.q.push.apply(checker.q, fn)
    return
  }
  checker.q.push(fn)
}

test('net', ({is, end}) => {

  process.nextTick(() => {
    const server = net.createServer((s) => {
      s.end()
      server.close()
    })

    server.listen(PORT)

    process.nextTick(() => {
      const client = net.connect(PORT)

      client.end('meow')
    })
  })

  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
      end()
    }
  ])
})

test('setTimeout', ({is, end}) => {
  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'destroy')
      end()
    }
  ])
  process.nextTick(() => setTimeout(() => {}))
})

if (fiveTenPlus) {
  test('threw', ({is, teardown, end}) => {
    check([
      null,
      null,
      (s) => {
        const {op, phase, threw} = parse(s)
        is(op, 'TIMER')
        is(phase, 'post')
        is(threw, true)
        end()
      }
    ])

    process.nextTick(() =>
      domain.create()
        .on('error', () => {})
        .run(() => {
          setTimeout(() => {
            throw Error()
          })
        })
    )
  })
}

test('dgram', ({is, end}) => {
  process.nextTick(() => {
    const server = dgram.createSocket('udp4')
    server.bind(PORT)
    server.close()
  })

  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'UDP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'UDP')
      is(phase, 'destroy')
      end()
    }
  ])

})

test('fs', ({is, end}) => {
  process.nextTick(() => {
    fs.stat('/dev/random', () => { })
  })

  check([
    null, //ignore stray timer op in 5+
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'destroy')
      end()
    }
  ].slice(fiveTenPlus ? 0 : 1))

})

test('prefix & suffix', ({is, end}) => {
  check([
    (s) => {
      const {some, other} = parse(s)
      is(some, 'data')
      is(other, 'data')
      end()
    }
  ])

  process.nextTick(() => {
    setTimeout(()=> {})
  })

})

<commit_msg>stray log<commit_after>'use strict'
const PORT = 12346
const domain = require('domain')
const {test} = require('tap')
const net = require('net')
const dgram = require('dgram')
const fs = require('fs')
const tracer = require('../')('/dev/null', {suffix: {some: 'data'}, prefix: {other: 'data'}})
const {parse} = JSON
const fivePlus = process.versions.node[0] === '6' || process.versions.node[0] === '5'
const fiveTenPlus = fivePlus && +process.versions.node[2] >= 10

fs.write = (f, s, cb) => {
  checker(f, s)
  cb()
}

const checker = (f, s) => {
  let fn = checker.q.shift()
  if (fn) { fn(s) }
}
checker.q = []

const check = (fn) => {
  if (Array.isArray(fn)) {
    checker.q.push.apply(checker.q, fn)
    return
  }
  checker.q.push(fn)
}

test('net', ({is, end}) => {

  process.nextTick(() => {
    const server = net.createServer((s) => {
      s.end()
      server.close()
    })

    server.listen(PORT)

    process.nextTick(() => {
      const client = net.connect(PORT)

      client.end('meow')
    })
  })

  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'GETADDRINFOREQ')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCPCONNECT')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'SHUTDOWN')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TCP')
      is(phase, 'destroy')
      end()
    }
  ])
})

test('setTimeout', ({is, end}) => {
  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'TIMER')
      is(phase, 'destroy')
      end()
    }
  ])
  process.nextTick(() => setTimeout(() => {}))
})

if (fiveTenPlus) {
  test('threw', ({is, teardown, end}) => {
    check([
      null,
      null,
      (s) => {
        const {op, phase, threw} = parse(s)
        is(op, 'TIMER')
        is(phase, 'post')
        is(threw, true)
        end()
      }
    ])

    process.nextTick(() =>
      domain.create()
        .on('error', () => {})
        .run(() => {
          setTimeout(() => {
            throw Error()
          })
        })
    )
  })
}

test('dgram', ({is, end}) => {
  process.nextTick(() => {
    const server = dgram.createSocket('udp4')
    server.bind(PORT)
    server.close()
  })

  check([
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'UDP')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'UDP')
      is(phase, 'destroy')
      end()
    }
  ])

})

test('fs', ({is, end}) => {
  process.nextTick(() => {
    fs.stat('/dev/random', () => { })
  })

  check([
    null, //ignore stray timer op in 5+
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'init')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'pre')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'post')
    },
    (s) => {
      const {op, phase} = parse(s)
      is(op, 'FSREQ')
      is(phase, 'destroy')
      end()
    }
  ].slice(fiveTenPlus ? 0 : 1))

})

test('prefix & suffix', ({is, end}) => {
  check([
    (s) => {
      const {some, other} = parse(s)
      is(some, 'data')
      is(other, 'data')
      end()
    }
  ])

  process.nextTick(() => {
    setTimeout(()=> {})
  })

})

<|endoftext|>


<commit_before>/**
 * Copyright 2005-2011 MERETHIS
 * Centreon is developped by : Julien Mathis and Romain Le Merlus under
 * GPL Licence 2.0.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation ; either version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, see <http://www.gnu.org/licenses>.
 *
 * Linking this program statically or dynamically with other modules is making a
 * combined work based on this program. Thus, the terms and conditions of the GNU
 * General Public License cover the whole combination.
 *
 * As a special exception, the copyright holders of this program give MERETHIS
 * permission to link this program with independent modules to produce an executable,
 * regardless of the license terms of these independent modules, and to copy and
 * distribute the resulting executable under terms of MERETHIS choice, provided that
 * MERETHIS also meet, for each linked independent module, the terms  and conditions
 * of the license of that module. An independent module is a module which is not
 * derived from this program. If you modify this program, you may extend this
 * exception to your version of the program, but you are not obliged to do so. If you
 * do not wish to do so, delete this exception statement from your version.
 *
 * For more information : contact@centreon.com
 *
 */

/**
 * Load Page
 */
function loadPage()
{
    jQuery.ajax("./src/index.php?widgetId=" + widgetId + "&page=" + pageNumber, {
        success: function (htmlData) {
            jQuery("#hostMonitoringTable").empty().append(htmlData).append(function() {
                var h = jQuery("hostMonitoringTable").prop("scrollHeight");
                parent.iResize(window.name, h);
            });
            jQuery('.checkall').on('change', function() {
                var chck = this.checked;
                $(this).parents().find(':checkbox').each(function () {
                    $(this).prop('checked', chck);
                    clickedCb[$(this).attr('id')] = chck;
                });
            });
        }
    });
    if (autoRefresh) {
        if (timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(loadPage, (autoRefresh * 1000));
    }
}

/*
 * Load toolbar
 */
function loadToolBar()
{
    jQuery("#toolBar").load("./src/toolbar.php",{widgetId: widgetId});
}

jQuery(function () {
    loadToolBar();
    loadPage();
});
<commit_msg>fix(jQuery): missing #<commit_after>/**
 * Copyright 2005-2011 MERETHIS
 * Centreon is developped by : Julien Mathis and Romain Le Merlus under
 * GPL Licence 2.0.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation ; either version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, see <http://www.gnu.org/licenses>.
 *
 * Linking this program statically or dynamically with other modules is making a
 * combined work based on this program. Thus, the terms and conditions of the GNU
 * General Public License cover the whole combination.
 *
 * As a special exception, the copyright holders of this program give MERETHIS
 * permission to link this program with independent modules to produce an executable,
 * regardless of the license terms of these independent modules, and to copy and
 * distribute the resulting executable under terms of MERETHIS choice, provided that
 * MERETHIS also meet, for each linked independent module, the terms  and conditions
 * of the license of that module. An independent module is a module which is not
 * derived from this program. If you modify this program, you may extend this
 * exception to your version of the program, but you are not obliged to do so. If you
 * do not wish to do so, delete this exception statement from your version.
 *
 * For more information : contact@centreon.com
 *
 */

/**
 * Load Page
 */
function loadPage()
{
    jQuery.ajax("./src/index.php?widgetId=" + widgetId + "&page=" + pageNumber, {
        success: function (htmlData) {
            jQuery("#hostMonitoringTable").empty().append(htmlData).append(function() {
                var h = jQuery("#hostMonitoringTable").prop("scrollHeight");
                parent.iResize(window.name, h);
            });
            jQuery('.checkall').on('change', function() {
                var chck = this.checked;
                $(this).parents().find(':checkbox').each(function () {
                    $(this).prop('checked', chck);
                    clickedCb[$(this).attr('id')] = chck;
                });
            });
        }
    });
    if (autoRefresh) {
        if (timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(loadPage, (autoRefresh * 1000));
    }
}

/*
 * Load toolbar
 */
function loadToolBar()
{
    jQuery("#toolBar").load("./src/toolbar.php",{widgetId: widgetId});
}

jQuery(function () {
    loadToolBar();
    loadPage();
});
<|endoftext|>


<commit_before>const { exec, spawn } = require('child_process');

class Execute {
  static run(fullCmd) {
    return new Promise((resolve, reject) => {
    exec(fullCmd, (error, stdout, stderr) => {
      if (stderr || error) {
        reject(stderr || error);
      }
      resolve(stdout);
    });
  });
  }

  static cmd(base, params) {
    if (!params && base) {
    return base;
  }
  if (params.constructor !== Array) {
    throw new Error('params must be an Array');
  }

  return base + ' ' + params.join(' ');
  }
}

class Spawn {
  static run(cmd, params) {
    const child = spawn(cmd, params);
    return child;
  }
}

module.exports = {
  Execute,
  Spawn
};
<commit_msg>Minor refactor of Execute.js<commit_after>const { exec, spawn } = require('child_process');

class Execute {
  static run(fullCmd) {
    return new Promise((resolve, reject) => {
      exec(fullCmd, (error, stdout, stderr) => {
        if (error) {
          console.log(`Error in exec: ${ error }`);
          // throw error;
        }

        if (stderr) {
          reject(stderr);
        }
        if (stdout) {
          resolve(stdout);
        }
      });
    });
  }

  static cmd(base, params) {
    if (!params && base) {
    return base;
  }
  if (params.constructor !== Array) {
    throw new Error('params must be an Array');
  }

  return base + ' ' + params.join(' ');
  }
}

class Spawn {
  static run(cmd, params) {
    return spawn(cmd, params);
  }
}

module.exports = {
  Execute,
  Spawn
};
<|endoftext|>


<commit_before>var mineflayer = require('../')
  , vec3 = mineflayer.vec3
  , mc = require('minecraft-protocol')
  , assert = require('assert')
  , zlib = require('zlib')

describe("mineflayer", function() {
  it("chat", function(done) {
    var server = mc.createServer({ 'online-mode': false } );
    server.on('listening', function() {
      var bot = mineflayer.createBot({
        username: "player",
      });
      bot.on('chat', function(username, message) {
        assert.strictEqual(username, "gary");
        assert.strictEqual(message, "hello");
        bot.chat("hi");
      });
      bot.on('end', done);
      server.on('login', function(client) {
        client.write(0x03, { message: "<gary> hello" } );
        client.on(0x03, function(packet) {
          assert.strictEqual(packet.message, "hi");
          server.close();
        });
      });
    });
  });
  it("blockAt", function(done) {
    var server = mc.createServer({ 'online-mode': false } );
    var pos = vec3(1, 65, 1);
    var goldId = 41;
    server.on('listening', function() {
      var bot = mineflayer.createBot({
        username: "player",
      });
      bot.on('chunkColumnLoad', function(columnPoint) {
        assert.strictEqual(columnPoint.x, 0);
        assert.strictEqual(columnPoint.z, 0);
        assert.strictEqual(bot.blockAt(pos).type, goldId);
        server.close();
      });
      bot.on('end', done);
      server.on('login', function(client) {
        var buffer = new Buffer((4096 + 2048 + 2048 + 2048) * 4 + 256);
        buffer.fill(0);
        buffer.writeUInt8(goldId, 8192 + 273);
        zlib.deflate(buffer, function(err, compressed) {
          assert.ifError(err);
          client.write(0x33, {
            x: 0,
            z: 0,
            groundUp: true,
            bitMap: parseInt('00111100', 2),
            addBitMap: 0,
            compressedChunkData: compressed,
          });
        });
      });
    });
  });
});
<commit_msg>refactor tests<commit_after>var mineflayer = require('../')
  , vec3 = mineflayer.vec3
  , mc = require('minecraft-protocol')
  , assert = require('assert')
  , zlib = require('zlib')

describe("mineflayer", function() {
  var bot, server;
  beforeEach(function(done) {
    server = mc.createServer({ 'online-mode': false } );
    server.on('listening', function() {
      bot = mineflayer.createBot({
        username: "player",
      });
      done();
    });
  });
  afterEach(function(done) {
    bot.on('end', done);
    server.close();
  });
  it("chat", function(done) {
    bot.on('chat', function(username, message) {
      assert.strictEqual(username, "gary");
      assert.strictEqual(message, "hello");
      bot.chat("hi");
    });
    server.on('login', function(client) {
      client.write(0x03, { message: "<gary> hello" } );
      client.on(0x03, function(packet) {
        assert.strictEqual(packet.message, "hi");
        done();
      });
    });
  });
  it("blockAt", function(done) {
    var pos = vec3(1, 65, 1);
    var goldId = 41;
    bot.on('chunkColumnLoad', function(columnPoint) {
      assert.strictEqual(columnPoint.x, 0);
      assert.strictEqual(columnPoint.z, 0);
      assert.strictEqual(bot.blockAt(pos).type, goldId);
      done();
    });
    server.on('login', function(client) {
      var buffer = new Buffer((4096 + 2048 + 2048 + 2048) * 4 + 256);
      buffer.fill(0);
      buffer.writeUInt8(goldId, 8192 + 273);
      zlib.deflate(buffer, function(err, compressed) {
        assert.ifError(err);
        client.write(0x33, {
          x: 0,
          z: 0,
          groundUp: true,
          bitMap: parseInt('00111100', 2),
          addBitMap: 0,
          compressedChunkData: compressed,
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * User-agent detection
 */
( function ( $ ) {

	/* Private Members */

	/**
	 * @var profileCache {Object} Keyed by userAgent string,
	 * value is the parsed $.client.profile object for that user agent.
	 */
	var profileCache = {};

	/* Public Methods */

	$.client = {

		/**
		 * Get an object containing information about the client.
		 *
		 * @param nav {Object} An object with atleast a 'userAgent' and 'platform' key.
		 * Defaults to the global Navigator object.
		 * @return {Object} The resulting client object will be in the following format:
		 *  {
		 *   'name': 'firefox',
		 *   'layout': 'gecko',
		 *   'layoutVersion': 20101026,
		 *   'platform': 'linux'
		 *   'version': '3.5.1',
		 *   'versionBase': '3',
		 *   'versionNumber': 3.5,
		 *  }
		 */
		profile: function ( nav ) {
			/*jshint boss: true */

			if ( nav === undefined ) {
				nav = window.navigator;
			}
			// Use the cached version if possible
			if ( profileCache[nav.userAgent] === undefined ) {

				var
					versionNumber,

					/* Configuration */

					// Name of browsers or layout engines we don't recognize
					uk = 'unknown',
					// Generic version digit
					x = 'x',
					// Strings found in user agent strings that need to be conformed
					wildUserAgents = ['Opera', 'Navigator', 'Minefield', 'KHTML', 'Chrome', 'PLAYSTATION 3'],
					// Translations for conforming user agent strings
					userAgentTranslations = [
						// Tons of browsers lie about being something they are not
						[/(Firefox|MSIE|KHTML,\slike\sGecko|Konqueror)/, ''],
						// Chrome lives in the shadow of Safari still
						['Chrome Safari', 'Chrome'],
						// KHTML is the layout engine not the browser - LIES!
						['KHTML', 'Konqueror'],
						// Firefox nightly builds
						['Minefield', 'Firefox'],
						// This helps keep differnt versions consistent
						['Navigator', 'Netscape'],
						// This prevents version extraction issues, otherwise translation would happen later
						['PLAYSTATION 3', 'PS3']
					],
					// Strings which precede a version number in a user agent string - combined and used as match 1 in
					// version detectection
					versionPrefixes = [
						'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'netscape6', 'opera', 'version', 'konqueror',
						'lynx', 'msie', 'safari', 'ps3'
					],
					// Used as matches 2, 3 and 4 in version extraction - 3 is used as actual version number
					versionSuffix = '(\\/|\\;?\\s|)([a-z0-9\\.\\+]*?)(\\;|dev|rel|\\)|\\s|$)',
					// Names of known browsers
					names = [
						'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'konqueror', 'lynx', 'msie', 'opera',
						'safari', 'ipod', 'iphone', 'blackberry', 'ps3', 'rekonq'
					],
					// Tanslations for conforming browser names
					nameTranslations = [],
					// Names of known layout engines
					layouts = ['gecko', 'konqueror', 'msie', 'opera', 'webkit'],
					// Translations for conforming layout names
					layoutTranslations = [ ['konqueror', 'khtml'], ['msie', 'trident'], ['opera', 'presto'] ],
					// Names of supported layout engines for version number
					layoutVersions = ['applewebkit', 'gecko'],
					// Names of known operating systems
					platforms = ['win', 'mac', 'linux', 'sunos', 'solaris', 'iphone'],
					// Translations for conforming operating system names
					platformTranslations = [ ['sunos', 'solaris'] ],

					/* Methods */

					/**
					 * Performs multiple replacements on a string
					 */
					translate = function ( source, translations ) {
						var i;
						for ( i = 0; i < translations.length; i++ ) {
							source = source.replace( translations[i][0], translations[i][1] );
						}
						return source;
					},

					/* Pre-processing */

					ua = nav.userAgent,
					match,
					name = uk,
					layout = uk,
					layoutversion = uk,
					platform = uk,
					version = x;

				if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
					// Takes a userAgent string and translates given text into something we can more easily work with
					ua = translate( ua, userAgentTranslations );
				}
				// Everything will be in lowercase from now on
				ua = ua.toLowerCase();

				/* Extraction */

				if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
					name = translate( match[1], nameTranslations );
				}
				if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
					layout = translate( match[1], layoutTranslations );
				}
				if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
					layoutversion = parseInt( match[2], 10 );
				}
				if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
					platform = translate( match[1], platformTranslations );
				}
				if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
					version = match[3];
				}

				/* Edge Cases -- did I mention about how user agent string lie? */

				// Decode Safari's crazy 400+ version numbers
				if ( name.match( /safari/ ) && version > 400 ) {
					version = '2.0';
				}
				// Expose Opera 10's lies about being Opera 9.8
				if ( name === 'opera' && version >= 9.8) {
					match = ua.match( /version\/([0-9\.]*)/i );
					if ( match && match[1] ) {
						version = match[1];
					} else {
						version = '10';
					}
				}
				versionNumber = parseFloat( version, 10 ) || 0.0;

				/* Caching */

				profileCache[nav.userAgent] = {
					name: name,
					layout: layout,
					layoutVersion: layoutversion,
					platform: platform,
					version: version,
					versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ),
					versionNumber: versionNumber
				};
			}
			return profileCache[nav.userAgent];
		},

		/**
		 * Checks the current browser against a support map object to determine if the browser has been black-listed or
		 * not. If the browser was not configured specifically it is assumed to work. It is assumed that the body
		 * element is classified as either "ltr" or "rtl". If neither is set, "ltr" is assumed.
		 *
		 * A browser map is in the following format:
		 * {
		 *   'ltr': {
		 *     // Multiple rules with configurable operators
		 *     'msie': [['>=', 7], ['!=', 9]],
		 *      // Blocked entirely
		 *     'iphone': false
		 *   },
		 *   'rtl': {
		 *     // Test against a string
		 *     'msie': [['!==', '8.1.2.3']],
		 *     // RTL rules do not fall through to LTR rules, you must explicity set each of them
		 *     'iphone': false
		 *   }
		 * }
		 *
		 * @param map {Object} Browser support map
		 * @param profile {Object} (optional) a client-profile object.
		 *
		 * @return Boolean true if browser known or assumed to be supported, false if blacklisted
		 */
		test: function ( map, profile ) {
			/*jshint evil: true */

			var conditions, dir, i, op, val;
			profile = $.isPlainObject( profile ) ? profile : $.client.profile();
			dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
			// Check over each browser condition to determine if we are running in a compatible client
			if ( typeof map[dir] !== 'object' || map[dir][profile.name] === undefined ) {
				// Unknown, so we assume it's working
				return true;
			}
			conditions = map[dir][profile.name];
			if ( conditions === false ) {
				return false;
			}
			for ( i = 0; i < conditions.length; i++ ) {
				op = conditions[i][0];
				val = conditions[i][1];
				if ( typeof val === 'string' ) {
					if ( !( eval( 'profile.version' + op + '"' + val + '"' ) ) ) {
						return false;
					}
				} else if ( typeof val === 'number' ) {
					if ( !( eval( 'profile.versionNumber' + op + val ) ) ) {
						return false;
					}
				}
			}

			return true;
		}
	};
}( jQuery ) );
<commit_msg>Fix profile of some UAs and add exactMatchOnly param<commit_after>/**
 * User-agent detection
 */
( function ( $ ) {

	/* Private Members */

	/**
	 * @var {Object} profileCache Keyed by userAgent string,
	 * value is the parsed $.client.profile object for that user agent.
	 */
	var profileCache = {};

	/* Public Methods */

	$.client = {

		/**
		 * Get an object containing information about the client.
		 *
		 * @param {Object} nav An object with atleast a 'userAgent' and 'platform' key.
		 * Defaults to the global Navigator object.
		 * @returns {Object} The resulting client object will be in the following format:
		 *  {
		 *   'name': 'firefox',
		 *   'layout': 'gecko',
		 *   'layoutVersion': 20101026,
		 *   'platform': 'linux'
		 *   'version': '3.5.1',
		 *   'versionBase': '3',
		 *   'versionNumber': 3.5,
		 *  }
		 */
		profile: function ( nav ) {
			/*jshint boss: true */

			if ( nav === undefined ) {
				nav = window.navigator;
			}
			// Use the cached version if possible
			if ( profileCache[nav.userAgent] === undefined ) {

				var
					versionNumber,

					/* Configuration */

					// Name of browsers or layout engines we don't recognize
					uk = 'unknown',
					// Generic version digit
					x = 'x',
					// Strings found in user agent strings that need to be conformed
					wildUserAgents = ['Opera', 'Navigator', 'Minefield', 'KHTML', 'Chrome', 'PLAYSTATION 3', 'Iceweasel'],
					// Translations for conforming user agent strings
					userAgentTranslations = [
						// Tons of browsers lie about being something they are not
						[/(Firefox|MSIE|KHTML,?\slike\sGecko|Konqueror)/, ''],
						// Chrome lives in the shadow of Safari still
						['Chrome Safari', 'Chrome'],
						// KHTML is the layout engine not the browser - LIES!
						['KHTML', 'Konqueror'],
						// Firefox nightly builds
						['Minefield', 'Firefox'],
						// This helps keep differnt versions consistent
						['Navigator', 'Netscape'],
						// This prevents version extraction issues, otherwise translation would happen later
						['PLAYSTATION 3', 'PS3']
					],
					// Strings which precede a version number in a user agent string - combined and used as match 1 in
					// version detectection
					versionPrefixes = [
						'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'netscape6', 'opera', 'version', 'konqueror',
						'lynx', 'msie', 'safari', 'ps3', 'android'
					],
					// Used as matches 2, 3 and 4 in version extraction - 3 is used as actual version number
					versionSuffix = '(\\/|\\;?\\s|)([a-z0-9\\.\\+]*?)(\\;|dev|rel|\\)|\\s|$)',
					// Names of known browsers
					names = [
						'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'konqueror', 'lynx', 'msie', 'opera',
						'safari', 'ipod', 'iphone', 'blackberry', 'ps3', 'rekonq', 'android'
					],
					// Tanslations for conforming browser names
					nameTranslations = [],
					// Names of known layout engines
					layouts = ['gecko', 'konqueror', 'msie', 'opera', 'webkit'],
					// Translations for conforming layout names
					layoutTranslations = [ ['konqueror', 'khtml'], ['msie', 'trident'], ['opera', 'presto'] ],
					// Names of supported layout engines for version number
					layoutVersions = ['applewebkit', 'gecko'],
					// Names of known operating systems
					platforms = ['win', 'mac', 'linux', 'sunos', 'solaris', 'iphone'],
					// Translations for conforming operating system names
					platformTranslations = [ ['sunos', 'solaris'] ],

					/* Methods */

					/**
					 * Performs multiple replacements on a string
					 */
					translate = function ( source, translations ) {
						var i;
						for ( i = 0; i < translations.length; i++ ) {
							source = source.replace( translations[i][0], translations[i][1] );
						}
						return source;
					},

					/* Pre-processing */

					ua = nav.userAgent,
					match,
					name = uk,
					layout = uk,
					layoutversion = uk,
					platform = uk,
					version = x;

				if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
					// Takes a userAgent string and translates given text into something we can more easily work with
					ua = translate( ua, userAgentTranslations );
				}
				// Everything will be in lowercase from now on
				ua = ua.toLowerCase();

				/* Extraction */

				if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
					name = translate( match[1], nameTranslations );
				}
				if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
					layout = translate( match[1], layoutTranslations );
				}
				if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
					layoutversion = parseInt( match[2], 10 );
				}
				if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
					platform = translate( match[1], platformTranslations );
				}
				if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
					version = match[3];
				}

				/* Edge Cases -- did I mention about how user agent string lie? */

				// Decode Safari's crazy 400+ version numbers
				if ( name.match( /safari/ ) && version > 400 ) {
					version = '2.0';
				}
				// Expose Opera 10's lies about being Opera 9.8
				if ( name === 'opera' && version >= 9.8) {
					match = ua.match( /version\/([0-9\.]*)/i );
					if ( match && match[1] ) {
						version = match[1];
					} else {
						version = '10';
					}
				}
				versionNumber = parseFloat( version, 10 ) || 0.0;

				/* Caching */

				profileCache[nav.userAgent] = {
					name: name,
					layout: layout,
					layoutVersion: layoutversion,
					platform: platform,
					version: version,
					versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ),
					versionNumber: versionNumber
				};
			}
			return profileCache[nav.userAgent];
		},

		/**
		 * Checks the current browser against a support map object.
		 *
		 * A browser map is in the following format:
		 * {
		 *   // Multiple rules with configurable operators
		 *   'msie': [['>=', 7], ['!=', 9]],
		 *    // Match no versions
		 *   'iphone': false,
		 *    // Match any version
		 *   'android': null
		 * }
		 *
		 * It can optionally be split into ltr/rtl sections:
		 * {
		 *   'ltr': {
		 *     'android': null,
		 *     'iphone': false
		 *   },
		 *   'rtl': {
		 *     'android': false,
		 *     // rules are not inherited from ltr
		 *     'iphone': false
		 *   }
		 * }
		 *
		 * @param {Object} map Browser support map
		 * @param {Object} [profile] A client-profile object
		 * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, otherwise
		 * returns true if the browser is not found.
		 *
		 * @returns {boolean} The current browser is in the support map
		 */
		test: function ( map, profile, exactMatchOnly ) {
			/*jshint evil: true */

			var conditions, dir, i, op, val;
			profile = $.isPlainObject( profile ) ? profile : $.client.profile();
			if ( map.ltr && map.rtl ) {
				dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
				map = map[dir];
			}
			// Check over each browser condition to determine if we are running in a compatible client
			if ( typeof map !== 'object' || map[profile.name] === undefined ) {
				// Not found, return true if exactMatchOnly not set, false otherwise
				return !exactMatchOnly;
			}
			conditions = map[profile.name];
			if ( conditions === false ) {
				// Match no versions
				return false;
			}
			if ( conditions === null ) {
				// Match all versions
				return true;
			}
			for ( i = 0; i < conditions.length; i++ ) {
				op = conditions[i][0];
				val = conditions[i][1];
				if ( typeof val === 'string' ) {
					if ( !( eval( 'profile.version' + op + '"' + val + '"' ) ) ) {
						return false;
					}
				} else if ( typeof val === 'number' ) {
					if ( !( eval( 'profile.versionNumber' + op + val ) ) ) {
						return false;
					}
				}
			}

			return true;
		}
	};
}( jQuery ) );
<|endoftext|>


<commit_before>'use strict';

require('mocha');
var assert = require('assert');
var co = require('co');
var AsyncHelpers = require('../');
var asyncHelpers = null;

describe('async-helpers', function() {
  beforeEach(function() {
    AsyncHelpers.globalCounter = 0;
    asyncHelpers = new AsyncHelpers();
  });

  describe('set', function() {
    it('should set a sync helper', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert(typeof asyncHelpers.helpers.upper !== 'undefined', 'upper should be defined on `helpers`');
      assert.deepEqual(asyncHelpers.helpers.upper.toString(), upper.toString());
    });

    it('should set an async helper', function() {
      var upper = function(str, cb) {
        cb(null, str.toUpperCase());
      };
      upper.async = true;
      asyncHelpers.set('upper', upper);
      assert(typeof asyncHelpers.helpers.upper !== 'undefined', 'upper should be defined on `helpers`');
      assert(asyncHelpers.helpers.upper.async);
    });
  });

  describe('get', function() {
    it('should get the helper as is', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper').toString(), upper.toString());
    });

    it('should get a wrapped helper', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.notEqual(asyncHelpers.get('upper', { wrap: true }).toString(), upper.toString());
    });
  });

  describe('helpers', function() {
    it('should return actual value when not wrapped', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper')('doowb'), 'DOOWB');
    });

    it('should return an async id when wrapped', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper', { wrap: true })('doowb'), '{$ASYNCID$0$0$}');
    });

    it('should increment globalCounter for multiple instances of AsyncHelpers', function() {
      var asyncHelpers2 = new AsyncHelpers();
      assert.notEqual(asyncHelpers.globalCounter, asyncHelpers2.globalCounter);
      assert.equal(asyncHelpers.globalCounter, 0);
      assert.equal(asyncHelpers2.globalCounter, 1);
    });

    it('should return an async id with a custom prefix', function() {
      var asyncHelpers2 = new AsyncHelpers({prefix: '{$custom$prefix$$'});
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers2.set('upper', upper);
      assert.deepEqual(asyncHelpers2.get('upper', { wrap: true })('doowb'), '{$custom$prefix$$1$0$}');
    });

    it('should support helpers that take arrays as an argument', function() {
      var async = require('async');
      // function to use as an iterator
      var upper = function(str, next) {
        next(null, str.toUpperCase());
      };
      // use the async mapSeries function for the helper
      var map = async.mapSeries;
      // make sure asyncHelpers knows this is an async function
      map.async = true;
      asyncHelpers.set('map', map);
      var helper = asyncHelpers.get('map', {wrap: true});

      // call the helper to get the id
      var id = helper(['doowb', 'jonschlinkert'], upper);
      assert.equal(id, '{$ASYNCID$0$0$}');

      // resolveId the id
      return co(asyncHelpers.resolveId(id))
        .then(function(val) {
          assert.deepEqual(val, ['DOOWB', 'JONSCHLINKERT']);
        });
    });

    it('should support helpers used as arguments that return objects', function(done) {
      var profile = function(user, next) {
        if (typeof user !== 'object') {
          return next(new Error('Expected user to be an object but got ' + (typeof user)));
        }
        next(null, user.name);
      };
      profile.async = true;

      var user = function(name, next) {
        var res = {
          id: name,
          name: name
        };
        next(null, res);
      };
      user.async = true;
      asyncHelpers.set('user', user);
      asyncHelpers.set('profile', profile);
      var userHelper = asyncHelpers.get('user', {wrap: true});
      var userId = userHelper('doowb');
      assert.equal(userId, '{$ASYNCID$0$0$}');

      var profileHelper = asyncHelpers.get('profile', {wrap: true});
      var profileId = profileHelper(userId);

      asyncHelpers.resolveIds(profileId, function(err, val) {
        if (err) return done(err);
        assert.deepEqual(val, 'doowb');
        done();
      });
    });
  });

  describe('errors', function() {
    it('should handle errors in sync helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str) {
        throw new Error('UPPER Error');
      };
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle errors in async helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        throw new Error('UPPER Error');
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle returned errors in async helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        next(new Error('UPPER Error'));
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle errors with arguments with circular references', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        throw new Error('UPPER Error');
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var obj = {username: 'doowb'};
      obj.profile = obj;
      var id = helper(obj);
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('Expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });
  });

  describe('wrapHelper', function() {
    it('should return the helper when given the helper name', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      var fn = asyncHelpers.wrapHelper('upper');
      assert.equal(fn, upper);
      assert.deepEqual(fn('doowb'), 'DOOWB');
    });

    it('should return the wrapped helper when given the helper name and wrap option is true', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      var fn = asyncHelpers.wrapHelper('upper', {wrap: true});
      assert.notEqual(fn, upper);
      assert.notEqual(fn.toString(), upper.toString());
      assert.deepEqual(fn('doowb'), '{$ASYNCID$0$0$}');
    });

    it('should return a function when given a function', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      var fn = asyncHelpers.wrapHelper(upper);
      assert.equal(fn, upper);
      assert.deepEqual(fn('doowb'), 'DOOWB');
    });

    it('should return a wrapped function when given a function and wrap option is true', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      var fn = asyncHelpers.wrapHelper(upper, {wrap: true});
      assert.notEqual(fn, upper);
      assert.deepEqual(fn('doowb'), '{$ASYNCID$0$0$}');
    });

    it.skip('should return an object of helpers when given an object of helpers', function() {
      var helpers = {
        upper: function(str) { return str.toUpperCase(); },
        lower: function(str) { return str.toLowerCase(); }
      };
      asyncHelpers.set(helpers);
      var obj = asyncHelpers.wrapHelper();
      assert.deepEqual(obj, helpers);
      assert.equal(obj.upper('doowb'), 'DOOWB');
      assert.equal(obj.lower('DOOWB'), 'doowb');
    });

    it.skip('should return an object of wrapped helpers when given an object of helpers and wrap option is true', function() {
      var helpers = {
        upper: function(str) { return str.toUpperCase(); },
        lower: function(str) { return str.toLowerCase(); }
      };
      asyncHelpers.set(helpers);
      var obj = asyncHelpers.wrapHelper({wrap: true});
      assert.notDeepEqual(obj, helpers);
      assert.equal(obj.upper('doowb'), '{$ASYNCID$0$0$}');
      assert.equal(obj.lower('DOOWB'), '{$ASYNCID$0$1$}');
    });

    it.skip('should return an object of helpers from a helper group', function() {
      var helpers = function() {};
      helpers.isGroup = true;
      helpers.upper = function(str) { return str.toUpperCase(); };
      helpers.lower = function(str) { return str.toLowerCase(); };
      asyncHelpers.set('my-group', helpers);
      var res = asyncHelpers.wrapHelper('my-group');
      console.log(res);
      assert.deepEqual(res, helpers);
      assert.equal(res.upper('doowb'), 'DOOWB');
      assert.equal(res.lower('DOOWB'), 'doowb');
    });
  });

  describe('wrapHelpers', function() {

  });

  describe('wrapper', function() {

  });

  describe('reset', function() {

  });

  describe('matches', function() {

  });

  describe('hasAsyncId', function() {

  });

  describe('resolveId', function() {

  });

  describe('resolveArgs', function() {

  });

  describe('resolveObject', function() {

  });

  describe('resolveIds', function() {

  });
});
<commit_msg>lint tests<commit_after>'use strict';

require('mocha');
var assert = require('assert');
var co = require('co');
var AsyncHelpers = require('../');
var asyncHelpers = null;

describe('async-helpers', function() {
  beforeEach(function() {
    AsyncHelpers.globalCounter = 0;
    asyncHelpers = new AsyncHelpers();
  });

  describe('set', function() {
    it('should set a sync helper', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert(typeof asyncHelpers.helpers.upper !== 'undefined', 'upper should be defined on `helpers`');
      assert.deepEqual(asyncHelpers.helpers.upper.toString(), upper.toString());
    });

    it('should set an async helper', function() {
      var upper = function(str, cb) {
        cb(null, str.toUpperCase());
      };
      upper.async = true;
      asyncHelpers.set('upper', upper);
      assert(typeof asyncHelpers.helpers.upper !== 'undefined', 'upper should be defined on `helpers`');
      assert(asyncHelpers.helpers.upper.async);
    });
  });

  describe('get', function() {
    it('should get the helper as is', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper').toString(), upper.toString());
    });

    it('should get a wrapped helper', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.notEqual(asyncHelpers.get('upper', { wrap: true }).toString(), upper.toString());
    });
  });

  describe('helpers', function() {
    it('should return actual value when not wrapped', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper')('doowb'), 'DOOWB');
    });

    it('should return an async id when wrapped', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      assert.deepEqual(asyncHelpers.get('upper', { wrap: true })('doowb'), '{$ASYNCID$0$0$}');
    });

    it('should increment globalCounter for multiple instances of AsyncHelpers', function() {
      var asyncHelpers2 = new AsyncHelpers();
      assert.notEqual(asyncHelpers.globalCounter, asyncHelpers2.globalCounter);
      assert.equal(asyncHelpers.globalCounter, 0);
      assert.equal(asyncHelpers2.globalCounter, 1);
    });

    it('should return an async id with a custom prefix', function() {
      var asyncHelpers2 = new AsyncHelpers({prefix: '{$custom$prefix$$'});
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers2.set('upper', upper);
      assert.deepEqual(asyncHelpers2.get('upper', { wrap: true })('doowb'), '{$custom$prefix$$1$0$}');
    });

    it('should support helpers that take arrays as an argument', function() {
      var async = require('async');
      // function to use as an iterator
      var upper = function(str, next) {
        next(null, str.toUpperCase());
      };
      // use the async mapSeries function for the helper
      var map = async.mapSeries;
      // make sure asyncHelpers knows this is an async function
      map.async = true;
      asyncHelpers.set('map', map);
      var helper = asyncHelpers.get('map', {wrap: true});

      // call the helper to get the id
      var id = helper(['doowb', 'jonschlinkert'], upper);
      assert.equal(id, '{$ASYNCID$0$0$}');

      // resolveId the id
      return co(asyncHelpers.resolveId(id))
        .then(function(val) {
          assert.deepEqual(val, ['DOOWB', 'JONSCHLINKERT']);
        });
    });

    it('should support helpers used as arguments that return objects', function(done) {
      var profile = function(user, next) {
        if (typeof user !== 'object') {
          return next(new Error('Expected user to be an object but got ' + (typeof user)));
        }
        next(null, user.name);
      };
      profile.async = true;

      var user = function(name, next) {
        var res = {
          id: name,
          name: name
        };
        next(null, res);
      };
      user.async = true;
      asyncHelpers.set('user', user);
      asyncHelpers.set('profile', profile);
      var userHelper = asyncHelpers.get('user', {wrap: true});
      var userId = userHelper('doowb');
      assert.equal(userId, '{$ASYNCID$0$0$}');

      var profileHelper = asyncHelpers.get('profile', {wrap: true});
      var profileId = profileHelper(userId);

      asyncHelpers.resolveIds(profileId, function(err, val) {
        if (err) return done(err);
        assert.deepEqual(val, 'doowb');
        done();
      });
    });
  });

  describe('errors', function() {
    it('should handle errors in sync helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str) {
        throw new Error('UPPER Error');
      };
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          return Promise.reject(new Error('expected an error'));
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle errors in async helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        throw new Error('UPPER Error');
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          return Promise.reject(new Error('expected an error'));
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle returned errors in async helpers', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        next(new Error('UPPER Error'));
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var id = helper('doowb');
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });

    it('should handle errors with arguments with circular references', function() {
      var asyncHelpers3 = new AsyncHelpers();
      var upper = function(str, next) {
        throw new Error('UPPER Error');
      };
      upper.async = true;
      asyncHelpers3.set('upper', upper);
      var helper = asyncHelpers3.get('upper', {wrap: true});
      var obj = {username: 'doowb'};
      obj.profile = obj;
      var id = helper(obj);
      return co(asyncHelpers3.resolveId(id))
        .then(function(val) {
          throw new Error('Expected an error');
        })
        .catch(function(err) {
          assert(err.hasOwnProperty('helper'), 'Expected a `helper` property on `err`');
        });
    });
  });

  describe('wrapHelper', function() {
    it('should return the helper when given the helper name', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      var fn = asyncHelpers.wrapHelper('upper');
      assert.equal(fn, upper);
      assert.deepEqual(fn('doowb'), 'DOOWB');
    });

    it('should return the wrapped helper when given the helper name and wrap option is true', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      asyncHelpers.set('upper', upper);
      var fn = asyncHelpers.wrapHelper('upper', {wrap: true});
      assert.notEqual(fn, upper);
      assert.notEqual(fn.toString(), upper.toString());
      assert.deepEqual(fn('doowb'), '{$ASYNCID$0$0$}');
    });

    it('should return a function when given a function', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      var fn = asyncHelpers.wrapHelper(upper);
      assert.equal(fn, upper);
      assert.deepEqual(fn('doowb'), 'DOOWB');
    });

    it('should return a wrapped function when given a function and wrap option is true', function() {
      var upper = function(str) {
        return str.toUpperCase();
      };
      var fn = asyncHelpers.wrapHelper(upper, {wrap: true});
      assert.notEqual(fn, upper);
      assert.deepEqual(fn('doowb'), '{$ASYNCID$0$0$}');
    });

    it('should return an object of helpers when given an object of helpers', function() {
      var helpers = {
        upper: function(str) { return str.toUpperCase(); },
        lower: function(str) { return str.toLowerCase(); }
      };
      asyncHelpers.set(helpers);
      var obj = asyncHelpers.wrapHelper();
      assert.deepEqual(obj, helpers);
      assert.equal(obj.upper('doowb'), 'DOOWB');
      assert.equal(obj.lower('DOOWB'), 'doowb');
    });

    it('should return an object of wrapped helpers when given an object of helpers and wrap option is true', function() {
      var helpers = {
        upper: function(str) { return str.toUpperCase(); },
        lower: function(str) { return str.toLowerCase(); }
      };
      asyncHelpers.set(helpers);
      var obj = asyncHelpers.wrapHelper({wrap: true});
      assert.notDeepEqual(obj, helpers);
      assert.equal(obj.upper('doowb'), '{$ASYNCID$0$0$}');
      assert.equal(obj.lower('DOOWB'), '{$ASYNCID$0$1$}');
    });

    it.skip('should return an object of helpers from a helper group', function() {
      var helpers = function() {};
      helpers.isGroup = true;
      helpers.upper = function(str) { return str.toUpperCase(); };
      helpers.lower = function(str) { return str.toLowerCase(); };
      asyncHelpers.set('my-group', helpers);
      var res = asyncHelpers.wrapHelper('my-group');
      assert.deepEqual(res, helpers);
      assert.equal(res.upper('doowb'), 'DOOWB');
      assert.equal(res.lower('DOOWB'), 'doowb');
    });
  });

  describe('wrapHelpers', function() {

  });

  describe('wrapper', function() {

  });

  describe('reset', function() {

  });

  describe('matches', function() {

  });

  describe('hasAsyncId', function() {

  });

  describe('resolveId', function() {

  });

  describe('resolveArgs', function() {

  });

  describe('resolveObject', function() {

  });

  describe('resolveIds', function() {

  });
});
<|endoftext|>


<commit_before>var should = require('should'),
	lib = require('../lib.js'),
	fs = require('fs-extra'),
	path = require('path'),
	testutil = require("testutil"),
	async = require('async'),
	_ = require('lodash');

var TEST_DIR = '';

function prepareTestFiles(testFiles){
	_.each(testFiles, function(file){
		fs.outputFileSync(path.resolve(TEST_DIR, file), file);
	});
}

function executeTest(testFiles, expectedDir, commandOptions, done){
	//prepare test files
	prepareTestFiles(testFiles);

	//test
	lib.fileToDir(commandOptions, function(){
			testResult(testFiles, expectedDir, done);
		});
}

function testResult(testFiles, expectedDirectory, done){
	fs.readdir(expectedDirectory, function(err, resultFiles){
		if(err !== null){
			done(err);
			return;
		}
		var diff = _.difference(testFiles, resultFiles);
		should(resultFiles.length > 0 && diff.length === 0);
		done();
	});
}

describe('auto-file-to-dir', function() {
	beforeEach(function(done) {
		TEST_DIR = testutil.createTestDir("move-test");
		fs.readdir(TEST_DIR, function(err, resultFiles){
			console.log('before directory:');
			console.log(resultFiles);
			done();
		});
	});

	afterEach(function(done) {
		console.log('after');

		fs.readdir(TEST_DIR, function(err, resultFiles){
			console.log('resulting directory:');
			console.log(resultFiles);
			fs.remove(TEST_DIR, done);
		});
	});

	////////////////// TESTS

	it(' - minimum pattern', function(done){
		executeTest(
			['test 01.test', 'test 02.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('- numbers only', function(done){
		executeTest(
			['01.test', '02.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  no numbers', function(done){
		executeTest(
			['test a.test', 'test b.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  no spaces', function(done){
		executeTest(
			['test01.test', 'test02.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  brackets before', function(done){
		executeTest(
			['[aaa] test 01.test', '[bbb] test 02.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  brackets after', function(done){
		executeTest(
			['test 01 [aaa].test', 'test 02 [bbb].test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  multiple number groups', function(done){
		executeTest(
			['test 01 02.test', 'test 01 03.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});
});<commit_msg>remove debug output<commit_after>var should = require('should'),
	lib = require('../lib.js'),
	fs = require('fs-extra'),
	path = require('path'),
	testutil = require("testutil"),
	async = require('async'),
	_ = require('lodash');

var TEST_DIR = '';

function prepareTestFiles(testFiles){
	_.each(testFiles, function(file){
		fs.outputFileSync(path.resolve(TEST_DIR, file), file);
	});
}

function executeTest(testFiles, expectedDir, commandOptions, done){
	//prepare test files
	prepareTestFiles(testFiles);

	//test
	lib.fileToDir(commandOptions, function(){
			testResult(testFiles, expectedDir, done);
	});
}

function testResult(testFiles, expectedDirectory, done){
	fs.readdir(expectedDirectory, function(err, resultFiles){
		if(err !== null){
			done(err);
			return;
		}
		var diff = _.difference(testFiles, resultFiles);
		should(resultFiles.length > 0 && diff.length === 0);
		done();
	});
}

describe('auto-file-to-dir', function() {
	beforeEach(function(done) {
		TEST_DIR = testutil.createTestDir("move-test");
		done();
		// fs.readdir(TEST_DIR, function(err, resultFiles){
// 			console.log('before directory:');
// 			console.log(resultFiles);
// 			done();
// 		});
	});

	afterEach(function(done) {
		// console.log('after');
		fs.remove(TEST_DIR, done);

		// fs.readdir(TEST_DIR, function(err, resultFiles){
		// 	console.log('resulting directory:');
		// 	console.log(resultFiles);
		// });
	});

	////////////////// TESTS

	it(' - minimum pattern', function(done){
		executeTest(
			['test 01.test', 'test 02.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('- numbers only', function(done){
		executeTest(
			['01.test', '02.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  no numbers', function(done){
		executeTest(
			['test a.test', 'test b.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  no spaces', function(done){
		executeTest(
			['test01.test', 'test02.test'],
			TEST_DIR,
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  brackets before', function(done){
		executeTest(
			['[aaa] test 01.test', '[bbb] test 02.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  brackets after', function(done){
		executeTest(
			['test 01 [aaa].test', 'test 02 [bbb].test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});

	it('-  multiple number groups', function(done){
		executeTest(
			['test 01 02.test', 'test 01 03.test'],
			path.resolve(TEST_DIR, 'test'),
			['node', 'auto-file-to-dir', TEST_DIR],
			done
		);
	});
});<|endoftext|>


<commit_before>var slug     = require('slug');
var fs       = require('fs');
var path     = require('path');
var Future   = require('data.future');
var Maybe    = require('data.maybe');
var utils    = require('./utils');
var FS       = require('io.filesystem')(fs);
var filterM  = require('control.monads').filterM;
var parallel = require('control.async')(Future).parallel;
var unary    = require('core.arity').unary;
var flip     = require('core.lambda').flip;
var zipWith  = require('data.array/zips/zip-with');
var extend   = require('xtend');

module.exports = function(homePath) {

  var novelHome      = λ[homePath];
  var joinPath       = λ a b -> path.join(a, b);
  var appendPath     = flip(joinPath);
  var extendWithPath = λ(data, path) -> extend(data, { path: path });

  function normaliseNovel(a) {
    if (a.title == null)
      throw new Error('<title> is required. ' + JSON.stringify(a));

    return {
      title      : a.title,
      author     : Maybe.fromNullable(a.author),
      modifiedAt : a.modifiedAt? Maybe.of(new Date(a.modifiedAt)) : Maybe.Nothing(),
      tags       : a.tags || []
    }
  }

  function novelList(dir) {
    return $do {
      folders <- FS.listDirectory(dir);
      dirs    <- filterM(Future, FS.isDirectory, folders.map(joinPath(dir)));
      files   <- parallel(dirs.map(appendPath('novel.json') ->> FS.readAsText));
      var data = files.map(unary(JSON.parse) ->> normaliseNovel)
      return zipWith(extendWithPath, data, dirs);
    }
  }

  return novelList

}
<commit_msg>Uses destructuring.<commit_after>var slug     = require('slug');
var fs       = require('fs');
var path     = require('path');
var Future   = require('data.future');
var Maybe    = require('data.maybe');
var extend   = require('xtend');
var FS       = require('io.filesystem')(fs);
var utils    = require('./utils');

var { filterM }  = require('control.monads');
var { parallel } = require('control.async')(Future);
var { unary }    = require('core.arity');
var { flip }     = require('core.lambda');
var zipWith      = require('data.array/zips/zip-with');

module.exports = function(homePath) {

  var novelHome      = λ[homePath];
  var joinPath       = λ a b -> path.join(a, b);
  var appendPath     = flip(joinPath);
  var extendWithPath = λ(data, path) -> extend(data, { path: path });

  function normaliseNovel(a) {
    if (a.title == null)
      throw new Error('<title> is required. ' + JSON.stringify(a));

    return {
      title      : a.title,
      author     : Maybe.fromNullable(a.author),
      modifiedAt : a.modifiedAt? Maybe.of(new Date(a.modifiedAt)) : Maybe.Nothing(),
      tags       : a.tags || []
    }
  }

  function novelList(dir) {
    return $do {
      folders <- FS.listDirectory(dir);
      dirs    <- filterM(Future, FS.isDirectory, folders.map(joinPath(dir)));
      files   <- parallel(dirs.map(appendPath('novel.json') ->> FS.readAsText));
      var data = files.map(unary(JSON.parse) ->> normaliseNovel)
      return zipWith(extendWithPath, data, dirs);
    }
  }

  return novelList

}
<|endoftext|>