<commit_before>import {assert} from 'chai';
import Cursor from 'kittik-cursor';
import Shape from '../../src/Shape';

const cursor = Cursor.create();

describe('Shape', () => {
  it('Should properly initialize shape instance with no arguments', () => {
    const shape = new Shape(cursor);

    assert.instanceOf(shape, Shape);
  });

  it('Should properly initialize shape instance with arguments', () => {
    const shape = new Shape(cursor, {text: 'test'});

    assert.instanceOf(shape, Shape);
    assert.equal(shape.getText(), 'test');
  });

  it('Should properly get/set property from the shape', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.get('text'), '');
    assert.instanceOf(shape.set('animation.name', 'print'), Shape);
    assert.equal(shape.get('animation.name'), 'print');
    assert.instanceOf(shape.set('animation.name', 'test'), Shape);
    assert.equal(shape.get('animation.name'), 'test');
  });

  it('Should properly get/set text', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getText(), '');
    assert.instanceOf(shape.setText('test'), Shape);
    assert.equal(shape.getText(), 'test');
  });

  it('Should properly get/set width', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getWidth(), 15);
    assert.instanceOf(shape.setWidth(5), Shape);
    assert.equal(shape.getWidth(), 5);
    assert.instanceOf(shape.setWidth('50%'), Shape);
    assert.equal(shape.getWidth(), Math.ceil(cursor._width / 2));
  });

  it('Should properly get/set height', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getHeight(), 5);
    assert.instanceOf(shape.setHeight(15), Shape);
    assert.equal(shape.getHeight(), 15);
    assert.instanceOf(shape.setHeight('50%'), Shape);
    assert.equal(shape.getHeight(), Math.floor(cursor._height / 2));
  });

  it('Should properly get/set x coordinate', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getX(), 10);
    assert.instanceOf(shape.setX(20), Shape);
    assert.equal(shape.getX(), 20);
    assert.instanceOf(shape.setX('left'), Shape);
    assert.equal(shape.getX(), 0);
    assert.instanceOf(shape.setX('center'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width / 2 - shape.getWidth() / 2));
    assert.instanceOf(shape.setX('right'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width - shape.getWidth()));
    assert.instanceOf(shape.setX('50%'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width / 2));
  });

  it('Should properly get/set y coordinate', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getY(), 10);
    assert.instanceOf(shape.setY(20), Shape);
    assert.equal(shape.getY(), 20);
    assert.instanceOf(shape.setY('top'), Shape);
    assert.equal(shape.getY(), 0);
    assert.instanceOf(shape.setY('middle'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height / 2 - shape.getHeight() / 2));
    assert.instanceOf(shape.setY('bottom'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height - shape.getHeight()));
    assert.instanceOf(shape.setY('50%'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height / 2));
  });

  it('Should properly get/set background', () => {
    const shape = new Shape(cursor);

    assert.notOk(shape.getBackground());
    assert.instanceOf(shape.setBackground('red'), Shape);
    assert.equal(shape.getBackground(), 'red');
  });

  it('Should properly get/set foreground', () => {
    const shape = new Shape(cursor);

    assert.notOk(shape.getBackground());
    assert.instanceOf(shape.setForeground('yellow'), Shape);
    assert.equal(shape.getForeground(), 'yellow');
  });

  it('Should properly throw exception if render is not overridden', () => {
    const shape = new Shape(cursor);

    assert.throws(() => shape.render(), Error, 'render() method must be implemented');
  });

  it('Should properly serialize shape to object', () => {
    const shape = new Shape(cursor);
    const obj = shape.toObject();

    assert.deepEqual(obj, {
      type: 'Shape',
      options: {
        text: '',
        width: 15,
        height: 5,
        x: 10,
        y: 10,
        background: false,
        foreground: false
      }
    });
  });

  it('Should properly serialize shape to object with custom options', () => {
    const shape = new Shape(cursor, {
      text: 'test',
      x: 0,
      y: 0,
      width: 30,
      height: 50,
      background: 'red',
      foreground: 'black'
    });
    const obj = shape.toObject();

    assert.deepEqual(obj, {
      type: 'Shape',
      options: {
        text: 'test',
        width: 30,
        height: 50,
        x: 0,
        y: 0,
        background: 'red',
        foreground: 'black'
      }
    });
  });

  it('Should properly serialize shape to JSON', () => {
    const shape = new Shape(cursor);
    const json = shape.toJSON();

    assert.equal(json, '{"type":"Shape","options":{"text":"","width":15,"height":5,"x":10,"y":10,"background":false,"foreground":false}}');
  });

  it('Should properly serialize shape to JSON with custom options', () => {
    const shape = new Shape(cursor, {text: 'test', x: 0, y: 0, width: 30, height: 50});
    const json = shape.toJSON();

    assert.equal(json, '{"type":"Shape","options":{"text":"test","width":30,"height":50,"x":0,"y":0,"background":false,"foreground":false}}');
  });

  it('Should properly create Shape instance from static create()', () => {
    const shape = Shape.create(cursor, {text: 'test'});

    assert.equal(shape.getText(), 'test');
    assert.instanceOf(shape, Shape);
  });

  it('Should properly throw error if trying to create Shape not from Object representation', () => {
    const obj = {};

    assert.throws(() => Shape.fromObject(obj), Error, 'It looks like it is not an Object representation of the shape');
  });

  it('Should properly throw error if trying to create Shape not from its representation', () => {
    const obj = {type: 'Rectangle', options: {}};

    assert.throws(() => Shape.fromObject(obj), Error, 'Rectangle is not an Object representation of the Shape');
  });

  it('Should properly create Shape instance from Object representation', () => {
    const obj = {
      type: 'Shape',
      options: {
        text: 'test',
        width: 30,
        height: 50,
        x: 1,
        y: 1,
        background: 'red',
        foreground: 'black'
      }
    };

    const shape = Shape.fromObject(obj, cursor);

    assert.instanceOf(shape, Shape);
    assert.instanceOf(shape.getCursor(), Cursor);
    assert.equal(shape.getText(), 'test');
    assert.equal(shape.getWidth(), 30);
    assert.equal(shape.getHeight(), 50);
    assert.equal(shape.getX(), 1);
    assert.equal(shape.getY(), 1);
    assert.equal(shape.getBackground(), 'red');
    assert.equal(shape.getForeground(), 'black');
  });

  it('Should properly create Shape instance from JSON representation', () => {
    const json = '{"type":"Shape","options":{"text":"test","width":30,"height":50,"x":1,"y":1}}';
    const shape = Shape.fromJSON(json, cursor);

    assert.instanceOf(shape, Shape);
    assert.instanceOf(shape.getCursor(), Cursor);
    assert.equal(shape.getText(), 'test');
    assert.equal(shape.getWidth(), 30);
    assert.equal(shape.getHeight(), 50);
    assert.equal(shape.getX(), 1);
    assert.equal(shape.getY(), 1);
    assert.notOk(shape.getBackground());
    assert.notOk(shape.getForeground());
  });
});
<commit_msg>test(shape): Fix tests<commit_after>import {assert} from 'chai';
import Cursor from 'kittik-cursor';
import Shape from '../../src/Shape';

const cursor = Cursor.create();

describe('Shape', () => {
  it('Should properly initialize shape instance with no arguments', () => {
    const shape = new Shape(cursor);

    assert.instanceOf(shape, Shape);
  });

  it('Should properly initialize shape instance with arguments', () => {
    const shape = new Shape(cursor, {text: 'test'});

    assert.instanceOf(shape, Shape);
    assert.equal(shape.getText(), 'test');
  });

  it('Should properly get/set property from the shape', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.get('text'), '');
    assert.instanceOf(shape.set('animation.name', 'print'), Shape);
    assert.equal(shape.get('animation.name'), 'print');
    assert.instanceOf(shape.set('animation.name', 'test'), Shape);
    assert.equal(shape.get('animation.name'), 'test');
  });

  it('Should properly get/set text', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getText(), '');
    assert.instanceOf(shape.setText('test'), Shape);
    assert.equal(shape.getText(), 'test');
  });

  it('Should properly get/set width', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getWidth(), 15);
    assert.instanceOf(shape.setWidth(5), Shape);
    assert.equal(shape.getWidth(), 5);
    assert.instanceOf(shape.setWidth('50%'), Shape);
    assert.equal(shape.getWidth(), Math.ceil(cursor._width / 2));
  });

  it('Should properly get/set height', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getHeight(), 5);
    assert.instanceOf(shape.setHeight(15), Shape);
    assert.equal(shape.getHeight(), 15);
    assert.instanceOf(shape.setHeight('50%'), Shape);
    assert.equal(shape.getHeight(), Math.floor(cursor._height / 2));
  });

  it('Should properly get/set x coordinate', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getX(), 10);
    assert.instanceOf(shape.setX(20), Shape);
    assert.equal(shape.getX(), 20);
    assert.instanceOf(shape.setX('left'), Shape);
    assert.equal(shape.getX(), 0);
    assert.instanceOf(shape.setX('center'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width / 2 - shape.getWidth() / 2));
    assert.instanceOf(shape.setX('right'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width - shape.getWidth()));
    assert.instanceOf(shape.setX('50%'), Shape);
    assert.equal(shape.getX(), Math.floor(cursor._width / 2));
  });

  it('Should properly get/set y coordinate', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getY(), 10);
    assert.instanceOf(shape.setY(20), Shape);
    assert.equal(shape.getY(), 20);
    assert.instanceOf(shape.setY('top'), Shape);
    assert.equal(shape.getY(), 0);
    assert.instanceOf(shape.setY('middle'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height / 2 - shape.getHeight() / 2));
    assert.instanceOf(shape.setY('bottom'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height - shape.getHeight()));
    assert.instanceOf(shape.setY('50%'), Shape);
    assert.equal(shape.getY(), Math.floor(cursor._height / 2));
  });

  it('Should properly get/set background', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getBackground(), 'none');
    assert.instanceOf(shape.setBackground('red'), Shape);
    assert.equal(shape.getBackground(), 'red');
  });

  it('Should properly get/set foreground', () => {
    const shape = new Shape(cursor);

    assert.equal(shape.getForeground(), 'none');
    assert.instanceOf(shape.setForeground('yellow'), Shape);
    assert.equal(shape.getForeground(), 'yellow');
  });

  it('Should properly throw exception if render is not overridden', () => {
    const shape = new Shape(cursor);

    assert.throws(() => shape.render(), Error, 'render() method must be implemented');
  });

  it('Should properly serialize shape to object', () => {
    const shape = new Shape(cursor);
    const obj = shape.toObject();

    assert.deepEqual(obj, {
      type: 'Shape',
      options: {
        text: '',
        width: 15,
        height: 5,
        x: 10,
        y: 10,
        background: 'none',
        foreground: 'none'
      }
    });
  });

  it('Should properly serialize shape to object with custom options', () => {
    const shape = new Shape(cursor, {
      text: 'test',
      x: 0,
      y: 0,
      width: 30,
      height: 50,
      background: 'red',
      foreground: 'black'
    });
    const obj = shape.toObject();

    assert.deepEqual(obj, {
      type: 'Shape',
      options: {
        text: 'test',
        width: 30,
        height: 50,
        x: 0,
        y: 0,
        background: 'red',
        foreground: 'black'
      }
    });
  });

  it('Should properly serialize shape to JSON', () => {
    const shape = new Shape(cursor);
    const json = shape.toJSON();

    assert.equal(json, '{"type":"Shape","options":{"text":"","width":15,"height":5,"x":10,"y":10,"background":"none","foreground":"none"}}');
  });

  it('Should properly serialize shape to JSON with custom options', () => {
    const shape = new Shape(cursor, {text: 'test', x: 0, y: 0, width: 30, height: 50});
    const json = shape.toJSON();

    assert.equal(json, '{"type":"Shape","options":{"text":"test","width":30,"height":50,"x":0,"y":0,"background":"none","foreground":"none"}}');
  });

  it('Should properly create Shape instance from static create()', () => {
    const shape = Shape.create(cursor, {text: 'test'});

    assert.equal(shape.getText(), 'test');
    assert.instanceOf(shape, Shape);
  });

  it('Should properly throw error if trying to create Shape not from Object representation', () => {
    const obj = {};

    assert.throws(() => Shape.fromObject(obj), Error, 'It looks like it is not an Object representation of the shape');
  });

  it('Should properly throw error if trying to create Shape not from its representation', () => {
    const obj = {type: 'Rectangle', options: {}};

    assert.throws(() => Shape.fromObject(obj), Error, 'Rectangle is not an Object representation of the Shape');
  });

  it('Should properly create Shape instance from Object representation', () => {
    const obj = {
      type: 'Shape',
      options: {
        text: 'test',
        width: 30,
        height: 50,
        x: 1,
        y: 1,
        background: 'red',
        foreground: 'black'
      }
    };

    const shape = Shape.fromObject(obj, cursor);

    assert.instanceOf(shape, Shape);
    assert.instanceOf(shape.getCursor(), Cursor);
    assert.equal(shape.getText(), 'test');
    assert.equal(shape.getWidth(), 30);
    assert.equal(shape.getHeight(), 50);
    assert.equal(shape.getX(), 1);
    assert.equal(shape.getY(), 1);
    assert.equal(shape.getBackground(), 'red');
    assert.equal(shape.getForeground(), 'black');
  });

  it('Should properly create Shape instance from JSON representation', () => {
    const json = '{"type":"Shape","options":{"text":"test","width":30,"height":50,"x":1,"y":1}}';
    const shape = Shape.fromJSON(json, cursor);

    assert.instanceOf(shape, Shape);
    assert.instanceOf(shape.getCursor(), Cursor);
    assert.equal(shape.getText(), 'test');
    assert.equal(shape.getWidth(), 30);
    assert.equal(shape.getHeight(), 50);
    assert.equal(shape.getX(), 1);
    assert.equal(shape.getY(), 1);
    assert.equal(shape.getBackground(), 'none');
    assert.equal(shape.getForeground(), 'none');
  });
});
<|endoftext|>


<commit_before>(function(){
    var app = angular.module("roster", []);

    /* Controller for Rostermenu */
    app.controller("RosterMenuController", function(){
        this.checkoutAddJid = function(event){
            if(event.key == "Enter")
                Roster_ajaxSearchContact(event.target.value);
        };
    });

    /* Controller for Rosterlist */
    app.controller("RosterController", function($scope){
        /* Cache variables
        $scope.lsJid = localStorage.getItem("username").replace("@", "at");
        $scope.lsRoster = localStorage.getObject($scope.lsJid + "_Roster") || {};*/
        $scope.lsGroupState = /*"groupState" in $scope.lsRoster ? $scope.lsRoster.groupState : */{};

        //this.cache = localStorage.getObject($scope.lsJid + '_cache');
        $scope.contacts = /*this.cache && ("Roster" in this.cache) && ("contactsList" in this.cache.Roster) ? localStorage.getObject($scope.lsJid + '_cache').Roster.contactsList : */[];
        $scope.groups = [];

        /* Dictionaries */
        $scope.lookupgroups = {};
        $scope.lookupjid = {};

        $scope.initContacts = function(list){
            //if($scope.contacts.length == 0){
                //console.log("NO cache");
                for(var i = 0; i < list.length; i++){
                    /* New group */
                    if(!(list[i].groupname in $scope.lookupgroups)){
                        el = {
                            'agroup': list[i].groupname,
                            'agroupitems': [],
                            'tombstone': false,
                        };
                        $scope.pushInPlace(el, $scope.contacts, groupnameCompare);

                        /* Create a reference in the localstorage for toggling */
                        $scope.lsGroupState["rosterGroup_"+list[0].groupname] = true;
                    }
                    /* New jid */
                    if(!(list[i].jid in $scope.lookupjid)){
                        el = {
                            'ajid': list[i].jid,
                            'aval': list[i].value,
                            'ajiditems': [],
                            'tombstone': false,
                        };
                        $scope.pushInPlace(el, $scope.lookupgroups[list[i].groupname].agroupitems, jidAvalCompare);
                    }
                    /* New ressource (can't just push the whole set of same jid because there is no set) */
                    if(!$scope.isInJidItems(list[i].jid, list[i].ressource)){
                        $scope.pushInPlace(list[i], $scope.lookupjid[list[i].jid].ajiditems, ressourceCompare);
                    }
                }
            //}
            /* Rebound from cache */
            /*else{
                console.log("cache");
                for(var i = 0; i < $scope.contacts.length; i++){
                    if(!$scope.contacts[i].tombstone){
                        $scope.lookupgroups[$scope.contacts[i].agroup] = $scope.contacts[i];
                        for(var j = 0; j < $scope.contacts[i].agroupitems.length; j++){
                            if(!$scope.contacts[i].agroupitems[j].tombstone)
                                $scope.lookupjid[$scope.contacts[i].agroupitems[j].ajid] = $scope.contacts[i].agroupitems[j];
                            else // Cleanup tombstoned jid
                                $scope.contacts[i].agroupitems.splice(j, 1);                        }
                    }
                    else // Cleanup tombstoned groups
                        $scope.contacts.splice(i, 1);
                }
            }*/

            $scope.$apply();
        };

        $scope.initGroups = function(list){
            for(var i in list){
                if(!("rosterGroup_"+i in $scope.lsGroupState)){
                    list[i] = true;
                    $scope.lsGroupState["rosterGroup_"+i] = true;
                }
                else list[i] = $scope.lsGroupState["rosterGroup_"+i];
            }

            $scope.groups = list;
            $scope.$apply();
        };

        $scope.deleteContact = function(jid){
            $scope.lookupjid[jid].tombstone = true;

            $scope.$apply();
        };

        $scope.isInJidItems = function(jid, ressource){
            l = $scope.lookupjid[jid].ajiditems.length;
            for(var i = 0; i < l; i++){
                if($scope.lookupjid[jid].ajiditems[i].ressource == ressource)
                    return true;
            }
            return false;
        };

        $scope.pushInPlace = function(element, array, comparer){
            if(array === $scope.contacts){
                dico = $scope.lookupgroups;
                key = "agroup";
            } else {
                dico = $scope.lookupjid;
                key = "ajid";
            }

            /* Put element in the right place inside array */
            index = locationOf(element, array, comparer);
            array.splice(index, 0, element);

            /* Update dictionnary from the appropriate index */
            for(var i=index; i<array.length; i++){
                dico[array[i][key]] = array[i];
            }
        };

        $scope.updateContact = function(list){
            if($scope.contacts === null) $scope.contacts = [];
            /* Group change */
            if((list[0].jid in $scope.lookupjid)
                && !($scope.lookupjid[list[0].jid].ajiditems[0].groupname == list[0].groupname)){
                /* Kill jid from old location or whole group if it's the only jid */
                oldgroupname = $scope.lookupjid[list[0].jid].ajiditems[0].groupname;
                if($scope.lookupgroups[oldgroupname].agroupitems.length == 1)
                    $scope.lookupgroups[oldgroupname].tombstone = true;
                else
                    $scope.lookupjid[list[0].jid].tombstone = true;
            }
            /* New group is not in the list */
            if(!(list[0].groupname in $scope.lookupgroups)) {
                /* Create group */
                el = {
                    'agroup': list[0].groupname,
                    'agroupitems': [],
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.contacts, groupnameCompare);
                /* Reference in the localstorage for toggling */
                $scope.lsGroupState["rosterGroup_"+list[0].groupname] = true;
            }

            /* Jid is in the list and no group change */
            if(list[0].jid in $scope.lookupjid
                && ($scope.lookupjid[list[0].jid].ajiditems[0].groupname == list[0].groupname))
            {
                $scope.lookupjid[list[0].jid].aval = list[0].value;
                $scope.lookupjid[list[0].jid].ajiditems = list;
                $scope.lookupgroups[list[0].groupname].agroupitems.sort(jidAvalCompare);
            }
            else{
                el = {
                    'ajid':     list[0].jid,
                    'aval':     list[0].value,
                    'ajiditems': list,
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.lookupgroups[list[0].groupname].agroupitems, jidAvalCompare);
            }
            $scope.$apply();
        };

        this.showHideGroup = function(g){
            ls = $scope.lsGroupState["rosterGroup_"+g];
            if(ls === null){
                ls = $scope.lsGroupState.rosterGroup_Ungrouped;
                g = "Ungrouped";
            }

            ls = !ls;

            $scope.lsGroupState["rosterGroup_"+g] = ls;
            $scope.groups[g] = ls;
        };

        this.postChatAction = function(c){
            eval(c.rosterview.openchat);
        };

        this.postJingleAction = function(c){
            Popup.close();
            Popup.open(c.jid + "/" + c.ressource);
        };

        this.groupIsShown = function(grp){
            if(typeof $scope.groups[grp] != "undefined"){
                return $scope.groups[grp];
            }
            else return $scope.groups["Ungrouped"];
        };

        this.offlineIsShown = function(){
            if($scope.lsGroupState.rosterShow_offline)
                return "offlineshown";
            else
                return "";
        };

        this.getContactTitle = function(c){
            status = c.status || "";
            ressource = c.ressource || "";
            title = c.jid;
            if(status != "") title += " - " + status;
            if(ressource != "") title += " - " + ressource;
            return title;
        };

        this.getContactClient = function(c){
            liclass = "";
            if(c.rosterview.client)
                liclass = "client " + c.rosterview.client;
            return liclass;
        };

        this.getJidStatusRessource = function(c){
            lititle = c.jid;
            if(c.status != '') lititle += " - " + c.status;
            lititle += " - " + c.ressource;
            return lititle;
        };

        this.getPresenceInactiveClient = function(c){
            liclass = c.rosterview.presencetxt + " " + contact.rosterview.inactive;
            if(c.client) liclass += " client " + c.client;
            return liclass;
        };
    });
})();

/*window.onunload = window.onbeforeunload = function(e){
    var lsjid = angular.element(roster).scope().lsJid;

    // Cache Roster list in jid_cache.Roster
    if(localStorage.getObject(lsjid + "_cache") === null)
        localStorage.setObject(lsjid + "_cache", {"Roster": {"contactsList": angular.element(roster).scope().contacts}});
    else{
        var nv = localStorage.getObject(lsjid + "_cache");
        nv.Roster = {"contactsList": angular.element(roster).scope().contacts};
        localStorage.setObject(lsjid + "_cache", nv);
    }

    // Move this to disconnection moment ??
    // Keep group states in jid_Roster.groupStates
    angular.element(roster).scope().lsRoster.groupState = angular.element(roster).scope().lsGroupState;
    localStorage.setObject(lsjid + "_Roster", angular.element(roster).scope().lsRoster);
};*/

/* Functions to call angular inner functions */
function initContacts(tab){
    if(tab.length == 0)
        angular.element(roster).scope().contacts = null;
    else
        angular.element(roster).scope().initContacts(JSON.parse(tab));
}

function initGroups(tab){
    angular.element(roster).scope().initGroups(JSON.parse(tab));
}

function updateContact(tab){
    angular.element(roster).scope().updateContact(JSON.parse(tab));
}

function deleteContact(jid){
    angular.element(roster).scope().deleteContact(jid);
}

/* === PushInPlace subfunctions === */
function locationOf(element, array, comparer, start, end) {
    if (array.length === 0)
        return 0;
    start = start || 0;
    end = end || array.length;
    var pivot = (start + end) >> 1;  // >>1 = /2
    var c = comparer(element, array[pivot]);
    if ((end - start) <= 1){
        return (c == -1) ? pivot : pivot+1;
    }

    switch (c) {
        case -1: return locationOf(element, array, comparer, start, pivot);
        case 0: return pivot;
        case 1: return locationOf(element, array, comparer, pivot, end);
    };
};

/* Object comparison functions */
var groupnameCompare = function(a, b) {
    return a.agroup.localeCompare(b.agroup);
};

var ressourceCompare = function(a, b) {
    n = a.value - b.value;
    return n ? n < 0 ? -1 : 1 : 0;
};
/* Presence + alphabetical comparison */
var jidAvalCompare = function(a, b) {
    n = a.aval - b.aval;
    if(n == 0 && a.ajiditems.length > 0){ /* if the array is empty keep the 0 value */
        n = a.ajiditems[0].rosterview.name.localeCompare(b.ajiditems[0].rosterview.name);
    }
    return n ? n < 0 ? -1 : 1 : 0;
};

/* === Old functions still in use === */
function showHideOffline() {
    if(!localStorage.getObject("rosterShow_offline")){
        document.querySelector('ul#rosterlist').className = 'offlineshown';
        localStorage.setObject("rosterShow_offline", true);
    }
    else{
        document.querySelector('ul#rosterlist').className = '';
        localStorage.setObject("rosterShow_offline", false);
    }
}

MovimWebsocket.attach(function(){
    Roster_ajaxGetRoster();
});

movim_add_onload(function(){
    var search      = document.querySelector('#rostersearch');
    var roster      = document.querySelector('#roster');
    var rosterlist  = document.querySelector('#rosterlist');

    var roster_classback      = document.querySelector('#roster').className;
    var rosterlist_classback  = document.querySelector('#rosterlist').className;

    roster.onblur  = function() {
        roster.className = roster_classback;
        rosterlist.className = rosterlist_classback;
    };
    search.onkeyup = function(event) {
        if(search.value.length > 0) {
            roster.className = 'search';
            rosterlist.className = 'offlineshown';
        } else {
            roster.className = roster_classback;
            rosterlist.className = rosterlist_classback;
        }

        // We clear the old search
        var selector_clear = '#rosterlist div > li';
        var li = document.querySelectorAll(selector_clear);

        for(i = 0; i < li.length; i++) {
            li.item(i).className = '';
        }

        // We select the interesting li
        var selector = '#rosterlist div > li[title*=\'' + search.value + '\']';
        var li = document.querySelectorAll(selector);

        for(i = 0; i < li.length; i++) {
            li.item(i).className = 'found';
        }
    };
});
<commit_msg>1400065<commit_after>(function(){
    var app = angular.module("roster", []);

    /* Controller for Rostermenu */
    app.controller("RosterMenuController", function(){
        this.checkoutAddJid = function(event){
            if(event.key == "Enter")
                Roster_ajaxSearchContact(event.target.value);
        };
    });

    /* Controller for Rosterlist */
    app.controller("RosterController", function($scope){
        /* Cache variables */
        $scope.lsJid = localStorage.getItem("username").replace("@", "at");
        $scope.lsRoster = localStorage.getObject($scope.lsJid + "_Roster") || {};
        $scope.lsGroupState = "groupState" in $scope.lsRoster ? $scope.lsRoster.groupState : {};

        //this.cache = localStorage.getObject($scope.lsJid + '_cache');
        $scope.contacts = /*this.cache && ("Roster" in this.cache) && ("contactsList" in this.cache.Roster) ? localStorage.getObject($scope.lsJid + '_cache').Roster.contactsList : */[];
        $scope.groups = [];

        /* Dictionaries */
        $scope.lookupgroups = {};
        $scope.lookupjid = {};

        $scope.initContacts = function(list){
            //if($scope.contacts.length == 0){
                //console.log("NO cache");
                for(var i = 0; i < list.length; i++){
                    /* New group */
                    if(!(list[i].groupname in $scope.lookupgroups)){
                        el = {
                            'agroup': list[i].groupname,
                            'agroupitems': [],
                            'tombstone': false,
                        };
                        $scope.pushInPlace(el, $scope.contacts, groupnameCompare);

                        /* Create a reference in the localstorage for toggling */
                        $scope.lsGroupState["rosterGroup_"+list[0].groupname] = true;
                    }
                    /* New jid */
                    if(!(list[i].jid in $scope.lookupjid)){
                        el = {
                            'ajid': list[i].jid,
                            'aval': list[i].value,
                            'ajiditems': [],
                            'tombstone': false,
                        };
                        $scope.pushInPlace(el, $scope.lookupgroups[list[i].groupname].agroupitems, jidAvalCompare);
                    }
                    /* New ressource (can't just push the whole set of same jid because there is no set) */
                    if(!$scope.isInJidItems(list[i].jid, list[i].ressource)){
                        $scope.pushInPlace(list[i], $scope.lookupjid[list[i].jid].ajiditems, ressourceCompare);
                    }
                }
            //}
            /* Rebound from cache */
            /*else{
                console.log("cache");
                for(var i = 0; i < $scope.contacts.length; i++){
                    if(!$scope.contacts[i].tombstone){
                        $scope.lookupgroups[$scope.contacts[i].agroup] = $scope.contacts[i];
                        for(var j = 0; j < $scope.contacts[i].agroupitems.length; j++){
                            if(!$scope.contacts[i].agroupitems[j].tombstone)
                                $scope.lookupjid[$scope.contacts[i].agroupitems[j].ajid] = $scope.contacts[i].agroupitems[j];
                            else // Cleanup tombstoned jid
                                $scope.contacts[i].agroupitems.splice(j, 1);                        }
                    }
                    else // Cleanup tombstoned groups
                        $scope.contacts.splice(i, 1);
                }
            }*/

            $scope.$apply();
        };

        $scope.initGroups = function(list){
            for(var i in list){
                if(!("rosterGroup_"+i in $scope.lsGroupState)){
                    list[i] = true;
                    $scope.lsGroupState["rosterGroup_"+i] = true;
                }
                else list[i] = $scope.lsGroupState["rosterGroup_"+i];
            }

            $scope.groups = list;
            $scope.$apply();
        };

        $scope.deleteContact = function(jid){
            $scope.lookupjid[jid].tombstone = true;

            $scope.$apply();
        };

        $scope.isInJidItems = function(jid, ressource){
            l = $scope.lookupjid[jid].ajiditems.length;
            for(var i = 0; i < l; i++){
                if($scope.lookupjid[jid].ajiditems[i].ressource == ressource)
                    return true;
            }
            return false;
        };

        $scope.pushInPlace = function(element, array, comparer){
            if(array === $scope.contacts){
                dico = $scope.lookupgroups;
                key = "agroup";
            } else {
                dico = $scope.lookupjid;
                key = "ajid";
            }

            /* Put element in the right place inside array */
            index = locationOf(element, array, comparer);
            array.splice(index, 0, element);

            /* Update dictionnary from the appropriate index */
            for(var i=index; i<array.length; i++){
                dico[array[i][key]] = array[i];
            }
        };

        $scope.updateContact = function(list){
            if($scope.contacts === null) $scope.contacts = [];
            /* Group change */
            if((list[0].jid in $scope.lookupjid)
                && !($scope.lookupjid[list[0].jid].ajiditems[0].groupname == list[0].groupname)){
                /* Kill jid from old location or whole group if it's the only jid */
                oldgroupname = $scope.lookupjid[list[0].jid].ajiditems[0].groupname;
                if($scope.lookupgroups[oldgroupname].agroupitems.length == 1)
                    $scope.lookupgroups[oldgroupname].tombstone = true;
                else{
                    $scope.lookupjid[list[0].jid].tombstone = true;

                    console.log("Tombstone TRUE for " + list[0].jid);
                }
            }
            /* New group is not in the list */
            if(!(list[0].groupname in $scope.lookupgroups)) {
                console.log("New groupname" + list[0].groupname);
                /* Create group */
                el = {
                    'agroup': list[0].groupname,
                    'agroupitems': [],
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.contacts, groupnameCompare);
                /* Reference in the localstorage for toggling */
                $scope.lsGroupState["rosterGroup_"+list[0].groupname] = true;
            }

            /* Jid is in the list and no group change */
            if(list[0].jid in $scope.lookupjid
                && ($scope.lookupjid[list[0].jid].ajiditems[0].groupname == list[0].groupname))
            {
                $scope.lookupjid[list[0].jid].aval = list[0].value;
                $scope.lookupjid[list[0].jid].ajiditems = list;
                $scope.lookupgroups[list[0].groupname].agroupitems.sort(jidAvalCompare);
            }
            else{
                el = {
                    'ajid':     list[0].jid,
                    'aval':     list[0].value,
                    'ajiditems': list,
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.lookupgroups[list[0].groupname].agroupitems, jidAvalCompare);
            }
            $scope.$apply();
        };

        this.showHideGroup = function(g){
            ls = $scope.lsGroupState["rosterGroup_"+g];
            if(ls === null){
                ls = $scope.lsGroupState.rosterGroup_Ungrouped;
                g = "Ungrouped";
            }

            ls = !ls;

            $scope.lsGroupState["rosterGroup_"+g] = ls;
            $scope.groups[g] = ls;
        };

        this.postChatAction = function(c){
            eval(c.rosterview.openchat);
        };

        this.postJingleAction = function(c){
            Popup.close();
            Popup.open(c.jid + "/" + c.ressource);
        };

        this.groupIsShown = function(grp){
            if(typeof $scope.groups[grp] != "undefined"){
                return $scope.groups[grp];
            }
            else return $scope.groups["Ungrouped"];
        };

        this.offlineIsShown = function(){
            if($scope.lsGroupState.rosterShow_offline)
                return "offlineshown";
            else
                return "";
        };

        this.getContactTitle = function(c){
            status = c.status || "";
            ressource = c.ressource || "";
            title = c.jid;
            if(status != "") title += " - " + status;
            if(ressource != "") title += " - " + ressource;
            return title;
        };

        this.getContactClient = function(c){
            liclass = "";
            if(c.rosterview.client)
                liclass = "client " + c.rosterview.client;
            return liclass;
        };

        this.getJidStatusRessource = function(c){
            lititle = c.jid;
            if(c.status != '') lititle += " - " + c.status;
            lititle += " - " + c.ressource;
            return lititle;
        };

        this.getPresenceInactiveClient = function(c){
            liclass = c.rosterview.presencetxt + " " + contact.rosterview.inactive;
            if(c.client) liclass += " client " + c.client;
            return liclass;
        };
    });
})();

window.onunload = window.onbeforeunload = function(e){
    var lsjid = angular.element(roster).scope().lsJid;

    // Cache Roster list in jid_cache.Roster
    /*if(localStorage.getObject(lsjid + "_cache") === null)
        localStorage.setObject(lsjid + "_cache", {"Roster": {"contactsList": angular.element(roster).scope().contacts}});
    else{
        var nv = localStorage.getObject(lsjid + "_cache");
        nv.Roster = {"contactsList": angular.element(roster).scope().contacts};
        localStorage.setObject(lsjid + "_cache", nv);
    }
    */

    // Move this to disconnection moment ??
    // Keep group states in jid_Roster.groupStates
    angular.element(roster).scope().lsRoster.groupState = angular.element(roster).scope().lsGroupState;
    localStorage.setObject(lsjid + "_Roster", angular.element(roster).scope().lsRoster);
};

/* Functions to call angular inner functions */
function initContacts(tab){
    if(tab.length == 0)
        angular.element(roster).scope().contacts = null;
    else
        angular.element(roster).scope().initContacts(JSON.parse(tab));
}

function initGroups(tab){
    angular.element(roster).scope().initGroups(JSON.parse(tab));
}

function updateContact(tab){
    angular.element(roster).scope().updateContact(JSON.parse(tab));
}

function deleteContact(jid){
    angular.element(roster).scope().deleteContact(jid);
}

/* === PushInPlace subfunctions === */
function locationOf(element, array, comparer, start, end) {
    if (array.length === 0)
        return 0;
    start = start || 0;
    end = end || array.length;
    var pivot = (start + end) >> 1;  // >>1 = /2
    var c = comparer(element, array[pivot]);
    if ((end - start) <= 1){
        return (c == -1) ? pivot : pivot+1;
    }

    switch (c) {
        case -1: return locationOf(element, array, comparer, start, pivot);
        case 0: return pivot;
        case 1: return locationOf(element, array, comparer, pivot, end);
    };
};

/* Object comparison functions */
var groupnameCompare = function(a, b) {
    return a.agroup.localeCompare(b.agroup);
};

var ressourceCompare = function(a, b) {
    n = a.value - b.value;
    return n ? n < 0 ? -1 : 1 : 0;
};
/* Presence + alphabetical comparison */
var jidAvalCompare = function(a, b) {
    n = a.aval - b.aval;
    if(n == 0 && a.ajiditems.length > 0){ /* if the array is empty keep the 0 value */
        n = a.ajiditems[0].rosterview.name.localeCompare(b.ajiditems[0].rosterview.name);
    }
    return n ? n < 0 ? -1 : 1 : 0;
};

/* === Old functions still in use === */
function showHideOffline() {
    if(!localStorage.getObject("rosterShow_offline")){
        document.querySelector('ul#rosterlist').className = 'offlineshown';
        localStorage.setObject("rosterShow_offline", true);
    }
    else{
        document.querySelector('ul#rosterlist').className = '';
        localStorage.setObject("rosterShow_offline", false);
    }
}

MovimWebsocket.attach(function(){
    Roster_ajaxGetRoster();
});

movim_add_onload(function(){
    var search      = document.querySelector('#rostersearch');
    var roster      = document.querySelector('#roster');
    var rosterlist  = document.querySelector('#rosterlist');

    var roster_classback      = document.querySelector('#roster').className;
    var rosterlist_classback  = document.querySelector('#rosterlist').className;

    roster.onblur  = function() {
        roster.className = roster_classback;
        rosterlist.className = rosterlist_classback;
    };
    search.onkeyup = function(event) {
        if(search.value.length > 0) {
            roster.className = 'search';
            rosterlist.className = 'offlineshown';
        } else {
            roster.className = roster_classback;
            rosterlist.className = rosterlist_classback;
        }

        // We clear the old search
        var selector_clear = '#rosterlist div > li';
        var li = document.querySelectorAll(selector_clear);

        for(i = 0; i < li.length; i++) {
            li.item(i).className = '';
        }

        // We select the interesting li
        var selector = '#rosterlist div > li[title*=\'' + search.value + '\']';
        var li = document.querySelectorAll(selector);

        for(i = 0; i < li.length; i++) {
            li.item(i).className = 'found';
        }
    };
});
<|endoftext|>


<commit_before>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import browser from "webextension-polyfill";
import parser from "ua-parser-js";
import { js_beautify as beautify } from "js-beautify";
import { verifyFile, FileTypes, migrateTestCase, migrateProject, migrateUrls } from "./legacy/migrate";
import TestCase from "../models/TestCase";
import UiState from "../stores/view/UiState";
import ModalState from "../stores/view/ModalState";
import Selianize, { ParseError } from "selianize";
import Manager from "../../plugin/manager";
import chromeGetFile from "./filesystem/chrome";
import firefoxGetFile from "./filesystem/firefox";

export const supportedFileFormats = ".side, text/html";
const parsedUA = parser(window.navigator.userAgent);

export function getFile(path) {
  const browserName = parsedUA.browser.name;
  return (() => {
    if (browserName === "Chrome") {
      return chromeGetFile(path);
    } else if (browserName === "Firefox") {
      return firefoxGetFile(path);
    } else {
      return Promise.reject(new Error("Operation is not supported in this browser"));
    }
  })().then(blob => {
    return new Promise((res) => {
      const reader = new FileReader();
      reader.addEventListener("load", () => {
        res(reader.result);
      });
      reader.readAsDataURL(blob);
    });
  });
}

export function loadAsText(blob) {
  return new Promise((res) => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      res(e.target.result);
    };

    fileReader.readAsText(blob);
  });
}

export function saveProject(_project) {
  const project = _project.toJS();
  project.version = "1.0";
  downloadProject(project);
  UiState.saved();
}

function downloadProject(project) {
  return exportProject(project).then(code => {
    project.code = code;
    Object.assign(project, Manager.emitDependencies());
    return browser.downloads.download({
      filename: project.name + ".side",
      url: createBlob("application/json", beautify(JSON.stringify(project), { indent_size: 2 })),
      saveAs: true,
      conflictAction: "overwrite"
    });
  });
}

function exportProject(project) {
  return Manager.validatePluginExport(project).then(() => {
    return Selianize(project).catch(err => {
      const markdown = ParseError(err && err.message || err);
      ModalState.showAlert({
        title: "Error saving project",
        description: markdown,
        confirmLabel: "Download log",
        cancelLabel: "Close"
      }, (choseDownload) => {
        if (choseDownload) {
          browser.downloads.download({
            filename: project.name + "-logs.md",
            url: createBlob("text/markdown", markdown),
            saveAs: true,
            conflictAction: "overwrite"
          });
        }
      });
      return Promise.reject();
    });
  });
}

let previousFile = null;
function createBlob(mimeType, data) {
  const blob = new Blob([data], {
    type: "text/plain"
  });
  // If we are replacing a previously generated file we need to
  // manually revoke the object URL to avoid memory leaks.
  if (previousFile !== null) {
    window.URL.revokeObjectURL(previousFile);
  }
  previousFile = window.URL.createObjectURL(blob);
  return previousFile;
}

export function loadProject(project, file) {
  function displayError(error) {
    ModalState.showAlert({
      title: "Error migrating project",
      description: error.message,
      confirmLabel: "Close"
    });
  }
  loadAsText(file).then((contents) => {
    if (/\.side$/.test(file.name)) {
      loadJSONProject(project, contents);
    } else {
      try {
        const type = verifyFile(contents);
        if (type === FileTypes.Suite) {
          ModalState.importSuite(contents, (files) => {
            project.fromJS(migrateProject(files));
          });
        } else if (type === FileTypes.TestCase) {
          const { test, baseUrl } = migrateTestCase(contents);
          if (project.url && project.url !== baseUrl) {
            ModalState.showAlert({
              title: "Migrate test case",
              description: `The test case you're trying to migrate has a different base URL (${baseUrl}) than the project's one.  \nIn order to migrate the test case URLs will be made absolute.`,
              confirmLabel: "Migrate",
              cancelLabel: "Discard"
            }, (choseDownload) => {
              if (choseDownload) {
                project.addTestCase(TestCase.fromJS(migrateUrls(test, baseUrl)));
              }
            });
          }
        }
      } catch (error) {
        displayError(error);
      }
    }
  });
}

function loadJSONProject(project, data) {
  project.fromJS(JSON.parse(data));
  Manager.emitMessage({
    action: "event",
    event: "projectLoaded",
    options: {
      projectName: project.name
    }
  });
}
<commit_msg>fixed an issue where testcases wouldnt migrate if baseUrl was empty<commit_after>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import browser from "webextension-polyfill";
import parser from "ua-parser-js";
import { js_beautify as beautify } from "js-beautify";
import { verifyFile, FileTypes, migrateTestCase, migrateProject, migrateUrls } from "./legacy/migrate";
import TestCase from "../models/TestCase";
import UiState from "../stores/view/UiState";
import ModalState from "../stores/view/ModalState";
import Selianize, { ParseError } from "selianize";
import Manager from "../../plugin/manager";
import chromeGetFile from "./filesystem/chrome";
import firefoxGetFile from "./filesystem/firefox";

export const supportedFileFormats = ".side, text/html";
const parsedUA = parser(window.navigator.userAgent);

export function getFile(path) {
  const browserName = parsedUA.browser.name;
  return (() => {
    if (browserName === "Chrome") {
      return chromeGetFile(path);
    } else if (browserName === "Firefox") {
      return firefoxGetFile(path);
    } else {
      return Promise.reject(new Error("Operation is not supported in this browser"));
    }
  })().then(blob => {
    return new Promise((res) => {
      const reader = new FileReader();
      reader.addEventListener("load", () => {
        res(reader.result);
      });
      reader.readAsDataURL(blob);
    });
  });
}

export function loadAsText(blob) {
  return new Promise((res) => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      res(e.target.result);
    };

    fileReader.readAsText(blob);
  });
}

export function saveProject(_project) {
  const project = _project.toJS();
  project.version = "1.0";
  downloadProject(project);
  UiState.saved();
}

function downloadProject(project) {
  return exportProject(project).then(code => {
    project.code = code;
    Object.assign(project, Manager.emitDependencies());
    return browser.downloads.download({
      filename: project.name + ".side",
      url: createBlob("application/json", beautify(JSON.stringify(project), { indent_size: 2 })),
      saveAs: true,
      conflictAction: "overwrite"
    });
  });
}

function exportProject(project) {
  return Manager.validatePluginExport(project).then(() => {
    return Selianize(project).catch(err => {
      const markdown = ParseError(err && err.message || err);
      ModalState.showAlert({
        title: "Error saving project",
        description: markdown,
        confirmLabel: "Download log",
        cancelLabel: "Close"
      }, (choseDownload) => {
        if (choseDownload) {
          browser.downloads.download({
            filename: project.name + "-logs.md",
            url: createBlob("text/markdown", markdown),
            saveAs: true,
            conflictAction: "overwrite"
          });
        }
      });
      return Promise.reject();
    });
  });
}

let previousFile = null;
function createBlob(mimeType, data) {
  const blob = new Blob([data], {
    type: "text/plain"
  });
  // If we are replacing a previously generated file we need to
  // manually revoke the object URL to avoid memory leaks.
  if (previousFile !== null) {
    window.URL.revokeObjectURL(previousFile);
  }
  previousFile = window.URL.createObjectURL(blob);
  return previousFile;
}

export function loadProject(project, file) {
  function displayError(error) {
    ModalState.showAlert({
      title: "Error migrating project",
      description: error.message,
      confirmLabel: "Close"
    });
  }
  loadAsText(file).then((contents) => {
    if (/\.side$/.test(file.name)) {
      loadJSONProject(project, contents);
    } else {
      try {
        const type = verifyFile(contents);
        if (type === FileTypes.Suite) {
          ModalState.importSuite(contents, (files) => {
            project.fromJS(migrateProject(files));
          });
        } else if (type === FileTypes.TestCase) {
          const { test, baseUrl } = migrateTestCase(contents);
          if (!project.urls.includes(baseUrl)) {
            ModalState.showAlert({
              title: "Migrate test case",
              description: `The test case you're trying to migrate has a different base URL (${baseUrl}) than the project's one.  \nIn order to migrate the test case URLs will be made absolute.`,
              confirmLabel: "Migrate",
              cancelLabel: "Discard"
            }, (choseMigration) => {
              if (choseMigration) {
                project.addTestCase(TestCase.fromJS(migrateUrls(test, baseUrl)));
              }
            });
          } else {
            project.addTestCase(TestCase.fromJS(test, baseUrl));
          }
        }
      } catch (error) {
        displayError(error);
      }
    }
  });
}

function loadJSONProject(project, data) {
  project.fromJS(JSON.parse(data));
  Manager.emitMessage({
    action: "event",
    event: "projectLoaded",
    options: {
      projectName: project.name
    }
  });
}
<|endoftext|>


<commit_before>import element from '../../lib/element';
import render from '../../../src/api/render';

describe('api/render', function () {
  let elem;

  beforeEach(function () {
    elem = element().skate({
      properties: {
        name: {
          attribute: true,
          default: 'default',
          set: render
        }
      },
      render: render.html(function (elem) {
        return `${elem.name}`;
      })
    })();
  });

  it('should render the component', function () {
    expect(elem.textContent).to.equal('default');
    elem.name = 'updated';
    expect(elem.textContent).to.equal('updated');
  });
});
<commit_msg>Remove all usages of render.html() in tests.<commit_after>import element from '../../lib/element';
import render from '../../../src/api/render';

describe('api/render', function () {
  let elem;

  beforeEach(function () {
    elem = element().skate({
      properties: {
        name: {
          attribute: true,
          default: 'default',
          set: render
        }
      },
      render: function (elem) {
        elem.innerHTML = `${elem.name}`;
      }
    })();
  });

  it('should render the component', function () {
    expect(elem.textContent).to.equal('default');
    elem.name = 'updated';
    expect(elem.textContent).to.equal('updated');
  });
});
<|endoftext|>


<commit_before>(function(){
    var app = angular.module("roster", []);

    /* Controller for Rosterlist */
    app.controller("RosterController", function($scope){
        /* Cache variables */
        $scope.lsJid = localStorage.getItem("username").replace("@", "at");
        $scope.lsRoster = localStorage.getObject($scope.lsJid + "_Roster") || {};
        $scope.lsGroupState = "groupState" in $scope.lsRoster ? $scope.lsRoster.groupState : {};

        //this.cache = localStorage.getObject($scope.lsJid + '_cache');
        $scope.contacts = /*this.cache && ("Roster" in this.cache) && ("contactsList" in this.cache.Roster) ? localStorage.getObject($scope.lsJid + '_cache').Roster.contactsList : */[];
        $scope.groups = [];

        /* Dictionaries */
        $scope.lookupgroups = {};
        $scope.lookupjid = {};

        $scope.initContacts = function(list){
            console.log(list);
            /* Sort groups alphabetically */
            list.sort(groupnameCompare);

            $scope.contacts = list;
            /* Populate dictionaries */
            for(var i = 0; i < $scope.contacts.length; i++){
                $scope.lookupgroups[$scope.contacts[i].agroup] = $scope.contacts[i];
                /* Sort jid by presence and alphabetically */
                $scope.contacts[i].agroupitems.sort(jidAvalCompare);

                for(var j = 0; j < $scope.contacts[i].agroupitems.length; j++){
                    $scope.lookupjid[$scope.contacts[i].agroupitems[j].ajid] = $scope.contacts[i].agroupitems[j];
                }
            }
            $scope.$apply();
        };

        $scope.initGroups = function(list){
            for(var i in list){
                if(!("rosterGroup_"+i in $scope.lsGroupState)){
                    list[i] = true;
                    $scope.lsGroupState["rosterGroup_" + i] = true;
                }
                else list[i] = $scope.lsGroupState["rosterGroup_" + i];
            }

            $scope.groups = list;
            $scope.$apply();
        };

        $scope.deleteContact = function(jid){
            $scope.lookupjid[jid].tombstone = true;

            $scope.$apply();
        };

        $scope.pushInPlace = function(element, array, comparer){
            if(array === $scope.contacts){
                dico = $scope.lookupgroups;
                key = "agroup";
            } else {
                dico = $scope.lookupjid;
                key = "ajid";
            }

            /* Put element in the right place inside array */
            index = locationOf(element, array, comparer);
            array.splice(index, 0, element);

            /* Update dictionary from the appropriate index */
            for(var i=index; i<array.length; i++){
                dico[array[i][key]] = array[i];
            }
        };

        $scope.updateContact = function(list){
            console.log(list);
            if($scope.contacts === null) $scope.contacts = [];
            /* Group change */
            if((list.jid in $scope.lookupjid)
                && !($scope.lookupjid[list.jid].ajiditems.groupname == list.groupname)){
                /* Kill jid from old location or whole group if it's the only jid */
                oldgroupname = $scope.lookupjid[list.jid].ajiditems.groupname;
                if($scope.lookupgroups[oldgroupname].agroupitems.length == 1)
                    $scope.lookupgroups[oldgroupname].tombstone = true;
                else{
                    $scope.lookupjid[list.jid].tombstone = true;
                }
            }
            /* New group is not in the list */
            if(!(list.groupname in $scope.lookupgroups)) {
                /* Create group */
                el = {
                    'agroup': list.groupname,
                    'agroupitems': [],
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.contacts, groupnameCompare);
                /* Reference in the localstorage for toggling */
                $scope.lsGroupState["rosterGroup_" + list.groupname] = true;
            }

            /* Jid is in the list and no group change */
            if(list.jid in $scope.lookupjid
                && ($scope.lookupjid[list.jid].ajiditems.groupname == list.groupname))
            {
                $scope.lookupjid[list.jid].aval = list.value;
                $scope.lookupjid[list.jid].atruename = list.rosterview.name;
                $scope.lookupjid[list.jid].ajiditems = list;
                $scope.lookupgroups[list.groupname].agroupitems.sort(jidAvalCompare);
            }
            else{
                el = {
                    'ajid':     list.jid,
                    'atruename':     list.rosterview.name,
                    'aval':     list.value,
                    'ajiditems': list,
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.lookupgroups[list.groupname].agroupitems, jidAvalCompare);
            }
            $scope.$apply();

            //a new li is created, a new listener has to be created...
            document.getElementById(list.jid).onclick = function(e){Roster.clickOnContact(e);};
        };

        this.showHideGroup = function(g){
            ls = $scope.lsGroupState["rosterGroup_" + g];
            if(ls === null){
                ls = $scope.lsGroupState.rosterGroup_Ungrouped;
                g = "Ungrouped";
            }

            ls = !ls;

            $scope.lsGroupState["rosterGroup_" + g] = ls;
            $scope.groups[g] = ls;
        };

        /*this.postJingleAction = function(c){
            Popup.close();
            Popup.open(c.jid + "/" + c.resource);
        };*/

        this.groupIsShown = function(grp){
            if(typeof $scope.groups[grp] != "undefined"){
                return $scope.groups[grp];
            }
            else return $scope.groups["Ungrouped"];
        };

        this.getContactTitle = function(c){
            title = c.rosterview.name.toLowerCase() + " - " + c.jid;
            if(c.status) title += " - " + c.status;
            return title;
        };

        this.getContactClient = function(c){
            liclass = "";
            if(c.rosterview.client)
                liclass = "client " + c.rosterview.client;
            return liclass;
        };

        this.getJidStatusResource = function(c){
            lititle = c.jid;
            if(c.status != '') lititle += " - " + c.status;
            lititle += " - " + c.resource;
            return lititle;
        };

        this.getPresenceInactiveClient = function(c){
            liclass = c.rosterview.presencetxt + " " + contact.rosterview.inactive;
            if(c.client) liclass += " client " + c.client;
            return liclass;
        };
    });
})();

window.onunload = window.onbeforeunload = function(e){
    var lsjid = angular.element(roster).scope().lsJid;

    // Cache Roster list in jid_cache.Roster
    /*if(localStorage.getObject(lsjid + "_cache") === null)
        localStorage.setObject(lsjid + "_cache", {"Roster": {"contactsList": angular.element(roster).scope().contacts}});
    else{
        var nv = localStorage.getObject(lsjid + "_cache");
        nv.Roster = {"contactsList": angular.element(roster).scope().contacts};
        localStorage.setObject(lsjid + "_cache", nv);
    }
    */

    // Move this to disconnection moment ??
    // Keep group states in jid_Roster.groupStates
    angular.element(roster).scope().lsRoster.groupState = angular.element(roster).scope().lsGroupState;
    //angular.element(roster).scope().lsRoster.offlineShown = angular.element(rostermenu).scope().lsOfflineShown;
    localStorage.setObject(lsjid + "_Roster", angular.element(roster).scope().lsRoster);
};

/* Functions to call angular inner functions */
function initContacts(tab){
    if(tab.length == 0)
        angular.element(roster).scope().contacts = null;
    else
        angular.element(roster).scope().initContacts(JSON.parse(tab));

    Roster.refresh();
}

function initGroups(tab){
    angular.element(roster).scope().initGroups(JSON.parse(tab));
}

function updateContact(tab){
    angular.element(roster).scope().updateContact(JSON.parse(tab));
}

function deleteContact(jid){
    angular.element(roster).scope().deleteContact(jid);
}

/* === PushInPlace subfunctions === */
function locationOf(element, array, comparer, start, end) {
    if (array.length === 0)
        return 0;
    start = start || 0;
    end = end || array.length;
    var pivot = (start + end) >> 1;  // >>1 = /2
    var c = comparer(element, array[pivot]);
    if ((end - start) <= 1){
        return (c == -1) ? pivot : pivot+1;
    }

    switch (c) {
        case -1: return locationOf(element, array, comparer, start, pivot);
        case 0: return pivot;
        case 1: return locationOf(element, array, comparer, pivot, end);
    };
};

/* Object comparison functions */
var groupnameCompare = function(a, b) {
    return a.agroup.localeCompare(b.agroup);
};

/* Presence + alphabetical comparison */
var jidAvalCompare = function(a, b) {
    n = a.aval - b.aval;
    if(n == 0){
        n = a.atruename.localeCompare(b.atruename);
    }
    return n ? n < 0 ? -1 : 1 : 0;
};

/* === Old functions still in use === */
MovimWebsocket.attach(function(){
    Roster_ajaxGetRoster();
});

var Roster = {
    init : function() {
        var search      = document.querySelector('#rostersearch');
        var roster      = document.querySelector('#roster');
        var rosterlist  = document.querySelector('#rosterlist');

        roster.onblur  = function() {
            roster.className = roster_classback;
            rosterlist.className = rosterlist_classback;
        };
        search.oninput = function(event) {
            if(search.value.length > 0) {
                movim_add_class(roster, 'search');
                movim_add_class(rosterlist, 'offlineshown');
            } else {
                movim_remove_class(roster, 'search');
                movim_remove_class(rosterlist, 'offlineshown');
            }

            // We clear the old search
            var selector_clear = '#rosterlist div > li:not(.subheader)';
            var li = document.querySelectorAll(selector_clear);

            for(i = 0; i < li.length; i++) {
                movim_remove_class(li.item(i), 'found');
            }

            // We select the interesting li
            var selector = '#rosterlist div > li[title*="' + search.value.toLowerCase() + '"]:not(.subheader)';
            var li = document.querySelectorAll(selector);

            for(i = 0; i < li.length; i++) {
                movim_add_class(li.item(i), 'found');
            }
        };
    },
    refresh: function() {
        var items = document.querySelectorAll('#rosterlist div > li:not(.subheader)');
        var i = 0;

        while(i < items.length)
        {
            items[i].onclick = function(e){Roster.clickOnContact(e);};
            i++;
        }
    },

    reset: function(list) {
        for(i = 0; i < list.length; i++) {
            movim_remove_class(list[i], 'active');
        }
    },

    setFound : function(jid) {
        document.querySelector('input[name=searchjid]').value = jid;
    },

    clickOnContact : function(e) {
        Contact_ajaxGetContact(e.target.id);
        /*recalculated at each click*/
        var it = document.querySelectorAll('#rosterlist div > li:not(.subheader)');
        Roster.reset(it);
        movim_add_class(e.target, 'active');
        //document.querySelector('#roster').className = '';
    },
}

MovimWebsocket.attach(function() {
    Notification.notifs_key = 'contacts';
    Roster.refresh();
});

movim_add_onload(function(){
    Roster.init();
});
<commit_msg>- Remove group bool from localStorage when group is deleted<commit_after>(function(){
    var app = angular.module("roster", []);

    /* Controller for Rosterlist */
    app.controller("RosterController", function($scope){
        /* Cache variables */
        $scope.lsJid = localStorage.getItem("username").replace("@", "at");
        $scope.lsRoster = localStorage.getObject($scope.lsJid + "_Roster") || {};
        $scope.lsGroupState = "groupState" in $scope.lsRoster ? $scope.lsRoster.groupState : {};

        //this.cache = localStorage.getObject($scope.lsJid + '_cache');
        $scope.contacts = /*this.cache && ("Roster" in this.cache) && ("contactsList" in this.cache.Roster) ? localStorage.getObject($scope.lsJid + '_cache').Roster.contactsList : */[];
        $scope.groups = [];

        /* Dictionaries */
        $scope.lookupgroups = {};
        $scope.lookupjid = {};

        $scope.initContacts = function(list){
            /* Sort groups alphabetically */
            list.sort(groupnameCompare);

            $scope.contacts = list;
            /* Populate dictionaries */
            for(var i = 0; i < $scope.contacts.length; i++){
                $scope.lookupgroups[$scope.contacts[i].agroup] = $scope.contacts[i];
                /* Sort jid by presence and alphabetically */
                $scope.contacts[i].agroupitems.sort(jidAvalCompare);

                for(var j = 0; j < $scope.contacts[i].agroupitems.length; j++){
                    $scope.lookupjid[$scope.contacts[i].agroupitems[j].ajid] = $scope.contacts[i].agroupitems[j];
                }
            }
            $scope.$apply();
        };

        $scope.initGroups = function(list){
            for(var i in list){
                if(!("rosterGroup_"+i in $scope.lsGroupState)){
                    list[i] = true;
                    $scope.lsGroupState["rosterGroup_" + i] = true;
                }
                else list[i] = $scope.lsGroupState["rosterGroup_" + i];
            }

            $scope.groups = list;
            $scope.$apply();
        };

        $scope.deleteContact = function(jid){
            $scope.lookupjid[jid].tombstone = true;

            $scope.$apply();
        };

        $scope.pushInPlace = function(element, array, comparer){
            if(array === $scope.contacts){
                dico = $scope.lookupgroups;
                key = "agroup";
            } else {
                dico = $scope.lookupjid;
                key = "ajid";
            }

            /* Put element in the right place inside array */
            index = locationOf(element, array, comparer);
            array.splice(index, 0, element);

            /* Update dictionary from the appropriate index */
            for(var i=index; i<array.length; i++){
                dico[array[i][key]] = array[i];
            }
        };

        $scope.updateContact = function(list){
            if($scope.contacts === null) $scope.contacts = [];
            /* Group change */
            if((list.jid in $scope.lookupjid)
                && !($scope.lookupjid[list.jid].ajiditems.groupname == list.groupname)){
                /* Kill jid from old location or whole group if it's the only jid */
                oldgroupname = $scope.lookupjid[list.jid].ajiditems.groupname;
                if($scope.lookupgroups[oldgroupname].agroupitems.length == 1){
                    $scope.lookupgroups[oldgroupname].tombstone = true;
                    /*Remove group from localStorage*/
                    delete $scope.lsGroupState['rosterGroup_'+oldgroupname];
                }
                else{
                    $scope.lookupjid[list.jid].tombstone = true;
                }
            }
            /* New group is not in the list */
            if(!(list.groupname in $scope.lookupgroups)) {
                /* Create group */
                el = {
                    'agroup': list.groupname,
                    'agroupitems': [],
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.contacts, groupnameCompare);
                /* Reference in the localstorage for toggling */
                $scope.lsGroupState["rosterGroup_" + list.groupname] = true;
            }

            /* Jid is in the list and no group change */
            if(list.jid in $scope.lookupjid
                && ($scope.lookupjid[list.jid].ajiditems.groupname == list.groupname))
            {
                $scope.lookupjid[list.jid].aval = list.value;
                $scope.lookupjid[list.jid].atruename = list.rosterview.name;
                $scope.lookupjid[list.jid].ajiditems = list;
                $scope.lookupgroups[list.groupname].agroupitems.sort(jidAvalCompare);
            }
            else{
                el = {
                    'ajid':     list.jid,
                    'atruename':     list.rosterview.name,
                    'aval':     list.value,
                    'ajiditems': list,
                    'tombstone': false,
                };
                $scope.pushInPlace(el, $scope.lookupgroups[list.groupname].agroupitems, jidAvalCompare);
            }
            $scope.$apply();

            //a new li is created, a new listener has to be created...
            document.getElementById(list.jid).onclick = function(e){Roster.clickOnContact(e);};
        };

        this.showHideGroup = function(g){
            ls = $scope.lsGroupState["rosterGroup_" + g];
            if(ls === null){
                ls = $scope.lsGroupState.rosterGroup_Ungrouped;
                g = "Ungrouped";
            }

            ls = !ls;

            $scope.lsGroupState["rosterGroup_" + g] = ls;
            $scope.groups[g] = ls;
        };

        /*this.postJingleAction = function(c){
            Popup.close();
            Popup.open(c.jid + "/" + c.resource);
        };*/

        this.groupIsShown = function(grp){
            if(typeof $scope.groups[grp] != "undefined"){
                return $scope.groups[grp];
            }
            else return $scope.groups["Ungrouped"];
        };

        this.getContactTitle = function(c){
            title = c.rosterview.name.toLowerCase() + " - " + c.jid;
            if(c.status) title += " - " + c.status;
            return title;
        };

        this.getContactClient = function(c){
            liclass = "";
            if(c.rosterview.client)
                liclass = "client " + c.rosterview.client;
            return liclass;
        };

        this.getJidStatusResource = function(c){
            lititle = c.jid;
            if(c.status != '') lititle += " - " + c.status;
            lititle += " - " + c.resource;
            return lititle;
        };

        this.getPresenceInactiveClient = function(c){
            liclass = c.rosterview.presencetxt + " " + contact.rosterview.inactive;
            if(c.client) liclass += " client " + c.client;
            return liclass;
        };
    });
})();

window.onunload = window.onbeforeunload = function(e){
    var lsjid = angular.element(roster).scope().lsJid;

    // Cache Roster list in jid_cache.Roster
    /*if(localStorage.getObject(lsjid + "_cache") === null)
        localStorage.setObject(lsjid + "_cache", {"Roster": {"contactsList": angular.element(roster).scope().contacts}});
    else{
        var nv = localStorage.getObject(lsjid + "_cache");
        nv.Roster = {"contactsList": angular.element(roster).scope().contacts};
        localStorage.setObject(lsjid + "_cache", nv);
    }
    */

    // Update real localstorage
    angular.element(roster).scope().lsRoster.groupState = angular.element(roster).scope().lsGroupState;
    //angular.element(roster).scope().lsRoster.offlineShown = angular.element(rostermenu).scope().lsOfflineShown;
    localStorage.setObject(lsjid + "_Roster", angular.element(roster).scope().lsRoster);
};

/* Functions to call angular inner functions */
function initContacts(tab){
    if(tab.length == 0)
        angular.element(roster).scope().contacts = null;
    else
        angular.element(roster).scope().initContacts(JSON.parse(tab));

    Roster.refresh();
}

function initGroups(tab){
    angular.element(roster).scope().initGroups(JSON.parse(tab));
}

function updateContact(tab){
    angular.element(roster).scope().updateContact(JSON.parse(tab));
}

function deleteContact(jid){
    angular.element(roster).scope().deleteContact(jid);
}

/* === PushInPlace subfunctions === */
function locationOf(element, array, comparer, start, end) {
    if (array.length === 0)
        return 0;
    start = start || 0;
    end = end || array.length;
    var pivot = (start + end) >> 1;  // >>1 = /2
    var c = comparer(element, array[pivot]);
    if ((end - start) <= 1){
        return (c == -1) ? pivot : pivot+1;
    }

    switch (c) {
        case -1: return locationOf(element, array, comparer, start, pivot);
        case 0: return pivot;
        case 1: return locationOf(element, array, comparer, pivot, end);
    };
};

/* Object comparison functions */
var groupnameCompare = function(a, b) {
    return a.agroup.localeCompare(b.agroup);
};

/* Presence + alphabetical comparison */
var jidAvalCompare = function(a, b) {
    n = a.aval - b.aval;
    if(n == 0){
        n = a.atruename.localeCompare(b.atruename);
    }
    return n ? n < 0 ? -1 : 1 : 0;
};

/* === Old functions still in use === */
MovimWebsocket.attach(function(){
    Roster_ajaxGetRoster();
});

var Roster = {
    init : function() {
        var search      = document.querySelector('#rostersearch');
        var roster      = document.querySelector('#roster');
        var rosterlist  = document.querySelector('#rosterlist');

        roster.onblur  = function() {
            roster.className = roster_classback;
            rosterlist.className = rosterlist_classback;
        };
        search.oninput = function(event) {
            if(search.value.length > 0) {
                movim_add_class(roster, 'search');
                movim_add_class(rosterlist, 'offlineshown');
            } else {
                movim_remove_class(roster, 'search');
                movim_remove_class(rosterlist, 'offlineshown');
            }

            // We clear the old search
            var selector_clear = '#rosterlist div > li:not(.subheader)';
            var li = document.querySelectorAll(selector_clear);

            for(i = 0; i < li.length; i++) {
                movim_remove_class(li.item(i), 'found');
            }

            // We select the interesting li
            var selector = '#rosterlist div > li[title*="' + search.value.toLowerCase() + '"]:not(.subheader)';
            var li = document.querySelectorAll(selector);

            for(i = 0; i < li.length; i++) {
                movim_add_class(li.item(i), 'found');
            }
        };
    },
    refresh: function() {
        var items = document.querySelectorAll('#rosterlist div > li:not(.subheader)');
        var i = 0;

        while(i < items.length)
        {
            items[i].onclick = function(e){Roster.clickOnContact(e);};
            i++;
        }
    },

    reset: function(list) {
        for(i = 0; i < list.length; i++) {
            movim_remove_class(list[i], 'active');
        }
    },

    setFound : function(jid) {
        document.querySelector('input[name=searchjid]').value = jid;
    },

    clickOnContact : function(e) {
        Contact_ajaxGetContact(e.target.id);
        /*recalculated at each click*/
        var it = document.querySelectorAll('#rosterlist div > li:not(.subheader)');
        Roster.reset(it);
        movim_add_class(e.target, 'active');
        //document.querySelector('#roster').className = '';
    },
}

MovimWebsocket.attach(function() {
    Notification.notifs_key = 'contacts';
    Roster.refresh();
});

movim_add_onload(function(){
    Roster.init();
});
<|endoftext|>


<commit_before>(function () {
  'use strict';

  angular
    .module('app')
    .constant('Config', {
      sendEmailUrl: 'https://sunnymead-staging.herokuapp.com/sendEmail'
    });

})();<commit_msg>moving config to point to master<commit_after>(function () {
  'use strict';

  angular
    .module('app')
    .constant('Config', {
      sendEmailUrl: 'https://sunnymead.herokuapp.com/sendEmail'
    });

})();<|endoftext|>


<commit_before>var test = require('tape')

test('load config in eslint to validate all rule syntax is correct', function (t) {
  var CLIEngine = require('eslint').CLIEngine

  var cli = new CLIEngine({
    useEslintrc: false,
    configFile: 'eslintrc.json'
  })

  var code = 'var foo = 1\nvar bar = function () {}\nbar(foo)\n'

  t.ok(cli.executeOnText(code).errorCount === 0)
  t.end()
})
<commit_msg>code style<commit_after>var eslint = require('eslint')
var test = require('tape')

test('load config in eslint to validate all rule syntax is correct', function (t) {
  var CLIEngine = eslint.CLIEngine

  var cli = new CLIEngine({
    useEslintrc: false,
    configFile: 'eslintrc.json'
  })

  var code = 'var foo = 1\nvar bar = function () {}\nbar(foo)\n'

  t.ok(cli.executeOnText(code).errorCount === 0)
  t.end()
})
<|endoftext|>


<commit_before>var _ = require('lodash');
var async = require('async');
var assert = require('assert');

var valids = require('..');

function validatorAssert(validator, value, param, result) {
  assert.equal(valids.rules[validator]('name', value, param), result);
}

describe('validators', function() {

  it('should validate "required"', function() {
    var message = 'attribute "name" is required'
    validatorAssert('required', 'value', false, null);
    validatorAssert('required', 'value', true, null);
    validatorAssert('required', null, true, message);
    validatorAssert('required', undefined, true, message);
    validatorAssert('required', '', true, message);
  });

  it('should validate "min"', function() {
    validatorAssert('min', 'value', 4, null);
    validatorAssert('min', 'value', 5, null);
    validatorAssert('min', 'value', 6,
      'attribute "name" must have a minimum of 6 characters');
    validatorAssert('min', '', 1,
      'attribute "name" must have a minimum of 1 character');
  });

  it('should validate "max"', function() {
    validatorAssert('max', 'value', 6, null);
    validatorAssert('max', 'value', 5, null);
    validatorAssert('max', 'value', 4,
      'attribute "name" must have a maximum of 4 characters');
    validatorAssert('max', 'va', 1,
      'attribute "name" must have a maximum of 1 character');
  });

  it('should validate "choice"', function() {
    validatorAssert('choice', 'value', ['foo', 'value'], null);
    validatorAssert('choice', 'value', ['foo', 'bar'],
      'attribute "name" must be "foo" or "bar"');
    validatorAssert('choice', 'value', ['foo', 'bar', 'baz'],
      'attribute "name" must be "foo", "bar", or "baz"');
  });

  it('should validate "email"', function() {
    var message = 'attribute "name" must be a valid email address';
    validatorAssert('email', 'fake-email', false, null);
    validatorAssert('email', 'fake-email', true, message);
    validatorAssert('email', 'johndoe@example', true, message);
    validatorAssert('email', 'johndoe@example.', true, message);
    validatorAssert('email', 'johndoe@example.com', true, null);
  });

  it('should validate "postal_code"', function() {
    var message = 'attribute "name" must be a valid postal code'
    validatorAssert('postal_code', '1234', false, null);
    validatorAssert('postal_code', '1234', true, message);
    validatorAssert('postal_code', '123456', true, message);
    validatorAssert('postal_code', '12345-12345', true, message);
    validatorAssert('postal_code', '12345', true, null);
    validatorAssert('postal_code', '12345-6789', true, null);
  });

  it('should validate "username"', function() {
    var message = 'attribute "name" must only contain letters, numbers, ' +
      'periods, dashes, and underscores';
    validatorAssert('username', 'validUsername', false, null);
    validatorAssert('username', 'validUsername', true, null);
    validatorAssert('username', 'a1.-_', true, null);
    validatorAssert('username', 'a1.-_!', true, message);
    validatorAssert('username', ' ', true, message);
  });
});

describe('#validate()', function() {

  var schema = {
    name: {
      rules: {
        required: true
      }
    },
    email: {
      rules: {
        required: true,
        email: true
      }
    }
  };

  var options = {schema: schema};

  it('should validate nonexistent fields by default', function(done) {
    var testOptions = {schema: schema};
    valids.validate({}, options, function(messages) {
      assert.deepEqual(messages, {
        name: 'attribute "name" is required',
        email: 'attribute "email" is required'
      });
      done();
    });
  });

  it('should not validate nonexistent fields when validateAll is set ' +
    'to false', function(done) {
    var testOptions = {schema: schema, validateAll: false};
    valids.validate({}, testOptions, function(messages) {
      assert.equal(messages, null);
      done();
    });
  });

  it('should validate rules', function(done) {
    var values = {name: 'me', email: 'a@b.c', unspecified: true};
    valids.validate(values, options, function(messages) {
      assert.equal(messages, null);
      done();
    });
  });

  it('should validate with custom rule functions', function(done) {
    var testOptions = {
      schema: {
        custom: {
          rules: {
            customValidator: function(value, cb) {
              if (value === 'correct') {
                cb();
              } else {
                cb('customValidator message');
              }
            }
          }
        }
      }
    };

    async.parallel([
      function(cb) {
        valids.validate({custom: 'correct'}, testOptions, function(messages) {
          assert.equal(messages, null);
          cb();
        });
      },
      function(cb) {
        valids.validate({custom: 'fail'}, testOptions, function(messages) {
          assert.deepEqual(messages, {custom: 'customValidator message'});
          cb();
        });
      }
    ], done);
  });

  it('should use custom messages', function(done) {
    var testOptions = {
      schema: {
        email: {
          rules: {
            email: true
          }
        }
      },
      messages: {
        email: _.template('field "<%= name %>" failed')
      }
    };

    valids.validate({email: 'fake'}, testOptions, function(messages) {
      assert.deepEqual(messages, {email: 'field "email" failed'});
      done();
    });
  });
});
<commit_msg>Removed options variable<commit_after>var _ = require('lodash');
var async = require('async');
var assert = require('assert');

var valids = require('..');

function validatorAssert(validator, value, param, result) {
  assert.equal(valids.rules[validator]('name', value, param), result);
}

describe('validators', function() {

  it('should validate "required"', function() {
    var message = 'attribute "name" is required'
    validatorAssert('required', 'value', false, null);
    validatorAssert('required', 'value', true, null);
    validatorAssert('required', null, true, message);
    validatorAssert('required', undefined, true, message);
    validatorAssert('required', '', true, message);
  });

  it('should validate "min"', function() {
    validatorAssert('min', 'value', 4, null);
    validatorAssert('min', 'value', 5, null);
    validatorAssert('min', 'value', 6,
      'attribute "name" must have a minimum of 6 characters');
    validatorAssert('min', '', 1,
      'attribute "name" must have a minimum of 1 character');
  });

  it('should validate "max"', function() {
    validatorAssert('max', 'value', 6, null);
    validatorAssert('max', 'value', 5, null);
    validatorAssert('max', 'value', 4,
      'attribute "name" must have a maximum of 4 characters');
    validatorAssert('max', 'va', 1,
      'attribute "name" must have a maximum of 1 character');
  });

  it('should validate "choice"', function() {
    validatorAssert('choice', 'value', ['foo', 'value'], null);
    validatorAssert('choice', 'value', ['foo', 'bar'],
      'attribute "name" must be "foo" or "bar"');
    validatorAssert('choice', 'value', ['foo', 'bar', 'baz'],
      'attribute "name" must be "foo", "bar", or "baz"');
  });

  it('should validate "email"', function() {
    var message = 'attribute "name" must be a valid email address';
    validatorAssert('email', 'fake-email', false, null);
    validatorAssert('email', 'fake-email', true, message);
    validatorAssert('email', 'johndoe@example', true, message);
    validatorAssert('email', 'johndoe@example.', true, message);
    validatorAssert('email', 'johndoe@example.com', true, null);
  });

  it('should validate "postal_code"', function() {
    var message = 'attribute "name" must be a valid postal code'
    validatorAssert('postal_code', '1234', false, null);
    validatorAssert('postal_code', '1234', true, message);
    validatorAssert('postal_code', '123456', true, message);
    validatorAssert('postal_code', '12345-12345', true, message);
    validatorAssert('postal_code', '12345', true, null);
    validatorAssert('postal_code', '12345-6789', true, null);
  });

  it('should validate "username"', function() {
    var message = 'attribute "name" must only contain letters, numbers, ' +
      'periods, dashes, and underscores';
    validatorAssert('username', 'validUsername', false, null);
    validatorAssert('username', 'validUsername', true, null);
    validatorAssert('username', 'a1.-_', true, null);
    validatorAssert('username', 'a1.-_!', true, message);
    validatorAssert('username', ' ', true, message);
  });
});

describe('#validate()', function() {

  var schema = {
    name: {
      rules: {
        required: true
      }
    },
    email: {
      rules: {
        required: true,
        email: true
      }
    }
  };

  var options = {schema: schema};

  it('should validate nonexistent fields by default', function(done) {
    valids.validate({}, options, function(messages) {
      assert.deepEqual(messages, {
        name: 'attribute "name" is required',
        email: 'attribute "email" is required'
      });
      done();
    });
  });

  it('should not validate nonexistent fields when validateAll is set ' +
    'to false', function(done) {
    var testOptions = {schema: schema, validateAll: false};
    valids.validate({}, testOptions, function(messages) {
      assert.equal(messages, null);
      done();
    });
  });

  it('should validate rules', function(done) {
    var values = {name: 'me', email: 'a@b.c', unspecified: true};
    valids.validate(values, options, function(messages) {
      assert.equal(messages, null);
      done();
    });
  });

  it('should validate with custom rule functions', function(done) {
    var testOptions = {
      schema: {
        custom: {
          rules: {
            customValidator: function(value, cb) {
              if (value === 'correct') {
                cb();
              } else {
                cb('customValidator message');
              }
            }
          }
        }
      }
    };

    async.parallel([
      function(cb) {
        valids.validate({custom: 'correct'}, testOptions, function(messages) {
          assert.equal(messages, null);
          cb();
        });
      },
      function(cb) {
        valids.validate({custom: 'fail'}, testOptions, function(messages) {
          assert.deepEqual(messages, {custom: 'customValidator message'});
          cb();
        });
      }
    ], done);
  });

  it('should use custom messages', function(done) {
    var testOptions = {
      schema: {
        email: {
          rules: {
            email: true
          }
        }
      },
      messages: {
        email: _.template('field "<%= name %>" failed')
      }
    };

    valids.validate({email: 'fake'}, testOptions, function(messages) {
      assert.deepEqual(messages, {email: 'field "email" failed'});
      done();
    });
  });
});
<|endoftext|>